GStreamer:多个 RTMP 源,画中画在 Jetson Nano 上混合,然后与 Belabox 的 RTMP 管道一起使用

GStreamer: Multiple RTMP sources, Picture in Picture to mux on a Jetson Nano, then to be used with RTMP pipeline with Belabox

我的目标是在画中画组合中拥有 (2) 个 RTMP 源,将其编码为 h265 mpegts,仅从 cam1 rtmp 源混合音频,然后将其发送到 appsink;

这就是我的想法,但我可能错了:

[已确认] 工作(在设备上)画中画管道:

使用的设备:Camlink 4k (Sony Action Cam FDR-x3000) 和 Logitech c920

v4l2src device=/dev/video0 ! nvvidconv ! queue ! comp.sink_0
v4l2src device=/dev/video1 ! video/x-raw, width=800, height=448, framerate=30/1, format=YUY2 !
videobox left=-4 right=-4 top=-4 bottom=-4 ! nvvidconv ! queue ! comp.sink_1
 
nvcompositor name=comp sink_0::width=1920 sink_0::height=1080 sink_1::width=640 sink_1::height=360 sink_1::xpos=1266 sink_1::ypos=706 !
queue ! identity name=v_delay signal-handoffs=TRUE ! nvvidconv interpolation-method=5 !
nvv4l2h265enc control-rate=1 qp-range="28,50:0,38:0,50" iframeinterval=60 preset-level=4 maxperf-enable=true EnableTwopassCBR=true insert-sps-pps=true name=venc_bps !
h265parse config-interval=-1 ! queue max-size-time=10000000000 max-size-buffers=1000 max-size-bytes=41943040 !
mpegtsmux name=mux ! appsink name=appsink
 
alsasrc device=hw:2 ! identity name=a_delay signal-handoffs=TRUE ! volume volume=1.0 !
audioconvert ! opusenc bitrate=320000 ! opusparse ! queue ! mux.

[已确认] 工作 RTMP 管道:

使用的设备:Samsung s10e 使用 Larix Broadcaster 通过 RTMP 流式传输 x264

rtmpsrc location=rtmp://127.0.0.1/live/cam1 ! 
flvdemux name=demux 

demux.video ! identity name=v_delay signal-handoffs=TRUE ! h264parse ! nvv4l2decoder ! nvvidconv ! 
textoverlay text='' valignment=top halignment=right font-desc="Sans, 10" name=overlay ! queue ! 
videorate ! video/x-raw,framerate=60/1 !
nvvidconv interpolation-method=5 ! 
nvv4l2h265enc control-rate=1 qp-range="28,50:0,38:0,50" iframeinterval=60 preset-level=4 maxperf-enable=true EnableTwopassCBR=true insert-sps-pps=true name=venc_bps ! 
h265parse config-interval=-1 ! queue max-size-time=10000000000 max-size-buffers=1000 max-size-bytes=41943040 ! mux. 

demux.audio ! aacparse ! avdec_aac ! identity name=a_delay signal-handoffs=TRUE ! volume volume=1.0 ! 
audioconvert ! opusenc bitrate=128000 ! opusparse ! queue max-size-time=10000000000 max-size-buffers=1000 ! mux. 

mpegtsmux name=mux ! 
appsink name=appsink

我所有的尝试都失败了;

这些是我的尝试:

尝试 1:

rtmpsrc name=cam1 location=rtmp://127.0.0.1/live/cam1 ! flvdemux name=demux0 ! queue ! demux0.video ! identity name=v_delay signal-handoffs=TRUE ! h264parse ! nvv4l2decoder ! nvvidconv ! queue ! comp.sink_0 
rtmpsrc name=cam2 location=rtmp://127.0.0.1/live/cam2 ! flvdemux name=demux1 ! queue ! demux1.video ! identity signal-handoffs=TRUE ! h264parse ! nvv4l2decoder ! nvvidconv ! queue ! comp.sink_1 

nvcompositor name=comp sink_0::xpos=0 sink_0::ypos=0 sink_0::width=1920 sink_0::height=1080 sink_1::xpos=0 sink_1::ypos=240 sink_1::width=320 sink_1::height=240 ! 
videorate ! video/x-raw,framerate=60/1 ! 
nvvidconv interpolation-method=5 ! 

nvv4l2h265enc control-rate=1 qp-range="28,50:0,38:0,50" iframeinterval=60 preset-level=4 maxperf-enable=true EnableTwopassCBR=true insert-sps-pps=true name=venc_bps ! 
h265parse config-interval=-1 ! queue max-size-time=10000000000 max-size-buffers=1000 max-size-bytes=41943040 ! mux. 

demux0. ! queue ! audio/mpeg ! decodebin ! audioconvert ! audioresample ! autoaudiosink 

mpegtsmux name=mux ! 
appsink name=appsink

尝试 2:

rtmpsrc name=cam1 location=rtmp://127.0.0.1/live/cam1 ! 
flvdemux name=demux0
demux0.video ! identity name=v_delay0 signal-handoffs=TRUE ! h264parse ! nvv4l2decoder ! nvvidconv ! queue ! comp.sink_0

rtmpsrc name=cam2 location=rtmp://127.0.0.1/live/cam2 ! 
flvdemux name=demux1
demux1.video ! identity name=v_delay1 signal-handoffs=TRUE ! h264parse ! nvv4l2decoder ! videobox left=-4 right=-4 top=-4 bottom=-4 ! nvvidconv ! queue ! comp.sink_1

nvcompositor name=comp sink_0::width=1920 sink_0::height=1080 sink_1::width=640 sink_1::height=360 sink_1::xpos=10 sink_1::ypos=10 ! 
queue ! identity name=v_delay0 signal-handoffs=TRUE ! nvvidconv interpolation-method=5 ! 
queue ! identity name=v_delay1 signal-handoffs=TRUE ! nvvidconv interpolation-method=5 ! 
nvv4l2h265enc control-rate=1 qp-range="28,50:0,38:0,50" iframeinterval=60 preset-level=4 maxperf-enable=true EnableTwopassCBR=true insert-sps-pps=true name=venc_bps ! 
h265parse config-interval=-1 ! queue max-size-time=10000000000 max-size-buffers=1000 max-size-bytes=41943040 ! 
mpegtsmux name=mux ! appsink name=appsink

demux0.audio ! aacparse ! avdec_aac ! identity name=a_delay signal-handoffs=TRUE ! volume volume=1.0 ! 
audioconvert ! opusenc bitrate=320000 ! opusparse ! queue max-size-time=10000000000 max-size-buffers=1000 ! mux. 

当前的 GStreamer 配置:


更新 1:我尝试了@SeB 的解决方案,但没有成功:

以下是显示该过程的一些屏幕截图:

端口 4953 上的 videotestsrc:

端口 4954 上的 videotestsrc:

完整测试管道:


更新 2:解决方案:

通过利用@SeB 的回答并稍微修改一下,我能够获取两个 rtmpsrc 并将它们组合在一起,然后将其发送到不同密钥下的同一 rtmp 服务器,并使用随附的 rtmp 管道belacoder.

在我的测试过程中,这仅在您遵循 belabox 教程而不是预制图像时有效。

这是我使用的管道:

gst-launch-1.0 -v \
 rtmpsrc location=rtmp://127.0.0.1/live/cam1 ! flvdemux name=demux0 \
   demux0. ! queue ! video/x-h264 ! h264parse ! nvv4l2decoder ! nvvidconv ! 'video/x-raw(memory:NVMM),format=RGBA,width=1920,height=1080,pixel-aspect-ratio=1/1' ! identity ! queue ! comp.sink_0 \
   demux0. ! queue ! audio/mpeg ! mux. \
 rtmpsrc location=rtmp://127.0.0.1/live/cam2 ! flvdemux name=demux1 \
   demux1. ! queue ! video/x-h264 ! h264parse ! nvv4l2decoder ! nvvidconv ! video/x-raw,format=YUY2,width=800,height=448,pixel-aspect-ratio=1/1 ! videobox left=-4 right=-4 top=-4 bottom=-4 ! nvvidconv ! 'video/x-raw(memory:NVMM),format=RGBA,pixel-aspect-ratio=1/1' ! identity ! queue ! comp.sink_1 \
 nvcompositor name=comp sink_0::xpos=0 sink_0::ypos=0 sink_0::width=1920 sink_0::height=1080 sink_0::zorder=1 sink_1::xpos=0 sink_1::ypos=0 sink_1::width=808,sink_1::height=456 sink_1::zorder=2 ! 'video/x-raw(memory:NVMM),format=RGBA,pixel-aspect-ratio=1/1' ! nvvidconv ! 'video/x-raw(memory:NVMM),format=NV12' \
   ! nvv4l2h264enc control-rate=1 qp-range="28,50:0,38:0,50" iframeinterval=60 preset-level=4 maxperf-enable=true EnableTwopassCBR=true insert-sps-pps=true name=venc_bps ! h264parse config-interval=-1 ! queue max-size-time=10000000000 max-size-buffers=1000 max-size-bytes=41943040 ! mux. \
 flvmux name=mux ! rtmpsink location='location=rtmp://127.0.0.1/live/cam3 live=1'

然后我刚刚编辑了 belacoder 自带的 rtmp 管道从 /cam3 中提取。

这里是通过 SRTLA 使用 belaUI + belacoder 在 OBS Studio 中工作:

这是我在belaUI/belacoder中使用的管道:

rtmpsrc location=rtmp://127.0.0.1/live/cam3 ! 
flvdemux name=demux 

demux.video ! identity name=v_delay signal-handoffs=TRUE ! h264parse ! nvv4l2decoder ! nvvidconv ! 
textoverlay text='' valignment=top halignment=right font-desc="Sans, 10" name=overlay ! queue ! 
nvvidconv interpolation-method=5 ! 
nvv4l2h265enc control-rate=1 qp-range="28,50:0,38:0,50" iframeinterval=60 preset-level=4 maxperf-enable=true EnableTwopassCBR=true insert-sps-pps=true name=venc_bps ! 
h265parse config-interval=-1 ! queue max-size-time=10000000000 max-size-buffers=1000 max-size-bytes=41943040 ! mux. 

demux.audio ! aacparse ! avdec_aac ! identity name=a_delay signal-handoffs=TRUE ! volume volume=1.0 ! 
audioconvert ! voaacenc bitrate=128000 ! aacparse ! queue max-size-time=10000000000 max-size-buffers=1000 ! mux. 

mpegtsmux name=mux ! 
appsink name=appsink

我的设置对于我的 belabox (Jetson-nano) 上 运行 的 rtmp 服务器是唯一的,所以请记住这一点。

这是 belaUI 中选择的最终管道:

一旦你选择了它,你所要做的就是点击开始,你可以使用连接到 belabox 的所有互联网连接:

请记住,这真的很挑剔,如果您的某个 rtmps 源崩溃了,它会破坏整个管道,所以当所有 rtmp 源都在本地环境中并且您有 gts-launch 管道时,这最有效运行 作为一项服务。

如果您想了解有关开源 DIY 项目 belabox 的更多信息或想与我联系,请查看我的个人资料链接@https://whosebug.com/users/3331416/b3ck

刚刚尝试模拟您的源(我没有 RTMP 服务器,但应该直接尝试适应):

# Cam 1 1920x1080@30fps with audio
gst-launch-1.0 -e videotestsrc ! video/x-raw,format=NV12,width=320,height=240,framerate=30/1 ! nvvidconv ! 'video/x-raw(memory:NVMM),format=NV12,width=1920,height=1080,pixel-aspect-ratio=1/1' ! nvv4l2h264enc ! h264parse ! queue ! flvmux name=mux    audiotestsrc ! audioconvert ! voaacenc ! queue ! mux.   mux. ! tcpserversink port=4953
# Cam2 with 800x448@30fps
gst-launch-1.0 -e videotestsrc pattern=ball ! video/x-raw,format=NV12,width=320,height=240,framerate=30/1 ! nvvidconv ! 'video/x-raw(memory:NVMM),format=NV12,width=800,height=448,pixel-aspect-ratio=1/1' ! nvv4l2h264enc ! h264parse ! queue ! flvmux ! tcpserversink port=4954

然后,这应该输出视频和音频:

gst-launch-1.0 -v \
 tcpclientsrc port=4953 ! flvdemux name=demux0 ! h264parse ! nvv4l2decoder ! nvvidconv ! 'video/x-raw(memory:NVMM),format=RGBA,width=1920,height=1080,pixel-aspect-ratio=1/1' ! identity ! queue ! comp.sink_0 \
 tcpclientsrc port=4954 ! flvdemux name=demux1 ! h264parse ! nvv4l2decoder ! nvvidconv ! video/x-raw,format=YUY2,width=800,height=448,pixel-aspect-ratio=1/1 !  nvvidconv ! 'video/x-raw(memory:NVMM),format=RGBA,pixel-aspect-ratio=1/1' ! identity ! queue ! comp.sink_1 \
 nvcompositor name=comp sink_0::xpos=0 sink_0::ypos=0 sink_0::width=1920 sink_0::height=1080 sink_0::zorder=1 sink_1::xpos=0 sink_1::ypos=0 sink_1::width=800,sink_1::height=448 sink_1::zorder=2 ! 'video/x-raw(memory:NVMM),format=RGBA,pixel-aspect-ratio=1/1' ! nvvidconv ! autovideosink \
 demux0. ! queue ! audio/mpeg ! decodebin ! audioconvert ! audioresample ! autoaudiosink

如果没问题,您可以对合成视频进行 H265 编码(请注意,此处添加视频框,第二帧现在的大小为 808x456)并转发 mpeg 音频:

gst-launch-1.0 -v \
 tcpclientsrc port=4953 ! flvdemux name=demux0 \
   demux0. ! queue ! video/x-h264 ! h264parse ! nvv4l2decoder ! nvvidconv ! 'video/x-raw(memory:NVMM),format=RGBA,width=1920,height=1080,pixel-aspect-ratio=1/1' ! identity ! queue ! comp.sink_0 \
   demux0. ! queue ! audio/mpeg ! tsmux. \
 tcpclientsrc port=4954 ! flvdemux name=demux1 \
   demux1. ! queue ! video/x-h264 ! h264parse ! nvv4l2decoder ! nvvidconv ! video/x-raw,format=YUY2,width=800,height=448,pixel-aspect-ratio=1/1 ! videobox left=-4 right=-4 top=-4 bottom=-4 ! nvvidconv ! 'video/x-raw(memory:NVMM),format=RGBA,pixel-aspect-ratio=1/1' ! identity ! queue ! comp.sink_1 \
 nvcompositor name=comp sink_0::xpos=0 sink_0::ypos=0 sink_0::width=1920 sink_0::height=1080 sink_0::zorder=1 sink_1::xpos=0 sink_1::ypos=0 sink_1::width=808,sink_1::height=456 sink_1::zorder=2 ! 'video/x-raw(memory:NVMM),format=RGBA,pixel-aspect-ratio=1/1' ! nvvidconv ! 'video/x-raw(memory:NVMM),format=NV12' \
   ! nvv4l2h265enc control-rate=1 qp-range="28,50:0,38:0,50" iframeinterval=60 preset-level=4 maxperf-enable=true EnableTwopassCBR=true insert-sps-pps=true name=venc_bps ! h265parse config-interval=-1 ! queue max-size-time=10000000000 max-size-buffers=1000 max-size-bytes=41943040 ! tsmux. \
 mpegtsmux name=tsmux ! appsink name=appsink