现在很多视频资源都不是通过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>