Сохранить поток RTSP в файл AVI с Gstreamer

У меня есть видеосервер, который дает мне видео и аудио потоков через RTSP. Я вижу это с помощью инструмента gstreamer gst-launch с командой:

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

Теперь мне нужно сохранить этот видеопоток в файл для последующего воспроизведения в любом популярном видеоплеере (VLC, Windows Media Player и т. Д.).

Я пытался просто заменить autovideosink с filesink location=file.avi и добавить -e вариант, как рекомендуется в этом ответе. Файл создан, но я думаю, что он не в правильном формате видео (VLC не может воспроизвести его).

Также я попробовал команду из недавно упомянутого ответа:

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

Это дает мне ошибку:

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)

Причина в том (как я думаю) x264enc ! mp4mux предназначен для кодека H.264, но мое устройство работает только в режиме MPEG4 part2 (MP4V-ES, т.е. H.263). Поэтому мне нужно заменить некоторые элементы в конвейере, чтобы удовлетворить возможности моего устройства. Но, просматривая список плагинов gstreamer, я не могу найти подходящих для MP4V-ES (H.263).

А теперь мой вопрос: как изменить команду gst-launch для сохранения видео с моего немного старого устройства в файл для дальнейшего воспроизведения?

Полный журнал для команды с многословием:

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 нажата здесь.

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 ...

Также вы можете посмотреть на diff для "хорошо" (сохранить в файл работает) с "плохо" (ошибка произошла) по этой ссылке.

2 ответа

Решение

Кажется, что ваша камера производит потоки MPEG4 Type 2, которые вы пытаетесь обернуть в контейнер mp4. Поэтому попытка x264_enc не будет работать, поскольку тип потока несовместим. Во-вторых, вы не можете использовать мультиплексор MP4 с типом файла AVI, как с другой попыткой, хотя вы можете попробовать Avimux для этого. Разбивая поток, который хорошо работает при согласовании ограничений, мы можем построить его следующим образом:

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

rtpmp4vdepay, mpeg4videoparse и mp4mux как правило, завернутые в decodebin сам элемент, но просто чтобы сделать нашу жизнь проще и увидеть, что идет не так, всегда хорошо выложить элементы. Это дает вам контроль над конвейером, который вы строите, а не оставляете его на согласование ограничений, чтобы выяснить, что я бы не рекомендовал для IP-камер.

Я также рекомендовал бы опробовать конвейер (хотя избегайте декодирования для IP-камер):

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

Сказав, что эта ссылка размещена в исходном вопросе, показаны различные форматы переговоров при попытке воспроизвести поток. Например, тот, который "работает", пытается добавить элементы в порядке, указанном в рабочей линии выше, а нерабочий пытается договориться о другом формате, добавив элемент rtppcmudepay. Я думаю, что до камеры, которая заставляет декодер думать, что доступно более одного типа потока, и декодер стремится разрешить эти ограничения, добавив дополнительные элементы, которые не требуются.

С помощью avenc_mpeg4 вместо x264enc работает для меня. Последняя команда:

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

Оно работает. Но только 1 раз ~10. Другие 9 раз я получил ту же ошибку, что и в вопросе:

потоковое задание приостановлено, причина не связана (-1)

Я не знаю, какова реальная причина этого. Но я думаю, что это особенность устройства.

Тем не менее, команда, как:

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

работает стабильно, т.е. без ошибок.

Другие вопросы по тегам