【问题标题】:H264 WebRTC video streamed from ffmpeg through Janus is very choppy on playback从 ffmpeg 通过 Janus 流式传输的 H264 WebRTC 视频在播放时非常不稳定
【发布时间】:2019-11-09 07:39:42
【问题描述】:

尝试通过以下链流式传输视频:本地实例存储 (AWS) 上的 h264/mp​​4 文件->ffmpeg->rtp->同一实例上的 Janus->WebRTC 播放 (Chrome/mac)。即使没有任何资源似乎超载(所涉及的任何系统上的 CPU/内存/网络带宽),生成的视频也会断断续续。我也用 Coturn TURN 服务器,它也完全没有加载,带宽很充足。

尝试切换编解码器,但除了 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,但到目前为止尝试这样做没有成功。

【问题讨论】:

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


    【解决方案1】:

    ffmpeg 被优化用于输出块中的帧,而不是输出单个编码帧。多路复用器,在您的情况下是 rtp 多路复用器,通常在刷新到输出之前缓冲数据。所以 ffmpeg 没有针对需要或多或少逐帧输出的实时流媒体进行优化。然而,WebRTC 确实需要实时到达的帧,所以如果帧是成束发送的,它可能会丢弃“迟到的”帧,因此会出现断断续续的情况。

    不过,在 ffmpeg 中有一个选项,可以将 muxer 的缓冲区大小设置为 0,效果很好。它是:

    -max_delay 0

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

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

    【讨论】:

    • 不确定我是否完全理解它,但我按照我理解的方式尝试了它并没有帮助。如果你可以私下联系我,我可以付钱给你实际的解决方案。
    • fmpeg -re -stream_loop -1 -i ./short.mp4 -s 852x480 -c:v libx264 -profile:v baseline -b:v 4M -r 24 -g 60 -flags:v +global_header -bsf:v "dump_extra=freq=keyframe" -max_delay 0 -bf 0 -an -f rtp rtp://127.0.0.1:5004 还是很不稳定
    • 我已经修改了我的个人资料,以便您可以直接与我联系。谢谢。这越来越紧急,我仍然无法使其工作:(
    • 我已经调试了几天的 WebRTC 流,这终于解决了。天哪,我爱你!谢谢!
    【解决方案2】:

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

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

    感谢 Meetecho 的 Lorenzo Miniero 解决这个问题。

    【讨论】:

      猜你喜欢
      • 2020-08-08
      • 1970-01-01
      • 1970-01-01
      • 2012-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多