Skip to content
Advertisement

Loading local resources in an Electron App with a React frontend

I am working on an Electron App with a React front end that is aimed at performing some video tasks. At the moment, I am loading a video file on the backend, converting that to a base64 data format and then sending that to the React front end to use that as the source for the video player. This works as intended.

While this works great for smaller video files, there is a limit on how large the data being sent can be.

I was wondering if there’s an actual way to let React load the media file directly by passing the local url as the source? I know this is disallowed for web security reasons but my app is wrapped inside Electron and does not connect to the Internet.

If that is not possible, alternatively, what would be the best way to load large media files (sizes of 4GB and etc ..) to view it in the player?

Importing the video file directly inside the React Component is not an option because the video is dynamically imported by the user by selecting it from the local system.

Any help would be greatly appreciated.

Advertisement

Answer

I finally managed to find the solution to this. It is stated incorrectly in most places. So I decided to update what works for anyone else looking for an answer.

Do not disable webSecurity

Do NOT disable webSecurity as many places suggest. It is important to leave this on. If you have to do it, then you can set its value to webSecurity: app.isPackaged. This way during development it will be turned off but in a production build, it will be turned on. And because the app is being deployed from a file in the production build, local media works as intended.

But here’s the actual fix with webSecurity still enabled.

Solution

You need to create a custom protocol to handle your media. I had tried this many times before but unfortunately the code on the official docs for some reason does not return the values. So copying that directly just does not work.

app.whenReady().then(() => {
  // Create custom protocol for local media loading
  protocol.registerFileProtocol("media-loader", (request, callback) => {
    const url = request.url.replace("media-loader://", "");
    try {
      return callback(url);
    } catch (err) {
      console.error(error);
      return callback(404);
    }
  });

  // Create Window
  createWindow();
});

Once you have this new protocol setup, it is just a matter of loading your media directly using their absolute paths.

<video src={`media-loader://${path}`}></video>

With this setup, you no longer need to create an ObjectURL or pass the media files over IPC which is just not performant has a size limitation on how large a file you can load.

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement