我们想在单屏上展示多达 60 个高清电视频道的直播,就像这个显示 12 个标清频道的旧视频一样。我们已经在功能强大的服务器上使用软件实现了这一点,但想研究硬件加速,想知道当前的高端 GPU 能做什么?
https://www.youtube.com/watch?v=Ig6MpUsXyiY
不幸的是,我一直无法弄清楚这种技术的名称,到目前为止,我的努力只找到了“将多个显示器合并到视频墙”的解决方案,这与我想要的正好相反。
那么,我应该寻找什么来了解特定显卡可以渲染多少个高清源,并且(截至目前)是否有一个好的选择?
答案1
考虑到没有特定的软件适合您的目的*,我将尝试从 FFmpeg 的角度回答这个问题。
* 有一些,但那些都是专业的,因此价格相对较高。通常,人们会使用(半)硬件解决方案来实现这样的事情,尽管我必须承认:我自己从来不需要超过 2*2 的网格。
我假设以下几点:
- 输入流的长宽比为 16:9并应保持原样(即不裁剪)
- Output-Stream 的宽高比也是 16:9
- 输入流和输出流均为全高清(1920x1080 像素)
- 硬件功能是无限的(意思是:我无法测试我的答案,因为我没有 60 个输入流和/或与您相同的硬件。)
分屏
如果您不想裁剪掉任何输入,并且输入和输出的长宽比相同,则可以使用 n*n 流的网格。由于 8*8=64 是适合所有输入的最小网格,因此我们将使用它。4 个网格空间不会被填满 - 您可以在中间或角落留出它们(我将使用后者)。
-filter_complex "
nullsrc=size=1920x1080[base];
[0:v]scale=w=in_w/8:h=in_h/8[0_1];
[1:v]scale=w=in_w/8:h=in_h/8[0_1];
[2:v]scale=w=in_w/8:h=in_h/8[0_2];
[3:v]scale=w=in_w/8:h=in_h/8[0_3];
<<AND SO ON>>
[59:v]scale=w=in_w/8:h=in_h/8[7_6];
[base][0_1]overlay=x=240:y=0[tmp0];
[tmp0][0_2]overlay=x=480:y=0[tmp1];
<<AND SO ON>>
[tmp9][1_2]overlay=x=480:y=135[tmp10];
<<AND SO ON>>
[tmp58][7_6]overlay=x=1440:y=945
"
scale
如果输入流的大小已经适合您的网格,则可以省略-part:如果可以的话,我建议这样做。
流(流入和流出)
应该是最简单的部分,尽管这是我真正不能说太多的部分。FFmpeg 的流媒体指南对此有一些想法:
在输入端:
# Using TCP:
ffmpeg -i tcp://host:port?listen
# Using RTSP:
ffmpeg -rtsp_flags listen rtsp://host:port/live.sdp?tcp
在输出端:
# For TCP:
ffmpeg -i INPUT -f mpegts tcp://host:port
# For UDP:
ffmpeg -i INPUT -f mpegts udp://host:port
# For RTSP (using TCP instead of UDP):
ffmpeg -i input -f rtsp -rtsp_transport tcp rtsp://host:port/live.sdp
FFmpeg 的文档链接至此网站 - 它包含从 RTMP 到 RTMP 的转码示例。
加速度、延迟
FFmpeg 的流媒体指南建议进行以下设置:
-c:v libx264 -tune zerolatency -preset ultrafast
这些似乎很合理,因为它们可能不会对您的延迟产生太大影响。如果您愿意,可以尝试其他编解码器(x265 也有一个零延迟选项)。如果任何输入流都有可能有一个自动流,这-an
将是一个好主意,因为它将省略所有音频,因此可以少担心一个编码器。
现在,如果您想采用 GPU 路线,如果不知道您拥有的 GPU 的具体型号,我无法告诉您太多信息。FFmpeg 的 HWAccelIntro-Wiki可能对你有帮助。我个人不会为此烦恼——我甚至无法让我的 GTX970 在两个输入流下表现良好(我猜是因为 GPGPU 不是为多任务处理而设计的,但这是没有根据的说法),而h264_nvenc
开启的速度比开启的速度-preset fast
要慢得多。即使它能正常工作,事情也会很快变得混乱:流会变得臃肿(与 x264 相比),阻塞伪影也很常见。libx264
-preset ultrafast
把所有这些加在一起
# Calling FFmpeg, getting inputs:
ffmpeg -i tcp://host:port?listen <<REPEAT 59 TIMES>>
# Create the splitscreen:
-filter_complex "<<TAKE THE FILTER FROM ABOVE>>"
# Encoding-options:
-an -c:v libx264 -tune zerolatency -preset ultrafast
# Output as stream:
-f mpegts tcp://host:port
当然,你必须填写空白部分并删除注释。
结论
这应该是 FFmpeg 解决您问题的方法。您必须尝试一下才能知道它是否有效,对此我深表歉意。但代码本身应该可以工作 - 如果硬件(尤其是网络带宽)没有阻碍您,这种方法应该可以在任何相对较新的处理器上正常工作。