基于 IJKPlayer-concat 协议的视频无缝拼接技术实现
一、前言
Hi,大家好,我是承香墨影!
开门见山,开篇名义。今天来聊聊如何将多段视频,拼接成一个完整而连续的视频,然后无缝进行播放。
这样的需求应该不算偏门吧?
最简单的就是一些视频 App,会将大段的视频切割成小段的视频进行播放,还有一些在播放视频之前,会插播一段广告,这些需求都可以被本文的内容覆盖到。
说到多个视频拼接来说,如果你了解过 Google 出的 ExoPlayer 的话,它其内正好有一个 ConcatenatingMediaSource 可以来完成多个视频源的拼接工作,并且 Api 很好用,基本上算是无缝拼接。
不过呢,ExoPlayer 是依赖 MediaCodec 的,除了 Api Level 的限制之外(Api Level 16+),它对设备硬件也是有要求的,在一些低端机上,你会碰到一些莫名其妙的卡顿、马赛克、花屏等问题。而正是因为封装的太好了,如果你想自行添加软解,很遗憾,不太简单。而 Github 上 extensions 中,对 ffmpeg 的支持,也只是仅限于 Audio,对 Video 没有这个支持。
本文是基于另外一个很火的开源播放器:IJKPlayer,来看看如何去拼接视频。
二、IJKPlayer Concat
IJKPlayer 是一个基于 FFmpeg 的轻量级 Android/iOS 视频播放器,被 Bilibili 开源出来,算是国内很火的一款开源播放器了,很多 App 都在用。
因为背靠 FFmpeg,所以你在视频编码解码上碰到的大部分问题,IJKPlayer 都可以帮你解决,是一款非常好用的播放器。
IJKPlayer 本身已经很好用了,你如果想播放多段视频源的话,想要挨个的顺序播放,在要求不高或者本身有转场效果的前提条件下,也不是不可以。可如果是需要那种无缝的衔接,使用这种方式你会发现会有短暂的黑屏,因为加载新的视频源需要经历一小段时间,这种黑屏的现象在越差的设备上,越明显。
对此,我这里推荐的解决方案,就是使用 FFmpeg 的 concat 协议。
2.1 什么是 concat
concat 是 FFmpeg 提供的一个虚级联脚本分解器(以下简称 concat 协议),它是以一段有规则的脚本文件的形式存在的。可以使用 concat 定义一个视频播放列表,FFmpeg 在播放的时候,会根据你定义的顺序,一个接一个的解析进行播放,就好像他们本身就是一个视频源一样。
这么解释可能有点不清晰,不过如果你了解 .m3u8 的格式,你对 concat 的理解应该就不难,它们都是定义了一个视频列表,交由播放器的解码器去顺序播放。
具体的信息,可以去 FFmpeg 的官方文档中,查阅对应的内容。
FFmpeg Doc:
2.2 concat 文件
想要使用 concat 协议,首先需要定义一个待解析的文件。它必须是以 .ffcat 或者 .ffconcat 后缀结尾,并且文件的内容头,必须标记当前 concat 的版本号。
其内有两个可配置的选项:
- file:用于指定一个待解析的视频源,它可以指定一个本地的文件路径,或者一个在线的 Uri,都是合法的。
- duration:标记前一个 file 指定的视频源的长度,根据官方文档的介绍,它是和 seek 相关的,当你调整进度的时候,它可以精准的定位到文件。不过它是一个辅助参数,如果你拼接的视频码率什么的参数都一致,是可以不需要它的,所以 duration 是一个非必须的参数。
下面举个官方的例子来看看一个完整的 .ffcat 文件,应该是什么样子的。
ffconcat version 1.0
# my first filename
file /mnt/share/file-1.wav
duration 20.0
# my second filename including whitespace
file '/mnt/share/file 2.wav'
# my third filename including whitespace plus single quote
file '/mnt/share/file 3'\''.wav'
2.3 IJKPlayer 对 concat 的 Options 配置
在使用 IJKPlayer 的时候,会有一些设置是通过 setOption() 方法进行设置的,如果需要支持 concat 协议,同时也需要有对应的设置。
这里主要关注两点:
- protocol_whitelist : 协议白名单。
- safe:安全路径。
为了让 IJKPlayer 能支持 concat 协议,你需要将 concat 配置到它的白名单协议里,主要是为了添加 ffconcat 和 concat 两个。
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "protocol_whitelist", "rtmp,concat,ffconcat,file,subfile,http,https,tls,rtp,tcp,udp,crypto");
而 safe 主要是为了指定允许一些不安全的路径,默认值是 1 ,会拒绝一些不安全的文件路径。当然,什么是安全路径?你可以自行测试或者查阅文档,这里直接将它设置为 0 ,就可以将其安全监测关掉。
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT,"safe",0);
到此,基本上就说清楚关键点了,直接将这个 .ffcat 文件,丢给 IJKPlayer 就可以正常的顺序播放了。
concat 相关的内容非常的少,如果你在实际操作过程中,碰到问题,还是建议关注一下 Logcat 的输出信息,看看出错的原因。当然,通读一遍 FFmpeg 的 concat 文档,也是有帮助的。
三、Concat 查缺补漏
3.1 什么是安全路径
前面提到的,concat 文件中,file 后面跟随的文件路径,必须是一个安全路径,那什么是安全路径?
根据 concat 的文档描述,安全路径必须是一个相对路径,并且只不包含特殊符号,只包含(字母。数字、句点、下划线)等字符,并且路径开始的时候,不包含句点“.”,则认为是一个安全路径。
例如 :
file a.mp4
则认为是当前 .ffcat 文件所在目录下的 a.mp4 文件,这是一个安全路径。
相反的,例如 :"https://"、"file://"、"./" 这种视频源路径,均会视为不安全路径。
3.2 ffcat 文件是否一定要在本地
FFmpeg 只是接受一个 concat 协议格式的数据流,具体它是在本地还是在远端的服务器上,其实是不影响的。
3.3 file 是否可以混编
file 后面跟随的视频源的地址,concat 并不强制要求需要都在同一个地方。
ffconcat version 1.0
file /sdcard/a.mp4
file http://down4.xxx.com/hash/c644d9e118417e56d91cba3dc467ab9b.mp4
例如这样一个 .ffcat 文件,它是合法可播放的。
3.4 视频拼接的地方有黑屏闪动
concat 要求拼接的视频必须具有相同的流(相同的码率和时间基准等),所以如果前后两个视频源这些参数不一致,是可能导致闪一下黑屏的。
这个问题,我在非常差的电视盒子上做过测试,如果文件流保持一致,是可以做到无缝衔接。所以如果你也碰到这样的情况,不要怀疑 FFmpeg 的 concat 的问题,重新用 FFmpeg 转码一下你的视频文件再试试吧。
https://github.com/alwaystest/Blog/issues/58
https://www.jianshu.com/p/ea794a357b48
今天在公众号后台回复成长『成长』,将会得到我整理的一些学习资料,也能回复『加群』,一起学习进步。
推荐阅读:
- 漫画:程序员,你能“管理”好你的产品经理吗?
- 利用 Kotlin 的特性,优化 Intent 的数据传递!
- 解决 Lottie 动画包含图片的问题!
- Google 的 Flutter 学习资料!
- 远程控制智能电视,方案已开源!
基于 IJKPlayer-concat 协议的视频无缝拼接技术实现的更多相关文章
- 基于Kurento的WebRTC移动视频群聊技术方案
说在前面的话:视频实时群聊天有三种架构: Mesh架构:终端之间互相连接,没有中心服务器,产生的问题,每个终端都要连接n-1个终端,每个终端的编码和网络压力都很大.群聊人数N不可能太大. Router ...
- iOS直播-播放基于RTMP协议的视频
iOS直播-播放基于RTMP协议的视频 流媒体协议介绍 1. 伪流媒体: 渐进式下载 : 边下边存, 文件会保存 使用http协议,也能够实现视频播放, 也能快进快退等, 体验上跟流媒体很像. 优酷, ...
- 基于SURF特征的图像与视频拼接技术的研究和实现(一)
基于SURF特征的图像与视频拼接技术的研究和实现(一) 一直有计划研究实时图像拼接,但是直到最近拜读西电2013年张亚娟的<基于SURF特征的图像与视频拼接技术的研究和实现>,条 ...
- 基于Html5+HLS协议播放符合部标1078协议的实时流媒体视频
由于现在主流的部标GPS和1077视频监控平台,都是BS架构,在网页上播放视频,早期的很多平台用的都是ActiveX控件的形式,依赖于IE浏览器,需要降低浏览器的安全设置,而且非常难用.同时由于win ...
- 基于JT/T808协议的车辆监控平台架构方案
技术支持QQ:78772895 1.接入网关应用采用mina/netty+spring架构,独立于其他应用,主要负责维护接入终端的tcp链接.上行以及下行消息的解码.编码.流量控制,黑白名单等安全控制 ...
- Android 基于ijkplayer+Rxjava+Rxandroid+Retrofit2.0+MVP+Material Design的android万能播放器aaa
MDPlayer万能播放器 MDPlayer,基于ijkplayer+Rxjava+Rxandroid+Retrofit2.0+MVP+Material Design的android万能播放器,可以播 ...
- 使用java做一个能赚钱的微信群聊机器人(2020年基于PC端协议最新可用版)
前言 微信群机器人,主要用来管理群聊,提供类似天气查询.点歌.机器人聊天等用途. 由于微信将web端的协议封杀后,很多基于http协议的群聊机器人都失效了,所以这里使用基于PC端协议的插件来实现. 声 ...
- H5 的直播协议和视频监控方案
H5 的直播协议和视频监控方案 一.流媒体主要实现方式 二.流媒体技术 2.1 流媒体 2.2 直播 2.3 流协议 2.3.1 HLS 协议 2.3.2 RTMP 协议 2.3.3 RTSP 协议 ...
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载. 开源倾情奉献系列链接 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码 开源倾 ...
随机推荐
- The struts dispatcher cannot be found
1.错误描述 严重:Servlet.service() for servlet jsp threw exception The struts dispatcher cannot be found.Th ...
- Java中的throw和throws的区别
Java中的throw和throws的区别 1.throw关键字用于方法体内部,而throws关键字用于方法体部的方法声明部分: 2.throw用来抛出一个Throwable类型的异常,而throws ...
- DirectShow中写push模式的source filter流程 + 源代码(内附详细注释)
虽然网上已有很多关于DirectShow写source filter的资料,不过很多刚开始学的朋友总说讲的不是很清楚(可能其中作者省略了许多他认为简 单的过程),读者总希望看到象第一步怎么做,第二步怎 ...
- AJAX跨域问题总结
跨域是什么? 首先说下同源,同源策略是浏览器的一种安全策略,所谓同源是指,域名,协议,端口完全相同.而跨域就是不同源 ! 能够进行跨域的请求 一般a,img,link[rel=stylesheet], ...
- trs.getElementsByTagName is not a function 出现原因及解决办法
好久没有操作dom元素了,在定义dom元素时, let tBo = document.getElementById('tBody') let trs = tBo.getElementsByTagNam ...
- PHP二维数组搜索返回数组
$ar = array( 2 => array( 'catid' => 2, 'catdir' => 'notice', ), 5 => array( 'catid' => ...
- Maven 搭建 SSM 项目 (oracle)
简单谈一下maven搭建 ssm 项目 (使用数据库oracle,比 mysql 难,所以这里谈一下) 在创建maven 的web项目时,常常会缺了main/java , main/test 两个文件 ...
- jquery 实现拖动文件上传加进度条
通过对文件的拖动实现文件的上传,主要用到的是HTML5的ondrop事件,上传内容通道FormData传输: //进度条 <div class="parent-dlg" &g ...
- 我也不知道什么是"莫比乌斯反演"和"杜教筛"
我也不知道什么是"莫比乌斯反演"和"杜教筛" Part0 最近一直在搞这些东西 做了将近超过20道题目吧 也算是有感而发 写点东西记录一下自己的感受 如果您真的 ...
- Spring AOP梳理
一.Srping AOP AOP(Aspect Oriented Programming)解释为面向切面编程,何为切面,用刀把一块面包切成两半,刀切下去形成的面就叫切面,那么面向切面的就是形成切面的这 ...