首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >从ffmpeg到Janus的H264 WebRTC视频在播放上非常不稳定。

从ffmpeg到Janus的H264 WebRTC视频在播放上非常不稳定。
EN

Stack Overflow用户
提问于 2019-06-27 01:48:56
回答 2查看 12.6K关注 0票数 10

试图通过以下链传输视频:本地实例存储(AWS)上的H 264/MP4文件->ffmpeg->rtp->同一实例上的Janus->WebRTC回放(Chrome/mac)。即使没有任何资源看起来过载(CPU/内存/网络带宽在所涉及的任何系统上),但产生的视频还是不稳定的。我还使用了一个转身服务器,它也没有加载,带宽也很丰富。

尝试过转换编解码器,除了工作时还在工作的vp8 (有点不稳定,但非常罕见和可接受)之外,它并没有帮助,导致了如此高的CPU消耗,这实际上是不可接受的。

ffmpeg -re -stream_loop -1 -i ./short.mp4 -s 426x240 -c:v libx264 -profile:v baseline -b:v 1M -r 24 -g 60 -an -f rtp rtp://127.0.0.1:5004

由此产生的可持续发展方案是:

代码语言:javascript
运行
AI代码解释
复制
o=- 0 0 IN IP4 127.0.0.1
s=No Name
c=IN IP4 127.0.0.1
t=0 0
a=tool:libavformat 58.20.100
m=video 5004 RTP/AVP 96
b=AS:1000
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1

流是用Janus API设置为

代码语言:javascript
运行
AI代码解释
复制
            "janus" : "message",
            "transaction" : 'Transaction',
        "body": {
                "request" : "create",
                "type" : "rtp",
                "id" : newId,
                "name": streamId+newId,
                "audio": false,
                "video": true,
                "description" : streamId+newId,
                "videoport" : 5000+newId*4,
                "videopt" : 96,
                "videortpmap": "H264/90000",
                "secret" : "adminpwd"
            }
        }

尝试了各种生物武器的选择,一点帮助都没有。将-g (GOP大小)改变为较低的值可以缩短持续时间,但更频繁。在-g 3或4时,它是可以接受的,但可容忍质量的比特率,可以预见,会变得疯狂。

预期结果:视频播放没有波澜。

我的理论是,它可以是以下之一:

  • 无论是ffmpeg以缓冲区太小的方式提供数据,有时Janus需要在它还没有准备好的时候发送下一个数据包,饥饿的缓冲区并导致中断-那么也许有一种方法可以使ffmpeg编码成某种短时间(半秒左右)?调节流动的缓冲器)。多么?
  • 或者H264在UDP上的工作太差了,我无能为力。然后,我切换到TCP,但到目前为止,尝试这样做是不成功的。
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-30 01:20:01

这个解决方案在显而易见的方面证明是美丽的。ffmpeg将流以RTP的形式发送给Janus,Janus将其进一步发送给观众,显然是SRTP,因为这是WebRTC,而且始终是加密的。作为加密开销,它向每个数据包添加了一组字节。在某些情况下,它意味着数据包经过MTU并丢弃--每次发生时,视频中都有一个明显的猛击。

简单地添加?pkt_size=1300到输出ffmpeg的RTP就消除了这个问题。

感谢Meetecho公司的洛伦佐·米利耶罗( Lorenzo Miniero )弄明白了这一点。

票数 13
EN

Stack Overflow用户

发布于 2019-06-27 06:21:56

ffmpeg优化用于输出块中的帧,而不是输出单个编码帧。muxer (在您的例子中是rtp muxer )通常在刷新到输出之前缓冲数据。因此,ffmpeg并不是针对需要或多或少逐帧输出的实时流进行优化的。然而,WebRTC确实需要实时到达的帧,所以如果帧是成批发送的,那么它可能会丢弃“迟”帧,从而导致不稳定。

但是,在ffmpeg中有一个选项,将muxer的缓冲区大小设置为0,这很好。它是:

-max_delay 0

另外,对于WebRTC,您希望禁用b帧并将SPS-PPS附加到每个关键帧:

-bf 0 +global_header -bsf:v "dump_extra=freq=keyframe"

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56788387

复制
相关文章
enableEventValidation 回发或回调参数无效 的解决办法[通俗易懂]
回发或回调参数无效。在配置中使用 <pages enableEventValidation=”true”/> 或在页面中使用 <%@ Page EnableEventValidation=”true” %> 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。
全栈程序员站长
2022/09/15
2.2K0
回发或回调参数无效。在配置中使用 <pages enableEventValidation=”true”/> 或在页面中使用 <%@ Page EnableEventValidation=”true”
回发或回调参数无效。在配置中使用 <pages enableEventValidation=”true”/> 或在页面中使用 <%@ Page EnableEventValidation=”true” %> 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。
全栈程序员站长
2022/09/15
1.7K0
asp.net中回发或回调参数无效。在配置中使用 <pages enableEventValidation=”… 问题解决[通俗易懂]
回发或回调参数无效。在配置中使用 <pages enableEventValidation=”…
全栈程序员站长
2022/09/15
2K0
System.ArgumentException: 回发或回调参数无效。在配置中使用 < pages enableEventValidation=”true”/>
大家好,又见面了,我是你们的朋友全栈君。关于在同一个页面中使用Gridview控件的时候发现气updaeting事件无法被服务器所响应,看来它的错误报警然后查询了部分资料现在将整理的解决方法总结如下:点击update 事件无法响应原因出在回发或回调参数无效。在配置中使用 <pages enableEventValidation=”true”/> 或在页面中使用 <%@ Page EnableEventValidation=”true” %> 启用了事件验证。出于安全目的,此功能验证回发或回 调事件的参数是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。 说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。 异常详细信息: System.ArgumentException: 回发或回调参数无效。在配置中使用 < pages enableEventValidation=”true”/> 或在页面中使用 <% @ Page EnableEventValidation=”true” %> 启用了事件验证。出于安全目的,此功能验证回发或回调事件的参数 是否来源于最初呈现这些事件的服务器控件。如果数据有效并且是预期的,则使用 ClientScriptManager.RegisterForEventValidation 方法来注册回发或回调数据以进行验证。
全栈程序员站长
2022/09/15
1.5K0
回调参数详解
字面上的理解,回调函数就是传递一个参数化的函数,就是将这个函数作为一个参数传到另一个主函数里面,当那一个主函数执行完之后,再执行传进去的作为参数的函数。走这个过程的参数化的函数 就叫做回调函数。换个说法也就是被作为参数传递到另一个函数(主函数)的那个函数就叫做 回调函数
九霄道长
2021/03/02
2.7K0
什么是回调地狱?如何解决回调地狱问题_地狱回调
这个问题呢,需要从Node.js的API说起,这里就会有人问了?博主你不是说回调地狱的问题吗,怎么说到API了,别急,看博主一步一步的解释给你听:
全栈程序员站长
2022/11/15
3.2K0
scrapy回调函数传递参数
scrapy.Request 的callback传参的两种方式 1.使用 lambda方式传递参数 def parse(self, response): for sel in response.xpath('//li[@class="clearfix"]/div[@class="list_con"]'): item=DmozItem() item['href']=sel.xpath('h2/a/@href').extract()[0] yield sc
用户1558882
2018/04/03
1.2K0
回调
回调简单而言:在一个类(A)的方法(a)中调用另一个类(B)的方法(b),当方法(b)执行完之后就调用类(A)中的方法(c),这就是回调的过程,是不是很简单?简单分析可以知道一个类(A)持有另一个类(B)的引用,方法(c)就叫做回调函数,画成UML图就如下所示:
晚上没宵夜
2020/03/10
2.6K0
​29 - 回调函数和回调地狱
原文地址:https://dev.to/bhagatparwinder/callback-functions-callback-hell-79n
前端黑板报
2022/12/01
4.6K0
支付宝回调问题
跟我项目交接的那个人也不能说是坑,只能说他当初在订单方面也没有理解到位罢了 不过那哥们着实挺牛逼的  支付宝回调有些坑,参数api  回调参数支付价格明明是total_amount,实际却不是这个。还
陈灬大灬海
2018/09/12
1K0
支付宝回调问题
回调函数的工作机制 回调函数的用途
在一般人的眼中,对回调函数并不是十分的了解。实际上,在现在的互联网技术上这种函数有着十分重要的地位。这种函数不仅仅可以使得编程的效率大大提升,还是实现一些特殊功能的必须组成部分。那么什么是回调函数?这样的函数究竟有什么作用?下面就来为大家介绍一下。
用户8739405
2021/07/09
6.9K0
用Async解决回调问题
第一次接触编程时,我们就知道了一块代码是从头执行到尾的。 这就是所谓的同步编程:每个操作完成之后,后面的才会继续。 对于不花计算机太多时间的操作,比如数字相加、操作字符串、或变量赋值等等,这种执行过程没什么问题。
前端达人
2018/10/18
1.3K0
用Async解决回调问题
Ajax 的回调
页面上有两个button,以上js代码为button添加click事件。会输出什么样的结果呢?
用户7293182
2022/01/17
4.4K0
Angularjs的回调
$q.reject() 方法是在你捕捉异常之后,又要把这个异常在回调链中传下去时使用:
星回
2018/08/02
1.7K0
七、回调
修改PspNotifyEnableMask为00000009,创建和退出进程时就不会触发回调
zhang_derek
2022/09/29
1.7K0
关于回调
爱学习的前端歌谣
2023/10/18
2090
关于回调
回调函数
什么是回调函数,上面的问题说的是不是很空洞,不是太形象,下面是知乎上的一位网友给的答案:
LiosWong
2018/10/29
3.9K0
回调函数
  有点类似模板的功能,可以使用函数指针作为参数,当调用函数时,使用void *进行传递参数,细致比较时,再用int *之类的进行强制转换。回调函数,其实就是在参数中定义函数,调用时,回到主函数去调用这个函数。仔细用法如下: 首先定义查找函数 Node * search_list(Node *node, void const *value, int (*compare)(void const *,void const *)){ while(node!=NULL){ if(compar
用户1154259
2018/01/17
3.3K0
回调函数
回调地狱
一个函数,作为参数的形式传给另一个函数调用,那么这个这个函数就叫做回调函数。 当然回调函数很常见,如下
用户4793865
2023/01/12
1.4K0
函数指针做函数参数(回调函数)
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> //回调函数 //第一个参数是一个万能指针,用来接收用户输入的数据------因为我们不知道用户会输入什么样的数据类型,因此用万能指针 //第二个参数是一个函数指针-------将data数据放入函数中进行操作 void PrintText(void* data,void(*myPrint)(void* )) { myPrint(data); } //做回调函数的第二个参数 void myPrint(voi
大忽悠爱学习
2021/03/04
6290

相似问题

无效回发或回调参数

13

无效回发或回调参数

69

无效回发或回调参数

28

“无效回发或回调参数”

11

无效的回发或回调参数

11
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档