Record dynamically rtsp stream into .mp4 file

• Hardware Platform (Jetson / GPU) Jetson
• DeepStream Version 7.0
• JetPack Version (valid for Jetson only) 6.0
• Issue Type( questions, new requirements, bugs) Question

Hi, I’m trying to record an rtsp stream by adding/removing a bin to my pipeline. I use the 2 methods below and when I start, the .mp4 file is created and filled. The problem is that when I stop recording, the file is unreadable. I assume this is because the qtmux doesn’t receive the EOS but as I want my pipeline to continue after recording, I can’t set its state to NULL. I can’t use GLib.MainLoop() and therefore the bus in my situation, do you see how to solve this?

Here are the methods.

def start_recording(self,filepath):
        queue_bin = Gst.ElementFactory.make("queue","queue_bin")
        nvvideoconv_rec = Gst.ElementFactory.make("nvvideoconvert", "NvVidConvRec")
        capsfilter_rec = Gst.ElementFactory.make("capsfilter", "CapsfilterRec")
        caps_rec = Gst.Caps.from_string("video/x-raw, format=I420")
        capsfilter_rec.set_property("caps", caps_rec)
        encoder = Gst.ElementFactory.make("avenc_mpeg4", "Encoder") 
        encoder.set_property("bitrate", 2000000)
        codeparser = Gst.ElementFactory.make("mpeg4videoparse", "Mpeg4Parser")
        container = Gst.ElementFactory.make("qtmux", "Qtmux") 
        filesink = Gst.ElementFactory.make("filesink", "Filesink")
        filesink.set_property("location", filepath)

        self.record_bin = Gst.Bin.new("record_bin")
        self.record_bin.add(queue_bin)
        self.record_bin.add(nvvideoconv_rec)
        self.record_bin.add(capsfilter_rec)
        self.record_bin.add(encoder)
        self.record_bin.add(codeparser)
        self.record_bin.add(container)
        self.record_bin.add(filesink)

        queue_bin.link(nvvideoconv_rec)
        nvvideoconv_rec.link(capsfilter_rec)
        capsfilter_rec.link(encoder)
        encoder.link(codeparser)
        codeparser.link(container)
        container.link(filesink)

        bin_pad = queue_bin.get_static_pad("sink")
        ghost_pad = Gst.GhostPad.new("sink", bin_pad)
        self.record_bin.add_pad(ghost_pad)

        self.pipeline.add(self.record_bin)
        self.record_bin.set_state(Gst.State.PAUSED)

        tee_src_pad = self.tee_record.get_request_pad("src_%u")
        record_bin_pad = self.record_bin.get_static_pad("sink")
        if tee_src_pad.link(record_bin_pad) != Gst.PadLinkReturn.OK:
            sys.stderr.write("Failed to link tee record to record bin \n")

        self.record_bin.set_state(Gst.State.PLAYING)

def stop_recording(self):
        eos_event = Gst.Event.new_eos()
        self.record_bin.get_static_pad("sink").send_event(eos_event)
        self.record_bin.set_state(Gst.State.NULL)

        tee_src_pad = self.record_bin.get_static_pad('sink').get_peer()
        if tee_src_pad:
            tee_src_pad.unlink(self.record_bin.get_static_pad('sink'))
            self.tee_record.release_request_pad(tee_src_pad)

        self.pipeline.remove(self.record_bin)
        self.record_bin = None

Thanks in advance.

In this scenario, we recommend that you save the .ts stream with the mpegtsmux plugin.

It worked with mp4 by modifying the line self.record_bin.send_event(Gst.Event.new_eos()).

Thank you.