Najlepsze podejście do przesyłania strumieniowego HTTP w czasie rzeczywistym do klienta wideo HTML5

213

Naprawdę utknąłem, próbując zrozumieć najlepszy sposób przesyłania strumieniowego wyniku ffmpeg w czasie rzeczywistym do klienta HTML5 za pomocą node.js, ponieważ istnieje wiele zmiennych i nie mam dużego doświadczenia w tym obszarze, spędziłem wiele godzin próbując różnych kombinacji.

Mój przypadek użycia to:

1) Strumień wideo kamery RTSP H.264 IP jest pobierany przez FFMPEG i ponownie umieszczany w kontenerze mp4 przy użyciu następujących ustawień FFMPEG w węźle, wysyłany do STDOUT. Jest to uruchamiane tylko przy początkowym połączeniu klienta, aby częściowe żądania treści nie próbowały ponownie odrodzić FFMPEG.

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) Używam węzłowego serwera HTTP do przechwytywania STDOUT i przesyłania strumieniowego z powrotem do klienta na żądanie klienta. Kiedy klient po raz pierwszy się łączy, spawnuję powyższy wiersz poleceń FFMPEG, a następnie przesyłam potokiem strumień STDOUT do odpowiedzi HTTP.

liveFFMPEG.stdout.pipe(resp);

Użyłem również zdarzenia stream do zapisania danych FFMPEG do odpowiedzi HTTP, ale nie robi to różnicy

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

Używam następującego nagłówka HTTP (który jest również używany i działa podczas przesyłania strumieniowego wcześniej nagranych plików)

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) Klient musi używać tagów wideo HTML5.

Nie mam problemów z odtwarzaniem strumieniowym (przy użyciu fs.createReadStream z 206 częściową zawartością HTTP) do klienta HTML5 plik wideo wcześniej nagrany przy użyciu powyższego wiersza polecenia FFMPEG (ale zapisany w pliku zamiast STDOUT), więc znam strumień FFMPEG jest poprawny i nawet poprawnie widzę transmisję wideo na żywo w VLC podczas łączenia się z serwerem węzła HTTP.

Jednak próba przesyłania strumieniowego na żywo z FFMPEG przez węzeł HTTP wydaje się dużo trudniejsza, ponieważ klient wyświetli jedną ramkę, a następnie zatrzyma się. Podejrzewam, że problem polega na tym, że nie konfiguruję połączenia HTTP, aby było zgodne z klientem wideo HTML5. Próbowałem różnych rzeczy, takich jak użycie HTTP 206 (częściowa treść) i 200 odpowiedzi, umieszczanie danych w buforze, a następnie przesyłanie strumieniowe bez powodzenia, więc muszę wrócić do pierwszych zasad, aby upewnić się, że skonfigurowałem to poprawnie sposób.

Oto moje rozumienie tego, jak to powinno działać, proszę mnie poprawić, jeśli się mylę:

1) FFMPEG powinien zostać skonfigurowany w celu fragmentacji danych wyjściowych i użycia pustego moov (flagi FFMPEG frag_keyframe i empty_moov mov flagi). Oznacza to, że klient nie używa atomu moov, który zwykle znajduje się na końcu pliku, co nie jest istotne podczas przesyłania strumieniowego (bez końca pliku), ale oznacza, że ​​nie można szukać, co jest dobre w moim przypadku użycia.

2) Mimo że używam fragmentów MP4 i pustego MOOV, nadal muszę korzystać z częściowej zawartości HTTP, ponieważ odtwarzacz HTML5 będzie czekał na pobranie całego strumienia przed rozpoczęciem odtwarzania, co w przypadku transmisji na żywo nigdy się nie kończy, więc jest to niemożliwe.

3) Nie rozumiem, dlaczego przesyłanie strumieniowe strumienia STDOUT do odpowiedzi HTTP nie działa jeszcze podczas przesyłania strumieniowego na żywo, jeśli zapiszę do pliku, mogę łatwo przesyłać strumieniowo ten plik do klientów HTML5 przy użyciu podobnego kodu. Być może jest to kwestia synchronizacji, ponieważ uruchomienie FFMPEG zajmuje sekundę, połączenie z kamerą IP i wysyłanie fragmentów do węzła, a zdarzenia danych węzła również są nieregularne. Jednak bajtowanie powinno być dokładnie takie samo jak zapisywanie w pliku, a HTTP powinien być w stanie zaspokoić opóźnienia.

4) Podczas sprawdzania dziennika sieciowego z klienta HTTP podczas przesyłania strumieniowego pliku MP4 utworzonego przez FFMPEG z kamery widzę, że istnieją 3 żądania klienta: Ogólne żądanie GET dla wideo, które serwer HTTP zwraca około 40 KB, a następnie częściowe żądanie zawartości z zakresem bajtów dla ostatnich 10 KB pliku, a następnie końcowe żądanie dla bitów w środku nie załadowane. Może klient HTML5 po otrzymaniu pierwszej odpowiedzi prosi o załadowanie atomu MP4 MOOV ostatniej części pliku? W takim przypadku nie będzie działać w przypadku przesyłania strumieniowego, ponieważ nie ma pliku MOOV i nie ma końca pliku.

5) Podczas sprawdzania dziennika sieciowego podczas próby przesyłania strumieniowego na żywo otrzymuję przerwane początkowe żądanie z odebranymi około 200 bajtami, a następnie ponowne żądanie ponownie przerwane z 200 bajtami i trzecim żądaniem, które ma tylko 2 KB długości. Nie rozumiem, dlaczego klient HTML5 przerwałby żądanie, ponieważ strumień bajtów jest dokładnie taki sam, jak mogę z powodzeniem używać podczas przesyłania strumieniowego z nagranego pliku. Wygląda również na to, że węzeł nie wysyła pozostałej części strumienia FFMPEG do klienta, ale widzę dane FFMPEG w procedurze zdarzeń .on, więc dociera ono do serwera HTTP węzła FFMPEG.

6) Chociaż myślę, że potokowanie strumienia STDOUT do bufora odpowiedzi HTTP powinno działać, czy muszę zbudować bufor pośredni i strumień, który pozwoli, aby żądania klienta częściowej treści HTTP działały poprawnie tak jak wtedy, gdy (z powodzeniem) odczyta plik ? Myślę, że to jest główny powód moich problemów, ale nie jestem do końca pewien w Node, jak najlepiej to skonfigurować. I nie wiem, jak obsłużyć żądanie klienta dotyczące danych na końcu pliku, ponieważ nie ma końca pliku.

7) Czy jestem na niewłaściwej ścieżce, próbując obsłużyć 206 częściowych żądań treści i czy powinno to działać z normalnymi 200 odpowiedziami HTTP? Odpowiedzi HTTP 200 działają dobrze dla VLC, więc podejrzewam, że klient wideo HTML5 będzie działał tylko z częściowymi żądaniami treści?

Ponieważ wciąż uczę się tego, trudno jest przejść przez różne warstwy tego problemu (FFMPEG, węzeł, streaming, HTTP, HTML5 wideo), więc wszelkie wskazówki będą mile widziane. Spędziłem godziny badając tę ​​stronę i sieć, i nie spotkałem nikogo, kto byłby w stanie transmitować w czasie rzeczywistym w węźle, ale nie mogę być pierwszy i myślę, że to powinno zadziałać (jakoś !).

deandob
źródło
4
To trudny temat. Pierwsze jest pierwsze. Czy postawiłeś Content-Typesobie głowę? Czy używasz kodowania fragmentów? Od tego bym zaczął. Ponadto HTML5 nie musi zapewniać funkcji przesyłania strumieniowego, więcej informacji na ten temat można znaleźć tutaj . Najprawdopodobniej będziesz musiał zaimplementować sposób buforowania i odtwarzania strumienia wideo przy użyciu własnych środków ( patrz tutaj ), ponieważ prawdopodobnie nie jest to dobrze obsługiwane. Również Google w API MediaSource.
tsturzl
Dziękuję za odpowiedź. Tak, typem zawartości jest „wideo / mp4” i ten kod działa w przypadku przesyłania strumieniowego plików wideo. Niestety MediaSource jest tylko Chrome, muszę obsługiwać inne przeglądarki. Czy istnieje specyfika interakcji klienta wideo HTML5 z serwerem przesyłania strumieniowego HTTP? Jestem pewien, że chcę to zrobić, ale nie jestem pewien, jak dokładnie (z node.js, ale mógłbym użyć C # lub C ++, jeśli jest to łatwiejsze)
deandob
2
Problem nie występuje na twoim backendie. Dobra transmisja strumieniowa wideo. Problem tkwi w twoim interfejsie / kliencie, musisz sam zaimplementować streaming. HTML5 po prostu nie obsługuje strumieni. Najprawdopodobniej musisz zbadać opcje dla każdej przeglądarki. Dobrym początkiem byłoby zapoznanie się ze standardami w3 dla tagów wideo i interfejsów API mediów.
tsturzl
Wydaje się, że ta praca powinna być możliwa. Nie oferuję ostatecznej odpowiedzi, ale podejrzewam, że ten problem dotyczy faktu, że przeglądarka oczekuje na początku nagłówka / atomów kontenera mp4 na początku, a nie następnej klatki w strumieniu wideo. Jeśli wyślesz atom MOOV dla bardzo długiego filmu (tak, aby odtwarzacz ciągle prosił), a także inne oczekiwane nagłówki, a następnie zaczniesz kopiowanie z ffmpeg, może to działać. Trzeba też ukryć pasek przewijania za pomocą js w przeglądarce, aby nie mogli skanować do przodu.
jwriteclub
Proponuję rozważyć WebRTC, który z dnia na dzień zyskuje lepszą obsługę różnych przeglądarek.
Alex Cohn

Odpowiedzi:

209

EDYCJA 3: Począwszy od IOS 10, HLS będzie obsługiwał pofragmentowane pliki MP4. Odpowiedzią jest teraz utworzenie fragmentowanych zasobów mp4 z manifestem DASH i HLS. > Udawaj, że Flash, iOS9 i nowsze wersje oraz IE 10 i nowsze wersje nie istnieją.

Wszystko poniżej tego wiersza jest nieaktualne. Trzymam go tutaj dla potomności.


EDYCJA 2: Jak wskazują ludzie w komentarzach, rzeczy się zmieniają. Prawie wszystkie przeglądarki obsługują kodeki AVC / AAC. iOS nadal wymaga HLS. Ale za pomocą adapterów takich jak hls.js możesz grać w HLS w MSE. Nowa odpowiedź to HLS + hls.js, jeśli potrzebujesz iOS. lub po prostu Fragmented MP4 (tj. DASH), jeśli nie

Istnieje wiele powodów, dla których wideo, a szczególnie wideo na żywo, jest bardzo trudne. (Należy pamiętać, że pierwotne pytanie określało, że wideo HTML5 jest wymagane, ale pytający stwierdził, że Flash jest możliwy w komentarzach. Więc natychmiast to pytanie wprowadza w błąd)

Najpierw powtórzę: NIE MA OFICJALNEGO WSPARCIA DLA TRANSMISJI NA ŻYWO NA HTML5 . Są hacki, ale przebieg może się różnić.

EDYCJA: odkąd napisałem tę odpowiedź Media Source Extensions dojrzał i są bardzo blisko, aby stać się realną opcją. Są obsługiwane w większości głównych przeglądarek. IOS nadal trzyma się z daleka.

Następnie musisz zrozumieć, że Wideo na żądanie (VOD) i wideo na żywo są bardzo różne. Tak, oba są filmami, ale problemy są różne, stąd formaty są różne. Na przykład, jeśli zegar w twoim komputerze działa o 1% szybciej niż powinien, nie zauważysz na VOD. W przypadku wideo na żywo będziesz próbował odtworzyć wideo, zanim to nastąpi. Jeśli chcesz dołączyć do trwającego strumienia wideo na żywo, potrzebujesz danych niezbędnych do zainicjowania dekodera, więc musisz je powtórzyć w strumieniu lub wysłać poza pasmem. Dzięki VOD możesz odczytać początek pliku, którego szukają, w dowolnym momencie.

Teraz zagłębmy się trochę.

Platformy:

  • iOS
  • PC
  • Prochowiec
  • Android

Kodeki:

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

Typowe metody dostarczania wideo na żywo w przeglądarkach:

  • DASH (HTTP)
  • HLS (HTTP)
  • flash (RTMP)
  • flash (HDS)

Typowe metody dostarczania VOD w przeglądarkach:

  • DASH (Streaming HTTP)
  • HLS (Streaming HTTP)
  • flash (RTMP)
  • flash (Streaming HTTP)
  • MP4 (pseudo streaming HTTP)
  • Nie zamierzam mówić o MKV i OOG, ponieważ nie znam ich zbyt dobrze.

Tag wideo HTML5:

  • MP4
  • webm
  • ogg

Przyjrzyjmy się, które przeglądarki obsługują formaty

Safari:

  • HLS (tylko iOS i Mac)
  • h.264
  • MP4

Firefox

  • DASH (przez MSE, ale bez h.264)
  • h.264 tylko przez Flash!
  • VP9
  • MP4
  • OGG
  • Webm

TO ZNACZY

  • Lampa błyskowa
  • DASH (tylko przez MSE IE 11+)
  • h.264
  • MP4

Chrom

  • Lampa błyskowa
  • DASH (przez MSE)
  • h.264
  • VP9
  • MP4
  • webm
  • ogg

MP4 nie może być używany do wideo na żywo (UWAGA: DASH jest nadzbiorem MP4, więc nie myl się z tym). MP4 jest podzielony na dwie części: moov i mdat. mdat zawiera surowe dane audio wideo. Ale nie jest indeksowany, więc bez moov jest bezużyteczny. Moov zawiera indeks wszystkich danych w mdat. Jednak ze względu na swój format nie można go „spłaszczyć”, dopóki nie zostaną znane znaczniki czasu i rozmiar KAŻDEJ ramki. Może być możliwe skonstruowanie moov, który „zgina” rozmiary ramek, ale jest bardzo marnotrawny pod względem przepustowości.

Więc jeśli chcesz dostarczać wszędzie, musimy znaleźć najmniejszy wspólny mianownik. Zobaczysz, że nie ma tutaj LCD bez uciekania się do przykładu flasha:

  • iOS obsługuje tylko wideo h.264. i obsługuje tylko HLS na żywo.
  • Firefox w ogóle nie obsługuje h.264, chyba że używasz Flasha
  • Flash nie działa w systemie iOS

Najbliżej wyświetlacza LCD jest użycie HLS, aby zdobyć użytkowników iOS i flashować dla wszystkich innych. Moim osobistym ulubionym jest kodowanie HLS, a następnie użycie Flasha, aby grać w HLS dla wszystkich innych. Możesz grać w HLS we flashu za pomocą JW player 6 (lub napisać własny HLS do FLV w AS3, tak jak ja to zrobiłem)

Wkrótce najpopularniejszym sposobem na to będzie HLS na iOS / Mac i DASH przez MSE wszędzie indziej (właśnie to Netflix zrobi wkrótce). Nadal jednak czekamy, aż wszyscy zaktualizują swoje przeglądarki. Prawdopodobnie będziesz potrzebować osobnego DASH / VP9 dla Firefoksa (wiem o open264; jest do bani. Nie może robić wideo w profilu głównym lub wysokim. Więc jest obecnie bezużyteczny).

szatmary
źródło
Dzięki szatmary za szczegółowe tło i zalety / wady na temat różnych opcji. Wybrałem tę odpowiedź jako zaakceptowaną, ponieważ zarys pojęć jest ważniejszy niż konkretna poprawka, którą znalazłem, aby odpowiedzieć na pierwotne pytanie. Powodzenia z nagrodą!
deandob
9
To nie jest skuteczne rozwiązanie tego pytania. Poniżej znajduje się działające rozwiązanie tego problemu.
jwriteclub
2
Firefox obsługuje teraz natywnie MSE i h.264. Przejdź do www.youtube.com/html5 z najnowszą przeglądarką FF, aby potwierdzić. Testowałem z FF 37. Safari 8+ na Macu obsługuje teraz MSE.
BigTundra
@BigTundra tak, safari obsługuje MSE od czasu uruchomienia Yosemite na Macu. Ale nie iOS. Nie jestem pewien co do systemu Windows. (Czy safari na Windowsie nadal jest czymś?) Firefox 37.0.2 na (moim) komputerze Mac nie wydaje się w ogóle obsługiwać MSE zgodnie z tym linkiem. Ale obsługuje H.264. Firefox w przeszłości dodawał i usuwał i ponownie dodawał obsługę H.264.
szatmary
Aktualna przeglądarka obsługuje format wideo MPEG-4 / H.264: caniuse.com/#feat=mpeg4
Maxence
75

Dziękuję wszystkim, zwłaszcza szatmary, ponieważ jest to złożone pytanie i ma wiele warstw, wszystkie muszą działać, zanim będzie można przesyłać strumieniowo wideo na żywo. Aby wyjaśnić moje oryginalne pytanie i użycie wideo HTML5 w porównaniu do flasha - mój przypadek użycia ma silną preferencję dla HTML5, ponieważ jest ogólny, łatwy do wdrożenia na kliencie i przyszłości. Flash jest drugim co do wielkości drugim, więc trzymajmy się HTML5 w przypadku tego pytania.

Wiele się nauczyłem dzięki temu ćwiczeniu i zgadzam się, że transmisja na żywo jest znacznie trudniejsza niż VOD (który działa dobrze z wideo HTML5). Ale sprawiłem, że działało to zadowalająco w moim przypadku użycia, a rozwiązanie okazało się bardzo proste, po ściganiu bardziej złożonych opcji, takich jak MSE, flash, skomplikowane schematy buforowania w węźle. Problem polegał na tym, że FFMPEG uszkadzał pofragmentowane MP4 i musiałem dostroić parametry FFMPEG, a wystarczyło standardowe przekierowanie potoku strumienia węzłów przez http, którego użyłem pierwotnie.

W MP4 dostępna jest opcja „fragmentacji”, która dzieli MP4 na znacznie mniejsze fragmenty, które mają swój własny indeks i sprawia, że ​​opcja MP4 na żywo jest wykonalna. Ale nie można szukać z powrotem w strumieniu (OK w moim przypadku użycia), a nowsze wersje FFMPEG obsługują fragmentację.

Czas może być problemem, a moje rozwiązanie ma opóźnienie od 2 do 6 sekund spowodowane kombinacją remuxingu (w rzeczywistości FFMPEG musi odbierać strumień na żywo, remux, a następnie wysłać go do węzła w celu obsługi przez HTTP) . Niewiele można na to poradzić, jednak w Chrome wideo stara się nadrobić tyle, ile może, co sprawia, że ​​film jest nieco nerwowy, ale bardziej aktualny niż IE11 (mój preferowany klient).

Zamiast wyjaśniać, jak działa kod w tym poście, sprawdź GIST z komentarzami (kod klienta nie jest uwzględniony, jest to standardowy tag wideo HTML5 z adresem serwera węzła http). GIST jest tutaj: https://gist.github.com/deandob/9240090

Nie udało mi się znaleźć podobnych przykładów tego przypadku użycia, więc mam nadzieję, że powyższe wyjaśnienie i kod pomogą innym, zwłaszcza że nauczyłem się wiele z tej strony i nadal uważam się za początkującego!

Chociaż jest to odpowiedź na moje konkretne pytanie, wybrałem odpowiedź szatmary jako zaakceptowaną, ponieważ jest najbardziej wyczerpująca.

deandob
źródło
33
Przepraszam, ale znalazłem to sam, zapis mojej odpowiedzi wyjaśnia to całkiem jasno. Wcześniejsze odpowiedzi były pomocne i doceniane, ale nie przyczyniły się znacząco, a nawet przesłałem działający kod do GIST i nikt inny tego nie zrobił. Nie jestem zainteresowany „reputacją”, chcę się dowiedzieć, czy moje podejście i kod można ulepszyć. Odpowiedź, którą zaznaczyłem, rozwiązała mój problem, więc nie jestem pewien, o co chodzi. Jestem dość nowy w SO, więc cieszę się, że mogę mówić o interakcji w inny sposób, uważam tę stronę za przydatną, a moja odpowiedź powinna pomóc innym.
deandob
2
Wydaje się, że w tej społeczności nie jest właściwe wybieranie odpowiedzi jako zaakceptowanej, jeśli zadałeś pytanie, nawet jeśli naprawi to pierwotny problem. Chociaż wydaje się to sprzeczne z intuicją, dokumentacja pojęć jest ważniejsza niż faktyczna poprawka, z którą jestem w porządku, ponieważ pomaga innym się uczyć. Wyłączyłem odpowiedź i wybrałem szatmary jako najbardziej artykułowane wokół pojęć.
deandob
6
@deandob: Wysłałem nagrodę za sprawne rozwiązanie tego problemu, który udało się podarować . Przyjęta odpowiedź potwierdza, że ​​nie ma działającego rozwiązania, a zatem jest wyraźnie niedokładna.
jwriteclub
2
Dzięki. Wydaje się, że inni zlekceważyli moją pierwotną odpowiedź jako błędną, a ponieważ jestem nowy, po prostu założyłem, że tak właśnie tutaj się wszystko dzieje. Nie chcę sprawiać kłopotów, ale sprawdzę z ludźmi z przepełnieniem stosu meta. BTW - moje rozwiązanie działa bardzo dobrze i powinno być wykonalne dla innych, i istnieje pewna odmiana opublikowanego rozwiązania, która może zmniejszyć początkowe opóźnienie (bufor w node.js początkowo następnie dąży do końca strumienia po stronie klienta) .
deandob
4
Mam wyjaśnienie od moderatora, że ​​moje oryginalne podejście do odpowiedzi na pytanie i wybrania go jako odpowiedzi było poprawne. Aby uzyskać więcej informacji (lub jeśli chcesz omówić to dalej), zobacz wątek na stronie meta. meta.stackexchange.com/questions/224068/…
deandob
14

Spójrz na JSMPEG projektu. Zaimplementowano tam świetny pomysł - dekodowanie MPEG w przeglądarce za pomocą JavaScript. Bajty z kodera (na przykład FFMPEG) mogą być przesyłane do przeglądarki za pomocą na przykład WebSockets lub Flash. Jeśli społeczność nadrobi zaległości, myślę, że na razie będzie to najlepsze rozwiązanie do przesyłania strumieniowego wideo HTML5.

Michael Romanenko
źródło
10
To dekoder wideo MPEG-1. Nie jestem pewien, czy rozumiesz, jak starożytny jest MPEG-1; jest starszy niż DVD. Jest nieco bardziej zaawansowany niż plik GIF.
Camilo Martin
13

Napisałem odtwarzacz wideo HTML5 wokół kodeka broadway h264 (emscripten), który może odtwarzać na żywo (bez opóźnień) wideo h264 we wszystkich przeglądarkach (komputer, iOS, ...).

Strumień wideo jest wysyłany przez websocket do klienta, dekodowany klatka na klatkę i wyświetlany w kanwie (używając webgl do przyspieszenia)

Sprawdź https://github.com/131/h264-live-player na github.

131
źródło
1
github.com/Streamedian/html5_rtsp_player Ci faceci zrobili coś podobnego, używając rtp h264 przez websocket
Victor.dMdB
12

Jednym ze sposobów przesyłania strumieniowego na żywo kamery internetowej opartej na RTSP do klienta HTML5 (wymaga ponownego kodowania, więc spodziewaj się utraty jakości i potrzebuje trochę mocy procesora):

  • Skonfiguruj serwer Icecast (może znajdować się na tym samym komputerze, na którym znajduje się serwer WWW lub na komputerze, który odbiera strumień RTSP z kamery)
  • Na komputerze odbierającym strumień z kamery nie używaj FFMPEG, ale gstreamer. Jest w stanie odbierać i dekodować strumień RTSP, ponownie go kodować i przesyłać strumieniowo na serwer Icecast. Przykładowy potok (tylko wideo, bez dźwięku):

    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

=> Następnie możesz użyć znacznika <video> z adresem URL strumienia icecast-stream ( http://127.0.0.1:12000/cam.webm ) i będzie on działał w każdej przeglądarce i urządzeniu obsługującym webm

Jannis
źródło
3

Spójrz na to rozwiązanie . Jak wiem, Flashphoner pozwala odtwarzać strumień audio + wideo na żywo na czystej stronie HTML5.

Do odtwarzania używają kodeków MPEG1 i G.711 . Włamanie polega na renderowaniu dekodowanego wideo do elementu płótna HTML5 i odtwarzaniu dekodowanego dźwięku w kontekście audio HTML5.

ankitr
źródło
2

To bardzo powszechne nieporozumienie. Nie ma obsługi wideo na żywo HTML5 (z wyjątkiem HLS na iOS i Mac Safari). Być może będziesz w stanie „zhakować” go za pomocą kontenera webm, ale nie spodziewałbym się, że będzie on powszechnie obsługiwany. To, czego szukasz, znajduje się w rozszerzeniach Media Source, w których możesz podawać fragmenty do przeglądarki pojedynczo. ale będziesz musiał napisać javascript po stronie klienta.

szatmary
źródło
Są, solutionsale nie ma supporttransmisji na żywo. Odnosi się to bezpośrednio do mojego komentarza przedstawionego powyżej. Webm jest obsługiwany w głównych przeglądarkach, głównie w najnowszej stabilnej wersji.
tsturzl
1
Naprawdę wolałbym nie transkodować z H.264 na webm i nie powinno to być konieczne. Ponieważ muszę obsługiwać IE11 i Safari, rozszerzenia MediaSource nie pomogą. Ale myślę, że jeśli symuluję strumień plików po stronie serwera (co działa!), Powinien on działać, ale będę musiał zasymulować bufor plików w node.js.
deandob
1
Zgodnie z innymi sugestiami szukałbym możliwości użycia WebRTC, który jest natywny w przeciwieństwie do VLC lub wtyczki flash. Wiem, że ta technologia jest nadal trudna do wdrożenia. Powodzenia.
1
Dostałem to do pracy, aktualizując do najnowszej wersji FFMPEG, ponieważ wygląda na to, że w mp4 wystąpiło uszkodzenie w trybie fragmentacji (konieczne do strumieniowania na żywo MP4, aby klient nie czekał na plik indeksu moov, który nigdy nie pojawi się podczas transmisji na żywo streaming). I mój kod node.js do przekierowania strumienia FFMPEG bezpośrednio do przeglądarki teraz działa.
deandob
1
Tak, działa dobrze na IE11 (moja preferowana przeglądarka). Otrzymuję szybką odpowiedź w Chrome.
deandob
2

Wypróbuj binaryjs. To jest tak jak socket.io, ale jedyne, co robi dobrze, to strumieniowe przesyłanie audio wideo. Binaryjs google go

Siddharth
źródło
1
Binary.JS nie przypomina Socket.IO. I nie jest to specyficzne dla strumieniowego przesyłania multimediów.
Brad