Update MSE procession on JS side

This commit is contained in:
Alexey Khit
2022-11-07 23:36:13 +03:00
parent 717af29630
commit 5c64d1f847
+48 -70
View File
@@ -25,97 +25,75 @@
<!-- 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 ws = new WebSocket(`ws${baseUrl.substr(4)}/api/ws${location.search}`); const video = document.querySelector('#video');
ws.binaryType = "arraybuffer";
let mediaSource; function init() {
let mediaSource, sourceBuffer, queueBuffer = [];
ws.onopen = () => { const ws = new WebSocket(`ws${baseUrl.substr(4)}/api/ws${location.search}`);
console.log("Start WS"); ws.binaryType = "arraybuffer";
// https://web.dev/i18n/en/fast-playback-with-preload/#manual_buffering ws.onopen = () => {
// 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 = () => { mediaSource.onsourceopen = null;
console.debug("mediaSource.onsourceopen"); URL.revokeObjectURL(video.src);
ws.send(JSON.stringify({"type": "mse"}));
mediaSource.onsourceopen = null; };
URL.revokeObjectURL(video.src);
ws.send(JSON.stringify({"type": "mse"}));
}; };
};
let sourceBuffer, queueBuffer = []; ws.onmessage = ev => {
if (typeof ev.data === 'string') {
const data = JSON.parse(ev.data);
console.debug("ws.onmessage", data);
ws.onmessage = ev => { if (data.type === "mse") {
if (typeof ev.data === 'string') { sourceBuffer = mediaSource.addSourceBuffer(data.value);
const data = JSON.parse(ev.data); sourceBuffer.mode = "segments"; // segments or sequence
console.debug("ws.onmessage", data); sourceBuffer.onupdateend = () => {
if (!sourceBuffer.updating && queueBuffer.length > 0) {
if (data.type === "mse") { try {
sourceBuffer = mediaSource.addSourceBuffer(data.value); sourceBuffer.appendBuffer(queueBuffer.shift());
// important: segments supports TrackFragDecodeTime } catch (e) {
// sequence supports only TrackFragRunEntry Duration // console.warn(e);
sourceBuffer.mode = "segments"; }
sourceBuffer.onupdateend = () => { }
if (!sourceBuffer.updating && queueBuffer.length > 0) {
sourceBuffer.appendBuffer(queueBuffer.shift());
} }
} }
} } else if (sourceBuffer.updating || queueBuffer.length > 0) {
} else { queueBuffer.push(ev.data);
if (sourceBuffer.updating) {
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);
} }
} }
} }
video.onpause = () => {
ws.close();
setTimeout(init, 0);
}
} }
let offsetTime = 1, noWaiting = 0; init();
setInterval(() => {
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 = () => {
const endTime = video.seekable.end(video.seekable.length - 1);
video.currentTime = endTime - offsetTime;
noWaiting = -1;
}
</script> </script>
</body> </body>
</html> </html>