Blog
Blog copied to clipboard
IJKPlayer Concat
IJKPlayer Concat
标签(空格分隔): Android IJKPlayer
网上搜索IJKPlayer的相关资料,发现很难找到Android上的IJKPlayer完整的集成文档,连Github的Repo中都找不到详细的描述,大家都说用法和MediaPlayer相似,直接上手用就可以了。然后就花了好多时间来研究这个Lib。
首先,IJKPlayer和ExoPlayer简单对比一下,IJKPlayer基于FFmpeg,ExoPlayer依赖的是Android中的Low Level Media APIs(API Level 16+)。两个Lib都提供了简单的Demo介绍使用方法。ExoPlayer提供的文档信息更为详细一些,还有API Docs提供,ExoPlayer的API使用我个人感觉更为方便简单。
粗略了瞄了一下ExoPlayer的代码,看起来是蛮简单易懂的,但是如果要实现Customize,还是有点难度,比如我不想用他提供的ConcatenatingMediaSource
,想自己实现一个的时候,就感到有困难了,主要是我水平姿势不够,里面有DataSource
,MediaSource
,TrackSelector
,LoadControl
各种概念要想搞明白还是需要精读代码的。
ExoPlayer的源码解析文章好多都是基于1.x版本的,目前ExoPlayer已经到了2.x版本,感觉用的人不是很多的样子,国内使用的开源方案大部分还是IJKPlayer,但是文档什么的,真的是噩梦一样啊。
说一说IJKPlayer使用FFmpeg的concat功能。
首先ffmpeg.org给出了使用concat功能的一些知识点,首先,我们需要知道
‘ffconcat’ Generate an ffconcat file for the created segments. The resulting file can be read using the FFmpeg concat demuxer.
A list file with the suffix ".ffcat" or ".ffconcat" will auto-select this format.
要使用concat这个demuxer,我们需要一个.ffcat
or.ffconcat
结尾的文件。文件内容需要符合知识点里面的Syntax部分。所以我们大概就有了这么一个文件。
lalala.ffcat
ffconcat version 1.0
file file-1.wav
duration 20.0
file subdir/file-2.wav
这里给出的是ffmpeg官方的Example。当然如果是用在Android里面,鬼知道相对路径会在什么地方(反正我是不知道),所以路径上我选择使用绝对路径。至于那个duration,根据官方文档,说是所有的file段都加了以后可以实现整个concat之后视频文件的seek功能,这不重要,我们现在的目标是让它能运行起来。
绝对路径eg:
file '/storage/emulated/0/Download/PrisonBreakS05E04.mp4'
为什么说目的是让它运行起来呢,因为现在还不能运行起来啊。
根据文档,ffconcat version 1.0
的效果
It also sets the safe option to 1 if it was -1.
至于为什么要加ffconcat version 1.0
,因为我看大家写的文章都加了,所以我也加了,具体作用官方知识点有说明,因为急于搞定播放这个事情,make FFmpeg recognize the format automatically
这里我就先跳过了,视频format的东西,不知道跳进坑里面爬出来需要多久,之前折腾PotPlayer的时候就看过那些巨复杂的设置,妈蛋你看个视频而已,折腾那么半天,各种参数调啊调,累不累?反正我是近视加散光。。。没有蓝光播放器什么的,暂时也用不着那么挑剔。反正目测是个大坑,先不跳了。
而safe
If set to 1, reject unsafe file paths. A file path is considered safe if it does not contain a protocol specification and is relative and all components only contain characters from the portable character set (letters, digits, period, underscore and hyphen) and have no period at the beginning of a component.
If set to 0, any file name is accepted.
The default is 1.
-1 is equivalent to 1 if the format was automatically probed and 0 otherwise.
所以我们用了绝对路径,就要想办法让safe这个参数为0。
这里有个家伙简单粗暴的通过修改源码的办法解决了这件事情。简书
通过Google,翻阅Issue,终于找到了优雅的方式,其实IJKPlayer是提供了API来修改这个参数的。
首先IJKPlayer提供的Example中VideoActivity
使用了tv.danmaku.ijk.media.example.widget.media.IjkVideoView
这么是个自定义View来播放,简单是简单,就是太简单了,不适合自定义。
所以我查到了这个用法。使用Player和SurfaceView结合来播放视频。至于这里的依赖呢,我偷懒直接Gradle添加Compile就好了,只是播放的话省的自己去编译了。
然后player.setDataSource
把上面lalala.ffconcat
文件的绝对路径传进去,当然要注意需要申请对应的读取权限哈。
根据Issue 211和Issue 1925在读取concat文件出错Operation not permitted
的时候,在初始化Player的时候需要这样处理
- add file to protocol_whitelist
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "protocol_whitelist", "rtmp,concat,ffconcat,file,subfile,http,https,tls,rtp,tcp,udp,crypto");
- set format option "safe" = "0"
ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT,"safe",0);
这样子,就应该没有什么问题了。
测试的时候要多关注Logcat的输出信息,Option设置有没有生效在Log中是有Log的。
写完才发现IJKPlayer的源码中是有完善的方法注释的。现在知道为什么Example中为什么要依赖别的Module了,这样就能看到方法的说明了。
为什么没有source级别的jar包提供啊。。。
请问,使用 IJKPlayer concat 来做多个视频连播时,如何知道从第x个视频播到了下一个视频呢? 我目前没有找到它的回调,暂时只能监听它的播放时长来做,不过不太准确 😢