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.49k stars 1.75k forks source link

recordRTC instance does not use function passed into onStateChanged #757

Open dpetryuk-amplify opened 3 years ago

dpetryuk-amplify commented 3 years ago

Version

5.5.9

Description

When setting onStateChanged the recordRTC instance only uses the default function for onStateChanged and never calls the function that is passed in to set the property.

This is how I'm creating the instance and setting the function for the event callback: Note that this is done inside a React component this.audioRecorder = new RecordRTC(currentRecordingStream, audioRecorderOptions); this.audioRecorder.onStateChanged = state => console.log("RECORDER STATE: ", state); console.log("onStateChanged after passing in my function: ", this.audioRecorder.onStateChanged);

Screen Shot 2021-07-20 at 10 23 13 AM

However, when the state for the recorder changes, the default function gets called instead and the state is logged using the original function. I am logging the internal onStateChanged here Screen Shot 2021-07-20 at 10 25 03 AM

The original function I pass in never gets called.

@muaz-khan

cvalerio commented 2 years ago

Just passed 3 hours on this. All depends on how you init your audioRecorder:

this.audioRecorder = new RecordRTC(...

I was doing exactly the same, and had your same issue. It required me to stepping into the library code to understand what was happening. Basically, if you use RecordRTC as a constructor, what it does return is not the class this (self), but a different object (https://github.com/muaz-khan/RecordRTC/blob/master/RecordRTC.js line 349), with only references to some of the functions of the "instance". The onStateChange function is defined in this returnObject and not synced with self when you mutate it. Also, the returnObject variable, that is returned in fact by the RecordRTC function, is not assigned to self, causing the issue you (and I) have, because when you this.audioRecorder.onStateChanged = ... you are changing the onStateChanged function on the returnObject but not on self (which is used by startRecording to change state).

The solution to this issue is to use RecordRTC as a function, not a constructor, as per documentation (that could be more specific about this, IMO):

this.audioRecorder = RecordRTC(...

I agree that a function should only work in one way, and probably the library would need a constructor AND a builder function (aka factory) in two separated things.

adrianrudnik commented 2 years ago

Similar issue here, but with RecordRTCPromisesHandler, I cannot get it to work.

let stream: MediaStream | null = null
let recorder: RecordRTCPromisesHandler | null = null

stream = await navigator.mediaDevices.getUserMedia({ audio: true })
recorder = new RecordRTCPromisesHandler(stream, {
  type: 'audio',
  disableLogs: false
})

recorder.recordRTC.onStateChanged = (state) => console.log('new state', state)
recorder.startRecording()

never fires onStateChanged. I tried to debug it with the browser:

recorder.startRecording() // inside, self.recordRTC.onStateChanged has the correct cb.
self.recordRTC.startRecording(); // one level down, self.recordRTC.onStateChanged has the default cb, no sign of the new one.

Not sure why though. Even tried to fiddle with the simple demo but could not get it to work. It seems like the same error as above, but RecordRTCPromisesHandler as a hard error if not used with new as the first thing in there, so no workaround for that approach.

hilltopmediadesign commented 2 years ago

Just went through this myself.

Go to the recordRTC library. Search for this code, and add the "return state".

    onStateChanged: function(state) {
        if (!config.disableLogs) {
            console.log('Recorder state changed:', state);
        }
        return state
    },

then to use: recorderInstance.onStateChanged = function(state){ console.log(state) }

LetMeDream commented 8 months ago

Still getting this same error when using 'new RecordRTCPromisesHandler'

Adding 'return state' as @hilltopmediadesign suggested hasn't worked for me.