Understanding the MPEG-4 moov atom: Pseudo-Streaming in Mp4
This article is targeted to anyone who is looking to deliver Mp4 videos over internet. It provides technical details about the metadata that can hamper good encoding and delivery, causing poor playback performance.
An atom is a self-contained data unit containing information about the video file. The moov atom, aka movie atom, defines the timescale, duration, and display characteristics of the movie, as well as sub-atoms containing information for each track in the movie. The optimal location of the moov atom depends on the selected delivery method. This article explains the details around moov atom, and how to properly place it for Mp4 streaming over HTTP.
There are two major methods for video delivery in current age of ‘cord-cutters’, ‘cord-nevers’, short-videos and binged-watched content: progressive download and chunked streaming. Regardless of the method you choose, the experience for viewers is very similar. Your choice depends on your budget, the player you are using, and the type of content e.g. short user-generated videos Vs movies (I will not be talking about the ‘level of content protection needed’ in this article). In this article I will explain the importance of moov atom structure from the perspective of progressive download of Mp4 videos.
The progressive download method downloads and caches video on the viewer’s device. A short period of time is required to buffer and cache the beginning of the media file before it starts playing. Your player can calculate an appropriate buffer time based on the rate the data is being received and the total length of the video. Once the video has been cached, subsequent viewing does not require any buffering. Generally you would use a content delivery network (CDN) using the standard HTTP protocol to deliver these videos. While this method is efficient when used through CDN for delivery, there is yet another detail to be considered to make the whole playback experience smooth for your end user, called pseudo-streaming which is still progressive download but with a twist.
So, what is pseudo-streaming? It is simply a video that can play while it’s being downloaded i.e. it can start playing even before its completely downloaded.
So, in essence the ‘progressive download method used for a video that can play faster’, hence this has to do with your content packaging/ encoding.
Stream packaging is the process of making a multiplexed media file. Also known as muxing, this procedure combines multiple elements that enable control of the distribution delivery process into a single file. Some of these elements are represented in self-contained atoms.
An atom is a basic data unit that contains a header and a data field.
The header contains referencing metadata that describes how to find, process, and access the contents of the data field, which may include (but is not limited to) the following components:
Video frames, Audio samples, Interleaving AV data, Captioning data, Chapter index, Title, Poster, User data, Various technical metadata: codec, timescale, version, preferred playback rate, preferred playback volume, movie duration, etc.
What’s important for pseudo-streaming is that the file metadata (the moov atom) should be at the start of the file rather than at the end. Usually this is an option set when encoding the file (called quick start or fast start).
The moov atom
In an MPEG-4-compliant container, every movie contains a moov atom. Normally, a movie atom contains a movie header atom (an mvhd atom) that defines the timescale and duration information for the entire movie, as well as its display characteristics. The movie atom also contains one track atom (a trak atom) for each track in the movie. Each track atom contains one or more media atoms (an mdia atom) along with other atoms that define other track and movie characteristics.
In this tree-like hierarchy, the moov atom acts an index of the video data. It is here that the MPEG-4 muxer stores information about the file to enable the viewer to play and scrub the file. The file will not start to play until the player can access this index.
Unless specified otherwise, the moov atom is normally stored at the end of the file in on-demand (VoD) content, after all of the information describing the file has been generated. Depending on the type of on demand delivery method selected-progressive download, streaming, or local playback-the location will need to move either to the end or to the beginning of the file.
Since our use case is progressive download or streaming over HTTP, the moov atom will have to be moved to the beginning of the file. This ensures that the required movie information is downloaded first, enabling playback to start right away. If the moov atom is located at the end of the file, it forces the download of the entire file first before it will start playback.
The placement of the moov atom is specified in various software packages through settings such as “progressive download,” “fast start,” “use streaming mode,” or similar options. Software packages such as MP4creator or AtomicParsley enable you to analyze the location of the moov atom in your encoded files. And if you are using ffmpeg, you can do something like
ffmpeg -v trace -i videofile.mp4 2>&1 | grep -e 'mdat' -e 'moov'
This will produce an output like,
[mov,mp4,m4a,3gp,3g2,mj2 @ 000000000036ca40] type:'mdat' parent:'root' sz: 62740 48 65044 [mov,mp4,m4a,3gp,3g2,mj2 @ 000000000036ca40] type:'moov' parent:'root' sz: 2264 62788 65044
Since moov appears second, it is at the end of the file in this example and hence would require moving to start in the interest of the streaming playback experience.
Some tools enable relocation of the moov atom to the beginning of the file’s structure through post processing of the compressed MPEG-4 (MP4) file. One such tool is MP4Creator, mentioned earlier, and another is MP4 FastStart. The best way to handle the moov atom location, however, is to set it during the compression and muxing portion of the encoding process. This minimizes the probability of the moov atom inadvertently being placed at the end.
Importance of moov atom Location
As explained earlier, positioning the moov atom at the beginning of the file structure expedites the playback experience and access to the data payload for decoding and presentation by the player. In case of progressive download, the moov atom data must be received before playback can begin.
Another important reason for having the moov atom at the beginning relates to the file, player, and CDN relationship in streaming. When the user requests a video asset, player requests a “range” at the beginning of the file to get the metadata. If metadata is stored at the end of the file, it then requests a range at the end of the file where metadata is stored, and then it requests the file from the beginning again. Since range requests can overlap, this process of back-and-forth requests may cause rebuffering. This is especially true if the user is watching video randomly or in small segments instead of the entire video from start to finish. Therefore, always encoding or muxing files with the moov atom at the beginning is recommended to avoid rebuffering caused by moov atom location.
moov atom Location and Placing it Properly
Now let’s talk about a scenario where you already have video archive and want to check if it is ‘fit’ to be streamed over HTTP as progressive download.
There are many references and tools that you can use to handle moov atom. In this example I am going to use
mediainfo — a lib readily available or downloadable on Linux systems.
Use the following command to check if media is streamable, which would produce an output like the screenshot below (Figure 2):
find .-name "*.m*" -type f | (while read FN; do echo "$FN:$(mediainfo"--Inform=General;IsStreamable: %IsStreamable%" "$FN")"; done)
If files show
IsStreamable: No, you can either re-encode or use a utility to move the moov atom.
- Re-encoding takes much longer than using a utility to move the Moov Atom so here’s how we will do it:
- Create new video files with correct config:
for FILE in `find . -type f ` ; do NEWFILE=`echo “$FILE” | sed ‘s/.mp4/_NEW.mp4/g’` ; qt-faststart “$FILE” $NEWFILE ; done
- New files will have ‘_NEW’ in the name
2. Validation: Reverse grep to find old file list: ls | grep -v ‘_NEW’
- If you have other files in the same folder, use the -E in grep and add more extension in search that you want to exclude from reverse-search e.g.: ls | grep -vE ‘_NEW|.jpg|.png|other name/ext in your folder’
3. Delete old Mp4 files, leaving new Mp4s:
for FILE in `ls | grep -v ‘_NEW’` ; do rm $FILE ; done
4. Rename new Mp4s and remove ‘_NEW’ from the name
for FILE in `find . -type f ` ; do NEWFILE=`echo “$FILE” | sed ‘s/_NEW.mp4/.mp4/g’` ; mv “$FILE” $NEWFILE ; done
If you check for the
IsStreamable status now, it should show ‘Yes’:
Hope this article helped you to start with your Mp4 delivery workflow quickly.
PS: If you liked the article, please support it with claps 👏. Cheers