如何使用ffmpeg实现最小化直播延迟

59

我有一个问题。我想要使用ffmpeg从我的网络摄像头进行直播流。

  1. 我启动了ffserver,它可以正常工作。
  2. 在另一个终端中,我使用以下命令启动ffmpeg进行流媒体传输,并且它也可以正常工作:

    sudo ffmpeg -re -f video4linux2 -i /dev/video0 -fflags nobuffer -an http://localhost:8090/feed1.ffm
    
  3. 在我的配置文件中,我有这个流:

  4. <Stream test.webm>
    Feed feed1.ffm
    Format webm
     NoAudio
     VideoCodec libvpx
     VideoSize 720x576
     VideoFrameRate 25
     # Video settings
        VideoCodec libvpx
        VideoSize 720x576           # Video resolution
        VideoFrameRate 25           # Video FPS
        AVOptionVideo flags +global_header  # Parameters passed to encoder 
                                        # (same as ffmpeg command-line parameters)
        AVOptionVideo cpu-used 0
        AVOptionVideo qmin 10
        AVOptionVideo qmax 42
        #AVOptionVideo quality good
        PreRoll 5
         StartSendOnKey
        VideoBitRate 400            # Video bitrate
     </Stream>
    
  5. 我使用以下命令启动流:

    ffplay http://192.168.1.2:8090/test.webm 它可以工作,但是我有4秒的延迟,我希望尽量减少这种延迟,因为这对我的应用程序很重要。 谢谢。


3
你可以尝试减小probesize的值:ffplay -probesize 500000 http://192.168.1.2:8090/test.webm(将其设置为500KB,也可以尝试其他值,如果我没记错的话默认值是5MB)。 - pogorskiy
好的,谢谢。现在我必须在移动浏览器中观看流媒体,所以我不能使用ffplay。我需要一些建议来优化配置文件。 - Pasquale C.
2
阅读http://ffmpeg.org/sample.html,我可以想象你可以尝试使用VideoBufferSize或减少GOP(它会增加带宽使用)。 - Antonio Bardazzi
1
你找到解决方案了吗? - F Andrei
5个回答

74

我找到了三个命令,帮助我减少直播流的延迟。第一个命令非常基础和直接,第二个命令结合了其他选项,可能在每个环境中的工作方式不同,而最后一个命令是我在文档中发现的hacky版本,虽然一开始很有用,但目前第一个选项更稳定且适合我的需求。

1. 使用基本命令-fflags nobuffer

此格式标志减少了初始输入流分析期间缓冲引入的延迟。此命令将显着减少延迟,并不会引入音频故障。

ffplay -fflags nobuffer -rtsp_transport tcp rtsp://<host>:<port>

2. 高级选项 -flags low_delay 和其他选项。

我们可以将之前的-fflags nobuffer格式标志与其他通用选项和高级选项结合使用,以获得更详细的命令:

  • -flags low_delay 这个编解码器通用标志将强制低延迟。
  • -framedrop:如果视频不同步,则丢弃视频帧。如果主时钟未设置为视频,则默认启用。使用此选项可为所有主时钟源启用帧丢弃。
  • -strict experimental,最后-strict指定遵循标准的严格程度,experimental选项允许非标准化的实验性内容、实验性(未完成/正在进行中/未经充分测试)解码器和编码器。此选项是可选的,请记住,实验性解码器可能会带来安全风险,请勿将其用于解码不受信任的输入。
ffplay -fflags nobuffer -flags low_delay -framedrop \
-strict experimental -rtsp_transport tcp rtsp://<host>:<port>

这个命令可能会引入一些音频故障,但很少发生。

另外,您可以尝试添加以下内容:

  • -avioflags direct 以减少缓冲,并且
  • -fflags discardcorrupt 以丢弃损坏的数据包,但我认为这是非常激进的方法。 这可能会破坏音视频同步
ffplay -fflags nobuffer -fflags discardcorrupt -flags low_delay \ 
-framedrop -avioflags direct -rtsp_transport tcp rtsp://<host>:<port>

3. 一种hacky选项(在旧文档中找到)

这是一种基于将-probesize-analyzeduration设置为较低值的调试解决方案,以帮助您的流更快地启动。

  • -probesize 32设置要探测的字节数(即分析以获取流信息的数据大小)。较高的值将使在流中分散的更多信息能够被检测到,但会增加延迟。必须是不小于32的整数。默认值为5000000。
  • analyzeduration 0指定要分析的微秒数以探测输入。较高的值将使检测到的信息更准确,但会增加延迟。默认值为5000000微秒(5秒)。
  • -sync ext将主时钟设置为外部源,以尝试保持实时性。默认为音频。主时钟用于控制音视频同步。这意味着此选项将音视频同步设置为一种类型(即type=audio/video/ext)。
ffplay -probesize 32 -analyzeduration 0 -sync ext -rtsp_transport tcp rtsp://<host>:<port>

该命令有时可能会引入一些音频问题。

-rtsp_transport 可以根据您的流设置为 udptcp。在这个例子中,我使用的是 tcp


1
所有这些对我的测试都没有任何影响。使用SDL预览与ffmpeg(而不是ffplay)是减少延迟的唯一选择(但缺乏声音是一个明显的缺点)。 - b005t3r
1
将analyzeduration和probesize从默认值减小到适当的数值对我很有帮助。可以将流开始时间缩短2-3秒。 - D T
我不建议在直播中使用 nobuffer 标志。实际上,它似乎会在帧丢失时导致故障;导致视频要么停顿几秒钟,要么重复某些片段 - 这种行为可以通过 -vsync 选项进行控制。此外,这样的直播 VOD 充满了损坏的帧,并且必须重新编码。在我的情况下,删除 nobuffer 标志解决了问题。 - Patryk Cieszkowski
1
@PatrykCieszkowski 记住这是 ffplay 的解决方案,而不是 ffmpeg 的。主要想法是在播放流时减少延迟。如果您想要存储或以低延迟进行转码,可能 ffmpeg -re 可以帮助,但是每个方案都有其优缺点。 - Teocci

21

FFMpeg的流媒体指南中有一个特定的部分介绍如何降低延迟。我还没有尝试他们所有的建议。 http://ffmpeg.org/trac/ffmpeg/wiki/StreamingGuide#Latency

他们特别注意了ffplay引入的延迟:

默认情况下,ffplay会引入一小段延迟,使用mplayer进行延迟测试(或使用-benchmark)时,也很方便使用-nocache。另外,使用SDL输出也被认为可以最小化延迟来查看帧: ffmpeg ... -f sdl -


7
谢谢,来自链接的 ffplay -probesize 32 -sync ext INPUT 命令对我有用! - user3473830
你实现了什么延迟?我需要超过100毫秒的流媒体延迟。这可能吗? - F Andrei
我没有测量最终的延迟,但在现场通过声音隔间进行监视时,它看起来非常接近实时,对我来说已经足够好了。 - Glen Blanchard

7
尝试将AVFormatContextflags设置为AVFMT_FLAG_NOBUFFER | AVFMT_FLAG_FLUSH_PACKETS
AVFormatContext *ctx;
...
ctx->flags = AVFMT_FLAG_NOBUFFER | AVFMT_FLAG_FLUSH_PACKETS;

尝试将解码器线程设置为1,似乎使用更多的线程会导致更多的延迟。

AVCodecContext *ctx;
...
ctx->thread_count = 1;

6
考虑使用过滤器选项-vf setpts=0。这将使所有帧尽快显示,而不会增加帧速率的延迟。如果流落后,这将使其能够赶上,因为我发现如果移动或调整ffplay窗口,它会落后。但是,如果您的视频数据以不一致的速率接收,则可能会使视频看起来不连贯。

2
我最终使用了以下命令:ffplay -flags low_delay -vf setpts=0 udp://127.0.0.1:10000。添加 -vf setpts=0 可以将延迟减少 6 帧。其他解决方案在我的情况下都不起作用。谢谢! - Rotem
设置-vf setpts=0是唯一能够在我播放USB Dshow摄像头时消除延迟的方法。我认为这是因为摄像头标记帧时间戳的速度比我的计算机时钟慢,所以ffplay最终会延迟播放,直到由于缓存已满而不得不丢弃帧。 - Ely

3

对于我来说,通过传递“-tune zerolatency”来解决延迟问题。

ffmpeg -f rawvideo -i /dev/video0 -preset slow -tune zerolatency -pix_fmt yuv420p -c:v libx264 -f rawvideo /tmp/pipe.h264

将运动矢量的质量降低了一些,但是对我来说延迟更加重要,因此......

(注意:保留HTML标签,不需要解释)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接