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.
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.
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/*"
],
I ran into the same issue with ffmpeg
and this is what I've done:
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
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).
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.
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.require('electron').remote.getGlobal('ffmpegpath')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With