Switch stream in media recorder

Hello,

I’m trying to record streams with the media recorder with the possibility to switch the stream recorded when I click to a switch button.

This is my example :

Promise.all(
        [
            //audio stream
            navigator.mediaDevices.getUserMedia({
                audio: {
                    deviceId: settings.audioDeviceId
                }
            }),
            //webcam stream
            navigator.mediaDevices.getUserMedia({
                video: {
                    deviceId: settings.videoDeviceId
                }
            }),
            //window stream
            navigator.mediaDevices.getUserMedia({
                audio: false,
                video: {
                    mandatory: {
                        chromeMediaSource: 'desktop',
                        chromeMediaSourceId: settings.submissionWindowId
                    }
                }
            })
        ])
        .then((streams) => {
            const [audioStream, videoStream, windowStream] = streams;

            const audioTrack = audioStream.getAudioTracks()[0];
            const windowTrack = windowStream.getVideoTracks()[0];
            const videoTrack = videoStream.getVideoTracks()[0];

            audioStream.addTrack(windowStream.getVideoTracks()[0]);

            this.setState({audioStream, windowStream, videoStream});
            this.setState({audioTrack, windowTrack, videoTrack});
            this.startRecord(audioStream);
            return audioStream;

        }).then(this.handleStream).catch(handleError);

startRecord(stream) {
    const mediaRecorder = new MediaRecorder(stream);
    mediaRecorder.start(100);
    const _this = this;
    mediaRecorder.ondataavailable = function(e) {

        if (e.data && e.data.size > 0) {
            let newArray = _this.state.chunks.slice();
            newArray.push(e.data);
            _this.setState({chunks:newArray});
        }
        console.log(_this.state.chunks.length);
    };

    this.setState({mediaRecorder});


}

I tried :

changeSource(event) {
    event.preventDefault();

    const audioStream = this.state.audioStream;
    let mediaRecorder = this.state.mediaRecorder;
    mediaRecorder.stop();

    if(this.props.currentVideoSource === 'pdf') {
        audioStream.removeTrack(this.state.windowTrack);
        audioStream.addTrack(this.state.videoTrack);
        this.props.switchVideoSource('video');
    } else {
        audioStream.removeTrack(this.state.videoTrack);
        audioStream.addTrack(this.state.windowTrack);
        this.props.switchVideoSource('pdf');
    }
    mediaRecorder.stream = audioStream;

    this.startRecord(audioStream);

    this.handleStream(audioStream);
}

handleStream (stream) {
    const video = document.querySelector('video');
    video.srcObject = stream,
    video.onloadedmetadata = (e) => video.play()
}

This code switch the stream on the video element but it doesn’t record the switched stream.

Any Idea ?

Thank you :slight_smile:

@sheppy Any thoughts?

Oops! Thought I’d replied to this days ago, but just found my partially-written message. Finished message follows…

Instead of using MediaStream.removeTrack() and addTrack(), use RTCRtpSender.replaceTrack():

audioStream.replaceTrack(this.state.windowTrack, this.state.videoTrack);

This will swap between the streams without breaking things. We don’t have it documented yet, but it does work.

Sheppy

@sheppy Your solution I found after I tried myself. But to help out the community I made a plain js library that can be used at https://github.com/meething/StreamSwitcher/

It basically extends the MediaStream with the capability
replaceVideoTrack and replaceAudioTrack

Also there is a demo page that can be used to see how it works. @khalil1608 Hope this helps you out as much it helped me out. Please feel free to improve on this