chrisguttandin / extendable-media-recorder

An extendable drop-in replacement for the native MediaRecorder.
MIT License
258 stars 13 forks source link

stop() listener doesn't trigger #646

Closed mylnikovD closed 3 years ago

mylnikovD commented 3 years ago

I'm using recorder in React in conjunction with wavesurfer.js to show the waves of recording and then create a player to listen the recording

// in App.tsx
import { register } from 'extendable-media-recorder';
import { connect } from 'extendable-media-recorder-wav-encoder';
//
useEffect(() => {
    async function init() {
      await register(await connect());
    }
    init();
  }, []);

// in component file
import { IMediaRecorder, MediaRecorder } from 'extendable-media-recorder';
class ComponentName extends Component<props, state>{
  waveSurfer?: WaveSurfer;
  mediaRecorder?: IMediaRecorder;

  async componentDidUpdate(prevProps: SamplePageProps, prevState: SamplePageState) {
    // recording state tracks the clicks on record button
    if (this.state.recording && !prevState.recording) {
    // Initializing wavesurfer to show waves
      this.waveSurfer = WaveSurfer.create({
        container: '#waveform',
        height: 38,
        waveColor: '#666666',
        barWidth: 1,
        interact: false,
        barHeight: 34,
        plugins: [MicrophonePlugin.create()],
      });
      const audioChunks: any[] = [];
      this.waveSurfer.microphone.on('deviceReady', stream => {
        this.mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/wav' });
        if (!this.mediaRecorder) return;
        this.mediaRecorder.start(400);
        this.mediaRecorder.addEventListener('dataavailable', (event: any) => {
          audioChunks.push(event.data);
        });

        this.mediaRecorder.addEventListener(
          'stop',
          () => {
            // doesn't trigger
            console.log('stop', audioChunks);
            const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
            const audioUrl = URL.createObjectURL(audioBlob);
            this.addNewRecord({ id: this.state.recordedSamples.length, audioUrl, selected: false, blob: audioBlob });
          },
        );
      });
      this.waveSurfer.microphone.start();
    }
  }

  toggleRecording = () => {
    if (this.state.recording) {
      if (!this.waveSurfer || !this.mediaRecorder) return;
      // prints correct mediarecorder object with all the methods
      console.log('this mediarecorder', this.mediaRecorder);
      this.waveSurfer.microphone.stop();
      // THIS DOES NOT TRIGGER 
      this.mediaRecorder.stop();
      this.props.logEvent('Stop sample recording', {
        url: this.props.location.pathname,
      });
   }
}

When I click the button to stop recording, toggleRecording function works as it should, but console log in stop listener doesn't print, and nothing described there works. The same setup with opus-media-recorder works as it should, but I find your library more convenient to use, would appreciate any tips :)

chrisguttandin commented 3 years ago

Hi @mylnikovD, thanks for raising that issue. The sad answer is that the stop event hasn't been implemented yet. It should be fairly straightforward to add it though. I will try to do it on the weekend.

mylnikovD commented 3 years ago

Thanks for reply, and looking forward for implementation, really appreciated for your great work! Opus requires some worker magic to work properly with React's bundler, so I'd gladly use your library instead :)

mylnikovD commented 3 years ago

Another question regarding audio processing. When I'm using your recorder to make 'audio/wav' instead of default 'audio/webm' in chrome for example, is the raw data from microphone changed somehow? For the project I'm working in now, we need the raw data intact

chrisguttandin commented 3 years ago

No the MediaStream is used as is. But you would need to disable the echoCancellation and co when calling getUserMedia() to make sure you get the raw microphone data.

chrisguttandin commented 3 years ago

Version 6.3.0 does now fire a stop event.