如何从Lambda正确运行二进制文件?

时间:2018-10-05 17:20:59

标签: node.js aws-lambda

我正在尝试从lambda运行sox音频二进制文件,我遵循了本指南:http://marcelog.github.io/articles/static_sox_transcoding_lambda_mp3.html 因此,我使用最新的Amazon Linux版本的docker创建了sox二进制文件,并将lambda部署为具有以下结构的zip软件包:

sox
index.js

Lambda代码:

exports.handler = async (event) => {
    initializeContext();

    try {
        const object = await getFile("test.mp3");

        const fs = require('fs');
        fs.writeFileSync("/tmp/test.mp3", object.Body);

        let result = child_process.execFileSync('sox', ['/tmp/test.mp3', '/tmp/testOutput.mp3', ... <filter params here>], {
            encoding: 'ascii'
            // shell: true
        });

        const file = fs.readFileSync("/tmp/testOutput.mp3");

        await putFile("testOutput.mp3", file);
    }
    catch(err) {
        try {
            await log("error", err); 
        }
        catch(err) {}
    }
};
let getFile = async function(fileName) {
    const params = {
        Bucket: bucket,
        Key: fileName
    };
    return await s3.getObject(params).promise();
};

let putFile = async function(fileName, body) {
    const params = {
        Bucket: bucket,
        Key: fileName,
        Body: body
    };
    await s3.putObject(params).promise();
};

因此,我需要从S3获取文件,对其进行处理并返回结果。 S3加载经过测试可以工作。但是,尝试启动“ sox”过程时出现“ EACCES”错误。 我想念什么?是否可以源自我使用了上一个Amazon Linux映像而Lambda使用了更旧版本的事实?

2 个答案:

答案 0 :(得分:1)

我在处理音频文件时遇到了麻烦。 npm软件包很方便。

https://github.com/stojanovic/lambda-audio

如果您的命令是

  

sox input.mp3 -c 1 output.wav

您的节点代码将如下所示,

const lambdaAudio = require('lambda-audio')
lambdaAudio.sox('./input.mp3 -c 1 /tmp/output.wav')
  .then(response => {
    // Do something when the file was converted
  })
  .catch(errorResponse => {
    console.log('Error from the sox command:', errorResponse)
  })

并将所有复杂的问题留在npm软件包中。

希望有帮助。

答案 1 :(得分:0)

最后,我发现要确保文件许可权,我必须在Amazon Linux docker映像内创建zip包。所以你需要

npm i lambda-audio

在其中,然后将node_modules与index.js一起压缩。 我的lambda包zip根文件夹是:

node_modules // npm i lambda-audio result
index.js

具有内存消耗优化功能的Node 8.10运行时工作解决方案:

process.env["PATH"] = process.env["PATH"] + ":" + process.env["LAMBDA_TASK_ROOT"];

const AWS = require("aws-sdk");
const s3 = new AWS.S3();
const lambdaAudio = require("lambda-audio");

let bucket;

exports.handler = async (event) => {
    try {
        bucket = event.bucket;
        const { inputFileName, outputFileName } = event;

        const fs = require("fs");
        const inputStream = fs.createWriteStream("/tmp/input.mp3");

        await getFileToStream(inputFileName, inputStream);

        await lambdaAudio.sox("/tmp/input.mp3 /tmp/output.mp3 <YOUR FILTERS HERE>);

        fs.unlinkSync("/tmp/input.mp3"); // removing unused input file

        const outputStream = fs.createReadStream("/tmp/output.mp3");
        await uploadFileFromStream(outputFileName, outputStream);
    }
    catch(err) {
        // Logging
    }
};

let getFileToStream = async function(fileName, writeStream) {
    const params = {
        Bucket: bucket,
        Key: fileName
    };
    const readStream = s3.getObject(params).createReadStream();

    const end = new Promise((resolve, reject) => {
        writeStream.on('close', () => resolve());
        writeStream.on('error', (err) => reject(err));
        readStream.on('error', (err) => reject(err));
    });

    readStream.pipe(writeStream);

    return end;
};

let uploadFileFromStream = async function(fileName, readStream) {
    const params = {
        Bucket: bucket,
        Key: fileName,
        Body: readStream
    };
    return await s3.upload(params).promise();
};