100 lines
3.0 KiB
HTML
100 lines
3.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>go2rtc - MSE</title>
|
|
<style>
|
|
body {
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
|
|
html, body {
|
|
height: 100%;
|
|
width: 100%;
|
|
}
|
|
|
|
#video {
|
|
width: 100%;
|
|
height: 100%;
|
|
background: black;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<!-- muted is important for autoplay -->
|
|
<video id="video" autoplay controls playsinline muted></video>
|
|
<script>
|
|
// support api_path
|
|
const baseUrl = location.origin + location.pathname.substr(
|
|
0, location.pathname.lastIndexOf("/")
|
|
);
|
|
const video = document.querySelector('#video');
|
|
|
|
function init() {
|
|
let mediaSource, sourceBuffer, queueBuffer = [];
|
|
|
|
const ws = new WebSocket(`ws${baseUrl.substr(4)}/api/ws${location.search}`);
|
|
ws.binaryType = "arraybuffer";
|
|
|
|
ws.onopen = () => {
|
|
mediaSource = new MediaSource();
|
|
video.src = URL.createObjectURL(mediaSource);
|
|
mediaSource.onsourceopen = () => {
|
|
mediaSource.onsourceopen = null;
|
|
URL.revokeObjectURL(video.src);
|
|
ws.send(JSON.stringify({"type": "mse"}));
|
|
};
|
|
};
|
|
|
|
ws.onmessage = ev => {
|
|
if (typeof ev.data === 'string') {
|
|
const data = JSON.parse(ev.data);
|
|
console.debug("ws.onmessage", data);
|
|
|
|
if (data.type === "mse") {
|
|
sourceBuffer = mediaSource.addSourceBuffer(data.value);
|
|
sourceBuffer.mode = "segments"; // segments or sequence
|
|
sourceBuffer.onupdateend = () => {
|
|
if (!sourceBuffer.updating && queueBuffer.length > 0) {
|
|
try {
|
|
sourceBuffer.appendBuffer(queueBuffer.shift());
|
|
} catch (e) {
|
|
// console.warn(e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else if (sourceBuffer.updating || queueBuffer.length > 0) {
|
|
queueBuffer.push(ev.data);
|
|
} else {
|
|
try {
|
|
sourceBuffer.appendBuffer(ev.data);
|
|
} catch (e) {
|
|
// console.warn(e);
|
|
}
|
|
}
|
|
|
|
if (video.seekable.length > 0) {
|
|
const delay = video.seekable.end(video.seekable.length - 1) - video.currentTime;
|
|
if (delay < 1) {
|
|
video.playbackRate = 1;
|
|
} else if (delay > 10) {
|
|
video.playbackRate = 10;
|
|
} else if (delay > 2) {
|
|
video.playbackRate = Math.floor(delay);
|
|
}
|
|
}
|
|
}
|
|
|
|
video.onpause = () => {
|
|
ws.close();
|
|
setTimeout(init, 0);
|
|
}
|
|
}
|
|
|
|
init();
|
|
</script>
|
|
</body>
|
|
</html>
|