Einführung in FFmpeg: Grundlagen; von Container, Streams und Codecs

bastla

mit bastla_Assi
Hallo Boardies,

seit längerer Zeit beschäftige ich mich nun schon mit Videobearbeitung, -kompression und -konvertierung. Weil ich selbst ziemlich lange auf Recherche im Internet unterwegs war und keine wirklich gute (und dazu noch deutschsprachige) Einführung in das Thema finden konnte, lag es nun an mir, anderen Leidtragenen zu helfen.
Ich werde deshalb versuchen, sofern es meine Zeit zulässt, eine kleine Reihe von Tutorials zu dem Thema zu veröffentlichen.

Beginnen möchte ich mit mit der Konvertierung von Videomaterial, da dies sicherlich ein Thema ist, welches für die meisten von Interesse sein dürfte. Wer musste denn schon nicht "mal eben" einen Film konvertieren, damit er auf einen Stick, eine DVD oder CD passte? Wer musste nicht schon mal einen Film konvertieren, um ihn auf der heimischen Kinoanlage zum Laufen zu bringen?

Es gibt eine Menge Tools (mehr kostenpflichtige als wirklich gute Freeware), die mit solchen "schnellen" und vor allen Dingen qualitativ "hochwertigen" Konvertierungen um die Gunst der User ringen.
Ich werde die Konvertierung von Videos mit Hilfe des Open-Source Programms FFmpeg erklären. FFmpeg ist kostenlos, OpenSource, plattformunabhängig und vor allen Dingen ein Allrounder auf dem Gebiet. Für Videobearbeitung eher weniger geeignet, aber in Sachen Konvertierung unschlagbar.

Ein "major turn-off" dürfte wohl sein, dass es nur über ein CLI zu bedienen ist, das heißt über die Kommandozeile und nicht über eine grafische Oberfläche. Aber so ist das nun mal: Videokonvertierung ist ein komplexes Thema, das lässt sich nicht einfach in einer "Allround-Oberfläche" darstellen (wobei Oberflächen, wie WinFF, für simple Aufgaben nicht gänzlich ungeeignet sind).


Bevor wir aber zur Benutzung von FFmpeg kommen, ja bevor wir noch zur Installation kommen, ist zunächst einiges über den grundlegenden Aufbau einer Videodatei zu wissen. Wenn ich im weiteren Verlauf dieses Tutorials von "Video" oder "Film" spreche, meine ich eine Videodatei.

Jeder Film ist eine Sammlung von dem Film/den Filmen im eigentlichen Sinne, Tonspuren und eventuell vorhandenen Untertiteln. Damit diese als eine einzige Datei auf dem Computer abgelegt werden können, sind sie sozusagen "zusammengepackt". Diese "Verpackung" wird Container genannt. Ein Container enthält mehrere Streams, das können halt Video-, und Audiospuren oder auch Untertitel sowie Metadaten sein.
Jeder Stream wiederum ist auf eine bestimmte Art und Weise komprimiert/verpackt worden. Würden einzelene Streams unkomprimiert/unverpackt gespeichert werden, also nur als Rohdaten, sammelten, natürlich je nach Qualität des Materials, für ein paar Minuten Film direkt mehrere Gigabyte an Daten an. Damit es nicht so weit kommt, werden die Daten mittels eines Codecs kodiert und müssen beim Abspielen wieder dekodiert werden.

Das ist auch der Grund, warum nicht jeder Player jede Videodatei abspielen kann, eventuell unterstützt er einen der verwendeten Codecs nicht, das Container-Format ist ihm unbekannt oder das Video ist einfach qualitativ "zu" hochwertig.

Was bei einer Konvertierung/Umwandlung eines Films passiert, erklärt diese (selbstgemachte :D) Grafik:
76917d1406803872-einfuehrung-in-ffmpeg-grundlagen-container-streams-codecs-transcoding_process.png

  1. demuxen: Der Demuxer "extrahiert" den zu bearbeitenden, kodierten Stream aus dem Container
  2. decoden: Der Decoder "entschlüsselt" den Stream und speichert die Rohdaten
  3. encoden: Der Encoder "verschlüsselt" diese Rohdaten nun wieder in einen neuen kodierten Stream
  4. muxen: Der Muxer "verpackt" den kodierten Stream in den neuen Container

Dieser ganze Vorgang wiederholt sich während des Konvertierens mehrere Male, das Video wird so schrittweise umgewandelt. FFmpeg kann so einzelne oder alle Streams eines Films neu kodieren (also den Codec ändern), weil zum Beispiel ein Abspielgerät nur einen bestimmten unterstützt, oder mehrere Streams aus verschiedenen Dateien zu einem neuem Video "zusammenmuxen".

Allein dieses Wissen kann schon extrem viel Zeit sparen: Wer beispielsweise einen Film im AVI-Format (AVI: Container) mit einem Videostream, der den Codec H.264 nutzt, und einem Audiostream im Codec MP3 vorliegen hat und für sein Abspielgerät eine mp4-Datei braucht (MP4: Container), braucht den Film nicht komplett zu konvertieren, denn H.264- und MP3-Streams sind mit dem MP4-Container komplett kompatibel.
Die Streams müssen nur gedemuxt und neu gemuxt werden. So entfällt der Schritt des Decodens und Encodens, was nicht nur extrem viel Zeit spart, sondern auch, was viel wichtiger ist, keinen Qualitätverlust bedeutet, da die Streams gar nicht angefasst werden.

FFmpeg kann alle gängigen Container und Codecs (de)muxen/decoden/encoden, jedoch gibt es einige Formate, für die nur De- oder Encoder vorliegen (in der Grafik mit "lesen" und "schreiben" verdeutlicht). Welche dies sind, erläutere ich zu einem späteren Zeitpunkt oder in einem anderen Tutorial.


Was nun folgt, ist eine (bei Weitem unvollständige) List mit allen gängigen Container und Codecs.

Container:

  • AVI (Audio Video Interleave):
    AVI, aus dem Hause Microsoft, war lange Zeit DER Standard für Videocontainer schlechthin, mit seiner Einführung brach die Zeit der Multimedia-PCs an.
    Heuzutage gilt AVI als überholt, es gibt eine Menge fähigerer Container. Besonders die mangelnde Unterstützung für Untertitel (subtitle-streams) und für variable Datenraten drängten AVI im Laufe der Zeit aus dem Wettbewerb. Wird von vielen alten DVD-Spielern als einziges Containerformat unterstützt und ist bei den meisten (auch modernen) Playern zumindest rudimentär noch enthalten.
    Enthält meistens die Videocodecs MPEG-4 part 2/DivX/Xvid und MP3- oder AC3-Audiocodecs, ist aber generell ein Codec-Allrounder.
  • FLV (Flash Video):
    FLV erlebte seinen Siegeszug mit über das Internet verbreiteten Videos. Passend zum Flash Player wurde FLV von Adobe entwickelt und kann eigentlich nur im Webbrowser abgespielt werden. Der Container sollte heute nicht mehr benutzt werden, zumal er nur wenige Codecs zulässt.
    FFmpeg kann aus Flash Videos die Codecs Sorenson Spark und H.264 nutzen, sowie auf Audoseite AAC und MP3.
  • MKV (Matroska Video):
    MKV ist DAS Schwergewicht unter den Container. Es gibt fast nichts, was MKV nicht kann. MKV unterstützt variable Datenraten, mehrere Video-, Audio- und Untertitel-Streams, Menüs (zumindest theoretisch, hab bisher noch keine praktische Umsetzung entdecken können), ist OpenSource, kann gestreamt werden und produziert am wenigsten Overhead (vom Container benötigter Speicherplatz, der nicht zu den Streams gehört).
    MKV kann alle möglichen Codecs enthalten. Für mich ist klar, dass MKV in naher Zukunft MP4 als führendes Containerformat ablösen wird.
    Allerdings wird MKV momentan von extrem wenigen DVD/Blu-ray-Playern unterstützt. Das liegt wohl daran, dass vor allem illegale "DVD Rips" im MKV-Format verbreitet werden, gerade weil alle Streams einer DVD sich in einer einzigen MKV-Datei bündeln lassen.
  • MP4:
    MP4 ist der aktuell der meistgenutzte Container. MP4 baut auf Apples QuickTime-Format auf und ist in Verbindung mit dem H.264-Videocodec und dem AAC-Audiocodec momentan Industriestandard, vor allem im HD-Bereich.
    Neben der Dateiendung .mp4 steckt der Container noch hinter vielen anderen, so z. B. .m4v, .m4a oder .m4b.
    Häufig verwendete Videocodecs sind H.264, MPEG-4 part 2/DivX/Xvid, MPEG-2 und MPEG1, als Audiocodecs findet sich meistens AAC, Apple Lossless/ALAC, MP3 und MP2. MP4 unterstützt nur DVD-Untertitel (bildbasiert) und kann nicht gestreamt werden.
  • MPG (MPEG Program Stream):
    MPG ist ein Container, der alle möglichen Codecs der MPEG (Moving Pictures Experts Group) beinhalten kann, also MPEG1, MPEG-2, MPEG-4 part 2. Als Audiocodecs lassen sich meistens DTS, ACC, AC3, MP3, MP2, MP1finden.
    DVDs nutzen diesen Container, mit MPEG-2 (moderne DVDs) oder MPEG-1 (alte DVDs) sowie AC3 oder DTS (moderne DVDs) oder MP2 (alte DVDs).
  • OGG:
    OGG ist ein komplett freies Containerformat von xiph.org, welcher meistens für ebenfalls von xiph.org entwickelte Codecs verwendet wird. Ogg kann problemlos gestream werden und erfreut sich seit längerem in der OpenSource-Community größerer Beliebtheit. OGG wird mittlerweile von vielen Playern und Abspielgeräten unterstützt, allerdings konnte sich der Container nie wirklich durchsetzen, besonders da mit MKV ein vergleichbarer und leistungsstärkerer Container erscheinen ist.
    Videocodecs: Theora, Dirac. Audiocodecs: Vorbis, Opus.
  • TS (MPEG Transport Stream):
    TS kann irgendeinen MPEG-Stream enthalten und wird vor allem im Rundfunk genutzt.

Video-Codecs:

Die im Nachfolgenden gelisteten Codecs bezeichnen wirklich nur den Codec! Codec ist nicht gleich De-/Encoder! FFmpeg kann für einen Codec andere oder mehrere De-/Encoder nutzen, welche nicht selbst von FFmpeg entwickelt wurden, sondern externe Projekte sind, die in FFmpeg integeriert wurden.

  • MPEG-2:
    MPEG-2 gibt es bereits seit 1994 und wird von DVDs genutzt. Heuzutage kommt es eigentlich nur noch im digitalen Rundunk (DVB) zum Gebrauch.
    FFmepg hat seinen eigenen Encoder für MPEG-2: mpeg2video
  • MPEG-4 part 2/DivX/Xvid:
    Gegenüber MPEG-2 komprimiert MPEG-4 part 2 (häufig einfach nur MPEG-4 genannt) erheblich besser. MPEG-4 wurde von Microsoft entwickelt und war bis zur Veröffentlichung von H.264 der leistungsstärkste Videocodec.
    DivX ist genaugenommen nicht der gleiche Codec wie MPEG-4, DivX wurde jedoch aus MPEG-4 entwickelt, nachdem MPEG-4 gehackt wurde. DivX wurde zu Beginn als OpenSource entwickelt, jedoch änderte das entwickelnde Unternehmen den Codec zu einem proprietärem Geschäftsmodell. Daraufhin entstand das von der Community gegründete Project Xvid auf Basis des DivX-Codes.
    FFmpeg hat einen eigenen, sehr guten Encoder für MPEG-4 part 2, nämlich mpeg4, kann allerding auch libxvid aus dem Xvid-Projekt nutzen. Einige Geräte unterstützten nur MPEG-4 part 2 Videos aus dem Xvid-Projekt, mit einem Trick kann jedoch auch der mpeg4-Encoder von FFmpeg genutzt werden.
  • MPEG-4 part 10/H.264/MPEG-4 AVC:
    H.264 ist unter vielen Namen unterwegs, aber in jedem Fall seit 2002 der beste und effizienteste Codec, kurz: das Schlachtschiff, auf dem Markt. An der Entwicklung waren eine ganze Menge unterschiedlichster Experten beteiligt, unter anderem vom Fraunhofer-Institut und Microsoft. Die ganze HD-Branche, inklusive Blu-ray, HD-DVD und DVB-S2, basiert auf H.264, dementsprechend wird H.264 von so ziemlich jedem modernen Player unterstützt.
    FFmpeg nutzt zur Enkodierung von H.264 den libx264-Encoder aus dem x264-Projekt.
  • MPEG-HEVC/H.265/MPEG-H part 2:
    Schon zwei Jahre nach der Veröffentlichung von H.264, also im Jahr 2004, wurde die Entwicklung von H.265 begonnen, mit dem Ziel die gleiche Qualität von H.264 bei doppelter Kompression zu erreichen. Ob H.265 sich durchsetzt, bezweifle ich, da H.264 in der gesamten Video-Branche überall angekommen ist. Die Nutzung von H.265 empfehle ich daher nicht, zumal der Codec noch in Entwicklung ist.
    FFmepg realisiert, auch seit kurzem erst, H.265 mittels libx265.
  • Theora:
    Theora ist der komplett freie und OpenSource Videocodec von xiph.org. Er wird meistens in Verbindung mit dem OGG-Container genutzt. Theora sollte eigentlich eine freie Alternative zu Codecs wie MPEG-4 part 2, RealVideo, DivX oder Windows Media Video sein, konnte sich aber nie richtig durchsetzen. Momentan soll er auf ein Level mit H.264 gebracht werden.
    FFmpeg nutzt libtheora, um Theora zu verarbeiten.
  • VP8:
    VP8 ist, wie Theora, ein patentfreier Codec, welcher von Googel aufgekauft und als OpenSource veröffentlich wurde, mit dem Ziel, sich als Standard in HTML5 zu etablieren. VP8 wird vor allem im WEBM-Format (WEBM = MKV-Container) mit dem freien Audiocodec Vorbis genutzt. VP8 erreicht nicht ganz die Qualität von H.264.
    Das FFmpeg-Team entwickelt zur Zeit einen Encoder für VP8, ebenso die x264-Entwickler. Bis deren Fertigstellung muss auf den Encoder libvpx ausgewichen werden, welcher jedoch ziemlich viele Bugs enthält.
  • VP9:
    VP9 wird mit dem Ziel entwickelt, die Kompression im Vergleich zu VP8 bei gleicher Qualität zu verdoppeln und damit H.265 in Zukunft abzulösen. VP9 ist seit kurzem erst in Firefox und Chrome implementiert. Der Codec selbst lässt sich nur mit dem Audiocodec Opus im WEBM-Format verwenden.
    FFmpeg nutzt den Encoder libvpx-vp9, da VP9 aber noch in Entwicklung und damit unsicher ist, muss die Verwendung mit der Option -strict experimental bestätigt werden.

Audio-Codecs:

  • AAC (Advanced Audio Coding):
    AAC ist Verbindung mit H.264 und dem MP4-Container überall anzutreffen, seien es Blu-rays oder Streaming-Dienste. Im Vergleich zu MP3 kann AAC bei niedrigeren Datenraten die gleiche Qualität ereichen. AAC nutzt, wie MP3, ID3-Tags für Metadaten.
    Für AAC gibt es gleich eine ganze Palette an Encoders, auch einen eigenen. Einige davon sind nicht frei, daher sind sie nicht in allen FFmpeg-Builds enthalten. Liste der Encoder (bester zuerst, schlechtester zuletzt): libfdk_aac, libfaac, acc (nativ), libvo_aacenc
  • AAC-HE und AAC-HE v2 (MPEG-4 High Efficiency Advanced Audio Coding):
    AAC-HE und die nachfolgende Version AAC-HE v2 sind weiterentwickelte Versionen des AAC-Codecs, welche mit extrem niedrigen Datenraten gute Qualitäten erreichen und sich damit besonders gut für das Streamen eigenen.
    Einziger mir bekannter Encoder für AAC-HE und AAC-HE v2 ist libfdk_aac. Damit auch wirklich AAC-HE und nicht AAC verwendet wird, muss mit -profile:a aac_he oder -profile:a aac_he_v2 noch das passende Audioprofil geladen werden.
  • AC3:
    AC3 ist der Audiocodec von Dolby Digital. Da er bis zu sechs Kanäle beinhalten kann und damit für 5.1 Surround Sound geeignet ist, findet er sich vor allen in Blu-rays, DVDs und im Rundfunk. AC3 wäre sicherlich eine Alternative zu AAC, leider komprimiert AAC besser.
    FFmpeg hat mit ac3 einen nativen Encoder.
  • MP3 (MPEG-2 Audio Layer III):
    MP3 war lange Zeit schlechthin DER Audiocodec, auch ohne Container nutzbar. Seine Kompression zielt darauf ab, dass wirklich nur die hörbaren Teile einer Tonspur in den MP3-Stream übertragen werden. Für das menschliche Ohr nicht hörbare Teile werden einfach ausgelassen. MP3 sollte heuzutage nicht mehr benutzt werden, da seine Kompression längst überholt ist und er nur zwei Kanäle (also Stereosound) unterstützt, auch wenn er noch extrem weit verbreitet ist.
    Auch längst Kult: Die ID3-Tags der MP3-Dateien.
    FFmepg nutzt libmp3lame als Encoder aus dem LAME-Projekt.
  • Vorbis:
    Vorbis ist der komplett freie Audiocodec von xiph.org und der einzige Codec von xiph.org, der eine einigermaßen große Verwendung fand. Besonders bei Spieleherstellern ist der Codec beliebt, da sie mit Vorbis nicht Gefahr laufen, Patente zu verletzten. Vorbis unterstützt variable Datenraten und ist MP3, auch wegen der besseren Kompression, mittlerweise vorzuziehen (nicht jedoch AAC). Eher beiläufiges Feature: Vorbis speichert theoretisch bis zu 255 Kanäle und bietet mit Vorbis comments eine flexibelere Möglichkeit Metadaten zu speichern als MP3 oder AAC!
    FFmpeg nutzt den Encoder für libvorbis für den Vorbis-Codec.

Bei den Video- wie auch Audiocodecs gilt zu beachten: Einige der Kompressionsverfahren haben sich einige Firmen patentieren lassen (allen voran die MPEG und deren Codecs)! Komplett freie Codecs sind nur Theora und Vorbis in Verbindung mit dem OGG-Container.

So, das sollte als Theorie für heute reichen. Codec-spezifische Themen, wie Farbsysteme, Kompressionsverfahren und Level, werde ich in einem der nächsten Tutorials ansprechen.
In den nächsten Tagen werde ich noch ein Tutorial zur Installation von FFmpeg schreiben. Die Nutzung und die Syntax von FFmepg erkläre ich dann direkt an der Nutzung einiger Codecs, die bei dieser Gelegenheit auch genauer erklärt werden.

Gruß
bastla :)
 

Anhänge

  • transcoding_process.png
    transcoding_process.png
    35,9 KB · Aufrufe: 3.475
Zuletzt bearbeitet:
Schöne Einführung.

Ich hab in diesem Jahr auch angefangen ffmpeg zu benutzen, aber die Syntax war mir für meine (wiederholenden) Aufgaben zu komplex.
Ich hab mir daher einen Batch-Wrapper für ffmpeg geschrieben:

Code:
@echo off
setlocal EnableDelayedExpansion
:: VERSION 0.2a
:: Creator Andreas "Obi-Wahn" Kanobel
:: www.obi-wahn.net
if "%1"=="-help" goto help
set command=%1
if /i "%command%"=="mp3" (
	set input=%2
	set output=%3
	set artist=%4
	set title=%5
	goto continue
)
if /i "%command%"=="wm" (
	set input=%2
	set watermark=%3
	set output=%4
	goto continue
)
if /i "%command%"=="imageWM" (
	set input=%2
	set watermark=%3
	set output=%4
	goto continue
)
if /i "%command%"=="thumb" (
	set input=%2
	set location=%3
	set output=%4
	goto continue
)
exit /b

:continue
:: GLOBAL SETTINGS
set ffmpeg=%cd%\ffmpeg.exe
set return=%cd%

:: WATERMARK SETTINGS
set vcodec=libx264
set vprofile=high
set preset=slow
set filter="scale=-1:1080,overlay=main_w-overlay_w:main_h-overlay_h"
set threads=0
set acodec=ac3
set abitrate=128k

:: IMAGE WATERMARK SETTINGS
set width=1024
set height=768
set quality=2
set filter="scale=%width%:%height%,overlay=main_w-overlay_w:main_h-overlay_h"

:: THUMBNAIL SETTINGS
set width=1280
set height=720
set quality=2


cd /D "%input%" > nul
goto execute%errorlevel%


:execute0
if not exist "%output%" md "%output%"
for /f "delims=;" %%i in ('dir /B /X "%input%"') do (
	:: SET FOR-LOOP COMMANDS --v
	set mp3_for=-i "%input%\%%i" -q:a 0 "%output%\%%~ni.mp3"
	set wm_for=-i "%input%\%%i" -i "%watermark%" -vcodec %vcodec% -vprofile %vprofile% -preset %preset% -filter_complex "%filter%" -threads %threads% -acodec %acodec% -b:a %abitrate% "%output%\%%~ni.mp4"
	set imageWM_for=-i "%input%\%%i" -i "%watermark%" -an -f image2 -qscale:v %quality% -filter_complex "%filter%" "%output%\%%~ni.jpg"
	set thumb_for=-i "%input%\%%i" -an -ss "%location%" -t 0:0:0.001 -f image2 -qscale:v %quality% -s %width%x%height% "%output%\thumb_%%~ni.jpg"
	:: SET FOR-LOOP COMMANDS --^
	"%ffmpeg%" -y !%command%_for!
)
cd /D "%return%"
exit /b

:execute1
:: SET SINGLE FILE COMMANDS --v
set mp3_dir=-i %input% -metadata title=%title% -metadata artist=%artist% -id3v2_version 3 -q:a 0 %output%
set wm_dir=-i %input% -i %watermark% -vcodec %vcodec% -vprofile %vprofile% -preset %preset% -filter_complex "%filter%" -threads %threads% -acodec %acodec% -b:a %abitrate% %output%
set imageWM_dir=-i %input% -i %watermark% -an -f image2 -qscale:v %quality% -filter_complex "%filter%" %output%
set thumb_dir=-i %input% -an -ss "%location%" -t 0:0:0.001 -f image2 -qscale:v %quality% -s %width%x%height% %output%
:: SET SINGLE FILE COMMANDS --^
"%ffmpeg%" -y !%command%_dir!
exit /b




:help
echo.
echo ^ ff.bat - a batch ffmpeg wrapper
echo.
echo.
echo ^ ff.bat mp3 input output artist title
echo ^    input      File or Folder containing Videos
echo ^    output     File or Folder where the mp3 should be stored
echo ^    artist     Artist ID3v2 Tag (Optional, not working with folders)
echo ^    title      Title ID3v2 Tag (Optional, not working with folders)
echo.
echo ^ ff.bat wm input watermark output
echo ^    input      Source Video or Folder
echo ^    watermark  Watermark image
echo ^    output     Output Video or Folder
echo.
echo ^ ff.bat imageWM input watermark output
echo ^    input      Source images
echo ^    watermark  Watermark image
echo ^    output     Output image or folder
echo.
echo ^ ff.bat thumb input location output
echo ^    input      Source Video or Folder
echo ^    location   Timeindex of the thumbnail (hh:mm:ss)
echo ^    output     Storage location of the thumbnail or Folder
echo.
exit /b
 
Oben