使用Python下载m3u8流视频

本文介绍了一种从M3U8链接下载视频的方法,并使用AES解密技术处理加密的视频片段。文章详细解释了如何解析M3U8文件,下载TS片段,获取解密密钥,以及使用Python的pycrypto库进行AES解密。

requirement:

pip3 install pycrypto

code:

# -*- coding:utf-8 -*-  
import os
import shutil
import requests
import datetime
from Crypto.Cipher import AES
from binascii import b2a_hex, a2b_hex
 
def download(url):
	#指定存储目录
    download_path = os.getcwd() + "/Downloads"
    if not os.path.exists(download_path):
        os.mkdir(download_path)
        
    #新建日期文件夹
    download_path = os.path.join(download_path, datetime.datetime.now().strftime('%Y%m%d_%H%M%S'))
    #print download_path
    os.mkdir(download_path)
    
    # 获取第一层M3U8文件内容
    all_content = requests.get(url).text  
    if "#EXTM3U" not in all_content:
        raise BaseException("非M3U8的链接")
 	
 	# 第一层
    if "EXT-X-STREAM-INF" in all_content:  
        file_line = all_content.split("\n")
        for line in file_line:
            if '.m3u8' in line:
            	# 拼出第二层m3u8的URL
                url = url.rsplit("/", 1)[0] + "/" + line 
                all_content = requests.get(url).text
 
    file_line = all_content.split("\n")
 
    unknow = True
    key = ""
    # 第二层
    for index, line in enumerate(file_line): 
    	# 找解密Key
        if "#EXT-X-KEY" in line:  
            method_pos = line.find("METHOD")
            comma_pos = line.find(",")
            method = line[method_pos:comma_pos].split('=')[1]
            print("Decode Method:", method)
            
            uri_pos = line.find("URI")
            quotation_mark_pos = line.rfind('"')
            key_path = line[uri_pos:quotation_mark_pos].split('"')[1]
            
            # 拼出key解密密钥URL
            key_url = url.rsplit("/", 1)[0] + "/" + key_path 
            res = requests.get(key_url)
            key = res.content
            print("key:" , key)
           
        # 找ts地址并下载
        if "EXTINF" in line:
            unknow = False
            # 拼出ts片段的URL
            pd_url = url.rsplit("/", 1)[0] + "/" + file_line[index + 1] 
            
            res = requests.get(pd_url)
            c_fule_name = file_line[index + 1].rsplit("/", 1)[-1]
            
            # AES 解密
            if len(key): 
                cryptor = AES.new(key, AES.MODE_CBC, key)  
                with open(os.path.join(download_path, c_fule_name + ".mp4"), 'ab') as f:
                    f.write(cryptor.decrypt(res.content))
            else:
                with open(os.path.join(download_path, c_fule_name), 'ab') as f:
                    f.write(res.content)
                    f.flush()
    if unknow:
        raise BaseException("未找到对应的下载链接")
    else:
        print("下载完成")
    merge_file(download_path)
    delete_ts(download_path)
 
def merge_file(path):
    path_list = []
    for file in os.listdir(path): 
        if file.endswith('.ts'): 
            path_list.append(file)
    path_list.sort()
    li = [os.path.join(path,filename) for filename in path_list]
    input_file = '|'.join(li)
    output_file = path + '.mp4'
    command = 'ffmpeg -i "concat:{}" -acodec copy -vcodec copy -absf aac_adtstoasc {}'.format(input_file, output_file))
    os.system(command)

def delete_ts(path):
    try:
        shutil.rmtree(path)
        print('ts文件已经删除')
    except:
        print('ts文件删除失败')

if __name__ == '__main__': 
    url = "https://xxxxxxxxxxx.m3u8" 
    download(url)

2019年12月21日更新

如果出现

too many open files

则是因为打开的文件数量超过系统允许的数量
可以手动修改允许的数量

ulimit -n 2048

参考

使用 Python 下载 M3U8 视频需要通过以下几个步骤: 1. 解析 M3U8 文件获取视频分片地址列表:M3U8 文件是一种包含视频分片地址的文本文件,我们需要通过解析 M3U8 文件获取视频分片地址列表。可以使用第三方库如 `m3u8` 进行解析,如下所示: ```python import m3u8 # 加载 M3U8 文件 m3u8_obj = m3u8.load('http://example.com/video.m3u8') # 获取分片地址列表 segments = m3u8_obj.segments ``` 2. 下载视频分片并保存到本地:遍历视频分片地址列表,使用 `requests` 库进行下载,并保存到本地文件中,如下所示: ```python import requests # 遍历分片地址列表,下载并保存到本地 for i, segment in enumerate(segments): url = segment.absolute_uri response = requests.get(url) with open(f'segment{i}.ts', 'wb') as f: f.write(response.content) ``` 其中,`segment{i}.ts` 是保存到本地的文件名,可以根据实际情况进行修改。 3. 合并视频分片成完整视频:将下载视频分片使用 `ffmpeg` 工具进行合并,可以使用 `subprocess` 模块调用系统命令实现,如下所示: ```python import subprocess # 合并视频分片 subprocess.call('ffmpeg -i "concat:segment0.ts|segment1.ts|segment2.ts" -c copy output.mp4', shell=True) ``` 其中,`concat:segment0.ts|segment1.ts|segment2.ts` 是视频分片文件名列表,多个文件用 `|` 分隔,`output.mp4` 是合并后的视频文件名,可以根据实际情况进行修改。 需要注意的是,下载和合并视频分片的过程可能比较耗时,需要根据分片数量和网络情况进行调整,以免出现网络超时等问题。同时,下载使用视频可能涉及到版权等法律问题,请遵守相关法律法规。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值