4

I'm trying to stream a video file using Javascript's MediaSource API in a React component.

Here's my component:

const RawPlayer: React.FC= () => {
    const videoRef = useRef<HTMLVideoElement>(null);


    useEffect(() => {
        const mimeCodec = 'video/mp4; codecs="avc1.42E01E, mp4a.40.2"';

        if (videoRef.current && MediaSource.isTypeSupported(mimeCodec)) {
            const myMediaSource = new MediaSource();
            const url = URL.createObjectURL(myMediaSource);

            videoRef.current.src = url;

            myMediaSource.addEventListener('sourceopen', () => {
                const videoSourceBuffer = myMediaSource.addSourceBuffer(mimeCodec);

                videoSourceBuffer.addEventListener('error', console.log);

                // this is just an express route that return an mp4 file using `res.sendFile`
                fetch('http://localhost:3001/video/bC4Zud78/raw').then((response) => {
                    return response.arrayBuffer();
                }).then((videoData) => {
                    videoSourceBuffer.appendBuffer(videoData);
                });
            });
        }
    });

    return (
        <video ref={videoRef} controls />
    );
};

Strangely it doesn't work. When I go on the page, there's a spinner on the video, the spinner disappear then nothing happens.

This error listener:

videoSourceBuffer.addEventListener('error', console.log);

Log this:

Which is not really an error.


Here's a reproduction: https://github.com/AnatoleLucet/react-MediaSource

The code is in src/App.tsx

Anatole Lucet
  • 1,603
  • 3
  • 24
  • 43
  • can we get some screenshots of the console log, the webpage and your components source code plz? – Dean Van Greunen Jan 09 '20 at 17:40
  • Shure, but what do you mean with "my components source code"? The `RawPlayer` comonent is directly used in an `App` components, `App` only contain `` and finaly `App` is rendered using `ReactDOM.render()` – Anatole Lucet Jan 09 '20 at 17:42
  • @DeanVanGreunen Edited. – Anatole Lucet Jan 09 '20 at 17:48
  • save yourself a headache and use this instead: https://www.npmjs.com/package/react-html5video – Dean Van Greunen Jan 09 '20 at 17:58
  • 1
    @DeanVanGreunen Well that doesn't really do what I want. I need to self manage the buffer so I can change the quality, the language, manage my segments and more... Without reloading the whole `Video` component. – Anatole Lucet Jan 09 '20 at 18:03
  • ohh thats a wimzy....well then this is definitely what you are looking for: https://www.npmjs.com/package/react-player – Dean Van Greunen Jan 09 '20 at 18:08
  • well I don't think this module is going to help me. The api I need to use is sending me segments of video (5 secs each), I need to put them together each time the client received a new segment. A bit like it's explained in [this article](https://medium.com/canal-tech/how-video-streaming-works-on-the-web-an-introduction-7919739f7e1). – Anatole Lucet Jan 09 '20 at 18:25
  • `videoRef.current.src = url;` shouldn't this be `videoRef.src = url;` – Dean Van Greunen Jan 09 '20 at 18:28
  • @DeanVanGreunen the url is added to the ` – Anatole Lucet Jan 09 '20 at 18:31
  • in the article is uses `VideoRef.src` https://imgur.com/gallery/orHiguS – Dean Van Greunen Jan 10 '20 at 00:02
  • @DeanVanGreunen I found the issue (check the answer I've made). But there's a diff between WebAPI's dom element selectors (for ex `getElementById`) and React's `useRef`. https://stackoverflow.com/a/37274379/8990411 – Anatole Lucet Jan 10 '20 at 00:09
  • 1
    @DeanVanGreunen Thanks you for helping anyway! – Anatole Lucet Jan 10 '20 at 12:58

2 Answers2

3

The issue was the file format I recieve from the api. If I try with this file in my fetch it works perfectly!

Anatole Lucet
  • 1,603
  • 3
  • 24
  • 43
1

A note on the file format: I struggled with this as well. The mp4 has to be fragmented for it to work with MediaSource (in my tests, please offer any corrections). You can use this utility to create a fragmented mp4 from an unfragmented one:

https://www.bento4.com/documentation/mp4fragment/

For a full list of valid mime codecs, see:

https://cconcolato.github.io/media-mime-support/

Hari
  • 373
  • 3
  • 11