Vibed this UserScript when someone was asking for a fast-forward and rewind feature in WFMU’s archive player. I have often wanted something like for myself, too.
<code>// ==UserScript==
// @name WFMU AccuPlayer ±10s
// @namespace local
// @version 1.1
// @description Add 10-second rewind and fast-forward buttons to WFMU AccuPlayer
// @match *://*.wfmu.org/archiveplayer/*
// @grant none
// @lastUpdated 2026-03-14
// ==/UserScript==
(() => {
'use strict';
const STEP = 10;
const BTN_CLASS = 'wfmu-skip-button';
const jump = (player, delta) => {
if (!player || !Number.isFinite(player.duration)) return;
player.currentTime = Math.max(0, Math.min(player.currentTime + delta, player.duration));
};
const makeButton = (label, title, onClick) => {
const btn = document.createElement('button');
btn.type = 'button';
btn.className = BTN_CLASS;
btn.textContent = label;
btn.title = title;
btn.addEventListener('click', onClick);
return btn;
};
const isEditable = (el) =>
el instanceof HTMLInputElement ||
el instanceof HTMLTextAreaElement ||
el?.isContentEditable;
const addStyles = () => {
if (document.getElementById('wfmu-skip-styles')) return;
const style = document.createElement('style');
style.id = 'wfmu-skip-styles';
style.textContent = `
.${BTN_CLASS} {
min-width: 44px;
height: 44px;
padding: 0 10px;
border: 1px solid #000;
border-radius: 999px;
background: #000;
color: #fff;
cursor: pointer;
font: 600 14px/1 sans-serif;
}
`;
document.head.append(style);
};
const init = () => {
const player = document.querySelector('#audio-player');
const transport = document.querySelector('.transport');
const playButton = document.querySelector('#play-button');
if (!player || !transport || !playButton) return false;
if (document.querySelector(`.${BTN_CLASS}`)) return true;
addStyles();
playButton.before(
makeButton('« 10', 'Back 10 seconds', () => jump(player, -STEP))
);
playButton.after(
makeButton('10 »', 'Forward 10 seconds', () => jump(player, STEP))
);
Object.assign(transport.style, {
display: 'flex',
alignItems: 'center',
gap: '10px',
});
document.addEventListener('keydown', (e) => {
if (isEditable(e.target)) return;
if (e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
jump(player, e.key === 'ArrowLeft' ? -STEP : STEP);
}
});
return true;
};
if (init()) return;
const observer = new MutationObserver(() => {
if (init()) observer.disconnect();
});
observer.observe(document.documentElement, { childList: true, subtree: true });
})();</code>