【问题标题】:Chrome: to play a video that is being downloaded via fetch/XHRChrome:播放正在通过 fetch/XHR 下载的视频
【发布时间】:2021-08-14 05:34:33
【问题描述】:

我想要实现的是让 Chrome 将视频文件作为数据加载(通过 Fetch API、XHR 等)并使用<video> 播放它,同时它仍在下载,而不发出两个单独的请求相同的 URL,无需等待文件完全下载。

从 Fetch API (response.body) 获取 ReadableStream 很容易,但我找不到将其输入 video 元素的方法。我发现我需要一个blob URL,可以使用MediaSource 对象创建。但是,SourceBuffer#appendStream 方法听起来正是我们所需要的,但它并没有在 Chrome 中实现,所以我无法将流直接连接到 MediaSource 对象。

我可能可以分块读取流,从中创建Uint8Arrays,然后使用SourceBuffer#appendBuffer,但这意味着除非块非常小,否则播放不会立即开始。此外,感觉就像手动做所有这些 API 应该能够开箱即用的事情。如果没有其他解决方案,而我走这条路,我应该注意什么?

是否有其他方法可以为ReadableStream 创建 blob URL?或者有没有办法让fetch<video> 共享请求?有这么多新的 API,我很容易错过一些东西。

【问题讨论】:

标签: javascript html5-video fetch-api media-source whatwg-streams-api


【解决方案1】:

经过几个小时的试验,找到了一个半途而废的解决方案:

const video = document.getElementById('audio');

const mediaSource = new MediaSource();

video.src = window.URL.createObjectURL(mediaSource);

mediaSource.addEventListener('sourceopen', async () => {

  const sourceBuffer = mediaSource.addSourceBuffer('audio/webm; codecs="opus"');

  const response = await fetch(audioSRC);

  const body = response.body

  const reader = body.getReader()

  let streamNotDone = true;

  while (streamNotDone) {

    const {value, done} = await reader.read();
    
    if (done) {streamNotDone = false; break;}
    
    await new Promise((resolve, reject) => {
      sourceBuffer.appendBuffer(value)

      sourceBuffer.onupdateend = (() => {
        resolve(true);
      })
    }) 

  }
});

它适用于https://developer.mozilla.org/en-US/docs/Web/API/MediaSource

此外,我仅使用 webm/opus 格式对此进行了测试,但我相信它应该也适用于其他格式只要您指定它

【讨论】:

  • @VC.one 因为它只适用于特定的编解码器。使用“MesiaSource.isTypeSupported()”
猜你喜欢
  • 2012-07-22
  • 1970-01-01
  • 2013-02-21
  • 1970-01-01
  • 2014-08-17
  • 2020-07-24
  • 1970-01-01
  • 1970-01-01
  • 2012-10-09
相关资源
最近更新 更多