Update MSE procession on JS side
This commit is contained in:
+27
-49
@@ -25,35 +25,28 @@
|
|||||||
<!-- muted is important for autoplay -->
|
<!-- muted is important for autoplay -->
|
||||||
<video id="video" autoplay controls playsinline muted></video>
|
<video id="video" autoplay controls playsinline muted></video>
|
||||||
<script>
|
<script>
|
||||||
const video = document.querySelector('#video');
|
|
||||||
|
|
||||||
// support api_path
|
// support api_path
|
||||||
const baseUrl = location.origin + location.pathname.substr(
|
const baseUrl = location.origin + location.pathname.substr(
|
||||||
0, location.pathname.lastIndexOf("/")
|
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}`);
|
const ws = new WebSocket(`ws${baseUrl.substr(4)}/api/ws${location.search}`);
|
||||||
ws.binaryType = "arraybuffer";
|
ws.binaryType = "arraybuffer";
|
||||||
|
|
||||||
let mediaSource;
|
|
||||||
|
|
||||||
ws.onopen = () => {
|
ws.onopen = () => {
|
||||||
console.log("Start WS");
|
|
||||||
|
|
||||||
// https://web.dev/i18n/en/fast-playback-with-preload/#manual_buffering
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/API/Media_Source_Extensions_API
|
|
||||||
mediaSource = new MediaSource();
|
mediaSource = new MediaSource();
|
||||||
video.src = URL.createObjectURL(mediaSource);
|
video.src = URL.createObjectURL(mediaSource);
|
||||||
mediaSource.onsourceopen = () => {
|
mediaSource.onsourceopen = () => {
|
||||||
console.debug("mediaSource.onsourceopen");
|
|
||||||
|
|
||||||
mediaSource.onsourceopen = null;
|
mediaSource.onsourceopen = null;
|
||||||
URL.revokeObjectURL(video.src);
|
URL.revokeObjectURL(video.src);
|
||||||
ws.send(JSON.stringify({"type": "mse"}));
|
ws.send(JSON.stringify({"type": "mse"}));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
let sourceBuffer, queueBuffer = [];
|
|
||||||
|
|
||||||
ws.onmessage = ev => {
|
ws.onmessage = ev => {
|
||||||
if (typeof ev.data === 'string') {
|
if (typeof ev.data === 'string') {
|
||||||
const data = JSON.parse(ev.data);
|
const data = JSON.parse(ev.data);
|
||||||
@@ -61,61 +54,46 @@
|
|||||||
|
|
||||||
if (data.type === "mse") {
|
if (data.type === "mse") {
|
||||||
sourceBuffer = mediaSource.addSourceBuffer(data.value);
|
sourceBuffer = mediaSource.addSourceBuffer(data.value);
|
||||||
// important: segments supports TrackFragDecodeTime
|
sourceBuffer.mode = "segments"; // segments or sequence
|
||||||
// sequence supports only TrackFragRunEntry Duration
|
|
||||||
sourceBuffer.mode = "segments";
|
|
||||||
sourceBuffer.onupdateend = () => {
|
sourceBuffer.onupdateend = () => {
|
||||||
if (!sourceBuffer.updating && queueBuffer.length > 0) {
|
if (!sourceBuffer.updating && queueBuffer.length > 0) {
|
||||||
|
try {
|
||||||
sourceBuffer.appendBuffer(queueBuffer.shift());
|
sourceBuffer.appendBuffer(queueBuffer.shift());
|
||||||
|
} catch (e) {
|
||||||
|
// console.warn(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
if (sourceBuffer.updating) {
|
} else if (sourceBuffer.updating || queueBuffer.length > 0) {
|
||||||
queueBuffer.push(ev.data)
|
queueBuffer.push(ev.data);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
sourceBuffer.appendBuffer(ev.data);
|
sourceBuffer.appendBuffer(ev.data);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let offsetTime = 1, noWaiting = 0;
|
video.onpause = () => {
|
||||||
|
ws.close();
|
||||||
setInterval(() => {
|
setTimeout(init, 0);
|
||||||
if (video.paused || video.seekable.length === 0) return;
|
|
||||||
|
|
||||||
if (noWaiting < 0) {
|
|
||||||
offsetTime = Math.min(offsetTime * 1.1, 5);
|
|
||||||
console.debug("offset time up:", offsetTime);
|
|
||||||
} else if (noWaiting >= 30) {
|
|
||||||
noWaiting = 0;
|
|
||||||
offsetTime = Math.max(offsetTime * 0.9, 0.5);
|
|
||||||
console.debug("offset time down:", offsetTime);
|
|
||||||
}
|
}
|
||||||
noWaiting += 1;
|
|
||||||
|
|
||||||
const endTime = video.seekable.end(video.seekable.length - 1);
|
|
||||||
let playbackRate = (endTime - video.currentTime) / offsetTime;
|
|
||||||
if (playbackRate < 0.1) {
|
|
||||||
// video.currentTime = endTime - offsetTime;
|
|
||||||
playbackRate = 0.1;
|
|
||||||
} else if (playbackRate > 10) {
|
|
||||||
// video.currentTime = endTime - offsetTime;
|
|
||||||
playbackRate = 10;
|
|
||||||
}
|
}
|
||||||
// https://github.com/GoogleChrome/developer.chrome.com/issues/135
|
|
||||||
video.playbackRate = playbackRate;
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
video.onwaiting = () => {
|
init();
|
||||||
const endTime = video.seekable.end(video.seekable.length - 1);
|
|
||||||
video.currentTime = endTime - offsetTime;
|
|
||||||
noWaiting = -1;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user