Ijkplayer: 视频缓冲和分段播放问题

Created on 17 Apr 2015  ·  72Comments  ·  Source: bilibili/ijkplayer

感谢作者贡献了这么好的项目!我在使用的时候碰到了一些问题:
1、在使用IJKFFMoviePlayerController的暂停时缓冲也跟着暂停了,我用NSTimer去输出缓冲也是不变
2、处理多段播放能否使用另一个FFPlayer进行预缓冲和切换
3、最终缓冲playableDuration与视频的duration会有0.4~0.6秒的差距,这个是否是正常的
谢谢

All 72 comments

视频缓冲问题找到了,是我MAX_QUEUE_SIZE设置的太小了,导致直接缓冲好停止在那里

  1. 理论上可以,但是我没试过有什么问题。
  2. 不正常,不过在我接受范围之内。

最终缓冲playableDuration我找到问题了,在ff_ffplay.c中的 static int read_thread(void *arg)中会在数据加载完后设置eof = 1,然后走continue,之后缓冲 ffp->playable_duration_ms = buf_time_position; 就不执行了,可以考虑把缓冲代码调到前面或者在加载成功的eof = 1处加入
ffp->playable_duration_ms = ffp_get_duration_l(ffp);
如果MAX_QUEUE_SIZE设置小一点还好,会有0.4~0.6s的误差,如果设置成50 * 1024 * 1024可能会有5~10+s的误差

分段播放(处理网络分段)上我还是有问题,在获得结束通知时再切换FFPlayer一定会造成1s左右的卡顿,我换成切换IjkMediaPlayer在显示时报错,然后看了以前的关于分段的issue #38 有一个concat协议,但是网上查了很久也没有发现有相关iOS代码,我想请教一下用concat处理分段具体应该怎么做 @bbcallen

这一段Syntax我看的很糊涂,我是按着这样的格式作为我的FFMrl
concat:url1|url2...
但是在读取的时候分段虽然都有加载,但是无法自动播放下一段,format_control_message也没有被调用
如果用
file 'url1'
file 'url2'
又无法识别
有没有一个相关示例代码能让我了解一下 @bbcallen

你直接看 libavformat/concatdec.c 的代码吧,很短的。

1.跟着ffmpeg源代码走我发现设置url为concat:url1|url2|...是对的,protocol也正确读出是concat,不过在执行ffurl_connect的uc->prot->url_open2(uc,uc->filename,uc->flags,options)报错走了url_open。
2.我对format_option设置 ffconcat , version 1.0但是返回没有ffconcat这个选项,而在concatdec的concat_probe对应的是AVProbeData的buf开头有ffconcat version 1.0,我想问一下我具体该在哪里设置ffconcat version 1.0?
3.我在部分资料中查到concat支持的格式很少,而在官方文档中又看到了对flv格式,我想问一下concat是否支持mp4,m4a,flv,f4a等格式。
谢谢 @bbcallen

因为ffmpeg的url有长度限制,无法通过url传入所有分段,
所以你需要构造一个 ffconcat 的文件,把分段的时长和url写进一个临时文件,
然后把这个临时文件传给ffmpeg.
概念上类似m3u8, http://en.wikipedia.org/wiki/M3U

理论上,只要压制参数完全相同的分段,都是可以支持。

就是我需要写一个txt,url为concat:filepath,或者文件结尾为".ffcat" or ".ffconcat" 对应文件类似于

ffconcat version 1.0
file 'url1'
duration 100
file 'url2'
duration 100
...

绕了太多的弯路,谢谢帮助 @bbcallen

我认真看了一下两位的答案,还有一些不懂。

  1. 例如一个视频有3段分片,在客户端把这三个分片的url和duration按照格式写入一个txt文件中?
  2. 如果是在客户端构造了这个txt文件,那么这个文件怎样传给ffmpeg呢?
  3. 文件中的duration是怎样获取的呢?
    还是这个txt文件是在服务端写好,然后客户端只需要将这个文件的地址当作url传入就可以了呢?

这些问题研究了半天还没有结果,还请各位不吝赐教。

这个是需要自己去实现的吧,默认应该是不行的,可以使用ffplay测试一下

1.你可以客户端生成也可以服务端生成,服务端也是传回这个文件url.
2.把这个文件保存的路径url传入ffmpeg即可,地址开头协议可用ffconcat.
3.需要服务器传回每段长度或者想办法获取,也可以不传duration不过这样有可能seek不精准或者无法seek.

@Zard1096 能否给一个范例的concat文件,我自己试了一个好像不行,文件名是test.txt,内容是:
ffconcat version 1.0
file 'http://xxxx'
duration 186
file 'http://xxx'
duration 210

调用的时候采用mVideoPath = "ffconcat:/storage/emulated/0/test.txt"
还是会提示无法播放

路径应该设为 ffconcat://fileurl,ffconcat是协议
或者你尝试将文件命名为 *.concat 或 *.ffconcat

@Zard1096 请给一个测试文件吧

文件构成一样的,没有区别,你截一下日志我帮你看一下吧
还有concat需要设置option safe 0

@Zard1096 不会只能本地文件吧

unsafe file name 要设置设置option safe 0
你为什么要在ffconcat中设置m3u8?有m3u8直接设置m3u8就能读了。
还有在ffconcat中的文件压制码率必须一样。
ffconcat中再包一层HLS协议我不确定能不能读。
iOS是有新版好像变成ijkmp_set_option
Android应该是有个类似的setOption的方法

测试下这个协议,safe是出于什么考虑呢

safe设置为0,还是一样的错误

@Zard1096 给个测试链接吧

我并没有服务器,测试concat我都是本地组装或者挂在自己mac的Apache上测的
还是显示unsafe我估计你是没设置对
你自己扔到服务器上改一下ip测测看吧
链接: http://pan.baidu.com/s/1bnsbKBX 密码: xser

今天这个协议还是有所了解了,我的也可以播放的,不错。

@Zard1096 播放分段视频 ijkplayer 的源码 是否需要修改,如果修改,请问 再哪里修改呢?谢谢

@Android4MediaPlayer 播放分段视频 ijkplayer 的源码 是否需要修改,如果修改,请问 再哪里修改呢?谢谢

@Zard1096 @Android4MediaPlayer 我用 Zard1096提供的concat文件 测试了 报错:
/storage/emulated/0/ffmpeg_concat/ffconcat.concat: Operation not permitted

不需要修改源码的,ffmpeg就本身支持

@Android4MediaPlayer 我测试成功了,但是 播放的时候 发现个问题,就是在播放分段视频的时候 播放一段时间会暂停,当点击 播放按钮的时候 他还是暂停的, 除非 seek 才会播放。你遇到过 这个问题么?

@Android4MediaPlayer 能留个QQ号么? 谢谢了

把你的链接贴出来以及log

@Android4MediaPlayer 链接: http://pan.baidu.com/s/1sjLzMah 密码: isf4

@Android4MediaPlayer log:
10-08 16:01:37.844: W/IJKMEDIA(4255): java.nio.ByteBuffer class loaded
10-08 16:01:37.844: I/IJKMEDIA(4255): MediaCodec: API-19
10-08 16:01:37.844: W/IJKMEDIA(4255): android.media.MediaCodec$BufferInfo class loaded
10-08 16:01:37.844: W/IJKMEDIA(4255): android.media.MediaCodec class loaded
10-08 16:01:37.864: W/IJKMEDIA(4255): IjkMediaPlayer_native_init
10-08 16:01:37.864: W/IJKMEDIA(4255): IjkMediaPlayer_native_setup
10-08 16:01:37.864: D/IJKMEDIA(4255): ffpipeline_create_from_android()
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_format_callback(0x55bf3b4d, 0x1d200492)
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_format_callback()=void
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_android_set_mediacodec_select_callback()
10-08 16:01:37.864: D/IJKMEDIA(4255): ffpipeline_set_mediacodec_select_callback
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_android_set_mediacodec_select_callback()=void
10-08 16:01:37.864: W/IJKMEDIA(4255): IjkMediaPlayer_setAvFormatOption
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_format_option(http-detect-range-support, 0)
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_format_option()=void
10-08 16:01:37.864: W/IJKMEDIA(4255): IjkMediaPlayer_setOverlayFormat
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_overlay_format(RV32(0x32335652))
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_overlay_format()=void
10-08 16:01:37.864: W/IJKMEDIA(4255): IjkMediaPlayer_setAvCodecOption
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_codec_option()
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_codec_option()=void
10-08 16:01:37.864: W/IJKMEDIA(4255): IjkMediaPlayer_setFrameDrop
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_framedrop(12)
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_framedrop()=void
10-08 16:01:37.864: W/IJKMEDIA(4255): IjkMediaPlayer_setAvFormatOption
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_format_option(safe, 0)
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_format_option()=void
10-08 16:01:37.864: W/IJKMEDIA(4255): IjkMediaPlayer_setAutoPlayOnPrepared
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_auto_play_on_prepared(0)
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_auto_play_on_prepared()=void
10-08 16:01:37.864: W/IJKMEDIA(4255): IjkMediaPlayer_setDataSourceAndHeaders
10-08 16:01:37.864: V/IJKMEDIA(4255): setDataSource: path /storage/emulated/0/ffmpeg_concat/ffconcat.concat
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_data_source(url="/storage/emulated/0/ffmpeg_concat/ffconcat.concat")
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_data_source(url="/storage/emulated/0/ffmpeg_concat/ffconcat.concat")=0
10-08 16:01:37.864: W/IJKMEDIA(4255): IjkMediaPlayer_setVideoSurface
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_android_surface(surface=0xa550001d)
10-08 16:01:37.864: D/IJKMEDIA(4255): ffpipeline_set_surface()
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_set_android_surface(surface=0xa550001d)=void
10-08 16:01:37.864: W/IJKMEDIA(4255): IjkMediaPlayer_prepareAsync
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_prepare_async()
10-08 16:01:37.864: I/IJKMEDIA(4255): SDL_RunThread: [4294] ff_msg_loop
10-08 16:01:37.864: W/IJKMEDIA(4255): message_loop
10-08 16:01:37.864: W/IJKMEDIA(4255): FFP_MSG_FLUSH:
10-08 16:01:37.864: I/IJKMEDIA(4255): SDL_RunThread: [4295] ff_vout
10-08 16:01:37.864: D/IJKMEDIA(4255): ffpipenode_create_video_output_from_android_mediacodec()
10-08 16:01:37.864: W/IJKMEDIA(4255): ijkmp_prepare_async()=0
10-08 16:01:37.874: I/IJKMEDIA(4255): SDL_RunThread: [4296] ff_read
10-08 16:01:37.884: E/IJKMEDIA(4255): concat seekable: 1, 3075209000
10-08 16:01:37.914: W/IJKMEDIA(4255): IjkMediaPlayer_setVideoSurface
10-08 16:01:37.914: W/IJKMEDIA(4255): ijkmp_set_android_surface(surface=0xafb0001d)
10-08 16:01:37.914: D/IJKMEDIA(4255): ffpipeline_set_surface()
10-08 16:01:37.914: W/IJKMEDIA(4255): ijkmp_set_android_surface(surface=0xafb0001d)=void
10-08 16:01:37.994: E/IJKMEDIA(4255): Option http-detect-range-support not found.
10-08 16:01:38.014: I/IJKMEDIA(4255): max_frame_duration: 3600.000
10-08 16:01:38.014: I/IJKMEDIA(4255): Input #0, concat, from '/storage/emulated/0/ffmpeg_concat/ffconcat.concat':
10-08 16:01:38.014: I/IJKMEDIA(4255): Duration:
10-08 16:01:38.014: I/IJKMEDIA(4255): 00:51:15.21
10-08 16:01:38.014: I/IJKMEDIA(4255): , start:
10-08 16:01:38.014: I/IJKMEDIA(4255): 0.000000
10-08 16:01:38.014: I/IJKMEDIA(4255): , bitrate:
10-08 16:01:38.014: I/IJKMEDIA(4255): 0 kb/s
10-08 16:01:38.014: I/IJKMEDIA(4255): Stream #0:0
10-08 16:01:38.014: I/IJKMEDIA(4255): : Video: h264 (High), yuv420p, 512x288 [SAR 1:1 DAR 16:9]
10-08 16:01:38.014: I/IJKMEDIA(4255): ,
10-08 16:01:38.014: I/IJKMEDIA(4255): 15.17 fps,
10-08 16:01:38.014: I/IJKMEDIA(4255): 15 tbr,
10-08 16:01:38.014: I/IJKMEDIA(4255): 1k tbn,
10-08 16:01:38.014: I/IJKMEDIA(4255): 30 tbc
10-08 16:01:38.014: I/IJKMEDIA(4255): Stream #0:1
10-08 16:01:38.014: I/IJKMEDIA(4255): : Audio: aac (HE-AAC), 44100 Hz, stereo, fltp
10-08 16:01:38.014: I/IJKMEDIA(4255): SDL_Android_AudioTrack: CHANNEL_OUT_STEREO
10-08 16:01:38.014: I/IJKMEDIA(4255): SDL_Android_AudioTrack: ENCODING_PCM_16BIT
10-08 16:01:38.024: I/IJKMEDIA(4255): SDL_Android_AudioTrack_new: init volume as 1.000000/(0.000000,1.000000)
10-08 16:01:38.024: I/IJKMEDIA(4255): AudioCodec: avcodec, aac
10-08 16:01:38.024: I/IJKMEDIA(4255): SDL_RunThread: [4302] ff_aout_android
10-08 16:01:38.024: I/IJKMEDIA(4255): SDL_RunThread: [4303] ff_audio_dec
10-08 16:01:38.034: I/IJKMEDIA(4255): VideoCodec: avcodec, h264
10-08 16:01:38.034: I/IJKMEDIA(4255): fps: 15.166667 (normal)
10-08 16:01:38.034: I/IJKMEDIA(4255): fps: 15.000000 (normal)
10-08 16:01:38.034: I/IJKMEDIA(4255): SDL_RunThread: [4310] ff_video_dec
10-08 16:01:38.034: W/IJKMEDIA(4255): ijkmp_get_msg: FFP_MSG_PREPARED
10-08 16:01:38.034: W/IJKMEDIA(4255): FFP_MSG_PREPARED:
10-08 16:01:38.034: W/IJKMEDIA(4255): FFP_MSG_VIDEO_SIZE_CHANGED: 512, 288
10-08 16:01:38.034: W/IJKMEDIA(4255): FFP_MSG_SAR_CHANGED: 1, 1
10-08 16:01:38.084: W/IJKMEDIA(4255): IjkMediaPlayer_setVideoSurface
10-08 16:01:38.084: W/IJKMEDIA(4255): ijkmp_set_android_surface(surface=0xb540001d)
10-08 16:01:38.084: D/IJKMEDIA(4255): ffpipeline_set_surface()
10-08 16:01:38.084: W/IJKMEDIA(4255): ijkmp_set_android_surface(surface=0xb540001d)=void
10-08 16:01:41.344: W/IJKMEDIA(4255): IjkMediaPlayer_start
10-08 16:01:41.344: W/IJKMEDIA(4255): ijkmp_start()
10-08 16:01:41.344: W/IJKMEDIA(4255): ijkmp_start()=0
10-08 16:01:41.344: W/IJKMEDIA(4255): ijkmp_get_msg: FFP_REQ_START
10-08 16:01:41.344: D/IJKMEDIA(4255): ijkmp_get_msg: FFP_REQ_START: start on fly
10-08 16:01:41.354: W/IJKMEDIA(4255): ijkmp_get_msg: FFP_REQ_START
10-08 16:01:41.354: D/IJKMEDIA(4255): ijkmp_get_msg: FFP_REQ_START: start on fly
10-08 16:01:41.444: W/IJKMEDIA(4255): FFP_MSG_VIDEO_SIZE_CHANGED: 512, 288
10-08 16:01:41.444: W/IJKMEDIA(4255): SDL_VoutFFmpeg_CreateOverlay(w=512, h=288, fmt=RV32(0x32335652, dp=0x555d9410)
10-08 16:01:41.454: W/IJKMEDIA(4255): FFP_MSG_VIDEO_SIZE_CHANGED: 512, 288
10-08 16:01:41.454: D/IJKMEDIA(4255): ANativeWindow_setBuffersGeometry: w=512, h=288, f=(0x4) => w=512, h=288, f=RV32(0x32335652)
10-08 16:01:41.454: W/IJKMEDIA(4255): SDL_VoutFFmpeg_CreateOverlay(w=512, h=288, fmt=RV32(0x32335652, dp=0x555d9410)
10-08 16:01:41.484: W/IJKMEDIA(4255): SDL_VoutFFmpeg_CreateOverlay(w=512, h=288, fmt=RV32(0x32335652, dp=0x555d9410)
10-08 16:01:41.484: W/IJKMEDIA(4255): FFP_MSG_VIDEO_SIZE_CHANGED: 512, 288
10-08 16:07:43.894: D/IJKMEDIA(4255): ffp_toggle_buffering_l: start
10-08 16:07:43.894: W/IJKMEDIA(4255): FFP_MSG_BUFFERING_START:

@Android4MediaPlayer 每次 到06:02的时候 就暂停了,应该是这个片段结束了。

OK,播放了你的文件 我这里没啥问题,从你日志看没啥错误啊

@Android4MediaPlayer 每次播放完一个片段后,就会暂停。难道是我代码没有更新?

@Android4MediaPlayer 我从新拉代码 然后编译下 试试看。兄弟,能留个联系方式么?谢谢了

@Android4MediaPlayer 最新拉的代码编译出错,这个错误 你有遇见过吗?
编译环境:Ubuntu14.04.2 ndk-r9d

执行 ./compile-ffmpeg.sh all 时报错:
/root/ijkplayer/ijkplayer/android/contrib/build/ffmpeg-armv5/toolchain/bin//arm-linux-androideabi-gcc
arm-linux-androideabi-gcc is unable to create an executable file.
C compiler test failed.

If you think configure made a mistake, make sure you are using the latest
version from Git. If the latest version fails, report the problem to the
[email protected] mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "config.log" produced by configure as this will help
solve the problem.

@Android4MediaPlayer
我拉了最新的代码 编译运行
10-27 13:46:50.896 3013-9592/tv.danmaku.ijk.media.sample D/IJKMEDIA: Format concat probed with size=2048 and score=100
10-27 13:46:50.896 3013-9592/tv.danmaku.ijk.media.sample E/IJKMEDIA: Unsafe file name 'http://k.youku.com/player/getFlvPath/sid/744428508261510e451af_00/st/flv/fileid/0300020800560061E1EA6D05E9B1D491606BDA-3964-9F4F-9946-25C5B4603808?K=23f19ca78184a9d3261e9bbf&ctype=10&ev=1&oip=2014996627&token=7785&ep=ZTSGBoHWjTTDb3D9fA4oO3w4YTm1MNSISplnikQPGu9Y7EknSh0UB1GpSsbwqHY%2FyRDdtXaTw%2BaFl2b%2Fi%2FiCqumw%2BJ6RwyCJMt5BwtEp2XrCY8%2BeBAJSfEdheI3jhgmN6oEo3euk6ng%3D&ymovie=1'
10-27 13:46:50.896 3013-9592/tv.danmaku.ijk.media.sample D/IJKMEDIA: Statistics: 3270 bytes read, 0 seeks
10-27 13:46:50.896 3013-9592/tv.danmaku.ijk.media.sample E/IJKMEDIA: /storage/emulated/0/ffconcat.concat: Operation not permitted
10-27 13:46:50.896 3013-9590/tv.danmaku.ijk.media.sample D/IJKMEDIA: FFP_MSG_ERROR: 0
10-27 13:46:50.896 3013-9592/tv.danmaku.ijk.media.sample I/IJKMEDIA: SDL_JNI_DetachThreadEnv: [9592]
10-27 13:46:50.986 3013-3013/tv.danmaku.ijk.media.sample E/tv.danmaku.ijk.media.player.IjkMediaPlayer: Error (-10000,0)
10-27 13:46:51.036 3013-3023/tv.danmaku.ijk.media.sample D/IJKMEDIA: IjkMediaPlayer_native_finalize
10-27 13:46:51.036 3013-3023/tv.danmaku.ijk.media.sample D/IJKMEDIA: IjkMediaPlayer_release

@Android4MediaPlayer 分段视频 还是播放不成功

set format option "safe" = "0"

@bbcallen
我再上层代码中 设置了option的
try {
switch (mSettings.getPlayer()) {
case Settings.PV_PLAYER__IjkMediaPlayer: {
IjkMediaPlayer ijkMediaPlayer = null;
if (mUri != null) {
ijkMediaPlayer = new IjkMediaPlayer();
ijkMediaPlayer.native_setLogLevel(IjkMediaPlayer.IJK_LOG_DEBUG);

                    if (mSettings.getUsingMediaCodec()) {
                        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);
                        if (mSettings.getUsingMediaCodecAutoRotate()) {
                            ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 1);
                        } else {
                            ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 0);
                        }
                    } else {
                        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);
                    }

                    //就是这里
                    ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER,"safe",0);

                    if (mSettings.getUsingOpenSLES()) {
                        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 1);
                    } else {
                        ijkMediaPlayer.setOption(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "opensles", 0);
                    }

还是 不行的

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

Protocol not on whitelist 'file'! iOS 打印这句话 啥意思啊

没有添加白名单

@asawalker 之前没看到,如作者说设置safe

2016-05-13 17:14:24.467 EMLiveDeveloper[18633:7239890] OK setup GL
ijkmp_ios_set_view(glView=0x1493481a0)
ijkmp_ios_set_view(glView=0x1493481a0)=void
2016-05-13 17:14:24.571 EMLiveDeveloper[18633:7239890] invalidateRenderBuffer
ijkmp_set_data_source(url="/var/containers/Bundle/Application/7F20C695-667A-4C1F-923A-62012BFE09A5/EMLiveDeveloper.app/ffconcat.concat")
ijkmp_set_data_source(url="/var/containers/Bundle/Application/7F20C695-667A-4C1F-923A-62012BFE09A5/EMLiveDeveloper.app/ffconcat.concat")=0
ijkmp_prepare_async()

2016-05-13 17:14:24.576 EMLiveDeveloper[18633:7239973] IJKSDLGLView: setupDisplay not ready
ijkmp_prepare_async()=0
Setting default whitelist 'file'
Format concat probed with size=2048 and score=100
Protocol not on whitelist 'file'!
Impossible to open ' 。。。。。

调试出来的信息是这个 请问问题出在哪里啊。 分段直播 , URL 取得是本地的 concat文件

请问有木有iOS 的 分段 播放的代码用例啊, txt放在本地, 然后一直报错, 播放不了

@Zard1096 请问,我也写了一个.concat文件,然后将该文件本地的URL作为参数,可是视频不播放,报错是:ffconcat://Users/mac/Library/Developer/CoreSimulator/Devices/746273E7-5F1A-4542-A98B-093449641FAB/data/Containers/Data/Application/CDCD7E95-7532-4AFD-9205-CD0CBA4836B7/Documents: Protocol not found
这是什么原因呀,我的.concat文件内容是http://pan.baidu.com/s/1i557xhb

@DanielYQ
协议为 concat:// , protocol是concat不是ffconcat
还有一个问题可能存在的问题是你文件好像只到了路径,没有到最终的文件

追加: 下了你的文件看了一下,第一段url错了,视频能否播放就由你自己验证了,格式没问题

检查ffmpeg的config是否没有开启concat

@Zard1096 恩恩,谢谢,刚刚发现是一个url里有错误字符,现在已经可以播放了,但是播放完一段视频之后,播放按钮就显示播放状态停止不动,没有自动跳转到下一段视频,这是什么原因呀

检查视频格式是否一致包括分辨率、码率等等
https://trac.ffmpeg.org/wiki/Concatenate#samecodec

@Zard1096 恩恩 连续播放问题解决了,太谢谢啦

@Zard1096 为何我按照同样的方式,应用崩溃了 ?
https://github.com/Bilibili/ijkplayer/issues/1883

@Zard1096 看了您的回复,我有一些问题想请教:如果获取到分段视频的地址了,但不知道视频每个分段的长度,该如何写concat这个文件?可否不指定duration?
搜索了很多资料,ijkplayer还支持m3u8(m3u8貌似可以不指定duration也可以播放),若要本地加载m3u8该如何处理?谢谢

@yujieace 请注意看之前的回答:

3.需要服务器传回每段长度或者想办法获取,也可以不传duration不过这样有可能seek不精准或者无法seek.

m3u8里面需要有每段时长信息的.
本地加载concat或者m3u8都需要你自己把这文件临时创建出或者打在包中.
m3u8详见https://en.wikipedia.org/wiki/M3U
concat详见http://www.ffmpeg.org/ffmpeg-formats.html#Syntax

@Zard1096 谢谢,看您的回复,不传duration回导致seek不准确,也就是无法快进快退是吗?
另外,我按照格式制作了concat文件,内容如下,没有设置duration:

ffconcat version 1.0
file http://k.youku.com/player/getFlvPath/sid/44733195503852024cdb4_00/st/flv/fileid/03000204005778FD88B1211468DEFECD144F9F-8756-2AFC-BCF7-9E7FEC180ABC?k=e7c075c751b65f7b2412bbf5&hd=0&myp=0&ts=399&ymovie=1&r=/3sLngL0Q6CXymAIiF9JUfR5MDecwxp/gSVk/o8apWJ3KUkaGrqktKh7cO9ZZoqYN5iGQUM9dNrj6YzDV+fl4OMsoPBJy59kIMXjfthZ4+umaT96+CqKvDyAr51NsTXn2poWQ+xj9cVraYzNQP/KDG/NojgIY2OXgIHFwsn0dIY=&oip=2043096855&sid=44733195503852024cdb4&token=1765&did=5518c41bbaa48bbd0f534c0c523f8ca8&ev=1&ctype=20&ep=GRWXwVoC47Sx01ubOR5igeT0es9pUeg1dtqFeFic4%2FM10wRdqEqPaaITwwlzVZcnW4QAm8%2FmXO%2FqFtHAh%2FNr%2BvR0sqyx8NMuqZutUomvzKsFF9zKKyIvstt5qHfnisxh
file http://k.youku.com/player/getFlvPath/sid/44733195503852024cdb4_01/st/flv/fileid/03000204015778FD88B1211468DEFECD144F9F-8756-2AFC-BCF7-9E7FEC180ABC?k=5c16451e0c5e43c3261f3943&hd=0&myp=0&ts=393&ymovie=1&r=/3sLngL0Q6CXymAIiF9JUfR5MDecwxp/gSVk/o8apWJ3KUkaGrqktKh7cO9ZZoqYN5iGQUM9dNrj6YzDV+fl4CwBj8af5NI7xg4ZfrOlYmO8VdSGamvIwEvmUFkRmVVUDA8Ljfilr1rIY+0deGvcS7eUtnM5993MpkZ/XvrxRnQ=&oip=2043096855&sid=44733195503852024cdb4&token=1765&did=5518c41bbaa48bbd0f534c0c523f8ca8&ev=1&ctype=20&ep=GRWXwVoC47Sx01ubOR5igRZZ8y1mLFf1OiAeNadbI%2BU10wRdqEqPaaITwwlzVZcnW4QAm8%2FmXO%2FqFtHAh%2FNr%2BvR0sqyx8NMuqZutUomvzKsFF9zKKyIvstt5qHfnisxh
file http://k.youku.com/player/getFlvPath/sid/44733195503852024cdb4_02/st/flv/fileid/03000204025778FD88B1211468DEFECD144F9F-8756-2AFC-BCF7-9E7FEC180ABC?k=0d2947244116d422261f3943&hd=0&myp=0&ts=300&ymovie=1&r=/3sLngL0Q6CXymAIiF9JUfR5MDecwxp/gSVk/o8apWJ3KUkaGrqktKh7cO9ZZoqYN5iGQUM9dNrj6YzDV+fl4NGzXle0KwE+AceDaNWPWZ4ro/MfxoINgNC/fB/MDfrNDA8Ljfilr1rIY+0deGvcSxfGnJrXdodk5SAd8dxTE5Q=&oip=2043096855&sid=44733195503852024cdb4&token=1765&did=5518c41bbaa48bbd0f534c0c523f8ca8&ev=1&ctype=20&ep=GRWXwVoC47Sx01ubOR5igfkl0pQ9vcGzOUPFFDHOfe010wRdqEqPaaITwwlzVZcnW4QAm8%2FmXO%2FqFtHAh%2FNr%2BvR0sqyx8NMuqZutUomvzKsFF9zKKyIvstt5qHfnisxh
file http://k.youku.com/player/getFlvPath/sid/44733195503852024cdb4_03/st/flv/fileid/03000204035778FD88B1211468DEFECD144F9F-8756-2AFC-BCF7-9E7FEC180ABC?k=0f055abf8ff0aa39282bb691&hd=0&myp=0&ts=328&ymovie=1&r=/3sLngL0Q6CXymAIiF9JUfR5MDecwxp/gSVk/o8apWJ3KUkaGrqktKh7cO9ZZoqYN5iGQUM9dNrj6YzDV+fl4Ege4aTG/++MzEGn+YDBskutanBsZsX7l9b4KT3refgKSXB4Xd6D6aeWaZF7TrrqoOxYPvvpOdWZQsrvHKoe98k=&oip=2043096855&sid=44733195503852024cdb4&token=1765&did=5518c41bbaa48bbd0f534c0c523f8ca8&ev=1&ctype=20&ep=GRWXwVoC47Sx01ubOR5igfQRn1hOjfesmuF30OX4%2BYI10wRdqEqPaaITwwlzVZcnW4QAm8%2FmXO%2FqFtHAh%2FNr%2BvR0sqyx8NMuqZutUomvzKsFF9zKKyIvstt5qHfnisxh

播放器的初始化代码如下

[IJKFFMoviePlayerController checkIfFFmpegVersionMatch:YES];
    [IJKFFMoviePlayerController setLogLevel:k_IJK_LOG_DEBUG];
    [IJKFFMoviePlayerController setLogReport:YES];
    self.player=[[IJKFFMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:_url] withOptions:[IJKFFOptions optionsByDefault]];
    IJKFFMoviePlayerController *player=(IJKFFMoviePlayerController *)self.player;
    //[player setPlayerOptionValue:@"0" forKey:@"safe"];
    player.tcpOpenDelegate=self;
    [self.player prepareToPlay];
    [_player setShouldAutoplay:YES];

初始化的_url为

concat://var/mobile/Containers/Data/Application/5A81A85F-1E2A-4DA1-BEF9-1F03CC7B5521/Documents/playList.concat

播放时出现如下log

===== custom modules begin =====
register demuxer : ijklivehook
===== custom modules end =====
av_version_info: ff3.1--ijk0.6.1--20160824--001
ijkmp_set_inject_opaque(0x156d39f70)
ijkmp_set_inject_opaque()=void
2016-09-08 15:43:39.125 MoeMoe[1635:213265] OK setup GL
ijkmp_ios_set_view(glView=0x15818fbd0)
ijkmp_ios_set_view(glView=0x15818fbd0)=void
ijkmp_set_data_source(url="concat://var/mobile/Containers/Data/Application/9A393744-BB5B-47AD-B98C-D9FB6906CF31/Documents/playList.concat")
ijkmp_set_data_source(url="concat://var/mobile/Containers/Data/Application/9A393744-BB5B-47AD-B98C-D9FB6906CF31/Documents/playList.concat")=0
ijkmp_prepare_async()
ijkmp_prepare_async()=0
2016-09-08 15:43:39.164 MoeMoe[1635:213265] invalidateRenderBuffer
2016-09-08 15:43:39.172 MoeMoe[1635:213394] IJKSDLGLView: setupDisplay not ready
2016-09-08 15:43:39.191 MoeMoe[1635:213265] invalidateRenderBuffer
2016-09-08 15:43:39.202 MoeMoe[1635:213394] IJKSDLGLView: setupDisplay not ready
2016-09-08 15:43:39.216 MoeMoe[1635:213265] invalidateRenderBuffer
2016-09-08 15:43:39.219 MoeMoe[1635:213341] IJKSDLGLView: setupDisplay not ready
2016-09-08 15:43:39.231 MoeMoe[1635:213265] FFP_MSG_ERROR: 0
2016-09-08 15:43:39.232 MoeMoe[1635:213265] IJKMPMoviePlayBackStateDidChange 2: paused
2016-09-08 15:43:39.232 MoeMoe[1635:213265] playbackStateDidChange: IJKMPMovieFinishReasonPlaybackError: 1

设置了duation后的log

===== custom modules begin =====
register demuxer : ijklivehook
===== custom modules end =====
av_version_info: ff3.1--ijk0.6.1--20160824--001
ijkmp_set_inject_opaque(0x148a68e80)
ijkmp_set_inject_opaque()=void
2016-09-08 15:42:51.034 MoeMoe[1610:212624] OK setup GL
ijkmp_ios_set_view(glView=0x148a69c90)
ijkmp_ios_set_view(glView=0x148a69c90)=void
ijkmp_set_data_source(url="concat://var/mobile/Containers/Data/Application/1F7BB37A-8E87-486F-85B4-809FF485CDD4/Documents/playList.concat")
ijkmp_set_data_source(url="concat://var/mobile/Containers/Data/Application/1F7BB37A-8E87-486F-85B4-809FF485CDD4/Documents/playList.concat")=0
ijkmp_prepare_async()
ijkmp_prepare_async()=0
2016-09-08 15:42:51.065 MoeMoe[1610:212624] invalidateRenderBuffer
2016-09-08 15:42:51.074 MoeMoe[1610:212729] IJKSDLGLView: setupDisplay not ready
2016-09-08 15:42:51.100 MoeMoe[1610:212624] FFP_MSG_ERROR: 0
2016-09-08 15:42:51.105 MoeMoe[1610:212624] invalidateRenderBuffer
2016-09-08 15:42:51.105 MoeMoe[1610:212709] IJKSDLGLView: setupDisplay not ready
2016-09-08 15:42:51.123 MoeMoe[1610:212624] invalidateRenderBuffer
2016-09-08 15:42:51.123 MoeMoe[1610:212709] IJKSDLGLView: setupDisplay not ready

播放没有启动。请问是什么问题?

 IJKSDLGLView: setupDisplay not ready

你没有把player的视图添加到你需要显示的视图中

@Zard1096 谢谢,之前贴的代码没有包含添加视图和布局的部分,但实际是添加了的,如下

[IJKFFMoviePlayerController checkIfFFmpegVersionMatch:YES];
    [IJKFFMoviePlayerController setLogLevel:k_IJK_LOG_DEBUG];
    [IJKFFMoviePlayerController setLogReport:YES];
    self.player=[[IJKFFMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:_url] withOptions:[IJKFFOptions optionsByDefault]];
    IJKFFMoviePlayerController *player=(IJKFFMoviePlayerController *)self.player;
    //[player setPlayerOptionValue:@"0" forKey:@"safe"];
    player.tcpOpenDelegate=self;
    //player.segmentOpenDelegate=self;
    [self.player prepareToPlay];
    [_player setShouldAutoplay:YES];
    _player.scalingMode=IJKMPMovieScalingModeAspectFit;
    self.player.view.frame=self.view.bounds;
    [self.view addSubview:self.player.view];
    [self.player.view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.view);
    }];

添加了还是出现这个问题

参照一下ijk的demo,添加视图应该在prepareToPlay之前添加

@bbcallen @Zard1096 @DanielYQ

//1.ffconcat.concat 内的内容
ffconcat version 1.0
file 'http://k.youku.com/player/getFlvPath/sid/0474436212876865a4570_1B/st/flv/fileid/0300011C1B57C641EED39F2D9B7D2FA6E55867-FC0C-E588-50B3-838A955BEEA6?ctype=86&ev=1&K=13cd7747c05894a1261f3f54&ep=D55ddhAAy75BHUfB6AjcpRKxW3XamE%2FI6YrkNtxu%2F1WiMtLsdFwqyTXMJ6kjN%2BP0ZzFvyjppXq%2FVRCKRpaThGecPQvpJvzt%2BVZT%2BPVgNzXSCNiEht4HLqVDSqqDX&oip=2015001211&token=2487'
duration 48
file 'http://k.youku.com/player/getFlvPath/sid/0474436212876865a4570_1A/st/flv/fileid/0300011C1A57C641EED39F2D9B7D2FA6E55867-FC0C-E588-50B3-838A955BEEA6?ctype=86&ev=1&K=d6b4bedc397d20f7261f3f54&ep=D55ddhAAy75BHUfB6AjcpRKxW3XamE%2FI6YrkNtxu%2F1aiMtLsdFwqyTXMJ6kjN%2BP0ZzFvyjppXq%2FVRCKRpaThGecPQvpJvzt%2BVZT%2BPVgNzXSCNiEht4HLqVDSqqDX&oip=2015001211&token=2487'
duration 47

//2.实现
[IJKFFMoviePlayerController checkIfFFmpegVersionMatch:YES];
[IJKFFMoviePlayerController setLogLevel:k_IJK_LOG_DEBUG];
[IJKFFMoviePlayerController setLogReport:YES];
/*
self.textView.text为concat://Users/shendou/Library/Developer/CoreSimulator/Devices/85A871E2-22C9-4386-8504-652006991081/data/Containers/Data/Application/1750394E-3C2E-4ED1-AA31-4DAF9ACB2B5A/Library/ffconcat.concat
*/
self.player=[[IJKFFMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:self.textView.text] withOptions:[IJKFFOptions optionsByDefault]];
self.player.tcpOpenDelegate=self;
[self.player prepareToPlay];
[_player setShouldAutoplay:YES];
_player.scalingMode=IJKMPMovieScalingModeAspectFit;
self.player.view.frame=self.view.bounds;
[self.view addSubview:self.player.view];

//3.打印
===== custom modules begin =====
register protocol: async
register protocol: ijkhttphook
register protocol: ijkinject
register protocol: ijklongurl
register protocol: ijksegment
register protocol: ijktcphook
register demuxer : ijklivehook
===== custom modules end =====
av_version_info: ff3.0--ijk0.5.0--dev0.4.5--rc11
ijkmp_set_inject_opaque(0x7f98fbe10600)
ijkmp_set_inject_opaque()=void
2016-09-21 16:19:13.996 IJKMediaDemo[1633:871930] OK setup GL
ijkmp_ios_set_view(glView=0x7f98fbc32eb0)
ijkmp_ios_set_view(glView=0x7f98fbc32eb0)=void
ijkmp_set_data_source(url="concat://Users/shendou/Library/Developer/CoreSimulator/Devices/85A871E2-22C9-4386-8504-652006991081/data/Containers/Data/Application/1750394E-3C2E-4ED1-AA31-4DAF9ACB2B5A/Library/ffconcat.concat")
ijkmp_set_data_source(url="concat://Users/shendou/Library/Developer/CoreSimulator/Devices/85A871E2-22C9-4386-8504-652006991081/data/Containers/Data/Application/1750394E-3C2E-4ED1-AA31-4DAF9ACB2B5A/Library/ffconcat.concat")=0
ijkmp_prepare_async()
===== versions =====
FFmpeg : ff3.0--ijk0.5.0--dev0.4.5--rc11
libavutil : 55.17.103
libavcodec : 57.24.102
libavformat : 57.25.100
libswscale : 4.0.100
libswresample: 2.0.101
===== options =====
player-opts : start-on-prepared = 1
player-opts : overlay-format = fcc-_es2
player-opts : max-fps = 30
player-opts : framedrop = 0
player-opts : videotoolbox-max-frame-width = 960
player-opts : videotoolbox = 0
player-opts : video-pictq-size = 3
format-opts : ijkinject-opaque = 140295037584896
format-opts : ijkapplication = 140295035467472
format-opts : user-agent = ijkplayer
format-opts : auto_convert = 0
format-opts : timeout = 30000000
format-opts : reconnect = 1

format-opts : safe = 0

ijkmp_prepare_async()=0
concat://Users/shendou/Library/Developer/CoreSimulator/Devices/85A871E2-22C9-4386-8504-652006991081/data/Containers/Data/Application/1750394E-3C2E-4ED1-AA31-4DAF9ACB2B5A/Library/ffconcat.concat: Protocol not found
2016-09-21 16:19:13.999 IJKMediaDemo[1633:871930] invalidateRenderBuffer
2016-09-21 16:19:13.999 IJKMediaDemo[1633:871978] IJKSDLGLView: setupDisplay not ready
2016-09-21 16:19:14.001 IJKMediaDemo[1633:871930] invalidateRenderBuffer
2016-09-21 16:19:14.001 IJKMediaDemo[1633:871978] IJKSDLGLView: setupDisplay not ready
2016-09-21 16:19:14.007 IJKMediaDemo[1633:871930] FFP_MSG_ERROR: 0

//4.我已经看过诸位的所有问答记录,并一模一样的跟着实践,但仍然失败了,还请诸位多多赐教,谢谢

Protocol not found去ffmpeg中把concat协议加上

@Zard1096

是在实现里加以下代码吗?
IJKFFOptions * options = [IJKFFOptions optionsByDefault];
[options setFormatOptionValue:@"concat,file" forKey:@"protocol_whitelist"];

IJKFFOptions * options = [IJKFFOptions optionsByDefault];
[options setFormatOptionValue:@"concat,file" forKey:@"protocol_whitelist"];

[IJKFFMoviePlayerController checkIfFFmpegVersionMatch:YES];
[IJKFFMoviePlayerController setLogLevel:k_IJK_LOG_DEBUG];
[IJKFFMoviePlayerController setLogReport:YES];
self.player=[[IJKFFMoviePlayerController alloc] initWithContentURL:[NSURL URLWithString:self.textView.text] withOptions:options];

self.player.tcpOpenDelegate=self;
[self.player prepareToPlay];
[_player setShouldAutoplay:YES];
_player.scalingMode=IJKMPMovieScalingModeAspectFit;
self.player.view.frame=self.view.bounds;
[self.view addSubview:self.player.view];

加了,效果一样

ijkmp_prepare_async()=0
concat://Users/shendou/Library/Developer/CoreSimulator/Devices/85A871E2-22C9-4386-8504-652006991081/data/Containers/Data/Application/99C21B60-A1DE-4FAA-A816-AF24D9FFC1F9/Library/ffconcat.concat: Protocol not found
2016-09-21 16:49:54.602 IJKMediaDemo[1947:888230] invalidateRenderBuffer
2016-09-21 16:49:54.602 IJKMediaDemo[1947:888409] IJKSDLGLView: setupDisplay not ready
2016-09-21 16:49:54.603 IJKMediaDemo[1947:888230] invalidateRenderBuffer
2016-09-21 16:49:54.604 IJKMediaDemo[1947:888409] IJKSDLGLView: setupDisplay not ready
2016-09-21 16:49:54.611 IJKMediaDemo[1947:888230] FFP_MSG_ERROR: 0

ffmpeg的config

@Zard1096
是CONFIG_CONCAT_PROTOCOL吗?

Android 有人使用吗? 能在线替换 部分视频 或者 视频中的音频文件吗? 谢谢~

虽然 closed,但硬是给看呆了。。。Protocol not found 应该是指路径的开头 concat:// 错误吧,路径是类似 file:// 开头吧。。。 concat 只需要把文件拓展名设成 .ffcat 或者 .ffconcat 就可以识别了。

Was this page helpful?
0 / 5 - 0 ratings