简体   繁体   English

无法通过websocket将视频流式传输到Firefox

[英]Unable to stream video over a websocket to Firefox

I have written some code stream video over a websocket so a sourcebuffer which works in Chrome and Edge. 我已经在websocket上编写了一些代码流视频,因此可以在Chrome和Edge中使用sourcebuffer

However, when I run this in Firefox, the video never plays back, just a spinning wheel animation is displayed. 但是,当我在Firefox中运行时,视频永远不会播放,只显示旋转轮动画。 When I check the <video> statistics, It reads HAVE_METADATA as the ready state and NETWORK_LOADING as the network state. 当我检查<video>统计信息时,它将HAVE_METADATA读作就绪状态,将NETWORK_LOADING作为网络状态读取。

The code looks follows: 代码如下:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
  </head>
  <body>
    <video controls></video>
    <script>
      var mime = 'video/mp4; codecs="avc1.4D401E,mp4a.40.2"';
      var address = 'ws://localhost:54132'

      /* Media Source */

      var source = new MediaSource();
      var video = document.querySelector('video');
      video.src = URL.createObjectURL(source);
      source.addEventListener('sourceopen', sourceOpen);

      /* Buffer */

      var buffer;
      var socket;
      var queue = [];
      var offset = -1;
      var timescale;

      // When the media source opens:
      function sourceOpen() {
        buffer = source.addSourceBuffer(mime);
        buffer.addEventListener('updateend', processQueue);

        socket = new WebSocket(address);
        socket.binaryType = 'arraybuffer';
        socket.onmessage = onMessage; 
      }

      // When more data is received.
      function onMessage(event) {
        queue.push(event.data);
        processQueue();
      }

      // Process queue if possible.
      function processQueue() {
        if ((queue.length == 0) || (buffer.updating)) {
          return;
        }

        var data = queue.shift();
        if (offset === -1) {
          var parsed = parseMP4(data);
          if (parsed.hasOwnProperty('moov')) {
            timescale = parsed.moov.mvhd.timescale;
          } else if (parsed.hasOwnProperty('moof')) {
            offset = 0 - (parsed.moof.traf[0].tfdt.baseMediaDecodeTime / this.timescale - 0.4);
            buffer.timestampOffset = offset;
          }
        }

        // console.log('appending ' + data.byteLength + ' bytes');
        buffer.appendBuffer(data);
      }

      // Parse out the offset.
      function parseMP4(data) {
        // SNIP for brevity
      }
    </script>
  </body>
</html>

Could not reproduce <video> element not playing at firefox 47. 无法重现<video>元素无法在Firefox 47播放。

Merged approaches at Mocking Websocket Message Events to create mock WebSocket events; Mocking Websocket Message Events中的合并方法,用于创建模拟WebSocket事件; bufferAll.html demo at Let's Make a Netflix An Intro to Streaming Media on the Web for MediaSource usage pattern. bufferAll.html演示让我们在网上bufferAll.html 制作流媒体介绍以获取MediaSource使用模式。

Included <progress> and progress event to notify user of media loading status. 包含<progress>progress事件以通知用户媒体加载状态。

 <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> </head> <body> <progress min="0" value="0"></progress><br><label></label><br> <video controls></video> <script> // http://nickdesaulniers.github.io/netfix/demo/bufferAll.html // http://jsfiddle.net/adamboduch/JVfkt/ // The global web socket. var sock, sourceBuffer; sock = new WebSocket( "ws://mock" ); sock.onerror = function(e) { console.log("sock error", e) } // This is unchanging production code that doesn"t know // we"re mocking the web socket. sock.onmessage = function( e ) { console.log("socket message", e.data); sourceBuffer.appendBuffer(e.data); }; var video = document.querySelector("video"); var progress = document.querySelector("progress"); var label = document.querySelector("label"); var assetURL = "http://nickdesaulniers.github.io/netfix/" + "demo/frag_bunny.mp4"; // Need to be specific for Blink regarding codecs // ./mp4info frag_bunny.mp4 | grep Codec var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'; if ("MediaSource" in window && MediaSource.isTypeSupported(mimeCodec)) { var mediaSource = new MediaSource; //console.log(mediaSource.readyState); // closed video.src = URL.createObjectURL(mediaSource); mediaSource.addEventListener("sourceopen", sourceOpen); } else { console.error("Unsupported MIME type or codec: ", mimeCodec); } video.addEventListener("canplay", function() { alert("video canplay") }) function sourceOpen (_) { //console.log(this.readyState); // open var mediaSource = this; sourceBuffer = mediaSource.addSourceBuffer(mimeCodec); fetchAB(assetURL, function (buf) { sourceBuffer.addEventListener("updateend", function (event) { console.log("sourceBuffer updateend event;" + "mediaSource.readyState:" , mediaSource.readyState); // mediaSource.endOfStream(); // video.play(); // console.log(mediaSource.readyState); // ended }); }); }; // mock `WebSocket` message function fetchAB (url, cb) { var xhr = new XMLHttpRequest; xhr.open("get", url); var file = url.split("/").pop(); xhr.responseType = "arraybuffer"; xhr.onload = function () { // mock `WebSocket` message sock.dispatchEvent( new MessageEvent( "message", { data: xhr.response })); console.log("video sent to sock", sock); cb(); }; xhr.onprogress = function(e) { progress.max = e.total; progress.value = e.loaded; label.innerHTML = "loading " + file + " ...<br>" + e.loaded + " of " + e.total + " bytes loaded"; } xhr.send(); }; </script> </body> </html> 

plnkr http://plnkr.co/edit/RCIqDXTB2BL3lec9bhfz plnkr http://plnkr.co/edit/RCIqDXTB2BL3lec9bhfz

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
  </head>
  <body>
    <progress min="0" value="0"></progress><br><label></label><br>
    <video controls></video>
    <script>
        // http://nickdesaulniers.github.io/netfix/demo/bufferAll.html
        // http://jsfiddle.net/adamboduch/JVfkt/
        // The global web socket.    
        var sock, sourceBuffer;
        sock = new WebSocket( "ws://mock" );
        sock.onerror = function(e) {
          console.log("sock error", e)
        }
        // This is unchanging production code that doesn"t know
        // we"re mocking the web socket.
        sock.onmessage = function( e ) {
          console.log("socket message", e.data);
          sourceBuffer.appendBuffer(e.data);
        }; 
      var video = document.querySelector("video");
      var progress = document.querySelector("progress");
      var label = document.querySelector("label");
      var assetURL = "http://nickdesaulniers.github.io/netfix/"
                     + "demo/frag_bunny.mp4";
      // Need to be specific for Blink regarding codecs
      // ./mp4info frag_bunny.mp4 | grep Codec
      var mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';

      if ("MediaSource" in window 
          && MediaSource.isTypeSupported(mimeCodec)) {
        var mediaSource = new MediaSource;
        //console.log(mediaSource.readyState); // closed
        video.src = URL.createObjectURL(mediaSource);
        mediaSource.addEventListener("sourceopen", sourceOpen);
      } else {
        console.error("Unsupported MIME type or codec: ", mimeCodec);
      }
      video.addEventListener("canplay", function() {
        alert("video canplay")
      })
      function sourceOpen (_) {
        //console.log(this.readyState); // open
        var mediaSource = this;
        sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
        fetchAB(assetURL, function (buf) {
          sourceBuffer.addEventListener("updateend", function (event) {
          console.log("sourceBuffer updateend event;"
                      + "mediaSource.readyState:"
                     , mediaSource.readyState);
            // mediaSource.endOfStream();
            // video.play();
            // console.log(mediaSource.readyState); // ended
          });

        });
      };
      // mock `WebSocket` message
      function fetchAB (url, cb) {
        var xhr = new XMLHttpRequest;
        xhr.open("get", url);
        var file = url.split("/").pop();
        xhr.responseType = "arraybuffer";
        xhr.onload = function () {
          // mock `WebSocket` message
          sock.dispatchEvent( new MessageEvent( "message", {
            data: xhr.response
        }));
        console.log("video sent to sock", sock);
        cb();
        };
        xhr.onprogress = function(e) {
           progress.max = e.total;
           progress.value = e.loaded;
           label.innerHTML = "loading " + file + " ...<br>"
                             + e.loaded + " of " 
                             + e.total + " bytes loaded";
        }
        xhr.send();
      };  
    </script>
  </body>
  </html>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM