Weiter zum Inhalt

24. August 2015

Livestreaming mit ffmpeg und HTML5

Update:

Ich bin nun auf eine Lösung der Wiedergabeprobleme unter Windows 10 gekommen. Anscheinend hat Microsoft etwas am Caching der Daten geändert.
Der Internet Explorer und Microsoft Edge versuchen aggressiver Daten zu cachen. So wurde das mpd-File nur einmal vom Server geladen und dann immer wieder gecacht. Dementsprechend wusste der Browser irgendwann nicht mehr, dass er neue Daten nachladen soll.

Die Lösung war den Apache Server einen Cache-Controll-Header mitzuschicken zu lassen. Das kann zum Beispiel so aussehen:

<Directory "D:/xampp/htdocs/chunks">
	<IfModule mod_headers.c>
		Header add Expires "Sun, 19 Nov 1978 05:00:00 GMT"
		Header add Cache-Control "no-store, no-cache, must-revalidate, post-check=0, pre-check=0"
	</IfModule>
</Directory>

Diese Konfiguration wird in die httpd.conf des Apaches eingefügt. Den Pfad zu euren Chunks muss im Directory-Tag natürlich angepasst werden.


 

Ich war in letzter Zeit auf der Suche nach einer Möglichkeit, Videoinhalte (z.B. Livebilder einer Webcam) über das Web zu streamen.

In diesem Bereich gibt es einige Lösungen, die Geld kosten (z.B. Wowza Media Streaming Server, Adobe Media Streaming Server) und auf das Browserplugin Adobe Flash Player setzen. Gerade in letzter Zeit gab es einige Sicherheitslücken im Flash Player, so dass ich ebenfalls darauf verzichten möchte.

Die meisten aktuellen Browser wie Mozilla Firefox, Google Chrome, Microsoft Internet Explorer unterstützt den vom W3 Konsortium festgelegten Standard der Media Source Extensions. Diese Schnittstelle ermöglicht es mittels JavaScript bzw. AJAX Video und Audio in Stücken (Chunks) vom Webserver zu laden und dem HTML5-Video-Element als Quelle zu übergeben.

Auf diese Weise können Video und Audio im Browser ohne zusätzliche Plugins, wie den Adobe Flash Player oder Microsoft Silverlight, abgespielt werden.

Ich konnte das Ganze mit einigen Browsern testen, leider funktionierte es nicht auf allen:

  • Mozilla Firefox 40.0.2: läuft (über about:config muss media.mediasource.whitelist auf false gesetzt werden)
  • Google Chrome 44.0.2403.157: läuft
  • Microsoft Internet Explorer 11.0.9600.17937 mit Update 11.0.22 (Windows 8.1): läuft
  • Microsoft Internet Explorer 11.0.10240 mit Update 11.0.22 (Windows 10): läuft läuft nicht (startet, bricht dann ab)
  • Microsoft Internet Explorer (Windows Phone 8.1 14234.375) läuft
  • Microsoft Edge: läuft läuft nicht (startet, bricht dann ab)
  • Microsoft Edge (Windows 10 Mobile 10512): läuft läuft nicht (startet, bricht dann ab)
  • Dolphin JetPack (Android): läuft nicht
  • Google Chrome (Android): läuft nicht

Leider läuft es auf meinen getesteten Mobilgeräten nicht rund. Ich hoffe die Anbieter können hier noch nachbessern.

Nun aber zur Umsetzung. Wie ich oben bereits erwähnt habe, müssen wir den Browser mit Häppchen an Video- und Audiodaten füttern. Dazu benötigen wir einen Segmenter, der das ursprüngliche Videosignal in Stücke aufteilt und Video/Audio in verschiedenen Dateien (Chunks) ablegt.

Eventuell ist uns der Eingabevideostream, z.B. von einer Webcam, zu groß um sie über unseren Internetanschluss ins Web zu streamen. Hat unser Eingabestream z.B. eine Bitrate von 15 MBit/s und unser Internetanschluss nur eine Uploadrate von 10 MBit/s, funktioniert das natürlich nicht. Wir müssen die Eingabe transcodieren, damit die Ausgabe in Echtzeit an den Browser gesendet werden kann.

Die gute Nachricht ist, das Tool ffmpeg kann beides: Transcodierung und Segmentierung. Ladet euch die neueste Version herunter. Bei der Version für Windows darauf achten, dass ihr die “static”-Version ladet.

Als nächstes benötigt man einen Webserver (z.B. Apache), damit die Daten an den Webbrowser gesendet werden können. Am einfachsten geht das mit der Installation von XAMPP. Für dieses Tutorial müsst ihr nur den Apache-Webserver installieren. MySQL, usw. benötigt ihr nicht.

Nach der Installation und dem Starten des Apache-Webservers, legt ihr im Ordner htdocs des XAMPP-Verzeichnisses einen neuen Ordner an, zum Beispiel stream.
Um uns das Leben zu vereinfachen, laden wir uns die DASH.js (Rechtsklick -> Speichern unter…) Bibliothek herunter und speichern sie in dem gerade angelegten Ordner stream, oder einem Unterordner nach Wahl.
Ebenfalls legen wir nun eine HTML-Datei an, die ein HTML5-Videoelement und den dazugehörigen JavaScript-Code beinhaltet.

<!DOCTYPE html>
<html>
<head>
	<title>Streaming</title>
	<script type="text/javascript" src="dash.all.js"></script>
</head>
<body>
    <video id="player" width="1280" height="720" controls></video>
    
    <script>
    // setup the video element and attach it to the Dash player
    var url = "chunks/stream.mpd";

    var context = new Dash.di.DashContext();
    var player = new MediaPlayer(context);

    player.startup();
    player.attachView(document.querySelector("#player"));
    player.attachSource(url);

    </script>
</body>
</html>

Über euren Browser solltet ihr nun die URL http://127.0.0.1/stream/ aufrufen und das Videoelement sehen können. Solltet ihr die dash.all.js in einem Unterordner gespeichert haben, muss das src-Attribut des script-Tag im head noch angepasst werden.

Als nächstes legen wir einen Ordner namens chunks im Ordner stream an. Darin werden die Chunks, die wir von ffmpeg bekommen, gespeichert. Ebenso ein Manifest, das dem Browser sagt welche Teile des Videos geladen werden sollen.

Aus dem ffmpeg-Archiv benötigt ihr nun die ffmpeg Datei bzw. ffmpeg.exe. Extrahiert diese in einen Ordner eurer Wahl und kopiert euch den Pfad.
Öffnet nun ein Konsolenfenster (Windows: Win+R und cmd eingeben) und navigiert in den Ordner chunks. Auf meinem PC beötigte ich folgende Befehle:

cd D:\xampp\stream\chunks && D:

Damit wird das Verzeichnis und die Partition gewechselt. Solltet ihr euer XAMPP auf der Systempartition haben, entfällt der Teil hinter && .

Nun müssen wir ffmpeg starten und so einstellen, dass wir die gewünschte Ausgabe erhalten. In meinem Beispiel soll die Ausgabe eine maximale Videobitrate von 4000 kbit/s und eine Audiobitrate von 128 kbit/s haben. Als Codecs kommen H.264 (Video) und AAC (Audio) zum Einsatz.

<Pfad zu ffmpeg>\ffmpeg.exe -i <Pfad zur Eingabedatei/Eingabestream> -vcodec libx264 -preset medium -tune zerolatency -profile:v high -b:v 4000k -maxrate 4000k -bufsize <2*maxrate>k -force_key_frames expr:gte(t,n_forced*5) -r 25 -vf "yadif=0:-1:0,scale=1280x720" -qmin 19 -threads 0 -strict experimental -acodec aac -b:a 128k -ac 2 -ar 44100 -af aresample=async=1000 -f dash -window_size 5 -extra_window_size 5 -remove_at_exit 1 stream.mpd

Gleichzeitig wird die Auflösung auf 1280×720 gesetzt und alle 5 Sekunden ein Keyframe forciert. Zum Schluss soll das Ausgabeformat dash sein (-f dash) mit dem dazugehörigen Manifest stream.mpd.

Habt ihr ffmpeg gestartet, werden die entsprechenden Chunks für Video und Audio in das Verzeichnis chunks kopiert und das Manifest geupdated.

Nun sollte beim Aufruf der zuvor eingerichteten Webseite das transkodierte Video zu sehen sein.

Kommentare wurden geschlossen.