HLS(HTTP Live Streaming)标准的视频及加密和解密播放
.m3u8 是 HLS(HTTP Live Streaming) 协议的索引文件,用于分割后的 TS 分片的播放调度。制作核心是 将 MP4 转码为 TS 分片 + 生成对应的 m3u8 索引,主流工具是 ffmpeg。
HLS 加密(AES-128 加密,HLS 协议标准加密方式),核心是通过 ffmpeg 结合加密密钥(key)、密钥信息文件(keyinfo)实现 TS 分片加密,播放器会自动请求密钥并解密播放。下面提供完整的加密、部署、解密播放示例。
一、HLS 加密核心原理
- 采用 AES-128-CBC 对称加密(HLS 协议强制要求,兼容性最好),所有 TS 分片均用该算法加密。
- 需准备 3 个核心文件:
- 加密密钥(
enc.key):二进制密钥文件,16 字节(AES-128 要求),用于加密 / 解密 TS 分片。 - 密钥信息文件(
enc.keyinfo):文本文件,记录密钥 URL、密钥本地路径、密钥初始化向量(IV,可选)。 - 加密后的
m3u8和 TS 分片:ffmpeg生成,m3u8中会携带加密信息(密钥 URL、加密算法)。
- 加密密钥(
- 播放流程:播放器解析 m3u8 → 读取加密信息 → 请求密钥 URL 获取
enc.key→ 用密钥解密 TS 分片并播放。
二、完整加密步骤(实操示例)
步骤 1:生成 AES-128 加密密钥(enc.key)
首先生成 16 字节的二进制密钥文件(两种方式任选其一)。
方式 1:使用 openssl 生成(推荐,跨平台)
# 生成 16 字节(128 位)二进制密钥,保存为 enc.key openssl rand 16 > enc.key
方式 2:手动创建(测试用,不推荐生产环境)
若没有
openssl,可手动创建文本文件,写入 16 个字符(本质是 16 字节数据),保存为 enc.key(注意:生产环境必须用随机强密钥)。步骤 2:创建密钥信息文件(enc.keyinfo)
创建文本文件
enc.keyinfo,内容包含 3 行(格式固定,不可错乱):# 第 1 行:密钥的公开访问 URL(播放器将通过该 URL 请求密钥,需部署到服务器可访问) http://你的服务器IP/hls/enc.key # 第 2 行:密钥的本地文件路径(ffmpeg 用于读取密钥加密 TS 分片,绝对路径/相对路径均可) ./enc.key # 第 3 行:AES 初始化向量(IV,可选,16 字节,不填则 ffmpeg 自动生成并写入 m3u8) # 可选:手动指定 IV(用 openssl 生成:openssl rand -hex 16),例如: # 5f7a8d9c0b1e2f3a4b5c6d7e8f9a0b1c
说明:
- 第 1 行的 URL 必须与后续服务器部署的
enc.key路径一致。- 若省略第 3 行(IV),
ffmpeg会为每个 TS 分片生成唯一 IV,并在m3u8中通过#EXT-X-KEY携带。
步骤 3:使用 ffmpeg 生成加密的 HLS(m3u8 + TS)
在已有 HLS 转换命令的基础上,添加
-hls_key_info_file 参数指定密钥信息文件,即可实现加密。示例 1:单分辨率加密 HLS(基础版)
ffmpeg -i input.mp4 \ -c:v h264 \ -c:a aac \ -hls_time 10 \ # 每个 TS 分片时长 10 秒 -hls_list_size 0 \ # 保留所有 TS 分片 -hls_segment_filename "output_%03d.ts" \ # TS 分片命名 -hls_key_info_file ./enc.keyinfo \ # 核心:指定密钥信息文件,启用 AES-128 加密 -hls_encryption_method aes-128 \ # 明确指定加密算法(可选,默认即为 aes-128) output.m3u8 # 生成加密后的 m3u8
示例 2:多分辨率加密 HLS(自适应码率版)
对每个分辨率的 m3u8 都使用相同的
enc.keyinfo 加密(推荐统一密钥,也可分分辨率用不同密钥):
# 生成 480p 加密分片 ffmpeg -i input.mp4 \ -c:v h264 \ -c:a aac \ -vf "scale=854:480" \ -hls_time 10 \ -hls_list_size 0 \ -hls_segment_filename "480p_%03d.ts" \ -hls_key_info_file ./enc.keyinfo \ 480p.m3u8 # 生成 720p 加密分片 ffmpeg -i input.mp4 \ -c:v h264 \ -c:a aac \ -vf "scale=1280:720" \ -hls_time 10 \ -hls_list_size 0 \ -hls_segment_filename "720p_%03d.ts" \ -hls_key_info_file ./enc.keyinfo \ 720p.m3u8 # 生成主 m3u8(索引多分辨率,无需额外加密,子 m3u8 已加密) echo "#EXTM3U #EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=854x480 480p.m3u8 #EXT-X-STREAM-INF:BANDWIDTH=2000000,RESOLUTION=1280x720 720p.m3u8" > main.m3u8
步骤 4:查看加密结果
执行命令后,会生成以下文件(以单分辨率为例):
./ ├─ enc.key # AES-128 加密密钥(二进制文件) ├─ enc.keyinfo # 密钥信息配置文件(仅本地转换用,无需部署到服务器) ├─ output.m3u8 # 加密后的索引文件(包含加密信息) ├─ output_001.ts # 加密后的 TS 分片(无法直接播放,需密钥解密) ├─ output_002.ts # 加密后的 TS 分片 └─ ...
打开加密后的 output.m3u8,会看到新增的 #EXT-X-KEY 标签(加密核心信息):
#EXTM3U #EXT-X-VERSION:3 #EXT-X-KEY:METHOD=AES-128,URI="http://你的服务器IP/hls/enc.key",IV=0x5f7a8d9c0b1e2f3a4b5c6d7e8f9a0b1c #EXT-X-TARGETDURATION:10 #EXT-X-MEDIA-SEQUENCE:0 #EXTINF:10.0, output_001.ts #EXTINF:10.0, output_002.ts #EXT-X-ENDLIST
METHOD=AES-128:指定加密算法为 AES-128。URI:播放器请求密钥的地址。IV:初始化向量(若手动指定则显示,自动生成则为随机值)。
三、服务器部署(加密文件需完整部署)
1. 部署文件清单
必须将 3 类文件部署到服务器(
enc.keyinfo 无需部署,仅本地转换用):/var/www/html/hls/ # 服务器 HLS 根目录
├─ enc.key # 加密密钥(必须与 m3u8 中 URI 路径一致)
├─ output.m3u8 # 加密后的 m3u8 索引
├─ output_001.ts # 加密后的 TS 分片
└─ output_002.ts # 加密后的 TS 分片
2. Nginx 配置(补充密钥访问权限,可选)
- 保留之前的 HLS MIME 类型配置。
- (可选)限制
enc.key的访问权限(如仅允许指定域名、IP 访问,防止密钥泄露):
http { types { application/vnd.apple.mpegurl m3u8; video/mp2t ts; } server { listen 80; server_name 你的服务器IP; root /var/www/html; # 限制 enc.key 仅允许内部播放器访问(可选,增强安全性) location /hls/enc.key { allow 127.0.0.1; # 允许本地访问 allow 你的客户端IP; # 允许播放器客户端 IP deny all; # 拒绝其他所有访问 add_header Cache-Control "no-cache, no-store"; # 禁止密钥缓存 } # HLS 文件访问目录 location /hls/ { autoindex off; # 关闭目录索引,防止文件列表泄露 expires 1h; # TS 分片设置缓存 } } }
3.重启 Nginx 生效:nginx -s reload。
四、解密播放(自动完成,无需手动操作)
HLS 加密的解密过程是播放器自动完成的,无需额外编写解密代码,满足以下条件即可正常播放:
- 播放器支持 HLS 加密(主流播放器均支持:Safari 原生、VLC、Chrome 安装 HLS 插件、移动端 ExoPlayer/AVPlayer)。
- 播放器能够正常访问
m3u8地址和enc.key地址(网络可达,无权限拦截)。
播放测试方法
- VLC 播放器:打开 → 网络串流 → 输入
http://你的服务器IP/hls/output.m3u8→ 播放(自动请求enc.key并解密)。 - Safari 浏览器:直接在地址栏输入
http://你的服务器IP/hls/output.m3u8→ 原生支持播放。 - Chrome 浏览器:安装「HLS Player」插件 → 打开插件 → 输入 m3u8 地址 → 播放。
注意:若播放失败,大概率是enc.key访问失败(如路径错误、Nginx 权限拦截、跨域问题),可直接访问http://你的服务器IP/hls/enc.key测试:若能下载到 16 字节的文件,说明密钥可正常访问。
五、增强安全性补充(生产环境建议)
- 密钥动态生成 / 分发:不直接部署静态
enc.key,而是通过后端接口(如 PHP/Java/Go)动态返回密钥,接口可添加身份验证(如 Token、签名),防止密钥被恶意抓取。- 示例:将
enc.keyinfo中的 URI 改为http://你的服务器IP/api/get_hls_key?video_id=123&token=xxx,后端接口验证通过后返回enc.key的二进制数据。
- 示例:将
- HTTPS 部署:将 m3u8、TS 分片、密钥的访问协议改为 HTTPS,防止密钥和 TS 分片在传输过程中被抓包窃取。
- 定期更换密钥:对于敏感视频,定期更换
enc.key并重新生成加密 TS 分片,降低密钥泄露后的影响范围。
六、常见问题排查
- 播放器提示「无法加载密钥」:检查
m3u8中的URI路径是否正确,服务器enc.key是否可访问,跨域是否配置。 - TS 分片可下载但无法播放:确认
enc.key是 16 字节,加密时使用的keyinfo路径正确,ffmpeg版本不低于 3.0(低版本不支持 HLS 加密)。 - 多分辨率播放切换失败:确认所有子 m3u8 均使用相同的密钥配置,主 m3u8 中的子 m3u8 路径正确。
总结
- HLS 加密核心是 AES-128 对称加密,依赖
enc.key(密钥)和enc.keyinfo(密钥信息)。 ffmpeg通过-hls_key_info_file参数实现加密,生成的 m3u8 会携带加密配置。- 服务器需部署
m3u8、TS 分片、enc.key,播放器自动完成密钥请求和解密。 - 生产环境需通过「动态密钥」「HTTPS」「权限控制」增强安全性。

浙公网安备 33010602011771号