我是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关闭命令?
提前致谢!
瑞克
答案 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将正确完成并关闭