Skip to content

enableWorker is webpack-only: default it off, make it opt-in - #5

Merged
ralyodio merged 1 commit into
mainfrom
fix-worker-webpack-only
Aug 30, 2026
Merged

enableWorker is webpack-only: default it off, make it opt-in#5
ralyodio merged 1 commit into
mainfrom
fix-worker-webpack-only

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

#4 turned the transmuxing worker on for everyone because media-streamer's live TV player sets it. media-streamer is Next.js. That is load-bearing, and it is the only reason it works there.

Why it breaks everywhere else

mpegts.js builds its worker by stringifying __webpack_modules__ — webpack's internal module registry — in utils/webworkify-webpack.js:

var sources = { main: __webpack_modules__ }
...
var blob = new self.Blob([src], { type: 'text/javascript' })
var worker = new self.Worker(URL.createObjectURL(blob))

A webpack host has that global. A host bundling with Bun, esbuild, Vite or Rollup does not, and the worker it assembles is broken.

Why it fails silently

Transmuxer does guard it — but only a synchronous throw reaches the catch:

if (config.enableWorker && typeof (Worker) !== 'undefined') {
    try { this._worker = work(require.resolve('./transmuxing-worker')); ... }
    catch (error) { /* fallback to inline transmuxing */ }
}

A Worker that constructs from a blob whose body then fails is asynchronous. Nothing throws, nothing falls back, no init segment ever arrives, and the player reports no error at all. Every stream simply does not play.

This is not hypothetical — it took tipoffwatch's player out in production (bundled by Bun; profullstack/tipoffwatch.com#16 reverts it there). Shipping it from here would have done the same to every consumer that is not Next.js.

The change

Default false; a host that knows it is webpack can pass enableWorker: true through MpegtsOptions. The capability is real where the bundler supports it — it just must never be the default.

Nothing else moves. The restart budget still refills on playing (the fix that stops streams dying after a minute or two), and the buffering profile is still media-streamer's on every screen.

Tests

92 pass, typecheck and prettier clean. The test that asserted the worker was on now asserts it is off and carries the whole reason, plus one that the webpack opt-in still works.

0.4.0 was never published, so this lands as 0.4.1 before anything consumes it.

🤖 Generated with Claude Code

https://claude.ai/code/session_01S5KxNHPQPY9Do9eWfJnGP4

The previous commit turned the transmuxing worker on for everyone because
media-streamer's live TV player sets it. media-streamer is Next.js. That is
load-bearing, and it is the only reason it works there.

mpegts.js builds its worker by STRINGIFYING `__webpack_modules__` --
webpack's internal module registry -- in `utils/webworkify-webpack.js`. A
webpack host has that global. A host bundling with Bun, esbuild, Vite or
Rollup does not, and the worker it assembles is broken.

It then fails in the worst available way. `Transmuxer` does wrap the setup in
a try/catch and fall back to inline transmuxing, but only a SYNCHRONOUS throw
reaches that catch. A Worker that constructs from a blob whose body then
fails is an asynchronous failure: nothing throws, nothing falls back, no init
segment ever arrives, and the player sits there having reported no error at
all. Every stream simply does not play.

This is not hypothetical -- it took tipoffwatch's player out in production,
which is bundled by Bun. Shipping it from here would have done the same to
every consumer that is not Next.js.

So the default is false and a host that knows it is webpack can pass
`enableWorker: true` through MpegtsOptions. The capability is real where the
bundler supports it; it just must never be the default.

Nothing else changes. The restart budget still refills on `playing`, which is
the fix that stops streams dying after a minute or two, and the buffering
profile is still media-streamer's on every screen.

92 tests pass, typecheck and prettier clean. 0.4.0 was never published, so
this lands as 0.4.1 before anything consumes it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S5KxNHPQPY9Do9eWfJnGP4
@ralyodio
ralyodio merged commit 6fbf4e0 into main Aug 30, 2026
1 check passed
@ralyodio
ralyodio deleted the fix-worker-webpack-only branch August 30, 2026 03:21
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.

1 participant