HLS(HTTP Live Streaming)标准的视频及加密和解密播放

.m3u8 是 HLS(HTTP Live Streaming) 协议的索引文件,用于分割后的 TS 分片的播放调度。制作核心是 将 MP4 转码为 TS 分片 + 生成对应的 m3u8 索引,主流工具是 ffmpeg。

HLS 加密(AES-128 加密,HLS 协议标准加密方式),核心是通过 ffmpeg 结合加密密钥(key)、密钥信息文件(keyinfo)实现 TS 分片加密,播放器会自动请求密钥并解密播放。下面提供完整的加密、部署、解密播放示例。

一、HLS 加密核心原理

 
  1. 采用 AES-128-CBC 对称加密(HLS 协议强制要求,兼容性最好),所有 TS 分片均用该算法加密。
  2. 需准备 3 个核心文件:
    • 加密密钥(enc.key):二进制密钥文件,16 字节(AES-128 要求),用于加密 / 解密 TS 分片。
    • 密钥信息文件(enc.keyinfo):文本文件,记录密钥 URL、密钥本地路径、密钥初始化向量(IV,可选)。
    • 加密后的 m3u8 和 TS 分片:ffmpeg 生成,m3u8 中会携带加密信息(密钥 URL、加密算法)。
     
  3. 播放流程:播放器解析 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. 第 1 行的 URL 必须与后续服务器部署的 enc.key 路径一致。
  2. 若省略第 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 配置(补充密钥访问权限,可选)

  1. 保留之前的 HLS MIME 类型配置。
  2. (可选)限制 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 加密的解密过程是播放器自动完成的,无需额外编写解密代码,满足以下条件即可正常播放:
  1. 播放器支持 HLS 加密(主流播放器均支持:Safari 原生、VLC、Chrome 安装 HLS 插件、移动端 ExoPlayer/AVPlayer)。
  2. 播放器能够正常访问 m3u8 地址和 enc.key 地址(网络可达,无权限拦截)。

播放测试方法

  1. VLC 播放器:打开 → 网络串流 → 输入 http://你的服务器IP/hls/output.m3u8 → 播放(自动请求 enc.key 并解密)。
  2. Safari 浏览器:直接在地址栏输入 http://你的服务器IP/hls/output.m3u8 → 原生支持播放。
  3. Chrome 浏览器:安装「HLS Player」插件 → 打开插件 → 输入 m3u8 地址 → 播放。
 
注意:若播放失败,大概率是 enc.key 访问失败(如路径错误、Nginx 权限拦截、跨域问题),可直接访问 http://你的服务器IP/hls/enc.key 测试:若能下载到 16 字节的文件,说明密钥可正常访问。
 
 

五、增强安全性补充(生产环境建议)

  1. 密钥动态生成 / 分发:不直接部署静态 enc.key,而是通过后端接口(如 PHP/Java/Go)动态返回密钥,接口可添加身份验证(如 Token、签名),防止密钥被恶意抓取。
    • 示例:将 enc.keyinfo 中的 URI 改为 http://你的服务器IP/api/get_hls_key?video_id=123&token=xxx,后端接口验证通过后返回 enc.key 的二进制数据。
     
  2. HTTPS 部署:将 m3u8、TS 分片、密钥的访问协议改为 HTTPS,防止密钥和 TS 分片在传输过程中被抓包窃取。
  3. 定期更换密钥:对于敏感视频,定期更换 enc.key 并重新生成加密 TS 分片,降低密钥泄露后的影响范围。
 

六、常见问题排查

  1. 播放器提示「无法加载密钥」:检查 m3u8 中的 URI 路径是否正确,服务器 enc.key 是否可访问,跨域是否配置。
  2. TS 分片可下载但无法播放:确认 enc.key 是 16 字节,加密时使用的 keyinfo 路径正确,ffmpeg 版本不低于 3.0(低版本不支持 HLS 加密)。
  3. 多分辨率播放切换失败:确认所有子 m3u8 均使用相同的密钥配置,主 m3u8 中的子 m3u8 路径正确。
 

总结

  1. HLS 加密核心是 AES-128 对称加密,依赖 enc.key(密钥)和 enc.keyinfo(密钥信息)。
  2. ffmpeg 通过 -hls_key_info_file 参数实现加密,生成的 m3u8 会携带加密配置。
  3. 服务器需部署 m3u8TS 分片enc.key,播放器自动完成密钥请求和解密。
  4. 生产环境需通过「动态密钥」「HTTPS」「权限控制」增强安全性。
 
 
 
 

 

posted @ 2026-01-20 09:42  与f  阅读(0)  评论(0)    收藏  举报