• 0
  • 0

e3u8资源下载

2021-06-24 666 0 admin 所属分类:Python

现在很多视频资源都不是通过mp4、avi等直链形式放到网站的了,而是采用hls视频切割成.ts的后缀文件分片传输

这样既节省了带宽也能防止人家直接下载保存资源

相关介绍

这类视频资源首先会加载 e3u8文件

该文件存储的是一堆ts资源 可以获取后批量下载ts资源到本地 然后合并成一个资源

import requests
import threadpool
url = 'https://www.xxx.com/index.m3u8'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0'
}

content = requests.get(url, headers=headers)

arr = content.text.split("\n")
poolsize = 10 # 开启十个线程

def download_file(data):
    r = requests.get(data['url'], headers=headers)
    with open(data['file'] , "wb") as code:
        code.write(r.content)
arr2 = []
index = 1
for i in arr:
    # 过滤 注释符号 '#'
    if "#" not in i and i.strip() != "":
        # 替换掉特殊字符
        i = i.replace("\n" , "")
        file = "d:\\Users\Administrator\\Desktop\\e3u8\\"+str(index)+".ts"
        index = index + 1
        arr2.append({"file":file,"index":index,"url":i})


pool = threadpool.ThreadPool(poolsize)
reqs = threadpool.makeRequests(download_file , arr2)

[pool.putRequest(req) for req in reqs]

pool.wait()

print("执行完毕")

最后知道window cmd命令合并

copy /b   *.ts   new.mp4

调用os模块 执行cmd命令

os.chdir(path)
os.system("copy /b *.ts merge.mp4")
os.system('del /Q *.ts')


线程池模快 请看

有些e3u8文件切片的数据都是经过加密的 可以打开文件中看到


这个时候需要在获取列表时把加密类型和秘钥解析出来 供后面解密使用

if "#EXT-X-KEY" in line:
    # 遍历每一行数据 存在加密类型
    method_pos = line.find("METHOD")
    comma_pos = line.find(",")
    # 取加密方法 存入全局变量
    method = i[method_pos:comma_pos].split('=')[1]
    uri_pos = line.find("URI")
    quotation_mark_pos = line.rfind('"')
    # 找到加密秘钥地址
    key_path = i[uri_pos:quotation_mark_pos].split('"')[1]
    res = requests.get(key_path)
    # 去加密秘钥二进制数据 存入全局变量 必须返回二进制数据
    key = res.content

获取ts二进制数据后判断是否需要解密

if len(key):
    #AES.MODE_CBC 就是AES-128加密类型
    cryptor = AES.new(key, AES.MODE_CBC, key)
    with open(data['file'], "ab") as f:
        # 必须填充数据块为16位 否则部分数据会加密失败
        f.write(cryptor.decrypt(pad(res.content,16,style='pkcs7')))
else:
    # 不需要解密 直接写入到本地
    with open(data['file'], "ab") as f:
        f.write(res.content)
        f.slush()

解密相关需要引入的模块有

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from binascii import b2a_hex
from binascii import a2b_hex


有人说可以用  文件切片,用ffmpeg 下次尝试

调用 ffmpeg 视频切片

生成未加密的ts

ffmpeg -i 待转换视频路径 -codec copy -f segment -segment_list index.m3u8 -segment_time 30 segment_%03d.ts

生成加密的ts

ffmpeg -i 待转换视频路径 -hls_time 10 -hls_key_info_file openssl生成的keyinfo文件 -hls_playlist_type vod -hls_segment_filename "output%03d.ts" e3u8索引文件保存地址

如何生成keyinfo文件

安装openssl后 

openssl rand  16 > encrypt2.key

如果需要自定义iv 执行如下代码

openssl rand -hex 16 >enc.iv.txt

生成hls_key_info_file 形式格式如下

网络地址
本地地址
向量值(可选)

openssl 解密ts视频 

openssl aes-128-cbc -d -in fileSequence0.ts -out fileSequence0_decrypto.ts -nosalt -iv a9b8013f809f34c03089920ff34aef7e -K 598ba998f204f30cb9004de670600b33

ffmpeg 合并ts视频

ffmpeg -i "concat:0.ts|1.ts|2.ts" -acodec copy -vcodec copy -absf aac_adtstoasc output.mp4

ffmpeg 直接下载未加密的 e3u8资源到本地

ffmpeg -i https://localhost/playlist.m3u8 -c copy file_name.mp4


参数表

key值     解释 
  -segment_time 切片时长
-hls_key_info_file 指定加密切片视频的加密文件[包含加密和解密URI信息],切片时会生成到播放列表中,视频播放器就可以根据播放列表的解密路径找到密钥进行解密播放
-segment_list 指定播放列表名称和目录
 -c 指定编码器
 -c copy 直接复制,不经过重新编码(这样比较快)
 -i 指定输入文件
 -author 设置作者
 -copyright 设置版权
 -f 强制设置输入输出的文件格式,默认情况下ffmpeg会根据文件后缀名判断文件格式
 -hls_time 每段文件的时间长度(单位:秒) 加密时使用
 -hls_list_size 0 索引播放列表的最大列数 默认5,0 为不限制
 -hls_playlist_type vod 表示当前的视频流并不是一个直播流,而是点播流
 -hls_segment_filename 输出 ts和m3u8 文件路径中间空格 %d:表示一位数字,从0开始  可以是%03d


使用 video标签 播放 m3u8

<video id="my-video" class="my-video" >
        <source src="http://www.xxx.com/playlist.m3u8"  type="application/x-mpegURL">
</video>



返回顶部