aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-17 14:36:25 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-17 14:36:25 +0200
commit4134729543139f4934c4ec4e4c6a2cda0606bcdf (patch)
tree515480b5e4da5e1f5ba89eb36d90d6090c3f5271 /packages/meshbay-hub/src/meshbay_hub/static
parentc91082b173a61d93a71f9be2696db3684dbfe05e (diff)
downloadmeshbay-4134729543139f4934c4ec4e4c6a2cda0606bcdf.tar.gz
fix(hub): trace the subtitle path end to end in the player
A subtitle button that spins for ever and never shows a track could not be told apart from a node that answered, a blob that never arrived, or a track attached with no cues in it: the whole path was silent. Every step of it happens on someone else's machine, over a link, against a file that may be gigabytes, so the only question worth asking when it does not finish is which step did not — and nothing recorded that. It now logs the request, the node's answer with hash, size and elapsed time, the fetched blob and its chunk count, the attachment, and the live TextTrack's mode and cue count. A failure says how long it took before failing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UGY17EPph5LsLzePPXhUVc
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/video-player.js26
1 files changed, 24 insertions, 2 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/video-player.js b/packages/meshbay-hub/src/meshbay_hub/static/video-player.js
index a150512..596a848 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/video-player.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/video-player.js
@@ -1100,21 +1100,39 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose, onDownload }) {
if (!transport) return;
setSubtitleTrack(track.i);
setSubtitleBusy(true);
+ // Traced end to end on purpose. Every step here happens on someone else's
+ // machine, over a link, against a file that may be gigabytes: when this
+ // does not finish, the only question worth asking is *which* step did not,
+ // and no other record of that exists.
+ const t0 = performance.now();
+ console.log('[MeshBay] subtitle: asking for track', track.i, 'of', entry.id.slice(0, 12));
try {
const info = await transport.requestSubtitle(entry.id, track.i);
+ console.log('[MeshBay] subtitle: node answered in',
+ Math.round(performance.now() - t0), 'ms —',
+ 'hash=', String(info.hash).slice(0, 12), 'size=', info.size,
+ 'mime=', info.mime);
const chunks = await pipelinedDownload(
transport, gekRef.current, info.hash, Math.ceil(info.size / CHUNK_SIZE));
+ console.log('[MeshBay] subtitle: blob fetched in',
+ Math.round(performance.now() - t0), 'ms —',
+ chunks.length, 'chunk(s)');
const url = URL.createObjectURL(
new Blob(chunks, { type: info.mime || 'text/vtt' }));
// Someone changed their mind while this was in flight. Dropping the blob
// rather than installing it is the whole point of the generation: the
// reply that arrives last is not the choice that was made last.
- if (subtitleGenRef.current !== gen) { URL.revokeObjectURL(url); return; }
+ if (subtitleGenRef.current !== gen) {
+ console.log('[MeshBay] subtitle: superseded, blob dropped');
+ URL.revokeObjectURL(url); return;
+ }
subtitleUrlRef.current = url;
setSubtitleUrl(url);
+ console.log('[MeshBay] subtitle: track attached');
} catch (err) {
if (subtitleGenRef.current !== gen) return;
- console.warn('[MeshBay] subtitle track', track.i, 'failed:', err);
+ console.warn('[MeshBay] subtitle track', track.i, 'failed after',
+ Math.round(performance.now() - t0), 'ms:', err);
setSubtitleTrack(null);
setSubtitleError(true);
} finally {
@@ -1137,6 +1155,10 @@ function VideoPlayer({ entry, transportRef, gekRef, onClose, onDownload }) {
for (let i = 0; i < v.textTracks.length; i++) {
v.textTracks[i].mode = subtitleUrl ? 'showing' : 'disabled';
}
+ console.log('[MeshBay] subtitle: textTracks =', v.textTracks.length,
+ 'mode =', v.textTracks[0] && v.textTracks[0].mode,
+ 'cues =', v.textTracks[0] && v.textTracks[0].cues
+ ? v.textTracks[0].cues.length : 'none');
}, [subtitleUrl]);
useEffect(() => {