O loop de vídeo HTML baixa novamente o arquivo de vídeo

8

Eu tenho um vídeo HTML5 bastante grande. Eu também estou usando o Chrome. O elemento video possui o loopatributo, mas sempre que o vídeo "faz um loop", o navegador baixa novamente o arquivo de vídeo. Eu configurei Cache-Control "max-age=15768000, private". No entanto, isso não impede downloads extras do arquivo idêntico. Estou usando o Amazon S3 para hospedar o arquivo. Além disso, o servidor s3 responde com o Accepts Rangescabeçalho que faz com que as várias centenas de downloads parciais do arquivo sejam solicitados com o 206código de resposta http.

Aqui está a minha tag de vídeo:

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

ATUALIZAR:

Parece que a melhor solução é impedir que o Accept Rangescabeçalho seja enviado com a resposta original e, em vez disso, use um código de resposta http 200. Como isso pode ser alcançado para que o vídeo seja totalmente armazenado em cache por meio de um .htaccessarquivo?

Desde já, obrigado.

Cannon Moyer
fonte
1
Qual é o tamanho do vídeo e com que frequência ele será repetido? Outra maneira de lidar com isso é com um trabalhador de serviço.
Brad
@ Brad É 900mb e faz um loop infinito.
Cannon Moyer
Você verificou o tamanho do cache no navegador?
David Bradshaw
Como você sabia que o navegador fez o download novamente do arquivo? Você tem o mesmo problema ao reproduzir o arquivo de uma fonte local (em oposição ao amazon s3). Você está reproduzindo o arquivo em uma única página ou ele existe no DOM?
#
1
Você tentou reencodificar seu vídeo? O mesmo acontece com uma versão webm do seu vídeo?
Kaiido

Respostas:

1

Não sei ao certo qual é o verdadeiro problema que você está enfrentando.

Pode ser que o Chrome tenha um limite de tamanho máximo para o que eles armazenariam em cache e, se for o caso, não usar solicitações de intervalo não resolveria nada.

Uma outra explicação possível é que a mídia de cache não é realmente uma tarefa simples.
Sem ver seu arquivo, é difícil saber com certeza em qual caso você está, mas é necessário entender que, para reproduzir uma mídia, o navegador não precisa buscar o arquivo inteiro.
Por exemplo, você pode muito bem reproduzir um arquivo de vídeo em um elemento <audio>, uma vez que o fluxo de vídeo não será usado, um navegador pode muito bem omiti-lo completamente e baixar apenas o fluxo de áudio. Não tenho certeza se algum, mas eles poderiam. A maioria dos formatos de mídia separa fisicamente os fluxos de áudio e vídeo no arquivo e suas posições de bytes são marcadas nos metadados.
Eles certamente poderiam armazenar em cache as solicitações de intervalo que realizam, mas acho que ainda é bastante raro.

Mas, por mais tentador que seja, desabilitar solicitações de intervalo, você deve saber que alguns navegadores (Safari) não reproduzirão sua mídia se o servidor não permitir solicitações de intervalo.
Então, mesmo assim, provavelmente não é o que você deseja.


A primeira coisa que você pode tentar é otimizar seu vídeo para uso na web. Em vez de mp4, sirva um arquivo webm. Isso geralmente ocupa menos espaço com a mesma qualidade e talvez você evite a limitação de tamanho máximo .

Se o arquivo resultante ainda for muito grande, uma solução suja seria usar um MediaSource para que o arquivo seja mantido na memória e você precisará buscá-lo apenas uma vez.

No exemplo a seguir, o arquivo será buscado inteiramente apenas uma vez, por blocos de 1 MB, transmitidos pelo MediaSource conforme ele está sendo buscado e, em seguida, apenas os dados na memória serão usados ​​para executar repetições:

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>

Kaiido
fonte
0

O Google Chrome tem um limite para o tamanho da captura de arquivos. Nesse caso, minha resposta anterior não funcionaria. Você deve usar algo como compressor de arquivos. Esse recurso pode compactar o arquivo o suficiente para tornar o cache de arquivos elegível. O navegador da web pode ter um novo tamanho de cache definido manualmente, mas isso não é possível se o usuário final não tiver designado seu cache para concordar com o espaço necessário para armazenar o vídeo longo.

JTS
fonte