Как закрыть дочерний процесс Node.js FFMPEG, который активно транслируется из источника прямого захвата?
Я новичок в Node.js и выяснил, как использовать child.spawn для запуска экземпляра FFMPEG, который используется для захвата живого видео и отправки его на Adobe Media Server через rtmp.
Каждый пример использования FFMPEG в сочетании с Node.js был с ограниченным по времени примером, поэтому дочерний процесс закрывается, как только FFMPEG достигает конца файла, который он конвертирует.
В этом случае нет конца файла.
Если я создаю экземпляр:
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-канал на моей тестовой коробке.
Есть ли способ передать FFMPEG команду выключения через stdin в Node.js?
Заранее спасибо!
стог
4 ответа
Следующий код загружается моим основным 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 для получения события и соответствующих ему данных. В этом случае событие "истина" загружает файл module.js, который запускает сеанс захвата FFMPEG в режиме реального времени, передает его на RTMP-сервер и корректно завершает работу FFMPEG по истечении 10 секунд.
Моя следующая задача - отключить его с помощью события, запускаемого из веб-интерфейса, в отличие от текущего метода тестирования тайм-аута.
Глядя на диспетчер задач в Windows, процесс FFMPEG закрывается, как и процесс вторичного узла.
Причина этого в том, что ни один из найденных мною модулей node-ffmpeg не поддерживает потоковую передачу через ввод ввода. Похоже, что они в основном для перекодирования существующего контента. Конечным результатом этого в идеале будет веб-интерфейс, который может запускать и останавливать FFMPEG. В нашем случае мы заменим Adobe Flash Media Live Encoder в качестве источника для нашего Adobe Media Server из-за невозможности сохранения стандартных файлов mp4.
Вам нужно отправить EOF после того, как файл завершится потоковой передачей в ffmpeg. тогда ffmpeg завершит работу и завершит работу правильно
Вы можете просто убить это.
ffmpeg.kill(SIGHUB)
или любой другой сигнал убийства, который вы пожелаете, см. http://en.wikipedia.org/wiki/Unix_signal
Если я правильно понимаю ваш пример, вы передаете все аргументы процесса узла в ffmpeg, включая поток. Для того, чтобы получить ваш ffmeg.end()
чтобы работать, вы должны были транслироваться прямо из вашего процесса узла. Я думаю, что ffmpeg не останавливается, когда он непрерывно получает данные с вашей камеры.
Далее следует более или менее окончательное решение проблемы запуска и закрытия живого сеанса FFMPEG с использованием Node.js:
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", который создается с помощью child_process.fork() в корневом файле application.js. Он читает текстовый файл, в котором хранится "состояние". Это состояние переключается с помощью метода записи / чтения в корневом приложении. В событии on('data') он читает файл, и если он обнаруживает, что состояние изменилось на false, он затем выключает FFMPEG, записывая команду 'q' в stdin.
Помимо уточнения с помощью базы данных, если бы я реализовал ее в более широком масштабе, я более чем открыт для обратной связи относительно более элегантного способа кодирования этого.