Как закрыть дочерний процесс 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.

Помимо уточнения с помощью базы данных, если бы я реализовал ее в более широком масштабе, я более чем открыт для обратной связи относительно более элегантного способа кодирования этого.

Другие вопросы по тегам