Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name yout-ube iframe player
- // @namespace https://example.com/
- // @description Replaces YouTube player with yout-ube iframe and blocks videoplayback on the parent page.
- // @match https://www.youtube.com/*
- // @match https://m.youtube.com/*
- // @run-at document-start
- // @grant none
- // ==/UserScript==
- (() => {
- "use strict";
- const TARGET_HOST = "www.yout-ube.com";
- const IFRAME_ATTR = "data-gm-yout-ube-iframe";
- const WRAP_ATTR = "data-gm-yout-ube-wrap";
- const BLOCK_PATTERNS = [
- /\/\/[^/]*googlevideo\.com\/videoplayback/i,
- /\/videoplayback(\?|$)/i,
- ];
- const shouldBlockUrl = (url) => {
- try {
- const s = String(url || "");
- return BLOCK_PATTERNS.some((re) => re.test(s));
- } catch {
- return false;
- }
- };
- const buildIframeUrl = () => {
- const u = new URL(location.href);
- u.hostname = TARGET_HOST;
- return u.toString();
- };
- const isWatchPage = () =>
- location.pathname === "/watch" && new URL(location.href).searchParams.has("v");
- const pauseAndNukeMedia = (root = document) => {
- try {
- root.querySelectorAll("video,audio").forEach((el) => {
- try { el.pause?.(); } catch {}
- try { el.muted = true; el.volume = 0; } catch {}
- try {
- el.removeAttribute("src");
- el.querySelectorAll?.("source").forEach((s) => s.remove());
- el.load?.();
- } catch {}
- });
- } catch {}
- };
- const stopAllInjectedIframes = () => {
- document.querySelectorAll(`iframe[${IFRAME_ATTR}]`).forEach((ifr) => {
- try { ifr.src = "about:blank"; } catch {}
- try { ifr.remove(); } catch {}
- });
- document.querySelectorAll(`div[${WRAP_ATTR}]`).forEach((w) => {
- try { w.remove(); } catch {}
- });
- };
- const installBlockers = () => {
- if (typeof window.fetch === "function") {
- const origFetch = window.fetch;
- window.fetch = function (input, init) {
- const url = (typeof input === "string") ? input : (input && input.url);
- if (shouldBlockUrl(url)) {
- return Promise.reject(new TypeError("Blocked by userscript: videoplayback"));
- }
- return origFetch.apply(this, arguments);
- };
- }
- if (window.XMLHttpRequest) {
- const origOpen = XMLHttpRequest.prototype.open;
- const origSend = XMLHttpRequest.prototype.send;
- XMLHttpRequest.prototype.open = function (method, url) {
- this.__gm_blocked_url__ = url;
- return origOpen.apply(this, arguments);
- };
- XMLHttpRequest.prototype.send = function () {
- if (shouldBlockUrl(this.__gm_blocked_url__)) {
- try { this.abort(); } catch {}
- return;
- }
- return origSend.apply(this, arguments);
- };
- }
- const mo = new MutationObserver((mutList) => {
- for (const m of mutList) {
- for (const n of m.addedNodes) {
- if (!(n instanceof Element)) continue;
- if (n.matches?.("video,audio")) pauseAndNukeMedia(n.parentNode || document);
- else if (n.querySelector) {
- if (n.querySelector("video,audio")) pauseAndNukeMedia(n);
- }
- }
- }
- });
- const startObs = () => {
- if (!document.documentElement) return;
- mo.observe(document.documentElement, { childList: true, subtree: true });
- };
- if (document.documentElement) startObs();
- else document.addEventListener("readystatechange", startObs, { once: true });
- };
- const findPlayerHost = () => {
- const selectors = [
- "#player.ytd-watch-flexy",
- "#player-container.ytd-watch-flexy",
- "ytd-player#ytd-player",
- "#movie_player",
- "ytd-watch-flexy #player",
- ];
- for (const sel of selectors) {
- const el = document.querySelector(sel);
- if (el) {
- if (el.id === "movie_player" && el.parentElement) return el.parentElement;
- return el;
- }
- }
- return null;
- };
- const ensureIframePlayer = () => {
- if (!isWatchPage()) return;
- const host = findPlayerHost();
- if (!host) return;
- const desiredSrc = buildIframeUrl();
- const existingIframe = host.querySelector(`iframe[${IFRAME_ATTR}]`);
- if (existingIframe) {
- if (existingIframe.src !== desiredSrc) {
- existingIframe.src = "about:blank";
- existingIframe.src = desiredSrc;
- }
- return;
- }
- host.textContent = "";
- const wrap = document.createElement("div");
- wrap.setAttribute(WRAP_ATTR, "1");
- wrap.style.position = "relative";
- wrap.style.width = "100%";
- wrap.style.aspectRatio = "16 / 9";
- wrap.style.minHeight = "360px";
- host.style.width = "100%";
- const iframe = document.createElement("iframe");
- iframe.setAttribute(IFRAME_ATTR, "1");
- iframe.src = desiredSrc;
- iframe.allow =
- "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share";
- iframe.allowFullscreen = true;
- iframe.referrerPolicy = "origin-when-cross-origin";
- iframe.loading = "eager";
- iframe.style.position = "absolute";
- iframe.style.inset = "0";
- iframe.style.width = "100%";
- iframe.style.height = "100%";
- iframe.style.border = "0";
- iframe.style.display = "block";
- wrap.appendChild(iframe);
- host.appendChild(wrap);
- };
- const handleRouteChange = () => {
- pauseAndNukeMedia(document);
- if (isWatchPage()) {
- ensureIframePlayer();
- } else {
- stopAllInjectedIframes();
- pauseAndNukeMedia(document);
- }
- };
- const installSpaHooks = () => {
- const schedule = (() => {
- let t = null;
- return () => {
- if (t) clearTimeout(t);
- t = setTimeout(() => {
- t = null;
- handleRouteChange();
- }, 50);
- };
- })();
- window.addEventListener("yt-navigate-start", schedule, true);
- window.addEventListener("yt-navigate-finish", schedule, true);
- window.addEventListener("yt-page-data-updated", schedule, true);
- window.addEventListener("popstate", schedule, true);
- window.addEventListener("hashchange", schedule, true);
- const mo = new MutationObserver(() => {
- if (isWatchPage()) ensureIframePlayer();
- });
- const start = () => {
- if (!document.documentElement) return;
- mo.observe(document.documentElement, { childList: true, subtree: true });
- };
- if (document.documentElement) start();
- else document.addEventListener("readystatechange", start, { once: true });
- let lastHref = location.href;
- setInterval(() => {
- if (location.href !== lastHref) {
- lastHref = location.href;
- handleRouteChange();
- }
- }, 250);
- handleRouteChange();
- };
- installBlockers();
- installSpaHooks();
- })();
Advertisement
Add Comment
Please, Sign In to add comment