使用GStreamer同步两个RTSP/RTP H264视频流的捕获

4

我有两个AXIS IP摄像头通过RTSP/RTP流传输H264流。两个摄像头都设置为与同一个NTP服务器同步,因此我认为两个摄像头将具有完全相同的时钟(可能相差几毫秒)。

在我的应用程序中,两个摄像头指向同一视图,并且需要处理相同时间的两个摄像头图像。因此,我想使用GStreamer同步图像捕获。

我尝试在不同的cmd提示符上分别调用两个管道,但视频相隔2-3秒 enter image description here

  1. gst-launch rtspsrc location=rtsp://192.168.16.136:554/live ! rtph264depay ! h264parse ! splitmuxsink max-size-time=100000000 location=cam1_video_%d.mp4
  2. gst-launch rtspsrc location=rtsp://192.168.16.186:554/live ! rtph264depay ! h264parse ! splitmuxsink max-size-time=100000000 location=cam2_video_%d.mp4

有人能提供一个gstreamer管道来同步两个H264流并将它们录制到不同的视频文件中吗?

谢谢! ARM

2个回答

2

我可以使用如下所示的gst-launch启动管道。与启动两个管道相比,它在捕获帧同步方面表现出良好的改进。大多数情况下,它们的差异在0-500毫秒之间。尽管如此,我仍然希望将它们同步到不到150毫秒的精度。

rtspsrc location=rtsp://192.168.16.136:554/axis-media/media.amp?videocodec=h264 \
    ! rtph264depay ! h264parse \
    ! splitmuxsink max-size-time=10000000000 location=axis/video_136_%d.mp4   \
rtspsrc location=rtsp://192.168.16.186:554/axis-media/media.amp?videocodec=h264 \
    ! rtph264depay ! h264parse \
    ! splitmuxsink max-size-time=10000000000 location=axis/video_186_%d.mp4

感谢有人能提供其他想法!
~Arm

1
嘿 @arm,你找到解决方案了吗? - Shivam Mangla
@ShivamMangla 你找到解决方案了吗?:) - jhagege
1
嘿@cyberjoac,我已经不再继续处理它了,我采用了一种解决方法,这对于我的目的来说已经足够了 - 我使用opencv从两个相机捕获最新帧并在处理旧帧时丢弃较新的帧,直到我准备好获取更新的帧。500毫秒的误差对于我的应用程序来说是可以接受的。 - Shivam Mangla

1
如果你将录制内容保存到不同的视频文件中,那么你不需要任何同步。因为这会完全将它们分开。每个RT(S)P流都包含不同的时间戳。如果你想以某种方式将它们对齐到同一时间(我是指真正的人类时间,比如“两个视频都应该从15:00开始”),那么你必须以某种方式配置它们(这只是一个想法)。
此外,你没有告诉我们rtp/rtsp流中包含什么(是MPEG ts还是纯IP等)。所以我会举例说明MPEG ts封装的rtp流。
我们将逐步进行:
假设这是一个摄像头,只是为了演示它可能是什么样子:
gst-launch-1.0 -v videotestsrc ! videoconvert ! x264enc ! mpegtsmux ! rtpmp2tpay ! udpsink host=127.0.0.1 port=8888

接收器需要使用 rtmp2tdepay(我们将元数据封装在 MPEG 容器中):
gst-launch-1.0 udpsrc port=8888 caps=application/x-rtp\,\ media\=\(string\)video\,\ encoding-name\=\(string\)MP2T ! rtpmp2tdepay ! decodebin ! videoconvert ! autovideosink

如果您使用相机进行测试,则autovideosink表示将弹出新窗口显示您的相机。
然后,您可以尝试将其存储在文件中。我们将使用mp4mux。因此,对于相同的相机输入,我们执行以下操作:
gst-launch-1.0 -e udpsrc port=8888 caps=application/x-rtp\,\ media\=\(string\)video\,\ encoding-name\=\(string\)MP2T ! rtpmp2tdepay ! tsdemux ! h264parse ! mp4mux ! filesink location=test.mp4

解释:我们不解码和重新编码(浪费处理能力),因此我将仅对MPEG TS流进行分离,而不是解码H264,然后将其解析为接受video/x-h264的mp4mux。
现在您可以为每个摄像机使用相同的管道...或者只需将所有元素复制粘贴到同一管道中...
现在,由于您没有提供任何 - 至少部分的 - 尝试去理解这个问题,这将成为您的家庭作业 :) 或者让自己更清楚地了解同步,因为我不理解它...
更新 根据您对问题的更新,此答案并不是很有用,但我将保留它作为参考。我不知道如何进行同步...
另一个建议..尝试查看udpsrc之后的时间戳..也许它们已经同步了..在这种情况下,您可以使用streamsynchronizer来同步两个流..或者可能是视频/音频混合器:
gst-launch-1.0 udpsrc -v port=8888 ! identity silent=false ! fakesink

这应该打印时间戳(PTS、DTS、持续时间…):
/GstPipeline:pipeline0/GstIdentity:identity0: last-message = chain   ******* (identity0:sink) (1328 bytes, dts: 0:00:02.707033598, pts:0:00:02.707033598, duration: none, offset: -1, offset_end: -1, flags: 00004000 tag-memory ) 0x7f57dc016400

比较每个流的PTS。也许您可以将两个udpsrc组合到一个管道中,然后在每个udpsrc之后放置identity(使用不同的name=something1),使它们同时开始接收。

希望对您有所帮助。


我知道的是,两者都是使用RTP/RTSP流传输H.264视频流的AXIS相机。我假设RTP数据包将具有一些时间戳,表示相机准备包含H.264编码视频帧的RTP数据包的时间。 - arm
在我的应用程序中,两个摄像头都指向同一场景,并且需要处理两个摄像头的相同ts帧。请查看此图像:Valid XHTML 我知道这些AXIS摄像头通过RTP / RTSP流传输H.264。我在2个cmd提示符上尝试了以下管道,并记录的视频相隔2-3秒。 1. gst-launch rtspsrc location = rtsp://192.168.16.136:554/live!rtph264depay!h264parse!splitmuxsink max-size-time = 100000000 location = v0_%d.mp4 2. gst-launch rtspsrc location = rtsp://192.168.16.186:554/live!rtph264depay!h264parse!splitmuxsink max-size-time = 100000000 location = v1_%d.mp4 - arm
@arm请将此内容作为更新写入您的问题中...好吧,我不知道...也许没有同步的方法...也许如果相机连接到NTP服务器...或者我不知道...同时启动两个相机...如果流具有相同的时间戳对应于相同的实时(这很重要),也许有一些方法可以同步此操作...你知道,一个是相同的流时间戳,另一个是它如何与“现实世界时间”相关联。 - nayana
谢谢otopolsky!我已经更新了问题,希望有人知道如何做到这一点。 - arm

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