fix stuff + add stuff
This commit is contained in:
parent
17131047c3
commit
79a81d23a1
@ -2,7 +2,7 @@
|
||||
var _yt_player = videojs;
|
||||
|
||||
var versionclient = "youtube.player.web_20250917_22_RC00"
|
||||
|
||||
|
||||
document.addEventListener("DOMContentLoaded", () => {
|
||||
// video.js 8 init - source can be seen in https://poketube.fun/static/vjs.min.js or the vjs.min.js file
|
||||
const video = videojs('video', {
|
||||
@ -28,13 +28,18 @@ var versionclient = "youtube.player.web_20250917_22_RC00"
|
||||
let syncing = false; // prevents normal ping-pong
|
||||
let restarting = false; // prevents loop-end ping-pong
|
||||
|
||||
// FIX: dynamic loop intent + disable native loop to avoid double-looping & missing 'ended'
|
||||
// FIX: explicit loop-state variables
|
||||
let desiredLoop =
|
||||
!!videoEl.loop ||
|
||||
qs.get("loop") === "1" ||
|
||||
qs.get("loop") === "true" ||
|
||||
window.forceLoop === true;
|
||||
|
||||
// FIX: tracks the short window *during* a loop restart where we auto-kick playback
|
||||
let isLoopingCycle = false;
|
||||
const LOOP_AUTOPLAY_RETRY_MS = 120;
|
||||
const LOOP_AUTOPLAY_RETRIES = 10;
|
||||
|
||||
// turn OFF native loop so 'ended' fires and we control both tracks together
|
||||
try { videoEl.loop = false; videoEl.removeAttribute?.('loop'); } catch {}
|
||||
try { audio.loop = false; audio.removeAttribute?.('loop'); } catch {}
|
||||
@ -269,7 +274,8 @@ var versionclient = "youtube.player.web_20250917_22_RC00"
|
||||
|
||||
// sync-safe play/pause handlers
|
||||
video.on('pause', () => {
|
||||
if (syncing || restarting) return;
|
||||
// FIX: if we’re in a loop restart, ignore transient pauses
|
||||
if (syncing || restarting || isLoopingCycle) return;
|
||||
syncing = true;
|
||||
try { if (!audio.paused) audio.pause(); } catch {}
|
||||
clearSyncLoop();
|
||||
@ -278,8 +284,7 @@ var versionclient = "youtube.player.web_20250917_22_RC00"
|
||||
|
||||
// FIX: do NOT mirror audio -> video; this was causing ping-pong after restarts
|
||||
audio.addEventListener('pause', () => {
|
||||
if (syncing || restarting) return;
|
||||
// just stop sync loop; do not pause video from here
|
||||
if (syncing || restarting || isLoopingCycle) return;
|
||||
clearSyncLoop();
|
||||
});
|
||||
|
||||
@ -292,14 +297,19 @@ var versionclient = "youtube.player.web_20250917_22_RC00"
|
||||
})().finally(() => { syncing = false; });
|
||||
});
|
||||
|
||||
// FIX: do NOT mirror audio -> video; only ensure loop running if audio resumes
|
||||
// Ensure loop running if audio resumes
|
||||
audio.addEventListener('play', () => {
|
||||
if (syncing || restarting) return;
|
||||
if (!syncInterval) startSyncLoop();
|
||||
});
|
||||
|
||||
video.on('waiting', () => { if (!restarting) { try { audio.pause(); } catch{}; clearSyncLoop(); } });
|
||||
video.on('playing', () => { if (audioReady && !restarting) audio.play()?.catch(()=>{}); if (!syncInterval) startSyncLoop(); });
|
||||
video.on('waiting', () => { if (!restarting && !isLoopingCycle) { try { audio.pause(); } catch{}; clearSyncLoop(); } });
|
||||
video.on('playing', () => {
|
||||
if (audioReady && !restarting) audio.play()?.catch(()=>{});
|
||||
if (!syncInterval) startSyncLoop();
|
||||
// FIX: once we truly start playing after a loop, clear the loop-cycle flag
|
||||
if (isLoopingCycle) isLoopingCycle = false;
|
||||
});
|
||||
|
||||
const errorBox = document.getElementById('loopedIndicator');
|
||||
video.on('error', () => {
|
||||
@ -388,6 +398,24 @@ var versionclient = "youtube.player.web_20250917_22_RC00"
|
||||
tick();
|
||||
});
|
||||
|
||||
// FIX: retry kicker used only during loop restarts
|
||||
const autoKickDuringLoop = async () => {
|
||||
let tries = 0;
|
||||
const tick = async () => {
|
||||
if (!isLoopingCycle) return;
|
||||
const vPaused = video.paused();
|
||||
const aPaused = audio.paused;
|
||||
if (!vPaused && !aPaused) { isLoopingCycle = false; return; }
|
||||
tries++;
|
||||
await tryPlay(video, true);
|
||||
await tryPlay(audio, false);
|
||||
if (tries < LOOP_AUTOPLAY_RETRIES && isLoopingCycle) {
|
||||
setTimeout(tick, LOOP_AUTOPLAY_RETRY_MS);
|
||||
}
|
||||
};
|
||||
setTimeout(tick, LOOP_AUTOPLAY_RETRY_MS);
|
||||
};
|
||||
|
||||
// --- unconditional looping with anti-pingpong ---
|
||||
const restartLoop = async () => {
|
||||
if (restarting) return;
|
||||
@ -399,44 +427,39 @@ var versionclient = "youtube.player.web_20250917_22_RC00"
|
||||
try { video.pause(); } catch {}
|
||||
try { audio.pause(); } catch {}
|
||||
|
||||
// FIX: actually reset BOTH media correctly; use video.js API for the player
|
||||
const startAt = 0.001; // tiny offset so 'ended' doesn't immediately refire
|
||||
suppressEndedUntil = performance.now() + 1000; // ignore stray 'ended' during restart
|
||||
video.currentTime(startAt);
|
||||
safeSetCT(audio, startAt);
|
||||
|
||||
// wait until both are ready to resume; don't spin forever
|
||||
await waitUntilPlayable(startAt, 1000);
|
||||
|
||||
// try to start both; if blocked, muted fallback inside tryPlay()
|
||||
// initial start attempt
|
||||
const vOk = await tryPlay(video, /*isVjsPlayer*/ true);
|
||||
const aOk = await tryPlay(audio, /*isVjsPlayer*/ false);
|
||||
|
||||
if (!(vOk && aOk)) {
|
||||
await new Promise(r => setTimeout(r, 120));
|
||||
await (vOk ? Promise.resolve() : tryPlay(video, true));
|
||||
await (aOk ? Promise.resolve() : tryPlay(audio, false));
|
||||
}
|
||||
// schedule gentle retries if either failed (autoplay policy, decode lag, etc.)
|
||||
if (!(vOk && aOk)) autoKickDuringLoop();
|
||||
|
||||
if (!syncInterval) startSyncLoop();
|
||||
} catch {
|
||||
// swallow and drop through
|
||||
// swallow
|
||||
} finally {
|
||||
restarting = false;
|
||||
}
|
||||
};
|
||||
|
||||
// FIX: use desiredLoop (dynamic) and ignore 'ended' fired during the seek grace window
|
||||
// FIX: use desiredLoop (dynamic) and set isLoopingCycle so we know to auto-kick
|
||||
video.on('ended', () => {
|
||||
if (restarting) return;
|
||||
if (performance.now() < suppressEndedUntil) return;
|
||||
if (desiredLoop) restartLoop();
|
||||
if (desiredLoop) { isLoopingCycle = true; restartLoop(); }
|
||||
else { try { audio.pause(); } catch {}; clearSyncLoop(); }
|
||||
});
|
||||
audio.addEventListener('ended', () => {
|
||||
if (restarting) return;
|
||||
if (performance.now() < suppressEndedUntil) return;
|
||||
if (desiredLoop) restartLoop();
|
||||
if (desiredLoop) { isLoopingCycle = true; restartLoop(); }
|
||||
else { try { video.pause(); } catch {}; clearSyncLoop(); }
|
||||
});
|
||||
// -----------------------------
|
||||
@ -448,8 +471,6 @@ var versionclient = "youtube.player.web_20250917_22_RC00"
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
// https://codeberg.org/ashley/poke/src/branch/main/src/libpoketube/libpoketube-youtubei-objects.json
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user