URL.createObjectURL(mediaSource) - 播放来自 URL 的视频 - MOOV atom - Elastic Transcoder

URL.createObjectURL(mediaSource) - play back video from URL - MOOV atom - Elastic Transcoder

我正在尝试通过创建 blob URL.

来播放视频(目前托管在 S3 上,具有 public 访问权限)

我使用 Elastic Transcoder 对视频进行编码,因为它应该将 MOOV atom 设置到顶部(开始)。

我无法让代码工作,但也找到了一个工作示例: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.e MP4Box 或 QT-FastStart,但它们似乎有点老套。我也愿意从 MP4 更改为 M3U8 播放列表,但我不知道要使用什么 MIME 类型。

当天晚上,我正在尝试回放 video/stream 并隐藏可能使用 blob 的 URL(来源)。

谢谢大家!

所以,首先,尽管这段代码似乎取自 mozilla documentation site, there are a few issues - you are not checking the readyState before calling endOfStream thus the error you get is valid, secondly, the play() call is blocked by the 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 格式不兼容:

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

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

好的,所以我通过使用 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(忽略输入视频的任何纵横比)

但是,根据原 post 的评论,我相信可能有更有效的方法来生成 blob url 并摄取到视频标签中。此示例直接从 https://developer.mozilla.org 复制而来。 如果有人提出更好的脚本(不是过度设计),请在此处 post。 感谢@Rudolfs Bundulis 的所有帮助!