如何将预编译的二进制文件与电子捆绑在一起

Ult*_*lly 12 ffmpeg node.js electron

我试图用电子应用程序包含预编译的二进制文件.我开始使用电子快速启动应用程序并修改我的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}`);
});
Run Code Online (Sandbox Code Playgroud)

我已将预编译的ffmpeg二进制文件放入node_modules/.bin/.在开发面板中一切都很好用,但是当我使用电子打包器设置应用程序时,它会spawn error ENOENT在触发时向控制台抛出一个.我确实在SO上找到了一个非常相似的问题,但这个问题似乎没有得到明确的回答.电子打包npm页面确实显示它们可以捆绑,但我找不到任何关于如何操作的文档.

gim*_*ete 27

问题是electron-builder或者electron-packager将依赖项捆绑到asar文件中.似乎如果依赖项具有二进制文件,node_modules/.bin它就足够聪明,不能打包它.

这是对ASAR包装文档electron-builder该主题.它说

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

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

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

  "build": {
    "asarUnpack": [
      "**/app/node_modules/some-module/*"
    ],
Run Code Online (Sandbox Code Playgroud)

对于你的特殊情况

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

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

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

  • 现在我们需要稍微更改代码以获得ffmpeg使用此代码的正确路径:( require('ffmpeg-static').path.replace('app.asar', 'app.asar.unpacked')如果我们处于开发阶段,replace()则不会替换任何正常的代码).

如果您使用的是webpack(或其他javascript捆绑包)

我遇到了require('ffmpeg-static').path在渲染器进程中返回相对路径的问题.但问题似乎是webpack改变了模块的需求方式,并阻止ffmpeg-static提供完整的路径.在Dev Tools中,require('ffmpeg-static').path当手动运行时工作正常,但是当在捆绑代码中执行相同操作时,我总是得到相对路径.所以这就是我所做的.

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


小智 6

我知道我有点晚了,但只想提一下ffbinaries我不久前为此目的创建的 npm 包。

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


Ult*_*lly 2

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

从应用程序目录中,我运行以下命令以将 ffmpeg 二进制文件包含为模块:

mkdir node_modules/ffmpeg
cp /usr/local/bin/ffmpeg node_modules/ffmpeg/
ln -s ../ffmpeg/ffmpeg node_modules/.bin/ffmpeg
Run Code Online (Sandbox Code Playgroud)

(将 /usr/local/bin/ffmpeg 替换为您当前的二进制路径,从此处下载)放置链接允许 electro-packager 包含我保存到 node_modules/ffmpeg/ 的二进制文件。

然后,为了获取捆绑的应用程序路径,我通过运行以下命令安装了 npm 包 app-root-dir:

npm i -S app-root-dir
Run Code Online (Sandbox Code Playgroud)

因为我可以获取应用程序路径,所以我只是附加了我的二进制文件的子文件夹并从那里生成。这是我放置在 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}` );
    });
Run Code Online (Sandbox Code Playgroud)