Converting RealMedia, DivX, and Windows Media WMV Videos to MPEG-4
As part of the cataloguing and overhaul of my extensive video collection I faced the issue of converting a collection of storage formats to something more universal. I was amazed at how hard it was to discover recommendations for the best formats, codecs, and settings, and how difficult getting the tools to do it was.
I’m documenting much of what I did here in case I need it again in the future, and to help others who face the same situation
I used to host my online video collection on Windows 2003 Server so I provided a streaming WMV file of low quality and a downloadable high-quality DivX-encoded (MPEG-4 Version 5) AVI.
RealMedia RM30 and RM40
In addition I needed to convert from RealMedia too, because when I first started processing my DV camcorder videos in 2000 the best codecs available were RealMedia RMV30 and RMV40.
I quickly found that there are no reliable Linux-based tools to convert from RM30. ffmpeg has a contribution as a result of a Google Summer of Code 2007 project that does process the two proprietary RealMedia formats but even though I downloaded the latest ffmpeg source-code from SVN trunk, and the subsequent build of ffmpeg could recognise the input-file video codec (RM30), it still couldn’t manage to convert it.
I then fired up a Windows XP SP2 virtual machine guest in kvm and installed VirtualDub, AVIsynth, Real Alternate, and the Xvid codec and lame mp3 codecs.
Although the guest can access the video files on the host via the network I decided to copy them into the guest before working on them.
AVIsynth is a very clever program! What it is does is very sneaky and quite unexpected. To begin with, you don’t run it, you just install it.
I created a script for AVIsynth called RealMedia.avs on the desktop containing:
video=DirectShowSource(”C:\Users\TJ\Some-RealMedia-File.rm”, convertfps=true, fps=15)
Note: convertfps=true is required if the source is variable bit rate (VBR) otherwise video runs dramatically out of synchronisation with the audio, and in my case looped at the end of the converted file about 10 times!
I started VirtualDub. Using File>Open… I selected the RealMedia.avs file.
When any program tries to open a .avs file AVISynth captures the request via a hook in the Windows file handling functions. It then reads the AVIsynth script commands inside the .avs file. The result is returned as a file stream to the requesting application, in this case VirtualDub, which thinks the stream data belongs to the .avs file - clever!
Next, in VirtualDub, I set the video options to full stream processing and compression to use Xvid, and audio options to copy source (which was un-encoded PCM mono 8kHz 16-bit).
I saved these settings using File>Save Settings… so I could reload them easily later.
To run the conversion do File>Save as AVI… and enter a file-name. I used the original name with the .avi suffix.
The thing to understand here is that for each file to be converted the RealMedia.avs script file has to be edited and the filename entered. Therefore I had it open in notepad and after each conversion changed the file-name and saved the file.
Then I’d go back to the VirtualDub File>Open… step and select RealMedia.avs again.
Note: As an alternative I copied the RealMedia.avs file so there was one for each file to be converted (filename01.avs, filename02.avs, etc.) and added them to VirtualDub's batch job list by ticking the check-box in the File>Save as AVI... dialog box. Once all were added the jobs can be run using File>Job control... which allows the jobs to be run over-night or when the PC is otherwise idle.
In the kvm virtual machine the conversion was running at about 6 frames per second so I decided to stop using the virtual machine and boot into Vista (it came with the laptop but never gets used!). I went through the process of installing the programs and codecs once again and resumed converting the files.
Note: I copied the RealMedia files to be converted into the Vista partition from Linux before booting Vista.
Once up and running in Vista VirtualDub was reporting around 80 frames per second.
Sometimes there would be crashes with suggestions of AVIsynth errors. One batch of these made me think the source videos were somehow corrupt but a simple log-out/log-in cleared things up and I was able to continue converting.
Once done I rebooted into Linux for the AVI to MP4 step.
Converting from AVI to MPEG-4 container with MPEG-4 part 2 (xvid) video and MP3 audio
I now had MPEG-4 part-2 (xvid) in an AVI container so ffmpeg could handle the rest of the job.
To convert to a standard MPEG-4 (mp4) container with MPEG-4 part 2 (xvid) video and MPEG-1 level 3 (mp3) audio I processed each file with the command line:
ffmpeg -threads 2 -f mp4 -i <filename-xvid.avi> -vcodec mpeg4 -b 150k \ -acodec libmp3lame \ -copyright '<copyright message>' -year <year> -author '<author>' -album '<album>' -title '<title>' \ -y <filename-xvid-mp3.mp4>
I used 150k video bit-rate since the original RealMedia videos were 15 fps, 320×288 and relatively low quality. This kept the final file-size down, too.
After the RealMedia-sourced low quality files were processed I moved on to the higher-quality higher-resolution (720 x 576) AVIs encoded using the DivX MPEG-4 version 5 codec and ADPCM stereo audio.
The command line here was similar:
ffmpeg -threads 2 -f mp4 -i <filename-divx.avi> -vcodec mpeg4 -sameq \ -acodec libmp3lame \ -copyright '<copyright message>' -year <year> -author '<author>' -album '<album>' -title '<title>' \ -y <filename-xvid-mp3.mp4>
Note: sameq was necessary to preserve the original video quality. It has the effect of maintaining the source’s variable bit rate. I tried various fixed bit-rates right up to 1500k without getting acceptable quality.
Converting from AVI to MPEG-4 container with MPEG-4 part 10 (h.264) video and AAC audio
The file sizes of the mp4 MPEG-4 part 2 (xvid) files were often more than twice the size of the original DivX AVI files so I decided to look at using the latest MPEG standard, h.264 video and AAC audio.
ffmpeg -threads 2 -f mp4 -i <filename-divx.avi> -vcodec libx264 -sameq \ -acodec libfaac \ -copyright '<copyright message>' -year <year> -author '<author>' -album '<album>' -title '<title>' \ -y <filename-h264-aac.mp4>
Here’s an example of the file size differences. It is clear that h.264 is much better than xvid, although I’m unsure why it is still so much bigger than the DivX original.
46M 2004-05-16 17:20 Veranda-Squirrel.divx.avi 155M 2008-02-01 17:45 Veranda-Squirrel-xvid-mp3.mp4 63M 2008-02-01 18:01 Veranda-Squirrel-h264-aac.mp4
So finally all my high-quality videos are and will be MPEG-4 using h.264 and AAC codecs, which should future-proof me for some time to come.
Note: ffmpeg must have been configured and built with support for the codecs to be used. When it runs it reports the configure options used. This is the report from my newly-built ffmpeg:
FFmpeg version SVN-r11697, Copyright (c) 2000-2008 Fabrice Bellard, et al. configuration: –enable-gpl –enable-nonfree –enable-pp –enable-swscaler –enable-pthreads –enable-libvorbis –enable-libtheora –enable-libgsm –enable-libdc1394 –disable-debug –enable-libmp3lame –enable-libfaadbin –enable-libfaad –enable-libfaac –enable-libxvid –enable-libx264 –enable-liba52 –enable-libamr_nb –enable-libamr_wb –enable-shared –prefix=/usr/local –extra-cflags=-I/usr/local/include –extra-ldflags=-L/usr/local/lib
If during conversion to h.264 (using libx264) you see OVERFLOW or UNDERFLOW errors similar to these:
[libx264 @ 0×2ba1144258a0]OVERFLOW levelcode=43772 bitrate= 7.0kbits/s [libx264 @ 0×2ba1144258a0]OVERFLOW levelcode=4377 [libx264 @ 0×2ba1144258a0]OVERFLOW levelcode=4377.8 bitrate= 6.3kbits/s [libx264 @ 0×2ba1144258a0]OVERFLOW levelcode=4377 [libx264 @ 0×2ba1144258a0]OVERFLOW levelcode=4377.6 bitrate= 6.0kbits/s [libx264 @ 0×2ba1144258a0]OVERFLOW levelcode=4377
you need to add the ffmpeg option -qmin to cause ffmpeg to pass a rationale VBR quantization minimum. I used -qmin 10:
ffmpeg -threads 2 -f mp4 -i <filename-divx.avi> -vcodec libx264 -sameq -qmin 10 \ -acodec libfaac -copyright '<copyright message>' -year <year> -author '<author>' -album '<album>' -title '<title>' \ -y <filename-h264-aac.mp4>
Here’s a technical note from the author of libx264 explaining it in double-dutch:
When encoding CAVLC in Baseline or Main profile, there is a limit on the size of any one DCT coefficient. This limit can only be reached with very low QP or with extreme quantization matrices, so it shouldn’t normally be a problem, but ffmpeg has lousy defaults (such as min QP=2) which allow such extreme cases.