简体   繁体   English

使用gstreamer将rtsp流保存到avi文件中

[英]Save rtsp stream into avi file with gstreamer

I have a video server which gives me a video & audio streams over rtsp. 我有一台视频服务器,可以通过rtsp为我提供视频和音频流。 I can see it using gstreamer tool gst-launch with command: 我可以使用带有命令的gstreamer工具gst-launch看到它:

 gst-launch-1.0 uridecodebin uri=rtsp://path/to/source ! autovideosink 

Now I need to store that video stream into file for subsequent playback in any popular video player (VLC, Windows Media Player and so on). 现在,我需要将该视频流存储到文件中,以便随后在任何流行的视频播放器(VLC,Windows Media Player等)中播放。

I tried simply replace autovideosink with filesink location=file.avi and add -e option like recommended in that answer . 我试着简单地将autovideosink替换为filesink location=file.avi并添加-e选项,如该答案中所建议。 File created but I think it's no in correct video format (VLC can't play it). 文件已创建,但我认为不是正确的视频格式(VLC无法播放)。

Also I tried command from recently referenced answer: 我也尝试从最近引用的答案命令:

 gst-launch-1.0 -e rtspsrc location=rtsp://path/to/source ! decodebin ! x264enc ! mp4mux ! filesink location=file.avi 

It gives me error: 它给我错误:

 ERROR: from element /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc0: Internal data flow error. Additional debug info: gstbasesrc.c(2865): gst_base_src_loop (): /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc0: streaming task paused, reason not-linked (-1) 

The reason is (as I think) x264enc ! mp4mux 原因是(我认为) x264enc ! mp4mux x264enc ! mp4mux is for H.264 codec, but my device works only in MPEG4 part2 mode (MP4V-ES, ie H.263). x264enc ! mp4mux适用于H.264编解码器,但我的设备仅在MPEG4 part2模式(MP4V-ES,即H.263)下工作。 So I need to replace some elements in pipeline to satisfy abilities of my device . 因此,我需要替换管道中的某些元素来满足设备的功能。 But by looking in gstreamer plugins list I can't found any suitable for MP4V-ES (H.263). 但是通过查看gstreamer插件列表,我找不到适合MP4V-ES(H.263)的任何文件。

And now my question is: how to modify gst-launch command to save video from my slightly old device into file to further playing? 现在我的问题是:如何修改gst-launch命令以将视频从稍旧的设备保存到文件中以进一步播放?

Full log for command with verbosity: 详细的命令完整日志:

gst-launch-1.0 -e -v rtspsrc location=rtsp://192.168.101.44/moxa-cgi/multicaststream_ch1_stream1 ! decodebin ! avenc_mpeg4 ! mp4mux ! filesink location=file.mp4

 Setting pipeline to PAUSED ... Pipeline is live and does not need PREROLL ... Progress: (open) Opening Stream Progress: (connect) Connecting to rtsp://192.168.101.44/moxa-cgi/multicaststream_ch1_stream1 Progress: (open) Retrieving server options Progress: (open) Retrieving media info Progress: (request) SETUP stream 0 /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager: latency = 2000 /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager: ntp-sync = false /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager: use-pipeline-clock = false /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager: drop-on-latency = false /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager: buffer-mode = Slave receiver to sender clock /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc0: timeout = 5000000000 (gst-launch-1.0:9068): GStreamer-WARNING **: gstpad.c:4555:store_sticky_event:<udpsrc1:src> Sticky event misordering, got 'caps' before 'stream-start' /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc1.GstPad:src: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc1.GstPad:src: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc1: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSink:udpsink0: ttl = 128 Progress: (request) SETUP stream 1 /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc2: timeout = 5000000000 /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc3.GstPad:src: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc3: caps = application/x-rtcp (gst-launch-1.0:9068): GStreamer-WARNING **: gstpad.c:4555:store_sticky_event:<udpsrc3:src> Sticky event misordering, got 'caps' before 'stream-start' /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc3.GstPad:src: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager.GstGhostPad:recv_rtcp_sink_1.GstProxyPad:proxypad5: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager/GstRtpSession:rtpsession1.GstPad:sync_src: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager/GstRtpSsrcDemux:rtpssrcdemux1.GstPad:rtcp_sink: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager/GstRtpSession:rtpsession1.GstPad:recv_rtcp_sink: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager.GstGhostPad:recv_rtcp_sink_1: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSink:udpsink2: ttl = 128 Progress: (open) Opened Stream Setting pipeline to PLAYING ... New clock: GstSystemClock Progress: (request) Sending PLAY request Progress: (request) Sending PLAY request Progress: (request) Sent PLAY request /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc0: timeout = 0 /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc2: timeout = 0 /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager/GstRtpSession:rtpsession0.GstPad:send_rtcp_src: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager.GstGhostPad:send_rtcp_src_0: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSink:udpsink1.GstPad:sink: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager.GstGhostPad:send_rtcp_src_0.GstProxyPad:proxypad3: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager/GstRtpSession:rtpsession1.GstPad:send_rtcp_src: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager.GstGhostPad:send_rtcp_src_1: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSink:udpsink3.GstPad:sink: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager.GstGhostPad:send_rtcp_src_1.GstProxyPad:proxypad6: caps = application/x-rtcp /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager.GstGhostPad:recv_rtp_src_1_109102090_0: caps = application/x-rtp, media=(string)audio, payload=(int)0, clock-rate=(int)8000, encoding-name=(string)PCMU, encoding-params=(string)1, a-tool=(string)"MOXA\\ 4CH\\ Streamming\\ Server\\ V1.0", a-type=(string)broadcast, x-qt-text-nam=(string)"4CH\\ Streaming", x-qt-text-inf=(string)/dev/at2042, clock-base=(uint)2318609, seqnum-base=(uint)26256, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1 /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0.GstGhostPad:recv_rtp_src_1_109102090_0: caps = application/x-rtp, media=(string)audio, payload=(int)0, clock-rate=(int)8000, encoding-name=(string)PCMU, encoding-params=(string)1, a-tool=(string)"MOXA\\ 4CH\\ Streamming\\ Server\\ V1.0", a-type=(string)broadcast, x-qt-text-nam=(string)"4CH\\ Streaming", x-qt-text-inf=(string)/dev/at2042, clock-base=(uint)2318609, seqnum-base=(uint)26256, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1 /GstPipeline:pipeline0/GstDecodeBin:decodebin0.GstGhostPad:sink.GstProxyPad:proxypad0: caps = application/x-rtp, media=(string)audio, payload=(int)0, clock-rate=(int)8000, encoding-name=(string)PCMU, encoding-params=(string)1, a-tool=(string)"MOXA\\ 4CH\\ Streamming\\ Server\\ V1.0", a-type=(string)broadcast, x-qt-text-nam=(string)"4CH\\ Streaming", x-qt-text-inf=(string)/dev/at2042, clock-base=(uint)2318609, seqnum-base=(uint)26256, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1 /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind.GstPad:src: caps = application/x-rtp, media=(string)audio, payload=(int)0, clock-rate=(int)8000, encoding-name=(string)PCMU, encoding-params=(string)1, a-tool=(string)"MOXA\\ 4CH\\ Streamming\\ Server\\ V1.0", a-type=(string)broadcast, x-qt-text-nam=(string)"4CH\\ Streaming", x-qt-text-inf=(string)/dev/at2042, clock-base=(uint)2318609, seqnum-base=(uint)26256, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1 /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstTypeFindElement:typefind.GstPad:sink: caps = application/x-rtp, media=(string)audio, payload=(int)0, clock-rate=(int)8000, encoding-name=(string)PCMU, encoding-params=(string)1, a-tool=(string)"MOXA\\ 4CH\\ Streamming\\ Server\\ V1.0", a-type=(string)broadcast, x-qt-text-nam=(string)"4CH\\ Streaming", x-qt-text-inf=(string)/dev/at2042, clock-base=(uint)2318609, seqnum-base=(uint)26256, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1 /GstPipeline:pipeline0/GstDecodeBin:decodebin0.GstGhostPad:sink: caps = application/x-rtp, media=(string)audio, payload=(int)0, clock-rate=(int)8000, encoding-name=(string)PCMU, encoding-params=(string)1, a-tool=(string)"MOXA\\ 4CH\\ Streamming\\ Server\\ V1.0", a-type=(string)broadcast, x-qt-text-nam=(string)"4CH\\ Streaming", x-qt-text-inf=(string)/dev/at2042, clock-base=(uint)2318609, seqnum-base=(uint)26256, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1 /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0.GstGhostPad:recv_rtp_src_1_109102090_0.GstProxyPad:proxypad8: caps = application/x-rtp, media=(string)audio, payload=(int)0, clock-rate=(int)8000, encoding-name=(string)PCMU, encoding-params=(string)1, a-tool=(string)"MOXA\\ 4CH\\ Streamming\\ Server\\ V1.0", a-type=(string)broadcast, x-qt-text-nam=(string)"4CH\\ Streaming", x-qt-text-inf=(string)/dev/at2042, clock-base=(uint)2318609, seqnum-base=(uint)26256, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1 /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager.GstGhostPad:recv_rtp_src_1_109102090_0.GstProxyPad:proxypad7: caps = application/x-rtp, media=(string)audio, payload=(int)0, clock-rate=(int)8000, encoding-name=(string)PCMU, encoding-params=(string)1, a-tool=(string)"MOXA\\ 4CH\\ Streamming\\ Server\\ V1.0", a-type=(string)broadcast, x-qt-text-nam=(string)"4CH\\ Streaming", x-qt-text-inf=(string)/dev/at2042, clock-base=(uint)2318609, seqnum-base=(uint)26256, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1 /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstRtpPcmuDepay:rtppcmudepay0.GstPad:src: caps = audio/x-mulaw, channels=(int)1, rate=(int)8000 /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstMuLawDec:mulawdec0.GstPad:sink: caps = audio/x-mulaw, channels=(int)1, rate=(int)8000 /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstRtpPcmuDepay:rtppcmudepay0.GstPad:sink: caps = application/x-rtp, media=(string)audio, payload=(int)0, clock-rate=(int)8000, encoding-name=(string)PCMU, encoding-params=(string)1, a-tool=(string)"MOXA\\ 4CH\\ Streamming\\ Server\\ V1.0", a-type=(string)broadcast, x-qt-text-nam=(string)"4CH\\ Streaming", x-qt-text-inf=(string)/dev/at2042, clock-base=(uint)2318609, seqnum-base=(uint)26256, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1 /GstPipeline:pipeline0/GstDecodeBin:decodebin0/GstMuLawDec:mulawdec0.GstPad:src: caps = audio/x-raw, format=(string)S16LE, layout=(string)interleaved, rate=(int)8000, channels=(int)1 /GstPipeline:pipeline0/GstDecodeBin:decodebin0.GstDecodePad:src_0.GstProxyPad:proxypad9: caps = audio/x-raw, format=(string)S16LE, layout=(string)interleaved, rate=(int)8000, channels=(int)1 /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager.GstGhostPad:recv_rtp_src_0_2387976809_96: caps = application/x-rtp, media=(string)video, payload=(int)96, clock-rate=(int)90000, encoding-name=(string)MP4V-ES, profile-level-id=(string)3, config=(string)000001B003000001B50900000100000001200088400668582120A31F, a-tool=(string)"MOXA\\ 4CH\\ Streamming\\ Server\\ V1.0", a-type=(string)broadcast, x-qt-text-nam=(string)"4CH\\ Streaming", x-qt-text-inf=(string)/dev/at2042, clock-base=(uint)26503772, seqnum-base=(uint)15792, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1 /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0.GstGhostPad:recv_rtp_src_0_2387976809_96: caps = application/x-rtp, media=(string)video, payload=(int)96, clock-rate=(int)90000, encoding-name=(string)MP4V-ES, profile-level-id=(string)3, config=(string)000001B003000001B50900000100000001200088400668582120A31F, a-tool=(string)"MOXA\\ 4CH\\ Streamming\\ Server\\ V1.0", a-type=(string)broadcast, x-qt-text-nam=(string)"4CH\\ Streaming", x-qt-text-inf=(string)/dev/at2042, clock-base=(uint)26503772, seqnum-base=(uint)15792, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1 /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0.GstGhostPad:recv_rtp_src_0_2387976809_96.GstProxyPad:proxypad11: caps = application/x-rtp, media=(string)video, payload=(int)96, clock-rate=(int)90000, encoding-name=(string)MP4V-ES, profile-level-id=(string)3, config=(string)000001B003000001B50900000100000001200088400668582120A31F, a-tool=(string)"MOXA\\ 4CH\\ Streamming\\ Server\\ V1.0", a-type=(string)broadcast, x-qt-text-nam=(string)"4CH\\ Streaming", x-qt-text-inf=(string)/dev/at2042, clock-base=(uint)26503772, seqnum-base=(uint)15792, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1 /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstRtpBin:manager.GstGhostPad:recv_rtp_src_0_2387976809_96.GstProxyPad:proxypad10: caps = application/x-rtp, media=(string)video, payload=(int)96, clock-rate=(int)90000, encoding-name=(string)MP4V-ES, profile-level-id=(string)3, config=(string)000001B003000001B50900000100000001200088400668582120A31F, a-tool=(string)"MOXA\\ 4CH\\ Streamming\\ Server\\ V1.0", a-type=(string)broadcast, x-qt-text-nam=(string)"4CH\\ Streaming", x-qt-text-inf=(string)/dev/at2042, clock-base=(uint)26503772, seqnum-base=(uint)15792, npt-start=(guint64)0, play-speed=(double)1, play-scale=(double)1 ERROR: from element /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc0: Internal data flow error. Additional debug info: gstbasesrc.c(2865): gst_base_src_loop (): /GstPipeline:pipeline0/GstRTSPSrc:rtspsrc0/GstUDPSrc:udpsrc0: streaming task paused, reason not-linked (-1) EOS on shutdown enabled -- waiting for EOS after Error Waiting for EOS... 

Ctrl+C pressed here. 此处按Ctrl + C。

 handling interrupt. Interrupt: Stopping pipeline ... Interrupt while waiting for EOS - stopping pipeline... Execution ended after 0:00:12.942466327 Setting pipeline to PAUSED ... Setting pipeline to READY ... Setting pipeline to NULL ... Freeing pipeline ... 

Also you can look at diff for "good" (save to file works) with "bad" (error occured) on this link . 您也可以在此链接上查看“好”(保存到文件的工作)与“坏”(发生错误)的差异。

Using avenc_mpeg4 instead of x264enc works for me. 使用avenc_mpeg4代替x264enc对我有效。 The final command is: 最后的命令是:

gst-launch-1.0 -e rtspsrc location=rtsp://path/to/source ! decodebin ! avenc_mpeg4 ! mp4mux ! filesink location=file.avi

It works. 有用。 But only 1 time of ~10. 但是只有〜10的1倍。 Other 9 times I got same error as in the question: 其他9次,我得到与问题相同的错误:

streaming task paused, reason not-linked (-1) 流任务已暂停,原因未链接(-1)

I don't know what is the real reason for it. 我不知道真正的原因是什么。 But I think it's device feature. 但是我认为这是设备功能。

However, command like: 但是,命令如下:

gst-play-1.0 rtsp://path/to/source

works stable, ie without errors. 工作稳定,即没有错误。

The camera you have seems to be producing MPEG4 Type 2 streams which you are trying to wrap up in a mp4 container. 您的相机似乎正在产生MPEG4 Type 2流,您正尝试将其包装在mp4容器中。 So the x264_enc attempt will not work as the stream type is incompatible. 因此x264_enc尝试将不起作用,因为流类型不兼容。 Secondly you cannot use a MP4 mux with an AVI file type as with your other attempt though you can try avimux for that. 其次,尽管可以尝试使用av​​imux,但不能像其他尝试一样使用具有AVI文件类型的MP4 mux。 Breaking down the stream which works well from the caps negotiation we can construct it as: 从上限协商中分解出行之有效的流,我们可以将其构造为:

gst-launch-1.0 -v -e rtspsrc location=rtsp://path/to/source ! rtpmp4vdepay ! mpeg4videoparse ! mp4mux ! filesink location=test.mp4

The rtpmp4vdepay , mpeg4videoparse and the mp4mux are typically wrapped up in the decodebin element itself but just to make our life easier and to see what is going wrong it is always good to lay the elements out. rtpmp4vdepaympeg4videoparsemp4mux通常包装在decodebin元素本身中,但只是为了使我们的生活更轻松并查看出了什么问题,将元素布置好总是一件好事。 It gives you control over the pipeline you are constructing rather than leaving it to the caps negotiation to figure that out which I would not recommend for IP Cameras. 它使您可以控制正在构建的管道,而不必进行上限协商来确定我不建议对IP摄像机使用的管道。

I would also recommend trying out the pipeline (avoid the decodebin for IP cameras though): 我也建议尝试一下管道(尽管避免使用IP摄像机的解码器):

gst-launch-1.0 -e rtspsrc location=rtsp://path/to/source ! decodebin ! avenc_mpeg4 ! mp4mux ! filesink location=file.mp4

Having said that this link posted in the original question, shows the different negotiation formats when trying to play the stream. 话虽如此, 该链接张贴在原始问题中,显示了尝试播放流时的不同协商格式。 For example the one which 'works' trys to add elements in the order mentioned in the working pipline above and the non-working one try's to negotiate a different format by adding rtppcmudepay element. 例如,“有效”的尝试按上面工作节中提到的顺序添加元素,而无效的尝试通过添加rtppcmudepay元素来协商另一种格式。 I think it would be down to the camera which is making the decodebin think that there is more than one type of stream available and the decodebin aims to resolve those caps by adding additonal elements which are not required. 我认为这取决于相机,这使得解码器认为存在不止一种类型的流,并且解码器旨在通过添加不需要的附加元素来解决这些限制。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM