Skip to content

Instantly share code, notes, and snippets.

@balbuf
Created April 4, 2021 16:18
Show Gist options
  • Save balbuf/ce4535fec20aa70d2df4a543d8f35b41 to your computer and use it in GitHub Desktop.
Save balbuf/ce4535fec20aa70d2df4a543d8f35b41 to your computer and use it in GitHub Desktop.
Bookmarklet to add video controls for the active video on a page
(function () {
let activeVideo;
const controls = document.createElement('div');
controls.innerHTML = `
<style>
body {
overflow: hidden;
margin: 0;
}
.input-rate {
text-align: right;
}
button, input {
font-size: 2em;
flex-grow: 1;
margin: 4px;
}
div.container {
display: flex;
justify-content: space-between;
flex-wrap: wrap;
}
.break {
flex-basis: 100%;
height: 0;
}
</style>
<div class="container">
<button class="action-pause">Pause</button>
<button class="action-play">Play</button>
<input class="input-rate" size="4" value="1">
<button class="action-rate">x</button>
<div class="break"></div>
<button class="action-back10">&lsaquo;10s</button>
<button class="action-back5">&lsaquo;5s</button>
<button class="action-fwd5">5s&rsaquo;</button>
<button class="action-fwd10">10s&rsaquo;</button>
</div>
`;
const rate = controls.querySelector('.input-rate');
rate.addEventListener('focus', () => rate.value = (activeVideo && activeVideo.playbackRate) || 1);
controls.querySelector('.action-pause').addEventListener('click', () => activeVideo.pause());
controls.querySelector('.action-play').addEventListener('click', () => activeVideo.play());
controls.querySelector('.action-rate').addEventListener('click', () => activeVideo.playbackRate = parseFloat(rate.value) || 1);
controls.querySelector('.action-back10').addEventListener('click', () => activeVideo.currentTime -= 10);
controls.querySelector('.action-back5').addEventListener('click', () => activeVideo.currentTime -= 5);
controls.querySelector('.action-fwd5').addEventListener('click', () => activeVideo.currentTime += 5);
controls.querySelector('.action-fwd10').addEventListener('click', () => activeVideo.currentTime += 10);
const controlFrame = document.createElement('iframe');
document.body.appendChild(controlFrame);
controlFrame.style = 'width: 350px; height: 100px; position: fixed; right: 0; top: 0; background: white;';
controlFrame.contentDocument.body.appendChild(controls);
Array.from(document.getElementsByTagName('iframe'))
.map((iframe) => iframe.contentWindow)
.concat(window)
.forEach(win => {
win.navigator.mediaSession.setActionHandler('play', () => activeVideo.play());
win.navigator.mediaSession.setActionHandler('pause', () => activeVideo.pause());
win.navigator.mediaSession.setActionHandler('previoustrack', () => activeVideo.currentTime = activeVideo.currentTime - 5);
win.navigator.mediaSession.setActionHandler('nexttrack', () => activeVideo.currentTime = activeVideo.currentTime + 7);
Array.from(win.document.getElementsByTagName('video')).forEach(video => {
if (!activeVideo) activeVideo = video;
video.addEventListener('play', () => {
activeVideo = video;
rate.value = activeVideo.playbackRate;
});
new Proxy(video, {
set: function (obj, prop, value) {
obj[prop] = value;
console.log(value);
return true;
},
});
});
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment