一、对于普通的加密方式
直接使用下面的命令就行
ffmpeg -i animal.mp4 -vcodec copy -acodec copy -encryption_scheme cenc-aes-ctr -encryption_key c7e16c4403654b85847037383f0c2db3 -encryption_kid a7e61c373e219033c21091fa607bf3b8 -encryption_iv 1234567890abcdef1234567890abcdef encrypted_IV3.mp4
简单解释一下各种参数的作用,
播放的话,采用的是ffplay,命令行如下
ffplay encrypted_IV.mp4 -dencryption_key c7e16c4403654b85847037383f0c2db3 -decryption_iv 1234567890abcdef1234567890abcdef
对于代码加密代码,此处复制的别人的,项目并不需要这个,我就没做验证
AVDictionary *opts = NULL;
// 指定加密参数
av_dict_set(&format_opts, "encryption_scheme", "cenc-aes-ctr", 0);
av_dict_set(&format_opts, "encryption_key", "c7e16c4403654b85847037383f0c2db3", 0);
av_dict_set(&format_opts, "encryption_kid", "a7e61c373e219033c21091fa607bf3b8", 0);
ret = avformat_write_header(AVFormatContext, &format_opts);
解密的代码也是别人的,但我是经过验证的,确认可行
AVDictionary *format_opts = NULL;
// 指定解密key
av_dict_set(&format_opts, "decryption_key", "c7e16c4403654b85847037383f0c2db3", 0);
av_dict_set(&format_opts, "decryption_iv", "1234567890abcdef1234567890abcdef", 0);
err = avformat_open_input(&AVFormatContext, "path", AVInputFormat, &format_opts);
二、对于流式的加密方式
命令行如下
ffmpeg -i animal.mp4 -movflags frag_keyframe -encryption_scheme cenc-aes-ctr -encryption_key c7e16c4403654b85847037383f0c2db3 -encryption_kid a7e61c373e219033c21091fa607bf3b8 encrypted.mp4
播放的话和普通的一致。
出现下面这三个字段,就是说明成功了。工具我用的是Bento4,Bento4有个命令mp4dump可以查看。
三、需要注意的是---moov
ffmpeg有一个参数,叫empty_moov 。当你创建一个MP4文件时,通常它首先写入一个moov
原子(也就是元数据),然后是mdat
原子(包含实际的音频/视频数据)。但是,如果你想开始记录并在之后添加元数据,你需要首先写入一个空的moov
原子,简单理解就是:
普通的MP4 的格式(从上到下): moov -> data
加了empty_moov的MP4格式: empty_moov -> data -> moov
如果你把moov移动到了MP4末尾的同时做了aes-ctr加密,就会出错,因为ffmpeg在解密aes-ctr时要先知道加密的重要参数,而这个参数就在moov中,然后才能进行解密,如果moov放在了末尾,那ffmpeg就不知道要怎么解密了。该情况下我遇到的错误有下面几种
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x149204a10] Incorrect number of samples in encryption info
[mov,mp4,m4a,3gp,3g2,mj2 @ 0x1426658b0] saio atom found without saiz
[h264 @ 0x7f93ba8a3e00] Invalid NAL unit size (217505651 > 1332).
[h264 @ 0x7f93ba8a3e00] Error splitting the input into NAL units.