2014-01-24

Simple Video Tricks

While working on the new Recorder (see also last posting) I suddenly faced several challanges with the resulting video files:
  • Many short chunks (50MB each, about 30-60 seconds) need to be merged
  • Extract the actual talk from a longer recording, e.g. the recorder was on for one hour but the talk was only half an hour
  • Convert the video into another container format because Adobe Premiere does not like AVI files
  • Create video thumbnails
  • Convert videos to be compatible with HTML5 <video> playback
Turns out that avconv (or ffmpeg) is the swiss army knife for all of these tasks! I am not qualified to say which is better, for my purposes the avconv that ships with Ubuntu is good enough. The examples given here work with both. When I write avconv I mean both tools.

Since I don't want to degrade the video quality through repeated decode/encode steps I always use -codec copy after the input file to simply copy over the audio and video data without reencoding it.

Concatenate Videos

This is probably the easiest part: avconv has an input protocol called concat which simply reads several files sequentially:

avconv -i concat:file1|file2 -codec copy out.mp4

Note: This method simply concatenates the input files as-is. It is mostly useful for transport streams. This methods usually fails to concatenate files that have container metadata. For that you can use the concat demuxer that is only available in ffmpeg. Full details can be found in the ffmpeg Wiki.

This script automates the process. It takes two files as arguments and concatenates all the files in the same directory starting from the first one and ending with the last one. Further arguments are passed to avconv.

Convert Video Container

One of the most common tasks is to convert the video container, e.g. from AVI to MOV or MP4:

avconv -i input.avi -codec copy output.mov

Create Video Thumbnails

Another simple task. Extract an image from the video after 4 seconds:

avconv -i input.avi -ss 4 -vframes 1 poster.jpg

Or for all the videos in a directory:

ls *.mp4 | while read ; do avconv -i "$REPLY" -vframes 1 -ss 4 -y "$REPLY.jpg" ; done


Create HTML5 Video

Convering a video for HTML5 playback requires keeping some standards, e.g. using a compatible profile and level. The following worked very well for me:

avconv -i INPUT-FILE -pix_fmt yuv420p -c:v libx264 -crf 30 -preset slower -profile:v Main -level 31 -s 568x320 -c:a aac -ar 22050 -ac 1 -b:a 64k -strict experimental out.mp4 ; qt-faststart out.mp4 OUTPUT-FILE.mp4 ; rm out.mp4

For smartphone consumption this is more than good enough. The result is about 3MB/min. You can increase the video size (e.g. 854x480) or quality (e.g. -crf 28), but this will also significantly increase the file size. The qt-faststart moves some MP4 metadata to the beginning of the file so that the file can be streamed.

Create video from image

Simple way to create a video of 3 seconds length at 25 frames/sec from a PNG image:

avconv -loop 1 -i image.png -r 25 -t 3 video.mp4