从ffmpeg通过Janus流式传输的H264 WebRTC视频在播放时非常不稳定

时间:2019-06-27 09:48:56

标签: video-streaming webrtc h.264 janus-gateway

尝试通过以下链流传输视频:本地实例存储(AWS)上的h264 / mp4文件-> ffmpeg-> rtp->同一实例上的Janus-> WebRTC播放(Chrome / mac)。即使所有资源似乎都没有过载(所涉及的任何系统上的CPU /内存/网络带宽),结果视频也很不稳定。我还使用了Coturn TURN服务器,它也没有完全加载并且带宽充足。

尝试过切换编解码器,除了vp8不能工作之外,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

产生的SDP是:

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将流设置为

            "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"
            }
        }

尝试了bw的各种选项,完全没有帮助。将-g(GOP大小)更改为较低的值可以使断续时间更短,但更频繁。在-g 3或4时可以接受,但是可以预见的可忍受质量的比特率变得疯狂。

预期结果:视频播放时没有断断续续。

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

  • 这两种ffmpeg都以缓冲区太小的方式提供数据,因此有时Janus需要在尚未准备就绪时发送下一个数据包,使缓冲区饿死并导致中断-因此也许有一种方法可以使ffmpeg编码为某种短的(半秒左右的缓冲来调节流量)。怎么样?

  • 或者H264在UDP上无法正常工作,我无能为力。然后我必须切换到TCP,但到目前为止,尝试执行此操作均未成功。

2 个答案:

答案 0 :(得分:1)

事实证明,该解决方案很漂亮。 ffmpeg将流作为RTP发送给Janus,Janus将其进一步发送给查看者,显然是SRTP,因为它是WebRTC,并且始终是加密的。这给每个数据包增加了一堆字节作为加密开销。在某些情况下,这意味着数据包经过MTU并被丢弃-每次发生时,视频中都会出现明显的跳动。

简单地添加?pkt_size = 1300以输出ffmpeg的RTP URL即可解决问题。

感谢Meetecho的Lorenzo Miniero弄清楚了这一点。

答案 1 :(得分:0)

ffmpeg已优化,用于以块的形式输出帧,而不是用于输出单独的编码帧。复用器(在您的情况下为rtp复用器)通常在刷新后缓冲数据以输出。因此,ffmpeg并未针对需要或多或少逐帧输出的实时流进行优化。但是,WebRTC实际上确实需要实时到达的帧,因此,如果成束发送帧,则可能会丢弃“迟到”的帧,从而造成断断续续。

但是,ffmpeg中有一个选项,可以将多路复用器的缓冲区大小设置为0,效果很好。它是:

-max_delay 0

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

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