I' m wirklich stecken versucht, den besten Weg zu verstehen, Echtzeit-Ausgabe von ffmpeg zu einem HTML5-Client mit node.js zu streamen, da es eine Reihe von Variablen im Spiel sind und ich don' t haben eine Menge Erfahrung in diesem Raum, nachdem viele Stunden versucht, verschiedene Kombinationen. Mein Anwendungsfall ist:
liveFFMPEG = child_process.spawn("ffmpeg", [
"-i", "rtsp://admin:[email protected]:554" , "-vcodec", "copy", "-f",
"mp4", "-reset_timestamps", "1", "-movflags", "frag_keyframe+empty_moov",
"-" // output to stdout
], {detached: false});
liveFFMPEG.stdout.pipe(resp);
Ich habe auch das Stream-Ereignis verwendet, um die FFMPEG-Daten in die HTTP-Antwort zu schreiben, aber das macht keinen Unterschied
xliveFFMPEG.stdout.on("data",function(data) {
resp.write(data);
}
Ich verwende den folgenden HTTP-Header (der auch beim Streaming voraufgezeichneter Dateien verwendet wird und funktioniert)
var total = 999999999 // fake a large file
var partialstart = 0
var partialend = total - 1
if (range !== undefined) {
var parts = range.replace(/bytes=/, "").split("-");
var partialstart = parts[0];
var partialend = parts[1];
}
var start = parseInt(partialstart, 10);
var end = partialend ? parseInt(partialend, 10) : total; // fake a large file if no range reques
var chunksize = (end-start)+1;
resp.writeHead(206, {
'Transfer-Encoding': 'chunked'
, 'Content-Type': 'video/mp4'
, 'Content-Length': chunksize // large size to fake a file
, 'Accept-Ranges': 'bytes ' + start + "-" + end + "/" + total
});
EDIT 3: Ab IOS 10 wird HLS fragmentierte mp4-Dateien unterstützen. Die Lösung ist es, fragmentierte mp4-Assets mit einem DASH- und HLS-Manifest zu erstellen. Tun Sie so, als ob Flash, iOS9 und darunter und IE 10 und darunter nicht existieren würden.
EDIT 2: Wie die Leute in den Kommentaren anmerken, ändern sich die Dinge. Fast alle Browser werden AVC/AAC-Codecs unterstützen. iOS benötigt immer noch HLS. Aber über Adaptoren wie hls.js kann man
HLS in MSE. Die neue Antwort ist HLS+hls.js, wenn Sie iOS benötigen. oder einfach Fragmentiertes MP4 (d.h. DASH), wenn Sie es nicht brauchen
Es gibt viele Gründe, warum Video und insbesondere Live-Video sehr schwierig ist. (Bitte beachten Sie, dass in der ursprünglichen Frage angegeben wurde, dass HTML5-Video eine Voraussetzung ist, der Fragesteller aber in den Kommentaren angab, dass Flash möglich ist. Daher ist diese Frage sofort irreführend)
Zunächst möchte ich wiederholen: ES GIBT KEINE OFFIZIELLE UNTERSTÜTZUNG FÜR LIVE-STREAMING ÜBER HTML5. Es gibt Hacks, aber das kann variieren.
EDIT: Seit ich diese Antwort geschrieben habe, sind Media Source Extensions gereift,
und sind nun kurz davor, eine brauchbare Option zu werden. Sie werden unterstützt auf den meisten großen Browsern. IOS ist nach wie vor ein Hindernis.
Als Nächstes müssen Sie verstehen, dass Video on Demand (VOD) und Live-Video sehr unterschiedlich sind. Ja, es handelt sich bei beiden um Video, aber die Probleme sind unterschiedlich, und daher sind auch die Formate unterschiedlich. Wenn zum Beispiel die Uhr in Ihrem Computer 1 % schneller läuft als sie sollte, werden Sie das bei einem VOD nicht bemerken. Bei Live-Videos versuchen Sie, das Video abzuspielen, bevor es passiert. Wenn Sie sich in einen laufenden Live-Videostream einklinken wollen, benötigen Sie die Daten, die zur Initialisierung des Decoders erforderlich sind, d. h. sie müssen im Stream wiederholt oder außerhalb des Bandes gesendet werden. Bei VOD können Sie den Anfang der Datei lesen und an einem beliebigen Punkt suchen.
Lassen Sie uns nun ein wenig eintauchen.
Plattformen:
Codecs:
Gängige Übertragungsmethoden für Live-Video in Browsern:
Gängige Bereitstellungsmethoden für VOD in Browsern:
html5 video tag:
Sehen wir uns an, welche Browser welche Formate unterstützen
Safari:
Firefox
IE
Chrome
MP4 kann nicht für Live-Video verwendet werden (HINWEIS: DASH ist eine Obermenge von MP4, also nicht damit verwechseln). MP4 wird in zwei Teile zerlegt: moov und mdat. mdat enthält die rohen Audio- und Videodaten. Sie sind jedoch nicht indiziert, so dass sie ohne moov nutzlos sind. Das moov enthält einen Index aller Daten im mdat. Aufgrund seines Formats kann es jedoch nicht geglättet werden, bis die Zeitstempel und die Größe JEDES Einzelbildes bekannt sind. Es ist zwar möglich, eine Moov-Datei zu erstellen, die die Frame-Größen fälscht, aber das ist sehr verschwenderisch in Bezug auf die Bandbreite.
Wenn Sie also überall liefern wollen, müssen wir den kleinsten gemeinsamen Nenner finden. Sie werden sehen, dass es hier kein LCD gibt, ohne auf Flash zurückzugreifen Beispiel:
Das, was einem LCD am nächsten kommt, ist die Verwendung von HLS für iOS-Nutzer und Flash für alle anderen. Mein persönlicher Favorit ist es, HLS zu kodieren und dann Flash zu verwenden, um HLS für alle anderen abzuspielen. Sie können HLS in Flash über JW Player 6 abspielen (oder Ihr eigenes HLS in FLV in AS3 schreiben, wie ich es getan habe).
Bald wird die gängigste Methode HLS auf iOS/Mac und DASH über MSE überall sonst sein (so wird es auch Netflix bald machen). Aber wir warten immer noch darauf, dass alle ihre Browser aktualisieren. Sie werden wahrscheinlich auch ein separates DASH/VP9 für Firefox benötigen (ich weiß von open264; es ist scheiße. Es kann keine Videos im Haupt- oder Hochprofil darstellen. Also ist es derzeit nutzlos).
Vielen Dank an alle, insbesondere an szatmary, da dies eine komplexe Frage ist und viele Ebenen hat, die alle funktionieren müssen, bevor man Live-Video streamen kann. Um meine ursprüngliche Frage und die Verwendung von HTML5-Video im Vergleich zu Flash zu klären - mein Anwendungsfall hat eine starke Präferenz für HTML5, weil es generisch ist, einfach auf dem Client zu implementieren und die Zukunft. Flash ist weit abgeschlagen an zweiter Stelle, also bleiben wir in dieser Frage bei HTML5.
Ich habe durch diese Übung viel gelernt und stimme zu, dass Live-Streaming viel schwieriger ist als VOD (das gut mit HTML5-Video funktioniert). Aber ich habe das für meinen Anwendungsfall zufriedenstellend hinbekommen und die Lösung erwies sich als sehr einfach, nachdem ich komplexere Optionen wie MSE, Flash und ausgeklügelte Puffersysteme in Node ausprobiert hatte. Das Problem war, dass FFMPEG das fragmentierte MP4 beschädigte und ich die FFMPEG-Parameter anpassen musste, und die Standard-Node-Stream-Pipe-Umleitung über http, die ich ursprünglich verwendete, war alles, was benötigt wurde.
In MP4 gibt es eine 'Fragmentierung' Option, die das MP4 in viel kleinere Fragmente zerlegt, die ihren eigenen Index haben und die MP4-Live-Streaming-Option praktikabel machen. Es ist jedoch nicht möglich, in den Stream zurückzusuchen (was für meinen Anwendungsfall OK ist), und spätere Versionen von FFMPEG unterstützen die Fragmentierung.
Beachten Sie, dass das Timing ein Problem sein kann, und bei meiner Lösung habe ich eine Verzögerung zwischen 2 und 6 Sekunden, die durch eine Kombination aus Remuxen verursacht wird (FFMPEG muss den Live-Stream empfangen, remuxen und dann an den Knotenpunkt senden, um ihn über HTTP zu übertragen). Daran lässt sich nicht viel ändern, aber in Chrome versucht das Video, so viel wie möglich aufzuholen, was das Video etwas ruckelig macht, aber aktueller als im IE11 (meinem bevorzugten Client).
Anstatt zu erklären, wie der Code funktioniert in diesem Beitrag, überprüfen Sie die GIST mit Kommentaren (der Client-Code ist nicht enthalten, es ist ein Standard-HTML5-Video-Tag mit dem Knoten http-Server-Adresse). GIST ist hier: https://gist.github.com/deandob/9240090
Ich war nicht in der Lage, ähnliche Beispiele für diesen Anwendungsfall zu finden, daher hoffe ich, dass die obige Erklärung und der Code anderen helfen, zumal ich so viel von dieser Website gelernt habe und mich immer noch als Anfänger betrachte!
Obwohl dies die Antwort auf meine spezielle Frage ist, habe ich szatmary's Antwort als die akzeptierte Antwort ausgewählt, da sie am umfassendsten ist.
Dies ist ein weit verbreiteter Irrglaube. Es gibt keine Live-HTML5-Video-Unterstützung (außer für HLS auf iOS und Mac Safari). Möglicherweise können Sie es mit einem Webm-Container "hacken", aber ich würde nicht erwarten, dass das allgemein unterstützt wird. Was Sie suchen, ist in den Media Source Extensions enthalten, wo Sie die Fragmente an den Browser ein zu einer Zeit zu füttern. aber Sie müssen einige Client-Seite Javascript zu schreiben.