Skip to content

Instantly share code, notes, and snippets.

@andremichelle
Last active November 10, 2023 04:30
Show Gist options
  • Save andremichelle/91b4180c10a4f86928fb32fab6b34687 to your computer and use it in GitHub Desktop.
Save andremichelle/91b4180c10a4f86928fb32fab6b34687 to your computer and use it in GitHub Desktop.
This code enables efficient looping of WebM videos by streaming and caching them in memory. It prevents the browser from repeatedly streaming the video when the loop property triggers a restart, ensuring a smooth and resource-friendly playback experience.
// Tested on all major browsers (Macbook Pro), Fails on IOS (https://caniuse.com/?search=MediaSource)
export const streamAndCacheMediaSource = (videoElement: HTMLVideoElement, url: string): void => {
const MimeCodec = "video/webm; codecs=\"vp9\""
if (!MediaSource.isTypeSupported(MimeCodec)) {throw new Error(`${MimeCodec} is not supported`)}
const mediaSource = new MediaSource()
mediaSource.addEventListener("sourceopen", async () => {
if (mediaSource.readyState !== "open") {throw new Error("readyState not open")}
const sourceBuffer = mediaSource.addSourceBuffer(MimeCodec)
sourceBuffer.mode = "sequence"
sourceBuffer.addEventListener("error", () => {throw new Error("Unknown error. Check 'chrome://media-internals/'")})
fetch(url).then(async (response: Response) => {
const reader = response.body!.getReader()
while (true) {
const result = await reader.read()
if (result.done) {
mediaSource.endOfStream()
break
} else {
await new Promise<void>((resolve) => {
sourceBuffer.appendBuffer(result.value)
sourceBuffer.addEventListener("update", () => resolve(), { once: true })
})
}
}
})
})
videoElement.src = URL.createObjectURL(mediaSource)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment