avconv - a very fast video and audio converter

mail

How to mix an audio + a video track ?

Let's imagine you retrieved 2 files with youtube-dl : Now is the time to put the audio and video tracks together :
audioFile="Thunderstruck by Steve'n'Seagulls (LIVE)-e4Ao-iNPPUc.webm"; videoFile="Thunderstruck by Steve'n'Seagulls (LIVE)-e4Ao-iNPPUc.mp4"; outputFile='output.mp4'; ffmpeg -i "$videoFile" -i "$audioFile" -c:v copy -c:a aac "$outputFile"
This converts the audio stream into AAC, because —for an unknown reason— it is not possible to keep the original audio format.
mail

How to concatenate audio / video files ?

avconv -i concat:"file1|file2|file3" -c copy output
mail

How to convert audio files ?

WAV to MP3 :

for audioFile in *wav; do avconv -i "$audioFile" -codec:a libmp3lame -b:a 256k "${audioFile%.*}.mp3"; done

WAV to FLAC (source) :

for audioFile in *wav; do avconv -i "$audioFile" -af aformat=s16:44100 "${audioFile%.*}.flac"; done

This encodes to 16 bits at 44100 hertz.

mail

avconv

Usage

Audio and video can be converted with avconv (which can be installed with the Debian package libav-tools).
avconv replaces ffmpeg that is now obsolete.

This is actually wrong : due to a flamewar between ffmpeg and avconv project leaders, the avconv team started making things confusing for everybody with questionable assertions (sources : 1, 2). ffmpeg is still actively developed and maintained.

Flags

General flags (source) :

Flag Usage
-af filterGraph Apply filterGraph to the input audio stream
A filterGraph is a process made of several piped filters. One of the available filterGraphs is aformat
-f format Force input or output file format. The format is normally autodetected for input files and guessed from file extension for output files, so this option is not needed in most cases. To list supported file formats (containers) : avconv -formats
  • D : container can be decoded (read)
  • E : container can be encoded (written)
-i inputFile input file. It is possible to have several input files :
avconv -i file1 -i file2
and to refer to individual streams with -map x:y
-map fileId:streamId -map x:y refers to :
  • x : ID of input file (1st file listed on the command line with -i file is 0, and so on)
  • y : input file stream ID
Examples : 1, 2
-ss position
  • When used as an input option (before -i), seeks in this input file to position.
  • When used as an output option (before an output filename), decodes but discards input until the timestamps reach position.
  • Seeking is made as "best effort" (read documentation for details)
  • position may be either in seconds or in hh:mm:ss[.xxx] form.
-t duration Stop writing the output after its duration reaches duration.
duration may be a number in seconds, or in hh:mm:ss[.xxx] form.
-threads n Use n threads for processing.
Or auto : ??? (showed the maximum CPU usage when tried )
Or 0 : ???
-y Overwrite output files without asking (actually auto-answers "yes" to Overwrite (y/n) ? prompt.)

Audio / video / filter / preset flags :

Flag Usage
-aspect ratio Set the video display aspect ratio
  • It is possible to apply this to a given stream with -aspect:x:y ratio
  • The result is fine in VLC, my but my LG TV sees no difference
-c codec
-codec codec
Generic specification : -codec[:optional_stream_specifier] codec input|output|stream
Select a decoder (when used before an input file) or an encoder (when used before an output file) for one or more streams. codec is the name of a decoder/encoder or the special value copy (output only) to indicate that the stream is not to be re-encoded (often seen as : -c copy).
-acodec codec
-codec:a codec
Specify the audio codec.
-c:a copy means that the input audio will be copied as is, without any transcoding.
-b:stream value Set the bitrate of the (optional parameter) stream stream (a for audio, v for video) to value bits/s (value can use the k suffix)
-crf quality Select the quality for constant quality mode. It goes from 0 (lossless) upwards logarithmically. You'll probably want a value between 19 and 25 in most cases.
-deinterlace deinterlace the video stream
-preset type Configuration preset. This does some automatic settings based on the general type of the image (?). Sets the speed of the encoding, either "slow", "medium", or "fast". Slow should get you smaller file sizes with an obvious tradeoff.
-r:stream value Set the frame rate of the specified video stream stream to value frames/s
-s:stream WxH Declare the size (width*height) of the input stream, OR set frame size to WxH
-vcodec codec
-codec:v codec
Specify the video codec.
-vf filter Apply the filter filter to the input video

Example

Get information about avconv capabilities :

List available codecs :
avconv -codecs
V : video codec
A : audio codec
S : subtitle codec

Get information (codec, bitrate, ...) about a media file (video / sound / video + sound track(s) / subtitles / ...) :

avconv -i file, and look at the Stream #x.y lines.

This command returns a failure exit code as avconv expects an "output file" parameter (I found no better solution so far ). For this reason ("failure" exit code + output message sent to stderr rather than stdout), you have to redirect everything to stdout before processing it :

for a single file :
avconv -i file 2>&1 | grep 'Stream'
for multiple files :
streamType='Audio'; for mediaFile in *; do echo "$mediaFile"; avconv -i "$mediaFile" 2>&1 | grep -E "Stream.*$streamType"; done
mail

How to trim audio or video files ?

General case :

The command below will :
  1. "open" inputFile to do stuff with it
  2. "select" data starting at startTime of inputFile
  3. make this selection last for duration
  4. and copy the selection into outputFile

avconv -i inputFile -ss startTime -t duration -codec copy outputFile

  • startTime and duration are in either a number of seconds, or in the hh:mm:ss[.xxx] format.
  • If no duration is specified, the process will continue until the end of the input file.

Cut a few seconds from the beginning of a video :

The command above may work pretty well. But, depending on the input file itself (I got this with a .avi file), it may end in a huge series of :

Non-monotonous DTS in output stream 0:1; previous: 103475, current: 34492; changing to 103476. This may result in incorrect timestamps in the output file.
+ audio and video not in sync anymore. This has to do with the file format itself (AVI container, mkv, mpg, mp4, ...) and codecs. see also

Re-encoding the audio track (here in mp3 format) fixed it :

avconv -i input.avi -ss 15.5 -c:v copy -c:a mp3 output.avi

During the tests to find the right start time (-ss value), save time by not processing the input until the end :

avconv -y -i input.avi -ss 15.5 -t 30 -c:v copy -c:a mp3 output.avi

TESTING :
outputDir='./output'; mkdir -p "$outputDir"; for input in *avi; do echo "$input"; avconv -y -i "$input" -ss 15.5 -t 15 -c:v copy -c:a mp3 "$outputDir/$input"; done

REAL :
outputDir='./output'; mkdir -p "$outputDir"; for input in *avi; do echo "$input"; avconv -i "$input" -ss 15.5 -c:v copy -c:a mp3 "$outputDir/$input"; done
mail

How to re-order the audio tracks of a .mkv file ?

Situation

I'd like to share a .mkv movie from my PC with MiniDLNA and play it on my TV. However, my TV automatically plays the 1st audio track (whatever language it is) and won't let me select another one.

Details

So far, I don't know whether this is :

Solution

Since I can't debug + fix the firmware of my TV, let's see what happens if I change the order of the audio tracks in the .mkv file :
List all tracks of the movie file :
avconv -i movie.mkv 2>&1 | grep Stream
Stream #0.0(eng): Video: h264 (High), yuv420p, 1920x1080, PAR 1:1 DAR 16:9, 23.98 fps, 1k tbn, 47.95 tbc (default)
Stream #0.1(eng): Audio: ac3, 48000 Hz, 5.1, fltp, 448 kb/s	my TV plays this audio track
Stream #0.2(fre): Audio: ac3, 48000 Hz, 5.1, fltp, 448 kb/s	I want this one played
Stream #0.3(fre): Subtitle: srt
Stream #0.4(eng): Subtitle: srt
Change the order of tracks with -map :
With that option, avconv can build a new multi-track output file by picking tracks from the specified input file. The 1st map of the command line is for the 1st track of the output file. The 2nd map of the command line is for the 2nd track of the output file, and so on.

avconv -i input.mkv -map 0:0 -map 0:2 -map 0:1 -c copy output.mkv

This specifies the tracks of output.mkv to be :
  • Track 0 : track 0 of input.mkv (video)
  • Track 1 : track 2 of input.mkv (french audio)
  • Track 2 : track 1 of input.mkv (english audio)
-c copy means the tracks must not be re-encoded but copied as-is.
In output.mkv, we now have :
avconv -i output.mkv 2>&1 | grep 'Stream'
Stream #0.0(eng): Video: h264 (High), yuv420p, 1920x1080, PAR 1:1 DAR 16:9, 23.98 fps, 1k tbn, 47.95 tbc (default)
Stream #0.1(fre): Audio: ac3, 48000 Hz, 5.1, fltp, 448 kb/s
Stream #0.2(eng): Audio: ac3, 48000 Hz, 5.1, fltp, 448 kb/s
We've not picked the subtitles tracks !
Same as above, with ALL tracks :
avconv -i input.mkv -map 0:0 -map 0:2 -map 0:1 -map 0:3 -map 0:4 -c copy output.mkv
Last words : the whole operation lasted 1.5 minutes on my PC for a 3.9GB input file. It is actually more stressful for the HDD than for the CPU (30% of a core used).
mail

How to extract the audio track from a movie ?

There are several methods to get an audio track (source) :

As uncompressed audio :

avconv -i movie.mp4 audio.wav

As MP3 :

  • one file : avconv -i movie.mp4 -codec:a libmp3lame audio.mp3
  • more files :
    • for videoFile in *mp4; do avconv -i "$videoFile" -codec:a libmp3lame "$videoFile".mp3; done
    • outputDir='./audio'; mkdir -p "$outputDir"; for videoFile in *mp4; do avconv -i "$videoFile" -codec:a libmp3lame -b:a 256k "$outputDir/${videoFile%.*}.mp3"; done
Don't forget to specify the audio bitrate (defaults to 64kbit/s) with -b:a bitrate :
avconv -i movie.mp4 -codec:a libmp3lame -b:a 256k audio.mp3
Check :
Get information (codec, bitrate, ...) about a media file

Only a snippet, as MP3 :

avconv -y -ss 00:14:30 -i movie.avi -t 4.5 -codec:a libmp3lame audio.mp3

As Ogg Vorbis :

  • one file : avconv -i movie.mp4 -codec:a libvorbis audio.ogg
  • more files : outputDir='./ogg'; mkdir -p "$outputDir"; for sourceFile in *mp4; do avconv -i "$sourceFile" -codec:a libvorbis "$outputDir/${sourceFile%.*}.ogg"; done
For a reason unknown so far, this command _sometimes_ re-encodes the specified video file into "Ogg Theora" video format instead of extracting the audio track + converting it to Ogg Vorbis. I must have missed something important

Copy the audio track as-is with the map method :

This method should be preferred whenever possible since it only extracts the audio data with no reconversion :

  • preserves the original audio quality
  • doesn't produce an artificial "high quality" audio file from a lower quality source (which is what websites offering to download music from YouTube as MP3 do)
  • best possible audio quality vs file size ratio

  1. identify the audio track :
    Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 389 kb/s, 29.97 fps, 29.97 tbr, 90k tbn, 59.94 tbc (default)
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
  2. copy it into a new file :
    avconv -i movie.mp4 -map 0:1 -c copy audio.mp4
  3. you can make sure this file as only 1 audio track :
    Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
  4. Rename the audio file based on the type of audio format :
    mv audio.{mp4,aac}
mail

How to convert video files ?

Transcode files (details) :

From any format to MPEG 1 :
avconv -i input.mp4 output.mpg
From any format to MPEG 2 :
avconv -i input.mp4 -f dvd output.mpg
From any format to H.264 inside an MP4 container :
avconv -i input.mp4 -strict experimental -vcodec libx264 -deinterlace -threads 0 output.mp4
-strict experimental was suggested by the software :
encoder 'aac' is experimental and might produce bad results.
Add '-strict experimental' if you want to use it.
From any format, convert video to H.264 + leave audio as-is, and save the result into an MP4 container :
avconv -i input.mp4 -threads auto -c:a copy -vcodec libx264 output.mp4

Rotate a video :

Please note :
  • Videos shot with a smartphone have a Rotation metadata parameter. It is used by the built-in player to orient the video properly (source).
  • Looks like VLC ignores or misinterprets this parameter (?)
  • Despite all my efforts, I've not been able to rotate a video made with an Android phone with avconv. Neither did others.
  • OpenShot did it very well with a few clicks.
  • Converting videos can be HARD on CPU, cause overheating (?) and make the system hang To workaround this, considering adjusting manually the CPU frequency.

90° :

https://stackoverflow.com/questions/3937387/rotating-videos-with-ffmpeg/9570992#9570992
	ffmpeg -i in.mov -vf "transpose=1" out.mov

For the transpose parameter you can pass:

0 = 90Counterclockwise and Vertical Flip (default)
1 = 90Clockwise
2 = 90Counterclockwise
3 = 90Clockwise and Vertical Flip

https://ffmpeg.org/ffmpeg-filters.html#transpose-1

180° (source) :

avconv has no option to do so, but this can be achieved either with 2 consecutive 90° rotations, or with an horizontal flip followed by a vertical flip :
avconv -i input.mp4 -vf "hflip,vflip" -codec:v libx264 -preset slow -crf 20 -codec:a copy flipped.mp4
avconv -i input.mp4 -metadata:s:v rotate="0" -vf "hflip,vflip" -c:v libx264 -crf 23 -acodec copy output.mp4 (source)

Change a video resolution by percentage (source) :

To scale down the video to 25% of its original resolution :

avconv -i inputFile -vf scale=iw*0.25:-1 -codec:a copy outputFile

-codec:a copy allows to stream copy the audio without re-encoding.