一尘不染

将预编译的二进制文件捆绑到电子应用程序中

node.js

关于如何将像imagemagick这样的第三方预编译二进制文件包含到电子应用程序中,是否有很好的解决方案?有node.js模块,但它们都是包装程序或与系统范围内已安装库的本地绑定。我想知道是否可以在发行版中捆绑预编译的二进制文件。


阅读 349

收藏
2020-07-07

共1个答案

一尘不染

请参阅 下面的 UPDATE (此方法现在并不理想)。

我确实找到了解决方案,但是我不知道这是否被视为最佳实践。我找不到包含第三方预编译二进制文件的任何好的文档,因此我一直在弄弄它直到最终与我的ffmpeg二进制文件一起使用。这是我做的(从电子快速入门,node.js
v6开始):

Mac OS X方法

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

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

(替换/usr/local/bin/ffmpeg为当前的二进制路径,请从此处下载)放置链接可使电子包装程序包括我保存到的二进制文件node_modules/ffmpeg/

然后获取捆绑的应用程序路径(以便我可以为二进制文件使用绝对路径…不管我做什么,相对路径似乎都不起作用),我通过运行以下命令安装了npm软件包app-
root-dir命令:

npm i -S app-root-dir

现在有了根应用程序目录,我只需为二进制文件附加子文件夹并从那里生成。这是我放在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}` );
        });

Windows方法

  1. 打开电子基础文件夹(electron-quick-start是默认名称),然后进入node_modules文件夹。在此处创建一个名为ffmpeg的文件夹,然后将静态二进制文件复制到该目录中。注意:它必须是二进制文件的静态版本,因为ffmpeg我在这里获取了最新的Windows版本。

  2. 为了获取捆绑的应用程序路径(以便我可以为二进制文件使用绝对路径…不管我做什么,相对路径似乎都不起作用),我通过运行以下命令安装了npm包app-root-dir从我的应用目录中的命令提示符:

     npm i -S app-root-dir
    
  3. 在您的node_modules文件夹中,导航到.bin子文件夹。您需要在此处创建几个文本文件,以告知节点包括刚复制的二进制exe文件。使用您喜欢的文本编辑器并创建两个文件,其中一个文件的名称ffmpeg如下:

        #!/bin/sh
    basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")

    case `uname` in
        *CYGWIN*) basedir=`cygpath -w "$basedir"`;;
    esac

    if [ -x "$basedir/node" ]; then
      "$basedir/node"  "$basedir/../ffmpeg/ffmpeg" "$@"
      ret=$?
    else
      node  "$basedir/../ffmpeg/ffmpeg" "$@"
      ret=$?
    fi
    exit $ret

第二个文本文件名为ffmpeg.cmd

    @IF EXIST "%~dp0\node.exe" (
     "%~dp0\node.exe"  "%~dp0\..\ffmpeg\ffmpeg" %*
    ) ELSE (
       @SETLOCAL
     @SET PATHEXT=%PATHEXT:;.JS;=;%
     node  "%~dp0\..\ffmpeg\ffmpeg" %*
    )

接下来,您可以按以下步骤在Windows电子发行版(位于renderer.js中)中运行ffmpeg(我也使用了app-root-
dir节点模块)。请注意添加到二进制路径中的引号,如果您的应用安装到带有空格的目录(例如C:\Program Files\YourApp),则没有这些空格将无法使用。

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

    const
        spawn = require( 'child_process' ).spawn;
        var ffmpeg = spawn( 'cmd.exe', ['/c',  '"'+ffmpegpath+ '"', '-i', clips_input[0]]);  //add whatever switches you need here, test on command line first
    ffmpeg.stdout.on( 'data', data => {
         console.log( `stdout: ${data}` );
     });
    ffmpeg.stderr.on( 'data', data => {
         console.log( `stderr: ${data}` );
     });

更新:统一的简单方法

嗯,随着时间的推移和Node的更新,这种方法不再是包含预编译二进制文件的最简单方法。它仍然有效,但是npm install运行时,node_modules下的二进制文件夹将被删除,必须再次替换。以下方法适用于Node v12。

此新方法消除了符号链接的需要,并且在Mac和Windows中也类似地工作。相对路径现在似乎有效。

  1. 您仍然需要appRootDir: npm i -S app-root-dir

  2. bin在我ffmpeg的示例中,在应用程序的根目录下创建一个名为的文件夹,并将预编译的静态二进制文件放在此处。

  3. 在渲染器脚本中使用以下代码:

    const appRootDir = require('app-root-dir').get();
    const ffmpegpath = appRootDir + '/bin/ffmpeg';
    const spawn = require( 'child_process' ).spawn;
    const child = spawn( ffmpegpath, ['-i', inputfile, 'out.mp4']);  //add whatever switches you need here, test on command line first
    child.stdout.on( 'data', data => {
        console.log( `stdout: ${data}` );
    });
    child.stderr.on( 'data', data => {
        console.log( `stderr: ${data}` );
    });
2020-07-07