Back to basics: adding a playback speed control to an audio player
Monday, December 28th, 2020Currently I am publishing the new Developer Advocacy Handbook chapter by chapter and I also started recording audio versions of each chapter. A common request of people is to be able to control the speed of a audio/video recording. Luckily enough, using basic HTML5 and JavaScript, this is not that hard to achieve, so let’s do it.
You can see and hear the result in the following video:
You can check the final version on Codepen
See the Pen
Audio with speed control by Christian Heilmann (@codepo8)
on CodePen.
The best start is always sensible HTML.
<div class="speedcontrolcontainer"> <audio src="https://file-examp…xample_MP3_2MG.mp3" controls></audio> <div> <label for="pbrate">Speed:</label> <input type="range" id="pbrate" min=.5 max=3 value=1 step=.1> <span></span> </div> </div> |
In this case, using the audio element with a controls attribute already gives us a play button, a scrubber, time display, volume and an overflow menu with download option. For the speed control, we need a slider with a label to keep it accessible and a span element to show the current value of the playback speed. The range control is good for this as it also gives us keyboard access and allows us to limit the speeds we want to allow. In this case, from half speed to four times the speed.
Let’s only go into basic CSS for styling here:
.scc { max-width: 30em; display: block; border: 1px solid #000; padding: 10px; font-family: Sans-serif; } .scc audio { width: 100%; display: block; } .scc div { display: flex; padding: .5em 0; gap: 5px; } .scc label { flex: 1; } .scc input[type="range"] { flex: 5; } .scc span { flex: 1; text-align: center; } |
We give the control a container element and set it to a max-width of 30em. We display the audio element as block and make it use up all the available space. We give the new speed control a bit of padding and use flexbox to lay it out.
The last bit is to use JavaScript to create the rest of the functionality:
const audio = document.querySelector('.scc audio'); const playbackrate = document.querySelector('.scc input'); const display = document.querySelector('.scc span'); const displayvalue = val => { return parseInt(val * 100, 10) + '%' } display.innerText = displayvalue(audio.playbackRate); playbackrate.addEventListener('change', e => { audio.playbackRate = playbackrate.value; display.innerText = displayvalue(playbackrate.value); }); |
- We get references to the audio element, the slider and the span we want to display the current value of the slide in.
- As the playback speed in the audio API is a number, we need to convert it to a percentage. This is what the displayvalue method does for us.
- We display the current playbackRate of the audio element in the span next to the slider.
- We apply an event Listener to the input element that fires every time it changed.
- When there is a change, we set the playbackRate of the audio element to the value of the slider
- And we display the percentage in the span
One thing that is missing is that users may want to have their favourite speed stored so they don’t have to set it again chapter by chapter. To do this, we can use localStorage, set the playbackRate and value when we load the document and store it when the slider changed.
const audio = document.querySelector('.scc audio'); const playbackrate = document.querySelector('.scc input'); const display = document.querySelector('.scc span'); const displayvalue = val => { return parseInt(val * 100, 10) + '%' } if (window.localStorage.pbspeed) { audio.playbackRate = window.localStorage.pbspeed; playbackrate.value = window.localStorage.pbspeed; } display.innerText = displayvalue(audio.playbackRate); playbackrate.addEventListener('change', e => { audio.playbackRate = playbackrate.value; display.innerText = displayvalue(playbackrate.value); window.localStorage.pbspeed = playbackrate.value; }); |
And that’s it! An audio playback control with playback speed option.