Chrome: для воспроизведения видео, которое загружается через fetch/XHR
Я пытаюсь добиться, чтобы Chrome загружал видеофайл в виде данных (через Fetch API, XHR и т. Д.) И воспроизводил его, используя <video>
пока он все еще загружается, не отправляя два отдельных запроса на один и тот же URL и не дожидаясь полной загрузки файла.
Это легко получить ReadableStream
из Fetch API (response.body
), но я не могу найти способ кормить его в video
элемент. Я понял, мне нужно blob
URL для этого, который может быть создан с помощью MediaSource
объект. Тем не менее SourceBuffer#appendStream
метод, который звучит как то, что нужно, не реализован в Chrome, поэтому я не могу подключить поток напрямую к MediaSource
объект.
Я, вероятно, могу прочитать поток в кусках, создать Uint8Array
из них, и использовать SourceBuffer#appendBuffer
, но это означает, что воспроизведение не начнется немедленно, если только размер чанка не очень мал. Кроме того, создается ощущение, что вы вручную делаете что-то, что все эти API должны иметь в наличии из коробки. Если нет других решений, и я иду по этому пути, каких предостережений я должен ожидать?
Существуют ли другие способы создания URL-адреса BLOB-объекта для ReadableStream
? Или есть способ сделать fetch
а также <video>
подать заявку? Есть так много новых API, что я мог легко что-то пропустить.
2 ответа
После часов экспериментов нашел наполовину рабочее решение:
const video = document.getElementById('audio');
const mediaSource = new MediaSource();
video.src = window.URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', async () => {
const sourceBuffer = mediaSource.addSourceBuffer('audio/webm; codecs="opus"');
const response = await fetch(audioSRC);
const body = response.body
const reader = body.getReader()
let streamNotDone = true;
while (streamNotDone) {
const {value, done} = await reader.read();
if (done) {streamNotDone = false; break;}
await new Promise((resolve, reject) => {
sourceBuffer.appendBuffer(value)
sourceBuffer.onupdateend = (() => {
resolve(true);
})
})
}
});
Он работает с https://developer.mozilla.org/en-US/docs/Web/API/MediaSource.
Кроме того, я тестировал это только с форматом webm / opus, но я считаю, что он должен работать с другими форматами, если вы его укажете .
Попробуй это:
(async function(){
const res = await fetch('http://xxxx.mp4')
const blob = await res.blob()
const src = window.URL.createObjectURL(blob)
const el = document.getElementById('video')
el.src = src
el.play()
})()