HTML视频循环重新下载视频文件

时间:2019-10-27 06:41:21

标签: javascript html google-chrome http amazon-s3

我有一个很大的HTML5视频。我也在使用Chrome。 video元素具有@ViewChildren(ModalDirective) cellTemplates: QueryList<ModalDirective>; cellTemplatesMap: any; ... ngAfterContentInit() { this.cellTemplatesMap = this.cellTemplates.reduce((acc, cur) => { acc[cur.name] = cur.template; return acc; }, {}); } 属性,但是每次视频“循环播放”时,浏览器都会重新下载视频文件。我设置了loop。但是,这不会阻止对相同文件的任何额外下载。我正在使用Amazon S3托管文件。 s3服务器还使用Cache-Control "max-age=15768000, private"标头进行响应,这将导致使用Accepts Ranges http响应代码来请求文件的数百次部分下载。

这是我的视频标签:

206

更新:

看来,最好的解决方案是阻止<video autoplay="" loop="" class="asset current"> <source src="https://mybucket.s3.us-east-2.amazonaws.com/myvideo.mp4"> </video> 标头与原始响应一起发送,而应使用200 http响应代码。如何做到这一点,以便通过Accept Ranges文件完全缓存视频?

先谢谢了。

3 个答案:

答案 0 :(得分:0)

Google chrome对文件捕获的大小有限制。在这种情况下,我先前的答案将无效。您应该使用类似file-compressor的名称,该资源可能能够充分压缩文件,从而使文件缓存符合条件。网络浏览器可以手动设置新的缓存大小,但是如果最终用户未指定其缓存与容纳长视频所需的空间一致,则此操作不可行。

答案 1 :(得分:0)

我不确定您面临的真正问题是什么。

Chrome可能会对其缓存的内容设置最大大小限制,如果是这种情况,那么不使用Range-Requests不会解决任何问题。

另一个可能的解释是,缓存媒体并不是一个简单的任务。
在没有看到文件的情况下,很难确定是哪种情况,但是您必须了解,要播放媒体,浏览器不需要提取整个文件。
例如,您可以很好地在

但是很可能会禁用Range-Requests,所以您必须知道,如果服务器不允许Range-Requests,某些浏览器(Safari)将无法播放媒体。
因此,即使那样,它也可能不是您想要的。


您可能要尝试的第一件事是针对网络使用情况优化视频。代替mp4,提供一个webm文件。对于相同的质量,这些通常会占用较少的空间,并且也许您会避免最大尺寸限制

如果生成的文件仍然太大,那么肮脏的解决方案是使用MediaSource,以便将文件保留在内存中,并且只需要提取一次即可。

在下面的示例中,该文件将仅以1MB的块的大小被完全提取一次,并在提取时由MediaSource流式传输,然后仅将内存中的数据用于循环播放:

document.getElementById('streamVid').onclick = e => (async () => {

const url = 'https://upload.wikimedia.org/wikipedia/commons/transcoded/2/22/Volcano_Lava_Sample.webm/Volcano_Lava_Sample.webm.360p.webm';
// you must know the mimeType of your video before hand.
const type = 'video/webm; codecs="vp8, vorbis"';
if( !MediaSource.isTypeSupported( type ) ) {
  throw 'Unsupported';
}

const source = new MediaSource();
source.addEventListener('sourceopen', sourceOpen);
document.getElementById('out').src = URL.createObjectURL( source );

// async generator Range-Fetcher
async function* fetchRanges( url, chunk_size = 1024 * 1024 ) {
  let chunk = new ArrayBuffer(1);
  let cursor = 0;
  while( chunk.byteLength ) {
    const resp = await fetch( url, {
      method: "get",
        headers: { "Range": "bytes=" + cursor + "-" + ( cursor += chunk_size ) }
      }
    )
    chunk = resp.ok && await resp.arrayBuffer();
    cursor++; // add one byte for next iteration, Ranges are inclusive
    yield chunk;
  }
}
// set up our MediaSource
async function sourceOpen() {
  const buffer = source.addSourceBuffer( type );
//  buffer.mode = "sequence";
  // waiting forward to appendAsync...
  const appendBuffer = ( chunk ) => {
    return new Promise( resolve => {
      buffer.addEventListener( 'update', resolve, { once: true } );
      buffer.appendBuffer( chunk );
    } );
  }
  // while our RangeFetcher is running
  for await ( const chunk of fetchRanges(url) ) {
    if( chunk ) { // append to our MediaSource
      await appendBuffer( chunk );
    }
    else { // when done
      source.endOfStream();
    }
  }
}
})().catch( console.error );
<button id="streamVid">stream video</button>
<video id="out" controls muted autoplay loop></video>

答案 2 :(得分:0)

来到这里的人面临的一种可能性 - 开发工具在网络选项卡下有一个“禁用缓存”选项。启用后(意味着缓存被禁用)浏览器可能不会缓存视频,因此需要再次下载它们。 disable cache from network tab