0
votes

I cannot convert a video file into an audio file inside AWS lambda function using Node JS. While running my lambda function it doesn't throw any error it executes without any error. But the audio file size is still 0 MB size. I am not able to find bugs or any issues in my code.

Here is my code,

const fs = require('fs');
const childProcess = require('child_process');
const AWS = require('aws-sdk');
const path = require('path');
AWS.config.update({
    region : 'us-east-2'
});
const s3 = new AWS.S3({apiVersion: '2006-03-01'});


exports.handler = (event, context, callback) => {
    process.env.PATH = process.env.PATH + ':/tmp/';
    process.env['FFMPEG_PATH'] = '/tmp/ffmpeg';
    const BIN_PATH = process.env['LAMBDA_TASK_ROOT'];
    process.env['PATH'] = process.env['PATH'] + ':' + BIN_PATH;

    childProcess.exec(
        'cp /var/task/ffmpeg /tmp/.; chmod 755 /tmp/ffmpeg;',
        function (error, stdout, stderr) {
            if (error) {
                console.log('Error occured',error);
            } else {
                var ffmpeg = '/tmp/ffmpeg';
                var createStream = fs.createWriteStream("/tmp/video.mp3");
                createStream.end();
                var params = {
                    Bucket: "test-bucket",
                    Key: event.Records[0].s3.object.key
                };
                s3.getObject(params, function(err, data) {
                    if (err) {
                        console.log("Error", err);
                    }
                    fs.writeFile("/tmp/vid.mp4", data.Body, function (err) {
                        if (err) console.log(err.code, "-", err.message);
                        return callback(err);
                    }, function() {
                        try {
                            var stats = fs.statSync("/tmp/vid.mp4");
                            console.log("size of the file1 ", stats["size"]);
                            try {
                                console.log("Yeah");
                                const inputFilename = "/tmp/vid.mp4";
                                const mp3Filename = "/tmp/video.mp3";
                                // // Convert the FLV file to an MP3 file using ffmpeg.
                                const ffmpegArgs = [
                                    '-i', inputFilename,
                                    '-vn', // Disable the video stream in the output.
                                    '-acodec', 'libmp3lame', // Use Lame for the mp3 encoding.
                                    '-ac', '2', // Set 2 audio channels.
                                    '-q:a', '6', // Set the quality to be roughly 128 kb/s.
                                    mp3Filename,
                                ];
                                try {
                                    const process = childProcess.spawnSync(ffmpeg, ffmpegArgs);
                                    console.log("stdout ", process.stdout);
                                    console.log("stderr ", process.stderr);
                                    console.log("tmp files ");
                                    fs.readdir('/tmp/', (err, files) => {
                                        files.forEach(file => {
                                            var stats = fs.statSync(`/tmp/${file}`);
                                            console.log("size of the file2 ", stats["size"]);
                                          console.log(file);
                                        });
                                      });

                                } catch (e) {
                                    console.log("error while converting video to audio ", e);
                                }

                                // return process;
                            } catch (e) {
                                console.log(e);
                            }
                        } catch (e) {
                            console.log("file is not complete", e);
                        }
                    }, function () {
                        console.log("checking ");
                        var stats = fs.statSync("/tmp/video.mp3");
                        console.log("size of the file2 ", stats["size"]);
                    });

                    return callback(err);
                });
            }
        }
    )
}

Code workflow

First of all, I have downloaded ffmpeg binary exec file and put into my project directory. After that, I compressed my project and put it into the lambda function. This lambda function will be triggered whenever the new files are uploaded into an S3 bucket. I have checked /tmp/ storage files and the audio file .mp3 present but the size is 0 MB.

Note

And also, in my code the below is not calling or this part is not reaching. When I look into Cloudwatch logs I can't see this console log messages. I don't know why this function is not calling.

function () {
        console.log("checking ");
        var stats = fs.statSync("/tmp/video.mp3");
        console.log("size of the file2 ", stats["size"]);
    });

Please help me to find the solution of this issue. I have spent a lot of times to figure out this issue. But I am not able to find the solution. Any suggestions are welcome!! Thanks,

1

1 Answers

0
votes

There are many limitations that can cause Lambda to bomb while trying to do conversions. The first thing you will need to do is compile ffmpeg for AWS Linux, generally, you have to compile with static links instead of dynamic links.

Another approach is to use a docker container and running it on aws ecs fargate, this will allow you to control the dependencies much easier, and you do not have any limitations on run time, and you can still outsource the management of machines to AWS.

Transcoding Video on Lambda https://intoli.com/blog/transcoding-on-aws-lambda/

Pre-compiled ffmpeg https://johnvansickle.com/ffmpeg/