MP4 for Flash in Linux

Flash version 9 can play mp4 streams. This document describes how to transcode an arbitrary video file to an mp4 file suitable for streaming to a web browser.

Linux needs about 3 times the processing speed to play movies using the web browser then using a stand-alone movie player such as vlc or mplayer. I have heard that the Flash player in Windows is more efficient.

Required Software

The software required is

The H264 Video Stream

To transcode the file p.mpg into an h264 encoded file ps.264 use the commands
$ ffmpeg -i p.mpg -deinterlace -f yuv4mpegpipe -pix_fmt yuv420p \
    -s 640x360 -y /dev/stdout |
  y4mtoyuv |
  x264 --fps 30000/1001 --sar 1:1 --pass 1 --bitrate 512 \
    --stats p.stats --level 4.1 --keyint 14 --min-keyint 2 \
    --ref 3 --mixed-refs --bframes 2 --b-adapt 2 --weightb --direct auto \
    --deblock -1:-1 --subme 7 \
    --trellis 2 --partitions p8x8,b8x8,i4x4,i8x8 --8x8dct \
    --ipratio 1.1 --pbratio 1.1 \
    --vbv-bufsize 14475 --vbv-maxrate 17500 --qcomp 0.5 \
    --me umh --threads auto --progress --no-psnr \
    --no-ssim --output ps.264 /dev/stdin 640x360 \
    --mvrange 511 --aud --nal-hrd
As an asside, changing the resolution to 720x480, the aspect ratio to --sar 32:27 and the bitrate to --bitrate 768 yields a standard definition h264 video file that can be multiplexed with an ac3 audio stream and burned to HD-DVD or Blu-ray. Using these bitrates more than 50 hours of standard definition video will fit on one 25GB Blu-ray disk. More information about HD-DVD and Blu-ray may be found at H264 HD Video Workflow.

The AAC Audio Stream

To encode the audio file use the commands
$ ffmpeg -i p.mpg -ab 48k -ar 22050 -acodec libfaac -y ps.aac

Multiplex the Audio and Video

To multiplex the video and audio together in the ISO Media, MPEG v4 system, version 2 format suitable for streaming video use the commands
$ MP4Box -new -add ps.264 -add ps.aac \
    -fps 29.97002997002997002997 -isma ps.mp4
The flag -isma is used to select the version 2 format.

Making Thumbnails

When placing a video on a website, it is useful to represent it with a thumbnail image. Find a representative frame in the video using
$ mplayer -vf screenshot ps.mp4
and press the "s" key when the frame is displayed. I used gimp to rescale the vertical height of the frame grab to 120 pixels, crop the width to 160 pixels and to save it as a jpg image. The result was a 4:3 aspect ratio jpg thumbnails with a resolution of 160x120.

Videos on the Webserver

This example assumes the directories /movies and /java have been created at the root level on the webserver. Download the JW FLV Media Player and unpack mediaplayer.zip into the /java directory. Place the mp4 video and jpg thumbnails in the /movies directory. Now make a file called playlist.xml and place it in the /movies directory with the video files.

Suppose there are two videos bellacat.mp4 and bellamo.mp4 with thumbnails bellacat_s.jpg and bellamo_s.jpg in the /movies directory. A playlist for these videos is given by

<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
    <head>
        <meta name="title" content="Bella's Playlist"/>
    </head>
    <body>
        <seq>
            <par>
                <audio
                    title="Bella and the Cat"
                    src="/movies/bellacat.mp4"
alt="Bella the poodle puppy plays with the cat next door."
                />
                <img src="/movies/bellacat_s.jpg"/>
            </par>
            <par>
                <audio
                    title="Bella and Mo"
                    src="/movies/bellamo.mp4"
alt="Bella the poodle puppy plays with Mo the dachshund/terrier."
                />
                <img src="/movies/bellamo_s.jpg"/>
            </par>
        </seq>
    </body>
</smil>
Absolute paths must be used to specify the location of the videos and thumbnails even though playlist.xml is already in the /movies directory.

Embedding the Player

There is a setup wizard on the www.longtailvideo.com website that can be used to generate code to embed the JW FLV Media Player on a webpage. When I wrote this, the setup wizard was incompatible with the version of swfobject.js packed in mediaplayer.zip. One option is to downgrade swfobject.js to version 1.5 so the code generated by the setup wizard works. A second option is to use different code. I chose the second option.

To embed the media player with swfobject.js version 2.1 on a webpage use

<script type="text/javascript" src="/java/swfobject.js"></script>
<script type="text/javascript">
    swfobject.registerObject("rmplayer","9.0.98","/java/expressInstall.swf");
</script>
<object id="rmplayer" classid="clsid:0096fbd585b2d0a71e0f0030b2bfa194"
        name="rmplayer" width="640" height="679">
    <param name="movie" value="/java/player.swf" />
    <param name="allowfullscreen" value="true" />
    <param name="allowscriptaccess" value="always" />
    <param name="flashvars" 
        value="file=/movies/playlist.xml&playlistsize=300&playlist=bottom" />
    <object type="application/x-shockwave-flash" data="/java/player.swf"
        width="640" height="679">
        <param name="movie" value="/java/player.swf" />
        <param name="allowfullscreen" value="true" />
        <param name="allowscriptaccess" value="always" />
        <param name="flashvars" 
            value="file=/movies/playlist.xml&playlistsize=300&playlist=bottom" />
        <p><a href="http://get.adobe.com/flashplayer">Get Flash</a>
            to see this movie.</p>
    </object>
</object>
where classid="clsid:0096fbd585b2d0a71e0f0030b2bfa194" and id="rmplayer" are unique identifiers on the webpage. The width of the video is 640. Therefore, the width of the media player should be 640 pixels. The height of the video is 360, the playbar is 19 and the playlist is 300. Therefore, the height of the media player should be 679 pixels.

It seems redundant for the parameters to appear twice; however, Internet Explorer reads one set and Firefox reads the other. Note also that absolute paths must again be used to specify the location of the java files and the playlist.

An example of video encoded with the techniques above appears on Bella's Homepage.

Concluding Remarks

The files encoded with x264 are superior from an efficiency point of view to files simply encoded with a command like
$ ffmpeg -i p.mpg -deinterlace -s 512x288 -ab 48k -ar 22050 -b 512k -y p.flv
Surprisingly, JW FLV Media Player version 4.5.203 with Flash version 9 enjoys smoother playback of mp4 files than the flv files on my Linux system.

Recent versions of Firefox will natively play ogg Theora video files. A method of creating a web page that displays video in any browser is described at Video for Everybody.


Last Updated: Sun Mar 27 22:20:34 PDT 2011