Hi,
I’m using a Mac, and I’ve noticed that only the play/pause media keys work with your video player. The rewind and forward media keys don’t seem to function.
On platforms like Udemy, I’m able to use media keys — including rewind and forward — even when I’m in a different app or tab (for example, while taking notes or following along in Notion). This saves a lot of time and avoids switching back and forth between the video and my notes.
If possible, could you enable support for rewind and forward media keys in your video player settings? It would make the learning experience much smoother and more efficient.
Thank you!
That does sound handy. We use Vimeo.com’s player, so we’re limited by the features they currently implement, unfortunately.
hi, @rob_kodekloud
I found a wrokaround using script for viemo , but it is add more and more Scripts for every new video load ,
I think you could add just a mediakeys script for your video element
could you please conside it
Thank you
// ==UserScript==
// @name Vimeo Media Keys with Dynamic Loader (Safe Singleton)
// @namespace https://greasyfork.org/en/users/1330666
// @version 1.3
// @description Adds media key controls (rewind/forward/play/pause) for Vimeo player after dynamic load, without duplicate instances
// @match https://vimeo.com/*
// @match https://player.vimeo.com/*
// @grant none
// @run-at document-start
// @license GPL-3.0-or-later
// ==/UserScript==
// Prevent multiple instances of the script from running
if (window.__vimeo_media_keys_loaded__) return;
window.__vimeo_media_keys_loaded__ = true;
(function () {
'use strict';
const waitForElement = (selector, timeout = 10000) =>
new Promise((resolve, reject) => {
const start = Date.now();
const timer = setInterval(() => {
const el = document.querySelector(selector);
if (el) return clearInterval(timer), resolve(el);
if (Date.now() - start > timeout) clearInterval(timer), reject();
}, 100);
});
let lastVideo = null;
async function bindMediaKeys() {
try {
const video = await waitForElement('video');
if (!video || video === lastVideo) return;
lastVideo = video;
navigator.mediaSession.setActionHandler('previoustrack', () => {
video.currentTime = Math.max(0, video.currentTime - 10);
});
navigator.mediaSession.setActionHandler('nexttrack', () => {
video.currentTime = Math.min(video.duration, video.currentTime + 10);
});
navigator.mediaSession.setActionHandler('play', () => video.play());
navigator.mediaSession.setActionHandler('pause', () => video.pause());
console.log('🎬 Media key handlers attached to new video.');
} catch (e) {
console.warn('⚠️ Video element not found in time:', e);
}
}
function initMutationObserver() {
let lastUrl = location.href;
new MutationObserver(() => {
const currentUrl = location.href;
if (currentUrl !== lastUrl) {
lastUrl = currentUrl;
lastVideo = null;
setTimeout(bindMediaKeys, 2000);
}
}).observe(document, { childList: true, subtree: true });
console.log('🔁 Mutation observer initialized.');
}
// Initial run
setTimeout(() => {
bindMediaKeys();
initMutationObserver();
}, 2000);
})();