如何使用支持MP3的SoX二进制文件来支持具有AWS的Linux AMI限制的NodeJS AWS Lambda函数?

时间:2016-07-16 23:03:23

标签: linux amazon-ec2 lambda build sox

过去3个月我一直在研究这个问题而且完全陷入困境。

我正在尝试打包我的NodeJS AWS Lambda函数,该函数将使用SoX及其依赖项将音频文件转换为MP3。我可以通过遵循引用herehere的说明来获取我的代码以识别SoX二进制文件的自定义位置。我最终将此代码添加到我的Lambda函数调用的开头,以更新process.env PATH变量以包含自定义二进制文件的路径。

process.env['PATH'] = process.env['PATH'] + ':' 
+ path.join(process.env['LAMBDA_TASK_ROOT'], 'binaries');

这导致我的process.env PATH更新看起来像这样:

/usr/local/lib64/node-v4.3.x/bin:/usr/local/bin:/usr/bin/:/bin:/var/task/binaries

哪个看起来正确,binaries是包含我编译的sox二进制文件的目录。

由于我使用NodeJS,我不得不修改sox-audio NPM模块,因此它使用更新的process.env变量进行child_process execspawn调用。这允许代码找到二进制文件,但我在执行期间仍然收到错误。

Sox process exited with code 127 and signal null

据我所知,尽管它可以找到我所包含的SoX二进制文件,但它无法找到与SoX一起使用的命令,但是如果没有更多信息我就无法告诉它是什么。我以为是因为我不确定我是否包含了二进制文件所包含的所有文件。

为了尝试在支持MP3的情况下制作一个干净的SoX编译版本,我创建了一个新的EC2 linux实例,然后按照here提供的说明进行操作。

我一行一行地确保能够使其工作,并在安装了一些依赖项以启用编译(例如developer tools)之后,并通过导出构建PATH export PATH=$PATH:/usr/local/bin我能够通过MP3支持安装完整版本。我测试了它,它的工作方式与我的需要完全一样。

由于AWS Lambda函数在与AWS EC2实例相同的精简版Linux(Amazon Linux AMI)上运行,理论上,如果我可以导出SoX构建并将其包含在我的Lambda包中,那么我应该能够获得它起作用。

这就是我遇到麻烦的地方。构建本身的是什么?在/usr/local/bin中有一个SoX linux可执行文件,它是一个单独的文件,但是还有更多的文件似乎与使SoX及其依赖项工作有关。以下是我在工作版本中/usr/local/bin内的文件列表。

files within /usr/local/bin

我尝试通过FTP导出所有这些文件,然后将它们导入另一个干净的EC2实例,但即使在运行export PATH=$PATH:/usr/local/bin之后,由于依赖性问题,SoX也无法运行。很明显,仅导出这些文件是不够的。

  • 我如何导出以及如何导出以将我的工作版SoX与支持MP3的实例配合使用,并将其包含在我的AWS Lambda函数中?
  • 要使MP3工作的安装依赖项的长列表是否会使这变得不可能?
  • 是否有文件不仅仅是我需要包含的/usr/local/bin目录?

我真的不知道还有什么可以用的。请帮忙:(

2 个答案:

答案 0 :(得分:10)

我花了3个月才最后发帖,我在同一天弄明白了。

在做了一些更多的研究后,我得出结论,我需要创建一个静态版本的SoX,并具有转换MP3所需的依赖性。我最后整理了一个脚本来创建基于this blog postthis blog post的静态构建。

我将两者结合起来的原因是因为我使用的是亚马逊Linux AMI,这是非常准确的。因此,第二篇博客中提到的所有debian和apt-get内容都不太可行。但是,我需要确保安装了编译器,这样我就不会遇到任何错误。以下是我最终运行的内容。我以root身份做了所有事情,因为在EC2 Amazon Linux AMI实例上特权受到相当限制。唯一需要像普通用户一样运行的是最后的PATH导出。

sudo yum update
sudo yum install gcc44 gcc-c++ libgcc44 cmake –y

# now grab sox and its dependencies
mkdir -p deps
mkdir -p deps/unpacked
mkdir -p deps/built
mkdir -p deps/built/libmad
mkdir -p deps/built/sox
mkdir -p deps/built/lame
wget -O deps/sox-14.4.1.tar.bz2 "http://downloads.sourceforge.net/project/sox/sox/14.4.1/sox-14.4.1.tar.bz2?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fsox%2Ffiles%2Fsox%2F14.4.1%2F&ts=1416316415&use_mirror=heanet"
wget -O deps/libmad-0.15.1b.tar.gz "http://downloads.sourceforge.net/project/mad/libmad/0.15.1b/libmad-0.15.1b.tar.gz?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Fmad%2Ffiles%2Flibmad%2F0.15.1b%2F&ts=1416316482&use_mirror=heanet"
wget -O deps/lame-3.99.5.tar.gz "http://downloads.sourceforge.net/project/lame/lame/3.99/lame-3.99.5.tar.gz?r=http%3A%2F%2Fsourceforge.net%2Fprojects%2Flame%2Ffiles%2Flame%2F3.99%2F&ts=1416316457&use_mirror=kent"

# unpack the dependencies
pushd deps/unpacked
tar xvfpj ../sox-14.4.1.tar.bz2
tar xvfpz ../libmad-0.15.1b.tar.gz
tar xvfpz ../lame-3.99.5.tar.gz
popd

# build libmad, statically
pushd deps/unpacked/libmad-0.15.1b
./configure --disable-shared --enable-static --prefix=$(realpath ../../built/libmad)
# Patch makefile to remove -fforce-mem
sed s/-fforce-mem//g < Makefile > Makefile.patched
cp Makefile.patched Makefile
make
make install
popd

# build lame, statically
pushd deps/unpacked/lame-3.99.5
./configure --disable-shared --enable-static --prefix=$(realpath ../../built/lame)
make
make install
popd

# build sox, statically
pushd deps/unpacked/sox-14.4.1
./configure --disable-shared --enable-static --prefix=$(realpath ../../built/sox) \
    LDFLAGS="-L$(realpath ../../built/libmad/lib) -L$(realpath ../../built/lame/lib)" \
    CPPFLAGS="-I$(realpath ../../built/libmad/include) -I$(realpath ../../built/lame/include)" \
    --with-mad --with-lame --without-oggvorbis --without-oss --without-sndfile --without-flac  --without-gomp
make -s
make install
popd

cp deps/built/sox/bin/sox .
rm -rf deps/built
rm -rf deps/unpacked

在此之后,我以普通用户身份运行以下内容

export PATH=$PATH:/home/ec2-user

然后我可以跑sox!只需在终端中键入sox,就可以在终端窗口中显示sox命令列表。

更好的是,我能够下载单个sox linux可执行文件,然后将其上传到全新的EC2实例。我必须在新实例上运行以使其工作的唯一事情如下:

sudo yum update
sudo yum install gcc44 gcc-c++ libgcc44 cmake –y
export PATH=$PATH:/home/ec2-user

我担心我不得不尝试再次构建它而不进行yum更新或yum安装,因为我最终想把它放在Lambda函数中,但这不是必需的!当我将它添加到我的测试Lambda函数并上传时,根据云日志,它没有问题。这必然意味着Lambda容器中使用的Amazon Linux AMI已经安装了yum更新和正确的编译器。

答案 1 :(得分:1)

花了几天时间弄清楚这个问题之后,我终于有了最快的方法来解决这个问题。有一个名为lambda-audio的npm软件包,但是目前,它无法与Amazon Linux AMI 2一起使用,因为它缺少依赖项 libgomp.so.1

在安装了lambda-audio之后,转到原始项目的分支https://github.com/jsonmaur/lambda-audio,然后从lib64文件夹下载libgomp文件。在节点模块下的lambda-audio包中手动创建lib64文件夹,然后复制下载的libgomp文件。

然后,执行以下一项操作:

在Lambda函数顶部附近添加以下行:

process.env['LD_LIBRARY_PATH'] = process.env['LD_LIBRARY_PATH'] + ':' + '/var/task/node_modules/lambda-audio/lib64'

或将其添加到lambda的env变量中。

LD_LIBRARY_PATH: /var/task/node_modules/lambda-audio/lib64:$LD_PRIMARY_PATH

希望这可以节省一些头痛。