Chrome:播放正在通过fetch/XHR下载的视频

Chrome: to play a video that is being downloaded via fetch/XHR

本文关键字:fetch XHR 下载 的视频 播放 Chrome      更新时间:2023-09-26

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

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

我可能会读取流块,从中创建Uint8Array s,并使用SourceBuffer#appendBuffer,但这意味着播放不会立即开始,除非块大小真的很小。而且感觉就像手工做一些所有这些api都应该能够开箱即用的事情。如果没有其他的解决方案,我走这条路,我应该期待什么警告?

是否可能有其他方法来创建一个blob URL的ReadableStream ?或者是否有办法使fetch<video>共享一个请求?有那么多新的api,我很容易错过一些。

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

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格式,但我相信它应该也适用于其他格式,只要你指定它