Sascha Heim
Sascha Heim

Reputation: 313

Node.JS: FFmpeg piped video encoding no thumbnail created

I want to pipe the video during upload to ffmpeg for realtime thumbnail creation. All went fine but no thumbnail.jpg was created and the ffmpeg stderr hangs after the libraries version display.

Updated: Ive updated my code but it also doesnt create a valid thumbnail.

var formidable = require('formidable'),
        http = require('http'),
        sys = require('sys'),
        spawn = require('child_process').spawn;

function spawnFfmpeg(exitCallback) {
    var args = ['-i', 'pipe:0', '-c:v', 'mjpeg', '-ss', '00:00:13', '-vframes', '1', '-s', '100x80', 'thumbnail.jpg']
    var ffmpeg = spawn('ffmpeg', args);
    console.log('Spawning ffmpeg ' + args.join(' '));

    ffmpeg.on('exit', exitCallback);
    ffmpeg.stderr.on('data', function(data) {
        console.log('grep stderr: ' + data);
    });
    return ffmpeg;
}

http.createServer(function(req, res) {
    if (req.url == '/' && req.method.toLowerCase() == 'get') {
        // show a file upload form
        res.writeHead(200, {'content-type': 'text/html'});
        res.end
                ('<form action="/upload" enctype="multipart/form-data" method="post">'
                        + '<input type="text" name="title"><br>'
                        + '<input type="file" name="upload" multiple="multiple"><br>'
                        + '<input type="submit" value="Upload">'
                        + '</form>'
                        );
    } else if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
        // parse a file upload
        var form = new formidable.IncomingForm();
        form.maxFieldsSize = 29 * 1024 * 1024;
        // Handle each part of the multi-part post
        var ffmpeg = spawnFfmpeg(function(code) {
            console.log('child process exited with code ' + code);
            res.end();
        });

        var form = new formidable.IncomingForm();
        // Handle each part of the multi-part post
        form.onPart = function(part) {
            // Handle each data chunk as data streams in
            part.addListener('data', function(data) {
                ffmpeg.stdout.pipe(res);
                res.pipe(ffmpeg.stdin);
                // Write each chunk to disk
                //savedFile.write(data);
            });
        };

        // Do it
        form.parse(req);
        return;
    }
}).listen(80, "127.0.0.1");

process.on('uncaughtException', function(err) {
});

Upvotes: 2

Views: 4362

Answers (2)

Sascha Heim
Sascha Heim

Reputation: 313

After Some research and many hours of testing ive found the correct solution ^_^

var formidable = require('formidable'),
        http = require('http'),
        sys = require('sys'),
        spawn = require('child_process').spawn;

function spawnFfmpeg(exitCallback) {
    var args = ['-i', 'pipe:0', '-c:v', 'mjpeg', '-ss', '00:00:13', '-vframes', '1', '-s', '100x80', 'thumbnail.jpg']
    var ffmpeg = spawn('ffmpeg', args);
    console.log('Spawning ffmpeg ' + args.join(' '));

    ffmpeg.on('exit', exitCallback);
    ffmpeg.stderr.on('data', function(data) {
        console.log('grep stderr: ' + data);
    });
    return ffmpeg;
}

http.createServer(function(req, res) {
    if (req.url == '/' && req.method.toLowerCase() == 'get') {
        // show a file upload form
        res.writeHead(200, {'content-type': 'text/html'});
        res.end
                ('<form action="/upload" enctype="multipart/form-data" method="post">'
                        + '<input type="text" name="title"><br>'
                        + '<input type="file" name="upload" multiple="multiple"><br>'
                        + '<input type="submit" value="Upload">'
                        + '</form>'
                        );
    } else if (req.url == '/upload' && req.method.toLowerCase() == 'post') {
        // parse a file upload
        var form = new formidable.IncomingForm();
        form.maxFieldsSize = 29 * 1024 * 1024;
        // Handle each part of the multi-part post
        var ffmpeg = spawnFfmpeg(function(code) {
            console.log('child process exited with code ' + code);
            res.end();
        });

        var form = new formidable.IncomingForm();
        // Handle each part of the multi-part post
        form.onPart = function(part) {
            // Handle each data chunk as data streams in
            part.addListener('data', function(data) {
                /*
                 * This only one line was the solution of my problem now all works really fast !! 500mbit like transloadit it does
                 */
                ffmpeg.stdin.write(data);
            });
        };

        // Do it
        form.parse(req);
        return;
    }
}).listen(80, "127.0.0.1");

process.on('uncaughtException', function(err) {
});

Upvotes: 3

pinxue
pinxue

Reputation: 1746

Your code looks like to start ffmpeg before the pipe is setup.

Following is not verified, but sounds like what you need:

http://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options

The 'stdio' option to child_process.spawn() is an array where each index corresponds to a fd in the child. The value is one of the following:

'pipe' - Create a pipe between the child process and the parent process. The parent end of the pipe is exposed to the parent as a property on the child_process object as ChildProcess.stdio[fd]. Pipes created for fds 0 - 2 are also available as ChildProcess.stdin, ChildProcess.stdout and ChildProcess.stderr, respectively.

Upvotes: 0

Related Questions