Skip to content

Instantly share code, notes, and snippets.

@hazycora
Last active July 6, 2023 15:20
Show Gist options
  • Save hazycora/26bafd2a587c4aab6a01a3d953795b48 to your computer and use it in GitHub Desktop.
Save hazycora/26bafd2a587c4aab6a01a3d953795b48 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Faster Ambient Mode
// @namespace http://tampermonkey.net/
// @version 0.2
// @description Makes YouTube's ambient mode feature change more rapidly.
// @author hazycora
// @match https://www.youtube.com/*
// @icon data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==
// @grant none
// ==/UserScript==
// to use this, disable youtube's built-in ambient mode
const cinematicFrameDuration = 20 // milliseconds between frames (crossfade occurs during this duration)
// some might want to change this to 50 or 100
function copyVideo(video, canvasContext) {
canvasContext.drawImage(video, 0, 0)
}
const observer = new MutationObserver(() => {
const video = document.querySelector('#container .html5-main-video')
const cinematics = document.querySelector('#cinematics')
if (video && cinematics) {
observer.disconnect()
console.log('hazy, disconnecting')
function drawCinematics({element, context}, {element: lastElement}) {
return new Promise(resolve => {
copyVideo(video, context)
const animation = element.animate([
{ opacity: "0" },
{ opacity: "1" },
], {
duration: cinematicFrameDuration,
fill: 'forwards',
iterations: 1,
})
animation.addEventListener('finish', () => resolve())
lastElement.animate([
{ opacity: "1" },
{ opacity: "0" },
], {
duration: cinematicFrameDuration,
fill: 'forwards',
iterations: 1,
})
})
}
async function drawLoop() {
const canvasLive = document.createElement('canvas')
const canvasLiveContext = canvasLive.getContext("2d")
canvasLive.id = 'cinematics-after'
const canvasPaused = document.createElement('canvas')
const canvasPausedContext = canvasPaused.getContext("2d")
canvasPaused.id = 'cinematics-before'
cinematics.appendChild(canvasPaused)
cinematics.appendChild(canvasLive)
let swap = false
let lastSize = ''
while (true) {
if (document.hidden) {
await new Promise(r => setTimeout(r, 1000))
continue
}
const newSize = [video.videoWidth, video.videoHeight].join('x')
if (newSize != lastSize) {
canvasLive.width = video.videoWidth
canvasLive.height = video.videoHeight
canvasPaused.width = video.videoWidth
canvasPaused.height = video.videoHeight
lastSize = newSize
}
let cinematicsPromise
if (!swap) {
cinematicsPromise = drawCinematics({element: canvasLive, context: canvasLiveContext}, {element: canvasPaused})
} else {
cinematicsPromise = drawCinematics({element: canvasPaused, context: canvasPausedContext}, {element: canvasLive})
}
await Promise.race([cinematicsPromise, new Promise(r => setTimeout(r, cinematicFrameDuration * 2))])
swap = !swap
}
}
drawLoop()
}
})
observer.observe(document.body, {
childList: true,
subtree: true,
})
const style = document.createElement('style')
style.innerHTML = `
ytd-watch-flexy[theater] #player.ytd-watch-flexy {
display: unset !important;
position: absolute;
top: 0;
padding-top: 56px;
padding-bottom: 400px;
overflow: hidden;
left: 0;
right: 0;
z-index: 0;
pointer-events: none;
height: 56.25vw;
max-height: calc(100vh - 169px);
}
#player-theater-container {
position: relative;
z-index: 10;
}
ytd-watch-flexy[theater] #player-theater-container.ytd-watch-flexy, ytd-watch-flexy[fullscreen] #player-theater-container.ytd-watch-flexy,
ytd-watch-flexy[theater] #player-wide-container.ytd-watch-flexy, ytd-watch-flexy[fullscreen] #player-wide-container.ytd-watch-flexy {
background: none;
z-index: 10;
}
#cinematics {
isolation: isolate;
position: relative;
display: grid;
place-items: center;
}
ytd-watch-flexy[theater] #cinematics {
position: relative;
width: 100%;
height: 56.25vw;
max-height: calc(100vh - 169px);
}
#cinematics canvas {
position: absolute;
mix-blend-mode: plus-lighter;
filter: blur(var(--blur));
--blur: 100px;
--spread: 8rem;
max-width: calc(100% + var(--spread));
height: calc(100% + var(--spread));
}`
document.body.appendChild(style)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment