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

  1. The FFMpeg version I used has experimental support for AAC, so I used the -strict experimental flag in the second pass
  2. I know that some versions of FFMpeg do not accept the -fpre option to specify the preset file, and requires -vpre
  3. option instead. Just copy the profile files into the presets folder, and use android_baseline instead of presets\libx264-android_baseline.ffpreset
  4. 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.
  5. 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.


blog comments powered by Disqus