Poor Man's Video Editing

I’ve done all my video editing in a very old-school, unix-style way. I actually have no experience with real video editing software, which may explain why I tolerate the manual process. Instead, I use several open source tools, none of which are designed specifically for video editing.

The first three are usually available from your Linux distribution repositories, making them trivial to obtain. The last one is easy to obtain and compile.

If you’re using a modern browser, you should have noticed my portrait on the left-hand side changed recently. That’s an HTML5 WebM video — currently with Ogg Theora fallback due to a GitHub issue. To cut the video down to that portrait size, I used the above four tools on the original video.

WebM seems to be becoming the standard HTML5 video format. Google is pushing it and it’s supported by all the major browsers, except Safari. So, unless something big happens, I plan on going with WebM for web video in the future.

To begin, as I’ve done before, split the video into its individual frames,

mplayer -vo jpeg -ao dummy -benchmark video_file

The -benchmark option hints for mplayer to go as fast as possible, rather than normal playback speed.

Next look through the output frames and delete any unwanted frames to keep, such as the first and last few seconds of video. With the desired frames remaining, use ImageMagick, or any batch image editing software, to crop out the relevant section of the images. This can be done in parallel with xargs-P option — to take advantage of multiple cores if disk I/O isn’t being the bottleneck.

ls *.jpg | xargs -I{} -P5 convert {} 312x459+177+22 {}.ppm

That crops out a 312 by 459 section of the image, with the top-left corner at (177, 22). Any other convert filters can be stuck in there too. Notice the output format is the portable pixmap (ppm), which is significant because it won’t introduce any additional loss and, most importantly, it is required by the next tool.

If I’m happy with the result, I use ppmtoy4m to pipe the new frames to the encoder,

cat *.ppm | ppmtoy4m | vpxenc --best -o output.webm -

As the name implies, ppmtoy4m converts a series of portable pixmap files into a YUV4MPEG2 (y4m) video stream. YUV4MPEG2 is the bitmap of the video world: gigantic, lossless, uncompressed video. It’s exactly the kind of thing you want to hand to a video encoder. If you need to specify any video-specific parameters, ppmtoy4m is the tool that needs to know it. For example, to set the framerate to 10 FPS,

... | ppmtoy4m -F 10:1 | ...

ppmtoy4m is a classically-trained unix tool: stdin to stdout. No need to dump that raw video to disk, just pipe it right into the WebM encoder. If you choose a different encoder, it might not support reading from stdin, especially if you do multiple passes. A possible workaround would be a named pipe,

mkfifo video.y4m
cat *.ppm | ppmtoy4m > video.y4m &
otherencoder video.4pm

For WebM encoding, I like to use the --best option, telling the encoder to take its time to do a good job. To do two passes and get even more quality per byte (--passes=2) a pipe cannot be used and you’ll need to write the entire raw video onto the disk. If you try to pipe it anyway, vpxenc will simply crash rather than give an error message (as of this writing). This had me confused for awhile.

To produce Ogg Theora instead of WebM, ffmpeg2theora is a great tool. It’s well-behaved on the command line and can be dropped in place of vpxenc.

To do audio, encode your audio stream with your favorite audio encoder (Vorbis, Lame, etc.) then merge them together into your preferred container. For example, to add audio to a WebM video (i.e. Matroska), use mkvmerge from MKVToolNix,

mkvmerge --webm -o combined.webm video.webm audio.ogg

Extra notes update: There’s a bug in imlib2 where it can’t read PPM files that have no initial comment, so some tools, including GIMP and QIV, can’t read PPM files produced by ImageMagick. Fortunately ppmtoy4m is unaffected. However, there is a bug in ppmtoy4m where it can’t read PPM files with a depth other than 8 bits. Fix this by giving the option -depth 8 to ImageMagick’s convert.

blog comments powered by Disqus

null program

Chris Wellons