URL.createObjectURL(mediaSource) - 从URL播放视频 - MOOV atom - Elastic Transcoder

时间:2018-06-13 21:38:10

标签: amazon-s3 video-streaming html5-video blob m3u8

我正在尝试通过创建blob网址来播放视频(当前托管在具有公共访问权限的S3上)。

我使用Elastic Transcoder对视频进行编码,因为它应该将MO​​OV原子设置为顶部(开始)。

我无法让代码工作,但也找到了一个有效的示例:link here

这是我的代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
  </head>
  <body>
    <video controls></video>
    <script>
      var video = document.querySelector('video');
      var assetURL = 'https://ovation-blob-url-test.s3.amazonaws.com/AdobeStock_116640093_Video_WM_NEW.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);
      }
      function sourceOpen (_) {
        //console.log(this.readyState); // open
        var mediaSource = this;
        var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
        fetchAB(assetURL, function (buf) {
          sourceBuffer.addEventListener('updateend', function (_) {
            mediaSource.endOfStream();
            video.play();
            //console.log(mediaSource.readyState); // ended
          });
          sourceBuffer.appendBuffer(buf);
        });
      };
      function fetchAB (url, cb) {
        console.log(url);
        var xhr = new XMLHttpRequest;
        xhr.open('get', url);
        xhr.responseType = 'arraybuffer';
        xhr.onload = function () {
          cb(xhr.response);
        };
        xhr.send();
      };
    </script>
  </body>
</html>

我做错了什么?我看了工具ie.eMP4Box或QT-FastStart,但它们似乎是一种旧学校。我也愿意从MP4更改为M3U8播放列表,但后来我不知道要使用哪种MIME类型。

当天我正在尝试播放视频/流并使用blob隐藏URL(原点)。

谢谢你们!

2 个答案:

答案 0 :(得分:0)

所以,首先,即使此代码似乎来自mozilla documentation site,也存在一些问题 - 您在调用readyState之前未检查endOfStream因此会出现错误是有效的,其次play()来电被autoplay policy changes阻止。如果添加错误处理程序,您实际上会看到appendBuffer失败。这是更新的代码段:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8"/>
  </head>
  <body>
    <video controls></video>
    <script>
      var video = document.querySelector('video');
      var assetURL = 'https://ovation-blob-url-test.s3.amazonaws.com/AdobeStock_116640093_Video_WM_NEW.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);
      }
      function sourceOpen (_) {
        //console.log(this.readyState); // open
        var mediaSource = this;
        var sourceBuffer = mediaSource.addSourceBuffer(mimeCodec);
        fetchAB(assetURL, function (buf) {
          sourceBuffer.addEventListener('updateend', function (_) {
            // console.log(mediaSource.readyState); // ended
            if (mediaSource.readyState === "open") {
                mediaSource.endOfStream();
                video.play();
            }
          });
          sourceBuffer.addEventListener('error', function (event) {
            console.log('an error encountered while trying to append buffer');
          });
          sourceBuffer.appendBuffer(buf);
        });
      };
      function fetchAB (url, cb) {
        console.log(url);
        var xhr = new XMLHttpRequest;
        xhr.open('get', url);
        xhr.responseType = 'arraybuffer';
        xhr.onload = function () {
          cb(xhr.response);
        };
        xhr.send();
      };
    </script>
  </body>
</html>

所以让我们进入下一个问题 - 实际错误。因此,使用chrome://media-internals/我们可以看到视频实际上无法加载与ISOBMFF格式不兼容:

Chrome media internals error

我对Elastic Transcoder不熟悉,但似乎它没有生成适合直播的mp4文件。另外,如果使用mse,将moov放在开头是不够的,视频实际上必须满足所有ISOBMFF requirements - 参见第3章和第4章。

您提到的工作示例不是有效的比较,因为它使用了src的blob,其中ISOBMFF规则不适用。如果您可以这样做,请不要使用MSE并将blob直接放在src中。如果您需要MSE,则必须正确复用它。

答案 1 :(得分:0)

好吧,所以我得到了原始代码示例,可以用ffmpeg编码我的MP4视频:

ffmpeg -i input.mp4 -vf scale=1920:1080,setsar=1:1 -c:v libx264 -preset medium -c:a aac -movflags empty_moov+default_base_moof+frag_keyframe output.mp4 -hide_banner

重要的是:-movflags empty_moov+default_base_moof+frag_keyframe

此设置还将视频缩放到1920x1080(不考虑输入视频的任何长宽比)

但是,根据原始帖子的评论,我确实相信可能会有一种更有效的方法来生成Blob网址并将其提取到视频标签中。该示例直接从https://developer.mozilla.org复制而来。 如果有人提出了更好的脚本(没有过度设计),请在此处发布。 谢谢@Rudolfs Bundulis的所有帮助!