Bester Ansatz für Echtzeit-http-Streaming zum HTML5-Video-Client

212

Ich bin wirklich festgefahren, um zu verstehen, wie man die Echtzeitausgabe von ffmpeg mit node.js am besten auf einen HTML5-Client streamen kann, da eine Reihe von Variablen im Spiel sind und ich nicht viel Erfahrung in diesem Bereich habe. Ich habe viele Stunden damit verbracht, verschiedene Kombinationen auszuprobieren.

Mein Anwendungsfall ist:

1) Der RTSP H.264-Stream der IP-Videokamera wird von FFMPEG aufgenommen und unter Verwendung der folgenden FFMPEG-Einstellungen im Knoten in einen MP4-Container übertragen und an STDOUT ausgegeben. Dies wird nur bei der ersten Clientverbindung ausgeführt, damit Teilinhaltsanforderungen nicht erneut versuchen, FFMPEG zu erzeugen.

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});

2) Ich verwende den Knoten-HTTP-Server, um das STDOUT zu erfassen und es auf Clientanforderung an den Client zurückzusenden. Wenn der Client zum ersten Mal eine Verbindung herstellt, spawne ich die obige FFMPEG-Befehlszeile und leite dann den STDOUT-Stream an die HTTP-Antwort weiter.

liveFFMPEG.stdout.pipe(resp);

Ich habe das Stream-Ereignis auch verwendet, um die FFMPEG-Daten in die HTTP-Antwort zu schreiben, aber es macht keinen Unterschied

xliveFFMPEG.stdout.on("data",function(data) {
        resp.write(data);
}

Ich verwende den folgenden HTTP-Header (der auch beim Streamen von aufgezeichneten 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
});

3) Der Client muss HTML5-Video-Tags verwenden.

Ich habe keine Probleme mit der Streaming-Wiedergabe (unter Verwendung von fs.createReadStream mit 206 HTTP-Teilinhalten) auf dem HTML5-Client eine Videodatei, die zuvor mit der obigen FFMPEG-Befehlszeile aufgezeichnet wurde (aber in einer Datei anstelle von STDOUT gespeichert wurde), sodass ich den FFMPEG-Stream kenne ist korrekt, und ich kann das Video-Live-Streaming in VLC sogar korrekt sehen, wenn eine Verbindung zum HTTP-Knotenserver hergestellt wird.

Der Versuch, live von FFMPEG über den Knoten HTTP zu streamen, scheint jedoch viel schwieriger zu sein, da der Client einen Frame anzeigt und dann stoppt. Ich vermute, das Problem ist, dass ich die HTTP-Verbindung nicht so einrichte, dass sie mit dem HTML5-Video-Client kompatibel ist. Ich habe eine Vielzahl von Dingen ausprobiert, z. B. die Verwendung von HTTP 206 (Teilinhalt) und 200 Antworten, das Speichern der Daten in einen Puffer und das Streaming ohne Glück. Daher muss ich zu den ersten Prinzipien zurückkehren, um sicherzustellen, dass ich dies richtig einrichte Weg.

Hier ist mein Verständnis, wie dies funktionieren sollte. Bitte korrigieren Sie mich, wenn ich falsch liege:

1) FFMPEG sollte so eingerichtet werden, dass die Ausgabe fragmentiert wird und ein leerer Moov verwendet wird (FFMPEG frag_keyframe und empty_moov mov Flags). Dies bedeutet, dass der Client nicht das moov-Atom verwendet, das sich normalerweise am Ende der Datei befindet, was beim Streaming nicht relevant ist (kein Dateiende), sondern dass keine Suche möglich ist, was für meinen Anwendungsfall in Ordnung ist.

2) Obwohl ich MP4-Fragmente und leeres MOOV verwende, muss ich immer noch HTTP-Teilinhalt verwenden, da der HTML5-Player vor dem Abspielen wartet, bis der gesamte Stream heruntergeladen ist, was bei einem Live-Stream niemals endet und daher nicht funktioniert.

3) Ich verstehe nicht, warum das Weiterleiten des STDOUT-Streams an die HTTP-Antwort beim Live-Streaming noch nicht funktioniert. Wenn ich in einer Datei speichere, kann ich diese Datei mit ähnlichem Code problemlos an HTML5-Clients streamen. Möglicherweise handelt es sich um ein Zeitproblem, da es eine Sekunde dauert, bis der FFMPEG-Spawn gestartet, eine Verbindung zur IP-Kamera hergestellt und Chunks an den Knoten gesendet werden. Die Knotendatenereignisse sind ebenfalls unregelmäßig. Der Bytestream sollte jedoch genau dem Speichern in einer Datei entsprechen, und HTTP sollte Verzögerungen berücksichtigen können.

4) Beim Überprüfen des Netzwerkprotokolls vom HTTP-Client beim Streamen einer von FFMPEG erstellten MP4-Datei von der Kamera werden drei Clientanforderungen angezeigt: Eine allgemeine GET-Anforderung für das Video, die der HTTP-Server etwa 40 KB zurückgibt, dann eine teilweise Inhaltsanforderung mit einem Bytebereich für die letzten 10 KB der Datei, dann eine endgültige Anforderung für die nicht geladenen Bits in der Mitte. Vielleicht fragt der HTML5-Client nach Erhalt der ersten Antwort nach dem letzten Teil der Datei, um das MP4-MOOV-Atom zu laden? In diesem Fall funktioniert das Streaming nicht, da keine MOOV-Datei und kein Dateiende vorhanden ist.

5) Wenn ich das Netzwerkprotokoll überprüfe, wenn ich versuche, live zu streamen, erhalte ich eine abgebrochene erste Anforderung mit nur etwa 200 empfangenen Bytes, dann eine erneut abgebrochene erneute Anforderung mit 200 Bytes und eine dritte Anforderung, die nur 2 KB lang ist. Ich verstehe nicht, warum der HTML5-Client die Anforderung abbrechen würde, da der Bytestream genau der gleiche ist, den ich beim Streaming von einer aufgezeichneten Datei erfolgreich verwenden kann. Es scheint auch, dass der Knoten den Rest des FFMPEG-Streams nicht an den Client sendet, aber ich kann die FFMPEG-Daten in der Ereignisroutine .on sehen, sodass er zum HTTP-Server des FFMPEG-Knotens gelangt.

6) Obwohl ich denke, dass das Weiterleiten des STDOUT-Streams an den HTTP-Antwortpuffer funktionieren sollte, muss ich einen Zwischenpuffer und einen Stream erstellen, damit die HTTP-Clientanforderungen für Teilinhalte ordnungsgemäß funktionieren, wenn eine Datei (erfolgreich) gelesen wird ? Ich denke, dies ist der Hauptgrund für meine Probleme, aber ich bin mir in Node nicht ganz sicher, wie ich das am besten einrichten soll. Und ich weiß nicht, wie ich eine Client-Anfrage für die Daten am Ende der Datei behandeln soll, da es kein Dateiende gibt.

7) Bin ich auf dem falschen Weg, wenn ich versuche, 206 Teilinhaltsanforderungen zu bearbeiten, und sollte dies mit normalen 200 HTTP-Antworten funktionieren? HTTP 200-Antworten funktionieren für VLC einwandfrei. Ich vermute also, dass der HTML5-Video-Client nur mit Teilinhaltsanforderungen funktioniert.

Da ich dieses Zeug noch lerne, ist es schwierig, die verschiedenen Ebenen dieses Problems (FFMPEG, Knoten, Streaming, HTTP, HTML5-Video) zu bearbeiten, sodass alle Hinweise sehr geschätzt werden. Ich habe stundenlang auf dieser Website und im Internet recherchiert und bin auf niemanden gestoßen, der in der Lage war, Echtzeit-Streaming in Node durchzuführen, aber ich kann nicht der Erste sein, und ich denke, dies sollte funktionieren (irgendwie) !).

Deandob
quelle
4
Dies ist ein heikles Thema. Das wichtigste zuerst. Hast du deine Content-Typein deinen Kopf gesetzt? Verwenden Sie die Chunk-Codierung? Dort würde ich anfangen. Außerdem bietet HTML5 nicht unbedingt die Funktionalität zum Streamen. Mehr dazu lesen Sie hier . Sie müssen höchstwahrscheinlich eine Möglichkeit implementieren, den Videostream mit Ihren eigenen Mitteln zu puffern und abzuspielen ( siehe hier ), obwohl dies wahrscheinlich nicht gut unterstützt wird. Google auch in MediaSource API.
tsturzl
Danke für die Antwort. Ja, der Inhaltstyp ist 'video / mp4' und dieser Code funktioniert zum Streamen von Videodateien. Leider ist MediaSource nur Chrome, ich muss andere Browser unterstützen. Gibt es eine Spezifikation, wie der HTML5-Video-Client mit einem HTTP-Streaming-Server interagiert? Ich bin mir sicher, was ich tun möchte, nur nicht genau, wie (mit node.js, könnte aber C # oder C ++ verwenden, wenn es einfacher ist)
Deandob
2
Das Problem liegt nicht in Ihrem Backend. Sie streamen Videos ganz gut. Das Problem liegt in Ihrem Frontend / Client. Sie müssen das Streaming selbst implementieren. HTML5 verarbeitet Streams einfach nicht. Sie müssen höchstwahrscheinlich die Optionen pro Browser untersuchen. Das Lesen der w3-Standards für die Video-Tag- und Medien-APIs wäre ein guter Anfang.
tsturzl
Es scheint , dass es sollte möglich sein , diese Arbeit zu machen. Ich biete keine endgültige Antwort an, aber ich vermute, dass dieses Problem damit zusammenhängt, dass der Browser den Rest des MP4-Container-Headers / der Atome am Anfang und nicht das nächste Bild im Videostream erwartet . Wenn Sie ein MOOV-Atom für ein sehr langes Video (damit der Player weiterhin anfordert) sowie die anderen erwarteten Header senden und dann mit dem Kopieren von ffmpeg beginnen, funktioniert dies möglicherweise. Sie müssten auch die Scrub-Leiste mit js im Browser ausblenden, damit sie nicht vorwärts scannen können.
Jwriteclub
Ich würde vorschlagen, WebRTC in Betracht zu ziehen, das von Tag zu Tag eine bessere browserübergreifende Unterstützung erhält.
Alex Cohn

Antworten:

209

EDIT 3: Ab IOS 10 unterstützt HLS fragmentierte mp4-Dateien. Die Antwort besteht nun darin, fragmentierte mp4-Assets mit einem DASH- und HLS-Manifest zu erstellen. > Stellen Sie sich vor, Flash, iOS9 und niedriger und IE 10 und darunter existieren nicht.

Alles unter dieser Zeile ist veraltet. Für die Nachwelt hier aufbewahren.


EDIT 2: Wie die Leute in den Kommentaren darauf hinweisen, ändern sich die Dinge. Fast alle Browser unterstützen AVC / AAC-Codecs. iOS benötigt weiterhin HLS. Aber über Adapter wie hls.js können Sie HLS in MSE spielen. Die neue Antwort lautet HLS + hls.js, wenn Sie iOS benötigen. oder einfach nur fragmentiertes MP4 (dh DASH), wenn Sie dies nicht tun

Es gibt viele Gründe, warum Videos und insbesondere Live-Videos sehr schwierig sind. (Bitte beachten Sie, dass in der ursprünglichen Frage angegeben wurde, dass HTML5-Video erforderlich ist, der Fragesteller jedoch in den Kommentaren angegeben hat, dass Flash möglich ist. Diese Frage ist also sofort irreführend.)

Zuerst möchte ich noch einmal wiederholen: Es gibt keine offizielle Unterstützung für Live-Streaming über HTML5 . Es gibt Hacks, aber Ihr Kilometerstand kann variieren.

BEARBEITEN: Seit ich diese Antwort geschrieben habe, sind die Medienquellenerweiterungen ausgereift und stehen kurz davor, eine praktikable Option zu werden. Sie werden von den meisten gängigen Browsern unterstützt. IOS ist weiterhin ein Hindernis.

Als nächstes müssen Sie verstehen, dass Video on Demand (VOD) und Live-Video sehr unterschiedlich sind. Ja, beide sind Videos, aber die Probleme sind unterschiedlich, daher sind die Formate unterschiedlich. Wenn beispielsweise die Uhr in Ihrem Computer 1% schneller läuft als sie sollte, werden Sie auf einem VoD nichts bemerken. Bei Live-Videos versuchen Sie, Videos abzuspielen, bevor dies geschieht. Wenn Sie einem laufenden Live-Videostream beitreten möchten, benötigen Sie die zum Initialisieren des Decoders erforderlichen Daten. Sie müssen daher im Stream wiederholt oder außerhalb des Bandes gesendet werden. Mit VOD können Sie den Anfang der gesuchten Datei bis zu einem beliebigen Punkt lesen.

Lassen Sie uns jetzt ein wenig graben.

Plattformen:

  • iOS
  • PC
  • Mac
  • Android

Codecs:

  • vp8 / 9
  • h.264
  • thora (vp3)

Allgemeine Übermittlungsmethoden für Live-Videos in Browsern:

  • DASH (HTTP)
  • HLS (HTTP)
  • Flash (RTMP)
  • Blitz (HDS)

Allgemeine Übermittlungsmethoden für VoD in Browsern:

  • DASH (HTTP-Streaming)
  • HLS (HTTP-Streaming)
  • Flash (RTMP)
  • Flash (HTTP-Streaming)
  • MP4 (HTTP-Pseudo-Streaming)
  • Ich werde nicht über MKV und OOG sprechen, weil ich sie nicht sehr gut kenne.

HTML5-Video-Tag:

  • MP4
  • webm
  • ogg

Schauen wir uns an, welche Browser welche Formate unterstützen

Safari:

  • HLS (nur iOS und Mac)
  • h.264
  • MP4

Feuerfuchs

  • DASH (über MSE, aber keine h.264)
  • h.264 nur über Flash!
  • VP9
  • MP4
  • OGG
  • Webm

IE

  • Blitz
  • DASH (nur über MSE IE 11+)
  • h.264
  • MP4

Chrom

  • Blitz
  • DASH (über MSE)
  • h.264
  • VP9
  • MP4
  • webm
  • ogg

MP4 kann nicht für Live-Videos verwendet werden (HINWEIS: DASH ist eine Obermenge von MP4, also verwechseln Sie sich nicht damit). MP4 ist in zwei Teile geteilt: moov und mdat. mdat enthält die Audio-Video-Rohdaten. Aber es ist nicht indiziert, also ist es ohne das Moov nutzlos. Das moov enthält einen Index aller Daten im mdat. Aufgrund seines Formats kann es jedoch nicht "abgeflacht" werden, bis die Zeitstempel und die Größe JEDES Frames bekannt sind. Es kann möglich sein, ein Moov zu konstruieren, das die Rahmengrößen "fibriert", aber in Bezug auf die Bandbreite sehr verschwenderisch ist.

Wenn Sie also überall liefern möchten, müssen wir den kleinsten gemeinsamen Nenner finden. Sie werden sehen, dass es hier kein LCD gibt, ohne auf das Blitzbeispiel zurückzugreifen:

  • iOS unterstützt nur h.264-Videos. und es unterstützt nur HLS für Live.
  • Firefox unterstützt h.264 überhaupt nicht, es sei denn, Sie verwenden Flash
  • Flash funktioniert unter iOS nicht

Das, was einem LCD am nächsten kommt, ist die Verwendung von HLS, um Ihre iOS-Benutzer zu erreichen, und das Blinken für alle anderen. Mein persönlicher Favorit ist es, HLS zu codieren und dann mit Flash HLS für alle anderen zu spielen. Sie können HLS in Flash über JW Player 6 spielen (oder wie ich Ihr eigenes HLS in AS3 in FLV schreiben).

In Kürze wird HLS unter iOS / Mac und DASH über MSE überall am häufigsten verwendet (dies wird Netflix in Kürze tun). Wir warten jedoch immer noch darauf, dass alle ihre Browser aktualisieren. Sie werden wahrscheinlich auch ein separates DASH / VP9 für Firefox benötigen (ich weiß über open264 Bescheid; es ist scheiße. Es kann keine Videos in Haupt- oder High-Profile-Qualität machen. Daher ist es derzeit nutzlos).

szatmary
quelle
Vielen Dank an szatmary für den detaillierten Hintergrund und die Vor- und Nachteile der verschiedenen Optionen. Ich habe diese Antwort als die akzeptierte ausgewählt, da die Gliederung der Konzepte wichtiger ist als die spezifische Korrektur, die ich zur Beantwortung der ursprünglichen Frage gefunden habe. Viel Glück mit dem Kopfgeld!
Deandob
9
Dies ist keine funktionierende Lösung für diese Frage. Im Folgenden finden Sie eine funktionierende Lösung für dieses Problem.
Jwriteclub
2
Firefox unterstützt jetzt MSE und h.264 nativ. Gehen Sie zur Bestätigung mit dem neuesten FF-Browser auf www.youtube.com/html5. Ich habe mit FF 37 getestet. Safari 8+ auf Mac unterstützt jetzt auch MSE.
BigTundra
@ BigTundra Ja, Safari unterstützt MSE seit dem Start von Yosemite auf dem Mac. Aber nicht iOS. Ich bin mir nicht sicher über Windows. (Ist Safari unter Windows immer noch eine Sache?) Firefox 37.0.2 auf (meinem) Mac scheint MSE laut diesem Link überhaupt nicht zu unterstützen. Unterstützt aber H.264. Firefox hat in der Vergangenheit H.264-Unterstützung hinzugefügt, entfernt und erneut hinzugefügt.
Szatmary
Aktuelle
Maxence
75

Vielen Dank an alle, besonders an szatmary, da dies eine komplexe Frage ist und viele Ebenen hat, die alle funktionieren müssen, bevor Sie Live-Videos streamen können. Um meine ursprüngliche Frage und die Verwendung von HTML5-Videos im Vergleich zu Flash zu klären, hat mein Anwendungsfall eine starke Präferenz für HTML5, da es allgemein gehalten und auf dem Client und in der Zukunft einfach zu implementieren ist. Flash ist ein entfernter Zweitbester, also bleiben wir bei HTML5 für diese Frage.

Ich habe durch diese Übung viel gelernt und bin mir einig, dass Live-Streaming viel schwieriger ist als VOD (was gut mit HTML5-Videos funktioniert). Aber ich habe dafür gesorgt, dass dies für meinen Anwendungsfall zufriedenstellend funktioniert, und die Lösung hat sich als sehr einfach herausgestellt, nachdem ich komplexere Optionen wie MSE, Flash und ausgefeilte Pufferungsschemata in Node verfolgt habe. Das Problem war, dass FFMPEG das fragmentierte MP4 beschädigte und ich die FFMPEG-Parameter anpassen musste und die ursprünglich verwendete Standard-Node-Stream-Pipe-Umleitung über http alles war, was benötigt wurde.

In MP4 gibt es eine "Fragmentierungs" -Option, die die mp4 in viel kleinere Fragmente aufteilt, die einen eigenen Index hat und die mp4-Live-Streaming-Option funktionsfähig macht. Es ist jedoch nicht möglich, in den Stream zurückzukehren (OK für meinen Anwendungsfall), 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 des Remuxing verursacht wird (effektiv muss FFMPEG den Live-Stream empfangen, remuxen und dann an den Knoten senden, um ihn über HTTP bereitzustellen). . Hier kann nicht viel getan werden, aber in Chrome versucht das Video so viel wie möglich aufzuholen, was das Video etwas nervös, aber aktueller als IE11 (mein bevorzugter Client) macht.

Anstatt zu erklären, wie der Code in diesem Beitrag funktioniert, lesen Sie die GIST mit Kommentaren (der Client-Code ist nicht enthalten, es handelt sich um ein Standard-HTML5-Video-Tag mit der HTTP-Server-Adresse des Knotens). GIST ist hier: https://gist.github.com/deandob/9240090

Ich konnte keine ähnlichen Beispiele für diesen Anwendungsfall finden, daher hoffe ich, dass die obige Erklärung und der obige Code anderen helfen, zumal ich auf dieser Website so viel gelernt habe und mich immer noch als Anfänger betrachte!

Obwohl dies die Antwort auf meine spezifische Frage ist, habe ich die Antwort von szatmary als die akzeptierte ausgewählt, da sie die umfassendste ist.

Deandob
quelle
33
Entschuldigung, aber ich habe das selbst gefunden. Das Aufschreiben meiner Antwort macht dies ziemlich deutlich. Die früheren Antworten waren alle hilfreich und geschätzt, trugen aber nicht wesentlich dazu bei, und ich habe sogar den Arbeitscode im GIST eingereicht, und niemand anderes hat dies getan. Ich interessiere mich nicht für den 'Ruf', ich möchte wissen, ob mein Ansatz und mein Code verbessert werden können. Und die Antwort, die ich angekreuzt habe, hat mein Problem gelöst, daher bin ich verwirrt darüber, worum es hier geht. Ich bin ziemlich neu in SO, daher bin ich froh, dass ich aufgefordert werde, auf andere Weise zu interagieren. Ich finde diese Seite nützlich und meine Antwort sollte anderen helfen.
Deandob
2
Es scheint in dieser Community nicht richtig zu sein, Ihre Antwort als akzeptierte Antwort auszuwählen, wenn Sie die Frage gestellt haben, auch wenn dadurch das ursprüngliche Problem behoben wurde. Obwohl dies nicht intuitiv zu sein scheint, ist die Dokumentation der Konzepte wichtiger als die eigentliche Korrektur, mit der ich einverstanden bin, da sie anderen beim Lernen hilft. Ich habe meine Antwort abgewählt und Szatmarys als die am besten artikulierten um die Konzepte ausgewählt.
Deandob
6
@deandob: Ich habe eine Prämie für eine funktionierende Lösung für dieses Problem veröffentlicht, die Sie erfolgreich bereitgestellt haben. Die akzeptierte Antwort besagt, dass es keine funktionierende Lösung gibt und daher eindeutig ungenau ist.
Jwriteclub
2
Vielen Dank. Es scheint, dass andere meine ursprüngliche Antwort als falsch herabgestuft haben, und da ich neu bin, habe ich einfach angenommen, dass die Dinge hier so funktionieren. Ich möchte keine Aufregung verursachen, aber ich werde mich bei den Leuten über den Meta-Stack-Überlauf erkundigen. Übrigens - meine Lösung funktioniert sehr gut und sollte für andere funktionsfähig sein. Es gibt eine Variation der veröffentlichten Lösung, die die anfängliche Verzögerung verringern kann (Puffer in node.js versuchen zunächst, das Ende des Streams auf Client-Seite zu beenden). .
Deandob
4
Ich habe von einem Moderator klargestellt, dass mein ursprünglicher Ansatz, die Frage selbst zu beantworten und diese als Antwort auszuwählen, der richtige Ansatz war. Weitere Informationen (oder wenn Sie dies weiter diskutieren möchten) finden Sie im Thread auf der Metaseite. meta.stackexchange.com/questions/224068/…
Deandob
14

Schauen Sie sich das JSMPEG- Projekt an. Dort ist eine großartige Idee implementiert - MPEG im Browser mit JavaScript zu dekodieren. Bytes vom Encoder (z. B. FFMPEG) können beispielsweise mit WebSockets oder Flash an den Browser übertragen werden. Wenn die Community aufholt, wird es meiner Meinung nach die derzeit beste HTML5-Live-Video-Streaming-Lösung sein.

Michael Romanenko
quelle
10
Das ist ein MPEG-1-Videodecoder. Ich bin mir nicht sicher, ob Sie verstehen, wie alt MPEG-1 ist. Es ist älter als DVDs. Es ist etwas fortgeschrittener als eine GIF-Datei.
Camilo Martin
13

Ich habe einen HTML5-Video-Player rund um den Broadway-H264-Codec (emscripten) geschrieben, der H264-Videos in allen Browsern (Desktop, iOS, ...) live (ohne Verzögerung) wiedergeben kann.

Der Videostream wird über einen Websocket an den Client gesendet, Frame für Frame dekodiert und in einem Canva angezeigt (mit Webgl zur Beschleunigung).

Schauen Sie sich https://github.com/131/h264-live-player auf github an.

131
quelle
1
github.com/Streamedian/html5_rtsp_player Diese Jungs haben etwas Ähnliches gemacht, das RTP H264 über Websocket verwendet
Victor.dMdB
12

Eine Möglichkeit, eine RTSP-basierte Webcam live auf einen HTML5-Client zu streamen (beinhaltet eine Neucodierung, also Qualitätsverlust erwarten und etwas CPU-Leistung benötigen):

  • Richten Sie einen Icecast-Server ein (möglicherweise auf demselben Computer, auf dem sich Ihr Webserver befindet, oder auf dem Computer, der den RTSP-Stream von der Kamera empfängt).
  • Verwenden Sie auf dem Computer, der den Stream von der Kamera empfängt, nicht FFMPEG, sondern gstreamer. Es kann den RTSP-Stream empfangen und dekodieren, neu codieren und an den Icecast-Server streamen. Beispiel-Pipeline (nur Video, kein Audio):

    gst-launch-1.0 rtspsrc location=rtsp://192.168.1.234:554 user-id=admin user-pw=123456 ! rtph264depay ! avdec_h264 ! vp8enc threads=2 deadline=10000 ! webmmux streamable=true ! shout2send password=pass ip=<IP_OF_ICECAST_SERVER> port=12000 mount=cam.webm

=> Sie können dann das <video> -Tag mit der URL des icecast-Streams ( http://127.0.0.1:12000/cam.webm ) verwenden und es funktioniert in jedem Browser und Gerät, das webm unterstützt

Jannis
quelle
3

Schauen Sie sich diese Lösung an . Wie ich weiß, ermöglicht Flashphoner die Wiedergabe von Live-Audio- und Videostreams auf der reinen HTML5-Seite.

Sie verwenden MPEG1- und G.711- Codecs für die Wiedergabe. Der Hack rendert dekodiertes Video in ein HTML5-Canvas-Element und spielt dekodiertes Audio über den HTML5-Audiokontext ab.

ankitr
quelle
2

Dies ist ein sehr häufiges Missverständnis. Es gibt keine Unterstützung für Live-HTML5-Videos (außer HLS unter iOS und Mac Safari). Möglicherweise können Sie es mit einem WebM-Container "hacken", aber ich würde nicht erwarten, dass dies allgemein unterstützt wird. Was Sie suchen, ist in den Medienquellenerweiterungen enthalten, in denen Sie die Fragmente einzeln dem Browser zuführen können. Sie müssen jedoch clientseitiges Javascript schreiben.

szatmary
quelle
Es gibt solutionsaber keine supportfür Live-Streaming. Dies bezieht sich direkt auf meinen Kommentar oben. Und webm wird in den wichtigsten Browsern unterstützt, hauptsächlich in der neuesten stabilen Version.
tsturzl
1
Ich würde es wirklich vorziehen, nicht von H.264 nach webm zu transkodieren, und es sollte nicht notwendig sein. Da ich IE11 und Safari unterstützen muss, helfen MediaSource-Erweiterungen nicht weiter. Aber ich denke, wenn ich einen Dateistream auf der Serverseite simuliere (was funktioniert!), Sollte es funktionieren, aber ich muss einen Dateipuffer auf node.js simulieren.
Deandob
1
Wie andere vorgeschlagen haben, würde ich nach einer Möglichkeit suchen, WebRTC zu verwenden, das im Gegensatz zu VLC oder Flash-Plugin nativ ist. Ich weiß, dass diese Technologie immer noch schwer zu implementieren ist. Viel Glück.
1
Ich habe dies zum Laufen gebracht, indem ich auf die neueste Version von FFMPEG aktualisiert habe, da es den Anschein hat, dass die MP4-Datei beschädigt ist, wenn der fragmentierte Modus verwendet wird (erforderlich für MP4-Live-Streaming, damit der Client nicht auf die Moov-Indexdatei wartet, die im Live-Modus niemals verfügbar sein wird Streaming). Und mein node.js-Code zum Umleiten des FFMPEG-Streams direkt zum Browser funktioniert jetzt.
Deandob
1
Ja, funktioniert gut mit IE11 (meinem bevorzugten Browser). Ich bekomme eine nervöse Antwort in Chrome.
Deandob
2

Versuchen Sie binaryjs. Es ist genau wie socket.io, aber das einzige, was es gut macht, ist, dass es Audio-Video streamen kann. Binaryjs googeln es

Siddharth
quelle
1
Binary.JS ist nichts anderes als Socket.IO. Und es ist nicht spezifisch für Medien-Streaming.
Brad