Skip to content
 

using ffmpeg for cutting media files – and the gotchas involved

So here I was, trying to complete some ordinary transcoding / media file cutting tasks with ffmpeg. Turns out there are some weird gotchas when using some versions of ffmpeg (in my case, SVN-r10571) on the commandline.

Problem 1: transcoding to mp3 insists on using 64kbits/s or 128kbits/s bitrate

So a simple task is to transcode an audio file of some arbitrary format to MP3. In my case, I only wanted a 30-second piece of the original file, converted to MP3. The original was in 256kbits/s, and I decided to use the same bitrate for the output, just for kicks. Reading the man page, -b is for video bitrate, and -ab is for audio bitrate. So I executed:

wrong:  ffmpeg -ss 00:00:30.00 -t 25 -i foo.mp3 -ab 256 foo-new.mp3

The output, of course, was this:

Input #0, mp3, from 'foo.mp3':
...
mdb:109, lastbuf:0 skipping granule 0
size= 393kB time=25.2 bitrate= 128.0kbits/s
video:0kB audio:393kB global headers:0kB muxing overhead 0.007950%

128 kbits/s. That was…not what I wanted.

Turns out, as the ffmpeg man page hints but does not specify clearly, a “k” is required to label the units of the new bitrate. As in:

right:  ffmpeg -ss 00:00:30.00 -t 25 -i foo.mp3 -ab 256k foo-new.mp3

This time, the output was:
Input #0, mp3, from 'foo.mp3':
...
mdb:109, lastbuf:0 skipping granule 0
size= 782kB time=25.0 bitrate= 256.0kbits/s
video:0kB audio:782kB global headers:0kB muxing overhead 0.003996%

Much better. It’s very strange how that if I don’t give it the ending “k” but do give it a higher value than 64, it always bumps up the bitrate to 128kbits/s, from the default of 64k (but not to the number I actually wanted).

 

Problem 2: cutting media file without re-encoding

So ffmpeg can be used to cut a media file, without reencoding the media stream. You simply pass the raw copy codec to the -acodec (or the -vcodec for video) at encode time. For my MP3, I thought it was a pretty trivial problem, so I issued:

wrong: ffmpeg -i bar.mp3 -ss 00:00:30.00 -t 25 -acodec copy bar-new.mp3

This seemed to process correctly, except it created a 555-byte empty file with no content in it. What’s even weirder, if you issued:

wrong: ffmpeg -i bar.mp3 -ss 00:00:10.00 -t 25 -acodec copy bar-new.mp3

That is, -ss 00:00:10.00 to seek to the 10th second, and -t 25 to record 25 seconds worth of audio. Strangely enough, the output file had 15 seconds of audio, the subtraction of 25 by 10. Curiouser and curiouser. Now,

wrong: ffmpeg -i bar.mp3 -ss 00:00:10.00 -t 25 -acodec mp3 bar-new.mp3

does in fact create a 25-second MP3 file. Only, of course, a re-encoded one at 64kbits/s. Something that we are not looking for. But strange.

A post on ffmpeg-devel finally provided enough hints to clue me into the problem. Unlike many command line apps, the order of arguments passed to ffmpeg seem to be silently significant. The correct incantation is:

right: ffmpeg -ss 00:00:30.00 -t 25 -i bar.mp3 -acodec copy bar-new.mp3

Note the switched order for the arguments -i and the args -ss and -t, where the -i must follow the other two. Now, the desired 25-second file, cut from the original, is correctly produced.

When arguments are missing some arbitrary text or in the wrong order, ffmpeg doesn’t sanity-check or warn you of these…it just silently proceeds and does some very strange things. Things that make you scratch your head and wonder, “wtf? did I mistype an argument somewhere?”

Ah, and of course, you make me have to track down all these little idiosyncrasies, wading through blog posts and mailing lists and forums. Agh.

8 Comments

  1. [...] using ffmpeg for cutting media files – and the gotchas involved | The Sarth Repository [...]

  2. Troy says:

    Thanks for taking the time to delve into this. Glad I found this after an hour of pounding my head against the keyboard.

  3. [...] if the -isync is needed, but make sure you copy both codecs or it will create suckage. Thanks to this for demonstrating the proper command line [...]

  4. Merciful says:

    Read the manual! It clearly states that options, like the above one, apply to the first file following the options. So in “ffmpeg -i bar.mp3 -ss 00:00:10.00 -t 25 -acodec mp3 bar-new.mp3″ the -ss -t -acodec options all apply to the file “bar-new.mp3″.

    In “ffmpeg -ss 00:00:30.00 -t 25 -i bar.mp3 -acodec copy bar-new.mp3″ the -ss and -t option apply to bar.mp3 and the -acodec applies to “bar-new.mp3″.

    Look at this one (capture from webcam) to dvd mpeg:”ffmpeg -f mjpeg -s 464×480 -vcodec mjpeg -r 14 -i /dev/video0 -target pal-dvd ~/stream.mpeg”

    • yiming says:

      Thanks for the pointer. I would disagree with your conclusion that a manual is the end-all solution to the issue. The problem is that this sort of user interface design is unintuitive (yes, even CLIs are user interfaces). When specifying arguments on a command line, the majority of programs treat it as a hash of options, where order is unimportant. It would not occur to most users, even seasoned command-line jockeys, that it is the order of arguments that caused strange behavior.

      This sort of problem should be detected, and a warning printed to standard error. In most cases, it makes no sense to accept -t or -ss options for an output file rather than an input file, making detection quite easy for the majority of cases. It is the responsibility of ffmpeg to do this, because here it is ffmpeg that is behaving out of the norm, not the user.

      Imagine if I designed a doorknob — which looks like an ordinary doorknob — but requires that you pull/push on the knob to open, rather than turning it. I would expect that many users would be confused when they first try any door with this knob installed. If my oddly designed doorknob is used in all major buildings, users may indeed write blog posts about how unintuitive it is. And assuming that I cannot redesign my doorknob at all, I would post a sign that says “Pull to open”, rather than putting a 10-page operating manual (complete with diagrams) next to every such door, with a guy next to it yelling “Read the F’ing Manual!” :)

  5. THANK YOU for publishing this little and so precious knowledge!

    I’ve lost hours trying to cut the useless parts of a .TS file, and I couldn’t understand why ffmpeg was re-encoding everything (in crappy quality). I could have managed to find the “copy” codecs, but putting -ss on the beginning was beyond my imagination.

    I agree with yiming: command line should be as much as possible order-neutral, and sanity checks MUST occur.

  6. grateful says:

    I was totally confused by this as well, even after reading the man page. Thanks so much!

  7. Petar Hristov says:

    Thanks a lot!
    You have helped a lot of people!
    If one day I become rich I will express my gratitude in $$$!
    Promise is a promise!

    In man page of ffmpeg it is specified that parameters concerning the source file -i SOURCE_FILE need to be before it.
    But people do not read man pages.
    They use google and copy-paste.

Leave a Reply