2012-10-22 39 views
33

Pracuję nad usługą telewizji internetowej. Jednym z celów jest to, aby wideo było odtwarzane bez dodatkowych wtyczek do przeglądarek (z wyjątkiem Flasha).Transmisja na żywo za pośrednictwem MP4

Postanowiłem użyć MP4, ponieważ jest obsługiwany przez większość przeglądarek HTML5 i Flash (w zastępstwie). Filmy są transkodowane z ASF na serwerze przez FFMpeg.

Jednak znalazłem, że MP4 nie może być transmitowany na żywo, ponieważ ma atom moov dla metadanych, które muszą określać długość. FFMpeg nie może bezpośrednio przesyłać strumienia mp4 na standardowe wyjście, ponieważ umieszcza moov na końcu pliku. (Live transcoding and streaming of MP4 works in Android but fails in Flash player with NetStream.Play.FileStructureInvalid error)

Oczywiście istnieje MPEG-TS, ale nie jest obsługiwany przez HTML5 <video>.

To, o czym pomyślałem, to metoda transkodowania strumienia w czasie rzeczywistym na MP4 i na każde nowe żądanie HTTP dla niego, najpierw wyślij moov, który określa bardzo długi numer dla długości filmu, a następnie zacznij wysyłać reszta pliku MP4.

Czy można używać MP4 do przesyłania strumieniowego w ten sposób?

Po kilku badaniach i odpowiedzi av501, rozumiem, że rozmiary ramek muszą być znane, aby mogły działać.

Czy plik MP4 można podzielić na mniejsze części, aby można było przesyłać strumieniowo?

Oczywiście przełączenie na inny kontener/format jest opcją, ale jedynym formatem zgodnym zarówno z Flash, jak i HTML5 jest mp4/h264, więc jeśli będę musiał obsługiwać oba, będę musiał dwukrotnie transkodować.

Odpowiedz

5

Oto moje przemyślenia faceci, niektóre z nich mogą być tuż na innych sposób daleko. Błagam o ignorancję, ponieważ nikt tak naprawdę nie udokumentował tego procesu, a wszystko to w zgadywanych domysłach.

AvAssetWriter koduje tylko plik, wydaje się, że nie ma sposobu, aby uzyskać zakodowane wideo do pamięci. Odczytanie pliku podczas zapisywania go z wątku tła, aby powiedzieć, że gniazdo powoduje strumień elementarny, jest to w zasadzie m4v, który jest jego kontenerem z h264/acc mdata, ale bez atomów moov. (innymi słowy: bez nagłówka) Żaden gracz dostarczony przez Apple nie może odtwarzać tego strumienia, ale zmodyfikowany odtwarzacz oparty na ffplay powinien móc dekodować i odtwarzać strumień. To powinno działać, ponieważ ffplay używa libavformat, który może dekodować podstawowe strumienie, jedno zastrzeżenie, ponieważ nie ma informacji o długości pliku, niektóre rzeczy muszą być określone przez grę, DTS i PTS, a także odtwarzacz nie może szukać w pliku.

Alternatywnie można użyć surowych naul ze strumienia m4v do skonstruowania strumienia rtmp.

Jeśli chcesz porozmawiać dalej, możesz skontaktować się ze mną bezpośrednio.

Sposób uzyskania danych.

Tak czy inaczej, w każdym razie, musicie przebudować plik po stronie odbiorcy, ale sądzę, że można go po prostu podzielić na segmenty, Steve Mcfarin napisał trochę appleSegmentedEcorder, który można znaleźć na jego stronie github, rozwiązuje to niektóre problemy moov atomy, ponieważ masz wszystkie informacje o pliku.

+1

Oto dobre wytłumaczenie, zaczynające brzmieć jak rtmp lub jakiś niestandardowy protokół jest drogą do przejścia http://fabiensanglard.net/mobile_progressive_playback/index.php –

+0

Twoja odpowiedź jest zastrzeżona, została napisana powyżej. Czas jest kwestią strumieniowego przesyłania i odtwarzania. więc -1 – agfe2

2

Nie, to nie jest tylko bardzo długa .. trzeba znać dokładny rozmiar każdej klatki, aby utworzyć nagłówek w mp4. [dlatego jest tworzony na końcu przez różne kodery].

+0

Czy ta informacja nie może być pusta? Po kilku poprawkach udało mi się stworzyć plik m4v (w zasadzie MP4) bez atomu moov, który grał w Totem, bez pokazywania żadnych informacji o długości filmu. – Ivo

+0

Czy Twój m4v to mp4 (kontener) zawierający elementarny plik lub tylko elementarny plik? Bez nagłówka nie jest już zgodny. To, czy gra, zależy od tego, jak inteligentny jest gracz. Niektórzy gracze mogą ciężko pracować i próbować naprawić plik. Ale większość nie będzie grać. – av501

+0

Tak, wygląda na to, że m4v może być tylko plikiem mp4 lub surowym strumieniem h264. Te, które działały w przeglądarce to mp4, a ten generowany przez ffmpeg był nieprzetworzonym strumieniem. Wygląda więc na to, że nie da się tego zrobić. – Ivo

0

Wystarczy spojrzeć na drugą parę pytania ("Filmy są transkodowane z ASF na serwerze przez ffmpeg."), Wspomniałeś, że używasz ffmpeg do transkodowania filmów na serwer.

Użyj qt-faststart lub MP4Box, aby umieścić atom MOOV na początku pliku. (także upewnij się, że używasz kodeku AAC Audio H264 do uniwersalnego wsparcia)

Mam nadzieję, że to pomogło.

+2

Nie ma. Po wielu wyszukiwaniach w Google okazało się, że qt-faststart było często wspominane - ale nie będzie działało na transmisję na żywo, ponieważ strumień jest ciągły - ramki/długość nie mogą być znane od samego początku, dlatego nie można utworzyć atomu MOOV. qt-faststart pomoże, jeśli potrzebuję pseudostreamingu (ciągłe pobieranie). – Ivo

17

Możesz użyć podzielonego MP4. Rozproszony plik MP4 jest zbudowany następująco:

moov [moof mdat]+ 

Pole moov następnie zawiera tylko podstawowe informacje o torach (ile, ich rodzaj, inicjalizacji kodeka i tak dalej), ale nie ma informacji o próbkach w torze. Informacje na temat lokalizacji próbek i rozmiarów próbek znajdują się w polu wyboru, każde pole z moofiem zawiera mdat, który zawiera próbki opisane w poprzednim polu. Zazwyczaj można wybrać długość pary (moof, mdat) na około 2,4 lub 8 sekund (nie ma na to żadnej specyfikacji, ale wartości te wydają się być rozsądne dla większości przypadków użycia).

To jest sposób na zbudowanie niekończącego się strumienia MP4.

+0

zajrzyj tutaj: https://groups.google.com/forum/?fromgroups=#!topic/mp4parser-discussion/e7yg6clATHc ten facet ma bardzo podobne problemy. –

+3

Ostatecznie fragmentaryczny MP4 jest jak streaming HTTP na żywo HTTP i robi dobrą robotę. Zignorowałem to na początku, ponieważ uważałem, że fragmentacja wydaje się niepotrzebną komplikacją, ale teraz widzę, że to jedyna opcja. – Ivo

+0

@SebastianAnnies Wydaje się, że to działa (przynajmniej) Safari wydaje się żądać każdego fragmentu z osobnym żądaniem GET GET (od początku fragmentu do EOF, ale kończy się przedwcześnie), przez co cała obsługa strumienia jest bardziej uciążliwa. Czy masz takie samo doświadczenie? –