我正在使用 ffmpeg 从四输入捕获卡读取,并输出 3 个同时的流:
- HDMI1+2 覆盖 -> rtsp://localhost:5545/hud1
- HDMI1+3 覆盖 -> rtsp://localhost:5545/hud2
- 仅 HDMI1 -> rtsp://localhost:5545/vis
这个输入1+2命令花了一些时间,但效果很好。
SOURCE1=(-f decklink -i 'DeckLink Quad HDMI Recorder (1)')
SOURCE2=(-f decklink -i 'DeckLink Quad HDMI Recorder (2)')
# Scale inputs, and transpose black pixels to alpha on the overlay
FILTER=(-filter_complex "
[0:v]scale=960:540[base];
[1:v]scale=540:540,colorkey=black:0.1:0.1[overlay];
[base][overlay]overlay=(W-w)/2:(H-h)/2
")
ENCODING_OPTIONS=(
-c:v libx264 # x264 codec
-preset fast # Balances latency, quality, bandwidth
-crf 18 # 18 = visually lossless. That's good enough
-an # Strip out audio
)
STREAMING_OPTIONS=(
-b:v 5000k # Target 5000 kbps bitrate
-maxrate 5500k # Should be a little higher than target to allow catchup
-bufsize 4000k # Bigger buffer is better for stability but reduces latency
-r30 # Don't need 60fps,
-tune zerolatency
)
SINK=(-f rtsp rtsp://localhost:5545/hud1)
ffmpeg \
"${SOURCE1[@]}" \
"${SOURCE2[@]}" \
"${FILTER[@]}" \
"${ENCODING_OPTIONS[@]}" \
"${STREAMING_OPTIONS[@]}" \
"${SINK[@]}"
问题:
驱动程序不允许两个 ffmpeg 实例监听同一个频道。如果我运行 HDMI1+2,然后尝试仅传输 HDMI1,我会得到:
Error opening input: Input/output error
Error opening input file DeckLink Quad HDMI Recorder (1)
尝试 1:环回 RTSP:
如果我先运行“仅输入 1”,然后使用运行和 ,它确实可以工作。但是,在我的配置下,每次 RTSP 跳转都会增加约 2 秒的延迟。这意味着输入 1 比覆盖延迟约 2 秒。SOURCE1=(-i rtsp://localhost/base)
Input 1+2
Input 1+3
尝试 2:/dev/shm
我尝试将“仅输入 1”输出到SINK=(-f shm /dev/shm/base)
,希望从 Input1+2 和 Input1+3 流中读取该内容。我希望将其保留在本地可以消除延迟。
Requested output format 'shm' is not known.
尝试 3:unix://
SINK=(-f mpegts -listen 1 unix:/run/user/1000/base.socket)
我尝试通过设置来使用unix 域套接字SOURCE1=(-i unix:/run/user/1000/base.socket)
,但最终得到:
Unable to choose an output format for 'unix:/run/user/1000/base.socket'; use a standard extension for the filename or specify the format manually.
所以我尝试使用不同的扩展:
SINK=(-f mpegts -listen 1 unix:/run/user/1000/base.mkv)
但是当我尝试用 Input1+2 读取它时,我得到:
Could not find codec parameters for stream 1 ...: unspecified frame size
...
Output file does not contain any stream
尝试#4:一体化:
我觉得这可能是解决方案,但还不够。我尝试使用split=3
过滤器和-map
功能在一个 ffmpeg 实例中完成所有操作,但当基础图像上有覆盖层时,其分辨率要差得多。我不确定我的流媒体选项是每个流的还是在所有三个流之间共享的。
VISUAL_SOURCE=(-f decklink -i 'DeckLink Quad HDMI Recorder (1)' )
HUD1_SOURCE=( -f decklink -i 'DeckLink Quad HDMI Recorder (2)' )
HUD2_SOURCE=( -f decklink -i 'DeckLink Quad HDMI Recorder (3)' )
FILTER_PAIR=(-filter_complex "
[0:v]scale=960:540,split=3[vis0][vis1][vis2];
[1:v]scale=540:540,colorkey=black:0.1:0.1[hud1];
[2:v]scale=540:540,colorkey=black:0.1:0.1[hud2];
[vis1][hud1]overlay=(W-w)/2:(H-h)/2[hud1overlay];
[vis2][hud2]overlay=(W-w)/2:(H-h)/2[hud2overlay]
")
ENCODING_OPTIONS=(
-c:v libx264
-preset fast
-crf 18
-an
)
STREAMING_OPTIONS=(
-b:v 5000k
-maxrate 5500k
-bufsize 4000k
-r 30
-tune zerolatency
-xerror
)
SINK1=(-map '[vis0]' -f rtsp rtsp://localhost:5545/vis)
SINK2=(-map '[hud1overlay]' -f rtsp rtsp://localhost:5545/hud1)
SINK3=(-map '[hud2overlay]' -f rtsp rtsp://localhost:5545/hud2)
ffmpeg \
"${VISUAL_SOURCE[@]}" \
"${HUD1_SOURCE[@]}" \
"${HUD2_SOURCE[@]}" \
"${FILTER_PAIR[@]}" \
"${ENCODING_OPTIONS[@]}" \
"${STREAMING_OPTIONS[@]}" \
"${SINK1[@]}" \
"${SINK2[@]}" \
"${SINK3[@]}"
第一个输出rtsp://.../base
(原始 SOURCE1)看起来很棒(类似于我原来只有 2 个输入和一个输出的尝试),但是rtsp://.../hud1
(rtsp://.../hud2
SOURCE 2/3 除以 SOURCE 1)的分辨率很差。