Videos mit ffmpeg und h264/x264 für Sony Ericsson's P1i (und wahrscheinlich andere ebenfalls) konvertieren

Kurze Einleitung:
Ich bin stolzer Besitzer eines P1i, seit nun mehr bald zwei Jahren. Dieses benutze ich gelegentlich auch mal um mir in Freistunden mit Kaffeine aufgenommene Serien/Filme anzugucken.
Um sie halbwegs platzsparend und abspielfähig auf das Gerät zu kriegen habe ich früher dieses ffmpeg-kommando benutzt (gefunden hier):

ffmpeg -i input.avi -vcodec h264 -r 15 -b 192 -s 320xY -acodec aac -ac 2 -ab 64 -ar 32000 output.mp4

Die Größe (-s 320xY) sollte man natürlich so wählen, dass das Ausgabe-Video das selbe Seitenverhältnis hat wie das Eingabe-Video.
Dies hat dann irgendwann aufgehört zu funktionieren, wie sich herausstellte weil ffmpeg den Namen aller externen Codecs zu lib geändert hat. Mit folgendem Kommando klappte es dann erstmal wieder:

ffmpeg -i input.avi -vcodec libx264 -r 15 -b 192 -s 320x240 -acodec libfaac -ac 2 -ab 64 -ar 32000 output.mp4

Aber auch nur für ein paar Monate, bis ffmpeg die video-presets für x264 einführte. Mit denen hab ich's einfach nicht mehr hinbekommen die Videos so zu encoden das mein Handy was mit ihnen anfangen konnte, bis heute. Dank der Hilfe von Dark_Shikari im #ffmpeg Channel hab ich es jetzt aber endlich wieder hinbekommen. Mit folgendem Kommando klappt's endlich wieder:

ffmpeg -i input.avi -vcodec libx264 -vpre hq -vpre baseline -level 11 -r 15 -crf 22 -s 320x240 -acodec libfaac -ac 2 -ab 64k -ar 32000 output.mp4

Gefehlt hat bisher das -level 11 Argument. Das P1i unterstützt nämlich nur ein "H.264 Base Profile". Über's genaue Level schweigen sich die Docs die ich gefunden habe leider aus, aber mit -level 11 klappt's auf jeden Fall und Dark_Shakiri versicherte mir das die Einstellung keinerlei Auswirkung auf die tatsächlich angewandten Features (und somit die Qualität) hat, sondern das Video nur als "Level 1.1 H.264" markiert. Update: Durch rumexperimentieren hab ich rausgefunden, dass das P1i irgendwo zwischen 1.1 (klappt immer) und 1.2 (es dürfen ruhig ein paar mehr Macroblocks = Frames/s sein, B-Frames sollte man aber niedrig belassen) liegt. Das folgende Script enkodiert die Videos immer als H.264 Base Profile Level 1.1 Video, um sicher zugehen, dass das Handy es auch wirklich wiedergeben kann.
Ach und an die Bitrate-Einstellungen hat sich ffmpeg auch nicht mehr gehalten, deswegen benutz ich jetzt stattdessen den -crf Parameter: Niedriger bedeutet bessere Quali, höher bedeutet kleinere Dateigröße. 22 find ich nen ganz ordentlichen Kompromiss. Ich nehm' alles zurück und behaupte das Gegenteil. :-P H.264 1.1 Spezifikationen sehen eine maximale Bitrate von 192kbps vor, also sollte man doch mit konstanter Bitrate encoden.
Und da ich darüber, dass das alles wieder funzt, so froh bin hab ich auch gleich ein kleines Shell-Script zusammen gehauen (Shell-Veteranen kriegen wahrscheinlich nur beim Anblick schon die Krätze ;-), dass die Berechnung der richtigen Höhe, Framerate und Anzahl B-Frames gleich mit übernimmt:

#!/bin/sh
# convertHandy.sh
target_width=320
size=`ffmpeg -i $1 2>&1 | grep Stream.*Video | grep -o "[0-9]\+x[0-9]\+"`
echo $size
width=`echo $size | sed s/x.*//g`
height=`echo $size | sed s/.*x//g`
target_height=$(($target_width*$height/$width)) # Seitenverhältnis beibehalten
target_framerate=$((3000/((($target_width+15)/16)*(($target_height+15)/16)))) # maximal 3000 Macroblocks pro Sekunde laut H.264
# 1.1 Spezifikationen
target_refs=$((900/((($target_width+15)/16)*(($target_height+15)/16)))) # Formel ist von Wikipedia geklaut :P
echo $target_width'x'$target_height
echo $target_framerate
echo $target_refs
ffmpeg -i $1 -vcodec libx264 -vpre hq -vpre baseline -level 11 -vb 192k -bufsize 500k -maxrate 192k -refs $target_refs \
-r $target_framerate -s $target_width'x'$target_height -acodec libfaac -ac 2 -ab 64k -ar 32000 $2

Einfach als convertHandy.sh speichern und mit "sh convertHandy.sh input.avi output.mp4" aufrufen. Voilá. :-)