在互联网视频时代,M3U8 协议因其自适应码率流媒体传输能力而广泛应用于各大视频平台。本文将介绍 Media-Segment-Grabber —— 一款功能强大、设计精良的 M3U8 视频流分段提取工具,它能够高效地将网络视频流下载并合并为完整的视频文件。
项目简介
Media-Segment-Grabber 是一个基于 Python 的命令行工具,专门用于下载 M3U8 格式的视频流。项目采用了多线程并发下载技术,配合智能重试机制和浏览器伪装策略,显著提升了下载效率和成功率。
核心特性
- ✅ 多线程并发下载:支持 8-32 个线程同时下载,大幅提升下载速度
- ✅ 智能重试机制:失败分片自动重试,最多支持 20 次重试
- ✅ 浏览器伪装技术:模拟真实浏览器行为,随机切换 User-Agent
- ✅ 嵌套 M3U8 支持:自动解析多层嵌套的播放列表
- ✅ 实时进度显示:通过 tqdm 显示下载进度、速度和剩余时间
- ✅ 配置文件加密:使用 AES-256-CBC 加密保护敏感配置信息
- ✅ 跨平台支持:兼容 Windows、Linux 和 macOS
技术架构
核心依赖
项目使用了以下 Python 库:
requests>=2.31.0 # HTTP 请求
tqdm>=4.66.0 # 进度条显示
urllib3>=2.0.0 # SSL 处理
pycryptodome>=3.19.0 # 加密解密
关键技术实现
1. 配置文件加密保护
项目采用 AES-256-CBC 加密算法保护配置文件,确保敏感信息(如 API 密钥、URL 等)的安全:
class ConfigDecryptor:
"""配置解密器 - 使用 AES-256-CBC + Base64 解密"""
def __init__(self, secret_key):
# 使用 SHA256 哈希生成 32 字节密钥
self.key = hashlib.sha256(secret_key.encode('utf-8')).digest()
def decrypt(self, iv_b64, encrypted_b64):
# Base64 解码后使用 AES-CBC 解密
iv = base64.b64decode(iv_b64)
encrypted = base64.b64decode(encrypted_b64)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
decrypted = unpad(cipher.decrypt(encrypted), AES.block_size)
return decrypted.decode('utf-8')
2. 浏览器伪装策略
工具内置了多个主流浏览器的 User-Agent 池,并在每次请求时随机选择:
USER_AGENTS = {
'chrome': [
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36...',
# 多个 Chrome 版本
],
'firefox': [...],
'safari': [...],
'edge': [...],
}
每次重试时,工具会自动切换浏览器类型,配合完整的 HTTP 请求头模拟真实浏览器行为。
3. 智能重试机制
项目的重试机制是其核心亮点之一:
- 初始下载:使用多线程并发下载所有分片
- 失败检测:收集下载失败的分片索引
- 模拟访问:每次重试前访问页面资源(CSS、JS、Favicon 等)
- 浏览器切换:切换到下一个浏览器类型
- 针对性重试:仅重试失败的分片,节省带宽和时间
下载流程:
┌─────────────┐
│ 模拟浏览器访问 │
└──────┬──────┘
│
▼
┌─────────────┐
│ 解析M3U8文件 │
└──────┬──────┘
│
▼
┌─────────────┐
│ 多线程下载 │
└──────┬──────┘
│
▼
┌─────────────┐
│ 检测失败分片 │
└──────┬──────┘
│
▼
┌─────────────┐
│ 重试循环(20次)│
│ - 模拟访问 │
│ - 切换浏览器 │
│ - 下载失败项 │
└──────┬──────┘
│
▼
┌─────────────┐
│ 合并所有分片 │
└──────┬──────┘
│
▼
┌─────────────┐
│ 清理临时文件 │
└─────────────┘
4. 嵌套 M3U8 解析
许多视频平台使用多层 M3U8 结构(主播放列表 → 子播放列表 → TS 分片)。项目自动检测并解析嵌套结构:
def parse_m3u8(self, url=None):
# 检测是否包含 .ts 文件
has_ts_files = any(line.endswith('.ts') for line in lines)
if not has_ts_files:
# 嵌套 M3U8,递归解析子播放列表
return self.parse_m3u8(nested_url)
# 提取所有 TS 分片 URL
for line in lines:
if line.endswith('.ts'):
self.segment_urls.append(full_url)
使用方法
安装依赖
pip install requests tqdm urllib3 pycryptodome
配置文件
在 config_encrypted.json 中配置下载参数(已加密):
{
"m3u8_url": {"iv": "...", "encrypted": "..."},
"output_file": {"iv": "...", "encrypted": "..."},
"max_threads": {"iv": "...", "encrypted": "..."},
"base_url": {"iv": "...", "encrypted": "..."}
}
运行下载
python download_video.py
下载示例输出
============================================================
M3U8 视频多线程下载器
============================================================
正在模拟浏览器访问...
✓ https://www.xiaobaotv.tv/
✓ https://www.xiaobaotv.tv/template/mytheme/statics/css/mytheme-font.css
...
成功访问 7/7 个资源
正在解析M3U8文件...
检测到嵌套M3U8,正在解析子播放列表...
共找到 1482 个视频分片
开始下载,使用 16 个线程...
下载进度: 100%|████████████████████████| 1482/1482 [08:13<00:00, 3.00分片/s]
第 1 次重试 48 个失败的分片...
重试后仍有 1 个分片失败
第 2 次重试 1 个失败的分片...
所有分片下载成功!
下载完成!
成功: 1482/1482 个分片
总大小: 2166.94 MB
视频合并完成!
技术亮点
1. 线程安全设计
使用 threading.Lock() 确保多线程环境下的数据一致性:
self.lock = threading.Lock()
with self.lock:
self.downloaded_size += len(chunk)
browser_type = self.current_user_agent
self.current_user_agent = get_next_browser_type(browser_type)
2. 流式下载
使用 iter_content() 实现流式下载,避免大文件内存占用:
response = requests.get(url, stream=True)
for chunk in response.iter_content(chunk_size=8192):
if chunk:
f.write(chunk)
3. 智能恢复机制
每次重试前访问多个页面资源,模拟真实用户浏览行为,提高请求成功率。请求之间添加 0.5-2 秒随机延迟,避免被识别为机器人。
适用场景
- 视频资源备份:下载自己发布的视频进行备份
- 离线观看:将在线视频下载到本地离线观看
- 技术研究:学习 M3U8 协议和视频流传输原理
- 网络测试:测试网络带宽和下载性能
注意事项
⚠️ 重要提醒:
- 本工具仅供学习研究和技术交流使用
- 请遵守当地法律法规和版权保护规定
- 不要用于下载受版权保护的内容
- 不要用于商业用途
- 使用本工具产生的一切后果由使用者自行承担
项目总结
Media-Segment-Grabber 是一个设计精良的视频下载工具,它不仅仅是一个简单的下载脚本,更展示了以下几个工程实践:
- 配置安全:使用加密配置保护敏感信息
- 反爬对抗:通过浏览器伪装和智能重试提高成功率
- 性能优化:多线程并发下载提升效率
- 用户体验:实时进度显示和友好的输出信息
- 健壮性:完善的错误处理和自动恢复机制
项目采用 MIT 开源协议,欢迎开发者提交 Issue 和 Pull Request,共同改进这个工具。
项目地址:Media-Segment-Grabber 许可证:MIT License 作者:Media-Segment-Grabber Team