[playback] CDN-first for dual-source videos + reliable hosted playback

Two fixes for hosted (CDN) playback that users hit on a torrent-first instance:

1. Reliability: clear crossOrigin before direct hosted playback (in
   resetVideoElement and right before video.src = httpsUrl). A leftover
   crossOrigin="anonymous" from a prior WebTorrent attempt on the reused
   <video> forced a CORS request that CDNs / redirect targets (e.g. archive.org
   storage nodes) reject, failing with MEDIA_ERR_SRC_NOT_SUPPORTED ("source not
   supported or blocked"). Direct <video> playback never needs CORS, so any URL
   now plays.

2. CDN-first for dual-source: when a hosted URL exists, play it first for
   instant, reliable startup; WebTorrent is reserved for URL-less videos (and
   explicit forcedSource: "torrent"). Previously a torrent-first instance made
   dual-source videos wait on a P2P cold start before falling back to the CDN.
   The torrent-first branch is now only reached without a URL, so it waits
   indefinitely for peers (no plan B) rather than on a fixed timeout.

Tests: hosted playback clears crossOrigin and plays; a torrent-first instance
plays the URL first when one exists and never calls WebTorrent; URL-less videos
still use WebTorrent. Spec-corrected two playbackService_order tests that
encoded the old torrent-first-for-dual-source behavior. All mutation-verified.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
thePR0M3TH3ANandClaude Opus 4.8 committed 2026-06-18 12:15:38 -04:00
1 parent 4e5bfaa6af
commit 89747d7290
3 files changed
+144 -27

No files matched your search

+34 -3
View File
@@ -898,6 +898,20 @@ class PlaybackSession extends SimpleEventEmitter {
}
activeVideoEl.src = "";
activeVideoEl.srcObject = null;
// Direct hosted playback must NOT require CORS. A leftover
// crossOrigin="anonymous" (e.g. set by a prior WebTorrent attempt on
// this reused element) makes the browser issue a CORS request that many
// CDNs — and redirect targets like archive.org's storage nodes — do not
// answer with Access-Control-Allow-Origin, so the load dies with
// MEDIA_ERR_SRC_NOT_SUPPORTED ("source not supported or blocked"). We
// never read pixels from the hosted <video>, so clear it and let any
// URL play.
try {
activeVideoEl.removeAttribute("crossorigin");
} catch (err) {
// ignore
}
activeVideoEl.crossOrigin = null;
try {
activeVideoEl.load();
} catch (err) {
@@ -1086,6 +1100,14 @@ class PlaybackSession extends SimpleEventEmitter {
};
try {
// Guarantee the direct load is CORS-free regardless of how we got
// here (see resetVideoElement) so any hosted URL plays reliably.
try {
activeVideoEl.removeAttribute("crossorigin");
} catch (err) {
// ignore
}
activeVideoEl.crossOrigin = null;
activeVideoEl.src = httpsUrl;
const playPromise = activeVideoEl.play();
if (playPromise && typeof playPromise.catch === "function") {
@@ -1180,6 +1202,13 @@ class PlaybackSession extends SimpleEventEmitter {
// --- Execution Flow ---
let tryUrlFirst = this.service.urlFirstEnabled;
// CDN-first for dual-source videos: whenever a hosted URL is available,
// play it first for instant, reliable startup. WebTorrent is reserved for
// videos that have no URL (or when the viewer explicitly forces P2P). This
// intentionally takes precedence over a torrent-first instance default,
// because waiting on a P2P cold-start when a working CDN exists is the
// slow, flaky path users were hitting.
if (httpsUrl) tryUrlFirst = true;
if (forcedSource === "url") tryUrlFirst = true;
if (forcedSource === "torrent") tryUrlFirst = false;
@@ -1223,9 +1252,11 @@ class PlaybackSession extends SimpleEventEmitter {
// Try Torrent First
if (this.magnetForPlayback) {
try {
// If we have a fallback URL, use the effective timeout.
// Otherwise, we must wait indefinitely for peers because there is no plan B.
const torrentTimeout = httpsUrl ? effectiveTimeout : 0;
// We only reach the torrent-first path when there is no hosted URL
// to fall back to (CDN-first handles the dual-source case above) or
// the viewer explicitly forced P2P. Either way there is no plan B,
// so wait indefinitely for peers rather than abandoning playback.
const torrentTimeout = 0;
// Wrap Torrent attempt in timeout
const torrentResult = await withTimeout(