File-size decomposition of the playback-critical module (no behavior change).
Move the pure helpers (compareServiceWorkerScripts, normalizeTrackerList,
appendProbeTrackers, normalizeNumber, toError) and the service-worker
controller-claim pair (requestClientsClaim, waitForActiveController, as
instance-param functions with thin delegators) into js/webtorrentHelpers.js.
Dropped the now-unused safeDecodeURIComponent import from webtorrent.js.
webtorrent.js: 1256 -> 1043 lines (back under its 1087 limit).
All moved functions were module-private (no public-export/test-import changes).
Build + full unit suite green (incl. WebTorrent regression/handlers/minimal
tests).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The video's hosted CDN URL was added to WebTorrent's `urlList`, but a
standalone hosted-file URL is only a valid BEP19 webseed for a SINGLE-file
torrent. For a multi-file torrent WebTorrent treats it as a base directory and
appends "<torrent name>/<file path>", producing a doubled URL that 404s on
every request — the flood seen on e.g. archive.org videos.
The CDN URL is no longer placed in urlList. It's forwarded separately as
`hostedUrlWebSeed` and attached post-metadata (handleTorrentStream) via
torrent.addWebSeed ONLY when the torrent is a single file, where the URL maps
directly to the file. Multi-file torrents get no file-pointing webseed, so no
flood. Magnet-declared `ws=` webseeds are unaffected (passed via urlList as
before). With CDN-first, dual-source videos play the CDN directly anyway, so
this only affects forced-torrent / URL-less paths.
Tests: a single-file torrent receives the hosted URL via addWebSeed; a
multi-file torrent does not. The single-file guard is mutation-verified.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
WebTorrent (handleTorrentStream) hardening:
- Resolve only when playback is actually viable (loadeddata/canplay/playing),
not the instant streamTo() is called. A dead/too-slow swarm is no longer
reported as success, so the caller's fallback can run.
- Pre-playback torrent errors reject (caller falls back); post-playback errors
go to an onPlaybackError hook instead of a dead reject().
- Mid-stream stall watchdog surfaces an onStall hook ("waiting for peers").
- Fix a <video> listener leak: stream listeners are tracked and torn down
before the next stream and on cleanup() (the modal reuses one element).
- Stream the largest decodable file from a multi-file torrent and deselect the
rest (wider ext set: mp4/m4v/webm/mkv/mov/ogv/ogg) so the swarm isn't spent
downloading files we never play.
playbackCoordinator wires onStall/onPlaybackError to user-facing status.
Forced-source deep links (test affordance):
- The main app honors ?v=<nevent>&playback=torrent|url (mirrors the embed
player) to force a playback path; a missing source shows a clear message.
- The video share menu gains "Copy WebTorrent URL" / "Copy CDN URL" items that
copy the forced-source deep link (disabled with a reason when unavailable).
Tests: webtorrent-handlers (resolve-on-readiness, pre/post-ready errors, stall
fires/clears, largest-file select/deselect, no listener accumulation),
playback-forced-source (param normalization), videoMenuRenderers (copy items +
availability). All mutation-verified.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
- Merged `handleChromeTorrent` and `handleFirefoxTorrent` into `handleTorrentStream` with a `context` parameter.
- Preserved browser-specific logic (CORS workaround for Chrome, highWaterMark for Firefox).
- Added `tests/webtorrent-handlers.test.mjs` to cover the refactored logic.
Co-authored-by: PR0M3TH3AN <[email protected]>
Improves the playback startup sequence in `js/webtorrent.js` by explicitly listening for `loadeddata` in addition to `canplay` and checking `readyState` immediately after streaming starts. This ensures autoplay is triggered reliably even if the browser has already buffered enough data or if the `canplay` event logic is bypassed.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Create `docs/webtorrent-architecture.md` detailing the "Webseeds are Peers" strategy.
- Update `docs/video-availability-checks.md` with cross-reference.
- Add "CRITICAL" warning comments to `js/webtorrent.js` and `js/gridHealth.js` to prevent regressions.
- Enhance `tests/webtorrent-regression.test.mjs` to explicitly verify `urlList` passing in mocks.
Co-authored-by: PR0M3TH3AN <[email protected]>
Reverts `js/webtorrent.js` and `js/gridHealth.js` to a simplified implementation that correctly treats webseeds as peers. This ensures that videos with only webseeds (and 0 P2P peers) are considered healthy and playable, resolving an issue where such videos were marked as unhealthy or failed to stream.
- Updates `js/webtorrent.js` to use `client.add(url, { urlList: [...] })` for better webseed integration.
- Updates `js/gridHealth.js` to rely on `peers > 0` for health, removing complex `webseedOnly` logic.
- Updates `tests/webtorrent-regression.test.mjs` to verify that webseeds are counted as peers and result in a healthy state with reason "peer".
Co-authored-by: PR0M3TH3AN <[email protected]>
- Add detailed logging inside `js/webtorrent.js` (guarded by `NODE_ENV=test`) to inspect the state of `peers`, `hasWebSeed`, and `webseedOnly` when a probe times out.
- This is intended to diagnose why `webseedOnly` evaluates to false in CI despite logs indicating `hasExplicitWebSeed` is true.
Co-authored-by: PR0M3TH3AN <[email protected]>
- Increase `timeoutMs` in `tests/webtorrent-regression.test.mjs` from 50ms to 200ms to reduce flakiness in CI environments.
- Add debug logging to `js/webtorrent.js` (guarded by `NODE_ENV === 'test'`) to inspect `probePeers` inputs and `client.add` errors, helping diagnose why `webseedOnly` detection might fail in CI.
- Log failure details in `tests/webtorrent-regression.test.mjs` if assertion fails.
Co-authored-by: PR0M3TH3AN <[email protected]>
This change addresses two issues with WebTorrent webseed handling:
1. **Grid Availability Check:** Modified `js/gridHealth.js` to correctly classify torrents with only webseeds as "healthy" and report 1 peer (instead of 0) so the UI availability check passes.
2. **Video Player Bootstrap:** Modified `js/webtorrent.js` (`probePeers` and `streamVideo`) to explicitly append provided webseed URLs (`urlList`) to the magnet link as `&ws=` parameters. This forces the WebTorrent client to recognize and use these webseeds as initial peers for bootstrapping the swarm.
Tested via `tests/verification/verify_webseed_fix.mjs` (logic verification).
Co-authored-by: PR0M3TH3AN <[email protected]>
Previously, `probePeers` would mark a stream as unhealthy (healthy: false) if no P2P peers were found, even if a valid webseed was present. This caused the UI to potentially disable playback or show error states for webseed-only content.
This fix ensures that if `peers === 0` but `hasWebSeed` is true, the probe result returns `healthy: true` with reason `"webseed"`.
Added `tests/webtorrent-regression.test.mjs` to verify this behavior and prevent future regressions.
Co-authored-by: PR0M3TH3AN <[email protected]>
Extracts `ws` (web seed) parameters from the magnet link and merges them with the explicit `urlList` (e.g., from direct URL) when initializing the WebTorrent stream. This fixes a regression where magnet-embedded web seeds were ignored if a direct URL was provided.
- Updates `js/magnets.js` to parse `ws` parameters and export `webSeedsFromMagnet`.
- Updates `js/webtorrent.js` to merge magnet web seeds with `opts.urlList`.
- Adds regression test `tests/webtorrent-webseeds.test.mjs`.
Co-authored-by: PR0M3TH3AN <[email protected]>
Diagnosed a CORS error on local development environment caused by WebTorrent fetching `.torrent` files from R2 buckets (via `xs` parameter) that do not allow localhost origin.
Modified `js/webtorrent.js` to strip the `xs` parameter from magnet links when running on `localhost` or `127.0.0.1`. This prevents the browser from attempting the blocked fetch request, resolving the console error while maintaining functionality (falling back to DHT/peers).
Verified using `scripts/agent/debug_frontend.py` which captures frontend console logs via Playwright.
Tests run:
- `npm run lint`
- `npm run test:unit:shard1`
- `python3 scripts/agent/debug_frontend.py` (verified error is gone)
Co-authored-by: PR0M3TH3AN <[email protected]>
- Added a null check for `this.client` in `js/webtorrent.js` after `await this.init()` to prevent `TypeError` when cleanup occurs during initialization.
- Updated `js/utils/profileMedia.js` to silently ignore the legacy `images/robot.png` path, preventing "Unsupported media URL" warnings.
Co-authored-by: PR0M3TH3AN <[email protected]>
This commit instruments the embed runtime to forward structured logs and lifecycle events
(Nostr, relay, pointer resolution, playback decision, WebTorrent) to the parent window
via `postMessage` when the `embed_debug=1` query parameter is present.
It also adds a defensive guard to `resetTorrentStats` in `js/app.js` to prevent TypeErrors.
Changes:
- Added `js/embedDiagnostics.js` module.
- Modified `js/embed.js` to initialize diagnostics and instrument startup.
- Modified `js/app.js` to instrument playback fallback and patch `resetTorrentStats`.
- Modified `js/webtorrent.js` to instrument peer probing and streaming.
Updated `probePeers` in `js/webtorrent.js` to detect `ws` (WebSeed) parameters in magnet links. If a web seed is present, the torrent is now considered "healthy" with at least one peer, even if tracker probing fails or returns zero peers. This ensures videos hosted on R2 (or other HTTP sources) are correctly marked as available in the UI.