8
votes

I'm having an issue will MediaElement.js (my flash video player) not playing my .m4V video files (encoded using ffmpeg) until the video is fully loaded.

I have tested this with various third party video files that appear to play straight away before they have completely loaded. Only my files do not :(

When played using the html5 video solution they play straight away, just not on the flash fallback.

Could this be to do with the settings the video is being encoded at? I don't see any other reason.

CODE:

<video id="player1" src='BriefTour.m4v' type="video/mp4" preload="none"></video>

<script>
var videoPlayer = MediaElement('player1',{
  success:function(me){me.play();}              
});
</script>

As you can see I am specifying no option, the player is on default settings.

Hope someone has encoutered this before and can help me out!

4
Hey, how are you encoding your videos or where are you sourcing them from?Kit
I'm using FFMpeg to encode them server-side.wilsonpage
Note that both Kit and John Dyers answers below work great and accomplish the same thing... just depends if you want a command line or a desktop solution.squarecandy

4 Answers

10
votes

As you are encoding your own videos and using FFmpeg, I suggest using 'qt-faststart'.

This is a useful tool included with FFmpeg that rearranges a file with H.264 video, "such that the moov atom is in front of the data, thus facilitating network streaming". Basically, it allows web movies to start playing before they are completely downloaded.

Enable it with the following the ffmpeg directory:

cd ~/ffmpeg
make tools/qt-faststart

Usage (after your ffmpeg encoding):

qt-faststart input.foo output.foo

This should allow your player to play the video while it is still downloading.

6
votes

Flash can't always play MP4s if they are not indexed in the way it wants.

To fix your file, just download this: QTIndexSwapper

2
votes

I tried qt-faststart with my own MP4 (h264+AAC) encoded files and was always getting an "last atom in file was not a moov atom" error message (and no output file). I was then assuming my files were ok and searched for the problem elsewere. After hours of testing, my assumption proved to be wrong - indeed, it seems my files had no moov-atom at all, not at the beginning nor at the end!

To succesfully fix this I used ffmpeg first to "regenerate" the file - that is, remux the original h264+AAC tracks into a new MP4 file without reencoding it:

ffmpeg -i souce_file.mp4 -acodec copy -vcodec copy target_file_1.mp4

After this, the new file should have its proper moov-atom at the end. So now you can use qt-faststart in order to move it to the beginning, as Kit explained in his answer:

qt-faststart target_file_1.mp4 target_file_2.mp4

After doing that, mediaelement plays all my videos just right after clicking on the play button, when the file starts downloading! :)

If your problem is you already have all your files in a youtube-like site, your hosting is Linux-based, ffmpeg is not there and you cannot compile it on your own, you my find it useful getting a static build of ffmpeg. You can find that here:

http://ffmpeg.gusari.org/static/ (32 bit) or here: http://dl.dropbox.com/u/24633983/ffmpeg/index.html (64 bit)

Unfortunately, on the 32-bit build I used there was no qt-faststart, not as binary nor as source code. In this case you can download it from ffmpeg SVN and compile it directly with gcc. I did it succesfully in my ultra-el-cheapo shared hosting. It doesn't seem to have any build dependencies. Or you can even try my own qt-faststart binary build and see if it works for you.

EDIT: I've just discovered that in newer versions there's no need for qt-faststart at all. You can encode directly with ffmpeg using the following option:

-movflags +faststart 
1
votes

I wanted to expand a little on John Dyer's comment and say that using QTIndexSwapper isn't just for the Flash fallback / fallfoward functionality of MediaElement.js but also works for the non-Flash player.

The problem I had was in the non-Flash player my .mp4 file was having to load the full video before it'd start playing (I didn't check the Flash version until after I had it working without Flash) and QTIndexSwapper solved the problem.

I wanted to point this out as when I first read the comment I thought it applied only to Flash and didn't try it straight away. Not that I'm taking anything away from John Dyer as it was his comment which solved my problem in the end, I just wanted to add to it so hopefully others won't make my mistake.

If anyone is interested I wrote a blog post about this problem and about a PHP class which should fix it too.