Real-time MPEG-2 encoding with ffmpeg

I’ve done some significant experimentation with different options for encoding MPEG-2 video from a live video source with ffmpeg.  The objective was to create video that was approximately 3 Mbps at a “decent” resolution; this video would be manually edited and then converted to Web quality.  By “decent”, I mean a high enough resolution so that the video can survive the transcode to Web resolutions without too many re-encoding artifacts.   When encoding a live source, performance is critical; if ffmpeg can’t keep up with the live frames being captured, you may as well not even try to encode the video; your live capture buffers will quickly fill up and bring down your encoding system.  Obviously, you can’t use any sort of two-pass encoding, either.

UPDATE, 2010-01-10: see this article for more details related to high-bitrate MPEG-2 encoding.

In my tests of real-time encoding, I encountered one particular transition that was very difficult for ffmpeg to encode without artifacts.  I use this as a worst-case scenario for testing various settings of the MPEG-2 encoder.  You can see the artifacts in the following images (click on the images to see the full-size versions, where the artifacts are very obvious):

Bad Transition - Frame 3 Bad Transition - Frame 4

View the MPEG-2 clip.

Note: this example in this article uses a snapshot of the ffmpeg subversion code from September 10, 2009.

Here’s the command line I started with:

First, we’ll go through these options and then we’ll talk about what I changed to get better results.

Video options

Let’s go through the various options to control the video encoding.

This instructs ffmpeg to use MPEG-2 video encoding

For convenience, I wanted to be able to play the video in QuickTime (with the MPEG-2 Playback Component). I found that QuickTime could not play yuv422p MPEG-2 (YUV 4:2:2 Planar), but it can handle yuv420p (YUV 4:2:0 Planar)

ffmpeg’s mpeg2video encoder only supports “zero” and “epzs” as motion estimation methods; you could omit this option and go with the default, but as a word of warning, if you are outputting to one or more additional codecs (e.g. MPEG-4), you might be using another motion estimation method, and without an explicit motion estimation method specified for the mpeg2video encoder, ffmpeg will try to use the same motion estimation method used by the other codec, and it will fail.  Better to be safe here and explicitly specify the me_method.

ffmpeg’s mpeg2video encoder does not do automatic thread detection, so I set this to 4 because I’m working on a 4-core machine; you could omit this option, but if you’re outputting to one or more codecs, and you’re using -threads 0 with another codec, ffmpeg will try to use the automatic thread detection on the MPEG-2 output, and it will fail.

MPEG-2 must be either 25 or 29.97 frames per second; no other frame rates will work.

use a GOP size of 15, a very standard GOP size

Output a frame size of 704×396

2.5 Mbps with tolerance of 300k; the mpeg2video codec requires that the tolerance be “large enough” for the bitrate (so you can’t set a 10k tolerance on a 3Mbps bitrate, for example); a larger tolerance had some effect on video quality, but nothing near the -bf 2 effect.

Audio options

Now a look at the audio options:

use MPEG-1 layer II audio (you could use ac3, mp3, or libfaac instead, but that might cause some compatibility issues — I don’t believe that DVD VOBs can contain AAC audio, for example)

Output 2-channnel audio at 192Kbps and a 44100 Hz sampling rate.

Use audio/video sync method 1 (I always use this audio sync method).

Output options

Finally, have a look at the output options:

Use the VOB output format; don’t be tempted to use the mpeg2video format — you won’t get any audio track.

Improving the quality

Now lets look at how we can improve the quality, especially during that horrible transition.  The command-line options here are the result of a lot of experimentation.


Adding B-frames seemed to give the most bang for the buck.

this inserts two B-frames between each P frame; ffmpeg’s default is to use no B-frames at all; Using B-frames made very noticeable differences in video quality while also reducing file size (many artifacts were removed)


Transition - no B-frames Transition - B-frames

Sample video:

Rate distortion optimal quantization

rate-distortion optimal quantization; this cleans up the bulk of the artifacting that remained after enabling B-frames.


Transition - B-frames Transition - Trellis

Sample video:

Pel ME Compare Function

Explicitly specify the full pel me compare function, sub pel me compare function; this seems to pick up any tiny bits of artifacting after -trellis 2; important to note that on its own, this does not make the video quality improvement that -trellis 2 does.


Transition - Trellis Transition - CMP

Sample video:

GOP Size

use a GOP size of 45; this made a noticeable improvement in the quality.  The impact is comparable to the impact I saw from adding -trellis 2 to the command-line options.

I’ve seen recommendations about going up to -g 100, but I’ve also read that some decoders might have trouble with very large GOP sizes, which could make it hard/impossible to use the resulting video with some editors.


Transition - CMP Transition - GOP 45

Sample video:

Final command-line

Here is the final command I used:



2 thoughts on “Real-time MPEG-2 encoding with ffmpeg

  1. please is there a way to intergrate all you said in a web app ?
    sorry i am still a new to this and i have been given a school projet realtime streaming and i intend to use ffmpeg for realtime encoding and display it with a web app.but for the moment i am stuck after multiple reseach in the internet.
    please i realy need help

    1. This article is pretty old and really doesn’t apply to current ffmpeg versions. You also wouldn’t use MPEG2 for a streaming application.

      You want to encode to h264, and you probably want to stream via HLS, which is supported by almost all current browsers (either directly or with Javascript extensions) with the exception of MSIE 11 and below. For MSIE, you need to use RTMP streaming along with a flash-based player.

      I think this article is a good overview of how to do that.

Leave a Reply

Your email address will not be published. Required fields are marked *