Encode h.264 and WebM videos for MediaElement.js using FFmpeg

I recently added a video player to a client’s site. I found John Dyer’s MediaElement.js to be an excellent solution for doing this. As long as you provide both an h.264 and WebM encoded version of the video, it will play natively on almost all browsers. For unsupported browsers it will fall back to Flash.

The client’s videos were all wmv’s, so they would need to be converted to h.264 and WebM. Luckily John also provided some directions for encoding to these formats using FFmpeg:

http://johndyer.name/ffmpeg-settings-for-html5-codecs-h264mp4-theoraogg-vp8webm/

Unfortunately FFmpeg has changed since the commands were published, so some slight modifications were required. I also made some modifications so that the aspect ratio of the video was preserved and to encode the video at a lower bit rate and faster speed.  As well, some of the videos being converted were really short, and would be finished before the 10 second mark that the thumbnail is created at. To solve this problem I modified the script to attempt to capture the thumbnail at the 1, 2, 3, 5 and 10 second mark – with each successful capture overwriting the last.

Here’s the updated batch file that I used:


REM mp4 (H.264 / AAC)
"c:\program files\ffmpeg\bin\ffmpeg.exe" -y -i %1 -vcodec libx264 -pix_fmt yuv420p -vprofile high -preset fast -b:v 500k -maxrate 500k -bufsize 1000k -vf scale=trunc(oh*a/2)*2:480 -threads 0 -acodec libvo_aacenc -b:a 128k %1.mp4

REM webm (VP8 / Vorbis)
"c:\program files\ffmpeg\bin\ffmpeg.exe" -y -i %1 -vcodec libvpx -quality good -cpu-used 5 -b:v 500k -maxrate 500k -bufsize 1000k -vf scale=trunc(oh*a/2)*2:480 -threads 0 -acodec libvorbis -f webm %1.webm

REM jpeg (screenshot at 10 seconds, but just in case of a short video - take a screenshot earlier and overwrite)
"c:\program files\ffmpeg\bin\ffmpeg.exe" -y -i %1 -ss 1 -vframes 1 -r 1 -vf scale=trunc(oh*a/2)*2:480 -f image2 %1.jpg
"c:\program files\ffmpeg\bin\ffmpeg.exe" -y -i %1 -ss 2 -vframes 1 -r 1 -vf scale=trunc(oh*a/2)*2:480 -f image2 %1.jpg
"c:\program files\ffmpeg\bin\ffmpeg.exe" -y -i %1 -ss 3 -vframes 1 -r 1 -vf scale=trunc(oh*a/2)*2:480 -f image2 %1.jpg
"c:\program files\ffmpeg\bin\ffmpeg.exe" -y -i %1 -ss 5 -vframes 1 -r 1 -vf scale=trunc(oh*a/2)*2:480 -f image2 %1.jpg
"c:\program files\ffmpeg\bin\ffmpeg.exe" -y -i %1 -ss 10 -vframes 1 -r 1 -vf scale=trunc(oh*a/2)*2:480 -f image2 %1.jpg

I also created a seperate batch file that will iterate over all wmv’s in a given directory and run the encoder batch against each file:


for /r %1 %%i in (*.wmv) do "c:\program files\ffmpeg\CreateWebVideos.bat" %%i


Posted

in

by

Comments

7 responses to “Encode h.264 and WebM videos for MediaElement.js using FFmpeg”

  1. Mike Avatar
    Mike

    It’s probably just a typo in your batch file, but I think you mean (H.264 / AVC) rather than ACC. If this is the biggest problem either of us run into, we’re in good shape. Thanks for this!

    1. Chris Coulson Avatar

      Thanks for pointing that out. It’s actually supposed to be AAC (for the audio codec used). I’ve updated the post.

  2. Dan Avatar
    Dan

    Hi Chris, great article! It helped me to get started with webm encoding.

    I couldn’t figure out why my webm videos would play on Firefox and Chrome, but not Android, so I did some testing and analysis and discovered that the formula for resizing would only work for my Android S3 if the formula was: scale=trunc(oh*a/16)*16:x where x is a multiple of 16.

    I may be incorrect, but it seems to be consistent in my results.

    I hope this helps some peeps out!

  3. Peter Avatar
    Peter

    For image thumbnails. Your sample means that ffmpeg must load video file each time it will generate image thumbnail from it. This can be expensive on memory consumption. There is another way to extract multiple image thumbnails from video at once. Sample: https://trac.ffmpeg.org/wiki/Create%20a%20thumbnail%20image%20every%20X%20seconds%20of%20the%20video

  4. Peter Avatar
    Peter

    For backup, example (from that web site):

    This will create one thumbnail image every minute, named img001.jpg, img002.jpg, img003.jpg, … (%03d means that ordinal number of each thumbnail image should be formatted using 3 digits)

    ffmpeg -i myvideo.avi -f image2 -vf fps=fps=1/60 img%03d.jpg

  5. Faron Coder Avatar
    Faron Coder

    Hello —

    For those who use unix based ffmpeg – here’s the corresponding to author’s codes (above) in name of unix.

    ffmpeg -y -i $fileid -vcodec libx264 -pix_fmt yuv420p -vprofile high -preset fast -b:v 500k -maxrate 500k -bufsize 1000k -vf “scale=trunc(oh*a/2)*2:480” -threads 0 -acodec libvo_aacenc -b:a 128k “$file.mp4” < /dev/null

    ffmpeg -y -i $fileid -vcodec libvpx -quality good -cpu-used 5 -b:v 500k -maxrate 500k -bufsize 1000k -vf "scale=trunc(oh*a/2)*2:480" -threads 0 -acodec libvorbis -f webm "$file.webm" < /dev/null

    ffmpeg -y -i $fileid -ss 1 -vframes 1 -r 1 -vf "scale=trunc(oh*a/2)*2:480" -f image2 "$file.jpg" < /dev/null
    ffmpeg -y -i $fileid -ss 2 -vframes 1 -r 1 -vf "scale=trunc(oh*a/2)*2:480" -f image2 "$file.jpg" < /dev/null
    ffmpeg -y -i $fileid -ss 3 -vframes 1 -r 1 -vf "scale=trunc(oh*a/2)*2:480" -f image2 "$file.jpg" < /dev/null
    ffmpeg -y -i $fileid -ss 5 -vframes 1 -r 1 -vf "scale=trunc(oh*a/2)*2:480" -f image2 "$file.jpg" < /dev/null
    ffmpeg -y -i $fileid -ss 10 -vframes 1 -r 1 -vf "scale=trunc(oh*a/2)*2:480" -f image2 "$file.jpg" < /dev/null

  6. Aslam Doctor Avatar

    This is just perfect. Thank You for all the efforts in sharing. I had the MP4 files but they were not working on chrome. Now after using Your conversion method, its working perfectly.

Leave a Reply

Your email address will not be published. Required fields are marked *