Skip to content

Fix remote/HLS transcription: player keeps the previous media, export references the stale source - #431

Merged
maboa merged 2 commits into
mainfrom
fix/remote-hls-player-and-export-media-ref
Jul 28, 2026
Merged

Fix remote/HLS transcription: player keeps the previous media, export references the stale source#431
maboa merged 2 commits into
mainfrom
fix/remote-hls-player-and-export-media-ref

Conversation

@maboa

@maboa maboa commented Jul 28, 2026

Copy link
Copy Markdown
Member

Fixes #430.

Problem

Transcribing a remote/HLS URL (e.g. a stream.place playlist) left the previous media in the player, and the interactive-transcript export then linked that stale source in its "Media file or URL" field.

Root causes

  1. hls.js never loaded on servers that serve .mjs with an empty/incorrect MIME type. Browsers reject module scripts unless served as JavaScript, so import('hls.js') threw, the attach silently catch-swallowed it, and the HLS player stayed blank. (Transcription still worked — it uses a separate byte-range path, not the player.)
  2. attachMediaPlayback never cleared a plain-URL src left by earlier media; hls.js won't reliably override an existing src, so the old media remained.

Fix

  • Rename js/vendor/hls-1.6.16.mjs.js (content unchanged): .js is served as JavaScript everywhere and import() still parses it as a module. Update the importmap + service-worker precache; add a unit guard that no vendored module is served as .mjs.
  • Clear the source (removeAttribute('src') + load()) before (re)attaching, and surface fatal hls.js errors instead of swallowing them.
  • Record the real media reference on #hyperplayer.dataset.mediaRef (filename for a local file; original URL for remote/HLS — HLS turns player.src into an opaque blob: MediaSource URL). guessMediaSrc prefers an http(s) src (fresh remote URL wins) else the stamped ref; the export dialog refreshes the field on every open; storage clears the ref on Recents load.

Tests

  • e2e: local filename, plain remote URL replacing a stale source, HLS (blob src → original URL in the export), fresh-URL-beats-stale-ref, refresh-on-open, import-input safety.
  • unit: guard that the importmap / service worker / js/vendor/ reference no .mjs.

Verified in-browser: the HLS video now loads and plays, and the export references the playlist URL. Cache-busts for the three changed scripts → 0.8.10.

maboa added 2 commits July 28, 2026 22:54
…reference it correctly on export (#430)

Transcribing a remote/HLS URL left the PREVIOUS media in the player, and the
interactive-transcript export then linked that stale source. Two root causes:

1. hls.js never loaded on servers that serve .mjs with an empty/incorrect MIME
   type. Browsers reject module scripts unless served as JavaScript, so
   import('hls.js') threw, the attach silently caught it, and the HLS player
   stayed blank (transcription still worked — it uses a separate byte-range path).
   Rename js/vendor/hls-1.6.16.mjs -> .js (content unchanged): .js is served as
   JavaScript everywhere and import() still parses it as a module. Update the
   importmap and service-worker precache to match, and add a unit guard that no
   vendored module is served as .mjs.

2. attachMediaPlayback tore down a prior hls.js instance but not a plain-URL src
   left by earlier media; hls.js won't reliably override an existing src, so the
   old media remained. Clear the source (removeAttribute('src') + load()) before
   (re)attaching. Also surface fatal hls.js errors instead of swallowing them.

For the export dialog, record the real media reference on #hyperplayer.dataset.
mediaRef (the filename for a local file via the central capture, the original URL
for remote/HLS via attachMediaPlayback — HLS turns player.src into an opaque
blob: MediaSource URL). guessMediaSrc now prefers an http(s) src (so a fresh
remote URL wins) and otherwise uses the stamped ref; the dialog refreshes the
field on every open; storage clears the ref on Recents load.

Tests: e2e for local filename, plain remote URL replacing a stale source, HLS
(blob src -> original URL in the export), fresh-URL-beats-stale-ref, and
refresh-on-open; a unit guard against .mjs vendored modules. Cache-bust the three
changed scripts to 0.8.10.
…with a clearer message (#430)

A cross-origin media URL that plays fine in the <video> element can still be
unreadable to fetch() when the host sends no CORS headers — playback is CORS-exempt
but transcription must read the raw bytes. The old error ("network / CORS error")
lumped this together with a genuinely unreachable host and read as an app bug.

classifyMediaUrl now, when fetch() rejects without a status, probes with a no-cors
HEAD: if the server responds (opaquely) the failure is CORS, so it says so and
suggests downloading the file or enabling CORS on the host; otherwise it reports a
plain network error. An HTTP error status is surfaced as-is.

Adds unit tests for the three paths (CORS-blocked, unreachable, HTTP error) and
bumps the file's @Version to 0.8.10.
@maboa
maboa merged commit ec1a6cd into main Jul 28, 2026
1 check passed
@maboa
maboa deleted the fix/remote-hls-player-and-export-media-ref branch July 28, 2026 21:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remote/HLS transcription: player keeps the previous media, and the interactive-transcript export references the stale source

1 participant