can't append to sourceBuffer because mediaSource Element (Parent) was removed

2

I'm having problem with video Streaming.

I'm using socket io for video Streaming and react for front end.

Front End code looks like this:-

class VideoElement extends React.Component {
    constructor(props) {
        /* props is having Id, projectDesignSocket */
        super();
        this.state = { hasError: false };
        this.videoRef = React.createRef();
        this.mediaSource = null;
        this.sourceBuffer = null;
    }

    componentDidMount() {
        this.mediaSource = new MediaSource();
        this.videoRef.current.src = URL.createObjectURL(this.mediaSource);
        this.mediaSource.onsourceopen = (e) => {
            URL.revokeObjectURL(this.videoRef.current.src);
            this.sourceBuffer = this.mediaSource.addSourceBuffer("video/webm; codecs=\"vp8, opus\"");
            this.sourceBuffer.mode = 'sequence';
            this.props.projectDesignSocket.on(`${this.props.Id}VideoData`, ({ blob }) => {
                try {

                    this.sourceBuffer.appendBuffer(blob);
                }
                catch (err) {
                    console.log(err);
                }
                finally { 
                    console.log(this.sourceBuffer);
                }
            });
        }
    }

    render() {
        if (this.state.hasError) {
            return <h1>error</h1>;
        }
        else {
            return <video autoPlay ref={this.videoRef} id={this.props.Id}></video>;
        }
    }

    componentWillUnmount() {
        this.mediaSource.onsourceopen = null;
        this.props.projectDesignSocket.off(`${this.props.Id}VideoData`);
    }

    static getDerivedStateFromError(error) {
        return { hasError: true };
    }

    componentDidCatch(error, info) {
        console.log(error, info);
    }
}

class VideoConfrence extends React.Component {
    /* prop is having projectDesignSocket, isAdmin, userList, currentRoom, userName, userId */
    constructor(props) {
        super();
        this.state = {};
        this.userVideoRef = React.createRef();
        this.mediaRecorder = null;
        this.videoStream = null;
    }

    static getDerivedStateFromProps(nextProp, prevState) {
        if (nextProp.userList !== prevState.userList) {
            return { userList: nextProp.userList }
        }
        else {
            return {};
        }
    }

    componentDidMount() {
        navigator.mediaDevices.getUserMedia({
            audio: true,
            video: true
        }).then(stream => {
            this.videoStream = stream;
            this.userVideoRef.current.srcObject = stream;
            this.mediaRecorder = new MediaRecorder(stream);
            this.mediaRecorder.start(100);
            this.mediaRecorder.ondataavailable = (e) => {
                if (e.data.size) { 
                    this.props.projectDesignSocket.emit('video', {
                        room: this.props.currentRoom,
                        data: { userId: this.props.userId, blob: e.data }
                    });
                }
            }
        }).catch(err => {
            console.log(err);
        });
    }


    render() {
        return (
            <div className='videoConfrencing'>
                <video autoPlay ref={this.userVideoRef} />
                {
                    this.state.userList.map((item, index) => {
                        if (item !== this.props.userId) {
                            return <VideoElement key={index} Id={item} projectDesignSocket={this.props.projectDesignSocket} />
                        }
                        else {
                            return null;
                        }
                    })
                }
            </div>
        );
    }

    componentWillUnmount() {
        this.videoStream.getTracks().forEach(function (track) {
            track.stop();
        });
        this.mediaRecorder.ondataavailable = null;
        this.props.projectDesignSocket.off('newMemberAdded');
    }
}

And Backend Like This :-

socket.on('video', function ({ room, data }) {
        // data has userid and blob as it's properties 

        if (room && data ) {
            socket.broadcast.to(room).emit(`${data.userId}VideoData`, {blob:data.blob});
        }
    })

error is occuring at try/catch block of componentDidMount of VideoElement

err:-Media resource blob:http://localhost:3000/493042c5-431b-40a1-aff6-5fafe218a677 could not be decoded, error: Error Code: NS_ERROR_FAILURE (0x80004005)

basicaly i'm designing an app for video confrencing and,

i've used mediaRecorder to record stream obtained by getUserMedia into Blobs and send those blobs to server throgh socket ('video event')

and the server receives roomName from which event was emmited, userId and blob of video and broadcast an event ${userId}VideoData to the specific room

when a user connects the server start receiving blobs and start broadcasting event ${userId}VideoData with {userId, blob} as values to be passed to client

when another user connects his webcam feeds are also sent to server...the user connected before him receives his video blobs and is able to play them , this user also receives video blobs of previously connected user but is unable to play them , on first append to sourceBuffer above warning is logged after which if appended again error is thrown!!

the error is that user which connects cant see the video of other users which were connected before him but is able to see the video of users connected after him!!

but users connected before him are able to see his video without any error

reactjs
socket.io
html5-video
media-source
domexception
asked on Stack Overflow Oct 17, 2020 by Amresh Kumar

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0