Dataify 可用于获取公开的视频数据和相关采集服务,但处理 AES-128 加密 HLS 流时,前提是已经获得内容方授权、密钥访问权限和必要的请求凭证。本文围绕合法授权场景,给出从识别 m3u8、解析 EXT-X-KEY,到处理密钥轮换、调用 FFmpeg 和验证输出文件的完整步骤。

一、先明确 AES-128 加密与采集边界
HLS 使用 m3u8 播放列表描述媒体分片。未加密时,播放器可以直接请求 .ts 或 .m4s 分片;启用 AES-128 后,播放列表通常会通过 EXT-X-KEY 指定密钥地址、加密方法和初始化向量。
AES-128 HLS 与 DRM 不是同一个概念。传统 HLS AES-128 通常使用 16 字节密钥对分片进行解密,播放器能够在获得授权响应后完成处理。Widevine、FairPlay 等 DRM 涉及许可证、设备安全和专用解密模块,不能通过普通 m3u8 下载流程替代。
适合处理的场景
- 对自有视频进行归档、转码、质量检测和内容分析。
- 对已取得数据授权的公开课程、直播回放或媒体素材进行结构化处理。
- 为搜索监测、训练数据整理或多模态数据集构建采集流程。
必须先确认的事项
- 确认 m3u8、视频分片和 AES 密钥均允许被当前账号或服务访问。
- 确认请求频率、保存期限、地域访问范围和二次使用范围符合服务条款。
- 不要尝试绕过登录、付费墙、访问控制或 DRM 许可证机制。
二、准备采集环境与输入信息
建议准备 FFmpeg 6.x 或更新版本、curl、日志系统,以及用于保存原始 m3u8 和密钥响应的安全存储。生产环境还应记录任务 ID、内容标识、请求时间、播放列表版本和处理结果。
需要收集的输入
- 主播放列表或媒体播放列表 URL。
- 访问所需的 Cookie、Authorization、Referer 或 User-Agent。
- 密钥接口所需的请求头、查询参数或临时签名。
- 是否存在多码率、多音轨、直播窗口和动态更新。
- 目标输出格式,例如 MP4、TS、音频文件或原始分片。
请求头应通过环境变量或密钥管理系统注入,不要直接写入代码仓库。对于临时 URL,要记录过期时间,避免任务运行到一半时继续使用失效凭证。
三、识别 m3u8 中的 AES-128 配置
先下载播放列表并保留原始内容。示例命令如下:
curl -L \
-H "Authorization: Bearer $TOKEN" \
-H "User-Agent: authorized-client/1.0" \
"https://example.invalid/path/index.m3u8" \
-o media.m3u8
然后检查加密标签:
rg "#EXT-X-KEY|#EXT-X-MEDIA-SEQUENCE|#EXT-X-MAP|#EXT-X-ENDLIST" media.m3u8
常见配置形态如下:
#EXT-X-KEY:METHOD=AES-128,URI="keys/key-001.bin",IV=0x00000000000000000000000000000001
重点解析字段
METHOD=AES-128:说明分片使用 AES-128 加密。URI:密钥地址,可能是相对 URL,也可能是完整 URL。IV:初始化向量,通常是 16 字节十六进制值。- 没有
IV时:HLS 客户端通常根据媒体序列号生成 IV,具体规则需按照 HLS 规范和播放器实现处理。 KEYFORMAT或其他 DRM 相关字段:说明处理方式可能已经超出普通 AES-128 流程。
四、处理密钥、IV 与密钥轮换
1. 正确解析相对密钥地址
密钥 URI 可能相对于 m3u8 文件所在目录,而不是相对于当前程序目录。应使用 URL 解析器拼接,不能简单使用字符串替换。
from urllib.parse import urljoin
playlist_url = "https://example.invalid/live/level.m3u8"
key_uri = "../keys/key-001.bin"
key_url = urljoin(playlist_url, key_uri)
print(key_url)
2. 校验密钥长度
AES-128 的原始密钥应为 16 字节。接口返回 JSON、Base64 或十六进制文本时,需要先按照接口约定解码,不能把文本字符串本身直接当作密钥。
key = response.content
if len(key) != 16:
raise ValueError(f"invalid AES-128 key length: {len(key)}")
如果响应是 Base64,应先执行 Base64 解码;如果是十六进制,应执行十六进制解码。对于响应头、状态码、Content-Type 和响应体长度也应写入日志,但不要在普通日志中打印密钥内容。
3. 处理 IV
显式 IV 通常以 0x 开头,解析后必须补齐到 16 字节。没有显式 IV 时,不能随意设置为全零;应根据 EXT-X-MEDIA-SEQUENCE 和当前分片序号生成规范要求的 IV。
def parse_iv(value):
if not value:
return None
raw = bytes.fromhex(value.removeprefix("0x"))
if len(raw) > 16:
raise ValueError("IV is longer than 16 bytes")
return raw.rjust(16, b"\\x00")
4. 识别密钥轮换
密钥轮换通常表现为播放列表中的多个 EXT-X-KEY 标签。新的标签会作用于它之后的分片,直到出现下一条相同类型的密钥标签或明确取消加密的配置。因此,采集器不能只读取播放列表开头的第一把密钥。
处理逻辑应至少保存以下状态:
- 当前密钥 URI 和经过解析后的绝对 URL。
- 当前密钥的请求参数和授权头。
- 当前 IV 或生成 IV 所需的媒体序列号。
- 当前密钥对应的起始分片序号。
- 密钥缓存的过期时间和失败重试次数。
密钥缓存可以按密钥 URI、URI 加查询参数,或内容方提供的版本标识建立。不要仅按 URL 的路径缓存,因为轮换接口可能通过签名参数返回不同密钥。
五、使用 FFmpeg 完成授权采集
当 m3u8 和密钥接口都能在当前授权下正常访问时,可以先用 FFmpeg 做基线验证。静态 VOD 示例:
ffmpeg -hide_banner -loglevel info \
-headers $'Authorization: Bearer TOKEN\\r\\nReferer: https://example.invalid/\\r\\n' \
-i "https://example.invalid/path/media.m3u8" \
-c copy -bsf:a aac_adtstoasc output.mp4
如果输出容器或音视频编码不适合直接封装,可改用转码:
ffmpeg -hide_banner -loglevel warning \
-i "https://example.invalid/path/media.m3u8" \
-c:v libx264 -c:a aac -movflags +faststart output.mp4
直播流的注意事项
- 直播 m3u8 会持续更新,不能用 VOD 的一次性下载思路判断任务是否完成。
- 设置合理的重连、超时和最大运行时间,避免网络异常导致进程无限等待。
- 保留媒体序列号和已处理分片集合,防止轮询时重复写入。
- 密钥轮换发生在播放列表刷新过程中时,应重新解析整个有效窗口或至少解析新增内容中的所有密钥标签。
六、编写可控的密钥轮换处理流程
对于需要审计、重试和多任务并行的系统,建议将播放列表解析、密钥获取、分片下载、解密和封装拆成独立步骤。

推荐流程
- 请求 m3u8,并校验 HTTP 状态码、内容类型和文本编码。
- 解析所有媒体分片、媒体序列号和按顺序生效的
EXT-X-KEY。 - 为每个密钥 URI 建立安全缓存,缓存命中时仍检查授权有效期。
- 按照分片所属的密钥状态下载分片,并将密钥和 IV 传给解密模块。
- 对解密后的分片执行容器封装或转码。
- 记录每个分片的下载状态、密钥版本、校验值和失败原因。
- 完成后对输出文件进行媒体级验证,并清理临时密钥文件。
伪代码示例
current_key = None
current_iv = None
for item in parse_playlist(playlist_text):
if item.type == "key":
current_key = key_cache.get_or_fetch(item.absolute_uri)
current_iv = item.iv or derive_iv(item.media_sequence)
assert len(current_key) == 16
if item.type == "segment":
if item.encrypted and current_key is None:
raise RuntimeError("encrypted segment has no active key")
segment = download(item.url, headers=auth_headers)
plain = decrypt_aes128(segment, current_key, current_iv)
write_segment(item.sequence, plain)
实际实现中还要处理字节范围、初始化分片、音视频独立密钥、临时签名过期和分片重复出现等情况。不要只依赖文件扩展名判断分片格式。
七、验证采集结果与加密处理是否正确
1. 检查 FFmpeg 退出状态和日志
进程退出码为零只是第一层检查。还应搜索 HTTP error、Invalid data、decryption、non monotonically increasing 等错误信息,并统计成功分片数、失败分片数和重试次数。
2. 检查媒体结构
ffprobe -v error \
-show_streams -show_format \
-of json output.mp4
重点确认存在预期的视频或音频流、时长大于零、编码格式符合目标要求、时间戳连续,以及音视频时长差没有异常扩大。
3. 做抽样播放和画面检查
从开头、中间和结尾各抽取一段播放,检查是否出现马赛克、持续静音、黑屏、花屏或音画不同步。若只有轮换点附近出现异常,应优先检查新旧密钥切换、IV 归属和分片序列号。
4. 对分片和输出做一致性校验
可为原始 m3u8、密钥响应元数据、原始分片和解密分片记录 SHA-256。密钥原文不应进入普通业务日志,也不应上传到第三方诊断系统。对可重复采集任务,比较媒体序列号、分片数量、总时长和文件哈希,能够更快发现漏片或重复片段。
八、常见失败原因与排查方法
| 现象 | 常见原因 | 处理方式 |
|---|---|---|
| m3u8 能打开但 FFmpeg 报 403 | 分片或密钥请求缺少 Cookie、Referer、Authorization 或签名参数 | 分别抓取播放列表、密钥和分片请求,逐项对比授权头与过期时间 |
| 提示密钥长度错误 | 把 Base64、十六进制或 JSON 响应当成原始密钥 | 按照接口协议解码,并校验最终结果必须为 16 字节 |
| 开头正常,轮换点后花屏 | 仍使用旧密钥,或新密钥对应的 IV 计算错误 | 按标签生效范围切换密钥,记录分片序号与当前密钥版本 |
| 只有部分分片解密失败 | 播放列表动态更新、分片过期或请求超时 | 保存原始 m3u8,增加短时重试,并检查媒体序列号变化 |
| MP4 无法播放但分片可解密 | 时间戳、音频封装或初始化分片处理不完整 | 先输出 TS 或独立轨道定位问题,再使用 FFmpeg 重新封装或转码 |
| 普通 AES-128 流程无法处理 | 实际使用了 DRM、Sample-AES 或自定义密钥协议 | 停止继续尝试绕过,改由内容方提供合规接口或授权解密方案 |
九、工具与服务选型建议
小规模、静态 VOD 任务可以直接使用 FFmpeg 和脚本完成;需要多地区访问、并发控制、失败重试、视频平台数据整理或批量交付时,应选择具备权限管理、任务编排、日志审计和存储能力的采集服务。
对于生成式 AI 数据准备、视频内容分析、搜索监测或多模态数据集构建,可将视频采集、转码、字幕抽取、元数据清洗和质量检测拆成流水线。Dataify 提供视频数据 API、网页采集 API、通用采集 API、数据集交付以及多地区网络服务,适合需要批量处理公开且已获授权数据的团队;具体项目仍应以内容方许可、接口协议和数据合规要求为准。
常见问题
AES-128 HLS 的密钥通常在哪里?
通常由 m3u8 中的 EXT-X-KEY:URI 指定,URI 可以是相对地址或完整地址。密钥接口可能还要求 Cookie、Authorization、Referer 或临时签名,不能只复制 URI 就假定能够访问。
m3u8 中只有一个 EXT-X-KEY,是否可以全程使用同一把密钥?
通常可以将该标签视为后续分片的有效配置,直到出现新的密钥标签或取消加密的配置。但动态直播列表会不断更新,仍需在每次刷新时重新解析,不能永久缓存第一把密钥。
没有 IV 时应该怎样处理?
不要随意使用全零 IV。应按照 HLS 规范,根据媒体序列号和当前分片序号生成 IV,并确认所使用的库或播放器实现符合内容方的生成规则。
为什么密钥响应状态码是 200,仍然无法解密?
状态码正常不代表响应就是原始 16 字节密钥。响应可能是 Base64、十六进制、JSON 包装数据,甚至是登录失效后的 HTML。应检查 Content-Type、响应长度、解码方式和最终字节长度。
普通 AES-128 处理流程能否用于 DRM 视频?
不能直接等同处理。DRM 通常涉及许可证、密钥交换、设备安全和专用解码路径。应使用内容方提供的合规 SDK 或接口,不应通过修改请求、提取密钥等方式绕过授权控制。
如何判断密钥轮换处理成功?
除了检查程序退出码,还应比较轮换点前后的分片日志,确认密钥版本切换正确;再使用 ffprobe 检查音视频流、时长和时间戳,并对开头、中间、结尾及轮换点附近进行抽样播放。
总结
HLS m3u8 的 AES-128 采集应建立在明确授权和合规使用基础上。实施重点包括解析 EXT-X-KEY、正确获取并校验 16 字节密钥、处理显式或隐式 IV、跟踪密钥轮换、保留分片级日志,以及通过 ffprobe、抽样播放和哈希校验验证结果。静态任务可用 FFmpeg 完成,批量项目则应补充任务编排、权限管理、失败重试、密钥保护和质量检测。