Mp4box. js создает с моими настройками поток, который не декодируется в FF и Chrome - PullRequest
0 голосов
/ 09 февраля 2020

Основная проблема: отображение живого потока H264 в браузере.

Решение: давайте просто конвертируем его в фрагментированный mp4 и загружаем порцию через порцию websocket (или XHR) в MSE.

Звучит слишком просто. Но я хочу сделать фрагментацию на стороне клиента с чистым JS.

, поэтому я пытаюсь использовать MP4Box. js. На странице readme он заявляет: у него есть демо: «Игрок, который выполняет фрагментацию на лету».

Однако производимые им фрагменты (сегменты) вызывают decodeErrors на Chrome и FireFox ( на Windows 10):

<html>
    <head>
        <title>WebSocket and MSE test</title>
        <script src="https://gpac.github.io/mp4box.js/dist/mp4box.all.js"></script>
    </head>

    <body>
        <video id="livestream" width="640" height="480" autoplay />
    </body>

    <script>
        var ws;                     // websocket
        var mp4box;                 // fragmentation
        var ms;                     // media source
        var sb;                     // source buffer
        var nextBufferStart = 0;
        var forceStart = true;
        var queue = [];

        function startVideo() {
          Log.setLogLevel(Log["debug"]);

          mp4box = MP4Box.createFile();

          mp4box.onError = function(e) {
            console.log("mp4box failed to parse data.");
          };

          mp4box.onMoovStart = function () {
            console.log("Starting to receive File Information");
          };

          mp4box.onReady = function(info) {
            console.log(info.mime);

            mp4box.onSegment = function (id, user, buffer, sampleNum) {
              console.log("Received segment on track "+id+" for object "+user+" with a length of "+buffer.byteLength+",sampleNum="+sampleNum);
              mp4box_onSegment(buffer);
            }

            var options = { nbSamples: 200 };
            mp4box.setSegmentOptions(info.tracks[0].id, null, options); // I don't need user object this time
            var initSegs = mp4box.initializeSegmentation();
            mp4box.start();
          };


          ms = new MediaSource();

          ms.addEventListener('sourceopen', ms_SourceOpened, false);

          var livestream = document.getElementById('livestream');
          livestream.src = window.URL.createObjectURL(ms);
        } 

        function ms_SourceOpened() {
          sb = ms.addSourceBuffer("video/mp4;codecs=\"avc1.4d4028\"");
          sb.addEventListener("updateend", sb_UpdateEnd);

          ws = new WebSocket("ws://a_websocket_server_which_serves_h264_file");
          ws.binaryType = "arraybuffer";
          ws.onmessage = function (event) {
            event.data.fileStart = nextBufferStart; //tried also with event.data.byteOffset, but resulted error.
            nextBufferStart = mp4box.appendBuffer(event.data);
            mp4box.flush(); //tried commenting out - unclear documentation!
          };
        }

        function sb_UpdateEnd() { // called when sourceBuffer is ready for more
          if (!sb.updating) { // really, really ready

            if (queue.length > 0) {
              data = queue.shift();
              console.log("queue PULL:", queue.length);

              var view = new Uint8Array(data);
              console.log("                        writing buffer with", view[0], view[1], view[2], view[3], view[4]);

              sb.appendBuffer(data);
            }
            else { 
              forceStart = true;
            }
          }
        }

        function mp4box_onSegment(buffer) {
          var view = new Uint8Array(buffer);
          console.log("got", buffer.byteLength, "bytes.  Values=", view[0], view[1], view[2], view[3], view[4]);

          if (forceStart && !sb.updating) {
            console.log("Streaming started with", view[0], view[1], view[2], view[3], view[4]);
            sb.appendBuffer(buffer);
            forceStart = false;
            return;
          }

          queue.push(buffer);
          console.log("queue push:", queue.length);
        }

        window.onload = function() {
          startVideo();
        }
    </script>
</html>

Что я делаю не так с кодом здесь? Chrome и FF оба с удовольствием воспроизводят файлы fmp4. Я уверен, что у меня есть легкая распространенная ошибка здесь. Но я не мог продолжать дальше.

Обновление

Я попытался воспроизвести мой файл mp4 с помощью проигрывателя на их сайте, и он работает, как и предполагалось.

Так что, очевидно, я ' Я здесь ошибаюсь.

Я прилагаю сюда вывод журнала как официального, так и моего игрока, пытаясь воспроизвести один и тот же источник. (Только важная часть, перед этим все линии равны):

Официально:

[MultiBufferStream] Appending new buffer (fileStart: 2028784 - Length: 4000)
[MultiBufferStream] 2 stored buffer(s) (48/8000 bytes): [0-3999], [2028784-2032783]
[MultiBufferStream] Found position in existing buffer #1
[MultiBufferStream] Repositioning parser at buffer position: 0
[MultiBufferStream] Found position in existing buffer #1
[MultiBufferStream] Repositioning parser at buffer position: 0
[ISOFile] Found 'mdat' end in buffered data
[BoxParser] Found box of type 'moov' and size 13572 at position 2028784
[MultiBufferStream] Found position in existing buffer #1
[MultiBufferStream] Repositioning parser at buffer position: 0
[BoxParser] Not enough data in stream to parse the entire 'moov' box
[Application] Starting to parse movie information
[ISOFile] Done processing buffer (fileStart: 2028784) - next buffer to fetch should have a fileStart position of 2032784

Мой игрок:

[MultiBufferStream] Appending new buffer (fileStart: 2028784 - Length: 4096)
[MultiBufferStream] 2 stored buffer(s) (48/8192 bytes): [0-4095], [2028784-2032879]
[MultiBufferStream] Found position in existing buffer #1
[MultiBufferStream] Repositioning parser at buffer position: 0
[MultiBufferStream] Found position in existing buffer #1
[MultiBufferStream] Repositioning parser at buffer position: 0
[ISOFile] Found 'mdat' end in buffered data
[BoxParser] Found box of type 'FJé' and size 27781302 at position 2028784
[MultiBufferStream] Found position in existing buffer #1
[MultiBufferStream] Repositioning parser at buffer position: 0
[BoxParser] Not enough data in stream to parse the entire 'FJé' box
[ISOFile] Done processing buffer (fileStart: 2028784) - next buffer to fetch should have a fileStart position of 29810086

Как вы видите, мой проигрыватель не распознает атом 'moov', и поэтому он испортил весь поток мультимедиа.

mp4box. js библиотеки все одинаковые.

Что может вызвать это?

...