前言
视频有数字版权,大家都应该保护。针对视频安全的保护手段可以从访问控制、内容加密、水印元数据、数字签名等几个方面着手。我们分别聊一下。
水印元数据
这个比较简单,在视频处理的时候往视频头加入元数据,标识版权所有等信息,可以在一定程度上识别视频属权。也可以往视频帧打上水印,引入不同时间,不同位置,不同形状,不同颜色等变化参数来对抗自动/智能水印消除的方法。
修改元数据关键的参数是-metadata key=value,我们举几个例子,譬如设置播放标题title=“xxxx”;也有-map_metadatainfile,具体可以参考ffmpeg官网。这些内容一般会显示在文件简介里面。
打入水印到视频里面,一般使用-vf滤镜系统,大概命令是-vf “filter”,各个常用滤镜如下:
- drawtext
文本内容水印,用text来指定水印文字,一般是-vf “drawtext=text='xxxx'”,我们可以针对text指定fontsize=60字号,字体fontfile=xxxx.ttf,字色fontcolor=white,背景色boxcolor=yellow,边框box=red,位置x=20:y=20,注意每个属性之间是用冒号隔离,命令例子如下所示:
-vf “drawtext=text=‘xxxxxx’:fontsize=60:fontcolor=white:x=20:y=20” - movie
相当于是2个画面帧内容融合,指定水印融合在原视频的位置和格式,命令例子如下,
-vf “movie=xxx.jpg[watermark];[in][watermark]overlay=20:20[out]”
前面我们在视频质量评分已经见过这个样子的滤镜组合方式,这里我们就不展开介绍。movive读入xxx.jpg,以watermart作为输出,overlay表示在in视频帧x=20,y=20的位置上按原始尺寸大小贴片watermark内容。其他还可以针对movie配置滤镜序列缩放scale,colorkey等,记得用逗号分割串联各个滤镜。 - 如果需要多个水印,那么就要使用filter_complex
假如我们需要先打入xxxx文字水印,又需要打入xxx.jpg水印,那么我们大概的命令例子如下:
-i xxx.jpg -filter_complex "drawtext=text='xxxx'[o1];[o1][1:v]overlay=20:H-h"
大概的意思是输入原视频帧,先drawtext后输出到o1,在o1视频帧x=20,底部对齐位置将xxx.jpg内容融合。其中的分号是分割2个滤镜的标识。其他参数在此省略,大家可以自行敲命令试试看。
访问控制
分成两个阶段的访问控制,请求视频播放地址的访问控制,播放视频地址的访问控制。
- 请求视频播放地址的访问控制在业务端控制,手段包括控制access toke有效期/合法用户、控制请求ip个数、控制api请求次数、refer标识请求来源是否合法、ua标识请求端是否合法。
- 播放视频地址访问控制一般发生在云存储服务商cos/oss提供的访问服务控制,通过发放访问凭证给客户端进行资源访问,资源访问必须要带上下发token才能正常访问,类型和上述形式差不多,都属于规则阻断机制。
内容加密
一般是对内容进行加密,播放的时候通过下发公钥进行解密播放。譬如针对整个mp4文件进行加密,但是如果mp4文件比较大,那么是不可取的,对大文件进行加解密是非常消耗资源的,也对播放延迟也是影响非常大。这个时候就可以考虑m3u8切片,针对切片进行加解密。考虑到前面好像没有提及这部分内容,我们先大概看看m3u8切片的命令:
ffmpeg -i in.mp4 -c:a copy -c:v libx264 -vf scale=1080:-2 -r 30 -crf 30 -vbsf h264_mp4toannexb -movflags frag_keyframe+faststart -f hls -hls_segment_type mpegts -hls_time 2 -hls_list_size 0 -hls_playlist_type vod -hls_flags delete_segments+split_by_time out.m3u8
以上大概是将视频以h264方式编码,然后转换成hls格式,生成m3u8文件,hls_xxx都是文件头内容参数。需要关注以下几个参数:
- -hls_segment_type mpegts,表示分片ts文件格式,还可以是fmp4
- -hls_time 2,表示预设分片时间长度
- -hls_list_size 0,把全部分片都包括上,否则只会包含前10片
- -hls_flags split_by_time,固定时间分片长度,否则自动调整合适分片时间长度
得到大概m3u8格式如下:
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXTINF:2.033333,
out_ts0.ts
#EXTINF:1.966667,
out_ts1.ts
#EXTINF:2.000000,
out_ts2.ts
...
#EXT-X-ENDLIST
针对m3u8文件进行加密,其本身就支持,只需要增加参数-hls_key_info_file enc.keyinfo,配置enc.keyinfo信息即可自动针对ts进行加密。enc.keyinfo文件内容大概包括加密的密钥信息,本地加密密钥路径还有可选的随机16位hex格式的IV。因为解密密钥请求这些需要请求风控,那么我们可以增加设定不允许m3u8本地缓存-hls_allow_cache 0。
#EXTM3U
#EXT-X-VERSION:3
#EXT-X-TARGETDURATION:2
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-ALLOW-CACHE:NO
#EXT-X-KEY:METHOD=AES-128,URI=https://.../enc.key,IV=0x...
#EXTINF:2.000000,
enc_out0.ts
#EXTINF:2.000000,
enc_out1.ts
#EXTINF:2.066667,
enc_out2.ts
...
#EXT-X-ENDLIST
可以关注的是#EXT-X-KEY:METHOD=是可以出现在m3u8文件的任何一个位置。也就是说,针对ts可以采用不同方式的加密串,只要能够匹配相应的加密key文件即可。同时针对URI请求访问是可以采用上述访问控制进行安全保护的。
除开常规m3u8内容加密之外,我们还可以自行配置分片/分包的加密策略,在传输给播放器之前先加密,再在播放的时候在把相应数据包进行解密之后,再post数据到解码器进行解码播放。这个需要客户端sdk支持,侵入到数据传输,解码解码流程。
数字版权管理
上面提到的针对内容进行加解密的通用方法就是DRM,它解决的是音视频盗版的问题。这个需要系统原生支持,譬如android系统的drm platform。感兴趣的大家可以去搭建使用。这里就不讨论了。
总结
可能还有很多很多保护视频的手段,我们就不能全部列举。在实际投产过程中需要真实面对问题,我们才能解决问题。在投入和产出之间作出平衡,在简单和效率作出平衡,基于现有技术栈和人力之间作出决定,譬如针对m3u8还可以对全部的ts文件名进行混淆乱序,增加脚本处理难度。总的来说,控制访问,内容加密,版权信息,水印标识,最终按需要上drm系统。