python下载M3U8视频脚本
·
安装依赖
pip install m3u8 requests
程序
import os
import time
import requests
import m3u8
from urllib.parse import urljoin
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
def download_m3u8_video(url, save_name='output.mp4'):
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)'}
print("📡 正在解析 m3u8 播放列表...")
try:
playlist = m3u8.load(uri=url, headers=headers)
except Exception as e:
print(f"❌ 解析失败: {e}")
return
# 检查是否存在 AES 加密
key, iv = None, None
if playlist.keys and playlist.keys[-1] is not None:
key_info = playlist.keys[-1]
key_uri = key_info.uri
# 【核心修复】:如果密钥是相对路径,使用 urljoin 拼接完整的 URL
if not key_uri.startswith('http'):
key_uri = urljoin(url, key_uri)
print(f"🔑 检测到加密,正在获取完整密钥链接: {key_uri}")
# 获取密钥内容(建议加上与下载视频相同的 headers,防止防盗链拦截)
key_resp = requests.get(key_uri, headers=headers, timeout=15)
key_resp.raise_for_status()
key = key_resp.content
# 获取 IV 向量,如果没有则默认使用全零的 16 字节
iv = key_info.iv
if iv:
iv = bytes.fromhex(iv.replace('0x', ''))
else:
iv = b'\x00' * 16
total = len(playlist.segments)
print(f"✅ 解析成功,共 {total} 个片段,开始下载并合并...")
start_time = time.time()
size = 0
with open(save_name, 'wb') as f:
for i, seg in enumerate(playlist.segments, 1):
try:
# 同样确保 TS 分片也是完整 URL
ts_url = seg.absolute_uri
r = requests.get(ts_url, headers=headers, timeout=15)
r.raise_for_status()
data = r.content
# 如果有密钥,进行 AES 解密
if key:
cipher = AES.new(key=key, mode=AES.MODE_CBC, iv=iv)
data = cipher.decrypt(pad(data, AES.block_size))
f.write(data)
size += len(data)
# 打印进度
elapsed = time.time() - start_time
speed = size / elapsed / 1024 / 1024
print(f"\r⏳ 进度: {i}/{total} | 已下载: {size / 1024 / 1024:.2f}MB | 速度: {speed:.2f}MB/s", end='')
except Exception as e:
print(f"\n❌ 第 {i} 个片段下载失败: {e}")
continue
print(f"\n🎉 视频已成功保存为: {save_name}")
if __name__ == '__main__':
M3U8_URL = "xxx"
download_m3u8_video(M3U8_URL, 'my_video.mp4')
更多推荐



所有评论(0)