
























.m3u8 是 HLS(HTTP Live Streaming) 协议的索引文件,用于分割后的 TS 分片的播放调度。制作核心是 将 MP4 转码为 TS 分片 + 生成对应的 m3u8 索引,主流工具是 ffmpeg。
HLS 加密(AES-128 加密,HLS 协议标准加密方式),核心是通过 ffmpeg 结合加密密钥(key)、密钥信息文件(keyinfo)实现 TS 分片加密,播放器会自动请求密钥并解密播放。下面提供完整的加密、部署、解密播放示例。
enc.key):二进制密钥文件,16 字节(AES-128 要求),用于加密 / 解密 TS 分片。enc.keyinfo):文本文件,记录密钥 URL、密钥本地路径、密钥初始化向量(IV,可选)。m3u8 和 TS 分片:ffmpeg 生成,m3u8 中会携带加密信息(密钥 URL、加密算法)。enc.key → 用密钥解密 TS 分片并播放。首先生成 16 字节的二进制密钥文件(两种方式任选其一)。
openssl 生成(推荐,跨平台)# 生成 16 字节(128 位)二进制密钥,保存为 enc.key openssl rand 16 > enc.key
若没有 openssl,可手动创建文本文件,写入 16 个字符(本质是 16 字节数据),保存为 enc.key(注意:生产环境必须用随机强密钥)。
创建文本文件 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携带。
在已有 HLS 转换命令的基础上,添加 -hls_key_info_file 参数指定密钥信息文件,即可实现加密。
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
对每个分辨率的 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
执行命令后,会生成以下文件(以单分辨率为例):
./ ├─ 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:初始化向量(若手动指定则显示,自动生成则为随机值)。必须将 3 类文件部署到服务器(enc.keyinfo 无需部署,仅本地转换用):
/var/www/html/hls/ # 服务器 HLS 根目录
├─ enc.key # 加密密钥(必须与 m3u8 中 URI 路径一致)
├─ output.m3u8 # 加密后的 m3u8 索引
├─ output_001.ts # 加密后的 TS 分片
└─ output_002.ts # 加密后的 TS 分片
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 加密的解密过程是播放器自动完成的,无需额外编写解密代码,满足以下条件即可正常播放:
m3u8 地址和 enc.key 地址(网络可达,无权限拦截)。http://你的服务器IP/hls/output.m3u8 → 播放(自动请求 enc.key 并解密)。http://你的服务器IP/hls/output.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 的二进制数据。enc.key 并重新生成加密 TS 分片,降低密钥泄露后的影响范围。m3u8 中的 URI 路径是否正确,服务器 enc.key 是否可访问,跨域是否配置。enc.key 是 16 字节,加密时使用的 keyinfo 路径正确,ffmpeg 版本不低于 3.0(低版本不支持 HLS 加密)。enc.key(密钥)和 enc.keyinfo(密钥信息)。ffmpeg 通过 -hls_key_info_file 参数实现加密,生成的 m3u8 会携带加密配置。m3u8、TS 分片、enc.key,播放器自动完成密钥请求和解密。此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。