Можно ли дождаться полной загрузки

У меня есть видеофайл (пример, 25 МиБ) — я заранее знаю, что он небольшой и поместится в кэш, но для усложения задачи предположим, что его длительность заранее не известна (другой пример, тоже 25 МиБ). Я хочу дождаться его полной загрузки и только после этого начать воспроизведение, чтобы гарантированно ничего не лагало, например.

К своему большому удивлению я обнаружил, что у тега <video> отсутствует событие load. Есть события progress, loadeddata и canplaythrough, но что с ними делать — непонятно. Мне попадались попытки посчитать окончание загрузки по сравнению длительности, но, во-первых, в надёжности этого метода есть сомнения, а во-вторых, это не сработает, если длительность в принципе неизвестна.

В связи с этим у меня возникают вопросы:

  • будет ли браузер в принципе загружать видеофайл до конца, или он его всего лишь немного забуферизует?
  • если будет, то можно ли отловить момент завершения загрузки?
  • если не будет, то можно ли отловить момент, когда браузер перестал совершать дальнейшую загрузку? (UPD: нашёл событие suspend, но вопрос про полную загрузку ещё актуален)

Ниже в два одинаковых сниппета с разными видеофайлами для поиграться.

const video = document.getElementById("video");
video.onload = () => console.log("onload не срабатывает");
video.onprogress = (event) => {
  console.log(`progress ${event.timeStamp}, duration: ${video.duration}`);
};
video.onloadeddata = () => console.log("loadeddata");
video.oncanplaythrough = () => console.log("canplaythrough");
video.onsuspend = () => console.log("suspend");
<video
  id="video"
  src="https://andreymal.org/files/bbb-test/bbb-with-duration.mp4"
  controls
  preload="auto"
  style="margin-bottom: 100vh">
</video>

const video = document.getElementById("video");
video.onload = () => console.log("onload не срабатывает");
video.onprogress = (event) => {
  console.log(`progress ${event.timeStamp}, duration: ${video.duration}`);
};
video.onloadeddata = () => console.log("loadeddata");
video.oncanplaythrough = () => console.log("canplaythrough");
video.onsuspend = () => console.log("suspend");
<video
  id="video"
  src="https://andreymal.org/files/bbb-test/bbb-without-duration.mp4"
  controls
  preload="auto"
  style="margin-bottom: 100vh">
</video>


Ответы (1 шт):

Автор решения: Qwertiy
  1. Нет, браузер грузит кусок файла и останавливает загрузку.
  2. Можно попробовать загрузить файл самостоятельно через fetch.
  3. Из скачанных через fetch данных можно создать ссылку - тогда уж точно все данные будут и не потребуется полагаться на кэширование.

fetch("//andreymal.org/files/bbb-test/bbb-with-duration.mp4")
  .then(resp => resp.blob())
  .then(blob => {
    var video = document.querySelector('video')
    video.src = URL.createObjectURL(blob)
    video.hidden = false
    video.play()
  })
video { display: block; max-height: calc(100vh - 16px); margin: auto; }
<video controls hidden muted>

→ Ссылка