user972014
user972014

Reputation: 3856

ffmpeg-python extract a specific video stream, change its FPS and embed it back in the video

I have a video containing several streams. A few data and one video.

I need to extract the video stream, change the frame rate, embed it back in the video (or combine all stream back to an output file)

If needed, this is the list of existing streams:

I only need stream 0 and 5 (both video streams) Converted to 2 FPS. And stream 3 which is gpmd, which some irrelevant data format that I need to keep.

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'C:\temp\video.360':
  Metadata:
    major_brand     : mp41
    minor_version   : 538120216
    compatible_brands: mp41
    creation_time   : 2020-09-08 16:35:49
  Duration: 00:00:28.13, start: 0.000000, bitrate: 66559 kb/s
    Stream #0:0(eng): Video: hevc (Main) (hvc1 / 0x31637668), yuvj420p(pc, bt709), 4096x1344 [SAR 1:1 DAR 64:21], 30036 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 29.97 tbc (default)
    Metadata:
      creation_time   : 2020-09-08 16:35:49
      handler_name    : GoPro H.265
      encoder         : GoPro H.265 encoder
    Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 189 kb/s (default)
    Metadata:
      creation_time   : 2020-09-08 16:35:49
      handler_name    : GoPro AAC
    Stream #0:2(eng): Data: none (tmcd / 0x64636D74), 0 kb/s (default)
    Metadata:
      creation_time   : 2020-09-08 16:35:49
      handler_name    : GoPro TCD
    Stream #0:3(eng): Data: none (gpmd / 0x646D7067), 96 kb/s (default)
    Metadata:
      creation_time   : 2020-09-08 16:35:49
      handler_name    : GoPro MET
    Stream #0:4(eng): Data: none (fdsc / 0x63736466), 20 kb/s (default)
    Metadata:
      creation_time   : 2020-09-08 16:35:49
      handler_name    : GoPro SOS
    Stream #0:5(eng): Video: hevc (Main) (hvc1 / 0x31637668), yuvj420p(pc, bt709), 4096x1344 [SAR 1:1 DAR 64:21], 30019 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 29.97 tbc (default)
    Metadata:
      creation_time   : 2020-09-08 16:35:49
      handler_name    : GoPro H.265
      encoder         : GoPro H.265 encoder
    Side data:
      displaymatrix: rotation of nan degrees
    Stream #0:6(eng): Audio: pcm_s32be (in32 / 0x32336E69), 48000 Hz, 4 channels, s32, 6144 kb/s (default)
    Metadata:
      creation_time   : 2020-09-08 16:35:49
      handler_name    : GoPro AMB

Upvotes: 3

Views: 3399

Answers (1)

CasualDemon
CasualDemon

Reputation: 6160

Luckily it is pretty straightforward when dealing with a single video stream. The hassle comes with ffmpeg-python and data streams, but is simple enough to understand.

The file that I used as an example has a video, audio, and a data stream:

Stream #0:0[0x100]: Video: hevc (Main 10) (HEVC / 0x43564548), yuv420p10le(tv, bt2020nc/bt2020/smpte2084), 1920x1080, 30 tbr, 90k tbn, 90k tbc
Stream #0:1[0x101](eng): Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 258 kb/s
Stream #0:2[0x102]: Data: bin_data ([6][0][0][0] / 0x0006)

This ffmpeg-pyton command will take that video file input.ts, convert it from 30fps to 5fps, and then copy it, any audio and the data streams into a new file called converted.ts.

import ffmpeg

my_file = ffmpeg.input("input.ts")
video = my_file.video.filter("fps", 5)
ffmpeg.output(video, my_file.audio, my_file["d"], "converted.ts", vcodec="libx264", acodec="copy").run()

The ffmpeg.output command is where all the streams must be supplied. In this case we are provdiding the video stream with its filter applied, all the audio streams my_file.audio and all the data streams my_file["d"] (aka -map 0:d to ffmpeg).

The output will then have the new video stream, and the audio and data will be copied.

Stream #0:0[0x100]: Video: h264 (High 10) ([27][0][0][0] / 0x001B), yuv420p10le(tv, bt2020nc/bt2020/smpte2084, progressive), 1920x1080, 5 fps, 5 tbr, 90k tbn, 10 tbc
Stream #0:1[0x101](eng): Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 258 kb/s
Stream #0:2[0x102]: Data: bin_data ([6][0][0][0] / 0x0006)

If you don't have audio, omit the my_video.audio and acodec options from the ffmpeg.output command

    ffmpeg.output(video, my_file["d"], "converted.ts", vcodec="libx264").run()

Upvotes: 4

Related Questions