您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
FB 短影音停用重播、解除靜音、增加可點擊的進度條
// ==UserScript== // @name facebook 短影音停用重播、解除靜音、增加可點擊的進度條 // @namespace http://tampermonkey.net/ // @version 1.4 // @description FB 短影音停用重播、解除靜音、增加可點擊的進度條 // @author shanlan(ChatGPT o3-mini) // @match *://www.facebook.com/* // @grant none // @run-at document-end // @license MIT // ==/UserScript== (() => { const click = el => { if (!el?.dispatchEvent) return; const o = { bubbles: true, cancelable: true, composed: true }; for (const [C, n] of [["PointerEvent","pointerdown"],["MouseEvent","mousedown"],["PointerEvent","pointerup"],["MouseEvent","mouseup"]]) { try { el.dispatchEvent(new (window[C] || MouseEvent)(n, o)); } catch {} } try { el.click(); } catch {} }; const findBtn = v => { const q = "div[role='button'][aria-label*='取消靜音'],div[role='button'][aria-label*='Unmute'],div[role='button'][aria-label*='Turn on sound']"; let r = v?.parentElement, i = 8; while (r && i--) { const b = r.querySelector(q); if (b) return b; r = r.parentElement; } return document.querySelector(q); }; const autoUnmute = v => { if (v._umt) return; let t = 0; const tick = () => { if (v && !v.muted && (v.volume || 0) > 0) { clearInterval(v._umt); v._umt = null; return; } const b = findBtn(v); if (b) click(b); if (++t >= 12) { clearInterval(v._umt); v._umt = null; } }; tick(); v._umt = setInterval(tick, 500); }; const addOverlay = v => { if (v._ov) return; const ov = document.createElement("div"); ov.style.cssText = "position:fixed;background:transparent;z-index:1000000;pointer-events:auto;"; const bar = document.createElement("div"); bar.style.cssText = "height:100%;width:0;background:#f00;"; ov.appendChild(bar); document.body.appendChild(ov); v._ov = ov; const pos = () => { const r = v.getBoundingClientRect(); ov.style.left = r.left + "px"; ov.style.top = (r.bottom - 8) + "px"; ov.style.width = r.width + "px"; ov.style.height = "8px"; requestAnimationFrame(pos); }; requestAnimationFrame(pos); v.addEventListener("timeupdate", () => { if (v.duration) bar.style.width = (v.currentTime / v.duration * 100) + "%"; }); ov.addEventListener("pointerdown", e => { e.preventDefault(); e.stopPropagation(); const r = ov.getBoundingClientRect(); const p = (e.clientX - r.left) / r.width; if (v.duration) v.currentTime = v.duration * p; }, { capture: true }); }; const enhance = v => { if (v._ok) return; v._ok = 1; v.loop = false; v.addEventListener("ended", () => { v.pause(); v.currentTime = v.duration; }); const kick = () => autoUnmute(v); ["canplay","play","loadedmetadata"].forEach(e => v.addEventListener(e, kick, { once: true })); kick(); addOverlay(v); }; const scan = n => { if (!n) return; n.nodeName === "VIDEO" ? enhance(n) : n.querySelectorAll?.("video").forEach(enhance); }; new MutationObserver(m => m.forEach(x => x.addedNodes.forEach(scan))) .observe(document.body, { childList: true, subtree: true }); document.querySelectorAll("video").forEach(enhance); })();