chrisguttandin/extendable-media-recorder

Error: The sampleRate is not defined.

Closed this issue ยท 10 comments

Hello ๐Ÿ‘‹

First of all, thank your time into this library.

I am trying to use the MediaRecorder with a custom encoder audio/wav with multiple audio tracks. On their parent track I am registering the new encoder like this:

useEffect(() => {
  const onInit = async () => {
    if (!MediaRecorder.isTypeSupported("audio/wav")) {
      await register(await connect());
    }
    console.log("Encoder registred");
  };
  onInit();
}, []);

But whenever a new child/audio tracks tries to create a new instance of MediaRecorder it throws an Uncaught error: The sampleRate is not defined. Any ideas?

This are my dependencies:

    "extendable-media-recorder": "^6.5.10",
    "extendable-media-recorder-wav-encoder": "^7.0.62",

Here is how I use the MediaRecorder inside of each AudioTrack

const mst = track.mediaStreamTrack; // AudioTrack
const stream = new MediaStream();
stream.addTrack(mst);

const mediaRecorder = new MediaRecorder(stream, {
  mimeType: "audio/wav",
});

mediaRecorder.ondataavailable = (e)  => mysocket.emit("stream", e.buffer);

mediaRecorder.start(1000);

Hi @tomtobac,

I guess you're using Chrome and the error originates from here:

throw new Error('The sampleRate is not defined.');

This happens if the the settings of the audio track don't contain the sampleRate information. Could you please check what mst.getSettings() returns in your case?

Hey @chrisguttandin , thank you for the quick reply.

Yes, both of them are NOT defined. just the sampleSize...

console.group(`Track ${track.sid}`);
console.log(`SampleSize of mst: ${mst.getSettings().sampleSize}`);
console.log(`SampleSize of stream: ${stream.getAudioTracks()[0].getSettings().sampleSize}`);
console.log(mst.getSettings());
console.groupEnd();

Output:

Track MT0de8b7e70f049a756ee9d79d30b943a0
  SampleSize of mst: 16
  SampleSize of stream: 16
  {
   deviceId: "7df3ef83-97f1-4d91-8314-7d6061289900"
   sampleSize: 16
  }

I guess at the beginning it doesn't have this properties my AudioTrack so I need to check if the sampleRate property exist before to initialize the MediaRecorder. I am kinda newbie in the world of media... I am wondering if there is any way to observe or react base on the this property.

Finally I was able to fix it not very elegant way... I will research more about it since the sample rate is undefined, then is set to 16000 and finally to 48000

const [sampleRate, setSampleRate] = useState(0);

useEffect(() => {
  const intervalId = setInterval(() => {
    const { sampleRate } = track.mediaStreamTrack.getSettings();
    console.log({ sampleRate }); // 16000, 48000, etc.
    if (sampleRate && sampleRate > 0) {
      clearInterval(intervalId);
      setSampleRate(sampleRate);
    }
  }, 200);
  return () => clearInterval(intervalId);
}, [track]);

useEffect(() => {
  const audioElement = audioElementRef.current;
  track.attach(audioElement);

  const mst = track.mediaStreamTrack;
  const stream = new MediaStream();
  stream.addTrack(mst);

  if (!sampleRate) return;

  const mediaRecorder = new MediaRecorder(stream, {
    mimeType: "audio/wav",
  });

}, [track, sampleRate]);

Thank you @chrisguttandin for your help

Interesting, is this a MediaStreamTrack that comes from a peer connection?

Hello. Yes it is.
when I first print the settings of the MediaStreamTrack I get:
{deviceId: '1f706ccd-473a-48f4-81db-76448bbb6998', sampleSize: 16}
the following ones I get:
{channelCount: 1, deviceId: '1f706ccd-473a-48f4-81db-76448bbb6998', latency: 0.01, sampleRate: 48000, sampleSize: 16}

If I understand this correctly the library should probably wait (with a timeout) until the sampleRate is defined. That seems to be what @tomtobac is doing anyway. It's also what fixed the problem for you, @jsoto-gladia, right?

I moved the code that reads the sampleRate by calling getSettings() into the start() method. This does at least ensure it get's called at a later point in time.

Please feel free to reopen this issue in case the problem persists.