FFmpeg – How to Make a High-Quality MPEG2 Video File

ffmpegmicrosoft-powerpointmpeg2videovideo conversion

I have got a WMV (v9 (WMV3), 960×720, 30.000030 fps, planar 4:2:0 YUV, produced by PowerPoint 2010) file and need to convert it to MPEG2 – the only format my TVset can read from an USB flash drive (I have also tried MP4/h.264, AVI/XVID – nothing but MPEG2 works).

I have managed to to the job with simple

ffmpeg -i "in.wmv" -c:v mpeg2video "out.mpg"

but the quality of the result is dreadful (clearly visible visual distortions are introduced) and the playback is not smooth (too slow at some moments).

I have also tried

ffmpeg -i "in.wmv" -c:v mpeg2video -pix_fmt yuv420p -me_method epzs -threads 4 -r 30.000030 -g 45 -bf 2 -trellis 2 -cmp 2 -subcmp 2 -s 960x720 -b 2500k -bt 300k -async 1 -y "out.mpg"

(I have found this somewhere in the Internet and modified a little bit – changed the resoultion, the refresh rate and the output format (from VOB to bare MPG)) succesfully but the quality is still too bad.

What parameters do I have to use to save as much quality as possible? Compression ratio doesn't matter at all, even increase in file size is acceptable.

Anther thing I actually need (I have chosen not to include it in the question title to avoid making it too specific but I'd appreciate it being considered in the answers) is adding pure silence as a sound track – there is no sound in the original but the TV set complains about it and I'd like to get rid of this complain. I have generated a same-length (second-precise) silence OGG Vorbis file using Audacity but I can't manage to merge it with the video:

ffmpeg -i in.mpg -i silence.ogg -c:v copy -c:a libmp3lame out.mpg

and even bare

ffmpeg -i in.mpg -c:v copy -out.mpg

gives "buffer underflow" and "packet too large" errors. (in.mpg are the files produced by the same FFMPEG binary and the same source WMV file using the first two commands in the question).

I am using a Zeranoe FFMPEG build on Windows 7.

Best Answer

The problem is that the default bitrate for the MPEG-2 is rather low (as with most other video encoders in ffmpeg, the H.264 one being an exception). MPEG-2 is also not the best choice as a codec these days.

Better quality for MPEG-2

You have a few options if you want to stick with MPEG-2:

  • Increase the bitrate. You're now using -b:v 2500k. If it's HD video, you will not get far with only 2.5 MBit/s. You need at least double that or even more to make the result look good. For example, use -b:v 6000k -target pal-dvd.

    For 720p, I think that you should still use a higher bitrate. Remember that DVDs use MPEG-2 and come in about 4.7 GB for 2hrs of movie, so you end up with around 5–8 MBit/s. MPEG-2 is really not very compression-efficient and works better at higher bitrates.

  • Use a specific quality setting. Change -b:v … to -qscale:v 2. The number here ranges from 1 to 31 and higher means lower quality. There's no point going beyond 4 or 5. If you don't care for the bitrate start with 2 and see if that works for you.

Messing with the number of B-frames, motion estimation method or GOP size may tweak the quality a little but won't result in big changes.

Silent audio

Use -f lavfi -i aevalsrc=0 to generate a silent audio stream. For example:

ffmpeg -i "in.wmv" -f lavfi -i aevalsrc=0 -shortest -c:v mpeg2video -qscale:v 2 -c:a libmp3lame "out.mpg"

You may need to add -target pal-dvd to the above command to force a certain buffer size.

I chose MP3 as codec. MPEG files cannot contain audio other than MPEG Layer I and II audio as well as PCM streams, so using a silent Ogg Vorbis file will not work unless you convert the audio stream as well (which is not what you're doing when you use -c:a copy).

Use a different video codec

I'm surprised that a TV that plays video files will read MPEG-2 but not anything else. At least MPEG-4 Part II video should be supported (that's what you know as "DivX" – an MPEG-4 Part II encoder). So you could try:

ffmpeg -i "in.wmv" -f lavfi -i aevalsrc=0 -shortest -c:v libxvid -qscale:v 2 -c:a libmp3lame "out.mp4"

Your TV might actually also support H.264, but only a certain profile. Try using the baseline profile, for example:

ffmpeg -i "in.wmv" -f lavfi -i aevalsrc=0 -shortest -c:v libx264 -profile:v baseline -crf 23 -c:a aac -strict experimental "out.mp4"

In the above example I've used the CRF option to set the quality instead of qscale. See the H.264 encoding guide for more.