我是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将完成并正确关闭