summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/app.js28
1 files changed, 23 insertions, 5 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/app.js b/packages/meshbay-hub/src/meshbay_hub/static/app.js
index 5a50010..3d87275 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/app.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/app.js
@@ -1481,6 +1481,7 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose }) {
const queueRef = useRef([]);
const appendingRef = useRef(false);
const endedRef = useRef(false);
+ const durationRef = useRef(0);
const flushQueue = useCallback(() => {
const sb = sbRef.current;
@@ -1510,25 +1511,34 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose }) {
return;
}
+ const onSeeking = () => {
+ const v = videoRef.current;
+ if (!v || !v.buffered.length) return;
+ const target = v.currentTime;
+ const end = v.buffered.end(v.buffered.length - 1);
+ const start = v.buffered.start(0);
+ if (target > end) v.currentTime = Math.max(end - 0.5, start);
+ else if (target < start) v.currentTime = start;
+ };
+
const startStream = async () => {
if (!gekRef.current && window.MeshBayCrypto) {
const gekB64 = await transport.fetchGEK();
gekRef.current = await window.MeshBayCrypto.importGEK(gekB64);
}
- let streamCodec = null;
-
transport.onStreamInit = (msg) => {
if (cancelled) return;
- streamCodec = msg.codec;
- const mime = `video/mp4; codecs="${streamCodec}"`;
+ const mime = `video/mp4; codecs="${msg.codec}"`;
if (!window.MediaSource || !MediaSource.isTypeSupported(mime)) {
- setError(t('video.err_mse', { codec: streamCodec }));
+ setError(t('video.err_mse', { codec: msg.codec }));
setPhase('error');
return;
}
+ durationRef.current = msg.duration || 0;
+
const ms = new MediaSource();
msRef.current = ms;
const url = URL.createObjectURL(ms);
@@ -1536,8 +1546,12 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose }) {
ms.addEventListener('sourceopen', () => {
if (cancelled) return;
+ if (durationRef.current > 0) {
+ ms.duration = durationRef.current;
+ }
const sb = ms.addSourceBuffer(mime);
sbRef.current = sb;
+ sb.mode = 'sequence';
sb.addEventListener('updateend', () => {
appendingRef.current = false;
flushQueue();
@@ -1548,6 +1562,7 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose }) {
if (videoRef.current) {
videoRef.current.src = url;
+ videoRef.current.addEventListener('seeking', onSeeking);
}
};
@@ -1578,6 +1593,9 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose }) {
return () => {
cancelled = true;
+ if (videoRef.current) {
+ videoRef.current.removeEventListener('seeking', onSeeking);
+ }
if (transport) {
transport.onStreamInit = null;
transport.onStreamData = null;