Encoding the perfect video for mobile devices is always hard: you want a small sized file, with high quality, and a codec which will work on all devices, no matter how fragmented the platform is.
Android supports a very nice set of video and audio formats. We see that support for H264 and AAC is available in all Android versions, but with some limitations: H264 is only supported in baseline profile and AAC is supported in MP4 container, and while testing we encountered some more limitations, like inability to play DCT-DECIMATTION encoded files.
I want to share the FFMpeg encoding configuration which worked for us.
FFMpeg configuration
We used H264, 20fps, 200kbps baseline profile, and AAC single channel 32kbps. 2 passes encoding was used.
Preset files
FFMpeg supports preset files to help removing the endless flags from the command line:
First pass preset file (named 'libx264-android_firstpass.ffpreset')
coder=1
flags=+loop
cmp=+chroma
partitions=+parti8x8+parti4x4+partp8x8+partb8x8
me_method=dia
subq=2
me_range=16
g=250
keyint_min=25
sc_threshold=40
i_qfactor=0.71
b_strategy=1
qcomp=0.6
qmin=10
qmax=51
qdiff=4
bf=0
refs=1
directpred=1
trellis=0
flags2=-bpyramid-mixed_refs-wpred-dct8x8-fastpskip
wpredp=0
rc_lookahead=30
Second pass preset file (named 'libx264-android_baseline.ffpreset')
coder=0
flags=+loop
cmp=+chroma
partitions=+parti8x8+parti4x4+partp8x8+partb8x8
me_method=dia
subq=2
me_range=16
g=250
keyint_min=25
sc_threshold=40
i_qfactor=0.71
b_strategy=1
qcomp=0.6
qmin=10
qmax=51
qdiff=4
bf=0
refs=1
directpred=1
trellis=0
flags2=-bpyramid-mixed_refs-wpred-dct8x8-fastpskip
wpredp=0
rc_lookahead=30
Encoding
From FFMpeg folder run the following command for the first pass:
bin\ffmpeg -i source_video_file.avi -vcodec libx264 -r 20 -s 320x240 -b 220k -bt 240k -pass 1 -fpre presets\libx264-android_firstpass.ffpreset -y -an NUL.mp4
For the second pass (and actual encoding):
bin\ffmpeg -i source_video_file.avi -strict experimental -acodec aac -ar 16000 -ab 32k -ac 1 -vcodec libx264 -r 20 -s 320x240 -b 220k -bt 240k -pass 2 -fpre presets\libx264-android_baseline.ffpreset -y target_video_file.mp4
Notes
- The FFMpeg version I used has experimental support for AAC, so I used the -strict experimental flag in the second pass
- I know that some versions of FFMpeg do not accept the -fpre option to specify the preset file, and requires -vpre option instead. Just copy the profile files into the presets folder, and use android_baseline instead of presets\libx264-android_baseline.ffpreset
- If you want to stream these video files, you'll need to add hints tracks. MP4Creator is a great tool that can add those hint tranks. Don't forget to add hints for both the video track and the audio track.
- If you see this warning in FFMpeg conversion: "Incompatible pixel format 'bgr24' for codec 'libx264', auto-selecting format 'yuv420p'", then IT WONT WORK IN ANDROID! I noticed this warning when editing video files with Camtasia. Switching to Piviti fixed the issue.