¿Cómo puedo agrupar un binario precomstackdo con un electrón?

Estoy tratando de incluir un binario precomstackdo con una aplicación electrónica. Comencé con la aplicación electrónica de inicio rápido y modifiqué mi archivo renderer.js para incluir este código que se activa cuando se suelta un archivo en el cuerpo:

 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}` ); }); 

He colocado mi binario ffmpeg precomstackdo en node_modules/.bin/ . Todo funciona bien en el panel de desarrollo, pero cuando uso el empaquetador de electrones para configurar la aplicación, arroja un spawn error ENOENT a la consola cuando se activa. Encontré una pregunta muy similar en SO, pero la pregunta no parece ser contestada definitivamente. La página npm en el empaquetador de electrones muestra que se pueden empaquetar, pero no puedo encontrar ninguna documentación sobre cómo hacerlo.

El problema es que electron-builder electron-packager o electron-packager su dependencia en el archivo asar . Parece que si la dependencia tiene un binario en node_modules/.bin es lo suficientemente inteligente como para no empaquetarlo.

Esta es la documentación para el empaquetado de asar para electron-builder de electron-builder sobre ese tema. Dice

Los módulos de nodo, que deben ser desempaquetados, serán detectados automáticamente

Entiendo que está relacionado con los binarios existentes en node_modules/.bin .

Si el módulo que está utilizando no se desempaqueta automáticamente, puede deshabilitar el archivado de asar completo o indicar explícitamente a electron-builder que no empaque ciertos archivos. Lo haces en tu archivo package.json como este:

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

Para su caso particular

Me encontré con el mismo problema con ffmpeg y esto es lo que he hecho:

  • Utilice ffmpeg-static . Este paquete agrupa binarios ffmpeg comstackdos estáticamente para Windows, Mac y Linux. También proporciona una forma de obtener la ruta completa del binario para el sistema operativo que está ejecutando: require('ffmpeg-static').path
  • Esto funcionará bien en el desarrollo, pero todavía tenemos que solucionar el problema de distribución.
  • Dígale a electron-builder que no empaque el módulo ffmpeg-static :

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

  • Ahora necesitamos cambiar ligeramente el código para obtener la ruta correcta a ffmpeg con este código: require('ffmpeg-static').path.replace('app.asar', 'app.asar.unpacked') (si estamos en desarrollo el replace() no reemplazará nada que esté bien).

Si está utilizando un paquete web (u otro empaquetador de javascript)

Me encontré con el problema que require('ffmpeg-static').path devolvía una ruta relativa en el proceso del renderizador. Pero el problema parecía ser que el paquete web cambia la forma en que se requiere el módulo y eso evita que ffmpeg-static proporcione una ruta completa. En las herramientas de desarrollo, la require('ffmpeg-static').path Funcionaba bien cuando se ejecutaba manualmente, pero al hacer lo mismo en el código empaquetado siempre obtenía una ruta relativa. Así que esto es lo que hice.

  • En el proceso principal, agregue esto antes de abrir BrowserWindow : global.ffmpegpath = require('ffmpeg-static').path.replace('app.asar', 'app.asar.unpacked') . El código que se ejecuta en el proceso principal no está incluido en el paquete web, por lo que siempre obtengo una ruta completa con este código.
  • En el proceso del procesador, seleccione el valor de esta manera: require('electron').remote.getGlobal('ffmpegpath')

Si resulta que alguien necesita una respuesta a esta pregunta: tengo una solución para esto, pero no tengo idea si esto se considera la mejor práctica. No pude encontrar ninguna buena documentación para incluir binarios precomstackdos de terceros, así que simplemente jugué con ella hasta que finalmente funcionó. Esto es lo que hice (comenzando con el inicio rápido de electron, node.js v6):

Desde el directorio de aplicaciones ejecuté los siguientes comandos para incluir el binario ffmpeg como un módulo:

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

(Reemplace / usr / local / bin / ffmpeg con su ruta binaria actual, descárguelo desde aquí) Al colocar el enlace, el paquete de electrones incluido para incluir el binario que guardé en node_modules / ffmpeg /.

Luego, para obtener la ruta de la aplicación incluida, instalé el paquete npm app-root-dir ejecutando el siguiente comando:

 npm i -S app-root-dir 

Como pude obtener la ruta de la aplicación, simplemente anexé la subcarpeta para mi binario y la generé desde allí. Este es el código que puse en 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}` ); }); 

Sé que llego un poco tarde, pero solo quería mencionar el paquete ffbinaries ffbinaries que creé hace un tiempo exactamente para este propósito.

Le permitirá descargar los archivos binarios ffmpeg / ffplay / ffserver / ffprobe a la ubicación especificada durante el inicio de la aplicación (por lo que no necesita empaquetarlo con su aplicación) o en una configuración de CI. Puede autodetectar la plataforma, también puede especificarla manualmente.