如何使用无延迟的方式流式传输实时视频(使用ffplay、mplayer),以及在ffplay中可以使用哪种封装格式?

19

我一直在测试使用不同的播放器同时播放多个直播流,因为我想获得最低的延迟值。我尝试了gstreamer播放器(gst-launch-0.01)、mplayer、totem和ffmpeg播放器(ffplay)。我使用了不同的配置值来获得它们每一个的最低延迟,例如:


ffplay -fflags nobuffer 
mplayer -benchmark

我正在使用UDP协议进行流媒体传输,而且我发现使用ffplay比mplayer或gst-launch获得了更好的数值。老实说,我不知道我需要进行哪种配置才能在gstreamer上实现更低的延迟。

现在,我需要两件事:

  1. 我想知道是否有更好的建议可以实现低于100毫秒的低延迟直播流。我现在的延迟高于100毫秒,对我来说效率并不高。

  2. 由于我目前正在使用ffplay,因为它是目前为止最好的选择。我想要一个简单的GUI,带有播放和录制按钮以及3个屏幕从不同的视频服务器进行流媒体传输,我只是不知道使用什么样的包装器(应该非常快速)!


1
我的流媒体中没有声音,已经被禁用了。无论如何,我在哪里可以购买这样的硬件? - user573014
好的,假设我对得到的值感到满意...你有什么想法可以在ffplay上面做一个简单的GUI,而不会造成更多的延迟吗? - user573014
我不会这样做。我会使用VLC,因为它的GUI已经高度可配置了。 - Brad
1
@Brad VLC 流媒体非常慢,延迟非常高...这就是为什么我不想使用它的原因。 - user573014
1
https://trac.ffmpeg.org/wiki/StreamingGuide 上有一个关于延迟的部分。 - rogerdpack
显示剩余4条评论
2个回答

16

对于需要非常低延迟的流媒体方案,您可以尝试NTSC。理想情况下,其延迟可以低至63微秒。

如果需要数字流媒体且预算为40ms,则可以参考rsaxvc在120hz处给出的答案,以获得接近NTSC级别的质量。如果需要通过无线电进行流媒体传输,则这是我见过的最好的低延迟选项,经过了很好的思考,并且分辨率将随着硬件能力的提高而扩展。

如果您指的是数字流媒体,并且希望通过wifi实现1080p的压缩比较好,那么如果要在今天的普通硬件上实现低于100ms的延迟,就会遇到困难,因为为了使压缩算法具有良好的压缩比,它需要许多上下文信息。例如,Mpeg 1使用12个帧组成一个ipbbpbbpbbpb GOP(图片组),其中i是“intra”帧,实际上是一张jpeg静态图像,p是一帧预测帧,它编码了i和p帧之间的某些运动,b帧编码了某些修复预测错误的地方。总之,即使以每秒60帧的速度捕获数据,12个帧仍需要200ms,因此需要250ms才能捕获数据,然后需要一些时间对其进行编码,然后传输,解码,缓冲音频以使声卡在CPU发送新块到DMA内存区域时不会丢失数据,并且同时需要排队发送2-3帧视频到视频显示器,以防止数字显示器上出现撕裂。因此,实际上至少需要15帧或250毫秒的延迟,加上传输引起的延迟。NTSC没有这样的延迟,因为它是模拟传输,唯一的“压缩”是两个巧妙的技巧:交织,在每次传输中仅传输一半每一帧的行,即在一帧上是偶数行,在下一帧上是奇数行,然后第二个技巧是通过使用3个黑白像素和其相位判别来确定显示的颜色,从而对颜色空间进行压缩,因此颜色信号以亮度(luma)信号的1/3的带宽进行传输。很酷吧?我想您也可以说音频也有一种“压缩”,即可以使用自动增益控制使20dB的模拟音频信号看起来提供近60dB的体验,因为在节目与商业广告之间的2-3秒寂静期间,AGC会在商业广告中将音量调高,使我们的耳朵爆发。后来,当我们获得了更高保真度的音频电路时,商业广告实际上比节目播放的音量要大,但这只是他们以前的方式,以使广告商提供与旧电视相同的影响力。

这段回忆之旅由怀旧(tm)品牌带给您。购买怀旧牌卫生香皂!;-)

这是我在Ubuntu 18.04上使用默认的ffmpegmpv达到的最佳效果。这需要第三代英特尔Core处理器或更高版本

ffmpeg -f x11grab -s 1920x1080 -framerate 60 -i :0.0 \
  -vaapi_device /dev/dri/renderD128 \
  -vf 'format=nv12,hwupload,scale_vaapi=w=1920:h=1080' \
  -c:v h264_vaapi -qp:v 26 -bf 0 -tune zerolatency -f mpegts \
  udp://$HOST_IP:12345

然后在媒体盒上:

mpv --no-cache --untimed --no-demuxer-thread --video-sync=audio \
  --vd-lavc-threads=1 udp://$HOST_IP:12345 
这可以在大约3Mbps的情况下实现1080p@60hz的延迟约为250毫秒,适用于通过wifi流媒体观看节目。 mpv可以调整音频和视频同步(Ctrl +-),对于流式桌面鼠标/键盘互动以进行媒体控制是可以容忍的,但是对于实时游戏来说无法使用(参见NVidia Shield,Google Stadia进行远程游戏)。
另外一件事:LCD/OLED/Plasma电视和一些LCD显示器具有帧插值功能,可以通过去隔行或通过SmoothVision(“Soap Opera Effect”)来实现。这种处理会增加输入延迟。您可以通常在显示器设置中关闭它,或通过连接到以“PC”或“Console”标记的输入端口来关闭它。一些显示器有更改输入的方法。在这种情况下,选择“PC”或“Console”可能会降低输入延迟,但是由于额外的处理被关闭可能会注意到颜色条纹、闪烁等问题。
CRT显示器基本上没有输入延迟。 但是,您将承受致电离辐射的风险。自己取舍吧。

为了实现更低的延迟,跳过B帧是相当常见的。新系统跳过I和P帧,而是使用混合的I+P格式,其中有一列I块随时间移动。 - rsaxvc
没错,但我说的是“如果你想要任何形式的高效压缩”,抛弃B帧和P帧基本上会将其转换成MJPEG流。此外,我试图描绘出所有导致延迟的因素,其中大多数是不可避免的......我忘记还提到了显示器本身的输入延迟,这也可能是OP高度乐观的“<100ms”延迟预算中相当重要的一部分。VNC可以在100毫秒以下管理,但那不是“视频流”。 - Wil
Mplayer播放一个UDP管道的帧内刷新帧,轻松击败WiFi上的100毫秒。输入延迟20毫秒或更少 60毫秒用于压缩,传输和解压缩 输出延迟20毫秒或更少 - rsaxvc
完成。我最初不想发布它,因为它非常专业化。 - rsaxvc
哇,非常感谢这个,它正在帮助我接近我的目标(考虑模拟器的游戏流)。我们的帧缓冲非常小,因此带宽实际上不是问题。(最多只有640x480)这是我的当前配置文件: http://dpaste.com/0Y3T6M2和当前结果 https://streamable.com/cftfv还没有达到目标,但更接近了。 我仍然在处理播放器方面的问题,但我希望我能做到。 - Radius
显示剩余3条评论

15

传统媒体播放器如VLC、FFmpeg和在某种程度上的MPlayer存在的问题是它们会尝试以一致的帧速率播放,这需要一些缓冲,这会影响延迟目标。另一种选择是尽可能快地呈现传入的视频,不关心其他任何东西。

@genpfault和我制定了一种自定义UDP协议,旨在用于飞行遥控车和四轴飞行器。该协议以低延迟为目标,但牺牲了几乎所有其他因素(分辨率、比特率、数据包速率、压缩效率)。在较小的分辨率下,我们将其运行在115200波特率的UART和XBEE上,但是在这些限制下的视频并没有像我们希望的那样有用。今天,我正在测试320x240配置,运行在笔记本电脑上(Intel i5-2540M),因为我已经没有原始设置。

您需要计划好您的延迟预算,以下是我花费预算的地方:

Acquisition - 我们选择了125FPS的PS3 Eye摄像头。因此,我们的延迟最多只有8毫秒左右。应避免使用“更智能”的摄像头,在设备上进行压缩(无论是h264还是MJPEG)。此外,如果您的摄像头具有任何自动曝光时间控制功能,则需要禁用它以锁定最快的帧速率,或提供充足的照明(今天,我的内置网络摄像头仅以8 FPS运行,因为自动曝光)。
Conversion - 如果可能,请让摄像头以您可以直接压缩的格式发出帧(通常是YUV格式,Eye本地支持)。然后您可以跳过此步骤,但我在这里花费了0.1mS。
Encoding - 我们使用了一个特别调整的H.264编码器。它需要约2.5mS,并且不需要缓冲未来的帧,但代价是压缩比。
Transport - 我们使用WiFi上的UDP,当没有其他无线电干扰时,延迟小于5mS。
Decoding - 这基本上受接收器CPU的限制。编码器可以通过发送可多线程解码的工作来帮助。这通常比编码更快。今天大约需要1.5mS。
Conversion - 您的解码器可能会为您执行此步骤,但通常编码器/解码器使用YUV,而显示器使用RGB,因此必须在它们之间进行转换。在我的笔记本电脑上需要0.1mS。
Display - 没有VSYNC,60 FPS的显示器延迟高达约17mS,加上一些LCD延迟,可能是6ms?这实际上取决于显示器,而我不确定这台笔记本电脑使用哪种面板。
The total comes to: 40.2mS.
编码: 当时,X264是我们能找到的最好的H264-AnnexB编码器。我们必须控制比特率、片段最大大小、vbv-bufsize、vbv-maxrate。从“superfast”和“zerolatency”的默认值开始,这将禁用B帧。 此外,帧内刷新是必须的!有效地允许将正常的“I”帧分割并与以下P帧混合。如果没有这个功能,你会在比特率需求中有“气泡”,这些“气泡”会暂时堵塞你的传输,增加延迟。
编码-传输规划: 编码器被调整为生成UDP大小的H264 NALU。这样,当一个UDP包丢失时,整个H264 NALU就会丢失,我们不必重新同步,解码器只是一种...打嗝...并继续进行一些图形损坏。
最终结果320x240

enter image description here

我用手机对着摄像头对准我的笔记本电脑进行测量,但速度比我能够可靠地测量的速度要快得多。压缩比为320x240x2B = 150kB/frame,压缩后每帧仅留下3kB左右。


你的面板输入延迟预算非常乐观……虽然不是不可能,但很少有人能够体验到低于9毫秒的延迟,通常更高,甚至高达数百毫秒。但我会调整我的答案 :-) - Wil
1
@Wil,你能给我发一个“几百毫秒”面板的例子吗?我认为大多数面板不会进行任何缓冲(或者最多只有一个用于重新调整大小的帧),因此会受到帧速率的限制。 - rsaxvc
3
带有SmoothVision的电视是一个很好的例子,将其连接24FPS的输入信号,它会使用3帧的缓冲来插值输出60FPS(或更高)。这就导致仅从插值引擎本身产生了125毫秒的输入延迟。大多数电视默认开启了SmoothVision(肥皂剧效果)。许多人正在使用电视作为显示器。最近(过去三年),对游戏玩家的认识逐渐提高。电视制造商已经开始添加低延迟的“游戏”模式(ALLM),甚至有些还支持FreeSync以获得<8ms的输入延迟。 - Wil
你可以通过使用光栅来测量输入延迟,而不是在相同字符单元格上重叠文本,这样会丢失面板灰到灰响应时间、相机曝光时间和滚动快门效应的数据,从而提高检测精度。输出一个光栅行,每2毫秒有1个白色像素后面跟着2个黑色像素。在320x240的分辨率下,你可以获得单行200毫秒的分辨率。同时流动态视频,以显示网络瓶颈效应。 - Wil
1
这是一个面板响应时间列表: https://displaylag.com/display-database/ 如果将<60hz的输入信号输入到启用了插值的设备中,或者输入包含连续相同帧的60hz信号(例如游戏低于60fps,以24fps播放的电影,锁定在30fps的控制台模拟器等),响应时间可能会比此列表中列出的更差。 - Wil
显示剩余2条评论

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