代码之家  ›  专栏  ›  技术社区  ›  lucky1928

MediaSourceExtension fMP4流媒体播放失败

  •  1
  • lucky1928  · 技术社区  · 8 年前

    下列的 this 链接,我只是将webm格式更改为fMP4,如下所示。但它不起作用。原始测试。webm文件工作正常。

    对于webm,配置如下:

    //source: http://html5-demos.appspot.com/static/test.webm
    var FILE = "test.webm"
    var codec = 'video/webm; codecs="vorbis,vp8"';
    

    对于fMP4,更改配置如下:

    //source http://yt-dash-mse-test.commondatastorage.googleapis.com/media/car-20120827-85.mp4
    var FILE = "car-20120827-85.mp4";
    var codec = 'video/mp4; codecs="mp4a,avc"';
    //var codec = 'video/mp4; codecs="mp4a.40.2,avc1.640028"';
    

    我猜fMP4的mime可能是错的,但我在网上搜索了很多次后才发现。

    <!DOCTYPE html>
    <html>
    <body>
    <section>
      <video controls autoplay width="320" height="240"></video>
      <pre id="log"></pre>
    </section>
    <script>
    //source: http://html5-demos.appspot.com/static/test.webm
    //var FILE = "test.webm"
    //var codec = 'video/webm; codecs="vorbis,vp8"';
    
    //source http://yt-dash-mse-test.commondatastorage.googleapis.com/media/car-20120827-85.mp4
    var FILE = "car-20120827-85.mp4";
    var codec = 'video/mp4; codecs="mp4a,avc"';
    //var codec = 'video/mp4; codecs="mp4a.40.2,avc1.640028"';
    
    var NUM_CHUNKS = 5;
    var video = document.querySelector('video');
    
    window.MediaSource = window.MediaSource || window.WebKitMediaSource;
    if (!!!window.MediaSource) {
      alert('MediaSource API is not available');
    }
    
    var mediaSource = new MediaSource();
    video.src = window.URL.createObjectURL(mediaSource);
    
    function callback(e) {
      var sourceBuffer = mediaSource.addSourceBuffer(codec);
    
      logger.log('mediaSource readyState: ' + this.readyState);
    
      GET(FILE, function(uInt8Array) {
        var file = new Blob([uInt8Array], {type: 'video/webm'});
        var chunkSize = Math.ceil(file.size / NUM_CHUNKS);
    
        logger.log('num chunks:' + NUM_CHUNKS);
        logger.log('chunkSize:' + chunkSize + ', totalSize:' + file.size);
    
        // Slice the video into NUM_CHUNKS and append each to the media element.
        var i = 0;
    
        (function readChunk_(i) {
          var reader = new FileReader();
    
          // Reads aren't guaranteed to finish in the same order they're started in,
          // so we need to read + append the next chunk after the previous reader
          // is done (onload is fired).
          reader.onload = function(e) {
            sourceBuffer.appendBuffer(new Uint8Array(e.target.result));
            logger.log('appending chunk:' + i);
            if (i == NUM_CHUNKS - 1) {
              mediaSource.endOfStream();
            } else {
              if (video.paused) {
                video.play(); // Start playing after 1st chunk is appended.
              }
              readChunk_(++i);
            }
          };
    
          var startByte = chunkSize * i;
          var chunk = file.slice(startByte, startByte + chunkSize);
    
          reader.readAsArrayBuffer(chunk);
        })(i);  // Start the recursive call by self calling.
      });
    }
    
    mediaSource.addEventListener('sourceopen', callback, false);
    mediaSource.addEventListener('webkitsourceopen', callback, false);
    
    mediaSource.addEventListener('webkitsourceended', function(e) {
      logger.log('mediaSource readyState: ' + this.readyState);
    }, false);
    
    function GET(url, callback) {
      var xhr = new XMLHttpRequest();
      xhr.open('GET', url, true);
      xhr.responseType = 'arraybuffer';
      xhr.send();
    
      xhr.onload = function(e) {
        if (xhr.status != 200) {
          alert("Unexpected status code " + xhr.status + " for " + url);
          return false;
        }
        callback(new Uint8Array(xhr.response));
      };
    }
    </script>
    <script>
    function Logger(id) {
      this.el = document.getElementById('log');
    }
    Logger.prototype.log = function(msg) {
      var fragment = document.createDocumentFragment();
      fragment.appendChild(document.createTextNode(msg));
      fragment.appendChild(document.createElement('br'));
      this.el.appendChild(fragment);
    };
    
    var logger = new Logger('log');
    </script>
    </body>
    </html>
    
    1 回复  |  直到 8 年前
        1
  •  2
  •   Pablo Montilla    8 年前

    问题是 fMP4 格式不同于 webm . 而您可以拆分 webm 文件以任意定义的块为单位,不能使用 fMP4 .

    这个 fMP4 文件只是一堆“盒子”,基本上是由 type , length 和 content (可以包含其他框,使其具有层次结构)。您必须分析文件并为sourceBuffer提供 moov 首先是框(初始化段),然后是 moof mdat 可以解码和播放的方框。

    你可能需要在 fMP4 格式(aka ISO BMFF ).