直接用requests下载m3u8文件无效,因其仅为含.ts分片url的文本,需解析后逐个下载分片并处理鉴权、路径拼接、加密解密及ffmpeg合并等完整流程。

为什么直接用 requests 下载 m3u8 文件没用
m3u8 本身只是个播放列表文本文件,里面记录的是一个个 .ts 分片的 URL 地址,不是视频本体。直接 requests.get("xxx.m3u8") 只能拿到几百字节的文本,比如:#EXTM3U\n#EXT-X-VERSION:3\n#EXT-X-TARGETDURATION:10\n#EXTINF:9.960,\nchunk_00001.ts\n...
真正要下载的是这些 chunk_*.ts 文件。如果目标站启用了 Referer 或 Cookie 鉴权,漏掉请求头会导致大量 403;如果分片 URL 是相对路径,不拼对 base URL 就会 404。
怎么用 Python 抓全 ts 分片并保存到本地
核心是解析 m3u8 文本、补全每个 segment.uri 的绝对地址、带正确 headers 下载。推荐用 requests + m3u8 库(非标准库,需 pip install m3u8):
import m3u8
import requests
from urllib.parse import urljoin
<p>m3u8_url = "<a href="https://www.php.cn/link/3e43df7f86a57ed8ce8ce3b26a8a08de">https://www.php.cn/link/3e43df7f86a57ed8ce8ce3b26a8a08de</a>"
headers = {"Referer": "<a href="https://www.php.cn/link/e4639aefe47ac53c3df3d8f9846b5161">https://www.php.cn/link/e4639aefe47ac53c3df3d8f9846b5161</a>", "User-Agent": "Mozilla/5.0"}</p><h1>获取并解析 m3u8</h1><p>res = requests.get(m3u8_url, headers=headers)
playlist = m3u8.loads(res.text)</p><h1>遍历所有 segment,拼出绝对 URL 并下载</h1><p>base_url = urljoin(m3u8_url, ".") # 确保相对路径能正确解析
for i, segment in enumerate(playlist.segments):
ts_url = urljoin(base_url, segment.uri)
ts_res = requests.get(ts<em>url, headers=headers)
with open(f"chunk</em>{i:05d}.ts", "wb") as f:
f.write(ts_res.content)</p>
注意点:
- 不要硬编码
"chunk_*.ts"名字——有些站点用seg-1234567890-a1b2c3.ts这类随机名,应优先用segment.uri.split("/")[-1]提取原始文件名 - 务必检查
playlist.is_variant:如果是 True,说明这是主 m3u8(含多清晰度子列表),得先选一个子流再加载其 m3u8 - 部分站点对单 IP 请求频率敏感,加
time.sleep(0.1)比硬扛 429 更稳妥
ffmpeg 合并 ts 分片时常见报错和绕过方法
最常用命令是:ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mp4,但容易卡在三类问题:
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
-
Invalid data found when processing input:多半是某个.ts分片下载不完整(如网络中断、服务端返回 200 空内容)。建议下载后用ffprobe -v error chunk_00001.ts检查是否可解析,或加-v quiet -show_entries format=duration -of default=noprint_wrappers=1:nokey=1验证时长 -
Non-monotonous DTS:分片间时间戳不连续,尤其出现在直播流或加密流未解密时。此时不能用-c copy,得重编码:-c:v libx264 -c:a aac -strict experimental -
filelist.txt格式错误:必须每行写file 'chunk_00001.ts'(单引号不能少),且不能有空行或 BOM 头;Windows 记事本保存易出 BOM,建议用 VS Code 或echo -e "file 'a.ts'\nfile 'b.ts'" > filelist.txt
要不要解密 AES-128 加密的 m3u8 流
如果 m3u8 里出现 #EXT-X-KEY:METHOD=AES-128,URI="key.key",说明分片是加密的。不处理的话,ffmpeg 合并出来的视频是花屏或黑屏。
解密关键三步:
- 用
requests下载key.key(注意同样要带 Referer/Cookie) - 用
pycryptodome(pip install pycryptodome)按 AES-128-CBC 模式解密每个.ts文件,IV 通常来自segment.key.iv(十六进制字符串,需转bytes.fromhex()) - 解密后保存为新
.ts文件再合并;别试图让 ffmpeg 自动解密——它只支持 URI 是本地路径且 key 文件无权限限制的场景,线上 key 服务基本不可用
真实场景里,加密逻辑可能藏在 JS 中动态生成 key 或 iv,这时候就得逆向或换方案。m3u8 下载和合并本身不难,难的是鉴权链路和反爬对抗——这点比 ffmpeg 参数重要得多。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










