diff --git a/public/admin.html b/public/admin.html index cf310b2..d91f3e0 100644 --- a/public/admin.html +++ b/public/admin.html @@ -3153,7 +3153,10 @@ }; const checkLinkRow = async (row, silent = false) => { - if (!row || !row.isConnected || row.dataset.probeActive === '1') return; + // Note: no probeActive guard here — a newer check (e.g. triggered by pasting a + // cookie while the URL probe is still in flight) must be allowed to start. + // The probeToken check below discards any stale/superseded result. + if (!row || !row.isConnected) return; const statusEl = row.querySelector('.stream-check-status'); const { url, type } = getRowProbeTarget(row); if (!url) { @@ -4660,6 +4663,8 @@ div.querySelector('.l-url').addEventListener('blur', () => scheduleLinkRowCheck(div, 0)); div.querySelector('.l-type').addEventListener('change', () => scheduleLinkRowCheck(div, 0)); div.querySelector('.l-proxy-mode').addEventListener('change', () => scheduleLinkRowCheck(div, 0)); + div.querySelector('.l-upstream-cookie')?.addEventListener('input', () => scheduleLinkRowCheck(div)); + div.querySelector('.l-upstream-cookie')?.addEventListener('blur', () => scheduleLinkRowCheck(div, 0)); if (url) scheduleLinkRowCheck(div, 250); div.querySelector('.link-move-up')?.addEventListener('click', () => moveLinkRowStep(div, -1)); div.querySelector('.link-move-down')?.addEventListener('click', () => moveLinkRowStep(div, 1)); diff --git a/public/player.html b/public/player.html index 20caf17..589cca9 100644 --- a/public/player.html +++ b/public/player.html @@ -1302,10 +1302,14 @@ const hls = new Hls({ enableSoftwareAES: !!keyOverride, loader: keyOverride ? CustomLoader : Hls.DefaultConfig.loader, + startLevel: -1, debug: false }); hls.loadSource(url); hls.attachMedia(video); + // Keep ABR / auto quality active from the start so playback isn't + // pinned to the lowest rung when the source (re)loads. + hls.on(Hls.Events.MANIFEST_PARSED, () => { hls.currentLevel = -1; }); art.hls = hls; art.on('destroy', () => hls.destroy()); } else if (video.canPlayType('application/vnd.apple.mpegurl')) { @@ -1331,6 +1335,28 @@ }, plugins: hlsControlPlugins }); + // The hls-control plugin labels its quality menu from hls.currentLevel, which + // is whatever rung hls.js happens to be on when the player becomes ready + // (often the lowest). Re-assert auto mode and refresh the menu so the default + // selection shows "Auto" rather than the lowest resolution. + playerInstance.on('ready', () => { + const root = playerInstance.template?.$player; + // Default the resolution menu to its "Auto" (ABR) entry instead of a fixed + // rung. The plugin tags each entry with data-value; Auto is value -1. Clicking + // it runs the plugin's own onSelect, which puts hls.js in auto mode and marks + // Auto as the selected item in both the control bar and the settings panel. + const autoItem = root?.querySelector('.art-control-hls-quality .art-selector-item[data-value="-1"]'); + if (autoItem) autoItem.click(); + // The native source (视角) control and the plugin resolution control get + // inserted in opposite DOM order under live vs archive mode, so their + // left/right positions flip. Force the archive layout in both: source + // selector on the left, resolution on the right. + const sourceCtrl = root?.querySelector('.art-control-quality'); + const resCtrl = root?.querySelector('.art-control-hls-quality'); + if (sourceCtrl && resCtrl && sourceCtrl.parentNode === resCtrl.parentNode) { + resCtrl.parentNode.insertBefore(sourceCtrl, resCtrl); + } + }); startPlaybackMonitor(data, password); } });