2
votes

Trying out Amazon Lambda / nodejs 8. My goal is to launch ffmpeg, generate a short clip and upload it to S3 bucket.

I created the function following the image resize tutorial. Edited the code to get output from simple linux commands like ls or cat /proc/cpuinfo - all works.

Now, added the ffmpeg binary for i686 - ffmpeg static build by JohnVan Sickle (thanks!). Changed the code to launch simple ffmpeg command that is supposed to create sa 2-seconds small video clip.

That fails, according to logs, with the signal SIGSEGV returned to the "close" event handler of child_process.spawn()

As far as I understand, this could be caused by the ffmpeg binary incompatibility with the static build. Or by some mistake in my code.

Several npm modules rely on the static builds from johnvansickle.com/ffmpeg and there are no such issues filed on their github. Maybe there's some other mistake I made?

Should I compile ffmpeg myself under Amazon Linux AMI amzn-ami-hvm-2017.03.1.20170812-x86_64-gp2 which is under the hood of AWS Lambda?


upd. Launched EC2 t2.micro instance from the same AMI, downloaded the same ffmpeg static build, and it works just fine from the command line. Now I doubt that it is a compilation issue.

Also tried copying ffmpeg executable to /tmp/ffmpeg and chmod 755 just to make sure. Running simple ffmpeg --help command via child_process.execSync() returns "Error: Command failed: /tmp/ffmpeg --help"


const join = require('path').join;
const tmpdir = require('os').tmpdir;
const process = require('process');
const fs = require('fs');
const spawn = require('child_process').spawn;
const exec = require('child_process').exec;

const async = require('async');
const AWS = require('aws-sdk');
const util = require('util');

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


const tempDir = process.env['TEMP'] || tmpdir();
const filename = join(tempDir, 'test.mp4');
const s3 = new AWS.S3();


exports.handler = function(event, context, callback) {
  var dstBucket = srcBucket + "resized";
  var dstKey  = "render-test.mp4";

  async.waterfall([
    function transform(next) {
      var args = [
        '-filter_complex',
        '"testsrc=r=25:s=640x480:d=3"',
        '-an',
        '-y',
        '-hide_banner',
        '-c:v', 'libx264',
        filename,
      ];

      console.log("Will launch ffmpeg");
      const childProcess = spawn('ffmpeg', args);

      childProcess.on('close', function(e) {
        console.log('ffmpeg close event: ' + JSON.stringify(arguments));
        next();
      });

      console.log("After launched ffmpeg");
    },

    function upload(next) {
      ...
    }
  ], function (err) {
    ...
  });
};
2
I would have the Lambda execute "ffmpeg --help" initially as the most basic check of binary compatibility and exec permissions. - jarmod
@jarmod I tried that as well. First I do ls-lA on the ffmpeg executalbe to verifythe path is correct stdout: -rwxr-xr-x 1 slicer 497 43875308 Apr 7 12:37 /var/task/ffmpeg and empty stdout and stderr. Then when I try the ffmpeg --help it fails with error: Error: Command failed: /var/task/ffmpeg --help - Serge
Also tried copying the executable to /tmp/ and chmod 755 /tmp/ffmpeg prior to executing - same result. The file is there, has correct permissions: -rwxr-xr-x 1 sbx_user1051 495 43875308 Apr 7 18:56 /tmp/ffmpeg, but still Command failed: /tmp/ffmpeg --help - Serge
"Should I compile ffmpeg myself under Amazon Linux AMI amzn-ami-hvm-2017.03.1.20170812-x86_64-gp2" I'd say yes. That is, to my understanding, the primary reason thst image is made available... for compiling compatible binaries. - Michael - sqlbot
@Michael-sqlbot I made another test - launched EC2 t2.micro from the AMI, and downloaded the same static build of ffmpeg. It works fine from command line. So it might not be the build, but nodejs / Lambda restrictions that cause the issue. - Serge

2 Answers

3
votes

Fixed. Despite the misleading fact that static build of ffmpeg from JohnVanSickle.com does run on Amazon EC2 instance of the AMI, mentioned in Lambda environment, same binary fails to execute under AWS Lambda.

I compiled ffmpeg on the AWS EC2 t2.micro instance of the same AMI using markus-perl/ffmpeg-build-script. It also surprised me with an error of aom codec version. Changed one line in the script to disable the aom codec and ffmpeg finally has compiled. Took a couple of hours on the weak t2.micro instance.

The resulting ffmpeg binary is ~10Mb lighter than the static build mentioned above and runs on AWS Lambda just fine!

Hope this will help someone.

1
votes

Instead of building a binary on your own, you can use ffmpeg-lambda-layer ( https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:145266761615:applications~ffmpeg-lambda-layer)

Deploy it and add it as a layer to your function. Within your function the binary can be accessed as '/opt/bin/ffmpeg'.