我如何关闭一个Node.js的FFMPEG子进程,它是活跃的流从一个实时捕获源



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

我所见过的FFMPEG与Node.js结合使用的每个例子都有时间限制,因此一旦FFMPEG到达它正在转换的文件的末尾,子进程就会关闭。

在这种情况下,没有"end of file"

如果我实例化:

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

它创建实时提要。

我已经尝试使用:

立即关闭子进程
    setTimeout(function() {
        ffmpeg.stdin.resume();
        ffmpeg.stdin.write('insert command to echo q to close FFMPEG');
        ffmpeg.stdin.end();
    });

然而,这似乎不起作用。在我的测试框上,我仍然可以看到我的rtmp提要。

是否有任何方法通过stdin在Node.js中传递FFMPEG关闭命令?

提前感谢!

瑞克

我的主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'事件加载模块.js文件,该文件启动FFMPEG的实时捕获会话,将其提供给RTMP服务器,并在超时10秒后优雅地关闭FFMPEG。

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

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

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

你可以直接杀死它。

ffmpeg.kill(SIGHUB)

或任何其他您希望的终止信号,参见http://en.wikipedia.org/wiki/Unix_signal


如果我正确理解您的示例,您将节点进程的所有参数传递给ffmpeg,包括流。为了让您的ffmeg.end()工作,您必须直接从您的节点进程流。我认为ffmpeg不停止时,它不断接收数据从您的相机

下面是使用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,则通过向stdin写入'q'命令关闭FFMPEG。

如果我要在更大的规模上实现它,那么除了通过使用数据库来改进它之外,我更愿意听取关于更优雅的编码方式的反馈。

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

相关内容

  • 没有找到相关文章

最新更新