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

작성자

카테고리:

← 피드로
DEV Community · puspaksahu17 · 2026-08-22 개발(SW)

puspaksahu17

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:

원문에서 계속 ↗