我如何将一个预编译的二进制文件与电子打包在一起

我正在尝试包含一个预编译的二进制文件和一个电子应用程序。 我开始使用电子快速启动应用程序,并修改了我的renderer.js文件,以包含将文件放在主体上时触发的代码:

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

我已将预编译的ffmpeg二进制文件放入node_modules/.bin/ 。 在开发面板中一切都很好,但是当我使用电子包装器来设置应用程序时,触发时会向控制台抛出一个spawn error ENOENT 。 我的确发现了一个非常类似的问题 ,但这个问题似乎没有明确的答案。 电子包装商的npm页面确实表明它们可以捆绑在一起,但我找不到有关如何这样做的文件。

问题是electron-builder或者electron-packager会把你的依赖关系捆绑到asar文件中。 看起来,如果依赖关系在node_modules/.bin有一个二进制文件,那么它就足够聪明,不会打包它。

这是electron-builder关于该主题的asar封装文件 。 它说

将自动检测必须解压缩的节点模块

我知道它与node_modules/.bin现有二进制文件相关。

如果您正在使用的模块没有自动解压缩,则可以完全禁用asar归档或明确告诉electron-builder不打包某些文件。 你在你的package.json文件中这样做:

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

为你的特殊情况

我遇到了与ffmpeg相同的问题,这就是我所做的:

  • 使用ffmpeg-static 。 该软件包捆绑了针对Windows,Mac和Linux的静态编译的ffmpeg二进制文件。 它还提供了一种获取正在运行的操作系统的二进制文件的完整path的方法: require('ffmpeg-static').path
  • 这在开发中可以正常工作,但是我们仍然需要解决分发问题。
  • 告诉electron-builder不要包装ffmpeg-static模块:

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

  • 现在我们需要稍微改变一下代码,以得到正确的pathffmpeg这个代码: require('ffmpeg-static').path.replace('app.asar', 'app.asar.unpacked') (如果我们是在开发中, replace()不会取代任何好的东西)。

如果您使用的是webpack(或其他JavaScript打包程序)

我遇到了require('ffmpeg-static').path的问题,path在渲染器进程中返回相对path。 但是这个问题似乎是webpack改变了模块的需求,并阻止ffmpeg-static提供一个完整的path。 在开发工具中, require('ffmpeg-static').path在手动运行时工作正常,但是在捆绑代码中做同样的事情时,我总是得到一个相对path。 所以这就是我所做的。

  • 在主stream程中,在打开BrowserWindow之前添加: global.ffmpegpath = require('ffmpeg-static').path.replace('app.asar', 'app.asar.unpacked') 。 在主进程中运行的代码不会被webpack捆绑在一起,所以我总是得到这个代码的完整path。
  • 在渲染器进程中,以这种方式select值: require('electron').remote.getGlobal('ffmpegpath')

如果有人碰巧需要这个问题的答案:我有一个解决scheme,但我不知道这是否被认为是最佳实践。 我找不到任何包含第三方预编译二进制文件的好文档,所以我只是一直搞清楚它,直到最终运行。 这是我做的(从电子快速入门开始,node.js v6):

从app目录中,我运行以下命令,将ffmpeg二进制文件作为模块包含在内:

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

(用当前的二进制pathreplace/ usr / local / bin / ffmpeg,从这里下载)放置链接允许electron-packager包含我保存到node_modules / ffmpeg /的二进制文件。

然后,通过运行以下命令来获取绑定的应用程序path,我安装了npm软件包app-root-dir:

 npm i -S app-root-dir 

因为我可以得到应用程序的path,我只是追加我的二进制子文件夹,从那里产生。 这是我放在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}` ); }); 

我知道我有点晚了,但只是想提及ffbinaries npm包,我刚刚创build了刚刚为此目的。

它将允许您在应用程序启动过程中将ffmpeg / ffplay / ffserver / ffprobe二进制文件下载到指定位置(因此您不需要将其与应用程序捆绑在一起),也可以在CI设置中下载。 它可以自动检测平台,也可以手动指定。