ffmpeg'in gerçek zamanlı çıktısını node.js kullanarak bir HTML5 istemcisine aktarmanın en iyi yolunu anlamaya çalışırken gerçekten takıldım, çünkü oyunda çok sayıda değişken var ve bu alanda çok fazla deneyimim yok, farklı kombinasyonları denemek için saatler harcadım. Benim kullanım durumum:
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);
FFMPEG verilerini HTTP yanıtına yazmak için stream olayını da kullandım ancak bir fark yaratmadı
xliveFFMPEG.stdout.on("data",function(data) {
resp.write(data);
}
Aşağıdaki HTTP başlığını kullanıyorum (önceden kaydedilmiş dosyaları yayınlarken de kullanılır ve çalışır)
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
});
- DÜZENLE: IOS 10'dan itibaren HLS, parçalanmış mp4 dosyalarını destekleyecektir. Cevap şimdi, bir DASH ve HLS bildirimi ile parçalanmış mp4 varlıkları oluşturmaktır. flash, iOS9 ve altı ve IE 10 ve altı yokmuş gibi davranın.
DÜZENLEME 2: Yorumlardaki insanların da belirttiği gibi, işler değişiyor. Neredeyse tüm tarayıcılar AVC/AAC codec bileşenlerini destekleyecektir. iOS hala HLS gerektiriyor. Ancak hls.js gibi adaptörler aracılığıyla MSE'de HLS. iOS'a ihtiyacınız varsa yeni cevap HLS+hls.js'dir. veya sadece Parçalanmış MP4 (yani DASH) eğer yapmazsanız't
Videonun ve özellikle de canlı videonun çok zor olmasının birçok nedeni var. (Orijinal soruda HTML5 videonun bir gereklilik olduğunun belirtildiğini, ancak soruyu soranın yorumlarda Flash'ın mümkün olduğunu belirttiğini lütfen unutmayın. Dolayısıyla, bu soru hemen yanıltıcıdır)
Önce tekrar ifade edeyim: HTML5 ÜZERINDEN CANLI YAYIN IÇIN RESMI BIR DESTEK YOKTUR. Hack'ler var, ancak kilometreniz değişebilir.
DÜZENLEME: Bu yanıtı yazdığımdan beri Medya Kaynağı Uzantıları olgunlaştı, ve artık uygulanabilir bir seçenek olmaya çok yakınlar. Destekleniyorlar çoğu büyük tarayıcıda. IOS bir engel olmaya devam ediyor.
Ardından, Talep Üzerine Video (VOD) ve canlı videonun çok farklı olduğunu anlamanız gerekir. Evet, her ikisi de videodur, ancak sorunlar farklıdır, dolayısıyla formatlar da farklıdır. Örneğin, bilgisayarınızdaki saat olması gerekenden %1 daha hızlı çalışıyorsa, VOD'da bunu fark etmezsiniz. Canlı videoda, videoyu gerçekleşmeden önce oynatmaya çalışacaksınız. Devam eden bir canlı video akışına katılmak istiyorsanız, kod çözücüyü başlatmak için gerekli verilere ihtiyacınız vardır, bu nedenle akış içinde tekrarlanmalı veya bant dışına gönderilmelidir. VOD ile, dosyanın başlangıcını okuyabilir ve istediğiniz noktaya kadar arayabilirsiniz.
Şimdi biraz daha derine inelim.
Platformlar:
Codec'ler:
Tarayıcılarda canlı video için yaygın Teslim yöntemleri:
Tarayıcılarda VOD için yaygın Teslimat yöntemleri:
html5 video etiketi:
Hangi tarayıcıların hangi formatları desteklediğine bakalım
Safari:
Firefox
IE
Krom
MP4 canlı video için kullanılamaz (NOT: DASH, MP4'ün bir üst kümesidir, bu yüzden bununla karıştırmayın). MP4 iki parçaya ayrılır: moov ve mdat. mdat ham ses video verilerini içerir. Ancak indekslenmez, bu nedenle moov olmadan işe yaramaz. Moov, mdat'taki tüm verilerin bir dizinini içerir. Ancak formatı nedeniyle, HER karenin zaman damgaları ve boyutu bilinene kadar 'düzleştirilemez'. Çerçeve boyutlarını 'fibs' eden bir moov oluşturmak mümkün olabilir, ancak bant genişliği açısından çok savurgandır.
Dolayısıyla, her yere teslimat yapmak istiyorsanız, en az ortak paydayı bulmamız gerekiyor. Burada flaşa başvurmadan LCD olmadığını göreceksiniz Örnek:
LCD'ye en yakın şey, iOS kullanıcılarınızı almak için HLS kullanmak ve diğer herkes için flaş kullanmaktır. Benim kişisel favorim HLS'yi kodlamak, ardından diğer herkes için HLS'yi oynatmak için flash kullanmaktır. JW player 6 aracılığıyla flash'ta HLS oynatabilirsiniz (veya benim yaptığım gibi AS3'te FLV'ye kendi HLS'nizi yazabilirsiniz)
Yakında, bunu yapmanın en yaygın yolu iOS/Mac'te HLS ve diğer her yerde MSE aracılığıyla DASH olacaktır (Netflix yakında bunu yapacak). Ancak hala herkesin tarayıcılarını yükseltmesini bekliyoruz. Ayrıca muhtemelen Firefox için ayrı bir DASH/VP9'a ihtiyacınız olacak (open264'ü biliyorum; berbat. Ana veya yüksek profilli video yapamıyor. Yani şu anda işe yaramaz).
Herkese, özellikle de szatmary'ye teşekkürler çünkü bu karmaşık bir soru ve canlı video akışı yapabilmeniz için hepsinin çalışıyor olması gereken birçok katmanı var. Asıl sorumu ve HTML5 video kullanımını flash'a karşı açıklığa kavuşturmak için - kullanım durumum HTML5'i güçlü bir şekilde tercih ediyor çünkü genel, istemcide uygulanması kolay ve gelecek. Flash uzak bir ikinci en iyidir, bu nedenle bu soru için HTML5'e bağlı kalalım.
Bu alıştırma sayesinde çok şey öğrendim ve canlı yayın yapmanın VOD'dan (HTML5 video ile iyi çalışır) çok daha zor olduğuna katılıyorum. Ancak bunu kullanım durumum için tatmin edici bir şekilde çalıştırdım ve MSE, flash, Node'da ayrıntılı arabelleğe alma şemaları gibi daha karmaşık seçenekleri takip ettikten sonra çözümün çok basit olduğu ortaya çıktı. Sorun FFMPEG'in parçalanmış MP4'ü bozmasıydı ve FFMPEG parametrelerini ayarlamam gerekiyordu ve başlangıçta kullandığım http üzerinden standart node akış borusu yönlendirmesi gereken tek şeydi.
MP4'te, mp4'ü kendi dizinine sahip olan ve mp4 canlı akış seçeneğini uygulanabilir kılan çok daha küçük parçalara ayıran bir 'parçalama' seçeneği vardır. Ancak akışa geri dönmek mümkün değil (benim kullanım durumum için sorun yok) ve FFMPEG'in sonraki sürümleri parçalanmayı destekliyor.
Not zamanlama bir sorun olabilir ve benim çözümümde remuxing'in bir kombinasyonundan kaynaklanan 2 ila 6 saniye arasında bir gecikme yaşıyorum (etkili bir şekilde FFMPEG'in canlı akışı alması, remux etmesi ve ardından HTTP üzerinden servis için node'a göndermesi gerekiyor). Bu konuda pek bir şey yapılamaz, ancak Chrome'da video olabildiğince yetişmeye çalışıyor, bu da videoyu biraz titretiyor ancak IE11'den (tercih ettiğim istemci) daha güncel.
Bu yazıda kodun nasıl çalıştığını açıklamak yerine, yorumlarla birlikte GIST'e göz atın (istemci kodu dahil değildir, node http sunucu adresini içeren standart bir HTML5 video etiketidir). GIST burada: https://gist.github.com/deandob/9240090
Bu kullanım durumuna benzer örnekler bulamadım, bu nedenle yukarıdaki açıklama ve kodun başkalarına yardımcı olmasını umuyorum, özellikle de bu siteden çok şey öğrendiğim ve kendimi hala acemi olarak gördüğüm için!
Bu benim özel sorumun cevabı olmasına rağmen, szatmary'nin cevabını en kapsamlı olduğu için kabul edilen cevap olarak seçtim.
Bu çok yaygın bir yanılgıdır. Canlı HTML5 video desteği yoktur (iOS ve Mac Safari'deki HLS hariç). Bir webm konteyneri kullanarak bunu 'hackleyebilirsiniz' ancak bunun evrensel olarak desteklenmesini beklemiyorum. Aradığınız şey, parçaları tarayıcıya teker teker besleyebileceğiniz Medya Kaynağı Uzantılarına dahil edilmiştir. ancak bazı istemci tarafı javascript yazmanız gerekecektir.