Подтвердить что ты не робот

Ошибка MediaSource: этот SourceBuffer был удален из исходного медиа-источника

Я экспериментирую с новым API MediaSource, доступным в Chrome.

Я пытаюсь добавить двоичные данные "на лету" из WebSocket в источник видео.

Начиная с примера в https://html5-demos.appspot.com/static/media-source.html, мой код в настоящее время:

var websocket = new WebSocket('ws://localhost:8080');
websocket.binaryType = 'arraybuffer';

var mediaSource = new MediaSource();
var buffer;
var queue = [];

var video = $('.video')[0];
video.src = window.URL.createObjectURL(mediaSource);

mediaSource.addEventListener('sourceopen', function(e) {
  video.play();

  buffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.64001E"');

  buffer.addEventListener('updatestart', function(e) { console.log('updatestart: ' + mediaSource.readyState); });
  buffer.addEventListener('update', function(e) { console.log('update: ' + mediaSource.readyState); });
  buffer.addEventListener('updateend', function(e) { console.log('updateend: ' + mediaSource.readyState); });
  buffer.addEventListener('error', function(e) { console.log('error: ' + mediaSource.readyState); });
  buffer.addEventListener('abort', function(e) { console.log('abort: ' + mediaSource.readyState); });

  buffer.addEventListener('update', function() { // Note: Have tried 'updateend'
    if (queue.length > 0 && !buffer.updating) {
      buffer.appendBuffer(queue.shift());
    }
  });
}, false);

mediaSource.addEventListener('sourceopen', function(e) { console.log('sourceopen: ' + mediaSource.readyState); });
mediaSource.addEventListener('sourceended', function(e) { console.log('sourceended: ' + mediaSource.readyState); });
mediaSource.addEventListener('sourceclose', function(e) { console.log('sourceclose: ' + mediaSource.readyState); });
mediaSource.addEventListener('error', function(e) { console.log('error: ' + mediaSource.readyState); });

websocket.addEventListener('message', function(e) {
  if (typeof e.data !== 'string') {
    if (buffer.updating || queue.length > 0) {
      queue.push(e.data);
    } else {
      buffer.appendBuffer(e.data);
    }
  }
}, false);

Я последовательно получаю сообщение об ошибке: InvalidStateError: Failed to execute 'appendBuffer' on 'SourceBuffer': This SourceBuffer has been removed from the parent media source. после одного добавления. Похоже, что MediaSource закрывается сразу после вызова buffer.appendData().

Как это сделать элегантно?

Примечание: chrome://media-internals/не возвращает никакой полезной информации.

4b9b3361

Ответ 1

В конечном счете проблема заключалась в том, что я отправлял h264-видео вниз по websocket. API MediaSource поддерживает только MPEG-DASH и VP8 с ключевыми сегментами в настоящее время (в Chrome 35).

Кроме того, как только я попробовал VP8, я увидел, что добавляю несколько кадров из строя.

  • Требуется добавление if (buffer.updating || queue.length > 0) в websocket.onmessage.
  • Также необходимо добавить if (queue.length > 0 && !buffer.updating) в buffer.addEventListener('update', ...).

Примечание. Я применил исправления, упомянутые здесь, к коду в вопросе, поэтому единственная проблема с кодом в вопросе заключается в неправильном кодеке