UltrasoundJelly UltrasoundJelly - 2 months ago 40
Node.js Question

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.

Answer

If anyone happens to need an answer to this question: I do have a solution to this, but I have no idea if this is considered best practice. I couldn't find any good documentation for including 3rd party precompiled binaries, so I just fiddled with it until it finally worked. Here's what I did (starting with the electron quick start, node.js v6):

From the app directory I ran the following commands to include the ffmpeg binary as a module:

mkdir node_modules/ffmpeg
cp /usr/local/bin/ffmpeg node_modules/ffmpeg/
ln -s ../ffmpeg/ffmpeg node_modules/.bin/ffmpeg

(replace /usr/local/bin/ffmpeg with your current binary path, download it from here) Placing the link allowed electron-packager to include the binary I saved to node_modules/ffmpeg/.

Then to get the bundled app path I installed the npm package app-root-dir by running the following command:

npm i -S app-root-dir

Since I could then get the app path, I just appended the subfolder for my binary and spawned from there. This is the code that I placed in renderer.js:.

var appRootDir = require('app-root-dir').get();
var ffmpegpath=appRootDir+'/node_modules/ffmpeg/ffmpeg';
console.log(ffmpegpath);

const
    spawn = require( 'child_process' ).spawn,
    ffmpeg = spawn( ffmpegpath, ['-i',clips_input[0]]);  //add whatever switches you need here

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