alwaystest / Blog

24 stars 2 forks source link

IJKPlayer Concat #58

Open alwaystest opened 7 years ago

alwaystest commented 7 years ago

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,我们需要一个.ffcator.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 211Issue 1925在读取concat文件出错Operation not permitted的时候,在初始化Player的时候需要这样处理

  1. 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");

  2. set format option "safe" = "0"

    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_FORMAT,"safe",0);

这样子,就应该没有什么问题了。

测试的时候要多关注Logcat的输出信息,Option设置有没有生效在Log中是有Log的。

写完才发现IJKPlayer的源码中是有完善的方法注释的。现在知道为什么Example中为什么要依赖别的Module了,这样就能看到方法的说明了。

为什么没有source级别的jar包提供啊。。。

coolryze commented 5 years ago

请问,使用 IJKPlayer concat 来做多个视频连播时,如何知道从第x个视频播到了下一个视频呢? 我目前没有找到它的回调,暂时只能监听它的播放时长来做,不过不太准确 😢