Creating MP4 videos ready for HTTP streaming

H.264 in MP4

Generally, you want to create x264 video within an MP4 container. This option is supported by basically any device and browser.

The following should be enough. Make sure to replace input name and CRF options. The latter sets the quality, where sane values range from 19 to 25 – lower means better quality, but also higher bitrate:

ffmpeg -i input.avi -c:v libx264 -crf 23 -c:a aac -movflags faststart output.mp4

You can also use Handbrake for encoding if you like the GUI way.

Using the faststart option

Now, what you need to do is move the MP4 container's MOOV atom to the beginning. This atom (in essence, a unit of data in the MP4 container) will contains important metadata about the video/audio streams themselves. -movflags faststart should do exactly that.

If your FFmpeg version doesn't have this option, consider upgrading. If you cannot upgrade, you can achieve the same thing with any of the below tools:

  • QTIndexSwapper, an Adobe AIR application

  • MP4Box, free and open source, running a command similar to the following, where you can change the interval (here, 500):

    mp4box -inter 500 input.mp4

  • qt-faststart in Python, which works everywhere where Python is installed.

    qtfaststart input.mp4

That's about it.

Controlling bitrate / quality

Now, of course, for streaming you may actually want to constrain the bitrate to stay within certain bounds. You can read more about that in my blog post on rate control methods.

For example, by adding -maxrate 2M -bufsize 2M to the encoding options, you cap the encoding to 2 Mbit/s, which may be sufficient for 720p video. The required bitrate will depend, of course, on how complex the content is. This takes some trial and error.


This is an answer to last comment by you @abrahab.

You don't need to mp4box a file to be able to pseudo stream it via nginx. The MP4 streaming module takes care of it irrespective of positioning of moov atoms (mp4box shifts the moov atom to beginning of file).


Now for the 500 server error, are you using "-frag" option with mp4box? MP4 streaming module can't read fragmented MP4 files. Good use of mp4box for pseudo streaming is to interleave the videos for better seeking. Moov atom shifting is an added advantage.

I always do this to mp4box an FFmpeg-encoded file

MP4Box -add MyVideo.mp4 -isma Myvideo-box.mp4

This will also interleave the MP4 file in 500 milliseconds of chunks by default.


You can simply convert a non-streamable AVI or MP4, also without re-encoding everything, by doing this:

ffmpeg -i INPUT.mp4 -c copy -movflags faststart STREAMABLE_OUTPUT.mp4

There's no need to re-encode anything, because just the moov atom has to be moved.