openssl rand 16 >D:\video\encrypt.key
openssl rand -hex 16
ffmpeg -y -i [原始视频文件路径] -c:v libx264 -c:a copy -f hls -hls_time 180 -hls_list_size 0 -hls_key_info_file [密钥文件路径] -hls_playlist_type vod -hls_segment_filename [切片文件路径] [索引文件路径]
ffmpeg -y -i test.mp4 -c:v libx264 -c:a copy -f hls -hls_time 180 -hls_list_size 0 -hls_key_info_file enc.keyinfo -hls_playlist_type vod -hls_segment_filename "file%d.ts" playlist.m3u8
使用ffmpeg视频切片并加密
想达到的目的:将一个mp4视频文件切割为多个ts片段,并在切割过程中对每一个片段使用 AES-128 加密,最后生成一个m3u8的视频索引文件;
电脑环境 Fedora,已经安装了最新的ffmpeg;
如果要加密,首先准备好一下两个东西:
加密用的 key
openssl rand 16 > enc.key ( 生成一个enc.key文件 )
另一个是 iv
openssl rand -hex 16 ( 生成一段字符串,记下来)
新建一个文件 enc.keyinfo 内容格式如下:
Key URI # enc.key的路径,使用http形式
Path to key file # enc.key文件
IV # 上面生成的iv
几个例子:
http://localhost/video/enc.key
enc.key
48c674428c1e719751565ad00fe24243
最后重点来了
复制代码
ffmpeg -y \
-i test.mp4 \
-hls_time 12 \ # 将test.mp4分割成每个小段多少秒
-hls_key_info_file enc.keyinfo \
-hls_playlist_type vod \ # vod 是点播,表示PlayList不会变
-hls_segment_filename "file%d.ts" \ # 每个小段的文件名
playlist.m3u8 # 生成的m3u8文件
复制代码
生成的m3u8文件可以通过大部分播放器直接播放
ffmpeg 对mp4切片加密保存ts,通过密钥m3u8列表来播放。
git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg
利用ffmpeg将MP4文件切成ts和m3u8
1、将MP4转成m3u8
ffmpeg -i test.mp4 -codec copy -bsf h264_mp4toannexb test.ts
2、将ts转成m3u8
网上很多垃圾文章推荐segmenter工具,但用的时候,3.5G的ts文件丢了一半的数据,于是想到了ffmpeg转。
在国外网站找到命令,一句话搞定,没报半句错:
ffmpeg -i 12生肖.ts -c copy -map 0 -f segment -segment_list playlist.m3u8 -segment_time 10 output%03d.ts
顺便共享给各位国内的同仁,免得深受其苦。毕竟,大家都说HLS代表future,rtsp已经是过去式了。
使用ffmpeg将mp4切片成ts slice 并生成m3u8命令
使用ffmpeg将mp4切成ts片段的时候会碰到一个问题,就是生成的m3u8文件里只有最后的五个片段的信息。
这是因为ffmpeg 默认的list size 为5,所以只获得最后的5个片段。为了解决这个问题,需要指定参数-hls_list_size 0,这样就能包含所有的片段
ffmpeg -i input.mp4 -profile:v baseline -level 3.0 -s 640x360 -start_number 0 -hls_time 10 -hls_list_size 0 -f hls index.m3u8
不过最常用的命令是:
ffmpeg -i foo.mp4 -codec copy -vbsf h264_mp4toannexb -map 0 -f segment -segment_list out.m3u8 -segment_time 10 out%03d.ts
为什么要加上参数-vbsf h264_mp4toannexb
官方文档说Convert an H.264 bitstream from length prefixed mode to start code prefixed mode (as defined in the Annex B of the ITU-T H.264 specification).
这个问题在用ffmpeg从mp4里提取码流的时候(命令:ffmpeg -i foo.mp4 -vcodec copy -an foo.h264)也会碰到,生成的264文件无法播放,码流走中并没有00 00 00 01来分隔每一帧,这是因为默认是使用length prefixed mode,而不是以00 00 00 01起始码作为prefixed,也就是说没使用start code prefixed mode.
所以从mp4里提取码流的时候也需要加上参数-vbsf h264_mp4toannexb
正确命令为:ffmpeg -i foo.mp4 -vcodec copy -an -vbsf h264_mp4toannexb foo.h264
<video class="vjs-tech" width="100%" height="100%"
controls="controls" autoplay="autoplay"
x-webkit-airplay="true" x5-video-player-fullscreen="true"
preload="auto" playsinline="true" webkit-playsinline
x5-video-player-typ="h5">
<source type="application/x-mpegURL" src="http://dlhls.cdn.zhanqi.tv/zqlive/22578_yKdJM.m3u8">
</video>
https://www.cnblogs.com/codeAB/p/9184266.html
使用ffmpeg视频切片并加密
想达到的目的:将一个mp4视频文件切割为多个ts片段,并在切割过程中对每一个片段使用 AES-128 加密,最后生成一个m3u8的视频索引文件;
电脑环境 Fedora,已经安装了最新的ffmpeg;
如果要加密,首先准备好一下两个东西:
加密用的 key
openssl rand 16 > enc.key ( 生成一个enc.key文件 )
另一个是 iv
openssl rand -hex 16 ( 生成一段字符串,记下来)
新建一个文件 enc.keyinfo 内容格式如下:
Key URI # enc.key的路径,使用http形式
Path to key file # enc.key文件
IV # 上面生成的iv
几个例子:
http://localhost/video/enc.key
enc.key
48c674428c1e719751565ad00fe24243
最后重点来了
复制代码
ffmpeg -y \
-i test.mp4 \
-hls_time 12 \ # 将test.mp4分割成每个小段多少秒
-hls_key_info_file enc.keyinfo \
-hls_playlist_type vod \ # vod 是点播,表示PlayList不会变
-hls_segment_filename "file%d.ts" \ # 每个小段的文件名
playlist.m3u8 # 生成的m3u8文件
复制代码
生成的m3u8文件可以通过大部分播放器直接播放
在线视频平台如何实现视频加密功能
在线平台,(网站或手机app)学员通过在线平台购买学习,禁止学员下载、拷贝传播,这样的模式需要在线平台或app对接视频加密sdk程序,实现对课程视频的加密播放。该方式可以实现的一些功能:
1、视频文件在服务器上、网络传输过程中、浏览器缓存中,均为加密文件,杜绝加密后文件有短板漏洞,即使被下载到,也无法进行播放。
2、关键帧加密技术,加密前后的文件变化只增加几十个字节,基本保持一致大小,不增加网络传输压力
3、定制随机显示会员名走马灯(防止录屏)、定制logo、右键版权信息、播放片头片尾广告等功能。
4、加入权限控制和防盗链功能:限制非付费用户观看视频和非法下载视频。可以限制必须在某个网站中、用户登录后才可以进入播放器观看;
5、不同用户有不同的加密密钥,不同客户的加密系统和播放是无法共用的,即使一个客户购买也无法播放另外客户的视频;或者一个客户的加密被破解,也不会影响全部客户的使用。
6、播放过程中弹出题目,须回答题目才能继续观看;浮动会员ID显示,防录屏;播放列表功能等
<script src="https://cdn.jsdelivr.net/hls.js/latest/hls.min.js"></script>
<video id="video"></video>
<script>
if(Hls.isSupported()) {
var video = document.getElementById('video');
var hls = new Hls();
hls.loadSource('http://www.streambox.fr/playlists/test_001/stream.m3u8');
hls.attachMedia(video);
hls.on(Hls.Events.MANIFEST_PARSED,function() {
video.play();
});
}
</script>
<!DOCTYPE html>
<html>
<head>
<title>videojs支持hls直播实例</title>
<link href="./video.css?v=bcd2ce1385" rel="stylesheet">
</head>
<body>
<video id="roomVideo" class="video-js vjs-default-skin vjs-big-play-centered" x-webkit-airplay="allow" poster="" webkit-playsinline playsinline x5-video-player-type="h5" x5-video-player-fullscreen="true" preload="auto">
<source src="/chat/playlist.m3u8" type="application/x-mpegURL">
</video>
<script src="./video.js?v=fc5104a2ab23"></script>
<script src="./videojs-contrib-hls.js?v=c726b94b9923"></script>
<script type="text/javascript">
var myPlayer = videojs('roomVideo',{
bigPlayButton : false,
textTrackDisplay : false,
posterImage: true,
errorDisplay : false,
controlBar : false
},function(){
console.log(this)
this.on('loadedmetadata',function(){
console.log('loadedmetadata');
//加载到元数据后开始播放视频
startVideo();
})
this.on('ended',function(){
console.log('ended')
})
this.on('firstplay',function(){
console.log('firstplay')
})
this.on('loadstart',function(){
//开始加载
console.log('loadstart')
})
this.on('loadeddata',function(){
console.log('loadeddata')
})
this.on('seeking',function(){
//正在去拿视频流的路上
console.log('seeking')
})
this.on('seeked',function(){
//已经拿到视频流,可以播放
console.log('seeked')
})
this.on('waiting',function(){
console.log('waiting')
})
this.on('pause',function(){
console.log('pause')
})
this.on('play',function(){
console.log('play')
})
});
var isVideoBreak;
function startVideo() {
myPlayer.play();
//微信内全屏支持
document.getElementById('roomVideo').style.width = window.screen.width + "px";
document.getElementById('roomVideo').style.height = window.screen.height + "px";
//判断开始播放视频,移除高斯模糊等待层
var isVideoPlaying = setInterval(function(){
var currentTime = myPlayer.currentTime();
if(currentTime > 0){
$('.vjs-poster').remove();
clearInterval(isVideoPlaying);
}
},200)
//判断视频是否卡住,卡主3s重新load视频
var lastTime = -1,
tryTimes = 0;
clearInterval(isVideoBreak);
isVideoBreak = setInterval(function(){
var currentTime = myPlayer.currentTime();
console.log('currentTime'+currentTime+'lastTime'+lastTime);
if(currentTime == lastTime){
//此时视频已卡主3s
//设置当前播放时间为超时时间,此时videojs会在play()后把currentTime设置为0
myPlayer.currentTime(currentTime+10000);
myPlayer.play();
//尝试5次播放后,如仍未播放成功提示刷新
if(++tryTimes > 5){
alert('您的网速有点慢,刷新下试试');
tryTimes = 0;
}
}else{
lastTime = currentTime;
tryTimes = 0;
}
},3000)
}
</script>
</body>
</html>