Isolating sound from a video file using pure JavaScript

I’m working on a project where I capture screen content and sound with navigator.mediaDevices.getDisplayMedia and a MediaRecorder. This gives me a video file. Now I want to pull out just the audio part using only plain JavaScript in the browser. I’d like to let users download this audio file.

Here’s what I’m trying to do:

async function getSoundFromVideo(videoFile) {
  // Need help here!
  // How to separate audio from video?

  return soundFile;
}

Can anyone help me figure out the steps to make this work? I’ve looked online but haven’t found a clear answer for doing this with vanilla JS. Thanks!

hey there! i’ve done smth similar b4. have u tried using Web Audio API? u can create an AudioContext, connect ur video to it, then use a MediaStreamDestination to get the audio stream. from there, use MediaRecorder to save it as a file. hope this helps!

I encountered this challenge before and found a reliable solution using the Web Audio API along with MediaRecorder. In my experience, you begin by creating an AudioContext and then linking your video element using createMediaElementSource. By connecting that source to a MediaStreamDestination, you can extract the audio stream from the video. Using MediaRecorder to record this stream provides a Blob representing the isolated audio. This method has proven to be efficient in modern browsers, though it is important to account for browser-specific compatibility and handle potential errors robustly.

I actually tackled a similar problem in a project last year. Here’s what worked for me:

First, you’ll need to create an AudioContext and a MediaElementSource from your video file. Then, connect that to a MediaStreamDestination. This gives you an audio stream.

From there, you can use another MediaRecorder to capture just the audio. Something like:

async function getSoundFromVideo(videoFile) {
  const video = document.createElement('video');
  video.src = URL.createObjectURL(videoFile);
  await video.play();

  const audioCtx = new AudioContext();
  const source = audioCtx.createMediaElementSource(video);
  const destination = audioCtx.createMediaStreamDestination();
  source.connect(destination);

  const audioRecorder = new MediaRecorder(destination.stream);
  const chunks = [];

  audioRecorder.ondataavailable = e => chunks.push(e.data);
  audioRecorder.start();

  video.onended = () => audioRecorder.stop();

  return new Promise(resolve => {
    audioRecorder.onstop = () => {
      const blob = new Blob(chunks, { type: 'audio/webm' });
      resolve(blob);
    };
  });
}

This should give you an audio file the user can download. Hope it helps!