Add detailed playback teardown logging

This commit is contained in:
thePR0M3TH3AN committed 2025-09-29 12:10:36 -04:00
1 parent 6a3bc50066
commit 7e8d5f2fef
1 file changed
+122
+122
View File
@@ -5382,9 +5382,13 @@ class bitvidApp {
* Cleanup resources on unload or modal close.
*/
async cleanup({ preserveSubscriptions = false, preserveObservers = false } = {}) {
this.log(
`[cleanup] Requested (preserveSubscriptions=${preserveSubscriptions}, preserveObservers=${preserveObservers})`
);
// Serialise teardown so overlapping calls (e.g. close button spam) don't
// race each other and clobber a fresh playback setup.
if (this.cleanupPromise) {
this.log("[cleanup] Waiting for in-flight cleanup to finish before starting a new run.");
try {
await this.cleanupPromise;
} catch (err) {
@@ -5393,6 +5397,9 @@ class bitvidApp {
}
const runCleanup = async () => {
this.log(
`[cleanup] Begin (preserveSubscriptions=${preserveSubscriptions}, preserveObservers=${preserveObservers})`
);
try {
this.clearActiveIntervals();
this.cleanupUrlPlaybackWatchdog();
@@ -5437,8 +5444,11 @@ class bitvidApp {
}
// Tell webtorrent to cleanup
await torrentClient.cleanup();
this.log("[cleanup] WebTorrent cleanup resolved.");
} catch (err) {
console.error("Cleanup error:", err);
} finally {
this.log("[cleanup] Finished.");
}
};
@@ -5460,7 +5470,9 @@ class bitvidApp {
}
try {
this.log("[waitForCleanup] Awaiting previous cleanup before continuing.");
await this.cleanupPromise;
this.log("[waitForCleanup] Previous cleanup completed.");
} catch (err) {
console.warn("waitForCleanup observed a rejected cleanup:", err);
}
@@ -5488,6 +5500,9 @@ class bitvidApp {
teardownVideoElement(videoElement, { replaceNode = false } = {}) {
if (!videoElement) {
this.log(
`[teardownVideoElement] No video provided (replaceNode=${replaceNode}); skipping.`
);
return videoElement;
}
@@ -5499,6 +5514,18 @@ class bitvidApp {
}
};
const describeSource = () => {
try {
return videoElement.currentSrc || videoElement.src || "<unset>";
} catch (err) {
return "<unavailable>";
}
};
this.log(
`[teardownVideoElement] Resetting video (replaceNode=${replaceNode}) readyState=${videoElement.readyState} networkState=${videoElement.networkState} src=${describeSource()}`
);
safe(() => videoElement.pause());
safe(() => {
@@ -5526,6 +5553,9 @@ class bitvidApp {
});
if (!replaceNode || !videoElement.parentNode) {
this.log(
`[teardownVideoElement] Completed without node replacement (readyState=${videoElement.readyState}).`
);
return videoElement;
}
@@ -5586,6 +5616,10 @@ class bitvidApp {
}
});
this.log(
`[teardownVideoElement] Replaced modal video node (readyState=${clone.readyState} networkState=${clone.networkState}).`
);
return clone;
}
@@ -5600,6 +5634,9 @@ class bitvidApp {
}
const normalizedStallMs = Number.isFinite(stallMs) && stallMs > 0 ? stallMs : 0;
this.log(
`[registerUrlPlaybackWatchdogs] Installing watchdogs (stallMs=${normalizedStallMs}) readyState=${videoElement.readyState} networkState=${videoElement.networkState}`
);
let active = true;
let stallTimerId = null;
@@ -5624,6 +5661,9 @@ class bitvidApp {
if (!active) {
return;
}
this.log(
`[registerUrlPlaybackWatchdogs] Triggering fallback (${reason}) readyState=${videoElement.readyState} networkState=${videoElement.networkState}`
);
cleanup();
onFallback(reason);
};
@@ -5632,6 +5672,9 @@ class bitvidApp {
if (!active) {
return;
}
this.log(
"[registerUrlPlaybackWatchdogs] Hosted playback signaled success; clearing watchdogs."
);
cleanup();
if (typeof onSuccess === "function") {
onSuccess();
@@ -5678,6 +5721,7 @@ class bitvidApp {
}
this.urlPlaybackWatchdogCleanup = () => {
this.log("[registerUrlPlaybackWatchdogs] Manual watchdog cleanup invoked.");
cleanup();
};
@@ -8077,6 +8121,10 @@ class bitvidApp {
: "";
const magnetProvided = playbackConfig.provided;
this.log(
`[playVideoWithFallback] Session start urlProvided=${!!sanitizedUrl} magnetProvided=${magnetProvided} magnetUsable=${!!magnetForPlayback}`
);
if (this.currentVideo) {
this.currentVideo.magnet = magnetForPlayback;
this.currentVideo.normalizedMagnet = magnetForPlayback;
@@ -8089,6 +8137,8 @@ class bitvidApp {
this.currentMagnetUri = magnetForPlayback || null;
this.setCopyMagnetState(!!magnetForPlayback);
let ensureDebugListenersRemoved = () => {};
try {
if (!this.modalVideo) {
throw new Error("Video element is not ready for playback.");
@@ -8126,6 +8176,55 @@ class bitvidApp {
const activeVideoEl = this.teardownVideoElement(this.modalVideo);
if (activeVideoEl) {
this.modalVideo = activeVideoEl;
this.log(
`[playVideoWithFallback] Modal video prepared (readyState=${activeVideoEl.readyState} networkState=${activeVideoEl.networkState}).`
);
}
if (activeVideoEl) {
const debugEvents = [
"loadedmetadata",
"loadeddata",
"canplay",
"canplaythrough",
"play",
"playing",
"pause",
"stalled",
"suspend",
"waiting",
"ended",
"error",
];
const debugHandlers = [];
ensureDebugListenersRemoved = () => {
if (!debugHandlers.length) {
return;
}
for (const [eventName, handler] of debugHandlers) {
activeVideoEl.removeEventListener(eventName, handler);
}
debugHandlers.length = 0;
ensureDebugListenersRemoved = () => {};
};
for (const eventName of debugEvents) {
const handler = () => {
const { readyState, networkState, currentTime, paused, error } =
activeVideoEl;
let suffix = `readyState=${readyState} networkState=${networkState} currentTime=${Number.isFinite(currentTime) ? currentTime.toFixed(2) : currentTime} paused=${paused}`;
if (eventName === "error" && error) {
const errorMessage = error.message || "";
suffix += ` code=${error.code || ""} message=${errorMessage}`;
}
this.log(
`[playVideoWithFallback] <video> event ${eventName}; ${suffix}`
);
};
activeVideoEl.addEventListener(eventName, handler);
debugHandlers.push([eventName, handler]);
}
} else {
ensureDebugListenersRemoved = () => {};
}
this.resetTorrentStats();
@@ -8143,6 +8242,9 @@ class bitvidApp {
sanitizedUrl && /^https:\/\//i.test(sanitizedUrl) ? sanitizedUrl : "";
const webSeedCandidates = httpsUrl ? [httpsUrl] : [];
let cleanupHostedUrlStatusListeners = () => {};
const cleanupDebugListeners = () => {
ensureDebugListenersRemoved();
};
let fallbackStarted = false;
const startTorrentFallback = async (reason) => {
@@ -8155,6 +8257,7 @@ class bitvidApp {
fallbackStarted = true;
this.cleanupUrlPlaybackWatchdog();
cleanupHostedUrlStatusListeners();
cleanupDebugListeners();
if (activeVideoEl) {
try {
@@ -8197,6 +8300,13 @@ class bitvidApp {
this.log(
`[playVideoWithFallback] Falling back to WebTorrent (${reason}).`
);
this.log(
`[playVideoWithFallback] startTorrentFallback invoked with magnet=${!!magnetForPlayback} readyState=${
activeVideoEl ? activeVideoEl.readyState : "n/a"
} networkState=${
activeVideoEl ? activeVideoEl.networkState : "n/a"
}`
);
console.debug("[WT] add magnet =", magnetForPlayback);
const torrentInstance = await this.playViaWebTorrent(
magnetForPlayback,
@@ -8214,6 +8324,9 @@ class bitvidApp {
if (this.modalStatus) {
this.modalStatus.textContent = "Checking hosted URL...";
}
this.log(
`[playVideoWithFallback] Probing hosted URL ${httpsUrl} (readyState=${activeVideoEl?.readyState} networkState=${activeVideoEl?.networkState}).`
);
let hostedStatusResolved = false;
const hostedStatusHandlers = [];
const addHostedStatusListener = (eventName, handler, options) => {
@@ -8262,12 +8375,17 @@ class bitvidApp {
addHostedStatusListener("canplay", maybeMarkHostedUrl);
addHostedStatusListener("error", () => {
cleanupHostedUrlStatusListeners();
cleanupDebugListeners();
}, { once: true });
const probeResult = await this.probeUrl(httpsUrl);
const probeOutcome = probeResult?.outcome || "error";
const shouldAttemptHosted =
probeOutcome !== "bad" && probeOutcome !== "error";
this.log(
`[playVideoWithFallback] Hosted URL probe outcome=${probeOutcome} shouldAttemptHosted=${shouldAttemptHosted}`
);
if (shouldAttemptHosted) {
let outcomeResolved = false;
let outcomeResolver = () => {};
@@ -8358,6 +8476,7 @@ class bitvidApp {
this.modalStatus.textContent = HOSTED_URL_SUCCESS_MESSAGE;
}
cleanupHostedUrlStatusListeners();
cleanupDebugListeners();
return;
}
@@ -8370,6 +8489,7 @@ class bitvidApp {
`[playVideoWithFallback] Hosted URL probe reported "${probeOutcome}"; deferring to WebTorrent.`
);
cleanupHostedUrlStatusListeners();
cleanupDebugListeners();
}
if (magnetForPlayback) {
@@ -8384,8 +8504,10 @@ class bitvidApp {
this.modalStatus.textContent = message;
}
this.playSource = null;
cleanupDebugListeners();
this.showError(message);
} catch (error) {
ensureDebugListenersRemoved();
this.log("Error in playVideoWithFallback:", error);
this.showError(`Playback error: ${error.message}`);
}