Why Won’t my mp4 Play on Windows?!

If you’ve never asked this question before then you’ve never tried to convert a captured .avi file to a .mp4 and play it in Windows Media Player – it’s that simple.

I have some home videos I shot years ago using a Hitachi VM-E635LA 8mm camcorder. It was a nice camera in its day but its day is long past. I also have a Canopus ADVC 1394 720p capture card installed in my media center PC. It took me the better part of a Saturday googling and messing around to figure out how to get VirtualDub to capture raw video files from the camcorder without audio sync/speed problems in the resulting AVI (Audio/Video Interleave) file.

Sidebar: Capture Setup

  1. Open VirtualDub and select File | Capture AVI… from the menu.
  2. Select File | Set capture file… (F2) and give the output file a name.
  3. Select the device in the Device menu – the Canopus card uses a standard Windows capture card driver that shows up in this list – and in Device Manager – as “AVC Compliant DV Tape Recorder/Player (DirectShow)”.
  4. Select Video | Overlay from the menu (Preview doesn’t work with this driver).
  5. Select Audio | Enable audio capture and ensure the audio device is properly selected at the bottom of that menu – I used the capture card’s audio channel, so I selected “Capture device” (presumably meaning the video capture device).
  6. Select Capture | Timing… and here’s the trick to getting the audio to remain in sync with the video and not speed up and slow down as the video progresses – uncheck “Drop frames when captured frames are too close together” and “Insert null frames when captured frames are too far apart”. Also select do not resync between audio and video streams in this dialog box.
  7. Press F6 to start the capture, while simultaneously pressing the play button on the camcorder. Let it run till the show is over. Then press ESC to exit the capture and finalize the output file.

See, here’s the thing – the camcorder is basically a VCR (when running in playback mode). VCR’s are notorious for having (sometimes wildly) varying frame rates during playback. Hence, VirtualDub will drop frames and insert null frames – lots of them. Unfortunately, when it drops frames, it tries to speed up the audio to keep it in sync with the remaining frames, so you’re watching your captured video and suddenly your wife’s and children’s voices go up or down an octave.

On the other hand, if you don’t drop or insert frames and you don’t attempt to resync the audio to the video, the camcorder is pretty darn good at sending across exactly the sound that’s supposed to go with each frame of video captured. The moral? Don’t mess – just let it all happen at its own speed and it works just fine.

Why make this a sidebar? Because chances are good these instructions won’t work for you. You’d need a similar capture card and Canopus is not even a company anymore (though you can get some of their higher-end products from Grass Valley – a subsidiary of Belkin – who bought Canopus back in ’05).  Popular USB capture devices today can be had on eBay for 5 bucks or less and are known by a variety of names such as “EasyCAP”. The configuration for using these devices is significantly different from using a PCIe capture card. You can still get PCIe capture cards but they target high-end broadcast media and are kinda pricey.

End of Sidebar.

Now, where was I – oh yeah – we were talking about why you can’t convert these AVI files to mpeg4 and play them on Windows Media Player (WMP). Now, don’t get me wrong – I don’t really think WMP is the ultimate home theater experience. But when my mother wants to watch my newly digitized home videos, I don’t want her to have to download VideoLAN or some other third party player based on ffmpeg. I want her to be able to double-click the file and have it play, and on Windows, that’s WMP. (The same problem occurs on Mac OS, by the way, so wipe that smirk off your faces QuickTime users.)

It’s not really strange to me that you might stumble across a combination of settings in ffmpeg that actually don’t work on WMP or QuickTime – there are about a bazillion settings – and that’s just the settings for ffmpeg’s h.264 plugin library. What’s really strange is that no  one else seems to have these issues. Which is why I’m writing this post today.

I did eventually find a StackExchange (SuperUser) article that solved the issue for me.  It just took a couple of hours of sifting through answers like, “WMP can’t play mp4’s fool – get a real media player like VLAN.” Well, that was news to me – according to Microsoft, WMP version 12 should be able to play them – and version 12 is available for Windows 7 and up. Everyone with automatic updates enabled probably has it.

WMP can play mp4 files – the problem, as it happens, is that Microsoft’s definition of mp4 is a lot more strict that libx264’s definition. In the ffmpeg world, there are myriad discussions about “legacy” and “outdated” players. Turns out this world considers the latest versions of WMP and QuickTime to be outdated players (and in fairness to Apple, QuickTime 9 is officially in end-of-life status). All this really means is that you have to use a few settings to ensure the video stream generated by ffmpeg is compatible with WMP.

Here’s my command line for using ffmpeg to convert a captured AVI file to an mp4 file that WMP and QuickTime can play:

c:\> ffmpeg -i captured.avi -vf yadif -c:v libx264 -crf 23 ^
 -pix_fmt yuv420p -preset medium -c:a aac -b:a 128k -ac 1 output.mp4

Arguments:

-i <input-file>    - input file
-vf yadif          - "yet another deinterace filter"
-c:v libx264       - the video codec to use
-crf 23            - constant rate factor - 23 is the default
-pix_fmt yuv420p   - pixel format
-preset medium     - compression speed
-c:a aac           - audio codec to use
-b:a 128k          - audio bitrate
-ac 1              - audio channels

Many of these are self-explanatory, but there are a few odd ones, and at least one that makes all the difference with our favorite “legacy” players. Some of the more esoteric ones include the de-interlace filter. Let’s face it – any video captured from a VCR or camcorder is going to be interlaced. It’s so obvious you can literally see it in the content while it’s playing – and it’s annoying.

The other one that you might find strange is -ac 1. Why am I only allowing one audio channel? Because my camcorder only has one audio channel – even if you patch it into both left and right inputs on the capture card, all you’re getting is expensive mono. By telling ffmpeg to encode mono, you get the exact same effect in half the space.

The magic h.264 argument is -pix_fmt yuv420p. Most 8mm camcorders recorded data using a pixel format of yuv411 or 422 because the data fits better on the tape that way. After all, it was the camcorder designers that invented these formats. ffmpeg likes to keep things the same unless you tell it otherwise. And it seems WMP believes that any mp4 file containing video with a pixel format other than yuv420p is not worth playing. Strange attitude coming from a forward-thinking company like Microsoft… (I know that sounds totally facetious – and it was intended to, but… I’m kinda half serious, too.)