Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I bundle a precompiled binary with electron

I am trying to include a precompiled binary with an electron app. I began with electron quick start app and modified my renderer.js file to include this code that is triggered when a file is dropped on the body:

spawn = require('child_process').spawn,
  ffmpeg = spawn('node_modules/.bin/ffmpeg', ['-i', clips[0], '-an', '-q:v', '1', '-vcodec', 'libx264', '-y', '-pix_fmt', 'yuv420p', '-vf', 'setsar=1,scale=trunc(iw/2)*2:trunc(ih/2)*2,crop=in_w:in_h-50:0:50', '/tmp/out21321.mp4']);

ffmpeg.stdout.on('data', data => {
  console.log(`stdout: ${data}`);
});
ffmpeg.stderr.on('data', data => {
  console.log(`stderr: ${data}`);
});

I have placed my precompiled ffmpeg binary in node_modules/.bin/. Everything works great in the dev panel, but when I use electron-packager to set up the app, it throws a spawn error ENOENT to the console when triggered. I did find a very similar question on SO, but the question doesn't seem to be definitively answered. The npm page on electron-packager does show that they can be bundled, but I cannot find any documentation on how to do so.

like image 602
UltrasoundJelly Avatar asked Jul 13 '16 21:07

UltrasoundJelly


People also ask

How do you distribute an electron app?

To distribute your app manually, you need to download Electron's prebuilt binaries. Next, the folder containing your app should be named app and placed in Electron's resources directory as shown in the following examples. The location of Electron's prebuilt binaries is indicated with electron/ in the examples below.


1 Answers

The problem is that electron-builder or electron-packager will bundle your dependency into the asar file. It seems that if the dependency has a binary into node_modules/.bin it is smart enough to not package it.

This is the documentation for asar packaging for electron-builder on that topic. It says

Node modules, that must be unpacked, will be detected automatically

I understand that it is related to existing binaries in node_modules/.bin.

If the module you are using is not automatically unpacked you can disable asar archiving completely or explicitly tell electron-builder to not pack certain files. You do so in your package.json file like this:

  "build": {
    "asarUnpack": [
      "**/app/node_modules/some-module/*"
    ],

For your particular case

I ran into the same issue with ffmpeg and this is what I've done:

  • Use ffmpeg-static. This package bundles statically compiled ffmpeg binaries for Windows, Mac and Linux. It also provides a way to get the full path of the binary for the OS you are running: require('ffmpeg-static').path
  • This will work fine in development, but we still need to troubleshoot the distribution problem.
  • Tell electron-builder to not pack the ffmpeg-static module:

    "build": { "asarUnpack": [ "**/app/node_modules/ffmpeg-static/*" ],

  • Now we need to slightly change the code to get the right path to ffmpeg with this code: require('ffmpeg-static').path.replace('app.asar', 'app.asar.unpacked') (if we are in development the replace() won't replace anything which is fine).

If you are using webpack (or other javascript bundler)

I ran into the issue that require('ffmpeg-static').path was returning a relative path in the renderer process. But the issue seemed to be that webpack changes the way the module is required and that prevents ffmpeg-static to provide a full path. In the Dev Tools the require('ffmpeg-static').path was working fine when run manually, but when doing the same in the bundled code I was always getting a relative path. So this is what I did.

  • In the main process add this before opening the BrowserWindow: global.ffmpegpath = require('ffmpeg-static').path.replace('app.asar', 'app.asar.unpacked'). The code that runs in the main process is not bundled by webpack so I always get a full path with this code.
  • In the renderer process pick the value this way: require('electron').remote.getGlobal('ffmpegpath')
like image 70
gimenete Avatar answered Sep 28 '22 16:09

gimenete