0

I am trying to load heavy video file (around 300mb in tag in html. I tried setting the source as a URL but it lags and cause performance issue in chrome. I tried using the Media Source API in my react Application. But I am getting errors. Please suggest a way I can load heavy videos smoothly into browser in React.js.

Here is the component I created for implementing Media Source API:

import React, { useEffect, useRef } from 'react';

const VideoStream = (props) => {
  const videoRef = useRef(null);

  useEffect(() => {
    const video = videoRef.current;

    if (window.MediaSource) {
      const mediaSource = new MediaSource();
      video.src = URL.createObjectURL(mediaSource);

      mediaSource.addEventListener('sourceopen', handleSourceOpen);
    } else {
      console.error('MediaSource API is not supported.');
    }
  }, []);

  const handleSourceOpen = async (event) => {
    const mediaSource = event.target;
    console.log(videoRef.current)
    const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.42E01E, mp4a.40.2"');

    // Fetch and append media segments progressively
    const segmentUrl = props.src;
    const response = await fetch(segmentUrl);
    const segmentData = await response.arrayBuffer();
    console.log(segmentData)
    sourceBuffer.appendBuffer(segmentData);
    sourceBuffer.addEventListener('updateend', () => {
      if (!sourceBuffer.updating && mediaSource.readyState === 'open') {
        mediaSource.endOfStream();
      }
    });
    videoRef.current.play();
  };

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

export default VideoStream;

The error I am getting is:

GET blob:http://localhost:3000/b54e8a3a-769e-40a8-8cd3-3a49cf14946a net::ERR_FILE_NOT_FOUND

  • Do you need it to load immediately? If not there are many react video packages out there that allow you to defer loading until the user interacts with the component and just show an image initially. Also would recommend having that file on a CDN and not in your project – Dehn Hunsworth May 31 '23 at 16:37
  • I need to load it immediately on loading the screen. but the problem is large file size like 300mb makes the browser slow and the video becomes lagging. I want to render a video similar like a video streaming platforms where movies/ large files are rendered smoothly. – Gaurav Kaushal Jun 01 '23 at 06:07

1 Answers1

0

Streaming solutions do not actually load the entire video before playback starts - they are able to start playing back as soon as they have enough header information and enough frames from the start of the video. Play back then continues as the video continues to download.

This can be done either through simply requesting the video in 'pieces' using simple HTTP byte range requests, or it can be done by using dedicated Adaptive Bit Rate Streaming protocols like HLS and DASH (see more here: https://stackoverflow.com/a/42365034/334402).

For your case, you likely don't want the complexity of ABR streaming servers so byte range requesting should work fine. This will work without doing anything special in your react code - you can use the standard HTML5 tag - e.g.:

  return(
    <div className="video-wrapper">
        <video className="video-area" controls>
          <source src={props.source} type="video/mp4"/>
          Your browser does not support the video tag.
        </video>
    </div>
  )

There are a couple of conditions for this to work:

  • For MP4 videos the header data, or MOOV atom as it is known, generally needs to be at the start of the video rather than the end (although some browser are reportedly now clever enough to request and look at the end of the file if they can't find it at the start). See here for more info: https://trac.ffmpeg.org/wiki/HowToCheckIfFaststartIsEnabledForPlayback
  • Your server needs to support byte range requests - nearly all do, but you may need to check configuration ensure the functionality is enabled.
Mick
  • 24,231
  • 1
  • 54
  • 120