John Harding - Insert Catchy Title Here

Insert witty phrase/saying here.

Saturday, May 24, 2008

Encoding video for iPhone with mencoder

It's surprising how hard it is to find good, solid information about mencoder settings for the iPhone. I finally got a decent script that takes care of a few common scenarios I care about, and figured I'd share.

First, you need to get a decent build of mencoder. If you're working on linux, head over to the mplayer download page, grab the source, and build your own. I'm doing this on Windows, so I grabbed the binaries from sourceforge (svn rev 26446), since I didn't feel like monkeying with msys.

Now, let me start you with something that should definitely work, and then we'll talk about customizing:
mencoder INPUT -o output.mp4
-vf scale=480:-10,harddup
-oac faac -faacopts mpeg=4:object=2:raw:br=128
-of lavf -lavfopts format=mp4
-ovc x264 -x264encopts nocabac:level_idc=30:bframes=0

Breaking it down:
  • -vf scale=480:-10 - Scale width to 480, set height appropriately, but keep a multiple of 16.
  • -vf harddup - Insert duplicate frames to maintain frame rate (Note: not sure if this is really needed - can the iPhone handle variable framerate?)
  • -x264encopts nocabac - iPhone only supports baseline profile, which does not allow CABAC
  • -x264encopts level_idc=30 - iPhone only supports up to level 3.0
  • -x264encopts bframes=0 - Baseline profile does not allow B-frames
Here's what I'm currently using, for a bit higher quality:
mencoder.exe input.avi -o output.mp4 -vf scale=480:-10,harddup -lavfopts format=mp4 -faacopts mpeg=4:object=2:raw:br=128 -oac faac -ovc x264 -sws 9 -x264encopts nocabac:level_idc=30:bframes=0:global_header:threads=auto:subq=5:frameref=6:partitions=all:trellis=1:chroma_me:me=umh:bitrate=500 -of lavf

The extra options:
  • -sws 9 - I think I just grabbed this from somewhere - wtf?
  • global_header - Uses single global header instead of repeating every IDR - saves space
  • threads=auto - Enables multi-threaded encoding (faster, gives up a touch of quality)
  • subq=5 - Quarterpixel motion estimation
  • framref=6 - Use up to 6 reference frames
  • partitions=all - Consider all macroblock partition sizes
Other things I do, to come in a future blog post:
  • Two-pass encoding
  • Different settings for progressive DVD content, telecined DVD content, interlaced content, etc.
  • Manage this all via a python script
Thanks to Chris Prince for his encoding settings, which helped me find my original braindead mistake of poor scaling target size.

Labels: , , ,

26 Comments:

At 7:42 PM , Blogger Chris Prince said...

Another neat trick is that if you change this:
-vf scale=480:-10,harddup
to this:
-vf dsize=480:320:2,scale=-8:-8,harddup
the video will be scaled down however far is necessary to fit in 480x320.

This is especially interesting for encoding 4:3 content. Otherwise mencoder will scale to 480x360, and you'll cut off the top/bottom of the video, or else need to rescale at runtime.

(Ah, so many obscure settings. The 'man' page is the only place I've found them all documented -- and not always well!) http://www.mplayerhq.hu/DOCS/man/en/mplayer.1.html

 
At 10:38 AM , Blogger John said...

If you want to constrain the final size to be within 480x320, then I think you actually want -vf dsize=480:320:0, which tells it to keep display size within those bounds, rather than video size. 4:3 DVDs are authored at 720x480 and scaled at display time, so using dsize=480:320:2 will result in either a distored image (if display aspect ratio is not applied) or runtime rescaling (if it is).

In my testing w/ a 720x480 DVD source, 480:320:2 ended up with a 480x320 video, and it appears the display aspect ratio got lost in the process, such that mplayer and quicktime at least displayed it horizontally stretched.

 
At 5:20 PM , Blogger naviogg said...

It is amazing how hard it is to get good information on mencoder settings, giving all the cool things it does

And you've been kind enough to say what the commands *mean* instead of simply an inscrutible cookbook - yay!

However, I think your command is wrong - you have two -oac options, and I think the second should be -oav

Am I right?

 
At 6:37 PM , Blogger John said...

naviogg, you're totally right, that was a typo. Good catch - I've corrected the post.
Glad to hear the post was useful for you - I had the same frustration with poor documentation of options and the various configs people had posted in the past.

 
At 12:59 PM , Blogger Bob said...

Thanks for this awesome post, it really helps me as I am a total video encoding newbie. And a basic question, I have iPhone 3G with iTunes 7.7 and can't seem to get the mp4 file (it plays fine in Quicktime) to sync with iTunes/iPhone, any suggestions?

 
At 2:17 PM , Blogger Bob said...

Never mind my question, I figured it out, it was a DO'H moment. For those of you that are unaware, here are the steps
1) drag the mp4 file to iTunes Movies (top left under Library)
2) connect iPhone
3) Click on iPhone device
4) Click on Video tab
5) SCROLL DOWN - this is the DO'H moment for me LOL, check sync movies, check the movie
6) Sync iPhone
7) On iPhone, launch iPod app, click on Videos tab and there's the movie.

Enjoy!

 
At 9:33 AM , Anonymous Anonymous said...

thank for the wonderful post. i use this command to convert a flv to iphone mp4 format:

mencoder 47762donbgcums.flv -o test.mp4 -vf scale=480:-10,harddup -oac faac -faacopts mpeg=4:object=2:raw:br=128 -of lavf -lavfopts format=mp4 -ovc x264 -x264encopts qp=26:pass=1

but i phone safari cannot download the test.mp4 and I cannot even import the test.mp4 to iphone using itune. Am i missing somthing

 
At 11:09 AM , Blogger Adamm said...

Now, what are the chances that the one place on the Interweb with information on encoding video for the iPhone that actually works is someone I know? :)

Thanks, John, this is useful stuff. I'd been trying to futz around with VLC for a while and found that it worked perfectly on some videos and horribly on others.

I'm trying out your to_ipod.py script now. I had to hack it a bit to make it work on Ubuntu, so let me know if you'd like a patch.

Happy Labor day!

 
At 4:51 AM , Anonymous Mike Cole said...

Finally got everything installed and working on my Debian box. Getting the x264 codec installed and working took the longest, but I now have a perl script for converting everything thanks to your page and comments, so thanks everyone.

 
At 1:23 PM , Anonymous Anonymous said...

"-sws 9 - I think I just grabbed this from somewhere - wtf?"

that is the type of resize to use.
The most common are 1,2, or 9.
Bilinear (-sws 1) is fast but smooths the image. Bicubic (-sws 2) is the default. Lanczos (-sws 9) actually sharpens the image during resize.

0 fast bilinear
1 bilinear
2 bicubic (good quality) (default)
3 experimental
4 nearest neighbor (bad quality)
5 area
6 luma bicubic / chroma bilinear
7 gauss
8 sincR
9 lanczos
10 natural bicubic spline

 
At 4:10 PM , Blogger Jason said...

This comment has been removed by the author.

 
At 4:12 PM , Blogger Jason said...

That was a really good script to encode video files.

Based on your script, I made a little batch program to do the job easier.

http://www.myubuntu.ca/?p=193

 
At 4:05 PM , Blogger balazer said...

Thanks for the mencoder info.

Here's a Windows .bat file that will allow drag-and-drop encoding of multiple files: (assumes mencoder.exe in c:\program files\mencoder) It will also use .srt subtitles, if present. I haven't actually tested the output of this on an iPhone yet.

:cont

if '%1' == '' goto end

for %%F in (%1) do start "MEncoder" /low /min /wait "c:\program files\mencoder\mencoder.exe" %%F -priority belownormal -oac lavc -lavcopts acodec=libfaac:abitrate=128:aglobal=1 -a52drc 0 -ovc x264 -x264encopts nocabac:level_idc=30:bframes=0:global_header:crf=20 -of lavf -lavfopts format=mp4 -vf dsize=480:320:0,scale=-8:-8,harddup -o "%%~dpnF_iPhone.mp4" -slang en -sub "%%~dpnF.srt"

shift
goto cont

:end

pause

 
At 1:08 PM , Blogger Rich G said...

nice post. but it is possible with mencoder to create iphone reference movies?

so instead of serving up one, i've got a .mov that references a movie file (m4v or 3gp or whatever) depending on network connection.

you can do it with quicktime pro and something called makerefmovie but it's Mac/Windows only and I could do with a linux solution!

thanks!

 
At 12:34 PM , Anonymous Anonymous said...

My PHP contrib:

function convert_video($nom){
$input = "$nom.flv";
$output = "mp4/$nom.mp4";

$linia = "mencoder.exe $input -o $output ";

//$linia .= "-vf scale=480:-10,harddup";
$linia .= "-vf scale=480:320:2,scale=-8:-8,harddup ";

$linia .= "-lavfopts format=mp4 ";
$linia .= "-faacopts mpeg=4:object=2:raw:br=128 ";
$linia .= "-oac faac ";
$linia .= "-ovc x264 ";
$linia .= "-sws 9 ";
$linia .= "-x264encopts nocabac:level_idc=30:bframes=0:global_header:threads=auto:subq=5:frameref=6:partitions=all:trellis=1:chroma_me:me=umh:bitrate=500 ";
$linia .= "-of lavf";

exec($linia);
echo $nom."
";
//echo $linia."
";
}

$dix = "./folder/with/files/";
$d = dir($dix);
while(false !== ($arxiu = $d->read())) {
if($arxiu!=".."&&$arxiu!="."){
$arxiu = str_replace('.flv','',$arxiu);
convert_video($arxiu);
}
}
$d->close();

 
At 6:43 PM , Blogger Gordon said...

Why people? Why use all these scripts? (PHP?!) If you want to reuse the format, then use the built in mencoder config file. Then you can encode using

mencoder infile.avi -o outfile.mp4 -profile iphone
And it's sooooo much easier to edit/add to later on.
Default location is ~/.mplayer/mencoder.conf
add this to the file
[iphone]
profile-desc="Default profile for iphone"
vf=scale=480:-10,harddup
lavfopts=format=mp4
faacopts=mpeg=4:object=2:br=128
oac=faac=yes
ovc=x264=yes
sws=9
x264encopts=nocabac:level_idc=30:bframes=0:global_header:threads=auto:subq=5:frameref=6:partitions=all:trellis=1:chroma_me:me=umh:bitrate=500
of=lavf=yes

 
At 10:01 AM , Anonymous Anonymous said...

FFMPEG command line i used for iPod touch and iPhone 3Gs:

"\ffmpeg.exe" -i "Path\My.avi" -author "2Avi" -f mov -b 720k -r 23.976 -aspect 16:9 -s 480x320 -acodec libfaac -ab 256k -ar 44100 -ac 2 -y "Path\My_2avi.mp4"

i wrote an extra Userinterface for Windows with it so i can just click & go. I m sure ill try the mencoder soon.

ty

 
At 3:23 AM , Blogger khannie said...

Very useful post. Thanks. :)

Some minor feedback.....

-sws 9 seems to result in slightly lower picture quality than the default (-sws 2). I've checked the PSNR output from x264encopts on a few videos now and -sws 9 always seems to result in a lower PSNR (i.e. slightly worse picture quality).

If all that is "blah blah blah" to you, the short version is that you're better off leaving out the -sws 9 switch.

Also, a bitrate of 500 is quite low. Unless space is a concern for you, you're better off going with a higher bitrate (I'll be using around 800-1000 depending on the aspect ratio of the original).

 
At 9:50 AM , Blogger mlw said...

John's mencoder settings work fine if you want to prepare a video to transfer to your iPhone via iTunes. But the resulting MP4s won't play over HTTP in Safari on the iPhone.

To make a Safari streamable MP4 (H264, AAC) using Quicktime Pro to do the encoding you have to set "Restrict Profile(s) to Baseline".

But what are the correct x264 options to achieve the same result with mencoder?

 
At 10:18 PM , Blogger Adam Monsen said...

A few things:

1. folks, check out HandBrake. Transcoding made easy.
2. the longevity of this blog post is staggering.
3. JH - do you have a catchy title for this blog yet?

 
At 1:47 PM , Anonymous Anonymous said...

Newest version of x264 requires adding weightp=0 to the x264encopt arguments

 
At 5:44 PM , Anonymous Mobil | Mobiltelefon said...

Will this work for a 3Gs?

 
At 9:59 PM , Blogger John said...

Answering a bunch of recent comments:
@khannie: I'm not too familar with the various scalers - there's a lot of interaction between the material, scaler, bitrate, etc. http://www.wieser-web.de/MPlayer/sws1/ is an interesting overview.

@mlw: That's odd - I don't have any problems loading these videos. Worked via <object> and <a> tag on original iPhone (iOS 3.0), and via <video> and <a> tag on iPad (iOS 3.2.2) and it worked fine.

@adam: Yeah, Handbrake is probably a better solution for this all around. I keep telling myself I'm going to add things like interlace handling (which I believe Handbrake already deals with) and audio normalization (which I bet Handbrake does as well). Part of the motivation here was just digging deeper into mencoder, but I also hold out hope for building out my own automated workflow.
And doesn "Insert Catchy Title Here" qualify as a catchy title?

re: weightp - LAME. In support of Adam's comment, Handbrake seems to handle this for you. :)

@Mobil: Yes.

Random side note - I'm actually encoding at up to 640x480 for my Nexus One and should probably bump that up to the full 800x480 bounding box. If you're lucky enough to have an iPhone 4, you can do even higher res and bump up to Main Profile. You should actually be able to use almost the same settings as for AppleTV, though I'm not sure if I ever committed that to svn.

 
At 8:05 AM , OpenID Adam Monsen said...

Previous comment is spam (see poster's URL).

 
At 7:02 AM , Anonymous Arno said...

I had big trouble making my video work on a 3G : mencoder was overidding the profile to high, I don't know the reason.

I had to force the profile using

-x264encopts profile=baseline

Hope this will help

 
At 11:43 PM , Blogger H. Mijail Antón Quiles said...

For those like kannie using PSNR to measure quality: be aware that PSNR is purely technical, bit-to-bit, not perceptual. Any kind of processing, like sharpening, will obviously worsen PSNR while could improve subjective quality. Extreme example: adding a bit of grain/noise is usually recommended to improve visual quality.

 

Post a Comment

Subscribe to Post Comments [Atom]

<< Home