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

新手上路,请多包涵

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

我正在尝试将二进制数据从 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/ 不会返回任何有用的信息。

原文由 Chris Nolet 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 6.5k
2 个回答

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

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

  • 添加 if (buffer.updating || queue.length > 0)websocket.onmessage 是必需的。
  • if (queue.length > 0 && !buffer.updating) 中添加 buffer.addEventListener('update', ...) 也是必需的。

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

原文由 Chris Nolet 发布,翻译遵循 CC BY-SA 3.0 许可协议

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

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

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

寻找可能的解决方案:

  1. 使用 ffmpeg 转码您的 MP4 文件, 在此处 解释(标题 Fragmenting )。
  2. 使用 mp4v2 的 mp4file 找出确切的 MP4 编解码器, 在此处此处 进行了解释。
  3. 如果您没有音频,请省略音频编解码器部分:例如 'video/mp4; codecs="avc1.64001F"' 而不是 'video/mp4; codecs="avc1.64001F, mp4a.40.2"'

原文由 The Conspiracy 发布,翻译遵循 CC BY-SA 4.0 许可协议

推荐问题