Videos mit FFmpeg komprimieren
Um die Dateigröße eines Videos fürs Web zu reduzieren, beginnen Sie mit H.264-Video und AAC-Audio
in einem MP4-Container. Dieser Befehl erstellt output.mp4 aus einer lokalen Datei
input.mp4 mit qualitätsbasiertem Encoding:
if [ -e "./output.mp4" ] || [ -L "./output.mp4" ]; then
printf '%s\n' 'Choose a new filename: ./output.mp4 already exists.' >&2
false
else
ffmpeg -n -nostdin -xerror -i "./input.mp4" \
-map 0:V:0 -map '0:a:0?' \
-c:v libx264 -crf 23 -preset medium -pix_fmt yuv420p \
-c:a aac -b:a 128k -ac 2 -movflags +faststart "./output.mp4"
fi
Verlustbehaftete Komprimierung verwirft Details. Das Ergebnis kann kleiner sein, doch eine bereits effizient komprimierte Quelle kann beim erneuten Encoding größer werden. Behalten Sie das Original und vergleichen Sie die Ausgabe, bevor Sie Einstellungen für weitere Videos wählen. CRF steuert die Qualität, garantiert aber keine bestimmte Dateigröße.
Der Befehl wählt den ersten Videostream, der kein Coverbild ist, und die erste Audiospur, sofern
vorhanden. Bei vorhandenem Audio erzeugt er Stereo-AAC, andernfalls ein Video ohne Ton. Weitere
Audiospuren, Untertitelstreams und Datenstreams werden ausgelassen. Das optionale Audio-Mapping und
der Überschreibschutz mit -n sind in der
Befehlsreferenz von FFmpeg dokumentiert.
-nostdin deaktiviert interaktive Eingaben, und -xerror
bricht bei Fehlern ab, die FFmpeg erkennt. Ein Fehler kann eine unvollständige Ausgabe hinterlassen.
Veröffentlichen Sie diese nicht und werten Sie ihre geringe Größe nicht als erfolgreiche Komprimierung.
Voraussetzungen prüfen
Verwenden Sie Bash unter Linux mit ffmpeg und
ffprobe in Ihrem PATH. Diese Beispiele wurden mit FFmpeg 6.1.1 unter
Ubuntu 24.04 und FFmpeg 9.0.1 unter Linux getestet. Sie benötigen den Video-Encoder
libx264, den nativen Audio-Encoder aac und den
MP4-Muxer. Prüfen Sie Ihren Build:
ffmpeg -version &&
ffprobe -version &&
ffmpeg -hide_banner -h encoder=libx264 &&
ffmpeg -hide_banner -h encoder=aac
Die Hilfeausgabe sollte beide Encoder beschreiben. Eine Meldung wie „unknown“ oder „not recognized“ bedeutet, dass der Build ungeeignet ist, selbst wenn der Hilfebefehl erfolgreich endet. Falls Sie FFmpeg benötigen, finden Sie auf der Downloadseite Links zu Linux-Paketen sowie Builds für macOS und Windows. Die Shell-Beispiele hier sind für Linux gedacht.
Verwenden Sie einen progressiven Clip mit Standard-Dynamikumfang (SDR), quadratischen Pixeln und
jeweils gerader Breite und Höhe. Diese Befehle ändern weder die Videogröße noch führen sie
HDR-Tonemapping durch. yuv420p wählt 8-Bit-Video mit 4:2:0 aus; es wandelt
HDR-Farben nicht in korrekte SDR-Farben um. Setzen Sie Dateinamen in Anführungszeichen, einschließlich
des Präfixes ./ bei Namen, die mit einem Bindestrich beginnen. Jeder
Encoding-Vorgang verweigert das Ersetzen einer vorhandenen MP4-Datei. Wählen Sie daher beim Vergleich
von Einstellungen ein neues Ziel. Auch die Shell-Prüfung liefert bei einem vorhandenen Ziel einen
Fehlerstatus: FFmpegs eigener Überschreibschutz kann in manchen Versionen erfolgreich enden.
CRF und Voreinstellung getrennt wählen
Beginnen Sie für libx264 mit CRF 23. Probieren Sie 20, wenn kleiner Text oder
feine Details beeinträchtigt wirken, oder 26, wenn weniger Bytes wichtiger sind. Niedrigere CRF-Werte
erhalten mehr Details und erzeugen meist größere Dateien; höhere Werte opfern mehr Details zugunsten
von weniger Bytes. Codieren Sie für jeden Vergleich erneut ausgehend vom Original.
Die Voreinstellung steuert den Encoding-Aufwand von x264. medium ist ein
sinnvoller Ausgangspunkt; slow sucht länger nach effizienten Wegen, das
Video zu codieren. Das kann die Komprimierungseffizienz verbessern, verspricht aber weder eine feste
prozentuale Einsparung noch identische Qualität bei gleichem CRF. Die getrennten Regler für Qualität
und Voreinstellung finden Sie unter x264-Encoder-Optionen.
CRF-Werte und Namen von Voreinstellungen sind an einen Encoder gebunden. CRF 23 in x264 entspricht
nicht derselben Qualität in x265, VP9 oder AV1, und slow ist keine
encoderübergreifende Qualitätsskala. Wenn die Quellauflösung die Anzeigeauflösung übersteigt, kann
eine Größenänderung mehr bewirken als eine weitere Erhöhung des CRF-Werts. Prüfen Sie jedoch kleinen
Text und andere Details in der vorgesehenen Anzeigegröße, bevor Sie Pixel verwerfen.
Qualität und Dateigröße vergleichen
Untersuchen Sie Quelle und Ausgabe mit ffprobe. Dies gibt Stream-Eigenschaften, die Dauer in Sekunden und die Dateigröße in Bytes aus:
ffprobe -v error -show_format -show_streams -of json "./input.mp4" &&
ffprobe -v error -show_format -show_streams -of json "./output.mp4"
Achten Sie beim Videostream auf codec_name: "h264" und pix_fmt: "yuv420p".
Bei einer Quelle ohne Rotationsmetadaten sollten Breite und Höhe mit der Quelle übereinstimmen.
Ein Audiostream sollte aac mit zwei Kanälen melden, wenn die Eingabe Audio
enthielt. Vergleichen Sie format.size und format.duration mit der
Quelle. Kleine Unterschiede durch Audio-Padding sind normal; der Verlust von Sekunden an Inhalt
ist es nicht.
Decodieren Sie das vollständige Ergebnis, um Fehler jenseits der Metadaten zu erkennen:
ffmpeg -v error -nostdin -xerror -i "./output.mp4" \
-map 0:V:0 -map '0:a:0?' -f null -
Erfolgreiches Decodieren erzeugt hier keine Fehlerausgabe. Es misst nicht die visuelle Qualität. Spielen Sie beide Dateien in der vorgesehenen Anzeigegröße ab und prüfen Sie Bewegungen, Verläufe, kleinen Text und die Audiosynchronität. Eine kleinere Datei ist nur dann nützlich, wenn Bild und Ton für Ihre Seite akzeptabel bleiben.
Zwei Durchläufe für ein Größenbudget nutzen
Wenn Sie ein Upload-Limit einhalten müssen, wählen Sie eine durchschnittliche Bitrate statt CRF.
Als Ausgangspunkt dient die Berechnung video bits/s = (target bytes × 8 ÷ duration seconds) − audio bits/s. Reservieren Sie einen Teil
des Gesamtbudgets für den Container und Bitratenschwankungen und messen Sie anschließend die fertige
Datei. Zwei-Pass-Encoding zielt auf eine durchschnittliche Videobitrate ab; es ist kein exaktes
Byte-Limit.
Ein Clip von 60 Sekunden unter 10 MB (10.000.000 Bytes) hat beispielsweise insgesamt etwa
1.333 kbit/s zur Verfügung. Wenn Sie 5 % reservieren und 128 kbit/s für Audio einplanen, bleiben
etwa 1.139 kbit/s für Video. Runden Sie für einen ersten Versuch auf 1100k
ab. Nutzen Sie die tatsächliche Dauer Ihrer Quelle aus ffprobe und berechnen Sie die Werte für ein
anderes Limit neu. Ohne Audio bleibt in diesem Beispiel das Audiobudget ungenutzt.
Führen Sie diesen vollständigen Block in Bash aus. Er erstellt target.mp4
unabhängig von der vorherigen CRF-Ausgabe:
(
if [ -e "./target.mp4" ] || [ -L "./target.mp4" ]; then
printf '%s\n' 'Choose a new filename: ./target.mp4 already exists.' >&2
exit 1
fi
pass_dir=$(mktemp -d) || exit 1
trap 'rm -rf -- "$pass_dir"' EXIT
ffmpeg -y -nostdin -xerror -i "./input.mp4" \
-map 0:V:0 -c:v libx264 -b:v 1100k -preset medium -pix_fmt yuv420p \
-pass 1 -passlogfile "$pass_dir/stats" -an -f null /dev/null &&
ffmpeg -n -nostdin -xerror -i "./input.mp4" \
-map 0:V:0 -map '0:a:0?' \
-c:v libx264 -b:v 1100k -preset medium -pix_fmt yuv420p \
-pass 2 -passlogfile "$pass_dir/stats" \
-c:a aac -b:a 128k -ac 2 -movflags +faststart "./target.mp4"
)
Der erste Durchlauf sammelt Statistiken; && verhindert den zweiten
Durchlauf, wenn der erste fehlschlägt. Das temporäre Verzeichnis hält die
Durchlaufprotokolle verschiedener Ausführungen getrennt und wird
beim Beenden des Blocks entfernt. -y im ersten Durchlauf gilt nur für
die verworfene Ausgabe unter /dev/null; der zweite Durchlauf verwendet
-n, um target.mp4 zu schützen. Halten Sie Eingabe,
Bitrate, Voreinstellung und etwaige Videofilter in beiden Durchläufen gleich.
Wiederholen Sie die Prüf- und Decodierbefehle mit target.mp4 anstelle von
output.mp4. Wenn die Datei Ihr Limit überschreitet, senken Sie die Videobitrate
und führen Sie beide Durchläufe mit einem neuen Ausgabedateinamen erneut aus. Falls das Bild schon
inakzeptabel wird, bevor die Datei ins Budget passt, überdenken Sie Dauer oder Auflösung. Ein bloßer
Codec-Wechsel kann nicht für jedes Budget ein akzeptables Ergebnis garantieren.
Browserkompatibilität
H.264 ist der Video-Codec; MP4 ist der Container, der dieses Video und sein AAC-Audio enthält. Diese Kombination ist ein praktischer Ausgangspunkt für breite Webwiedergabe. Die Unterstützung hängt aber auch von Browser, Betriebssystem, Codec-Profil und -Level, Auflösung und Geräte-Decoder ab. Firefox kann für H.264 beispielsweise auf Codecs des Betriebssystems angewiesen sein. Lesen Sie den MDN-Leitfaden zu Video-Codecs und testen Sie die tatsächliche Datei auf den Browsern und Geräten Ihrer Zielgruppe. HEVC, VP9 und AV1 sind Alternativen, die Sie für diese Zielgruppe bewerten können, aber kein grundsätzlich besserer oder überall unterstützter Ersatz.
-movflags +faststart platziert den MP4-Index vor den Mediendaten. So kann ein Player, der
dies unterstützt, die Wiedergabe starten, ohne zuerst das Dateiende herunterzuladen. Das reduziert
weder die Größe des codierten Videos noch erzeugt es Varianten für adaptives Streaming. Die
MP4-Muxer-Dokumentation erläutert diesen zusätzlichen
Indexierungsschritt. Auch nach erfolgreichem lokalem Decodieren müssen Sie die Wiedergabe vor der
Veröffentlichung über Ihren tatsächlichen Webserver und Player prüfen.
Einstellungen mit Bedacht wiederverwenden
Testen Sie Ihre gewählten Einstellungen an repräsentativen Clips, bevor Sie eine Sammlung codieren. Eine Bildschirmaufnahme mit kleinem Text und ein mit einer Handkamera aufgenommener Clip benötigen eventuell unterschiedliche CRF-Werte. Verwenden Sie für jede Quelle ein separates Ziel und prüfen Sie den Status jedes Befehls, bevor Sie seine Ausgabe untersuchen oder veröffentlichen. Wählen Sie nach einem fehlgeschlagenen Encoding einen neuen Ausgabenamen oder entfernen Sie nur die gerade erstellte unvollständige Datei. Der Überschreibschutz gilt auch für Teildateien aus früheren Ausführungen.
