Created
May 26, 2024 15:28
-
-
Save alpgul/1a19c5db2a1020e5dc5023826b617535 to your computer and use it in GitHub Desktop.
MediaSource Demo
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>MediaSource Demo</title> | |
</head> | |
<body> | |
<script> | |
const video = document.createElement("video"); | |
document.body.append(video); | |
video.autoplay = true; | |
video.controls = true; | |
async function loadMediaSourceChunks( | |
url, | |
downloadChunkSize, | |
downloadTimeout | |
) { | |
try { | |
const mediaSource = new MediaSource(); | |
const blob = URL.createObjectURL(mediaSource); | |
video.src = blob; | |
mediaSource.addEventListener( | |
"sourceopen", | |
() => { | |
URL.revokeObjectURL(video.src); | |
fetchChunk(mediaSource, url, downloadChunkSize, downloadTimeout); | |
}, | |
{ once: true } | |
); | |
} catch (error) { | |
console.error("Error:", error); | |
} | |
} | |
async function fetchChunk(mediaSource, url, chunkSize) { | |
let start = 0; | |
let response = await fetch(url, { | |
headers: { Range: `bytes=${start}-${start + chunkSize - 1}` }, | |
}); | |
let length = parseInt(response.headers.get("Content-Length")); | |
let [range, size] = (response.headers.get("Content-Range") || "") | |
.replace(/bytes\s*/, "") | |
.split("/"); | |
let cursor = parseInt(range.split("-").pop()); | |
let sourceBuffer = mediaSource.addSourceBuffer( | |
response.headers.get("Content-Type") + | |
'; codecs="avc1.42E01E, mp4a.40.2"' | |
); | |
let end = size ? parseInt(size) : length; | |
start = cursor ? cursor + 1 : start + length + 1; | |
arrayBuffer = await response.arrayBuffer(); | |
sourceBuffer.addEventListener( | |
"updateend", | |
() => { | |
if ( | |
start >= end - 1 && | |
!sourceBuffer.updating && | |
mediaSource.readyState === "open" | |
) { | |
mediaSource.endOfStream(); | |
} | |
video.play(); | |
}, | |
{ once: true } | |
); | |
sourceBuffer.appendBuffer(arrayBuffer); | |
while (start < end) { | |
response = await fetch(url, { | |
headers: { Range: `bytes=${start}-${start + chunkSize - 1}` }, | |
}); | |
let length = parseInt(response.headers.get("Content-Length")); | |
let [range, size] = (response.headers.get("Content-Range") || "") | |
.replace(/bytes\s*/, "") | |
.split("/"); | |
let cursor = parseInt(range.split("-").pop()); | |
start = cursor ? cursor + 1 : start + length + 1; | |
arrayBuffer = await response.arrayBuffer(); | |
sourceBuffer = mediaSource.sourceBuffers[0]; | |
sourceBuffer.addEventListener( | |
"updateend", | |
() => { | |
if ( | |
start >= end - 1 && | |
!sourceBuffer.updating && | |
mediaSource.readyState === "open" | |
) { | |
mediaSource.endOfStream(); | |
} | |
}, | |
{ once: true } | |
); | |
sourceBuffer.appendBuffer(arrayBuffer); | |
} | |
} | |
loadMediaSourceChunks("./video.mp4", 100000);//https://github.com/mdn/dom-examples/blob/main/sourcebuffer/frag_bunny.mp4 | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment