Cách tiếp cận tốt nhất để truyền phát http thời gian thực tới ứng dụng video HTML5


212

Tôi thực sự bế tắc khi cố gắng hiểu cách tốt nhất để truyền phát đầu ra thời gian thực của ffmpeg sang máy khách HTML5 bằng cách sử dụng node.js, vì có một số biến khi chơi và tôi không có nhiều kinh nghiệm trong không gian này, đã dành nhiều giờ để thử các kết hợp khác nhau.

Trường hợp sử dụng của tôi là:

1) Luồng máy quay video IP RTSP H.264 được FFMPEG chọn và chuyển sang bộ chứa mp4 bằng các cài đặt FFMPEG sau trong nút, xuất ra STDOUT. Điều này chỉ chạy trên kết nối máy khách ban đầu, do đó, các yêu cầu nội dung một phần không cố gắng sinh ra FFMPEG một lần nữa.

liveFFMPEG = child_process.spawn("ffmpeg", [
                "-i", "rtsp://admin:12345@192.168.1.234:554" , "-vcodec", "copy", "-f",
                "mp4", "-reset_timestamps", "1", "-movflags", "frag_keyframe+empty_moov", 
                "-"   // output to stdout
                ],  {detached: false});

2) Tôi sử dụng máy chủ http của nút để chụp STDOUT và truyền phát lại cho máy khách theo yêu cầu của máy khách. Khi máy khách kết nối lần đầu tiên tôi sinh ra dòng lệnh FFMPEG ở trên, sau đó chuyển luồng STDOUT sang phản hồi HTTP.

liveFFMPEG.stdout.pipe(resp);

Tôi cũng đã sử dụng sự kiện truyền phát để ghi dữ liệu FFMPEG vào phản hồi HTTP nhưng không có sự khác biệt

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

Tôi sử dụng tiêu đề HTTP sau (cũng được sử dụng và hoạt động khi truyền phát các tệp được ghi trước)

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) Máy khách phải sử dụng thẻ video HTML5.

Tôi không gặp vấn đề gì với phát lại phát trực tuyến (sử dụng fs.createReadStream với 206 nội dung một phần HTTP) cho máy khách HTML5 một tệp video được ghi lại trước đó bằng dòng lệnh FFMPEG ở trên (nhưng được lưu vào tệp thay vì STDOUT), vì vậy tôi biết luồng FFMPEG là chính xác và tôi thậm chí có thể thấy chính xác video phát trực tiếp trong VLC khi kết nối với máy chủ nút HTTP.

Tuy nhiên, việc cố gắng phát trực tiếp từ FFMPEG qua nút HTTP có vẻ khó hơn rất nhiều vì máy khách sẽ hiển thị một khung rồi dừng lại. Tôi nghi ngờ vấn đề là tôi không thiết lập kết nối HTTP để tương thích với ứng dụng video HTML5. Tôi đã thử nhiều cách như sử dụng HTTP 206 (nội dung một phần) và 200 phản hồi, đưa dữ liệu vào bộ đệm sau đó phát trực tuyến mà không gặp may, vì vậy tôi cần quay lại các nguyên tắc đầu tiên để đảm bảo tôi thiết lập đúng đường.

Dưới đây là sự hiểu biết của tôi về cách thức hoạt động của nó, xin vui lòng sửa cho tôi nếu tôi sai:

1) FFMPEG nên được thiết lập để phân đoạn đầu ra và sử dụng một moov trống (FFMPEG Frag_keyframe và blank_moov Mov flags). Điều này có nghĩa là khách hàng không sử dụng nguyên tử moov thường ở cuối tập tin không liên quan khi phát trực tuyến (không có phần cuối của tập tin), nhưng có nghĩa là không thể tìm kiếm điều gì tốt cho trường hợp sử dụng của tôi.

2) Mặc dù tôi sử dụng các đoạn MP4 và MOOV trống, tôi vẫn phải sử dụng nội dung một phần HTTP, vì trình phát HTML5 sẽ đợi cho đến khi toàn bộ luồng được tải xuống trước khi phát, với luồng trực tiếp không bao giờ kết thúc nên không thể thực hiện được.

3) Tôi không hiểu tại sao đường truyền luồng STDOUT đến phản hồi HTTP không hoạt động khi phát trực tiếp nếu tôi lưu vào tệp Tôi có thể truyền tệp này dễ dàng đến các máy khách HTML5 bằng mã tương tự. Có lẽ đó là một vấn đề thời gian vì phải mất một giây để sinh sản FFMPEG bắt đầu, kết nối với camera IP và gửi các đoạn đến nút và các sự kiện dữ liệu nút cũng không thường xuyên. Tuy nhiên, bytestream phải chính xác giống như lưu vào một tệp và HTTP có thể phục vụ cho sự chậm trễ.

4) Khi kiểm tra nhật ký mạng từ máy khách HTTP khi phát trực tuyến tệp MP4 được tạo bởi FFMPEG từ máy ảnh, tôi thấy có 3 yêu cầu máy khách: Yêu cầu GET chung cho video, máy chủ HTTP trả về khoảng 40Kb, sau đó một phần yêu cầu nội dung với phạm vi byte cho 10K cuối cùng của tệp, sau đó yêu cầu cuối cùng cho các bit ở giữa không được tải. Có lẽ ứng dụng khách HTML5 sau khi nhận được phản hồi đầu tiên đang yêu cầu phần cuối của tệp để tải nguyên tử MP4 MOOV? Nếu đây là trường hợp, nó sẽ không hoạt động để phát trực tuyến vì không có tệp MOOV và không có kết thúc của tệp.

5) Khi kiểm tra nhật ký mạng khi cố gắng phát trực tiếp, tôi nhận được yêu cầu ban đầu bị hủy chỉ với khoảng 200 byte nhận được, sau đó yêu cầu lại lại bị hủy bỏ với 200 byte và yêu cầu thứ ba chỉ dài 2K. Tôi không hiểu tại sao máy khách HTML5 sẽ hủy bỏ yêu cầu vì bytestream hoàn toàn giống với tôi có thể sử dụng thành công khi truyền phát từ một tệp được ghi. Có vẻ như nút không gửi phần còn lại của luồng FFMPEG đến máy khách, tuy nhiên tôi có thể thấy dữ liệu FFMPEG trong thói quen sự kiện .on để nó đến máy chủ HTTP của nút FFMPEG.

6) Mặc dù tôi nghĩ rằng việc truyền luồng STDOUT vào bộ đệm phản hồi HTTP sẽ hoạt động, tôi có phải xây dựng một bộ đệm trung gian và luồng sẽ cho phép các yêu cầu máy khách nội dung một phần HTTP hoạt động đúng như khi nó (thành công) đọc một tệp ? Tôi nghĩ rằng đây là lý do chính cho các vấn đề của tôi tuy nhiên tôi không chắc chắn chính xác trong Node làm thế nào để thiết lập tốt nhất. Và tôi không biết làm thế nào để xử lý yêu cầu của khách hàng đối với dữ liệu ở cuối tệp vì không có kết thúc tệp.

7) Tôi có đang đi sai hướng khi cố gắng xử lý 206 yêu cầu nội dung một phần và điều này có nên hoạt động với 200 phản hồi HTTP bình thường không? Phản hồi HTTP 200 hoạt động tốt cho VLC vì vậy tôi nghi ngờ ứng dụng video HTML5 sẽ chỉ hoạt động với các yêu cầu nội dung một phần?

Vì tôi vẫn đang học những thứ này rất khó để xử lý các lớp khác nhau của vấn đề này (FFMPEG, nút, phát trực tuyến, HTTP, video HTML5) nên bất kỳ con trỏ nào cũng sẽ được đánh giá cao. Tôi đã dành hàng giờ để nghiên cứu trên trang web này và mạng và tôi không bắt gặp bất kỳ ai có thể phát trực tuyến thời gian thực trong nút nhưng tôi không thể là người đầu tiên và tôi nghĩ điều này sẽ có thể hoạt động (bằng cách nào đó !).


4
Đây là một chủ đề khó khăn. Điều đầu tiên. Bạn đã đặt Content-Typetrong đầu của bạn? Bạn đang sử dụng mã hóa chunk? Đó là nơi tôi sẽ bắt đầu. Ngoài ra, HTML5 không nhất thiết phải cung cấp chức năng phát trực tuyến, bạn có thể đọc thêm về điều đó tại đây . Rất có thể bạn sẽ cần thực hiện một cách để đệm và phát luồng video bằng phương tiện của riêng bạn ( xem tại đây ), nghĩ rằng điều này có thể không được hỗ trợ tốt. Đồng thời google vào API MediaSource.
tsturzl

Cảm ơn vi đa trả lơi. Có, loại nội dung là 'video / mp4' và mã này hoạt động để truyền phát tệp video. Thật không may, MediaSource chỉ là chrome, tôi phải hỗ trợ các trình duyệt khác. Có thông số kỹ thuật nào về cách máy khách video HTML5 tương tác với máy chủ phát trực tuyến HTTP không? Tôi chắc chắn những gì tôi muốn có thể được thực hiện, chỉ không chắc chắn chính xác như thế nào (với node.js nhưng có thể sử dụng C # hoặc C ++ nếu dễ dàng hơn)
deandob

2
Vấn đề không nằm ở phần cuối của bạn. Bạn đang truyền phát video tốt. Vấn đề là ở frontend / client của bạn, bạn cần tự thực hiện phát trực tuyến. HTML5 đơn giản là không xử lý các luồng. Bạn sẽ cần khám phá các tùy chọn trên mỗi trình duyệt rất có thể. Đọc các tiêu chuẩn w3 cho thẻ video và API phương tiện sẽ là một nơi tốt để bắt đầu.
tsturzl

Có vẻ như nó phải có thể làm cho công việc này. Tôi không đưa ra câu trả lời dứt khoát, nhưng tôi nghi ngờ rằng vấn đề này liên quan đến thực tế là trình duyệt đang mong đợi phần còn lại của tiêu đề / nguyên tử chứa mp4 ở đầu và không phải là khung tiếp theo trong luồng video. Nếu bạn gửi một nguyên tử MOOV cho một video rất dài (để người chơi tiếp tục yêu cầu) cũng như các tiêu đề dự kiến ​​khác và sau đó bắt đầu sao chép từ ffmpeg thì điều này có thể hoạt động. Bạn cũng sẽ phải ẩn thanh chà bằng js trong trình duyệt để chúng không thể quét về phía trước.
jwriteclub

Tôi sẽ đề nghị xem xét WebRTC đang đạt được hỗ trợ trình duyệt chéo tốt hơn từ ngày này sang ngày khác.
Alex Cohn

Câu trả lời:


209

EDIT 3: Kể từ iOS 10, HLS sẽ hỗ trợ các tệp mp4 bị phân mảnh. Câu trả lời bây giờ là tạo các tài sản mp4 phân mảnh, với bảng kê khai DASH và HLS. > Giả vờ flash, iOS9 trở xuống và IE 10 trở xuống không tồn tại.

Tất cả mọi thứ bên dưới dòng này đã hết hạn. Giữ nó ở đây cho hậu thế.


EDIT 2: Khi mọi người trong các bình luận đang chỉ ra, mọi thứ thay đổi. Hầu như tất cả các trình duyệt sẽ hỗ trợ codec AVC / AAC. iOS vẫn yêu cầu HLS. Nhưng thông qua các bộ điều hợp như hls.js, bạn có thể chơi HLS trong MSE. Câu trả lời mới là HLS + hls.js nếu bạn cần iOS. hoặc chỉ phân mảnh MP4 (tức là DASH) nếu bạn không

Có nhiều lý do tại sao video và cụ thể, video trực tiếp rất khó khăn. (Xin lưu ý rằng câu hỏi ban đầu đã chỉ định rằng video HTML5 là một yêu cầu, nhưng người hỏi cho biết Flash có thể có trong các nhận xét. Vì vậy, ngay lập tức, câu hỏi này gây hiểu nhầm)

Đầu tiên tôi sẽ trình bày lại: KHÔNG CÓ HPORT TRỢ CHÍNH THỨC ĐỂ ĐỔI TRỰC TIẾP TRÊN HTML5 . Có hack, nhưng số dặm của bạn có thể thay đổi.

EDIT: kể từ khi tôi viết câu trả lời này, Phần mở rộng nguồn phương tiện đã hoàn thiện và hiện đang rất gần để trở thành một lựa chọn khả thi. Chúng được hỗ trợ trên hầu hết các trình duyệt chính. IOS tiếp tục là một vấn đề khó khăn.

Tiếp theo, bạn cần hiểu rằng Video theo yêu cầu (VOD) và video trực tiếp rất khác nhau. Vâng, cả hai đều là video, nhưng các vấn đề là khác nhau, do đó các định dạng là khác nhau. Ví dụ: nếu đồng hồ trong máy tính của bạn chạy nhanh hơn 1% so với bình thường, bạn sẽ không nhận thấy trên VOD. Với video trực tiếp, bạn sẽ cố gắng phát video trước khi nó xảy ra. Nếu bạn muốn tham gia vào một luồng video trực tiếp đang diễn ra, bạn cần dữ liệu cần thiết để khởi tạo bộ giải mã, do đó, nó phải được lặp lại trong luồng hoặc được gửi ra khỏi băng tần. Với VOD, bạn có thể đọc phần đầu của tệp mà họ tìm kiếm đến bất kỳ điểm nào bạn muốn.

Bây giờ hãy đào một chút.

Nền tảng:

  • iOS
  • máy tính
  • Mac
  • Android

Mật mã:

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

Các phương thức phân phối phổ biến cho video trực tiếp trong trình duyệt:

  • DASH (HTTP)
  • HLS (HTTP)
  • đèn flash (RTMP)
  • đèn flash (HDS)

Các phương thức phân phối phổ biến cho VOD trong trình duyệt:

  • DASH (Truyền phát HTTP)
  • HLS (Truyền phát HTTP)
  • đèn flash (RTMP)
  • flash (Truyền phát HTTP)
  • MP4 (phát trực tuyến giả HTTP)
  • Tôi sẽ không nói về MKV và OOG vì tôi không biết rõ về họ.

thẻ video html5:

  • MP4
  • webm
  • ogg

Hãy xem trình duyệt nào hỗ trợ định dạng nào

Safari:

  • HLS (chỉ dành cho iOS và mac)
  • h.264
  • MP4

Firefox

  • DASH (thông qua MSE nhưng không có h.264)
  • h.264 chỉ qua Flash!
  • VP9
  • MP4
  • OGG
  • Webm

I E

  • Tốc biến
  • DASH (chỉ thông qua MSE IE 11+)
  • h.264
  • MP4

Trình duyệt Chrome

  • Tốc biến
  • DASH (thông qua MSE)
  • h.264
  • VP9
  • MP4
  • webm
  • ogg

Không thể sử dụng MP4 cho video trực tiếp (LƯU Ý: DASH là siêu bộ của MP4, vì vậy đừng nhầm lẫn với điều đó). MP4 được chia thành hai phần: moov và mdat. mdat chứa dữ liệu video âm thanh thô. Nhưng nó không được lập chỉ mục, vì vậy nếu không có moov, nó là vô dụng. Moov chứa một chỉ mục của tất cả dữ liệu trong mdat. Nhưng do định dạng của nó, nó không thể được 'làm phẳng' cho đến khi biết dấu thời gian và kích thước của khung MERYI. Có thể xây dựng một moov 'kích thước' kích thước khung hình, nhưng rất lãng phí băng thông.

Vì vậy, nếu bạn muốn giao hàng ở mọi nơi, chúng tôi cần tìm mẫu số ít phổ biến nhất. Bạn sẽ thấy không có màn hình LCD ở đây mà không dùng đến ví dụ flash:

  • iOS chỉ hỗ trợ video h.264. và nó chỉ hỗ trợ HLS cho trực tiếp.
  • Firefox hoàn toàn không hỗ trợ h.264, trừ khi bạn sử dụng flash
  • Flash không hoạt động trong iOS

Điều gần gũi nhất với LCD là sử dụng HLS để có được người dùng iOS của bạn và flash cho mọi người khác. Sở thích cá nhân của tôi là mã hóa HLS, sau đó sử dụng flash để phát HLS cho mọi người khác. Bạn có thể phát HLS trong flash qua JW player 6, (hoặc viết HLS của riêng bạn sang FLV trong AS3 như tôi đã làm)

Sắp tới, cách phổ biến nhất để làm điều này sẽ là HLS trên iOS / Mac và DASH thông qua MSE ở mọi nơi khác (Đây là những gì Netflix sẽ làm sớm). Nhưng chúng tôi vẫn đang chờ mọi người nâng cấp trình duyệt của họ. Bạn cũng có thể cần một DASH / VP9 riêng cho Firefox (Tôi biết về open264; nó rất tệ. Nó không thể quay video ở cấu hình chính hoặc cao. Vì vậy, hiện tại nó vô dụng).


Cảm ơn szatmary cho nền tảng chi tiết và pro / cons về các tùy chọn khác nhau. Tôi đã chọn câu trả lời này là câu trả lời được chấp nhận vì phác thảo của các khái niệm quan trọng hơn cách khắc phục cụ thể mà tôi tìm thấy để trả lời câu hỏi ban đầu. Chúc may mắn với tiền thưởng!
deandob

9
Đây không phải là một giải pháp làm việc cho câu hỏi này. Có một giải pháp làm việc cho vấn đề này dưới đây.
jwriteclub

2
Firefox hiện hỗ trợ MSE và h.264. Truy cập www.youtube.com/html5 với trình duyệt FF mới nhất để xác nhận. Tôi đã thử nghiệm với FF 37. Safari 8+ trên Mac hiện cũng hỗ trợ MSE.
BigTundra

@BigTundra có, safari đã hỗ trợ MSE kể từ khi Yosemite ra mắt trên Mac. Nhưng không phải iOS. Không chắc chắn về Windows. (Có phải safari trên windows vẫn là một thứ không?) Firefox 37.0.2 trên (của tôi) Mac dường như không hỗ trợ MSE chút nào theo liên kết đó. Nhưng không hỗ trợ H.264. Firefox đã thêm và xóa và thêm lại hỗ trợ H.264 trong quá khứ.
szatmary

Hỗ trợ up-to-date trình duyệt cho MPEG-4 định dạng / H.264 video: caniuse.com/#feat=mpeg4
Maxence

75

Cảm ơn tất cả mọi người đặc biệt là szatmary vì đây là một câu hỏi phức tạp và có nhiều lớp cho nó, tất cả những gì phải được làm việc trước khi bạn có thể truyền phát video trực tiếp. Để làm rõ câu hỏi ban đầu của tôi và sử dụng video HTML5 so với flash - trường hợp sử dụng của tôi có ưu tiên mạnh mẽ cho HTML5 vì nó chung chung, dễ thực hiện trên máy khách và tương lai. Flash là thứ tốt nhất thứ hai vì vậy hãy gắn bó với HTML5 cho câu hỏi này.

Tôi đã học được rất nhiều thông qua bài tập này và đồng ý phát trực tiếp khó hơn VOD (hoạt động tốt với video HTML5). Nhưng tôi đã làm điều này để hoạt động tốt cho trường hợp sử dụng của mình và giải pháp rất đơn giản, sau khi theo đuổi các tùy chọn phức tạp hơn như MSE, flash, các sơ đồ đệm phức tạp trong Node. Vấn đề là FFMPEG đã làm hỏng MP4 bị phân mảnh và tôi phải điều chỉnh các tham số FFMPEG, và chuyển hướng ống dòng nút tiêu chuẩn qua http mà tôi sử dụng ban đầu là tất cả những gì cần thiết.

Trong MP4, có một tùy chọn 'phân mảnh', chia mp4 thành các mảnh nhỏ hơn nhiều có chỉ số riêng và làm cho tùy chọn phát trực tiếp mp4 trở nên khả thi. Nhưng không thể tìm kiếm lại luồng (OK cho trường hợp sử dụng của tôi) và các phiên bản FFMPEG sau này hỗ trợ phân mảnh.

Lưu ý thời gian có thể là một vấn đề và với giải pháp của tôi, tôi có độ trễ từ 2 đến 6 giây do sự kết hợp của quá trình làm lại (FFMPEG thực sự phải nhận luồng trực tiếp, sau đó gửi lại cho nút để phục vụ qua HTTP) . Không thể làm được gì nhiều về điều này, tuy nhiên trong Chrome, video cố gắng bắt kịp hết mức có thể khiến video hơi giật nhưng hiện tại nhiều hơn IE11 (ứng dụng khách ưa thích của tôi).

Thay vì giải thích cách mã hoạt động trong bài đăng này, hãy kiểm tra GIST với các bình luận (mã máy khách không được bao gồm, đó là thẻ video HTML5 tiêu chuẩn có địa chỉ máy chủ http của nút). GIST có tại đây: https://gist.github.com/deandob/9240090

Tôi đã không thể tìm thấy các ví dụ tương tự của trường hợp sử dụng này, vì vậy tôi hy vọng lời giải thích và mã trên giúp ích cho những người khác, đặc biệt là khi tôi đã học được rất nhiều từ trang web này và vẫn coi mình là người mới bắt đầu!

Mặc dù đây là câu trả lời cho câu hỏi cụ thể của tôi, tôi đã chọn câu trả lời của szatmary là câu trả lời được chấp nhận vì nó là toàn diện nhất.


33
Xin lỗi, nhưng tôi tự tìm thấy điều này, việc viết lên câu trả lời của tôi làm cho điều này khá rõ ràng. Các câu trả lời trước đó đều hữu ích và được đánh giá cao nhưng không đóng góp đáng kể và tôi thậm chí đã gửi mã làm việc trong GIST và không ai khác có. Tôi không quan tâm đến 'danh tiếng', tôi quan tâm đến việc tìm hiểu xem cách tiếp cận và mã của tôi có thể được cải thiện hay không. Và câu trả lời tôi đã đánh dấu đã giải quyết vấn đề của tôi, vì vậy tôi bối rối không biết vấn đề ở đây là gì. Tôi khá mới với SO nên tôi rất vui khi được yêu cầu tương tác theo một cách khác, tôi thấy trang web này hữu ích và câu trả lời của tôi sẽ giúp người khác.
deandob

2
Có vẻ như không phải là điều thích hợp trong cộng đồng này để chọn câu trả lời của bạn làm câu trả lời được chấp nhận nếu bạn đặt câu hỏi ngay cả khi nó không khắc phục được vấn đề ban đầu. Mặc dù điều đó có vẻ phản trực giác, tài liệu về các khái niệm quan trọng hơn bản sửa lỗi thực tế, điều này tôi thấy ổn vì nó giúp người khác học hỏi. Tôi đã bỏ chọn câu trả lời của mình và chọn szatmary là câu nói rõ nhất xung quanh các khái niệm.
deandob

6
@deandob: Tôi đã đăng một tiền thưởng cho một giải pháp hiệu quả cho vấn đề này mà bạn đã cung cấp thành công. Câu trả lời được chấp nhận khẳng định rằng không có giải pháp làm việc và do đó rõ ràng là không chính xác.
jwriteclub

2
Cảm ơn. Có vẻ như những người khác đã đánh giá thấp câu trả lời ban đầu của tôi là sai và vì tôi mới nên tôi chỉ cho rằng đó là cách mọi thứ hoạt động quanh đây. Tôi không muốn gây ra bất kỳ phiền phức nào nhưng tôi sẽ kiểm tra với những người đang tràn meta stack. BTW - giải pháp của tôi đang hoạt động rất tốt và nó có thể hoạt động được với những người khác và có một biến thể về giải pháp được đăng có thể làm giảm độ trễ ban đầu (bộ đệm trong node.js ban đầu sau đó tìm cách kết thúc luồng ở cuối máy khách) .
deandob

4
Tôi đã làm rõ từ người điều hành rằng cách tiếp cận ban đầu của tôi là tự trả lời câu hỏi và chọn câu trả lời đó là cách tiếp cận đúng. Để biết thêm thông tin (hoặc nếu bạn muốn tranh luận thêm về vấn đề này), hãy xem chủ đề trên trang web meta. meta.stackexchange.com/questions/224068/
hàn

14

Hãy xem dự án JSMPEG . Có một ý tưởng tuyệt vời được triển khai ở đó - để giải mã MPEG trong trình duyệt bằng JavaScript. Ví dụ, byte từ bộ mã hóa (ví dụ FFMPEG) có thể được chuyển sang trình duyệt bằng WebSockets hoặc Flash. Nếu cộng đồng sẽ bắt kịp, tôi nghĩ, nó sẽ là giải pháp phát video trực tiếp HTML5 tốt nhất hiện nay.


10
Đó là bộ giải mã video MPEG-1. Tôi không chắc bạn hiểu MPEG-1 cổ đại như thế nào; nó cũ hơn DVD. Nó cao hơn một chút so với tệp GIF.
Camilo Martin

13

Tôi đã viết một trình phát video HTML5 xung quanh codec h264 broadway (emscripten) có thể phát video trực tiếp (không chậm trễ) trên tất cả các trình duyệt (máy tính để bàn, iOS, ...).

Luồng video được gửi qua websocket đến máy khách, giải mã khung hình trên mỗi khung và được hiển thị trong một canva (sử dụng webgl để tăng tốc)

Hãy xem https://github.com/131/h264-live-player trên github.


1
github.com/Streamedian/html5_rtsp_player Những người này đã làm một cái gì đó tương tự sử dụng rtp h264 trên websocket
Victor.dMdB

12

Một cách để phát trực tiếp webcam dựa trên RTSP sang máy khách HTML5 (liên quan đến mã hóa lại, do đó, sẽ mất chất lượng và cần một số năng lượng CPU):

  • Thiết lập máy chủ icecast (có thể trên cùng một máy mà máy chủ web của bạn đang bật hoặc trên máy nhận luồng RTSP từ cam)
  • Trên máy nhận luồng từ máy ảnh, không sử dụng FFMPEG mà là trình phát. Nó có thể nhận và giải mã luồng RTSP, mã hóa lại và truyền phát đến máy chủ icecast. Đường ống mẫu (chỉ video, không có âm thanh):

    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

=> Sau đó, bạn có thể sử dụng thẻ <video> với URL của luồng icecast ( http://127.0.0.1:12000/cam.webm ) và nó sẽ hoạt động trong mọi trình duyệt và thiết bị hỗ trợ webm


3

Hãy xem giải pháp này . Như tôi biết, Flashphoner cho phép phát luồng âm thanh trực tiếp + video trong trang HTML5 thuần túy.

Họ sử dụng codec MPEG1G.711 để phát lại. Bản hack đang kết xuất video được giải mã thành phần tử canvas HTML5 và phát âm thanh được giải mã thông qua ngữ cảnh âm thanh HTML5.



2

Đây là một quan niệm sai lầm rất phổ biến. Không có hỗ trợ video HTML5 trực tiếp (ngoại trừ HLS trên iOS và Mac Safari). Bạn có thể 'hack' nó bằng cách sử dụng bộ chứa webm, nhưng tôi không mong đợi rằng nó sẽ được hỗ trợ toàn cầu. Những gì bạn đang tìm kiếm được bao gồm trong Tiện ích mở rộng nguồn phương tiện, nơi bạn có thể cung cấp các đoạn cho trình duyệt một lần. nhưng bạn sẽ cần phải viết một số javascript phía máy khách.


solutionsnhưng không có supportđể phát trực tiếp. Điều này là trực tiếp đề cập đến nhận xét của tôi nhìn thấy ở trên. Và webm được hỗ trợ trên các trình duyệt chính, chủ yếu là phiên bản ổn định mới nhất.
tsturzl

1
Tôi thực sự không muốn chuyển mã từ H.264 sang webm và không cần thiết. Ngoài ra, tôi phải hỗ trợ IE11 và Safari, tiện ích mở rộng MediaSource sẽ không trợ giúp. Nhưng tôi nghĩ rằng nếu tôi mô phỏng một luồng tệp ở phía máy chủ (hoạt động!) Thì nó sẽ hoạt động, nhưng tôi sẽ phải mô phỏng bộ đệm tệp trên node.js.
deandob

1
Như đề xuất khác, tôi sẽ tìm kiếm một khả năng sử dụng WebRTC vốn không giống như VLC hoặc plugin flash. Tôi biết công nghệ này vẫn khó thực hiện. Chúc may mắn.

1
Tôi đã làm việc này bằng cách cập nhật lên phiên bản FFMPEG mới nhất vì có vẻ như đã xảy ra lỗi ở mp4 khi sử dụng chế độ phân mảnh (cần thiết cho phát trực tiếp MP4 để khách hàng không đợi tệp chỉ mục moov sẽ không bao giờ xuất hiện khi trực tiếp phát trực tuyến). Và mã node.js của tôi để chuyển hướng luồng FFMPEG trực tiếp đến trình duyệt hiện hoạt động.
deandob

1
Có, hoạt động tốt trên IE11 (trình duyệt ưa thích của tôi). Tôi nhận được phản hồi nhanh chóng trong Chrome.
deandob

2

Hãy thử binaryjs. Nó giống như socket.io nhưng chỉ có điều nó làm tốt là nó truyền phát video âm thanh. Binaryjs google nó


1
Binary.JS không có gì giống như Socket.IO. Và, nó không cụ thể cho truyền phát trực tuyến.
Brad
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.