javascript MediaSource 错误:此 SourceBuffer 已从父媒体源中删除

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24102075/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 02:11:41  来源:igfitidea点击:

MediaSource error: This SourceBuffer has been removed from the parent media source

javascripthtmlmedia-source

提问by Chris Nolet

I'm experimenting with the new MediaSource API available in Chrome.

我正在试验 Chrome 中可用的新 MediaSource API。

I'm trying to append binary data on the fly from a WebSocket to the video media source.

我正在尝试将二进制数据从 WebSocket 动态附加到视频媒体源。

Starting with the example at https://html5-demos.appspot.com/static/media-source.html, my code is currently:

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);

I consistently get the error message: InvalidStateError: Failed to execute 'appendBuffer' on 'SourceBuffer': This SourceBuffer has been removed from the parent media source.after one append. It looks like the MediaSource is closing immediately after the call to buffer.appendData().

我一直收到错误消息:InvalidStateError: Failed to execute 'appendBuffer' on 'SourceBuffer': This SourceBuffer has been removed from the parent media source.在一次追加之后。看起来 MediaSource 在调用 之后立即关闭buffer.appendData()

Any way to do this elegantly?

有什么办法可以优雅地做到这一点?

Note: chrome://media-internals/ doesn't return any useful information.

注意: chrome://media-internals/ 不会返回任何有用的信息。

采纳答案by Chris Nolet

Ultimately the issue was that I was sending h264 video down the websocket. The MediaSource API only supports MPEG-DASH and VP8 with keyframed segments currently (on Chrome 35).

最终的问题是我正在通过 websocket 发送 h264 视频。MediaSource API 目前仅支持带有关键帧片段的 MPEG-DASH 和 VP8(在 Chrome 35 上)。

Additionally, once I tried VP8, I saw that I was adding some frames out of order.

此外,一旦我尝试了 VP8,我发现我添加了一些乱序的帧。

  • Adding if (buffer.updating || queue.length > 0)in websocket.onmessagewas required.
  • Adding if (queue.length > 0 && !buffer.updating)in buffer.addEventListener('update', ...)was also required.
  • 添加if (buffer.updating || queue.length > 0)websocket.onmessage被要求。
  • 添加if (queue.length > 0 && !buffer.updating)buffer.addEventListener('update', ...)还要求。

Note:I applied the edits mentioned here to the code in the question, so the only issue with the code in the question is that the codec is wrong

注意:我将此处提到的编辑应用于问题中的代码,因此问题中的代码唯一的问题是编解码器错误

回答by The Conspiracy

Chrome is unbelievably picky when it comes to SourceBuffer codecs. Worse, it will return useless and misleading error messages as in case of the OP.

Chrome 对 SourceBuffer 编解码器的挑剔令人难以置信。更糟糕的是,它会像 OP 一样返回无用且误导性的错误消息。

It looks like the MediaSource is closing immediately after the call to buffer.appendData()

看起来 MediaSource 在调用后立即关闭 buffer.appendData()

That's exactly the case: Chrome is not happy with the video as it somehow doesn't exactlyconform to its likings and simply closes the source buffer without notice.

情况正是如此:Chrome 对视频不满意,因为它在某种程度上并不完全符合其喜好,并且只是在没有通知的情况下关闭了源缓冲区

Possible solutions to look for:

寻找可能的解决方案:

  1. Transcode your MP4 files using ffmpeg, explained here(headline Fragmenting).
  2. Use mp4file of mp4v2to find out the exact MP4 codec, explained hereand here.
  3. If you don't have audio, omit the audio codec part: e.g. 'video/mp4; codecs="avc1.64001F"'instead of 'video/mp4; codecs="avc1.64001F, mp4a.40.2"'.
  1. 使用ffmpeg 对您的 MP4 文件进行转码,在此处解释(标题Fragmenting)。
  2. 使用 mp4v2 的mp4file找出确切的 MP4 编解码器,在此处此处解释。
  3. 如果您没有音频,请省略音频编解码器部分:例如'video/mp4; codecs="avc1.64001F"'代替'video/mp4; codecs="avc1.64001F, mp4a.40.2"'.