I'm working on a project where I'm using <video>
elements as sources for canvas animations, and I'm aiming to send their audio through the Web Audio API using Tone.js. The canvas animations are fine, it's the audio that's giving me trouble. I'd like to keep the audio synced to the video if possible, so I'm using MediaStream
.
When a video loads, it's initially muted on the element itself. I do muted="false"
once audio is enabled with a button press that runs Tone.start()
. I grab the video's audio via captureStream()
, and hook it up to a gain node with the gain set to 0, essentially muting it again. In Firefox, everything works fine, and I can set the gain to whatever desired value. But in Chrome, I can't get rid of the original video audio – it's still going in the background. My "unmute" works, but it clearly plays a second copy of the audio, causing comb filtering.
I'm intending on doing more than just muting and unmuting, so while it's tempting to just use video.volume
instead of putting in all this work, this is just a proof of concept that isn't proving much at all right now. Any help is appreciated!
let video = document.querySelector(video);
// lower the video element's audio until we're ready
// might not be necessary, but it's just a cautionary step
video.volume = 0;
// unhook the audio from the video; works in FF, but not Chrome
let stream = video.mozCaptureStream ? video.mozCaptureStream() : video.captureStream();
let audioTrack = new MediaStream(stream.getAudioTracks());
let speaker = Tone.context.createMediaStreamSource(audioTrack);
// gain node is the *actual* volume control that I'm intending to use; it starts at 0 to mute the unhooked audio
let gain = new Tone.Gain(0);
Tone.connect(speaker, gain);
Tone.connect(gain, Tone.context.destination);
// if video.volume stays at 0, we hear nothing
video.volume = 1;
Edit: It may be worth mentioning that I did start with this Vonage API support page to better understand how to go about using captureStream()
like this, but the cloning and disabling process described in that article didn't work for me in FF or Chrome.