【问题标题】:HTML video loop re-downloads video fileHTML 视频循环重新下载视频文件
【发布时间】:2019-10-27 06:41:21
【问题描述】:

我有一个相当大的 HTML5 视频。我也在使用 Chrome。 video 元素具有loop 属性,但每次视频“循环”时,浏览器都会重新下载视频文件。我设置了Cache-Control "max-age=15768000, private"。但是,这不会阻止对相同文件的任何额外下载。我正在使用 Amazon S3 来托管文件。此外,s3 服务器使用 Accepts Ranges 标头进行响应,这导致使用 206 http 响应代码请求文件的数百个部分下载。

这是我的视频标签:

<video autoplay="" loop="" class="asset current">
    <source src="https://mybucket.s3.us-east-2.amazonaws.com/myvideo.mp4">
</video>

更新:

似乎最好的解决方案是防止 Accept Ranges 标头与原始响应一起发送,而是使用 200 http 响应代码。如何做到这一点,以便视频通过.htaccess 文件完全缓存?

提前致谢。

【问题讨论】:

  • 视频有多大,多久循环一次?另一种处理方法是使用服务人员。
  • @Brad 这是 900mb 并且无限循环。
  • 你检查过浏览器的缓存大小吗?
  • 你怎么知道浏览器重新下载了文件?当您从本地源播放文件时(与 amazon s3 相反),您是否有同样的问题。您是在单个页面中播放文件还是它存在于 DOM 中?
  • 您是否尝试重新编码您的视频?您的视频的 webm 版本是否也会发生同样的情况?

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


【解决方案1】:

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

可能是 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】:

    Google chrome 对其文件捕获的大小有限制。在这种情况下,我之前的答案将不起作用。您应该使用file-compressor 之类的东西,此资源可能能够将文件压缩到足以使文件缓存符合条件的程度。网络浏览器可以手动设置新的缓存大小,但是如果最终用户没有指定他们的缓存以同意保存长视频所需的空间,则这是不可行的。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2015-01-20
        • 1970-01-01
        • 2016-06-04
        • 2012-09-01
        • 1970-01-01
        • 2011-01-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多