muaz-khan / RecordRTC

RecordRTC is WebRTC JavaScript library for audio/video as well as screen activity recording. It supports Chrome, Firefox, Opera, Android, and Microsoft Edge. Platforms: Linux, Mac and Windows.
https://www.webrtc-experiment.com/RecordRTC/
MIT License
6.55k stars 1.76k forks source link

StereoAudioRecorder audio garbled on Safari #489

Open jonahjonah opened 5 years ago

jonahjonah commented 5 years ago

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.

DevJhns commented 5 years ago

@jonahjonah have you found out what was wrong?

jonsadka commented 5 years ago

Having this same issue using the following options

  mimeType: 'audio/wav',
  type: 'audio',
  recorderType: RecordRTC.StereoAudioRecorder,
  bufferSize: 4096,
  numberOfAudioChannels: 2,
  sampleRate: 44100,
ccchapman commented 4 years ago

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 commented 4 years ago

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.

DevJhns commented 4 years ago

@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 commented 4 years ago

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

ccchapman commented 4 years ago

@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.

DevJhns commented 4 years ago

@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 commented 4 years ago

@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...

jonsadka commented 4 years ago

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.

DevJhns commented 4 years ago

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

jonsadka commented 4 years ago

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

DevJhns commented 4 years ago

@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 commented 4 years ago

@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?

jonsadka commented 4 years ago

@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)

DevJhns commented 4 years ago

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

jonsadka commented 4 years ago

@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)

DevJhns commented 4 years ago

@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

numerized commented 4 years ago

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

DevJhns commented 4 years ago

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

DevJhns commented 4 years ago

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

numerized commented 4 years ago

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.

luckyxue commented 4 years ago

@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 commented 4 years ago

@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

Pmartbur commented 4 years ago

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??

jonsadka commented 4 years ago

@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',
});
jonklein commented 4 years ago

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.

trackedsupport commented 3 years ago

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?

TalissaDreossi commented 2 years ago

adding .clone() worked also for me

braden-w commented 1 year ago

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!