smorgasbork

 
  • Increase font size
  • Default font size
  • Decrease font size

Real-time MPEG-2 encoding with ffmpeg

E-mail Print

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:

ffmpeg -i test.mp4 \
    -vcodec mpeg2video -pix_fmt yuv420p -me_method epzs -threads 4 \
    -r 29.97 -g 15 -s 704x396 -b 2500k -bt 300k \
    -acodec mp2 -ac 2 -ab 192k -ar 44100 \    
    -async 1 \    
    -y \    
    -f vob output.mpg

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.

-vcodec mpeg2video

This instructs ffmpeg to use MPEG-2 video encoding

-pix_fmt yuv420p

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)

-me_method epzs

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.

-threads 4

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.

-r 29.97

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

-g 15

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

-s 704x396

Output a frame size of 704x396

-b 2500k -bt 300k

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:

-acodec mp2

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)

-ac 2 -ab 192k -ar 44100

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

-async 1

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

Output options

Finally, have a look at the output options:

-f vob 'test-vob-b3000-bt500-704x396-yuv420p-g45-bf2-trellis2-cmp2.mpg'

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.

B-frames

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

-bf 2

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)

Stills:

Transition - no B-frames Transition - B-frames

Sample video:

Rate distortion optimal quantization

-trellis 2

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

Stills:

Transition - B-frames Transition - Trellis

Sample video:

Pel ME Compare Function

-cmp 2 -subcmp 2

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.

Stills:

Transition - Trellis Transition - CMP

Sample video:

GOP Size

-g 45

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.

Stills:

Transition - CMP Transition - GOP 45

Sample video:

Final command-line

Here is the final command I used:

ffmpeg -i test.mp4 \
    -vcodec mpeg2video -pix_fmt yuv420p -me_method epzs -threads 4 \
    -r 29.97 -g 45 -bf 2 -trellis 2 -cmp 2 -subcmp 2 -s 704x396 -b 2500k -bt 300k \
    -acodec mp2 -ac 2 -ab 192k -ar 44100 \    
    -async 1 \    
    -y \    
    -f vob output.mpg


 

 

Comments

avatar Michael Orton
Hi,

Nice explanation of what the options do, and a lot of work! Something I've notice, which you dont mention is that trellis=2 seems to generate blockiness on the face of the weather presenter a few frames after the intro logo has vanished. Can't see any obvious reason for this, and wondering if its a result of re-encoding a decoded mpeg2 stream (which I'm assuming the off-air feed is). Your thoughts? Do you see it?
Name *
Email
Code   
ChronoComments by Joomla Professional Solutions
Submit Comment
Cancel
avatar Jason
A lot of that pixelation is there with the default trellis setting, too. It's possible that trellis=2 is making it a little bit worse. I don't know why that would happen. I don't think it's related to re-encoding -- the source video was either uncompressed or it was 100Mbps 1080i video, so any compression on the source video would have been more or less undetectable (although I understand that algorithms may react unexpectedly to patterns in the data resulting from *any* compression). But my gut tells me that's not what's going on.

Frankly, after reviewing my sample video, I don't see a whole lot of improvement from trellis=2. But when I wrote this, I was looking very closely at all frames of the video, not just the transition and post-transition frames. I guess I saw something then that I liked.
Name *
Email
Code   
ChronoComments by Joomla Professional Solutions
Submit Comment
Cancel
Name *
Email
Code   
Submit Comment