前言
最近有个需求,需要将服务器视频资源进行加密提供给客户端播放,防止用户盗用视频。
常用的加密方式
m3u8切片加密(本文使用)
各种在线播放视频的网站广泛使用的技术,切片同样是使用AES加密算法。
优点:各种浏览器,手机,小程序都能兼容,通用性很好。
缺点:由于是公开的算法,还原也十分简单,有很多影音嗅探工具能直接下载还原,加密效果很弱,防小白可以,聊胜于无。
防翻录:无
文件流加密
采用异或或者AES等文件流加密方式,对文件数据进行处理。播放时动态解密相应的数据到内存再播放。
优点:加密和解密速度都很快。
缺点:必须使用专用的播放器才能解密,加密强度较弱,专业破解人员可写工具瞬间提取。
防翻录:通过播放器,APP实现
视频逐帧转码加密
加密强度最高但同时也是技术实现最麻烦的一种。软件需要读取源视频内部编码,逐帧把视频编码转为私有视频编码,通常是基于H264来改写为私有协议(即非标准H264算法)。
优点:由于采用私有视频编码协议,除非熟知视频内部编码规则,否则绝无破解或提取的可能,安全性极高。但这种加密方式对开发者技术要求较高,比较少公司使用。
缺点:必须使用专用的播放器才能解密,加密过程类似于视频转码,需要消耗比较长的加密时间。
防翻录:通过播放器,APP实现
环境要求
原理
核心原理其实就是讲解了一个视频源从正常的mp4
格式如何变为加密后的m3u8
文件+ts
文件+key
秘钥文件,之后使用vlc
播放。
实验
使用 OpenSSL 生成密钥
openssl rand 16 > [密钥存放位置]
例如: openssl rand 16 > D:\openssl_key\encrypt.key
生成IV
openssl rand -hex 16
会生成一串字符串,后面会用到
本次案例生成的字符串: 10c27a9e3fa363dfe4c44b59b67304b3
编写keyinfo文件
http://localhost:8000/encrypt.key
D:\openssl_key\encrypt.key
10c27a9e3fa363dfe4c44b59b67304b3
一共有三段信息
第一段:解密文件路径,必须是URI,用来解密视频文件
第二段:是加密文件路径
第三段:之前生成的IV
FFmpeg 将视频切片且加密
ffmpeg -y -i D:\openssl_key\test.mp4 -c:v libx264 -c:a copy -f hls -hls_time 180 -hls_list_size 0 -hls_key_info_file D:\openssl_key\enc.keyinfo -hls_playlist_type vod -hls_segment_filename D:\openssl_key\file%d.ts D:\openssl_key\playlist.m3u8
命令参数解释
命令参数 | 解释 |
---|---|
-y | 不经过确认,输出时直接覆盖同名文件。 |
-c | 指定编码器 |
-c copy | 直接复制,不经过重新编码(这样比较快) |
-i | 指定输入文件 |
-title | 设置标题 |
-author | 设置作者 |
-copyright | 设置版权 |
-f | 强制设置输入输出的文件格式,默认情况下ffmpeg会根据文件后缀名判断文件格式 |
-hls_key_info_file | keyinfo文件路径 |
-hls_time | 每段文件的时间长度(单位:秒) |
-hls_list_size 0 | 索引播放列表的最大列数 默认5,0 为不限制 |
-hls_playlist_type vod | 表示当前的视频流并不是一个直播流,而是点播流 |
-hls_segment_filename | 输出 ts和m3u8 文件路径中间空格 ,例如:D:\openssl_key\ file%d.ts D:\openssl_key\playlist.m3u8 |
%d:表示一位数字,从0开始。
最终执行结果
最后生成的文件
m3u8 文件
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:183
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-KEY:METHOD=AES-128,URI="http://localhost:8000/encrypt.key",IV=0x10c27a9e3fa363dfe4c44b59b67304b3
#EXTINF:182.625000,
file0.ts
#EXTINF:31.958333,
file1.ts
#EXT-X-ENDLIST
文件内容解析
#EXTM3U M3U8文件头,必须放在第一行;
#EXT-X-MEDIA-SEQUENCE 第一个TS分片的序列号,一般情况下是0,但是在直播场景下,这个序列号标识直播段的起始位置; #EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION 每个分片TS的最大的时长;
#EXT-X-TARGETDURATION:10 每个分片的最大时长是 10s
#EXT-X-ALLOW-CACHE 是否允许cache;
#EXT-X-ALLOW-CACHE:YES
#EXT-X-ALLOW-CACHE:NO 默认情况下是YES
#EXT-X-ENDLIST M3U8文件结束符;
#EXTINF extra info,分片TS的信息,如时长,带宽等;一般情况下是
#EXTINF:<duration>,[<title>] 后面可以跟着其他的信息,逗号之前是当前分片的ts时长,分片时长 移动要小于
#EXT-X-TARGETDURATION 定义的值;
#EXT-X-VERSION M3U8版本号
#EXT-X-DISCONTINUITY 该标签表明其前一个切片与下一个切片之间存在中断。下面会详解
#EXT-X-PLAYLIST-TYPE 表明流媒体类型;
#EXT-X-KEY 是否加密解析,
#EXT-X-KEY:METHOD=AES-128,URI="https://priv.example.com/key.php?r=52" 加密方式是AES-128,秘钥需要请求 https://priv.example.com/key.php?r=52 ,请求回来存储在本地;
总结
本篇文章简单的介绍了如何使用FFmpeg 将视频生成 ts 切片并使用 AES-128 加密。