0

I want to create a Lambda function that invoked whenever someone uploads to the S3 bucket. The purpose of the function is to take the uploaded file and if its a video file (mp4) so make a new file which is a preview of the last one (using ffmpeg). The Lambda function is written in nodejs. I took the code here for reference, but I do something wrong for I get an error saying that no input specified for SetStartTime:

//dependecies
var async = require('async');
var AWS = require('aws-sdk');
var util = require('util');
var ffmpeg = require('fluent-ffmpeg');

// get reference to S3 client 
var s3 = new AWS.S3();


exports.handler = function(event, context, callback) {
    // Read options from the event.
    console.log("Reading options from event:\n", util.inspect(event, {depth: 5}));
    var srcBucket = event.Records[0].s3.bucket.name;
    // Object key may have spaces or unicode non-ASCII characters.
    var srcKey    =
    decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));  
    var dstBucket = srcBucket;
    var dstKey    = "preview_" + srcKey;

    // Sanity check: validate that source and destination are different buckets.
    if (srcBucket == dstBucket) {
        callback("Source and destination buckets are the same.");
        return;
    }

    // Infer the video type.
    var typeMatch = srcKey.match(/\.([^.]*)$/);
    if (!typeMatch) {
        callback("Could not determine the video type.");
        return;
    }
    var videoType = typeMatch[1];
    if (videoType != "mp4") {
        callback('Unsupported video type: ${videoType}');
        return;
    }

    // Download the video from S3, transform, and upload to a different S3 bucket.
    async.waterfall([
        function download(next) {
            // Download the video from S3 into a buffer.
            s3.getObject({
                    Bucket: srcBucket,
                    Key: srcKey
                },
                next);
            },
        function transform(response, next) {
        console.log("response.Body:\n", response.Body);
        ffmpeg(response.Body)
            .setStartTime('00:00:03')
            .setDuration('10')   //.output('public/videos/test/test.mp4')
        .toBuffer(videoType, function(err, buffer) {
                        if (err) {
                            next(err);
                        } else {
                            next(null, response.ContentType, buffer);
                        }
                 });
        },
        function upload(contentType, data, next) {
            // Stream the transformed image to a different S3 bucket.
            s3.putObject({
                    Bucket: dstBucket,
                    Key: dstKey,
                    Body: data,
                    ContentType: contentType
                },
                next);
            }
        ], function (err) {
            if (err) {
                console.error(
                    'Unable to modify ' + srcBucket + '/' + srcKey +
                    ' and upload to ' + dstBucket + '/' + dstKey +
                    ' due to an error: ' + err
                );
            } else {
                console.log(
                    'Successfully modify ' + srcBucket + '/' + srcKey +
                    ' and uploaded to ' + dstBucket + '/' + dstKey
                );
            }

            callback(null, "message");
        }
    );
};

So what am I doing wrong?

Gold Fish
  • 445
  • 6
  • 16
  • If the video is being uploaded multi-part you may be receiving an event for an incomplete upload. – Dave Maple Feb 04 '17 at 12:28
  • Probably not your problem, but it looks like setDuration() takes an integral number of seconds like 10, or a timestamp string like '00:00:10'. – jarmod Feb 04 '17 at 21:36
  • I found out that ffmpeg() wants a path as an argument. Anyway, it still doesn't work. I changed the code so it won't run in async.waterfall but in callbacks as you can see here: http://stackoverflow.com/questions/42129025/download-modify-and-upload-video-with-s3 – Gold Fish Feb 09 '17 at 05:40

0 Answers0