Node.js: realtime conversion from jpeg images to video file

后端 未结 3 510
轮回少年
轮回少年 2021-02-05 16:40

I\'m using node.js and through the socket.io library I receive chunks of data that are actually jpeg images. These images are frames of a realtime video captured from a remote w

相关标签:
3条回答
  • 2021-02-05 16:48

    FFMPEG supports streams as inputs, as stated in the docs.

    You can add any number of inputs to an Ffmpeg command. An input can be [...] a readable stream

    So for instance it supports using

    ffmpeg().input(fs.createReadStream('/path/to/input3.avi'));
    

    which creates a Readable stream from the file at '/path/to/input3.avi'.

    I don't know anything about FFMPEG, but you may pull your messages coming from socket.io (messages may be a Buffer already) and wrap it with your own implementation of Readable stream.

    0 讨论(0)
  • 2021-02-05 16:48

    Using require("child_process") you can use ffmpeg, or there are probably npm modules to help with this. ffmpeg will allow you to first take a list of jpegs and convert that to a video, second you can add a list (or just one) jpegs to the beginning or end of videos.

    0 讨论(0)
  • 2021-02-05 16:50

    I think you should look at videofy

    var exec = require("child_process").exec;
    var escape = require("shell-escape");
    var debug = require("debug")("videofy");
    var mkdirp = require("mkdirp");
    var uid = require("uid2");
    
    /*
     *  Expose videofy
     */
    
    module.exports = videofy;
    
    /**
     * Convert `input` file to `output` video with the given `opts`:
     *
     *  - `rate` frame rate [10]
     *  - `encoders` the video codec format, default is libx264
     *
     * @param {String} input
     * @param {String} output
     * @return
     * @api public
     */
    function videofy(input, output, opts, fn) {
        if (!input) throw new Error('input filename required');
        if (!output) throw new Error('output filename required');
    
        var FORMAT = '-%05d';
    
        // options
        if ('function' == typeof opts) {
            fn = opts;
            opts = {};
        } else {
            opts = opts || {};
        }
    
        opts.rate = opts.rate || 10;
        opts.codec = opts.codec || 'libx264';
    
        // tmpfile(s)
        var id = uid(10);
        var dir = 'tmp/' + id;
        var tmp = dir + '/tmp' + FORMAT + '.jpg';
    
    
        function gc(err) {
            debug('remove %s', dir);
            exec('rm -fr ' + dir);
            fn(err);
        }
    
        debug('mkdirp -p %s', dir);
    
        mkdirp(dir, function(error) {
            if (error) return fn(error);
    
            // convert gif to tmp jpg
            var cmd = ['convert', input, tmp];
            cmd = escape(cmd);
    
            debug('exec %s', cmd);
            // covert jpg collection to video
            exec(cmd, function(err) {
    
                if (err) return gc(err);
    
                var cmd = ['ffmpeg'];
    
                cmd.push('-f', 'image2');
                cmd.push('-r', String(opts.rate));
                cmd.push('-i', tmp);
                cmd.push('-c:v', String(opts.codec));
                cmd.push(output);
    
                cmd = escape(cmd);
    
                debug("exec %s", cmd);
    
                exec(cmd, gc);
            });
        });
    }
    
    0 讨论(0)
提交回复
热议问题