33

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.after one append. への呼び出しの直後に MediaSource が閉じているようbuffer.appendData()です。

これをエレガントに行う方法はありますか?

注: chrome://media-internals/ は有用な情報を返しません。

4

2 に答える 2

13

最終的に問題となったのは、h264 ビデオを WebSocket に送信していたことです。MediaSource API は、現在 (Chrome 35 で) キーフレーム セグメントを使用する MPEG-DASH および VP8 のみをサポートしています。

さらに、VP8 を試してみると、いくつかのフレームを順不同で追加していることに気付きました。

  • 追加if (buffer.updating || queue.length > 0)websocket.onmessage必要でした。
  • 追加も必要でしたif (queue.length > 0 && !buffer.updating)buffer.addEventListener('update', ...)

注:ここで言及した編集を質問のコードに適用したため、質問のコードの唯一の問題は、コーデックが間違っていることです

于 2014-06-11T00:34:29.047 に答える