Split MPEG-TS into MP4 files with gstreamer 1.12.2

2019-02-20 06:18发布

问题:

I have a MPEG-TS file which contains two video/audio stream-pairs:

$ gst-discoverer-1.0 Recorder_Aug01_12-30-39.ts
Analyzing Recorder_Aug01_12-30-39.ts
Done discovering Recorder_Aug01_12-30-39.ts

Topology:
  container: MPEG-2 Transport Stream
    audio: MPEG-2 AAC
      audio: MPEG-4 AAC
    video: H.264 (High Profile)
    audio: MPEG-2 AAC
      audio: MPEG-4 AAC
    video: H.264 (High Profile)

Properties:
  Duration: 0:01:49.662738259
  Seekable: yes
  Tags: 
      audio codec: MPEG-2 AAC
      video codec: H.264

Now I would like to extract the first video and audio streams and the second video/audio into two separate MP4 containers.

Showing both video streams in parallel works with a simple pipeline:

$ gst-launch-1.0 filesrc location=Recorder_Aug01_12-30-39.ts ! tsdemux name=ts \
    ts.video_0_0102 ! queue ! h264parse ! avdec_h264 ! videoconvert ! videoscale ! autovideosink \
    ts.video_0_0100 ! queue ! h264parse ! avdec_h264 ! videoconvert ! videoscale ! autovideosink

When I introduce the mp4mux together with a filesink element on one stream it still work, the first video stream is shown and the second video is saved to a MP4 container file:

$ gst-launch-1.0 filesrc location=Recorder_Aug01_12-30-39.ts ! tsdemux name=ts \
    ts.video_0_0102 ! queue ! h264parse ! avdec_h264 ! videoconvert ! videoscale ! ximagesink \
    ts.video_0_0100 ! queue ! h264parse ! mp4mux ! filesink location=2.mp4

Now for my problem: Once I try to have both streams saved through filesinks it fails:

$ gst-launch-1.0 filesrc location=Recorder_Aug01_12-30-39.ts ! tsdemux name=ts \
    ts.video_0_0102 ! queue ! h264parse ! mp4mux ! filesink location=1.mp4 \
    ts.video_0_0100 ! queue ! h264parse ! mp4mux ! filesink location=2.mp4
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
ERROR: from element /GstPipeline:pipeline0/GstMP4Mux:mp4mux0: Could not multiplex stream.
Additional debug info:
gstqtmux.c(3486): gst_qt_mux_add_buffer (): /GstPipeline:pipeline0/GstMP4Mux:mp4mux0:
Buffer has no PTS.
Execution ended after 0:00:00.001992389
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

I would like to achieve this using gstreamer because it should later be part of a larger processing workflow that needs a lot of introspection, so using ffmpeg or some external binary is no an option.

回答1:

GStreamer Buffer has no PTS Failure Mode

This may not completely solve the problem using GStreamer, but this is a workaround that I'm now using. It involves isolating out the failing component which is the 'mp4mux' element in the gstreamer pipeline.

I'm finding that even a sample video encoding in Gstreamer is currently failing e.g. with the Buffer has no PTS failure mode:

gst-launch-1.0 videotestsrc num_buffers=300 ! videoconvert ! videoscale ! omxh264enc ! h264parse ! mp4mux ! filesink location=test.mp4

Using Gstreamer for h264 Encoding only.

Removing the mp4mux element allows us to successfully create .h264 files. Particularly handy if you're using a Raspberry Pi omxh264 encoder element.

gst-launch-1.0 videotestsrc num_buffers=300 ! videoconvert ! videoscale ! omxh264enc ! filesink location=test.h264

Solving the problem of Mixing Audio and Video

Now to convert that into an MP4 (the initial goal) we can use the nice lightweight Gpac MP4box.

sudo apt-get install gpac

MP4Box -isma -inter 250 -fps 30.0 -mpeg4 -hint -noprog -add test.h264 test.mp4

Then you can add in your audio

MP4Box -add audio.mp3 test.mp4

Summary

  1. GStreamer appears currently broken with the No PTS failure mode when using Mp4Mux element.
  2. GStreamer general h264 encoding and piplines are awesome, and working.
  3. Using GPac to combine audio into Mp4 files is a viable alternative.