admin管理员组

文章数量:1289393

I've tried mediaStream Recording API and audioWorkletProcessor API but they both have a issue. If the video is muted by users, they will get nothing. I want to get the audio data no matter the video is muted or not by users. How can I do that?

I selected the video tag

const video = document.querySelector('video');
const stream = video.captureStream();

and use

    const recorder = new MediaRecorder(stream);

or use

    const audioContext = new AudioContext();
    const workletURL = chrome.runtime.getURL('audio-processor.js'); 

    audioContext.audioWorklet.addModule(workletURL)
        .then(() => {
            console.log("✅ AudioWorklet);

            const source = audioContext.createMediaStreamSource(stream);
            const audioWorkletNode = new AudioWorkletNode(audioContext, "audio-processor");

            source.connect(audioWorkletNode);
            audioWorkletNode.connect(audioContext.destination);


            audioWorkletNode.port.onmessage = (event) => {
                console.log(event.data);
                audioBufferQueue.push(new Float32Array(event.data));
            };
        })
        .catch(err => console.error("❌ AudioWorklet faile:", err));

they can't get audio data when muted.

I've tried mediaStream Recording API and audioWorkletProcessor API but they both have a issue. If the video is muted by users, they will get nothing. I want to get the audio data no matter the video is muted or not by users. How can I do that?

I selected the video tag

const video = document.querySelector('video');
const stream = video.captureStream();

and use

    const recorder = new MediaRecorder(stream);

or use

    const audioContext = new AudioContext();
    const workletURL = chrome.runtime.getURL('audio-processor.js'); 

    audioContext.audioWorklet.addModule(workletURL)
        .then(() => {
            console.log("✅ AudioWorklet);

            const source = audioContext.createMediaStreamSource(stream);
            const audioWorkletNode = new AudioWorkletNode(audioContext, "audio-processor");

            source.connect(audioWorkletNode);
            audioWorkletNode.connect(audioContext.destination);


            audioWorkletNode.port.onmessage = (event) => {
                console.log(event.data);
                audioBufferQueue.push(new Float32Array(event.data));
            };
        })
        .catch(err => console.error("❌ AudioWorklet faile:", err));

they can't get audio data when muted.

Share Improve this question edited Feb 20 at 9:42 just_code_dog asked Feb 20 at 9:31 just_code_dogjust_code_dog 1,0373 gold badges16 silver badges32 bronze badges 2
  • Not clear at all. How do you want to get audio? Download? On what side? Where does the video come from? Is it already recorded video the user views in the video element? What is the purpose of your extension and the principles of its operation? See also: How to create a Minimal, Reproducible Example. – Sergey A Kryukov Commented Feb 20 at 9:36
  • @SergeyAKryukov updated question – just_code_dog Commented Feb 20 at 9:43
Add a comment  | 

1 Answer 1

Reset to default 1

Instead of relying on captureStream(), we can:

  • Use createMediaElementSource(video) to tap into the audio before it gets muted.
  • Create a separate MediaStreamDestination() to extract the audio.
  • Merge the extracted audio with the video stream and pass it to MediaRecorder.

const video = document.querySelector("video");
const audioContext = new AudioContext();

// Create a MediaElementSource (Extracts audio before mute)
const source = audioContext.createMediaElementSource(video);

// Create a destination node to capture the unmuted audio
const destination = audioContext.createMediaStreamDestination();
source.connect(destination);

const audioStream = destination.stream; // Get audio stream separately

// Merge video + extracted audio
const finalStream = new MediaStream([
  ...video.captureStream().getVideoTracks(),
  ...audioStream.getAudioTracks(),
]);

   
const recorder = new MediaRecorder(finalStream);  // Record the final stream
recorder.start();

recorder.ondataavailable = (event) => {
  console.log("Captured Audio Data", event.data);
};

To record audio from a video (e.g., YouTube) even when muted, you must capture the system audio, not the video element’s internal stream.

Steps to Fix:

  • Use navigator.mediaDevices.getDisplayMedia() to capture both system audio and video.
  • Extract the audio track separately.
  • Merge it with a video element’s video stream.

async function captureVideoWithAudio() {
  // Step 1: Capture screen (includes system audio)
  const screenStream = await navigator.mediaDevices.getDisplayMedia({
    video: { frameRate: 30 },
    audio: { channelCount: 2, echoCancellation: false, noiseSuppression: false }
  });

  // Step 2: Extract audio track from system audio
  const audioTrack = screenStream.getAudioTracks()[0];

  if (!audioTrack) {
    console.error("No audio track available. Ensure system audio is shared.");
    return;
  }

  // Step 3: Select the video element
  const video = document.querySelector("video");

  if (!video) {
    console.error("No video element found!");
    return;
  }

  // Step 4: Get video stream from the video element (ignoring audio)
  const videoStream = video.captureStream();
  const videoTrack = videoStream.getVideoTracks()[0];

  if (!videoTrack) {
    console.error("No video track found!");
    return;
  }

  // Step 5: Combine video track with system audio track
  const finalStream = new MediaStream([videoTrack, audioTrack]);

  // Step 6: Start recording
  const recorder = new MediaRecorder(finalStream);
  recorder.start();

  recorder.ondataavailable = (event) => {
    console.log("Captured Audio Data", event.data);
  };
}

// Call the function when needed
captureVideoWithAudio();

本文标签: javascriptGet audio from html5 video tag with mutedStack Overflow