Skip to content

Instantly share code, notes, and snippets.

@affan2021shaikh
Last active April 24, 2026 01:22
Show Gist options
  • Select an option

  • Save affan2021shaikh/efa8b9f8c31b794d2d3b2a1b99928e0f to your computer and use it in GitHub Desktop.

Select an option

Save affan2021shaikh/efa8b9f8c31b794d2d3b2a1b99928e0f to your computer and use it in GitHub Desktop.

Revisions

  1. affan2021shaikh revised this gist Apr 24, 2026. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion YouTube Background Play Max.user.js
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@
    // @version 3.0.0
    // @description Best-effort background play for YouTube desktop and mobile web using only standard userscript features.
    // @author ChatGPT 5.3 Thinking
    // @downloadURL test
    // @downloadURL https://gist.github.com/affan2021shaikh/efa8b9f8c31b794d2d3b2a1b99928e0f/raw/YouTube%2520Background%2520Play%2520Max.user.js
    // @match https://www.youtube.com/*
    // @match https://m.youtube.com/*
    // @run-at document-start
  2. affan2021shaikh revised this gist Apr 24, 2026. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion DarkReader ES Module Equivalent.user.js
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@
    // @version 1.0
    // @description Use DarkReader in a cross-manager compatible way
    // @author ChatGPT 5.3
    // @downloadURL test
    // @downloadURL https://gist.github.com/affan2021shaikh/efa8b9f8c31b794d2d3b2a1b99928e0f/raw/DarkReader%2520ES%2520Module%2520Equivalent.user.js
    // @match *://*/*
    // @grant none
    // @require https://unpkg.com/darkreader/darkreader.min.js
  3. affan2021shaikh revised this gist Apr 24, 2026. 3 changed files with 49 additions and 485 deletions.
    484 changes: 0 additions & 484 deletions Dark Reader Everywhere.user.js
    Original file line number Diff line number Diff line change
    @@ -1,484 +0,0 @@
    // ==UserScript==
    // @name Dark Reader Everywhere
    // @namespace https://affan2021shaikh/
    // @version 2.0
    // @description Apply Dark Reader to every webpage with a small built-in control panel.
    // @match *://*/*
    // @run-at document-start
    // @noframes
    // @grant none
    // ==/UserScript==

    (() => {
    'use strict';

    const STORAGE_KEY = 'dr_everywhere_settings_v2';
    const PANEL_ID = 'dr-everywhere-panel';
    const BUTTON_ID = 'dr-everywhere-button';
    const STYLE_ID = 'dr-everywhere-style';
    const LIB_URLS = [
    'https://cdn.jsdelivr.net/npm/darkreader@latest/darkreader.min.js',
    'https://unpkg.com/darkreader@latest/darkreader.min.js'
    ];

    const DEFAULTS = {
    enabled: true,
    mode: 'enable', // "enable" or "auto"
    brightness: 100,
    contrast: 90,
    sepia: 10
    };

    let settings = loadSettings();
    let libLoadPromise = null;
    let panelOpen = false;

    function loadSettings() {
    try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (!raw) return { ...DEFAULTS };
    const parsed = JSON.parse(raw);
    return {
    ...DEFAULTS,
    ...parsed,
    enabled: !!parsed.enabled,
    mode: parsed.mode === 'auto' ? 'auto' : 'enable',
    brightness: clampNumber(parsed.brightness, 0, 200, DEFAULTS.brightness),
    contrast: clampNumber(parsed.contrast, 0, 200, DEFAULTS.contrast),
    sepia: clampNumber(parsed.sepia, 0, 100, DEFAULTS.sepia)
    };
    } catch {
    return { ...DEFAULTS };
    }
    }

    function saveSettings() {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
    }

    function clampNumber(value, min, max, fallback) {
    const n = Number(value);
    if (!Number.isFinite(n)) return fallback;
    return Math.min(max, Math.max(min, n));
    }

    function wait(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
    }

    async function loadDarkReader() {
    if (window.DarkReader) return window.DarkReader;
    if (libLoadPromise) return libLoadPromise;

    libLoadPromise = new Promise((resolve, reject) => {
    let index = 0;

    const tryNext = () => {
    if (window.DarkReader) {
    resolve(window.DarkReader);
    return;
    }

    if (index >= LIB_URLS.length) {
    reject(new Error('Failed to load Dark Reader from CDN.'));
    return;
    }

    const src = LIB_URLS[index++];
    const script = document.createElement('script');
    script.src = src;
    script.async = true;
    script.referrerPolicy = 'no-referrer';

    script.onload = () => {
    if (window.DarkReader) resolve(window.DarkReader);
    else tryNext();
    };

    script.onerror = () => {
    script.remove();
    tryNext();
    };

    (document.head || document.documentElement).appendChild(script);
    };

    tryNext();
    });

    return libLoadPromise;
    }

    async function applyDarkReader() {
    try {
    const DarkReader = await loadDarkReader();
    const config = {
    brightness: settings.brightness,
    contrast: settings.contrast,
    sepia: settings.sepia
    };

    if (!settings.enabled) {
    DarkReader.disable();
    } else if (settings.mode === 'auto') {
    DarkReader.auto(config);
    } else {
    DarkReader.enable(config);
    }

    updateStatusText();
    updateButtonText();
    } catch (err) {
    console.warn('[Dark Reader Everywhere] Could not load Dark Reader:', err);
    updateStatusText('Load failed');
    updateButtonText();
    }
    }

    function setEnabled(value) {
    settings.enabled = !!value;
    saveSettings();
    applyDarkReader();
    syncPanelFields();
    }

    function setMode(value) {
    settings.mode = value === 'auto' ? 'auto' : 'enable';
    saveSettings();
    applyDarkReader();
    syncPanelFields();
    }

    function setSetting(name, value) {
    settings[name] = value;
    saveSettings();
    applyDarkReader();
    syncPanelFields();
    }

    function ensureStyles() {
    if (document.getElementById(STYLE_ID)) return;
    const style = document.createElement('style');
    style.id = STYLE_ID;
    style.textContent = `
    #${BUTTON_ID} {
    position: fixed;
    right: 14px;
    bottom: 14px;
    z-index: 2147483647;
    border: 1px solid rgba(127,127,127,.35);
    border-radius: 999px;
    padding: 8px 12px;
    font: 13px/1.2 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    cursor: pointer;
    background: rgba(20,20,20,.88);
    color: #fff;
    box-shadow: 0 6px 24px rgba(0,0,0,.25);
    user-select: none;
    }
    #${PANEL_ID} {
    position: fixed;
    right: 14px;
    bottom: 56px;
    z-index: 2147483647;
    width: 300px;
    max-width: calc(100vw - 28px);
    background: rgba(20,20,20,.96);
    color: #fff;
    border: 1px solid rgba(127,127,127,.35);
    border-radius: 16px;
    box-shadow: 0 14px 40px rgba(0,0,0,.35);
    padding: 14px;
    font: 13px/1.35 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    }
    #${PANEL_ID} * {
    box-sizing: border-box;
    }
    #${PANEL_ID} .dr-row {
    margin: 10px 0;
    }
    #${PANEL_ID} .dr-title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    font-weight: 700;
    font-size: 14px;
    margin-bottom: 10px;
    }
    #${PANEL_ID} .dr-close {
    border: 0;
    border-radius: 8px;
    padding: 4px 8px;
    cursor: pointer;
    background: rgba(255,255,255,.12);
    color: #fff;
    }
    #${PANEL_ID} label {
    display: block;
    margin-bottom: 5px;
    opacity: .9;
    }
    #${PANEL_ID} input[type="range"] {
    width: 100%;
    }
    #${PANEL_ID} select,
    #${PANEL_ID} input[type="checkbox"] {
    vertical-align: middle;
    }
    #${PANEL_ID} .dr-inline {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    }
    #${PANEL_ID} .dr-small {
    opacity: .8;
    font-size: 12px;
    }
    #${PANEL_ID} .dr-actions {
    display: flex;
    gap: 8px;
    margin-top: 12px;
    }
    #${PANEL_ID} button {
    border: 0;
    border-radius: 10px;
    padding: 8px 10px;
    cursor: pointer;
    background: rgba(255,255,255,.12);
    color: #fff;
    }
    #${PANEL_ID} .dr-spacer {
    height: 1px;
    background: rgba(255,255,255,.1);
    margin: 10px 0;
    }
    #${PANEL_ID} .dr-value {
    font-variant-numeric: tabular-nums;
    opacity: .9;
    }
    `;
    (document.head || document.documentElement).appendChild(style);
    }

    function createUI() {
    if (document.getElementById(BUTTON_ID)) return;

    ensureStyles();

    const button = document.createElement('button');
    button.id = BUTTON_ID;
    button.type = 'button';
    button.textContent = 'Dark Reader';
    button.addEventListener('click', () => togglePanel());
    document.documentElement.appendChild(button);

    const panel = document.createElement('div');
    panel.id = PANEL_ID;
    panel.style.display = 'none';
    panel.innerHTML = `
    <div class="dr-title">
    <span>Dark Reader</span>
    <button class="dr-close" type="button" aria-label="Close">✕</button>
    </div>
    <div class="dr-row dr-inline">
    <label style="margin:0;">
    <input id="dr-enabled" type="checkbox">
    Enabled
    </label>
    <span id="dr-status" class="dr-small">Loading…</span>
    </div>
    <div class="dr-row">
    <label for="dr-mode">Mode</label>
    <select id="dr-mode" style="width:100%;padding:8px;border-radius:10px;border:1px solid rgba(255,255,255,.15);background:rgba(255,255,255,.08);color:#fff;">
    <option value="enable">Always on</option>
    <option value="auto">Follow system theme</option>
    </select>
    </div>
    <div class="dr-spacer"></div>
    <div class="dr-row">
    <div class="dr-inline">
    <label for="dr-brightness">Brightness</label>
    <span class="dr-value" id="dr-brightness-value"></span>
    </div>
    <input id="dr-brightness" type="range" min="0" max="200" step="1">
    </div>
    <div class="dr-row">
    <div class="dr-inline">
    <label for="dr-contrast">Contrast</label>
    <span class="dr-value" id="dr-contrast-value"></span>
    </div>
    <input id="dr-contrast" type="range" min="0" max="200" step="1">
    </div>
    <div class="dr-row">
    <div class="dr-inline">
    <label for="dr-sepia">Sepia</label>
    <span class="dr-value" id="dr-sepia-value"></span>
    </div>
    <input id="dr-sepia" type="range" min="0" max="100" step="1">
    </div>
    <div class="dr-actions">
    <button id="dr-toggle" type="button">Toggle</button>
    <button id="dr-reset" type="button">Reset</button>
    </div>
    <div class="dr-row dr-small" style="margin-top:10px;">
    Shortcut: Alt+Shift+D
    </div>
    `;
    document.documentElement.appendChild(panel);

    const closeBtn = panel.querySelector('.dr-close');
    const enabledEl = panel.querySelector('#dr-enabled');
    const modeEl = panel.querySelector('#dr-mode');
    const brightnessEl = panel.querySelector('#dr-brightness');
    const contrastEl = panel.querySelector('#dr-contrast');
    const sepiaEl = panel.querySelector('#dr-sepia');
    const brightnessValue = panel.querySelector('#dr-brightness-value');
    const contrastValue = panel.querySelector('#dr-contrast-value');
    const sepiaValue = panel.querySelector('#dr-sepia-value');
    const statusEl = panel.querySelector('#dr-status');
    const toggleBtn = panel.querySelector('#dr-toggle');
    const resetBtn = panel.querySelector('#dr-reset');

    closeBtn.addEventListener('click', () => togglePanel(false));
    enabledEl.addEventListener('change', () => setEnabled(enabledEl.checked));
    modeEl.addEventListener('change', () => setMode(modeEl.value));
    brightnessEl.addEventListener('input', () => setSetting('brightness', clampNumber(brightnessEl.value, 0, 200, DEFAULTS.brightness)));
    contrastEl.addEventListener('input', () => setSetting('contrast', clampNumber(contrastEl.value, 0, 200, DEFAULTS.contrast)));
    sepiaEl.addEventListener('input', () => setSetting('sepia', clampNumber(sepiaEl.value, 0, 100, DEFAULTS.sepia)));
    toggleBtn.addEventListener('click', () => setEnabled(!settings.enabled));
    resetBtn.addEventListener('click', () => {
    settings = { ...DEFAULTS };
    saveSettings();
    syncPanelFields();
    applyDarkReader();
    });

    function updateStatusText(text) {
    statusEl.textContent = text || (settings.enabled ? 'On' : 'Off');
    }

    function updateButtonText() {
    button.textContent = settings.enabled ? 'Dark Reader ✓' : 'Dark Reader';
    }

    function syncPanelFields() {
    enabledEl.checked = settings.enabled;
    modeEl.value = settings.mode;
    brightnessEl.value = String(settings.brightness);
    contrastEl.value = String(settings.contrast);
    sepiaEl.value = String(settings.sepia);
    brightnessValue.textContent = String(settings.brightness);
    contrastValue.textContent = String(settings.contrast);
    sepiaValue.textContent = String(settings.sepia);
    updateStatusText();
    updateButtonText();
    }

    window.__dr_everywhere_ui = {
    panel,
    button,
    syncPanelFields,
    updateStatusText,
    updateButtonText
    };

    syncPanelFields();
    }

    function syncPanelFields() {
    const ui = window.__dr_everywhere_ui;
    if (ui && ui.syncPanelFields) ui.syncPanelFields();
    }

    function updateStatusText(text) {
    const ui = window.__dr_everywhere_ui;
    if (ui && ui.updateStatusText) ui.updateStatusText(text);
    }

    function updateButtonText() {
    const ui = window.__dr_everywhere_ui;
    if (ui && ui.updateButtonText) ui.updateButtonText();
    }

    function togglePanel(force) {
    createUI();
    const ui = window.__dr_everywhere_ui;
    if (!ui) return;

    panelOpen = typeof force === 'boolean' ? force : !panelOpen;
    ui.panel.style.display = panelOpen ? 'block' : 'none';
    }

    function installKeyboardShortcuts() {
    window.addEventListener('keydown', (e) => {
    if (e.altKey && e.shiftKey && e.code === 'KeyD') {
    e.preventDefault();
    setEnabled(!settings.enabled);
    }
    if (e.altKey && e.shiftKey && e.code === 'KeyS') {
    e.preventDefault();
    togglePanel();
    }
    if (e.key === 'Escape' && panelOpen) {
    togglePanel(false);
    }
    }, true);
    }

    async function init() {
    createUI();
    installKeyboardShortcuts();

    // Give the page a moment to build its DOM, then apply the theme.
    await wait(0);
    await applyDarkReader();

    // Re-apply if the page changes heavily and the library is already loaded.
    const observer = new MutationObserver(() => {
    if (settings.enabled && window.DarkReader) {
    // Keep this lightweight: just ensure it stays on.
    if (!window.DarkReader.isEnabled || !window.DarkReader.isEnabled()) {
    applyDarkReader();
    }
    }
    });

    observer.observe(document.documentElement, { childList: true, subtree: true });

    window.addEventListener('beforeunload', () => {
    try {
    observer.disconnect();
    } catch {}
    });
    }

    if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init, { once: true });
    } else {
    init();
    }
    })();
    46 changes: 46 additions & 0 deletions DarkReader ES Module Equivalent.user.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,46 @@
    // ==UserScript==
    // @name DarkReader ES Module Equivalent
    // @namespace affan2021shaikh
    // @version 1.0
    // @description Use DarkReader in a cross-manager compatible way
    // @author ChatGPT 5.3
    // @downloadURL test
    // @match *://*/*
    // @grant none
    // @require https://unpkg.com/darkreader/darkreader.min.js
    // ==/UserScript==

    (function () {
    'use strict';

    // DarkReader is exposed globally
    const {
    enable: enableDarkMode,
    disable: disableDarkMode,
    auto: followSystemColorScheme,
    exportGeneratedCSS: collectCSS,
    isEnabled: isDarkReaderEnabled
    } = DarkReader;

    // Enable dark mode
    enableDarkMode({
    brightness: 100,
    contrast: 90,
    sepia: 10,
    });

    // Disable (example call)
    disableDarkMode();

    // Follow system scheme
    followSystemColorScheme();

    // Async call wrapped properly (no top-level await)
    (async () => {
    const CSS = await collectCSS();
    console.log('Generated CSS:', CSS);

    const isEnabled = isDarkReaderEnabled();
    console.log('Is enabled:', isEnabled);
    })();
    })();
    4 changes: 3 additions & 1 deletion YouTube Background Play Max.user.js
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,10 @@
    // ==UserScript==
    // @name YouTube Background Play Max
    // @namespace https://example.invalid/
    // @namespace affan2021shaikh
    // @version 3.0.0
    // @description Best-effort background play for YouTube desktop and mobile web using only standard userscript features.
    // @author ChatGPT 5.3 Thinking
    // @downloadURL test
    // @match https://www.youtube.com/*
    // @match https://m.youtube.com/*
    // @run-at document-start
  4. affan2021shaikh revised this gist Apr 17, 2026. 2 changed files with 1 addition and 2 deletions.
    2 changes: 1 addition & 1 deletion Dark Reader Everywhere.user.js
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    // ==UserScript==
    // @name Dark Reader Everywhere
    // @namespace https://example.com/
    // @namespace https://affan2021shaikh/
    // @version 2.0
    // @description Apply Dark Reader to every webpage with a small built-in control panel.
    // @match *://*/*
    1 change: 0 additions & 1 deletion Userscripts Installation Links
    Original file line number Diff line number Diff line change
    @@ -1 +0,0 @@
    hello
  5. affan2021shaikh revised this gist Apr 17, 2026. 1 changed file with 1 addition and 0 deletions.
    1 change: 1 addition & 0 deletions Userscripts Installation Links
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    hello
  6. affan2021shaikh revised this gist Apr 17, 2026. 1 changed file with 484 additions and 0 deletions.
    484 changes: 484 additions & 0 deletions Dark Reader Everywhere.user.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,484 @@
    // ==UserScript==
    // @name Dark Reader Everywhere
    // @namespace https://example.com/
    // @version 2.0
    // @description Apply Dark Reader to every webpage with a small built-in control panel.
    // @match *://*/*
    // @run-at document-start
    // @noframes
    // @grant none
    // ==/UserScript==

    (() => {
    'use strict';

    const STORAGE_KEY = 'dr_everywhere_settings_v2';
    const PANEL_ID = 'dr-everywhere-panel';
    const BUTTON_ID = 'dr-everywhere-button';
    const STYLE_ID = 'dr-everywhere-style';
    const LIB_URLS = [
    'https://cdn.jsdelivr.net/npm/darkreader@latest/darkreader.min.js',
    'https://unpkg.com/darkreader@latest/darkreader.min.js'
    ];

    const DEFAULTS = {
    enabled: true,
    mode: 'enable', // "enable" or "auto"
    brightness: 100,
    contrast: 90,
    sepia: 10
    };

    let settings = loadSettings();
    let libLoadPromise = null;
    let panelOpen = false;

    function loadSettings() {
    try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (!raw) return { ...DEFAULTS };
    const parsed = JSON.parse(raw);
    return {
    ...DEFAULTS,
    ...parsed,
    enabled: !!parsed.enabled,
    mode: parsed.mode === 'auto' ? 'auto' : 'enable',
    brightness: clampNumber(parsed.brightness, 0, 200, DEFAULTS.brightness),
    contrast: clampNumber(parsed.contrast, 0, 200, DEFAULTS.contrast),
    sepia: clampNumber(parsed.sepia, 0, 100, DEFAULTS.sepia)
    };
    } catch {
    return { ...DEFAULTS };
    }
    }

    function saveSettings() {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
    }

    function clampNumber(value, min, max, fallback) {
    const n = Number(value);
    if (!Number.isFinite(n)) return fallback;
    return Math.min(max, Math.max(min, n));
    }

    function wait(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
    }

    async function loadDarkReader() {
    if (window.DarkReader) return window.DarkReader;
    if (libLoadPromise) return libLoadPromise;

    libLoadPromise = new Promise((resolve, reject) => {
    let index = 0;

    const tryNext = () => {
    if (window.DarkReader) {
    resolve(window.DarkReader);
    return;
    }

    if (index >= LIB_URLS.length) {
    reject(new Error('Failed to load Dark Reader from CDN.'));
    return;
    }

    const src = LIB_URLS[index++];
    const script = document.createElement('script');
    script.src = src;
    script.async = true;
    script.referrerPolicy = 'no-referrer';

    script.onload = () => {
    if (window.DarkReader) resolve(window.DarkReader);
    else tryNext();
    };

    script.onerror = () => {
    script.remove();
    tryNext();
    };

    (document.head || document.documentElement).appendChild(script);
    };

    tryNext();
    });

    return libLoadPromise;
    }

    async function applyDarkReader() {
    try {
    const DarkReader = await loadDarkReader();
    const config = {
    brightness: settings.brightness,
    contrast: settings.contrast,
    sepia: settings.sepia
    };

    if (!settings.enabled) {
    DarkReader.disable();
    } else if (settings.mode === 'auto') {
    DarkReader.auto(config);
    } else {
    DarkReader.enable(config);
    }

    updateStatusText();
    updateButtonText();
    } catch (err) {
    console.warn('[Dark Reader Everywhere] Could not load Dark Reader:', err);
    updateStatusText('Load failed');
    updateButtonText();
    }
    }

    function setEnabled(value) {
    settings.enabled = !!value;
    saveSettings();
    applyDarkReader();
    syncPanelFields();
    }

    function setMode(value) {
    settings.mode = value === 'auto' ? 'auto' : 'enable';
    saveSettings();
    applyDarkReader();
    syncPanelFields();
    }

    function setSetting(name, value) {
    settings[name] = value;
    saveSettings();
    applyDarkReader();
    syncPanelFields();
    }

    function ensureStyles() {
    if (document.getElementById(STYLE_ID)) return;
    const style = document.createElement('style');
    style.id = STYLE_ID;
    style.textContent = `
    #${BUTTON_ID} {
    position: fixed;
    right: 14px;
    bottom: 14px;
    z-index: 2147483647;
    border: 1px solid rgba(127,127,127,.35);
    border-radius: 999px;
    padding: 8px 12px;
    font: 13px/1.2 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    cursor: pointer;
    background: rgba(20,20,20,.88);
    color: #fff;
    box-shadow: 0 6px 24px rgba(0,0,0,.25);
    user-select: none;
    }
    #${PANEL_ID} {
    position: fixed;
    right: 14px;
    bottom: 56px;
    z-index: 2147483647;
    width: 300px;
    max-width: calc(100vw - 28px);
    background: rgba(20,20,20,.96);
    color: #fff;
    border: 1px solid rgba(127,127,127,.35);
    border-radius: 16px;
    box-shadow: 0 14px 40px rgba(0,0,0,.35);
    padding: 14px;
    font: 13px/1.35 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    }
    #${PANEL_ID} * {
    box-sizing: border-box;
    }
    #${PANEL_ID} .dr-row {
    margin: 10px 0;
    }
    #${PANEL_ID} .dr-title {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    font-weight: 700;
    font-size: 14px;
    margin-bottom: 10px;
    }
    #${PANEL_ID} .dr-close {
    border: 0;
    border-radius: 8px;
    padding: 4px 8px;
    cursor: pointer;
    background: rgba(255,255,255,.12);
    color: #fff;
    }
    #${PANEL_ID} label {
    display: block;
    margin-bottom: 5px;
    opacity: .9;
    }
    #${PANEL_ID} input[type="range"] {
    width: 100%;
    }
    #${PANEL_ID} select,
    #${PANEL_ID} input[type="checkbox"] {
    vertical-align: middle;
    }
    #${PANEL_ID} .dr-inline {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    }
    #${PANEL_ID} .dr-small {
    opacity: .8;
    font-size: 12px;
    }
    #${PANEL_ID} .dr-actions {
    display: flex;
    gap: 8px;
    margin-top: 12px;
    }
    #${PANEL_ID} button {
    border: 0;
    border-radius: 10px;
    padding: 8px 10px;
    cursor: pointer;
    background: rgba(255,255,255,.12);
    color: #fff;
    }
    #${PANEL_ID} .dr-spacer {
    height: 1px;
    background: rgba(255,255,255,.1);
    margin: 10px 0;
    }
    #${PANEL_ID} .dr-value {
    font-variant-numeric: tabular-nums;
    opacity: .9;
    }
    `;
    (document.head || document.documentElement).appendChild(style);
    }

    function createUI() {
    if (document.getElementById(BUTTON_ID)) return;

    ensureStyles();

    const button = document.createElement('button');
    button.id = BUTTON_ID;
    button.type = 'button';
    button.textContent = 'Dark Reader';
    button.addEventListener('click', () => togglePanel());
    document.documentElement.appendChild(button);

    const panel = document.createElement('div');
    panel.id = PANEL_ID;
    panel.style.display = 'none';
    panel.innerHTML = `
    <div class="dr-title">
    <span>Dark Reader</span>
    <button class="dr-close" type="button" aria-label="Close">✕</button>
    </div>
    <div class="dr-row dr-inline">
    <label style="margin:0;">
    <input id="dr-enabled" type="checkbox">
    Enabled
    </label>
    <span id="dr-status" class="dr-small">Loading…</span>
    </div>
    <div class="dr-row">
    <label for="dr-mode">Mode</label>
    <select id="dr-mode" style="width:100%;padding:8px;border-radius:10px;border:1px solid rgba(255,255,255,.15);background:rgba(255,255,255,.08);color:#fff;">
    <option value="enable">Always on</option>
    <option value="auto">Follow system theme</option>
    </select>
    </div>
    <div class="dr-spacer"></div>
    <div class="dr-row">
    <div class="dr-inline">
    <label for="dr-brightness">Brightness</label>
    <span class="dr-value" id="dr-brightness-value"></span>
    </div>
    <input id="dr-brightness" type="range" min="0" max="200" step="1">
    </div>
    <div class="dr-row">
    <div class="dr-inline">
    <label for="dr-contrast">Contrast</label>
    <span class="dr-value" id="dr-contrast-value"></span>
    </div>
    <input id="dr-contrast" type="range" min="0" max="200" step="1">
    </div>
    <div class="dr-row">
    <div class="dr-inline">
    <label for="dr-sepia">Sepia</label>
    <span class="dr-value" id="dr-sepia-value"></span>
    </div>
    <input id="dr-sepia" type="range" min="0" max="100" step="1">
    </div>
    <div class="dr-actions">
    <button id="dr-toggle" type="button">Toggle</button>
    <button id="dr-reset" type="button">Reset</button>
    </div>
    <div class="dr-row dr-small" style="margin-top:10px;">
    Shortcut: Alt+Shift+D
    </div>
    `;
    document.documentElement.appendChild(panel);

    const closeBtn = panel.querySelector('.dr-close');
    const enabledEl = panel.querySelector('#dr-enabled');
    const modeEl = panel.querySelector('#dr-mode');
    const brightnessEl = panel.querySelector('#dr-brightness');
    const contrastEl = panel.querySelector('#dr-contrast');
    const sepiaEl = panel.querySelector('#dr-sepia');
    const brightnessValue = panel.querySelector('#dr-brightness-value');
    const contrastValue = panel.querySelector('#dr-contrast-value');
    const sepiaValue = panel.querySelector('#dr-sepia-value');
    const statusEl = panel.querySelector('#dr-status');
    const toggleBtn = panel.querySelector('#dr-toggle');
    const resetBtn = panel.querySelector('#dr-reset');

    closeBtn.addEventListener('click', () => togglePanel(false));
    enabledEl.addEventListener('change', () => setEnabled(enabledEl.checked));
    modeEl.addEventListener('change', () => setMode(modeEl.value));
    brightnessEl.addEventListener('input', () => setSetting('brightness', clampNumber(brightnessEl.value, 0, 200, DEFAULTS.brightness)));
    contrastEl.addEventListener('input', () => setSetting('contrast', clampNumber(contrastEl.value, 0, 200, DEFAULTS.contrast)));
    sepiaEl.addEventListener('input', () => setSetting('sepia', clampNumber(sepiaEl.value, 0, 100, DEFAULTS.sepia)));
    toggleBtn.addEventListener('click', () => setEnabled(!settings.enabled));
    resetBtn.addEventListener('click', () => {
    settings = { ...DEFAULTS };
    saveSettings();
    syncPanelFields();
    applyDarkReader();
    });

    function updateStatusText(text) {
    statusEl.textContent = text || (settings.enabled ? 'On' : 'Off');
    }

    function updateButtonText() {
    button.textContent = settings.enabled ? 'Dark Reader ✓' : 'Dark Reader';
    }

    function syncPanelFields() {
    enabledEl.checked = settings.enabled;
    modeEl.value = settings.mode;
    brightnessEl.value = String(settings.brightness);
    contrastEl.value = String(settings.contrast);
    sepiaEl.value = String(settings.sepia);
    brightnessValue.textContent = String(settings.brightness);
    contrastValue.textContent = String(settings.contrast);
    sepiaValue.textContent = String(settings.sepia);
    updateStatusText();
    updateButtonText();
    }

    window.__dr_everywhere_ui = {
    panel,
    button,
    syncPanelFields,
    updateStatusText,
    updateButtonText
    };

    syncPanelFields();
    }

    function syncPanelFields() {
    const ui = window.__dr_everywhere_ui;
    if (ui && ui.syncPanelFields) ui.syncPanelFields();
    }

    function updateStatusText(text) {
    const ui = window.__dr_everywhere_ui;
    if (ui && ui.updateStatusText) ui.updateStatusText(text);
    }

    function updateButtonText() {
    const ui = window.__dr_everywhere_ui;
    if (ui && ui.updateButtonText) ui.updateButtonText();
    }

    function togglePanel(force) {
    createUI();
    const ui = window.__dr_everywhere_ui;
    if (!ui) return;

    panelOpen = typeof force === 'boolean' ? force : !panelOpen;
    ui.panel.style.display = panelOpen ? 'block' : 'none';
    }

    function installKeyboardShortcuts() {
    window.addEventListener('keydown', (e) => {
    if (e.altKey && e.shiftKey && e.code === 'KeyD') {
    e.preventDefault();
    setEnabled(!settings.enabled);
    }
    if (e.altKey && e.shiftKey && e.code === 'KeyS') {
    e.preventDefault();
    togglePanel();
    }
    if (e.key === 'Escape' && panelOpen) {
    togglePanel(false);
    }
    }, true);
    }

    async function init() {
    createUI();
    installKeyboardShortcuts();

    // Give the page a moment to build its DOM, then apply the theme.
    await wait(0);
    await applyDarkReader();

    // Re-apply if the page changes heavily and the library is already loaded.
    const observer = new MutationObserver(() => {
    if (settings.enabled && window.DarkReader) {
    // Keep this lightweight: just ensure it stays on.
    if (!window.DarkReader.isEnabled || !window.DarkReader.isEnabled()) {
    applyDarkReader();
    }
    }
    });

    observer.observe(document.documentElement, { childList: true, subtree: true });

    window.addEventListener('beforeunload', () => {
    try {
    observer.disconnect();
    } catch {}
    });
    }

    if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', init, { once: true });
    } else {
    init();
    }
    })();
  7. affan2021shaikh revised this gist Apr 16, 2026. 2 changed files with 905 additions and 467 deletions.
    905 changes: 905 additions & 0 deletions YouTube Background Play Max.user.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,905 @@
    // ==UserScript==
    // @name YouTube Background Play Max
    // @namespace https://example.invalid/
    // @version 3.0.0
    // @description Best-effort background play for YouTube desktop and mobile web using only standard userscript features.
    // @match https://www.youtube.com/*
    // @match https://m.youtube.com/*
    // @run-at document-start
    // @grant none
    // @noframes
    // ==/UserScript==

    (() => {
    'use strict';

    const CFG = {
    debug: false,

    manualGraceMs: 1200,

    hiddenRetryMs: 200,
    visibleRetryMs: 350,
    maxRetryMs: 5000,

    hiddenRetryWindowMs: 30000,

    visibilitySpoof: true,
    mediaSession: true,
    audioKeepalive: true,
    pipFallback: true,
    mutedFallback: true,

    pipRetryCooldownMs: 15000,
    mutedRetryCooldownMs: 10000,
    restoreMuteAfterMs: 1200,
    };

    const log = (...args) => {
    if (CFG.debug) console.log('[YT BG Play Max]', ...args);
    };

    const SEL = [
    '#movie_player video',
    'ytd-player video',
    'video.html5-main-video',
    'video',
    ];

    const CONTROL_SEL = [
    '.ytp-play-button',
    '.ytp-big-mode-play-button',
    'button',
    '[role="button"]',
    'tp-yt-paper-icon-button',
    'yt-icon-button',
    ].join(',');

    const STATE = {
    currentVideo: null,
    desiredPlaying: false,

    lastGestureAt: 0,
    lastExplicitPlayPauseAt: 0,
    lastManualPauseAt: 0,

    hiddenSince: 0,

    retryTimer: 0,
    retryDelay: CFG.visibleRetryMs,
    playInFlight: false,
    booted: false,
    observerStarted: false,
    frameLoopStarted: false,

    failures: 0,

    lastPipAttemptAt: 0,
    lastMutedFallbackAt: 0,

    media: {
    ctx: null,
    oscillator: null,
    gain: null,
    unlocked: false,
    },

    originals: {
    hidden: null,
    visibilityState: null,
    webkitHidden: null,
    webkitVisibilityState: null,
    hasFocus: null,
    },
    };

    const now = () => Date.now();

    function isElement(v) {
    return v && v.nodeType === 1;
    }

    function isTypingTarget(target) {
    if (!isElement(target)) return false;
    const tag = target.tagName;
    return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || target.isContentEditable;
    }

    function getDescriptor(proto, prop) {
    let p = proto;
    while (p) {
    const d = Object.getOwnPropertyDescriptor(p, prop);
    if (d) return d;
    p = Object.getPrototypeOf(p);
    }
    return null;
    }

    function readActualHidden() {
    try {
    const d = STATE.originals.hidden;
    if (d && typeof d.get === 'function') return !!d.get.call(document);
    } catch (_) {}
    try {
    const d = STATE.originals.webkitHidden;
    if (d && typeof d.get === 'function') return !!d.get.call(document);
    } catch (_) {}
    try {
    return document.visibilityState !== 'visible';
    } catch (_) {
    return false;
    }
    }

    function readActualVisibilityState() {
    try {
    const d = STATE.originals.visibilityState;
    if (d && typeof d.get === 'function') return String(d.get.call(document));
    } catch (_) {}
    try {
    const d = STATE.originals.webkitVisibilityState;
    if (d && typeof d.get === 'function') return String(d.get.call(document));
    } catch (_) {}
    return readActualHidden() ? 'hidden' : 'visible';
    }

    function isActuallyHidden() {
    return readActualVisibilityState() !== 'visible';
    }

    function installVisibilitySpoof() {
    if (!CFG.visibilitySpoof) return;

    const proto = Document.prototype;

    STATE.originals.hidden = getDescriptor(proto, 'hidden');
    STATE.originals.visibilityState = getDescriptor(proto, 'visibilityState');
    STATE.originals.webkitHidden = getDescriptor(proto, 'webkitHidden');
    STATE.originals.webkitVisibilityState = getDescriptor(proto, 'webkitVisibilityState');
    STATE.originals.hasFocus = getDescriptor(proto, 'hasFocus');

    const installGetter = (prop, getter, original) => {
    try {
    if (original && original.configurable === false) return false;
    Object.defineProperty(proto, prop, {
    configurable: true,
    enumerable: original ? !!original.enumerable : false,
    get: getter,
    });
    return true;
    } catch (_) {
    return false;
    }
    };

    installGetter('hidden', function () {
    return false;
    }, STATE.originals.hidden);

    installGetter('visibilityState', function () {
    return 'visible';
    }, STATE.originals.visibilityState);

    installGetter('webkitHidden', function () {
    return false;
    }, STATE.originals.webkitHidden);

    installGetter('webkitVisibilityState', function () {
    return 'visible';
    }, STATE.originals.webkitVisibilityState);

    try {
    const original = STATE.originals.hasFocus;
    if (!original || original.configurable !== false) {
    Object.defineProperty(proto, 'hasFocus', {
    configurable: true,
    enumerable: original ? !!original.enumerable : false,
    writable: true,
    value: function () {
    return true;
    },
    });
    }
    } catch (_) {}
    }

    function setMediaSessionState() {
    if (!CFG.mediaSession) return;
    try {
    if (!('mediaSession' in navigator)) return;
    navigator.mediaSession.playbackState = STATE.desiredPlaying ? 'playing' : 'paused';
    } catch (_) {}
    }

    function stopKeepaliveAudio() {
    const m = STATE.media;
    try {
    if (m.ctx && m.ctx.state === 'running') {
    m.ctx.suspend().catch(() => {});
    }
    } catch (_) {}
    }

    function startKeepaliveAudio() {
    if (!CFG.audioKeepalive) return;
    if (!STATE.desiredPlaying) return;
    if (!isActuallyHidden()) {
    stopKeepaliveAudio();
    return;
    }

    const m = STATE.media;
    try {
    const AudioCtx = window.AudioContext || window.webkitAudioContext;
    if (!AudioCtx) return;

    if (!m.ctx) {
    m.ctx = new AudioCtx();
    m.gain = m.ctx.createGain();
    m.gain.gain.value = 0.00001;

    m.oscillator = m.ctx.createOscillator();
    m.oscillator.type = 'sine';
    m.oscillator.frequency.value = 40;

    m.oscillator.connect(m.gain);
    m.gain.connect(m.ctx.destination);
    m.oscillator.start();
    }

    if (m.ctx.state === 'suspended') {
    m.ctx.resume().catch(() => {});
    }
    } catch (_) {}
    }

    function unlockKeepaliveAudio() {
    if (!CFG.audioKeepalive) return;
    const m = STATE.media;
    m.unlocked = true;
    if (m.ctx && m.ctx.state === 'suspended') {
    m.ctx.resume().catch(() => {});
    }
    }

    function maybeStartKeepaliveAudio() {
    if (!CFG.audioKeepalive) return;
    if (!STATE.media.unlocked) return;
    startKeepaliveAudio();
    }

    function setDesiredPlaying(next, reason) {
    const changed = STATE.desiredPlaying !== next;
    STATE.desiredPlaying = next;

    if (next) {
    setMediaSessionState();
    maybeStartKeepaliveAudio();
    if (changed) scheduleRetry(reason || 'intent', true);
    } else {
    setMediaSessionState();
    stopKeepaliveAudio();
    clearTimeout(STATE.retryTimer);
    }
    }

    function manualGraceActive() {
    const t = now();
    const recent = Math.max(STATE.lastGestureAt, STATE.lastExplicitPlayPauseAt, STATE.lastManualPauseAt);
    return (t - recent) <= CFG.manualGraceMs;
    }

    function touchGesture(event) {
    STATE.lastGestureAt = now();

    if (isTypingTarget(event && event.target)) return;
    unlockKeepaliveAudio();
    }

    function inferControlIntent(event) {
    const target = event && event.target;
    if (!isElement(target)) return null;

    const control = target.closest('.ytp-play-button, .ytp-big-mode-play-button');
    if (control) {
    const label = [
    control.getAttribute('aria-label'),
    control.getAttribute('title'),
    control.getAttribute('data-title-no-tooltip'),
    control.textContent,
    ].filter(Boolean).join(' ').toLowerCase();

    if (label.includes('pause') && !label.includes('play')) return 'pause';
    if (label.includes('play') && !label.includes('pause')) return 'play';

    if (STATE.currentVideo) {
    return STATE.currentVideo.paused ? 'play' : 'pause';
    }
    }

    return null;
    }

    function onPointerLike(event) {
    touchGesture(event);

    const intent = inferControlIntent(event);
    if (intent === 'play') {
    STATE.lastExplicitPlayPauseAt = now();
    setDesiredPlaying(true, 'user-play');
    } else if (intent === 'pause') {
    STATE.lastExplicitPlayPauseAt = now();
    STATE.lastManualPauseAt = now();
    setDesiredPlaying(false, 'user-pause');
    }
    }

    function onKeydown(event) {
    if (event.repeat) return;
    if (isTypingTarget(event.target)) return;

    touchGesture(event);

    const key = String(event.key || '').toLowerCase();
    const mediaKey = key === 'mediaplaypause' || key === 'mediaplay' || key === 'play';
    const pauseKey = key === 'mediapause';

    if (mediaKey) {
    STATE.lastExplicitPlayPauseAt = now();
    setDesiredPlaying(true, 'media-key-play');
    return;
    }

    if (pauseKey) {
    STATE.lastExplicitPlayPauseAt = now();
    STATE.lastManualPauseAt = now();
    setDesiredPlaying(false, 'media-key-pause');
    return;
    }

    if (key === ' ' || key === 'spacebar' || key === 'k') {
    STATE.lastExplicitPlayPauseAt = now();
    if (STATE.currentVideo && !STATE.currentVideo.paused) {
    STATE.lastManualPauseAt = now();
    setDesiredPlaying(false, 'toggle-pause');
    } else {
    setDesiredPlaying(true, 'toggle-play');
    }
    }
    }

    function scoreVideo(v) {
    if (!(v instanceof HTMLVideoElement) || !v.isConnected) return -1e18;

    const r = v.getBoundingClientRect();
    const area = Math.max(0, r.width) * Math.max(0, r.height);

    let score = area;

    if (r.width > 0 && r.height > 0) score += 1_000_000;
    if (!v.paused) score += 250_000;
    if (v.readyState >= 2) score += 15_000;
    if (v.currentSrc) score += 5_000;
    if (document.body && document.body.contains(v)) score += 2_000;

    if (v.matches('.html5-main-video')) score += 250_000;
    if (v.closest('#movie_player')) score += 175_000;
    if (v.closest('ytd-player')) score += 125_000;
    if (v.closest('.html5-video-container')) score += 75_000;

    return score;
    }

    function pickVideo() {
    const seen = new Set();
    const candidates = [];

    for (const sel of SEL) {
    for (const v of document.querySelectorAll(sel)) {
    if (!seen.has(v)) {
    seen.add(v);
    candidates.push(v);
    }
    }
    }

    let best = null;
    let bestScore = -1e18;

    for (const v of candidates) {
    const s = scoreVideo(v);
    if (s > bestScore) {
    bestScore = s;
    best = v;
    }
    }

    return best;
    }

    function attachVideo(v) {
    if (!(v instanceof HTMLVideoElement)) return;
    if (v === STATE.currentVideo) return;

    if (STATE.currentVideo) {
    STATE.currentVideo.removeEventListener('play', onPlay, true);
    STATE.currentVideo.removeEventListener('playing', onPlaying, true);
    STATE.currentVideo.removeEventListener('pause', onPause, true);
    STATE.currentVideo.removeEventListener('ended', onEnded, true);
    STATE.currentVideo.removeEventListener('emptied', onVideoSourceChange, true);
    STATE.currentVideo.removeEventListener('loadstart', onVideoSourceChange, true);
    STATE.currentVideo.removeEventListener('loadedmetadata', onVideoSourceChange, true);
    STATE.currentVideo.removeEventListener('stalled', onNeedRetry, true);
    STATE.currentVideo.removeEventListener('waiting', onNeedRetry, true);
    STATE.currentVideo.removeEventListener('suspend', onNeedRetry, true);
    STATE.currentVideo.removeEventListener('canplay', onNeedRetry, true);
    }

    STATE.currentVideo = v;

    try {
    STATE.currentVideo.setAttribute('playsinline', '');
    STATE.currentVideo.setAttribute('webkit-playsinline', '');
    } catch (_) {}

    STATE.currentVideo.addEventListener('play', onPlay, true);
    STATE.currentVideo.addEventListener('playing', onPlaying, true);
    STATE.currentVideo.addEventListener('pause', onPause, true);
    STATE.currentVideo.addEventListener('ended', onEnded, true);
    STATE.currentVideo.addEventListener('emptied', onVideoSourceChange, true);
    STATE.currentVideo.addEventListener('loadstart', onVideoSourceChange, true);
    STATE.currentVideo.addEventListener('loadedmetadata', onVideoSourceChange, true);
    STATE.currentVideo.addEventListener('stalled', onNeedRetry, true);
    STATE.currentVideo.addEventListener('waiting', onNeedRetry, true);
    STATE.currentVideo.addEventListener('suspend', onNeedRetry, true);
    STATE.currentVideo.addEventListener('canplay', onNeedRetry, true);

    log('attached video');
    }

    function syncVideo() {
    const best = pickVideo();
    if (best) attachVideo(best);
    }

    function resetRetryDelay() {
    STATE.retryDelay = isActuallyHidden() ? CFG.hiddenRetryMs : CFG.visibleRetryMs;
    }

    function bumpRetryDelay() {
    STATE.retryDelay = Math.min(Math.max(STATE.retryDelay * 1.5, 200), CFG.maxRetryMs);
    }

    async function tryPictureInPicture(reason) {
    if (!CFG.pipFallback) return false;
    if (!STATE.currentVideo || !STATE.desiredPlaying) return false;
    if (!STATE.currentVideo.isConnected) return false;
    if (!(location.hostname.startsWith('m.') || matchMedia('(pointer: coarse)').matches)) return false;
    if (!document.pictureInPictureEnabled) return false;
    if (document.pictureInPictureElement === STATE.currentVideo) return true;
    if (STATE.currentVideo.disablePictureInPicture) return false;

    const t = now();
    if (t - STATE.lastPipAttemptAt < CFG.pipRetryCooldownMs) return false;
    STATE.lastPipAttemptAt = t;

    try {
    if (typeof STATE.currentVideo.requestPictureInPicture !== 'function') return false;
    await STATE.currentVideo.requestPictureInPicture();
    log('pip ok', reason);
    return true;
    } catch (err) {
    log('pip failed', reason, err && err.name ? err.name : err);
    return false;
    }
    }

    async function tryMutedFallback(reason) {
    if (!CFG.mutedFallback) return false;
    if (!STATE.currentVideo || !STATE.desiredPlaying) return false;
    if (!STATE.currentVideo.isConnected) return false;
    if (STATE.currentVideo.muted) return false;

    const t = now();
    if (t - STATE.lastMutedFallbackAt < CFG.mutedRetryCooldownMs) return false;
    STATE.lastMutedFallbackAt = t;

    const prevMuted = STATE.currentVideo.muted;
    const prevVolume = STATE.currentVideo.volume;

    try {
    STATE.currentVideo.muted = true;
    const p = STATE.currentVideo.play();
    if (p && typeof p.then === 'function') {
    await p;
    }

    setTimeout(() => {
    try {
    if (!STATE.currentVideo || STATE.currentVideo.paused) return;
    if (!STATE.desiredPlaying) return;
    STATE.currentVideo.muted = prevMuted;
    STATE.currentVideo.volume = prevVolume;
    } catch (_) {}
    }, CFG.restoreMuteAfterMs);

    log('muted fallback ok', reason);
    return true;
    } catch (err) {
    try {
    if (STATE.currentVideo) {
    STATE.currentVideo.muted = prevMuted;
    STATE.currentVideo.volume = prevVolume;
    }
    } catch (_) {}
    log('muted fallback failed', reason, err && err.name ? err.name : err);
    return false;
    }
    }

    async function safePlay(reason) {
    if (!STATE.currentVideo || !STATE.desiredPlaying) return false;
    if (STATE.playInFlight) return true;

    STATE.playInFlight = true;

    try {
    if (!STATE.currentVideo.isConnected) {
    syncVideo();
    if (!STATE.currentVideo) return false;
    }

    if (!STATE.currentVideo.paused && STATE.currentVideo.readyState >= 2) {
    STATE.failures = 0;
    resetRetryDelay();
    maybeStartKeepaliveAudio();
    setMediaSessionState();
    return true;
    }

    try {
    const p = STATE.currentVideo.play();
    if (p && typeof p.then === 'function') {
    await p;
    }

    STATE.failures = 0;
    resetRetryDelay();
    maybeStartKeepaliveAudio();
    setMediaSessionState();
    log('play ok', reason);
    return true;
    } catch (err) {
    log('play failed', reason, err && err.name ? err.name : err);
    }

    STATE.failures += 1;
    bumpRetryDelay();

    if (STATE.failures >= 2) {
    const pipOk = await tryPictureInPicture(reason);
    if (pipOk) {
    STATE.failures = 0;
    resetRetryDelay();
    maybeStartKeepaliveAudio();
    setMediaSessionState();
    return true;
    }
    }

    if (STATE.failures >= 3) {
    const mutedOk = await tryMutedFallback(reason);
    if (mutedOk) {
    STATE.failures = 0;
    resetRetryDelay();
    maybeStartKeepaliveAudio();
    setMediaSessionState();
    return true;
    }
    }

    return false;
    } finally {
    STATE.playInFlight = false;
    }
    }

    function scheduleRetry(reason, immediate = false) {
    if (!STATE.desiredPlaying) return;

    clearTimeout(STATE.retryTimer);

    const hidden = isActuallyHidden();
    const delay = immediate ? 0 : (hidden ? STATE.hiddenRetryDelay || CFG.hiddenRetryMs : STATE.retryDelay);

    STATE.retryTimer = setTimeout(async () => {
    if (!STATE.desiredPlaying) return;

    const stillHidden = isActuallyHidden();
    if (stillHidden && STATE.hiddenSince && (now() - STATE.hiddenSince) > CFG.hiddenRetryWindowMs) {
    return;
    }

    syncVideo();

    if (!STATE.currentVideo) {
    bumpRetryDelay();
    scheduleRetry(reason);
    return;
    }

    if (!STATE.currentVideo.paused && STATE.currentVideo.readyState >= 2) {
    STATE.failures = 0;
    resetRetryDelay();
    maybeStartKeepaliveAudio();
    return;
    }

    const ok = await safePlay(reason);
    if (!ok && STATE.desiredPlaying) {
    scheduleRetry(reason);
    }
    }, delay);
    }

    function onPlay() {
    setDesiredPlaying(true, 'play-event');
    }

    function onPlaying() {
    setDesiredPlaying(true, 'playing-event');
    }

    function onPause() {
    if (manualGraceActive()) {
    STATE.lastManualPauseAt = now();
    setDesiredPlaying(false, 'manual-pause');
    return;
    }

    if (STATE.desiredPlaying) {
    scheduleRetry('pause', true);
    }
    }

    function onEnded() {
    setDesiredPlaying(false, 'ended');
    }

    function onVideoSourceChange() {
    setTimeout(() => {
    syncVideo();
    if (STATE.desiredPlaying) scheduleRetry('source-change', true);
    }, 0);
    }

    function onNeedRetry() {
    if (STATE.desiredPlaying) scheduleRetry('buffering');
    }

    function onVisibilityChange() {
    const hidden = isActuallyHidden();

    if (hidden) {
    STATE.hiddenSince = now();
    if (STATE.desiredPlaying) {
    maybeStartKeepaliveAudio();
    scheduleRetry('hidden', true);
    }
    } else {
    STATE.hiddenSince = 0;
    if (STATE.desiredPlaying) {
    stopKeepaliveAudio();
    scheduleRetry('visible', true);
    }
    }
    }

    function onPageHide() {
    STATE.hiddenSince = now();
    if (STATE.desiredPlaying) scheduleRetry('pagehide', true);
    }

    function onPageShow() {
    STATE.hiddenSince = 0;
    if (STATE.desiredPlaying) scheduleRetry('pageshow', true);
    }

    function onFreeze() {
    if (STATE.desiredPlaying) scheduleRetry('freeze', true);
    }

    function onResume() {
    if (STATE.desiredPlaying) scheduleRetry('resume', true);
    }

    function patchPause() {
    const proto = HTMLMediaElement && HTMLMediaElement.prototype;
    if (!proto || typeof proto.pause !== 'function') return;

    const nativePause = proto.pause;
    proto.pause = function patchedPause() {
    try {
    if (
    this === STATE.currentVideo &&
    STATE.desiredPlaying &&
    isActuallyHidden() &&
    !manualGraceActive()
    ) {
    log('blocked hidden pause');
    return;
    }
    } catch (_) {}

    return nativePause.apply(this, arguments);
    };
    }

    function patchHistory() {
    const dispatch = () => window.dispatchEvent(new Event('ytbg-locationchange'));

    try {
    const pushState = history.pushState;
    if (typeof pushState === 'function') {
    history.pushState = function () {
    const ret = pushState.apply(this, arguments);
    dispatch();
    return ret;
    };
    }
    } catch (_) {}

    try {
    const replaceState = history.replaceState;
    if (typeof replaceState === 'function') {
    history.replaceState = function () {
    const ret = replaceState.apply(this, arguments);
    dispatch();
    return ret;
    };
    }
    } catch (_) {}

    window.addEventListener('popstate', dispatch, true);
    window.addEventListener('yt-navigate-finish', dispatch, true);
    window.addEventListener('yt-page-data-updated', dispatch, true);
    window.addEventListener('ytbg-locationchange', () => {
    setTimeout(() => {
    syncVideo();
    if (STATE.desiredPlaying) scheduleRetry('navigation', true);
    }, 0);
    }, true);
    }

    function startObserver() {
    if (STATE.observerStarted) return;

    const root = document.documentElement;
    if (!root) return;

    STATE.observerStarted = true;

    const mo = new MutationObserver(() => {
    syncVideo();
    if (STATE.desiredPlaying && (!STATE.currentVideo || !STATE.currentVideo.isConnected)) {
    scheduleRetry('mutation', true);
    }
    });

    mo.observe(root, { childList: true, subtree: true });

    syncVideo();
    log('observer started');
    }

    function startFrameLoop() {
    if (STATE.frameLoopStarted) return;
    STATE.frameLoopStarted = true;

    const tick = () => {
    if (STATE.desiredPlaying) {
    if (!STATE.currentVideo || !STATE.currentVideo.isConnected) {
    syncVideo();
    }

    if (STATE.currentVideo) {
    if (isActuallyHidden()) {
    if (STATE.currentVideo.paused) scheduleRetry('frame-hidden');
    } else if (STATE.currentVideo.paused) {
    scheduleRetry('frame-visible');
    }
    }
    }

    requestAnimationFrame(tick);
    };

    requestAnimationFrame(tick);
    }

    function installMediaSessionHandlers() {
    if (!CFG.mediaSession) return;

    try {
    if (!('mediaSession' in navigator)) return;
    if (typeof navigator.mediaSession.setActionHandler !== 'function') return;

    navigator.mediaSession.setActionHandler('play', () => {
    setDesiredPlaying(true, 'mediasession-play');
    });

    navigator.mediaSession.setActionHandler('pause', () => {
    STATE.lastManualPauseAt = now();
    setDesiredPlaying(false, 'mediasession-pause');
    });

    navigator.mediaSession.setActionHandler('stop', () => {
    STATE.lastManualPauseAt = now();
    setDesiredPlaying(false, 'mediasession-stop');
    });
    } catch (_) {}
    }

    function installGlobalListeners() {
    document.addEventListener('pointerdown', onPointerLike, true);
    document.addEventListener('pointerup', onPointerLike, true);
    document.addEventListener('click', onPointerLike, true);
    document.addEventListener('touchstart', onPointerLike, true);
    document.addEventListener('mousedown', onPointerLike, true);
    document.addEventListener('keydown', onKeydown, true);

    document.addEventListener('visibilitychange', onVisibilityChange, true);
    window.addEventListener('pagehide', onPageHide, true);
    window.addEventListener('pageshow', onPageShow, true);
    window.addEventListener('freeze', onFreeze, true);
    window.addEventListener('resume', onResume, true);
    window.addEventListener('focus', onVisibilityChange, true);
    window.addEventListener('blur', onVisibilityChange, true);
    }

    function boot() {
    if (STATE.booted) return;
    STATE.booted = true;

    installVisibilitySpoof();
    patchPause();
    patchHistory();
    installGlobalListeners();
    installMediaSessionHandlers();

    const tryStart = () => {
    startObserver();
    if (document.documentElement) startFrameLoop();
    };

    if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', tryStart, { once: true });
    } else {
    tryStart();
    }

    setInterval(() => {
    if (!STATE.desiredPlaying) return;

    syncVideo();

    if (!STATE.currentVideo) return;

    if (isActuallyHidden()) {
    if (STATE.currentVideo.paused) scheduleRetry('watchdog-hidden');
    maybeStartKeepaliveAudio();
    return;
    }

    if (STATE.currentVideo.paused) {
    scheduleRetry('watchdog-visible');
    } else {
    STATE.failures = 0;
    resetRetryDelay();
    stopKeepaliveAudio();
    }
    }, 250);
    }

    boot();
    })();
    467 changes: 0 additions & 467 deletions YouTube Background Play Plus.user.js
    Original file line number Diff line number Diff line change
    @@ -1,467 +0,0 @@
    // ==UserScript==
    // @name YouTube Background Play Plus
    // @namespace https://example.invalid/
    // @version 2.0.0
    // @description Best-effort background play for YouTube desktop and mobile web using only standard userscript features.
    // @match https://www.youtube.com/*
    // @match https://m.youtube.com/*
    // @run-at document-start
    // @grant none
    // @noframes
    // ==/UserScript==

    (() => {
    'use strict';

    const CFG = {
    manualGraceMs: 1000,
    hiddenRetryMs: 250,
    visibleRetryMs: 500,
    maxRetryMs: 5000,
    hiddenRetryWindowMs: 30000,
    debug: false,
    };

    const log = (...args) => {
    if (CFG.debug) console.log('[YT BG Play Plus]', ...args);
    };

    const SEL = [
    '#movie_player video',
    'ytd-player video',
    'video.html5-main-video',
    'video',
    ];

    const CONTROL_SEL = [
    'button',
    '[role="button"]',
    'tp-yt-paper-icon-button',
    'yt-icon-button',
    '.ytp-button',
    '.ytp-play-button',
    '.ytp-volume-panel',
    '.ytp-fullscreen-button',
    ].join(',');

    let currentVideo = null;
    let desiredPlaying = false;

    let lastGestureAt = 0;
    let lastExplicitControlAt = 0;
    let lastManualPauseAt = 0;
    let hiddenSince = 0;

    let observerStarted = false;
    let retryTimer = 0;
    let retryDelay = CFG.visibleRetryMs;
    let playInFlight = false;
    let booted = false;

    const now = () => Date.now();
    const max2 = Math.max;

    function touchGesture(event) {
    const t = now();
    lastGestureAt = t;

    const target = event && event.target;
    if (target instanceof Element && target.closest(CONTROL_SEL)) {
    lastExplicitControlAt = t;
    }
    }

    function manualGraceActive() {
    const t = now();
    const recent = max2(lastGestureAt, lastExplicitControlAt, lastManualPauseAt);
    return (t - recent) <= CFG.manualGraceMs;
    }

    function setMediaSessionState() {
    try {
    if (!('mediaSession' in navigator)) return;
    navigator.mediaSession.playbackState = desiredPlaying ? 'playing' : 'paused';
    } catch (_) {}
    }

    function installMediaSessionHandlers() {
    try {
    if (!('mediaSession' in navigator)) return;
    if (typeof navigator.mediaSession.setActionHandler !== 'function') return;

    navigator.mediaSession.setActionHandler('play', () => {
    desiredPlaying = true;
    setMediaSessionState();
    scheduleRetry('mediasession-play', true);
    });

    navigator.mediaSession.setActionHandler('pause', () => {
    desiredPlaying = false;
    lastManualPauseAt = now();
    setMediaSessionState();
    try {
    if (currentVideo && !currentVideo.paused) currentVideo.pause();
    } catch (_) {}
    });
    } catch (_) {}
    }

    function scoreVideo(v) {
    if (!(v instanceof HTMLVideoElement) || !v.isConnected) return -1e18;

    const r = v.getBoundingClientRect();
    const area = max2(0, r.width) * max2(0, r.height);

    let score = area;

    if (r.width > 0 && r.height > 0) score += 1_000_000;
    if (document.visibilityState === 'visible') score += 20_000;
    if (v.readyState >= 2) score += 10_000;
    if (!v.paused) score += 50_000;
    if (v.currentSrc) score += 2_000;

    if (v.matches('.html5-main-video')) score += 200_000;
    if (v.closest('#movie_player')) score += 150_000;
    if (v.closest('ytd-player')) score += 100_000;
    if (v.closest('.html5-video-container')) score += 50_000;

    return score;
    }

    function pickVideo() {
    const seen = new Set();
    const candidates = [];

    for (const sel of SEL) {
    for (const v of document.querySelectorAll(sel)) {
    if (!seen.has(v)) {
    seen.add(v);
    candidates.push(v);
    }
    }
    }

    let best = null;
    let bestScore = -1e18;

    for (const v of candidates) {
    const s = scoreVideo(v);
    if (s > bestScore) {
    bestScore = s;
    best = v;
    }
    }

    return best;
    }

    function attachVideo(v) {
    if (!(v instanceof HTMLVideoElement)) return;
    if (v === currentVideo) return;

    if (currentVideo) {
    currentVideo.removeEventListener('play', onPlay, true);
    currentVideo.removeEventListener('playing', onPlaying, true);
    currentVideo.removeEventListener('pause', onPause, true);
    currentVideo.removeEventListener('ended', onEnded, true);
    currentVideo.removeEventListener('emptied', onChangedSource, true);
    currentVideo.removeEventListener('loadstart', onChangedSource, true);
    currentVideo.removeEventListener('loadedmetadata', onChangedSource, true);
    currentVideo.removeEventListener('stalled', onNeedRetry, true);
    currentVideo.removeEventListener('waiting', onNeedRetry, true);
    currentVideo.removeEventListener('suspend', onNeedRetry, true);
    currentVideo.removeEventListener('canplay', onNeedRetry, true);
    }

    currentVideo = v;

    try {
    currentVideo.setAttribute('playsinline', '');
    currentVideo.setAttribute('webkit-playsinline', '');
    } catch (_) {}

    currentVideo.addEventListener('play', onPlay, true);
    currentVideo.addEventListener('playing', onPlaying, true);
    currentVideo.addEventListener('pause', onPause, true);
    currentVideo.addEventListener('ended', onEnded, true);
    currentVideo.addEventListener('emptied', onChangedSource, true);
    currentVideo.addEventListener('loadstart', onChangedSource, true);
    currentVideo.addEventListener('loadedmetadata', onChangedSource, true);
    currentVideo.addEventListener('stalled', onNeedRetry, true);
    currentVideo.addEventListener('waiting', onNeedRetry, true);
    currentVideo.addEventListener('suspend', onNeedRetry, true);
    currentVideo.addEventListener('canplay', onNeedRetry, true);

    log('attached video');
    }

    function syncVideo() {
    const best = pickVideo();
    if (best) attachVideo(best);
    }

    function resetRetryDelay() {
    retryDelay = document.hidden ? CFG.hiddenRetryMs : CFG.visibleRetryMs;
    }

    function bumpRetryDelay() {
    retryDelay = Math.min(Math.max(retryDelay * 1.5, 250), CFG.maxRetryMs);
    }

    function safePlay(reason) {
    if (!currentVideo || !desiredPlaying) return Promise.resolve(false);
    if (playInFlight) return Promise.resolve(true);

    playInFlight = true;

    let p;
    try {
    p = currentVideo.play();
    } catch (err) {
    playInFlight = false;
    log('play threw', reason, err && err.name ? err.name : err);
    return Promise.resolve(false);
    }

    if (p && typeof p.then === 'function') {
    return p.then(() => {
    playInFlight = false;
    resetRetryDelay();
    setMediaSessionState();
    log('play ok', reason);
    return true;
    }).catch((err) => {
    playInFlight = false;
    bumpRetryDelay();
    log('play failed', reason, err && err.name ? err.name : err);
    return false;
    });
    }

    playInFlight = false;
    resetRetryDelay();
    setMediaSessionState();
    return Promise.resolve(true);
    }

    function scheduleRetry(reason, immediate = false) {
    if (!desiredPlaying) return;

    clearTimeout(retryTimer);

    const delay = immediate ? 0 : (document.hidden ? CFG.hiddenRetryMs : retryDelay);
    retryTimer = setTimeout(async () => {
    if (!desiredPlaying) return;

    if (document.hidden && hiddenSince && (now() - hiddenSince) > CFG.hiddenRetryWindowMs) {
    return;
    }

    syncVideo();

    if (!currentVideo) {
    bumpRetryDelay();
    scheduleRetry(reason);
    return;
    }

    if (!currentVideo.paused && currentVideo.readyState >= 2) {
    resetRetryDelay();
    return;
    }

    const ok = await safePlay(reason);
    if (!ok && desiredPlaying) scheduleRetry(reason);
    }, delay);
    }

    function onPlay() {
    desiredPlaying = true;
    resetRetryDelay();
    setMediaSessionState();
    }

    function onPlaying() {
    desiredPlaying = true;
    resetRetryDelay();
    setMediaSessionState();
    }

    function onPause() {
    if (manualGraceActive()) {
    desiredPlaying = false;
    lastManualPauseAt = now();
    setMediaSessionState();
    return;
    }

    if (desiredPlaying) {
    scheduleRetry('pause');
    }
    }

    function onEnded() {
    desiredPlaying = false;
    resetRetryDelay();
    setMediaSessionState();
    }

    function onChangedSource() {
    setTimeout(() => {
    syncVideo();
    if (desiredPlaying) scheduleRetry('source-change', true);
    }, 0);
    }

    function onNeedRetry() {
    if (desiredPlaying) scheduleRetry('buffering');
    }

    function onVisibilityChange() {
    if (document.hidden) {
    hiddenSince = now();
    if (desiredPlaying) scheduleRetry('hidden', true);
    } else {
    hiddenSince = 0;
    if (desiredPlaying) scheduleRetry('visible', true);
    }
    }

    function onPageHide() {
    if (desiredPlaying) scheduleRetry('pagehide', true);
    }

    function onPageShow() {
    if (desiredPlaying) scheduleRetry('pageshow', true);
    }

    function onFocusChange() {
    if (desiredPlaying) scheduleRetry('focus-change', true);
    }

    function onUserIntent(event) {
    touchGesture(event);
    }

    function patchPause() {
    const proto = HTMLMediaElement && HTMLMediaElement.prototype;
    if (!proto || typeof proto.pause !== 'function') return;

    const nativePause = proto.pause;
    proto.pause = function patchedPause() {
    try {
    if (
    this === currentVideo &&
    desiredPlaying &&
    document.hidden &&
    !manualGraceActive()
    ) {
    log('blocked hidden pause');
    return;
    }
    } catch (_) {}

    return nativePause.apply(this, arguments);
    };
    }

    function patchHistory() {
    const dispatch = () => window.dispatchEvent(new Event('ytbg-locationchange'));

    try {
    const pushState = history.pushState;
    if (typeof pushState === 'function') {
    history.pushState = function () {
    const ret = pushState.apply(this, arguments);
    dispatch();
    return ret;
    };
    }
    } catch (_) {}

    try {
    const replaceState = history.replaceState;
    if (typeof replaceState === 'function') {
    history.replaceState = function () {
    const ret = replaceState.apply(this, arguments);
    dispatch();
    return ret;
    };
    }
    } catch (_) {}

    window.addEventListener('popstate', dispatch, true);
    window.addEventListener('yt-navigate-finish', dispatch, true);
    window.addEventListener('yt-page-data-updated', dispatch, true);
    window.addEventListener('ytbg-locationchange', () => {
    setTimeout(() => {
    syncVideo();
    if (desiredPlaying) scheduleRetry('navigation', true);
    }, 0);
    }, true);
    }

    function startObserver() {
    if (observerStarted) return;
    const root = document.documentElement || document;

    observerStarted = true;
    const mo = new MutationObserver(() => {
    syncVideo();
    });

    mo.observe(root, { childList: true, subtree: true });
    syncVideo();
    log('observer started');
    }

    function installGlobalListeners() {
    document.addEventListener('pointerdown', onUserIntent, true);
    document.addEventListener('touchstart', onUserIntent, true);
    document.addEventListener('mousedown', onUserIntent, true);
    document.addEventListener('click', onUserIntent, true);
    document.addEventListener('keydown', onUserIntent, true);

    document.addEventListener('visibilitychange', onVisibilityChange, true);
    window.addEventListener('pagehide', onPageHide, true);
    window.addEventListener('pageshow', onPageShow, true);
    window.addEventListener('focus', onFocusChange, true);
    window.addEventListener('blur', onFocusChange, true);
    }

    function boot() {
    if (booted) return;
    booted = true;

    patchPause();
    patchHistory();
    installGlobalListeners();
    installMediaSessionHandlers();

    if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', () => {
    startObserver();
    }, { once: true });
    } else {
    startObserver();
    }

    setInterval(() => {
    if (!desiredPlaying) return;

    syncVideo();
    if (!currentVideo) return;

    if (document.hidden) {
    if (currentVideo.paused) scheduleRetry('watchdog-hidden');
    return;
    }

    if (currentVideo.paused) {
    scheduleRetry('watchdog-visible');
    }
    }, 300);
    }

    boot();
    })();
  8. affan2021shaikh created this gist Apr 9, 2026.
    467 changes: 467 additions & 0 deletions YouTube Background Play Plus.user.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,467 @@
    // ==UserScript==
    // @name YouTube Background Play Plus
    // @namespace https://example.invalid/
    // @version 2.0.0
    // @description Best-effort background play for YouTube desktop and mobile web using only standard userscript features.
    // @match https://www.youtube.com/*
    // @match https://m.youtube.com/*
    // @run-at document-start
    // @grant none
    // @noframes
    // ==/UserScript==

    (() => {
    'use strict';

    const CFG = {
    manualGraceMs: 1000,
    hiddenRetryMs: 250,
    visibleRetryMs: 500,
    maxRetryMs: 5000,
    hiddenRetryWindowMs: 30000,
    debug: false,
    };

    const log = (...args) => {
    if (CFG.debug) console.log('[YT BG Play Plus]', ...args);
    };

    const SEL = [
    '#movie_player video',
    'ytd-player video',
    'video.html5-main-video',
    'video',
    ];

    const CONTROL_SEL = [
    'button',
    '[role="button"]',
    'tp-yt-paper-icon-button',
    'yt-icon-button',
    '.ytp-button',
    '.ytp-play-button',
    '.ytp-volume-panel',
    '.ytp-fullscreen-button',
    ].join(',');

    let currentVideo = null;
    let desiredPlaying = false;

    let lastGestureAt = 0;
    let lastExplicitControlAt = 0;
    let lastManualPauseAt = 0;
    let hiddenSince = 0;

    let observerStarted = false;
    let retryTimer = 0;
    let retryDelay = CFG.visibleRetryMs;
    let playInFlight = false;
    let booted = false;

    const now = () => Date.now();
    const max2 = Math.max;

    function touchGesture(event) {
    const t = now();
    lastGestureAt = t;

    const target = event && event.target;
    if (target instanceof Element && target.closest(CONTROL_SEL)) {
    lastExplicitControlAt = t;
    }
    }

    function manualGraceActive() {
    const t = now();
    const recent = max2(lastGestureAt, lastExplicitControlAt, lastManualPauseAt);
    return (t - recent) <= CFG.manualGraceMs;
    }

    function setMediaSessionState() {
    try {
    if (!('mediaSession' in navigator)) return;
    navigator.mediaSession.playbackState = desiredPlaying ? 'playing' : 'paused';
    } catch (_) {}
    }

    function installMediaSessionHandlers() {
    try {
    if (!('mediaSession' in navigator)) return;
    if (typeof navigator.mediaSession.setActionHandler !== 'function') return;

    navigator.mediaSession.setActionHandler('play', () => {
    desiredPlaying = true;
    setMediaSessionState();
    scheduleRetry('mediasession-play', true);
    });

    navigator.mediaSession.setActionHandler('pause', () => {
    desiredPlaying = false;
    lastManualPauseAt = now();
    setMediaSessionState();
    try {
    if (currentVideo && !currentVideo.paused) currentVideo.pause();
    } catch (_) {}
    });
    } catch (_) {}
    }

    function scoreVideo(v) {
    if (!(v instanceof HTMLVideoElement) || !v.isConnected) return -1e18;

    const r = v.getBoundingClientRect();
    const area = max2(0, r.width) * max2(0, r.height);

    let score = area;

    if (r.width > 0 && r.height > 0) score += 1_000_000;
    if (document.visibilityState === 'visible') score += 20_000;
    if (v.readyState >= 2) score += 10_000;
    if (!v.paused) score += 50_000;
    if (v.currentSrc) score += 2_000;

    if (v.matches('.html5-main-video')) score += 200_000;
    if (v.closest('#movie_player')) score += 150_000;
    if (v.closest('ytd-player')) score += 100_000;
    if (v.closest('.html5-video-container')) score += 50_000;

    return score;
    }

    function pickVideo() {
    const seen = new Set();
    const candidates = [];

    for (const sel of SEL) {
    for (const v of document.querySelectorAll(sel)) {
    if (!seen.has(v)) {
    seen.add(v);
    candidates.push(v);
    }
    }
    }

    let best = null;
    let bestScore = -1e18;

    for (const v of candidates) {
    const s = scoreVideo(v);
    if (s > bestScore) {
    bestScore = s;
    best = v;
    }
    }

    return best;
    }

    function attachVideo(v) {
    if (!(v instanceof HTMLVideoElement)) return;
    if (v === currentVideo) return;

    if (currentVideo) {
    currentVideo.removeEventListener('play', onPlay, true);
    currentVideo.removeEventListener('playing', onPlaying, true);
    currentVideo.removeEventListener('pause', onPause, true);
    currentVideo.removeEventListener('ended', onEnded, true);
    currentVideo.removeEventListener('emptied', onChangedSource, true);
    currentVideo.removeEventListener('loadstart', onChangedSource, true);
    currentVideo.removeEventListener('loadedmetadata', onChangedSource, true);
    currentVideo.removeEventListener('stalled', onNeedRetry, true);
    currentVideo.removeEventListener('waiting', onNeedRetry, true);
    currentVideo.removeEventListener('suspend', onNeedRetry, true);
    currentVideo.removeEventListener('canplay', onNeedRetry, true);
    }

    currentVideo = v;

    try {
    currentVideo.setAttribute('playsinline', '');
    currentVideo.setAttribute('webkit-playsinline', '');
    } catch (_) {}

    currentVideo.addEventListener('play', onPlay, true);
    currentVideo.addEventListener('playing', onPlaying, true);
    currentVideo.addEventListener('pause', onPause, true);
    currentVideo.addEventListener('ended', onEnded, true);
    currentVideo.addEventListener('emptied', onChangedSource, true);
    currentVideo.addEventListener('loadstart', onChangedSource, true);
    currentVideo.addEventListener('loadedmetadata', onChangedSource, true);
    currentVideo.addEventListener('stalled', onNeedRetry, true);
    currentVideo.addEventListener('waiting', onNeedRetry, true);
    currentVideo.addEventListener('suspend', onNeedRetry, true);
    currentVideo.addEventListener('canplay', onNeedRetry, true);

    log('attached video');
    }

    function syncVideo() {
    const best = pickVideo();
    if (best) attachVideo(best);
    }

    function resetRetryDelay() {
    retryDelay = document.hidden ? CFG.hiddenRetryMs : CFG.visibleRetryMs;
    }

    function bumpRetryDelay() {
    retryDelay = Math.min(Math.max(retryDelay * 1.5, 250), CFG.maxRetryMs);
    }

    function safePlay(reason) {
    if (!currentVideo || !desiredPlaying) return Promise.resolve(false);
    if (playInFlight) return Promise.resolve(true);

    playInFlight = true;

    let p;
    try {
    p = currentVideo.play();
    } catch (err) {
    playInFlight = false;
    log('play threw', reason, err && err.name ? err.name : err);
    return Promise.resolve(false);
    }

    if (p && typeof p.then === 'function') {
    return p.then(() => {
    playInFlight = false;
    resetRetryDelay();
    setMediaSessionState();
    log('play ok', reason);
    return true;
    }).catch((err) => {
    playInFlight = false;
    bumpRetryDelay();
    log('play failed', reason, err && err.name ? err.name : err);
    return false;
    });
    }

    playInFlight = false;
    resetRetryDelay();
    setMediaSessionState();
    return Promise.resolve(true);
    }

    function scheduleRetry(reason, immediate = false) {
    if (!desiredPlaying) return;

    clearTimeout(retryTimer);

    const delay = immediate ? 0 : (document.hidden ? CFG.hiddenRetryMs : retryDelay);
    retryTimer = setTimeout(async () => {
    if (!desiredPlaying) return;

    if (document.hidden && hiddenSince && (now() - hiddenSince) > CFG.hiddenRetryWindowMs) {
    return;
    }

    syncVideo();

    if (!currentVideo) {
    bumpRetryDelay();
    scheduleRetry(reason);
    return;
    }

    if (!currentVideo.paused && currentVideo.readyState >= 2) {
    resetRetryDelay();
    return;
    }

    const ok = await safePlay(reason);
    if (!ok && desiredPlaying) scheduleRetry(reason);
    }, delay);
    }

    function onPlay() {
    desiredPlaying = true;
    resetRetryDelay();
    setMediaSessionState();
    }

    function onPlaying() {
    desiredPlaying = true;
    resetRetryDelay();
    setMediaSessionState();
    }

    function onPause() {
    if (manualGraceActive()) {
    desiredPlaying = false;
    lastManualPauseAt = now();
    setMediaSessionState();
    return;
    }

    if (desiredPlaying) {
    scheduleRetry('pause');
    }
    }

    function onEnded() {
    desiredPlaying = false;
    resetRetryDelay();
    setMediaSessionState();
    }

    function onChangedSource() {
    setTimeout(() => {
    syncVideo();
    if (desiredPlaying) scheduleRetry('source-change', true);
    }, 0);
    }

    function onNeedRetry() {
    if (desiredPlaying) scheduleRetry('buffering');
    }

    function onVisibilityChange() {
    if (document.hidden) {
    hiddenSince = now();
    if (desiredPlaying) scheduleRetry('hidden', true);
    } else {
    hiddenSince = 0;
    if (desiredPlaying) scheduleRetry('visible', true);
    }
    }

    function onPageHide() {
    if (desiredPlaying) scheduleRetry('pagehide', true);
    }

    function onPageShow() {
    if (desiredPlaying) scheduleRetry('pageshow', true);
    }

    function onFocusChange() {
    if (desiredPlaying) scheduleRetry('focus-change', true);
    }

    function onUserIntent(event) {
    touchGesture(event);
    }

    function patchPause() {
    const proto = HTMLMediaElement && HTMLMediaElement.prototype;
    if (!proto || typeof proto.pause !== 'function') return;

    const nativePause = proto.pause;
    proto.pause = function patchedPause() {
    try {
    if (
    this === currentVideo &&
    desiredPlaying &&
    document.hidden &&
    !manualGraceActive()
    ) {
    log('blocked hidden pause');
    return;
    }
    } catch (_) {}

    return nativePause.apply(this, arguments);
    };
    }

    function patchHistory() {
    const dispatch = () => window.dispatchEvent(new Event('ytbg-locationchange'));

    try {
    const pushState = history.pushState;
    if (typeof pushState === 'function') {
    history.pushState = function () {
    const ret = pushState.apply(this, arguments);
    dispatch();
    return ret;
    };
    }
    } catch (_) {}

    try {
    const replaceState = history.replaceState;
    if (typeof replaceState === 'function') {
    history.replaceState = function () {
    const ret = replaceState.apply(this, arguments);
    dispatch();
    return ret;
    };
    }
    } catch (_) {}

    window.addEventListener('popstate', dispatch, true);
    window.addEventListener('yt-navigate-finish', dispatch, true);
    window.addEventListener('yt-page-data-updated', dispatch, true);
    window.addEventListener('ytbg-locationchange', () => {
    setTimeout(() => {
    syncVideo();
    if (desiredPlaying) scheduleRetry('navigation', true);
    }, 0);
    }, true);
    }

    function startObserver() {
    if (observerStarted) return;
    const root = document.documentElement || document;

    observerStarted = true;
    const mo = new MutationObserver(() => {
    syncVideo();
    });

    mo.observe(root, { childList: true, subtree: true });
    syncVideo();
    log('observer started');
    }

    function installGlobalListeners() {
    document.addEventListener('pointerdown', onUserIntent, true);
    document.addEventListener('touchstart', onUserIntent, true);
    document.addEventListener('mousedown', onUserIntent, true);
    document.addEventListener('click', onUserIntent, true);
    document.addEventListener('keydown', onUserIntent, true);

    document.addEventListener('visibilitychange', onVisibilityChange, true);
    window.addEventListener('pagehide', onPageHide, true);
    window.addEventListener('pageshow', onPageShow, true);
    window.addEventListener('focus', onFocusChange, true);
    window.addEventListener('blur', onFocusChange, true);
    }

    function boot() {
    if (booted) return;
    booted = true;

    patchPause();
    patchHistory();
    installGlobalListeners();
    installMediaSessionHandlers();

    if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', () => {
    startObserver();
    }, { once: true });
    } else {
    startObserver();
    }

    setInterval(() => {
    if (!desiredPlaying) return;

    syncVideo();
    if (!currentVideo) return;

    if (document.hidden) {
    if (currentVideo.paused) scheduleRetry('watchdog-hidden');
    return;
    }

    if (currentVideo.paused) {
    scheduleRetry('watchdog-visible');
    }
    }, 300);
    }

    boot();
    })();