fix stuff + add stuff
This commit is contained in:
parent
17131047c3
commit
79a81d23a1
@ -2,7 +2,7 @@
|
|||||||
var _yt_player = videojs;
|
var _yt_player = videojs;
|
||||||
|
|
||||||
var versionclient = "youtube.player.web_20250917_22_RC00"
|
var versionclient = "youtube.player.web_20250917_22_RC00"
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
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
|
// 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', {
|
const video = videojs('video', {
|
||||||
@ -28,13 +28,18 @@ var versionclient = "youtube.player.web_20250917_22_RC00"
|
|||||||
let syncing = false; // prevents normal ping-pong
|
let syncing = false; // prevents normal ping-pong
|
||||||
let restarting = false; // prevents loop-end 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 =
|
let desiredLoop =
|
||||||
!!videoEl.loop ||
|
!!videoEl.loop ||
|
||||||
qs.get("loop") === "1" ||
|
qs.get("loop") === "1" ||
|
||||||
qs.get("loop") === "true" ||
|
qs.get("loop") === "true" ||
|
||||||
window.forceLoop === 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
|
// turn OFF native loop so 'ended' fires and we control both tracks together
|
||||||
try { videoEl.loop = false; videoEl.removeAttribute?.('loop'); } catch {}
|
try { videoEl.loop = false; videoEl.removeAttribute?.('loop'); } catch {}
|
||||||
try { audio.loop = false; audio.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
|
// sync-safe play/pause handlers
|
||||||
video.on('pause', () => {
|
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;
|
syncing = true;
|
||||||
try { if (!audio.paused) audio.pause(); } catch {}
|
try { if (!audio.paused) audio.pause(); } catch {}
|
||||||
clearSyncLoop();
|
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
|
// FIX: do NOT mirror audio -> video; this was causing ping-pong after restarts
|
||||||
audio.addEventListener('pause', () => {
|
audio.addEventListener('pause', () => {
|
||||||
if (syncing || restarting) return;
|
if (syncing || restarting || isLoopingCycle) return;
|
||||||
// just stop sync loop; do not pause video from here
|
|
||||||
clearSyncLoop();
|
clearSyncLoop();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -292,14 +297,19 @@ var versionclient = "youtube.player.web_20250917_22_RC00"
|
|||||||
})().finally(() => { syncing = false; });
|
})().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', () => {
|
audio.addEventListener('play', () => {
|
||||||
if (syncing || restarting) return;
|
if (syncing || restarting) return;
|
||||||
if (!syncInterval) startSyncLoop();
|
if (!syncInterval) startSyncLoop();
|
||||||
});
|
});
|
||||||
|
|
||||||
video.on('waiting', () => { if (!restarting) { try { audio.pause(); } catch{}; clearSyncLoop(); } });
|
video.on('waiting', () => { if (!restarting && !isLoopingCycle) { try { audio.pause(); } catch{}; clearSyncLoop(); } });
|
||||||
video.on('playing', () => { if (audioReady && !restarting) audio.play()?.catch(()=>{}); if (!syncInterval) startSyncLoop(); });
|
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');
|
const errorBox = document.getElementById('loopedIndicator');
|
||||||
video.on('error', () => {
|
video.on('error', () => {
|
||||||
@ -388,6 +398,24 @@ var versionclient = "youtube.player.web_20250917_22_RC00"
|
|||||||
tick();
|
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 ---
|
// --- unconditional looping with anti-pingpong ---
|
||||||
const restartLoop = async () => {
|
const restartLoop = async () => {
|
||||||
if (restarting) return;
|
if (restarting) return;
|
||||||
@ -399,44 +427,39 @@ var versionclient = "youtube.player.web_20250917_22_RC00"
|
|||||||
try { video.pause(); } catch {}
|
try { video.pause(); } catch {}
|
||||||
try { audio.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
|
const startAt = 0.001; // tiny offset so 'ended' doesn't immediately refire
|
||||||
suppressEndedUntil = performance.now() + 1000; // ignore stray 'ended' during restart
|
suppressEndedUntil = performance.now() + 1000; // ignore stray 'ended' during restart
|
||||||
video.currentTime(startAt);
|
video.currentTime(startAt);
|
||||||
safeSetCT(audio, startAt);
|
safeSetCT(audio, startAt);
|
||||||
|
|
||||||
// wait until both are ready to resume; don't spin forever
|
|
||||||
await waitUntilPlayable(startAt, 1000);
|
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 vOk = await tryPlay(video, /*isVjsPlayer*/ true);
|
||||||
const aOk = await tryPlay(audio, /*isVjsPlayer*/ false);
|
const aOk = await tryPlay(audio, /*isVjsPlayer*/ false);
|
||||||
|
|
||||||
if (!(vOk && aOk)) {
|
// schedule gentle retries if either failed (autoplay policy, decode lag, etc.)
|
||||||
await new Promise(r => setTimeout(r, 120));
|
if (!(vOk && aOk)) autoKickDuringLoop();
|
||||||
await (vOk ? Promise.resolve() : tryPlay(video, true));
|
|
||||||
await (aOk ? Promise.resolve() : tryPlay(audio, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!syncInterval) startSyncLoop();
|
if (!syncInterval) startSyncLoop();
|
||||||
} catch {
|
} catch {
|
||||||
// swallow and drop through
|
// swallow
|
||||||
} finally {
|
} finally {
|
||||||
restarting = false;
|
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', () => {
|
video.on('ended', () => {
|
||||||
if (restarting) return;
|
if (restarting) return;
|
||||||
if (performance.now() < suppressEndedUntil) return;
|
if (performance.now() < suppressEndedUntil) return;
|
||||||
if (desiredLoop) restartLoop();
|
if (desiredLoop) { isLoopingCycle = true; restartLoop(); }
|
||||||
else { try { audio.pause(); } catch {}; clearSyncLoop(); }
|
else { try { audio.pause(); } catch {}; clearSyncLoop(); }
|
||||||
});
|
});
|
||||||
audio.addEventListener('ended', () => {
|
audio.addEventListener('ended', () => {
|
||||||
if (restarting) return;
|
if (restarting) return;
|
||||||
if (performance.now() < suppressEndedUntil) return;
|
if (performance.now() < suppressEndedUntil) return;
|
||||||
if (desiredLoop) restartLoop();
|
if (desiredLoop) { isLoopingCycle = true; restartLoop(); }
|
||||||
else { try { video.pause(); } catch {}; clearSyncLoop(); }
|
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
|
// https://codeberg.org/ashley/poke/src/branch/main/src/libpoketube/libpoketube-youtubei-objects.json
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user