DEV Community

puspaksahu17
puspaksahu17

Posted on

How to record Google Meet and Zoom calls with dual audio using the HTML5 MediaRecorder API

Recording virtual meetings like Google Meet or Zoom often comes with annoying hurdles: 5-minute freemium limits, forced software installations, or needing explicit host permission just to record local audio.

In this guide, we'll walk through how to build a browser-native screen recorder using the HTML5 MediaRecorder API and getDisplayMedia to capture both tab audio (meeting participants) and user microphone input simultaneously.


Understanding the Architecture

To record a full Google Meet or Zoom session locally in the browser without uploading video data to external servers, we need three core Web APIs:

  1. navigator.mediaDevices.getDisplayMedia(): Captures screen/tab video along with system/tab audio.
  2. navigator.mediaDevices.getUserMedia(): Captures the user's local microphone.
  3. AudioContext & MediaStreamAudioDestinationNode: Mixes both audio streams into a single track.
  4. MediaRecorder: Encodes video and combined audio into a downloadable WebM/MP4 blob.

Code Implementation

Here is how you capture and merge both audio sources in JavaScript:

async function startMeetingRecording() {
  // 1. Capture screen video and tab/system audio
  const displayStream = await navigator.mediaDevices.getDisplayMedia({
    video: { frameRate: { ideal: 30 } },
    audio: true // Captures Google Meet/Zoom meeting audio
  });

  // 2. Capture local microphone audio
  const micStream = await navigator.mediaDevices.getUserMedia({
    audio: { echoCancellation: true, noiseSuppression: true }
  });

  // 3. Mix both audio sources using Web Audio API
  const audioContext = new AudioContext();
  const dest = audioContext.createMediaStreamDestination();

  if (displayStream.getAudioTracks().length > 0) {
    const displaySource = audioContext.createMediaStreamSource(displayStream);
    displaySource.connect(dest);
  }

  if (micStream.getAudioTracks().length > 0) {
    const micSource = audioContext.createMediaStreamSource(micStream);
    micSource.connect(dest);
  }

  // 4. Combine video track + mixed audio stream
  const tracks = [
    ...displayStream.getVideoTracks(),
    ...dest.stream.getAudioTracks()
  ];
  const combinedStream = new MediaStream(tracks);

  // 5. Initialize MediaRecorder
  const mediaRecorder = new MediaRecorder(combinedStream, {
    mimeType: 'video/webm;codecs=vp9,opus'
  });

  const chunks = [];
  mediaRecorder.ondataavailable = (e) => chunks.push(e.data);
  mediaRecorder.onstop = () => {
    const blob = new Blob(chunks, { type: 'video/webm' });
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'meeting-recording.webm';
    a.click();
  };

  mediaRecorder.start();
}

---

Enter fullscreen mode Exit fullscreen mode


Live Application & Working Example

If you want to test this implementation live without writing code, we built a production version over at QuickWebSuite. It requires no signup, enforces no time caps, and processes 100% of video data locally inside your browser:

Top comments (0)