Skip to content

feat: attachSource, the delivery layer without the control bar - #1

Merged
ralyodio merged 1 commit into
mainfrom
attach-source
Aug 29, 2026
Merged

feat: attachSource, the delivery layer without the control bar#1
ralyodio merged 1 commit into
mainfrom
attach-source

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Adopting this package across the other sites turned up something worth acting on: three of the five already have a player, and none of them is thin.

repo what's there wholesale swap?
genrewatch / tipoffwatch player-entry.js, mpegts, live IPTV good fit
media-streamer 3 modals (761 + 451 + 412 lines), video.js + its own hls.js no
p0dcasters 511-line React context: queue, next/prev, persisted dock no
rssamplifier DockPlayer + PlaylistPlayer + queue no

Handing the last three createPlayer would mean deleting queues, next/previous and video.js to gain a nicer-looking bar. That is a regression dressed as an adoption.

What all three do need is the half below the UI — which engine plays this source. Each answers it separately today, which is how a podcast shipping an HLS enclosure plays on one of our sites and not another.

const attached = await attachSource(audioEl, { src: episode.enclosureUrl });
attached.destroy();

No DOM, no styles, no opinions about the host's UI. createPlayer now calls it too, so there is one engine ladder rather than two that drift.

One behaviour change, and it is an improvement

An unplayable source no longer attaches a native engine as a consolation prize. Pointing a <video> at an .m3u8 it cannot parse replaced a precise reason ("This browser cannot play HLS streams") with a generic media error a few seconds later.

Checks

8 new tests covering engine choice, the iOS fallback, that it creates no DOM and touches no classes, that destroy really lets go, and that an unplayable source reports rather than attaches. 79 pass overall; tsc and prettier clean.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WFLwZtXE6iBJyJSgrsWqRM

Three of the apps meant to adopt this already have a player, and they are not
thin ones: p0dcasters runs a 511-line queue-aware dock, rssamplifier has a
dock plus a playlist player, and media-streamer has a modal per source with
its own retry and favourites. Handing them `createPlayer` would mean deleting
queues, next/previous and video.js to gain a nicer-looking bar. That is a
regression dressed as an adoption.

What all three DO need is the half below the UI: which engine plays this
source. Each answers it separately today, which is how a podcast shipping an
HLS enclosure plays on one of our sites and not another.

So `attachSource(media, { src })` picks the engine, attaches it, and hands
back something that lets go. No DOM, no styles, no opinions about the host's
UI. `createPlayer` now calls it too rather than keeping a second copy of the
ladder -- a second copy is the one that stops matching.

One behaviour change falls out and is an improvement: an unplayable source no
longer attaches a native engine as a consolation. Pointing a <video> at an
.m3u8 it cannot parse replaced a precise reason ("this browser cannot play HLS
streams") with a generic media error a few seconds later.

8 new tests; 79 pass, tsc and prettier clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WFLwZtXE6iBJyJSgrsWqRM
@ralyodio
ralyodio merged commit fbe1852 into main Aug 29, 2026
3 checks passed
@ralyodio
ralyodio deleted the attach-source branch August 29, 2026 08:43
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