From 80039f6b3b61732280550612cb3c36a263124d5d Mon Sep 17 00:00:00 2001 From: ashley Date: Mon, 6 Oct 2025 20:49:12 +0200 Subject: [PATCH] test something --- css/player-base.js | 210 +++++++++++++-------------------------------- 1 file changed, 62 insertions(+), 148 deletions(-) diff --git a/css/player-base.js b/css/player-base.js index 4120508c..21f80bb4 100644 --- a/css/player-base.js +++ b/css/player-base.js @@ -2,7 +2,7 @@ var _yt_player = videojs; var versionclient = "youtube.player.web_20250917_22_RC00" - document.addEventListener("DOMContentLoaded", () => { + document.addEventListener("DOMContentLoaded", () => { const video = videojs('video', { controls: true, autoplay: false, @@ -17,9 +17,6 @@ var versionclient = "youtube.player.web_20250917_22_RC00" const videoEl = document.getElementById('video'); const audio = document.getElementById('aud'); - const audioEl = document.getElementById('aud'); - let volGuard = false; - try { videoEl.setAttribute('playsinline', ''); videoEl.setAttribute('webkit-playsinline', ''); } catch {} let syncing = false; @@ -37,23 +34,11 @@ var versionclient = "youtube.player.web_20250917_22_RC00" let prevVideoMuted = false; let prevAudioMuted = false; let pendingUnmute = false; + let firstSeekDone = false; try { videoEl.loop = false; videoEl.removeAttribute?.('loop'); } catch {} try { audio.loop = false; audio.removeAttribute?.('loop'); } catch {} - try { - const loopObserver = new MutationObserver(muts => { - for (const m of muts) { - if (m.type === 'attributes' && m.attributeName === 'loop') { - desiredLoop = videoEl.hasAttribute('loop') || !!videoEl.loop; - videoEl.removeAttribute('loop'); - videoEl.loop = false; - } - } - }); - loopObserver.observe(videoEl, { attributes: true, attributeFilter: ['loop'] }); - } catch {} - const pickAudioSrc = () => { const s = audio?.getAttribute?.('src'); if (s) return s; @@ -62,8 +47,7 @@ var versionclient = "youtube.player.web_20250917_22_RC00" if (audio?.currentSrc) return audio.currentSrc; return null; }; - let audioSrc = pickAudioSrc(); - + const audioSrc = pickAudioSrc(); const srcObj = video.src(); const videoSrc = Array.isArray(srcObj) ? (srcObj[0] && srcObj[0].src) : srcObj; @@ -75,33 +59,9 @@ var versionclient = "youtube.player.web_20250917_22_RC00" const SYNC_INTERVAL_MS = 250; const EPS = 0.15; - function timeInBuffered(media, t) { - try { - const br = media.buffered; - if (!br || br.length === 0 || !isFinite(t)) return false; - for (let i = 0; i < br.length; i++) { - const s = br.start(i) - EPS, e = br.end(i) + EPS; - if (t >= s && t <= e) return true; - } - } catch {} - return false; - } - function canPlayAt(media, t) { - try { - const rs = Number(media.readyState || 0); - if (!isFinite(t)) return false; - if (rs >= 3) return true; - return timeInBuffered(media, t); - } catch { return false; } - } - function bothPlayableAt(t) { - return canPlayAt(videoEl, t) && canPlayAt(audio, t); - } - function safeSetCT(media, t) { try { - if (!isFinite(t) || t < 0) return; - media.currentTime = t; + if (isFinite(t) && t >= 0) media.currentTime = t; } catch {} } @@ -123,42 +83,46 @@ var versionclient = "youtube.player.web_20250917_22_RC00" if (Math.abs(delta) > BIG_DRIFT) { safeSetCT(audio, vt); try { audio.playbackRate = 1; } catch {} - return; - } - if (Math.abs(delta) > MICRO_DRIFT) { - const targetRate = 1 + (delta * 0.12); + } else if (Math.abs(delta) > MICRO_DRIFT) { + const targetRate = 1 + delta * 0.12; try { audio.playbackRate = Math.max(0.85, Math.min(1.15, targetRate)); } catch {} - } else { - try { audio.playbackRate = 1; } catch {} - } + } else try { audio.playbackRate = 1; } catch {} }, SYNC_INTERVAL_MS); } + const errorBox = document.getElementById('loopedIndicator'); + const showError = msg => { + if (errorBox) { + errorBox.textContent = msg; + errorBox.style.display = 'block'; + errorBox.style.width = 'fit-content'; + } + }; + const markVPlaying = () => { vIsPlaying = true; maybeUnmuteRestore(); }; const markAPlaying = () => { aIsPlaying = true; maybeUnmuteRestore(); }; const markVNotPlaying = () => { vIsPlaying = false; }; const markANotPlaying = () => { aIsPlaying = false; }; - function bothActivelyPlaying() { return vIsPlaying && aIsPlaying; } + const bothActivelyPlaying = () => vIsPlaying && aIsPlaying; - function maybeUnmuteRestore() { + const maybeUnmuteRestore = () => { if (!pendingUnmute) return; if (bothActivelyPlaying()) { pendingUnmute = false; setTimeout(() => { - // Fix wrong mute restore - if (video.muted() && !prevVideoMuted) try { video.muted(false); } catch {} - if (audio.muted && !prevAudioMuted) try { audio.muted = false; } catch {} + try { if (video.muted() && !prevVideoMuted) video.muted(false); } catch {} + try { if (audio.muted && !prevAudioMuted) audio.muted = false; } catch {} }, 120); } - } + }; async function playTogether({ allowMutedRetry = true } = {}) { if (syncing || restarting) return; syncing = true; try { const t = Number(video.currentTime()); - if (isFinite(t) && Math.abs(Number(audio.currentTime) - t) > 0.05) safeSetCT(audio, t); + if (isFinite(t) && Math.abs(audio.currentTime - t) > 0.05) safeSetCT(audio, t); let vOk = true, aOk = true; try { const p = video.play(); if (p && p.then) await p; } catch { vOk = false; } @@ -168,122 +132,78 @@ var versionclient = "youtube.player.web_20250917_22_RC00" prevVideoMuted = !!video.muted(); prevAudioMuted = !!audio.muted; pendingUnmute = true; - try { video.muted(true); } catch {} - try { audio.muted = true; } catch {} + try { video.muted(true); audio.muted = true; } catch {} try { const p = video.play(); if (p && p.then) await p; } catch {} try { const p = audio.play(); if (p && p.then) await p; } catch {} } - // ensure no mismatch - if (!vOk && aOk) { - try { video.play().catch(() => showError('Video failed to start.')); } catch {} - } - if (vOk && !aOk) { - try { audio.play().catch(() => showError('Audio failed to start.')); } catch {} - } + if (!vOk && aOk) try { video.play().catch(() => showError('Video failed to start.')); } catch {} + if (vOk && !aOk) try { audio.play().catch(() => showError('Audio failed to start.')); } catch {} if (!syncInterval) startSyncLoop(); } finally { syncing = false; } } - function pauseTogether() { + const pauseTogether = () => { if (syncing) return; syncing = true; try { video.pause(); audio.pause(); clearSyncLoop(); } finally { syncing = false; } - } + }; - function tryStart() { + const tryStart = () => { if (audioReady && videoReady && !restarting) { const t = Number(video.currentTime()); - if (isFinite(t) && Math.abs(Number(audio.currentTime) - t) > 0.1) safeSetCT(audio, t); - if (bothPlayableAt(t)) playTogether({ allowMutedRetry: true }); - else pauseTogether(); - setupMediaSession(); + if (isFinite(t) && Math.abs(audio.currentTime - t) > 0.1) safeSetCT(audio, t); + playTogether({ allowMutedRetry: true }); } - } + }; - function attachRetry(elm, resolveSrc, markReady) { + const attachRetry = (elm, markReady) => { const onLoaded = () => { markReady(); tryStart(); }; elm.addEventListener('loadeddata', onLoaded, { once: true }); elm.addEventListener('loadedmetadata', onLoaded, { once: true }); - } - - const errorBox = document.getElementById('loopedIndicator'); - function showError(msg) { - if (errorBox) { - errorBox.textContent = msg; - errorBox.style.display = 'block'; - errorBox.style.width = 'fit-content'; - } - } - - function setupMediaSession() { - if ('mediaSession' in navigator) { - try { - navigator.mediaSession.metadata = new MediaMetadata({ - title: document.title || 'Video', - artist: '', - album: '', - artwork: [] - }); - } catch {} - navigator.mediaSession.setActionHandler('play', () => playTogether({ allowMutedRetry: true })); - navigator.mediaSession.setActionHandler('pause', pauseTogether); - } - } - - document.addEventListener('keydown', e => { - if (restarting) return; - if (e.code === 'MediaPlayPause') { - if (video.paused()) playTogether({ allowMutedRetry: true }); - else pauseTogether(); - } - }); + }; let mediaUnlocked = false; const unlock = () => { if (mediaUnlocked) return; mediaUnlocked = true; try { audio.muted = true; audio.play().then(() => audio.pause()).catch(()=>{}); } catch {} - try { const was = !!video.muted(); video.muted(true); video.play().then(()=>{ video.pause(); video.muted(was); }).catch(()=>{}); } catch {} + try { + const was = !!video.muted(); + video.muted(true); + video.play().then(() => { video.pause(); video.muted(was); }).catch(()=>{}); + } catch {} }; window.addEventListener('click', unlock, { once: true, capture: true }); window.addEventListener('keydown', unlock, { once: true, capture: true }); if (qua !== "medium") { - attachRetry(audio, pickAudioSrc, () => { audioReady = true; }); - attachRetry(videoEl, () => videoSrc, () => { videoReady = true; }); + attachRetry(audio, () => { audioReady = true; }); + attachRetry(videoEl, () => { videoReady = true; }); const clamp = v => Math.max(0, Math.min(1, Number(v))); video.on('volumechange', () => { - try { - if (!video.muted()) audio.volume = clamp(video.volume()); - audio.muted = video.muted(); - } catch {} + try { if (!video.muted()) audio.volume = clamp(video.volume()); audio.muted = video.muted(); } catch {} }); video.on('ratechange', () => { try { audio.playbackRate = video.playbackRate(); } catch {} }); video.on('error', () => { - const mediaError = video.error(); - let message = 'An unknown error occurred.'; - if (mediaError) { - if (mediaError.code === 1) return; - message = `Error ${mediaError.code}: ${mediaError.message || 'No message provided'} try to refresh the page?`; - } - showError(message); + const e = video.error(); + if (!e || e.code === 1) return; + showError(`Error ${e.code}: ${e.message || 'No message provided'} try to refresh the page?`); }); video.on('play', () => { markVPlaying(); if (!aIsPlaying) playTogether(); }); audio.addEventListener('play', () => { markAPlaying(); - if (!vIsPlaying) { - try { video.play().catch(() => showError('Video failed to start.')); } catch {} - } + if (!vIsPlaying) try { video.play().catch(() => showError('Video failed to start.')); } catch {} }); video.on('pause', () => { markVNotPlaying(); if (!restarting) pauseTogether(); }); audio.addEventListener('pause', () => { markANotPlaying(); if (!restarting) pauseTogether(); }); + video.on('waiting', () => { markVNotPlaying(); if (!restarting) { try { audio.pause(); } catch{}; clearSyncLoop(); } }); video.on('playing', markVPlaying); @@ -293,23 +213,18 @@ var versionclient = "youtube.player.web_20250917_22_RC00" let playPauseEvents = []; const SPAM_WINDOW_MS = 3000; const SPAM_LIMIT = 4; - - function recordPlayPause() { + const recordPlayPause = () => { const now = performance.now(); playPauseEvents.push(now); playPauseEvents = playPauseEvents.filter(t => now - t < SPAM_WINDOW_MS); - if (playPauseEvents.length > SPAM_LIMIT) { - pauseTogether(); - playPauseEvents = []; - } - } - + if (playPauseEvents.length > SPAM_LIMIT) { pauseTogether(); playPauseEvents = []; } + }; audio.addEventListener('play', recordPlayPause); audio.addEventListener('pause', recordPlayPause); video.on('play', recordPlayPause); video.on('pause', recordPlayPause); - // --- adaptive seek threshold --- + // --- adaptive seek threshold + firstSeek fix --- let wasPlayingBeforeSeek = false; let lastSeekTime = 0; video.on('seeking', () => { @@ -322,20 +237,22 @@ var versionclient = "youtube.player.web_20250917_22_RC00" if (restarting) return; const newTime = Number(video.currentTime()); const seekDiff = Math.abs(newTime - lastSeekTime); - - // threshold scales with video duration const dur = Number(video.duration()) || 60; - const threshold = Math.max(5, Math.min(dur * 0.66, 60)); // e.g., 40s for 1min, 60s max + const threshold = Math.max(5, Math.min(dur * 0.66, 60)); // adaptive + safeSetCT(audio, newTime); + + if (!firstSeekDone) { + firstSeekDone = true; + // always resume immediately after first seek + setTimeout(() => playTogether({ allowMutedRetry: true }), 150); + return; + } if (seekDiff > threshold) { pauseTogether(); - safeSetCT(audio, newTime); setTimeout(() => { - if (wasPlayingBeforeSeek && bothPlayableAt(newTime)) - playTogether({ allowMutedRetry: true }); + if (wasPlayingBeforeSeek) playTogether({ allowMutedRetry: true }); }, 200); - } else { - safeSetCT(audio, newTime); } }); @@ -356,14 +273,12 @@ var versionclient = "youtube.player.web_20250917_22_RC00" video.on('ended', () => { if (restarting) return; if (performance.now() < suppressEndedUntil) return; - if (desiredLoop) restartLoop(); - else pauseTogether(); + desiredLoop ? restartLoop() : pauseTogether(); }); audio.addEventListener('ended', () => { if (restarting) return; if (performance.now() < suppressEndedUntil) return; - if (desiredLoop) restartLoop(); - else pauseTogether(); + desiredLoop ? restartLoop() : pauseTogether(); }); document.addEventListener('fullscreenchange', () => { @@ -373,7 +288,6 @@ var versionclient = "youtube.player.web_20250917_22_RC00" }); - // https://codeberg.org/ashley/poke/src/branch/main/src/libpoketube/libpoketube-youtubei-objects.json