Media Cutting

Introduction

Our approach to cutting video is to use ffmpeg. The justification for this choice is as follows:

  • Ffmpeg is (at least in theory) multi-platform. So far we got it working successfully under Linux, Windows and Mac.
  • ... is open source, so we can add functionality and fix bugs ourselves.
  • ... is one of the very few free tools that support multiple video formats (although still does not split all of them well) and are multi-platform at the same time.
  • ... still goes under very active development, so there is a big chance it will at the end support most of the video formats properly.
Video file extensionvideo codecaudio codecSupportsplit quality
.mp4mpeg4aacyesgood
.avixvidmp3yesmoderate

TODO: Add the rest of the tested formats in the table.

Using ffmpeg

Spliting media with ffmpeg is quite easy. Below is some simple Python code showing how to do that:

import os

import string



StartTime=25 # seconds

StopTime=50  # seconds

InFile="Johan-Oomen-metadata-partial.mp4"

ffmpegexe="ffmpeg"

ResFile="cut_Johan-Oomen-metadata.mp4"



os.system(ffmpegexe + " -y -i " + InFile + " -vcodec copy -acodec copy " + 

          " -ss " + str(StartTime) + " -t " + str(StopTime-StartTime) + " " + ResFile)

This code, along with ffmpeg and the sample video are packed in the attached videosplit.zip file.

Ffmpeg can be used for other operations on media (like transcoding) as well. Here are some of the options explained:

  • -y overwrites the output file (does not ask for permission if the file exists already)
  • -i filename specifies the input file
  • -vcodec forces video codec. With copy copies the stream without re-encoding.
  • -acodec forces audio codec. With copy copies the stream without re-encoding.
  • -ss time specifies start time offset (in seconds)
  • -t time specifies duration time (in seconds)

For information about other options run ffmpeg -h.

Building ffmpeg

  • Linux: Ffmpeg compiles natively under Linux. See the documentation in ffmpeg sources.
  • Windows: We build ffmpeg cross-platform on Debian with mingw32. For how-to description see FfmpegWin.
  • Mac: Ffmpeg compiles natively under Mac OS/X. How to create a Universal Binary is explained in FfmpegMac. Download complete OSX testkit (Universal)

With some types of mp4 movies ffmpeg fails if used with the "-acodec copy" option. This is because frame_size of the audio stream is not initialized if multiple stts entries are found present in that stream. The workaround below solves this issue.

--- libavformat/mov.c.orig	2007-05-03 10:32:35.868450428 +0200

+++ libavformat/mov.c	2007-05-07 10:37:24.599577370 +0200

@@ -1419,7 +1419,7 @@

             sc->time_scale= mov->time_scale;

         av_set_pts_info(st, 64, sc->time_rate, sc->time_scale);

 

-        if (st->codec->codec_type == CODEC_TYPE_AUDIO && sc->stts_count == 1)

+	if (st->codec->codec_type == CODEC_TYPE_AUDIO /*&& sc->stts_count == 1*/)

             st->codec->frame_size = sc->stts_data[0].duration;

 

         if(st->duration != AV_NOPTS_VALUE){

Temporary fix for wrong video frame rate identification in mp4 videos

--- libavformat/mov.c.orig      2007-05-11 10:32:35.868450428 +0200

+++ libavformat/mov.c   2007-05-16 22:46:13.993701950 +0200

@@ -959,14 +959,19 @@



     for(i=0; i<entries; i++) {

         int sample_duration;

+        int sample_duration_round;

         int sample_count;



         sample_count=get_be32(pb);

         sample_duration = get_be32(pb);

         sc->stts_data[i].count= sample_count;

         sc->stts_data[i].duration= sample_duration;

-

-        sc->time_rate= ff_gcd(sc->time_rate, sample_duration);

+        if (st->codec->codec_type == CODEC_TYPE_VIDEO)

+          sample_duration_round = sample_duration - sample_duration%1000;

+        else

+          sample_duration_round = sample_duration;

+

+        sc->time_rate= ff_gcd(sc->time_rate, sample_duration_round);



         dprintf(c->fc, "sample_count=%d, sample_duration=%d

",sample_count,sample_duration);

Attachments