Sometimes it is useful to display levels for an audio node, even if that level is getting modified somewhere downstream.
The web audio API context is loading.
<p>The web audio API context is <span id="ctx-status">loading</span>. <button id="ctx-button">Loading</button></p>
<div class="demo-video">
<video controls id="the-video" crossorigin="anonymous" style="width: 100%;">
<source src="https://assets.rpy.xyz/testmedia/hoops.mp4" type="video/mp4">
Sorry, your browser doesn't support embedded videos.
</video>
<div>
<input type="range" id="gain" name="gain" min="0" max="1" value="0" step="0.05">
<label for="gain">Gain</label>
</div>
<div id="peak-meter" style="height: 72px"></div>
</div>
const audioCtx = new AudioContext();
const ctxStatus = document.getElementById('ctx-status');
const buttonElement = document.getElementById('ctx-button');
function updateAudioCtxStatus() {
ctxStatus.innerText = audioCtx.state;
if (audioCtx.state === 'suspended') {
buttonElement.innerText = 'Resume';
} else {
buttonElement.innerText = 'Suspend';
}
}
setInterval(updateAudioCtxStatus, 1000);
buttonElement.addEventListener('click', () => {
if (audioCtx.state === 'suspended') {
audioCtx.resume().then(updateAudioCtxStatus);
} else {
audioCtx.suspend().then(updateAudioCtxStatus);
}
});
const videoElement = document.getElementById('the-video');
const meterElement = document.getElementById('peak-meter');
const sourceNode = audioCtx.createMediaElementSource(videoElement);
const gainNode = audioCtx.createGain();
gainNode.gain.setValueAtTime(0, audioCtx.currentTime);
sourceNode.connect(gainNode);
gainNode.connect(audioCtx.destination);
const unused = new webAudioPeakMeter.WebAudioPeakMeter(sourceNode, meterElement);
const gainSlider = document.getElementById('gain');
gainSlider.addEventListener('change', (evt) => {
gainNode.gain.setValueAtTime(evt.target.value, audioCtx.currentTime);
});