首先能不能请问300-350ms是怎样设置参数的。。。
probesize设置小点
infbuf设为1不限制输入缓存
fflags设为nobuffer
max_cached_duration设置小点
packet-buffering设为0
start-on-prepared设为1
备注:局域网环境测试
问下这个问题有解决吗,我也遇到这个问题
做到了130ms,还得继续优化。。。
能看看你的option参数配置吗
@xufuji456 请问怎么配置或者修改达到130ms?
@xufuji456 朋友,你好,请问你的优化直播延时选项是否可以告知,我会有偿感谢的。
VideoOptionModel videoOptionMode01 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "fast", 1);//不额外优化
VideoOptionModel videoOptionMode02 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "probesize", 200);//10240
VideoOptionModel videoOptionMode03 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "flush_packets", 1);
//pause output until enough packets have been read after stalling
VideoOptionModel videoOptionMode04 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "packet-buffering", 0);//是否开启缓冲
//drop frames when cpu is too slow:0-120
VideoOptionModel videoOptionMode05 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "framedrop", 1);//丢帧,默认是1
//automatically start playing on prepared
VideoOptionModel videoOptionMode06 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "start-on-prepared", 1);
VideoOptionModel videoOptionMode07 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_CODEC, "skip_loop_filter", 48);//默认值48
//0:代表关闭;1:代表开启
VideoOptionModel videoOptionMode08 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 0);//开启硬解
VideoOptionModel videoOptionMode09 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-auto-rotate", 0);//自动旋屏
VideoOptionModel videoOptionMode10 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec-handle-resolution-change", 0);//处理分辨率变化
//max buffer size should be pre-read:默认为15*1024*1024
VideoOptionModel videoOptionMode11 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max-buffer-size", 0);//最大缓存数
VideoOptionModel videoOptionMode12 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "min-frames", 2);//默认最小帧数2
VideoOptionModel videoOptionMode13 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "max_cached_duration", 30);//最大缓存时长
//input buffer:don't limit the input buffer size (useful with realtime streams)
VideoOptionModel videoOptionMode14 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "infbuf", 1);//是否限制输入缓存数
VideoOptionModel videoOptionMode15 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "fflags", "nobuffer");
// VideoOptionModel videoOptionMode16 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");//tcp传输数据
VideoOptionModel videoOptionMode17 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzedmaxduration", 100);//分析码流时长:默认1024*1000
备注:这是Android配置,ios参数类似
@zhengchengbin610 感谢就不用了,大家相互学习而已
@xufuji456 感谢的回复,max_cached_duration 这个选项是需要自己去按照网络文章加进去吧? 交个朋友,这是我的QQ:471102531
max_cached_duration是自己加的,用来控制音视频缓存队列
我试了你给我的配置选项,但是还是有480ms的延时,不知什么了,我是局域网播放rtsp 流,请问有什么建议吗?
总延时=采集+编码(缓冲)+发送+传输+接收+解码(缓冲)+播放,你先确认下采集编码端有多少延时
@xufuji456 明白,我确认一下,不过我测试的流没有音频,然后我disable 掉了音频流的播放
@xufuji456 我用了一个其他的app 测试同一个流,延时在300ms左右,我的目标也就是300-350之间,但是我用ijkplayer的延时 一直保持在480ms 左右,感觉一直稳定在480ms,换了你的配置也是这样。对ijkplayer 还有什么修改优化的方法吗?
你换成硬解码试下
//0:代表关闭;1:代表开启
VideoOptionModel videoOptionMode08 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_PLAYER, "mediacodec", 1);//开启硬解
@xufuji456 是的,这个是否硬解码的选项 也有打开试过,基本没有什么变化,估计瓶颈延时不在解码部分,你是否可以给我修改的版本呢?
@zhengchengbin610 打开硬解后,可以降低 CPU 的使用率,可以让 CPU 做其他的事情,直播是因为码率一般不高,所以不明显,实际上是要好一些的
@Supecomer 你说的了解,只是针对目前延时一直在480ms的问题上,用硬解码不太明显,当然CPU肯定低了,对于整个APP性能是有提升的,关于延时问题你有什么建议吗
max_cached_duration是自己加的,用来控制音视频缓存队列
你好,我现在也是在局域网环境的推流,现在设置option后延迟在300ms左右,想进一步优化延迟,请问你添加max_cached_duration的逻辑能说下吗?非常感谢
判断音视频缓存队列时间戳是否大于max_cached_duration,如果大于,就丢视频帧,要注意的是整个GOP都需要丢,否则会花屏
你先把编译环境搭建好,建议在ubuntu环境编译。
具体修改可参考博客:https://www.jianshu.com/p/d6a5d8756eec
你先把编译环境搭建好,建议在ubuntu环境编译。
具体修改可参考博客:https://www.jianshu.com/p/d6a5d8756eec
已经处理好了,谢谢
我设置上面的参数后,在局域网中还是有2秒的延迟呢?
max_cached_duration是自己加的,用来控制音视频缓存队列
你好,我现在也是在局域网环境的推流,现在设置option后延迟在300ms左右,想进一步优化延迟,请问你添加max_cached_duration的逻辑能说下吗?非常感谢
您好,我设置上面的参数后还是有2秒的延迟呢,我就用了一个无线路由器,么有接网线测试的
1、你确认下推流端延时多少,用其他播放器拉流播放对比
2、确认下推流的码率、分辨率、帧率怎么样的
@xufuji456 关于基于ijkplayer低延时300ms以内优化方法,是否可以交流,有偿的,感谢
@zhengchengbin610 你那边直播的参数是怎么样的呢,分辨率、码率、帧率这些。
另外,这个300ms是在局域网测试的,外网环境具有不确定性
_No description provided._
你好 ,怎么看log 确认是延迟300-500ms
_No description provided._
你好 ,怎么看log 确认是延迟300-500ms
@cg19910712 打开秒表,然后拍照对比推流端和拉流端的时差
@xufuji456 大神你这个FFmpegAndroid里面的Onlive里面的so库 虽然能到达90ms 但是stop的时候没有发送teardown 来停止服务器发送rtsp
你先把编译环境搭建好,建议在ubuntu环境编译。
具体修改可参考博客:https://www.jianshu.com/p/d6a5d8756eec
您好,请问您编译的so库可以分享一下吗?
在开始播放器开始加载视频源的时候打开一个线程,用来监听时间变化,在setOnPreparedListener的onPrepared方法中,打印出准备了多长时间。在setOnInfoListener的onInfo方法中通知MEDIA_INFO_VIDEO_RENDERING_START时打印开始播放的时间。
------------------ 原始邮件 ------------------
发件人: "吃苹果的猫"notifications@github.com;
发送时间: 2019年7月22日(星期一) 中午11:38
收件人: "bilibili/ijkplayer"ijkplayer@noreply.github.com;
抄送: "724699262"l724699262@vip.qq.com;"Comment"comment@noreply.github.com;
主题: Re: [bilibili/ijkplayer] 请问下做RTSP直播,在局域网环境,1080p、30fps的视频流。现在通过设置相关option参数,延时在300-350ms。怎么做进一步优化,达到100ms左右延时呢 (#4267)
请问你们是怎么获取到延时时间的呢
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.
(Android平台) 请教下大家,网络波动的时候,或者RTSP服务器断开的时候,你们是如何捕捉到这个事件的?就是说没有一个错误回调的方法,我这边有设置 ijkMediaPlayer.setOnErrorListener(new IMediaPlayer.OnErrorListener() { 但是没有作用,什么打印都没有。希望有大神指点下,谢谢!
(Android平台) 请教下大家,网络波动的时候,或者RTSP服务器断开的时候,你们是如何捕捉到这个事件的?就是说没有一个错误回调的方法,我这边有设置 ijkMediaPlayer.setOnErrorListener(new IMediaPlayer.OnErrorListener() { 但是没有作用,什么打印都没有。希望有大神指点下,谢谢!
和Android平台应该没关系,ffmpeg拉流,本质离不开av_read_frame,RTSP-Server断开或者网络出错,av_read_frame会返回错误码,用av_err2str可以查出具体原因。
@xufuji456 大神你这个FFmpegAndroid里面的Onlive里面的so库 虽然能到达90ms 但是stop的时候没有发送teardown 来停止服务器发送rtsp
setup、teardown、play这些命令应该是推流端发送的,拉流端是接收命令进行处理
你先把编译环境搭建好,建议在ubuntu环境编译。
具体修改可参考博客:https://www.jianshu.com/p/d6a5d8756eec您好,请问您编译的so库可以分享一下吗?
@xufuji456 大神你这个FFmpegAndroid里面的Onlive里面的so库 虽然能到达90ms 但是stop的时候没有发送teardown 来停止服务器发送rtsp
setup、teardown、play这些命令应该是推流端发送的,拉流端是接收命令进行处理
退出拉流的时候,确实应该要发送 teardown 吧。 我用vlc拉rtsp然后退出的时候,vlc 是有发送 teardwon指令给到服务器端的,但是用这个就没有发送teardwon 指令
(Android平台) 请教下大家,网络波动的时候,或者RTSP服务器断开的时候,你们是如何捕捉到这个事件的?就是说没有一个错误回调的方法,我这边有设置 ijkMediaPlayer.setOnErrorListener(new IMediaPlayer.OnErrorListener() { 但是没有作用,什么打印都没有。希望有大神指点下,谢谢!
和Android平台应该没关系,ffmpeg拉流,本质离不开av_read_frame,RTSP-Server断开或者网络出错,av_read_frame会返回错误码,用av_err2str可以查出具体原因。
ijkplayer 有接口可以直接操作 av_read_frame 吗? av_err2str 这个在哪里可以查呢?
(Android平台) 请教下大家,网络波动的时候,或者RTSP服务器断开的时候,你们是如何捕捉到这个事件的?就是说没有一个错误回调的方法,我这边有设置 ijkMediaPlayer.setOnErrorListener(new IMediaPlayer.OnErrorListener() { 但是没有作用,什么打印都没有。希望有大神指点下,谢谢!
和Android平台应该没关系,ffmpeg拉流,本质离不开av_read_frame,RTSP-Server断开或者网络出错,av_read_frame会返回错误码,用av_err2str可以查出具体原因。
ijkplayer 有接口可以直接操作 av_read_frame 吗? av_err2str 这个在哪里可以查呢?
没直接操作av_read_frame的,这个在ff_ffplay.c读线程里面。
如果is->eof,在ffp_toggle_buffering是有实现通知的ffp_notify_msg2。
如果网络出错,也有匹配好几个错误码,下面的if(pb_error){..}
然后线程就被挂起等待,再次唤醒进入continue,回到循环开头,可能有加了暂停、abort之类的标志,然后退出循环了。
看了下,EOF好像返回的是BUFFERRING_END之类的标志,可能是在状态的监听里面。pb_error应该才回调到你说的OnErrorListener。这部分没仔细看。你可以在av_read_frame返回小于0的条件下加个
av_log(ffp, AV_LOG_ERROR, "av_read_frame error: %s\n", av_err2str(ret)); 重新编译看看在你的环境下,网络出错,断服务器返回什么错误,就比较容易追溯到回调的位置。
`
ret = av_read_frame(ic, pkt);
if (ret < 0) {
int pb_eof = 0;
int pb_error = 0;
if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) {
ffp_check_buffering_l(ffp);
pb_eof = 1;
// check error later
}
if (ic->pb && ic->pb->error) {
pb_eof = 1;
pb_error = ic->pb->error;
}
if (ret == AVERROR_EXIT) {
pb_eof = 1;
pb_error = AVERROR_EXIT;
}
if (pb_eof) {
if (is->video_stream >= 0)
packet_queue_put_nullpacket(&is->videoq, is->video_stream);
if (is->audio_stream >= 0)
packet_queue_put_nullpacket(&is->audioq, is->audio_stream);
if (is->subtitle_stream >= 0)
packet_queue_put_nullpacket(&is->subtitleq, is->subtitle_stream);
is->eof = 1;
}
if (pb_error) {
if (is->video_stream >= 0)
packet_queue_put_nullpacket(&is->videoq, is->video_stream);
if (is->audio_stream >= 0)
packet_queue_put_nullpacket(&is->audioq, is->audio_stream);
if (is->subtitle_stream >= 0)
packet_queue_put_nullpacket(&is->subtitleq, is->subtitle_stream);
is->eof = 1;
ffp->error = pb_error;
av_log(ffp, AV_LOG_ERROR, "av_read_frame error: %s\n", ffp_get_error_string(ffp->error));
// break;
} else {
ffp->error = 0;
}
if (is->eof) {
ffp_toggle_buffering(ffp, 0);
SDL_Delay(100);
}
SDL_LockMutex(wait_mutex);
SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10);
SDL_UnlockMutex(wait_mutex);
ffp_statistic_l(ffp);
continue;
} else {
is->eof = 0;
}
`
(Android平台) 请教下大家,网络波动的时候,或者RTSP服务器断开的时候,你们是如何捕捉到这个事件的?就是说没有一个错误回调的方法,我这边有设置 ijkMediaPlayer.setOnErrorListener(new IMediaPlayer.OnErrorListener() { 但是没有作用,什么打印都没有。希望有大神指点下,谢谢!
和Android平台应该没关系,ffmpeg拉流,本质离不开av_read_frame,RTSP-Server断开或者网络出错,av_read_frame会返回错误码,用av_err2str可以查出具体原因。
ijkplayer 有接口可以直接操作 av_read_frame 吗? av_err2str 这个在哪里可以查呢?
没直接操作av_read_frame的,这个在ff_ffplay.c读线程里面。
如果is->eof,在ffp_toggle_buffering是有实现通知的ffp_notify_msg2。
如果网络出错,也有匹配好几个错误码,下面的if(pb_error){..}
然后线程就被挂起等待,再次唤醒进入continue,回到循环开头,可能有加了暂停、abort之类的标志,然后退出循环了。
看了下,EOF好像返回的是BUFFERRING_END之类的标志,可能是在状态的监听里面。pb_error应该才回调到你说的OnErrorListener。这部分没仔细看。你可以在av_read_frame返回小于0的条件下加个
av_log(ffp, AV_LOG_ERROR, "av_read_frame error: %s\n", av_err2str(ret)); 重新编译看看在你的环境下,网络出错,断服务器返回什么错误,就比较容易追溯到回调的位置。`
ret = av_read_frame(ic, pkt);
if (ret < 0) {
int pb_eof = 0;
int pb_error = 0;
if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) {
ffp_check_buffering_l(ffp);
pb_eof = 1;
// check error later
}
if (ic->pb && ic->pb->error) {
pb_eof = 1;
pb_error = ic->pb->error;
}
if (ret == AVERROR_EXIT) {
pb_eof = 1;
pb_error = AVERROR_EXIT;
}if (pb_eof) { if (is->video_stream >= 0) packet_queue_put_nullpacket(&is->videoq, is->video_stream); if (is->audio_stream >= 0) packet_queue_put_nullpacket(&is->audioq, is->audio_stream); if (is->subtitle_stream >= 0) packet_queue_put_nullpacket(&is->subtitleq, is->subtitle_stream); is->eof = 1; } if (pb_error) { if (is->video_stream >= 0) packet_queue_put_nullpacket(&is->videoq, is->video_stream); if (is->audio_stream >= 0) packet_queue_put_nullpacket(&is->audioq, is->audio_stream); if (is->subtitle_stream >= 0) packet_queue_put_nullpacket(&is->subtitleq, is->subtitle_stream); is->eof = 1; ffp->error = pb_error; av_log(ffp, AV_LOG_ERROR, "av_read_frame error: %s\n", ffp_get_error_string(ffp->error)); // break; } else { ffp->error = 0; } if (is->eof) { ffp_toggle_buffering(ffp, 0); SDL_Delay(100); } SDL_LockMutex(wait_mutex); SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10); SDL_UnlockMutex(wait_mutex); ffp_statistic_l(ffp); continue; } else { is->eof = 0; }`
嗯,按照你说的加了打印,断开服务器之后,返回的错误是 end of file

这个是对应 ijkplayer 的哪个回调呢?
做到了130ms,还得继续优化。。。
做到了130ms,还得继续优化。。。
@xufuji456 能告知做到130ms的option的设置参数吗?
我在html5,最低做到了270ms。
就再下不去了。
楼请的130,是ijkplayer,不是H5的。
到130估计也很难下了。
我尝试使用rtsp局域网,最低到80ms。
但是些都不好在HTMl5上面使用。
最大时延是在: 播放器端; 流到了后要解码。这是软解的可能至少要50ms的时延了。
乐播投屏可以在1080p做到wifi 40ms延时,他们是如何实现的呢?(局域网)
乐播投屏可以在1080p做到wifi 40ms延时,他们是如何实现的呢?(局域网)
猜测并不是1080P,只是分辨率达到了1920*1080. 1080P是逐行扫描,直播或者低延时的高清,可能都比较困难。
码率不足,造成显示上面打折。
还有,你的40ms是如何测试的?RTSP Lan网络测试最快测到80ms。
如果 知道乐投是1080P,麻烦告知。
乐播投屏可以在1080p做到wifi 40ms延时,他们是如何实现的呢?(局域网)
猜测并不是1080P,只是分辨率达到了1920*1080. 1080P是逐行扫描,直播或者低延时的高清,可能都比较困难。
码率不足,造成显示上面打折。
还有,你的40ms是如何测试的?RTSP Lan网络测试最快测到80ms。如果 知道乐投是1080P,麻烦告知。
分辨率确实是1920x1080,延时利用的秒表,让投屏端显示秒表。然后把接收端和投屏端放在一起,用另一个设备拍照。上面显示的差值即为延迟。乐播投屏和接收端都可以在网上下到,很容易验证。
我现在想做一个基于rtsp的投屏,查了查目前的github,能跑通的就是libstreaming,但他是投的照相机,苦于codec不是很熟,不知道从何改起,把数据源变成屏幕
目前市面上产品以80ms延时为主,偶尔出现40ms,局域网传输,不考虑网络抖动和网络延时。
采用h265编解码,提高压缩率,降低传输延时,自定义传输层协议。
@xufuji456 请问怎么配置或者修改达到130ms?
如果不嫌多个库的话,可以使用live555 来连接rtsp流,,,github上可以找到一个live55helper,是把live555进行一次封装,很好用..使用liv555出来的数据直接就是h265或者265的裸流,给ffmpeg直接解码就行..这样在我的环境下(摄像头->H3516a编码->live555->ffmpeg软解->opengl渲染)效率解码综合下来能有180ms..我打印过日志从live555出来的数据到软解完4-6ms,主要延迟还是在摄像头编码板.pc端的,仅供参考
Most helpful comment
// VideoOptionModel videoOptionMode16 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "rtsp_transport", "tcp");//tcp传输数据
VideoOptionModel videoOptionMode17 = new VideoOptionModel(IjkMediaPlayer.OPT_CATEGORY_FORMAT, "analyzedmaxduration", 100);//分析码流时长:默认1024*1000
备注:这是Android配置,ios参数类似