talha khalid
talha khalid

Reputation: 301

Original audio of tab gets muted while using chrome.tabCapture.capture() and MediaRecorder()

when i use chrome.tabCapture.capture() with MediaRecorder API to record stream original audio of tabs which i am capturing gets muted but the audio comes OK in recorded stream, i want the audio in the tab to run normally ....

class Recorder {
  constructor(onChunksAvailable) {
    this.chunks = [];

    this.active = false;

    this.callback = onChunksAvailable;
  }

  start(stream) {
    if (this.active) {
      throw new Error("recorder is already running");
    }
    this.recorder = new MediaRecorder(stream, {
      mimeType: "audio/webm",
    });

    this.recorder.onstop = () => {
      stream.getAudioTracks()[0].stop();
      this.callback([...this.chunks]);

      setTimeout(() => {
        this.chunks = [];
      });

      this.active = false;
    };

    this.recorder.ondataavailable = (event) => this.chunks.push(event.data);

    this.active = true;
    this.recorder.start();
  }

  stop() {
    if (!this.active) {
      throw new Error("recorder is already stop");
    } else {
      this.recorder.stop();
    }
  }
}

let rec = new Recorder(async (chunks) => {
//using chunks then to get the stream
});

chrome.tabCapture.capture(
    {
      audio: true,
      video: false,
    },
    function (stream) {
        rec.start(stream);
}

Upvotes: 2

Views: 2041

Answers (1)

Tom
Tom

Reputation: 159

Forgive me for lack of documentation as I last played with these APIs years ago, but MDN has some stuff.

In my case adding these 3 lines to the start function was fixed.

this.context = new AudioContext();
this.stream = this.context.createMediaStreamSource(stream);
this.stream.connect(this.context.destination);
class Recorder {
  constructor(onChunksAvailable) {
    this.chunks = [];

    this.active = false;

    this.callback = onChunksAvailable;

    this.context = new AudioContext();
  }

  start(stream) {
    if (this.active) {
      throw new Error("recorder is already running");
    }

    // Reconnect the stream to actual output
    this.stream = this.context.createMediaStreamSource(stream);
    this.stream.connect(this.context.destination);

    this.recorder = new MediaRecorder(stream, {
      mimeType: "audio/webm",
    });

    this.recorder.onstop = () => {
      stream.getAudioTracks()[0].stop();
      this.callback([...this.chunks]);

      setTimeout(() => {
        this.chunks = [];
      });

      this.active = false;
    };

    this.recorder.ondataavailable = (event) => this.chunks.push(event.data);

    this.active = true;
    this.recorder.start();
  }

  stop() {
    if (!this.active) {
      throw new Error("recorder is already stop");
    } else {
      this.recorder.stop();
    }
  }
}

let rec = new Recorder(async (chunks) => {
//using chunks then to get the stream
});

chrome.tabCapture.capture(
    {
      audio: true,
      video: false,
    },
    function (stream) {
        rec.start(stream);
    })

Sorry for lack of details, but I believe when you start an audio capture it disconnects the stream from the default output (speakers). By creating a secondary MediaStreamSource and connecting it to the default output (AudioContext.destination) you can allow the stream to continue outputting to speakers while being input to your recorder.


Sources

MDN: AudioContext

MDN: MediaStreamSource

Chrome extension I made 2 years ago

Upvotes: 4

Related Questions