RecordRTC icon indicating copy to clipboard operation
RecordRTC copied to clipboard

StereoAudioRecorder audio garbled on Safari

Open jonahjonah opened this issue 5 years ago • 30 comments

I'm trying to use a StereoAudioRecorder to record audio. Its working on all other browsers, but on Safari the audio is coming out garbled (very scratchy and crackly, and lacking in detail, as if only some audio frequencies are coming through, or something like that).

Here's the function that prepares the recorder:

function prepareRTC(callback) {
  if (!window.microphone) {
    captureMicrophone( micCallback );
    return;
  } else {
    console.log('mic already captured!');
  }

  var options = {
    mimeType: 'audio/wav',
    fileExtension: 'wav',
    numberOfAudioChannels: 1,
    bufferSize: 16384,
    checkForInactiveTracks: true,
    recorderType: StereoAudioRecorder,
    desiredSampRate: 22050,
  };
  if(window.browser == 'safari') {
    options.type = 'audio';
    delete options.desiredSampRate;
    options.sampleRate = 44100;
    options.bufferSize = 4096;
    options.numberOfAudioChannels = 2;
  }

  if (window.audioRecorderPH || window.audioRecorder) {
    window.audioRecorder.destroy();
    window.audioRecorder = null;    
  }

  window.audioRecorderPH = new RecordRTCPromisesHandler(window.microphone, options);
  window.audioRecorder = window.audioRecorderPH.recordRTC;

  callback();
  return;
}

I use the options you suggest in your example. Instead of using an <audio> element, I use an AudioContext to play the audio, and I thought the problem might be related to that, but the audio is coming out messed up before it even gets to there (like if I try to play the blob using window.audioRecorder.toURL()). Here is a short recording of me, if you listen carefully you can hear I said "Recording on, on Safari."

Have you seen this kind of behavior before? Do you have any idea what might be causing it? Thank you for any help. And please let me know if any more details would be helpful.

jonahjonah avatar Mar 05 '19 23:03 jonahjonah

@jonahjonah have you found out what was wrong?

DevJhns avatar Sep 30 '19 01:09 DevJhns

Having this same issue using the following options

  mimeType: 'audio/wav',
  type: 'audio',
  recorderType: RecordRTC.StereoAudioRecorder,
  bufferSize: 4096,
  numberOfAudioChannels: 2,
  sampleRate: 44100,

jonsadka avatar Oct 16 '19 03:10 jonsadka

I am also having this issue using these options.

Strangely, the example referenced does work properly in Safari.

I am having troubles determining what is different.

ccchapman avatar Oct 17 '19 19:10 ccchapman

In my situation, the audio garbling appears to be caused by additional code using the AudioContext API. I used this to calculate the audio level for user visualization.

For the moment, I disabled this code in Safari and the audio recording is not garbled.

Perhaps it puts too much stress on the recording process in Safari.

ccchapman avatar Oct 17 '19 20:10 ccchapman

@ccchapman I also create AudioContext, for sound/silence detection, and sound garbles, but if I remove line desiredSampRate: 44100, all works, seems problem lies somewhere here, not sure if this is couse of high rate or AudioContext with desiredSampRate safari issues, on chrome all works

DevJhns avatar Oct 20 '19 16:10 DevJhns

or maybe safari using 48000 rate ? anyone knows StereoAudioRecorder sample rate by default?

DevJhns avatar Oct 21 '19 19:10 DevJhns

@DevJhns I think the default is 16000, per the README.

Your audio is not garbled when you remove desiredSampRate from your options? Mine still is.

ccchapman avatar Oct 21 '19 19:10 ccchapman

@ccchapman seems so, I don't define buffersize and no desiredSampRate also no sampleRate all I set: type: 'audio', mimeType: 'audio/wav', recorderType: StereoAudioRecorder, numberOfAudioChannels: 1

DevJhns avatar Oct 22 '19 13:10 DevJhns

@ccchapman actually example above works on mac safari(works with sampleRate: 48000),

on ios safari it is still garble/distortion sound I found this old safari bug https://github.com/Jam3/ios-safe-audio-context and this https://stackoverflow.com/questions/26336040/how-to-fix-changing-sample-rate-bug

in few words this happens couse of another apple fuc... mess up, as always.... sigh for some reason audiocontext may take wrong value, and it changes sample rate few times (if we have video or audio around, like in our case webrtc stream video/audio), so this couse distortion, I added audio: { sampleRate: 48000 } in navigator.mediaDevices and sampleRate: 48000 for RecordRTC now I can at least hear my voice, with distortion, kind robotic, but understandable at least, if I change sampleRate to 44100 in RecordRTC, hear no sound at all, strange...

DevJhns avatar Oct 28 '19 16:10 DevJhns

Per @ccchapman's comment, I too use the the AudioContext API to calculate the audio level for a visualization (example below).

I've tried all the possible combinations and still get the garbled/distorted sound. Using @DevJhns's recommendation to specify sampleRate in getUserMedia got me the closest, but recording still has some garbling/distortion.

  navigator.mediaDevices
    .getUserMedia({audio: {sampleRate: 48000}})
    .then(mediaStream => handleStreamSuccess(mediaStream))

  handleStreamSuccess(mediaStream) {
     const mediaRecorder = RecordRTC(mediaStream, {
        disableLogs: isProduction,
        mimeType: 'audio/wav',
        numberOfAudioChannels: 2,
        type: 'audio',
        checkForInactiveTracks: true,
        recorderType: RecordRTC.StereoAudioRecorder,
        bufferSize: 4096, 
        sampleRate: 48000
      });
    }

FYI I also tried using https://github.com/Jam3/ios-safe-audio-context to create the Audio Context but it still resulted in garbled/distorted audio.

jonsadka avatar Oct 29 '19 04:10 jonsadka

@jonsadka your audio garbles/distortes only in ios? What about audio from macbook safari ?

DevJhns avatar Oct 29 '19 20:10 DevJhns

@DevJhns was happing on Macbook Safari, didnt test on iOS. Were you able to use ios-safe-audio-context sucessfully?

jonsadka avatar Oct 29 '19 20:10 jonsadka

@jonsadka I haven't used it yet, wanna fix bug without other libs, my friend who have mac, said sound was ok, but this was before I added {audio: {sampleRate: 48000}}

just with audio: true and sampleRate: 48000 in recordrtc all worked there, but not on ios

DevJhns avatar Oct 29 '19 20:10 DevJhns

@jonsadka @ccchapman Actually I found solution, remove sampleRate: 48000 from audio, just set it to true or your settings, and pass stream.clone() to your function with audiocontext createMediaStreamSource(stream) caused all troubles

now I get clear sound on ios, sure it will be good on mac too, but....

now record work only once... any ideas, guys? can someone check how mac behaves?

DevJhns avatar Oct 30 '19 17:10 DevJhns

@jonsadka @ccchapman Actually I found solution, remove sampleRate: 48000 from audio, just set it to true or your settings, and pass stream.clone() to your function with audiocontext createMediaStreamSource(stream) caused all troubles

now I get clear sound on ios, sure it will be good on mac too, but....

now record work only once... any ideas, guys? can someone check how mac behaves?

I'll try when I get a chance, but if you clone the stream I'd imagine you'd have to make sure you update all your previous references of the stream to the new clone (or try creating a new media stream every time you want to re-record, which is less ideal)

jonsadka avatar Oct 30 '19 17:10 jonsadka

@jonsadka aslo passing stream.clone() to RecordRTC fix this oh yeah, at last =)

DevJhns avatar Oct 30 '19 19:10 DevJhns

@DevJhns nice! This workaround seems to work on the Apple devices tested below: ✅ MacBook Pro Safari 13.0.2 ✅ iPhone X iOS 13.2 ✅ iPhone 7 iOS 12.3.1 ✅ iPhone 5 iOS 12.4.2

What a neat little hack. I do wonder what some of the performance implications are of cloning a stream (will try to dig into this a little deeper)

jonsadka avatar Oct 31 '19 15:10 jonsadka

@jonsadka much better, than more external libs, huh?

Now it would be excellent if apple add mediarecorder support out of the box in at least 50 years (now it is in beta functions)

couse when I record with stereoaudiorecorder getting ~500-700 kb wav file 2-3 seconds vs ~8-12 kb webm... both 48000 rate, 60+ times difference

DevJhns avatar Oct 31 '19 19:10 DevJhns

Hi Guys I don't have same luck than you with passing stream.clone to RecordRTC I still have cracks when I am speaking with a peer and recording my voice at the same time

numerized avatar Nov 01 '19 22:11 numerized

@numerized show your recordrtc settings and what you do with stream except recording (libs, api, etc) do you set settings in audio (constraints)?

DevJhns avatar Nov 02 '19 02:11 DevJhns

@numerized your issues coused by rate misssetings, hard to say where problem is without knowing your api/libs stack and settings

DevJhns avatar Nov 05 '19 15:11 DevJhns

sorry guys I was travelling, so I don't get it, I'll try more soon, but I have the same crackling noises when using whereby.com on my IOS and no problem when I compile an actual cordova app and it's our new requirement, no IOS on Safari web so I'm good thanks all.

numerized avatar Apr 20 '20 17:04 numerized

@DevJhns nice! This workaround seems to work on the Apple devices tested below: ✅ MacBook Pro Safari 13.0.2 ✅ iPhone X iOS 13.2 ✅ iPhone 7 iOS 12.3.1 ✅ iPhone 5 iOS 12.4.2

What a neat little hack. I do wonder what some of the performance implications are of cloning a stream (will try to dig into this a little deeper)

I read your discussion carefully, unfortunately, I don’t know how to implement stream cloning.

luckyxue avatar Jun 21 '20 15:06 luckyxue

@jonsadka aslo passing stream.clone() to RecordRTC fix this oh yeah, at last =)

When the sampling rate is set to 16khz, the audio noise played back or saved is particularly large and severely distorted

luckyxue avatar Jun 21 '20 16:06 luckyxue

Hi, guys, I'm stuck in this also...I tried stream.clone, but doesn't work, still have a bad recording, it's full of glitchs and shorter than it should be. Which are the right rate settings for Safari??

Pmartbur avatar Jul 20 '20 03:07 Pmartbur

@Pmartbur @luckyxue this is the code I am using with the configuration. Is this still creating issues?

const mediaRecorder = RecordRTC(mediaStream.clone(), {
  checkForInactiveTracks: true,
  mimeType: 'audio/wav',
  numberOfAudioChannels: 2,
  recorderType: RecordRTC.StereoAudioRecorder,
  type: 'audio',
});

jonsadka avatar Aug 08 '20 06:08 jonsadka

For people still encountering this issue: do you have another audio/video element on the page (or did you ever have one) prior to the recording? In my usage, it appears that as soon as another audio/video element is played on the page, any subsequent audio context is tainted/corrupted and produces distorted results.

Try reproducing the issue without any other audio/video elements present. In my case, eliminating a video that is displayed before the recording seems to address the issue. Furthermore, I can put the video I want to display inside of an iframe and as long as that iframe is removed from the page before recording, the audio seems ok.

jonklein avatar Aug 20 '20 15:08 jonklein

The RecordRTC(mediaStream.clone(), fixed my issue but it does feel like a dirty hack. Does anyone know why that can make it work or what distorts it?

Also if we do the .clone() do I need to close the original one?

trackedsupport avatar Feb 07 '21 21:02 trackedsupport

adding .clone() worked also for me

TalissaDreossi avatar Jul 15 '22 10:07 TalissaDreossi

Thank you guys so much! I saw this thread and changed my implementation from

recorder = new RecordRTC(stream, options);

to

recorder = new RecordRTC(stream.clone(), options);

and it solved all issues!

braden-w avatar Mar 30 '23 00:03 braden-w