Skip to content

Instantly share code, notes, and snippets.

@XReyRobert
Created January 12, 2026 21:26
Show Gist options
  • Select an option

  • Save XReyRobert/21eabbbcf69a7b23c976d568173f395f to your computer and use it in GitHub Desktop.

Select an option

Save XReyRobert/21eabbbcf69a7b23c976d568173f395f to your computer and use it in GitHub Desktop.
Local web page to use full screen youtube videos with plast (macos)
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="referrer" content="strict-origin-when-cross-origin" />
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1" />
<style>
html, body {
margin: 0 !important;
width: 100% !important;
height: 100% !important;
overflow: hidden !important;
background: #000 !important;
}
/* Fill the viewport unconditionally */
#stage {
position: fixed !important;
inset: 0 !important;
overflow: hidden !important;
background: #000 !important;
}
/* The YT API inserts wrappers; force them all to occupy the stage */
#player,
#player > div {
position: absolute !important;
inset: 0 !important;
width: 100% !important;
height: 100% !important;
}
/*
Cover sizing:
Use CSS max() so we cover both portrait/landscape viewports without “small corner” behavior.
16:9 math:
16/9 = 1.7777778
9/16 = 0.5625
*/
#player iframe {
position: absolute !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
width: max(100vw, 177.7778vh) !important;
height: max(100vh, 56.25vw) !important;
border: 0 !important;
}
/* Invisible click-catcher to enable audio (no message) */
#unlock {
position: fixed;
inset: 0;
background: transparent;
z-index: 10;
cursor: default;
}
</style>
</head>
<body>
<div id="stage">
<div id="player"></div>
</div>
<div id="unlock" aria-hidden="true"></div>
<script src="https://www.youtube.com/iframe_api"></script>
<script>
function getVideoIdFromQuery() {
const qs = new URLSearchParams(location.search);
const raw = (qs.get("v") || qs.get("video") || "").trim();
// Safe charset; supports leading '-' (your ID includes it).
return /^[A-Za-z0-9_-]{6,32}$/.test(raw) ? raw : null;
}
const VIDEO_ID = getVideoIdFromQuery() || "-Yye4owQMsQ";
const ORIGIN = location.origin;
let player;
function setDesktopPassthrough(enabled) {
const iframe = document.querySelector("#player iframe");
if (iframe) iframe.style.pointerEvents = enabled ? "none" : "auto";
}
function kickMutedAutoplay(maxMs = 7000) {
const deadline = Date.now() + maxMs;
const t = setInterval(() => {
try {
const st = player.getPlayerState();
if (st !== YT.PlayerState.PLAYING) {
player.mute();
player.playVideo();
} else {
clearInterval(t);
}
} catch (_) {}
if (Date.now() > deadline) clearInterval(t);
}, 250);
}
function onYouTubeIframeAPIReady() {
player = new YT.Player("player", {
host: "https://www.youtube-nocookie.com",
videoId: VIDEO_ID,
playerVars: {
autoplay: 1,
controls: 0,
disablekb: 1,
fs: 0,
iv_load_policy: 3,
loop: 1,
playlist: VIDEO_ID, // required to loop a single video [oai_citation:1‡Google for Developers](https://developers.google.com/youtube/player_parameters?utm_source=chatgpt.com)
playsinline: 1,
rel: 0,
origin: ORIGIN,
enablejsapi: 1
},
events: {
onReady: (e) => {
// Improve autoplay reliability: ensure iframe explicitly allows autoplay.
try {
const iframe = e.target.getIframe();
iframe.setAttribute("allow", "autoplay; encrypted-media; picture-in-picture");
} catch (_) {}
// Restore initial behavior: autoplay muted.
try { e.target.mute(); } catch (_) {}
try { e.target.playVideo(); } catch (_) {}
// Keep clicks available until audio is enabled.
setDesktopPassthrough(false);
// If the big red button appears, keep nudging play() while muted.
kickMutedAutoplay();
},
onStateChange: (e) => {
if (e.data === YT.PlayerState.ENDED) {
try { e.target.seekTo(0, true); e.target.playVideo(); } catch (_) {}
}
}
}
});
}
// One real click to enable sound (no on-screen message).
document.getElementById("unlock").addEventListener("click", () => {
if (!player) return;
try { player.unMute(); player.setVolume(100); } catch (_) {}
try { player.playVideo(); } catch (_) {}
// Remove click-catcher and make the iframe non-interactive so desktop clicks pass through.
document.getElementById("unlock").remove();
setTimeout(() => setDesktopPassthrough(true), 100);
});
</script>
</body>
</html>
@XReyRobert
Copy link
Author

start a local server with:
python3 -m http.server 8099 --bind 127.0.0.1

point plash to http://127.0.0.1:8099/plash-youtube-audio.html?v=-Yye4owQMsQ
(replace -Yye4owQMsQ by the target video id)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment