web-dev-qa-db-ja.com

HTMLビデオループがビデオファイルを再ダウンロード

かなり大きい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ファイルを介してビデオが完全にキャッシュされるようにするには、どうすればよいですか?

前もって感謝します。

8
Cannon Moyer

私があなたが直面している本当の問題が何であるかは確かではありません。

Chromeには、キャッシュする最大サイズの制限があります。その場合、範囲リクエストを使用しないと何も解決されません。

他の考えられる説明はキャッシングメディアは実際には単純なタスクではないということです。
ファイルを見なくても、どちらであるかを確実に判断することは困難ですが、メディアを再生するために、ブラウザがファイル全体をフェッチする必要がないことを理解する必要があります。
たとえば、ビデオストリームは使用されないため、ブラウザは<audio>要素でビデオファイルを非常にうまく再生できます。ブラウザはそれを完全に省略して、オーディオストリームのみをダウンロードできます。あるかどうかは不明ですが、可能です。ほとんどのメディア形式は、ファイル内のオーディオストリームとビデオストリームを物理的に分離し、それらのバイト位置はメタデータでマークされます。
彼らは確かに彼らが実行するRange-Requestsをキャッシュすることができますが、それが彼らが行うことはまだ非常にまれだと思います。

ただし、範囲要求を無効にするのが魅力的な場合があるため、サーバーが範囲要求を許可しない場合、一部のブラウザー(Safari)がメディアを再生しないことを知っておく必要があります。
それでも、それはおそらくあなたが望むものではありません。


あなたが試したいと思うかもしれない最初の事柄はウェブ使用のためにあなたのビデオを最適化することです。 mp4の代わりに、webmファイルを提供します。これらは通常、同じ品質で必要なスペースが少なくなり、最大サイズの制限を回避できるでしょう。

結果のファイルがまだ大きすぎる場合は、MediaSourceを使用してファイルをメモリに保持し、一度だけフェッチする必要があるという汚い解決策があります。

次の例では、ファイルは1 MBのチャンクによって完全に1回だけフェッチされ、フェッチされるときに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>
1
Kaiido

Google chromeはファイルキャッチのサイズに制限があります。この場合、私の以前の答えは機能しません。 file-compressor このようなリソースを使用する必要がありますファイルを十分に圧縮して、ファイルキャッシュを適格にすることができます。Webブラウザーは新しいキャッシュサイズを手動で設定できますが、エンドユーザーが長いビデオを保持するために必要なスペースに同意するようにキャッシュを指定していない場合、これは実行できません。 。

0
JTS