如何关闭从实时捕获源主动流式传输的Node.js FFMPEG子进程?

时间:2013-01-07 21:17:38

标签: node.js ffmpeg streaming-video

我是Node.js的新手,并且已经想出如何利用child.spawn启动一个FFMPEG实例,用于捕获实时视频并通过rtmp将其发送到Adobe Media Server。

我看到的FFMPEG与Node.js一起使用的每个例子都带有时间限制的样本,因此一旦FFMPEG到达正在转换的文件的末尾,子进程就会关闭。

在这种情况下,没有“文件结束”。

如果我实例化:

    var ffmpeg = child.spawn('ffmpeg.exe', [args]);

它会创建实时Feed。

我已尝试立即关闭子进程:

    setTimeout(function() {
        ffmpeg.stdin.resume();
        ffmpeg.stdin.write('insert command to echo q to close FFMPEG');
        ffmpeg.stdin.end();
    });

然而,这似乎不起作用。我继续在我的测试盒上看到我的rtmp饲料。

有没有办法通过Node.js中的stdin传递FFMPEG关闭命令?

提前致谢!

瑞克

4 个答案:

答案 0 :(得分:1)

我的主app.js使用child_process.fork()方法将以下代码作为模块加载:

    var spawn = require('child_process').spawn;

    var ffmpeg = spawn('C:\\Program Files (x86)\\ffmpeg\\bin\\ffmpeg.exe', ['-y', '-threads', '-0', '-re', '-rtbufsize', '204800000', '-probesize', '4096', '-vsync', '2', '-async', '30', '-f', 'dshow', '-s', '320x240', '-i', 'video=Integrated Webcam:audio=Microphone Array (IDT High Defi', '-c:a', 'libvo_aacenc', '-ab', '48000', '-ar', '22050', '-ac', '2', '-c:v', 'libx264', '-s', '400x300', '-g', '96', '-x264opts', 'bitrate=1200', '-preset', 'ultrafast', '-profile:v', 'baseline', '-pix_fmt', 'yuv420p', '-aspect', '4:3', '-f', 'flv', 'rtmp://server']);

    setTimeout(function() {
        ffmpeg.stderr.on('data', function() {
            ffmpeg.stdin.setEncoding('utf8');
            ffmpeg.stdin.write('q');
            process.exit();
        });
    }, 10000);

远比我制作它复杂得多。主app.js是一个基本的HTML页面,它被提供并使用socket.io来接收事件及其相应的数据。在这种情况下,'true'事件会加载module.js文件,该文件启动FFMPEG的实时捕获会话,将其提供给RTMP服务器,并在10秒的超时时间内正常关闭FFMPEG。

我的下一个任务是通过从Web界面触发的事件关闭它,而不是当前的超时测试方法。

查看Windows中的任务管理器,FFMPEG进程将像辅助节点进程一样关闭。

原因是我发现的node-ffmpeg模块都没有支持通过捕获输入进行实时流式传输。它们似乎主要用于转码现有内容。理想情况下,最终结果将是一个基于Web的界面,可以启动和停止FFMPEG。我们的用例将取代Adobe Flash Media Live Encoder作为Adobe Media Server的源,因为它无法保存标准的mp4文件。

答案 1 :(得分:0)

你可以简单地kill

ffmpeg.kill(SIGHUB)

或您希望的任何其他杀戮信号,请参阅http://en.wikipedia.org/wiki/Unix_signal


如果我正确理解了您的示例,则将节点进程的所有args传递给ffmpeg,包括流。为了使ffmeg.end()能够正常工作,您必须直接从节点进程流式传输。我认为ffmpeg在连续从相机接收数据时不会停止。

答案 2 :(得分:0)

以下内容或多或少是使用Node.js启动和关闭实时FFMPEG会话问题的最终解决方案:

    var     spawn = require('child_process').spawn
,   fs = require('fs');


    function ffmpeg(cmd, opts, callback) {
    var p;
    //console.log(callback());
    if(p == undefined) {
        var p = spawn(cmd, opts);

        p.stderr.on('data', function(data) {
            /*p.stdin.setEncoding('utf8');
                p.stdin.write('q');
                process.exit()
            */
            fs.readFile(__dirname + '/server-state.json', function(error, data) {
                if(error) {
                        console.log(error); 
                    } else {
                        content = JSON.parse(data);
                        console.log(content['State']);

                        if(content['State'] == 'false') {
                            p.stdin.setEncoding('utf8');
                            p.stdin.write('q');
                            process.exit()
                        }
                    }
            });

        });

        return p;
    }

}

    ffmpeg_var = ffmpeg('C:\\Program Files (x86)\\ffmpeg\\bin\\ffmpeg.exe', ['-y', '-threads', '-0', '-re', '-rtbufsize', '204800000', '-probesize', '4096', '-vsync', '2', '-async', '30', '-f', 'dshow', '-s', '320x240', '-i', 'video=Integrated Webcam:audio=Microphone Array (IDT High Defi', '-c:a', 'libvo_aacenc', '-ab', '48000', '-ar', '22050', '-ac', '2', '-c:v', 'libx264', '-s', '400x300', '-g', '96', '-x264opts', 'bitrate=1200', '-preset', 'ultrafast', '-profile:v', 'baseline', '-pix_fmt', 'yuv420p', '-aspect', '4:3', '-f', 'mp4', __dirname + '/IntegrityTest.mp4'], function() {


    });

此代码封装在“module.js”文件中,该文件通过根application.js文件中的child_process.fork()实例化。它读取存储“状态”的文本文件。通过根应用程序中的写入/读取方法切换此状态。在on('data')事件中,它读取文件,如果它检测到状态已变为false,则它会通过将'q'命令写入stdin来关闭FFMPEG。

如果我要在更大范围内实施数据库,那么通过使用数据库来改进它之外,我不仅仅对有关更优雅的编码方式的反馈持开放态度。

答案 3 :(得分:0)

您需要在文件流式传输到ffmpeg后发送EOF。然后ffmpeg将正确完成并关闭