Есть ip-камера, которая отдает rtsp. Через ffmpeg записывается это все в сегменты. Но если отключить камеру, то ffmpeg падает. Node.js не всегда получается отследить падение процесса. Вижу 2 варианта. И в том, и в том нужна помощь:
1. Научить ноду более тщательно отслеживать падение ffmpeg;
2. ffmpeg не закрывается даже если нет камеры, а когда она подключена - продолжает запись.
Подскажите советом или готовым решением, если есть.
Ezhyg, пожалуйста, внимательно прочитайте вопрос.
Как следует из него - нода отслеживает процессы ffmpeg и запускает их заново, если они падают. Но, к сожалению, не всегда.
Насчет подробностей и того, что там происходит - происходит запись потока с камеры в видеофайлики (сегменты), что опять видно из моего вопроса.
Насчет тегов - теги проставлены не просто так, а потому, что это должно работать и на лине и на окнах. Работает все это на ноде, а запись осуществляется через ffmpeg.
Люди, знающие в этой теме понимают, что значит запись rtsp-потока в сегменты через ffmpeg. Незнающие, собственно, тут не нужны.
Неспроста на этот вопрос подписалось много человек - значит вопрос насущный и задан верно.
Из ваших агровопросов я понимаю, что вы, мягко говоря, некомпетентны в этом вопросе - вопросе ffmpeg + командной строки, и что вы тут забыли, я не понимаю. И как модератор, задавая вопросы ТАКИМ образом (без малейшего понятия дипломатии), вы ведете себя максимально некорректно. Моя рекомендация - не влезать, когда не понимаете о чем речь и поучиться, хотя бы чуть-чуть, тактичности.
Михаил Захаров, вопрос надо формулировать яснее и понятнее, в смысле описание ситуации.
запись потока можно вести тысячей способов, потому и нужна конкретика.
И как модератор
Хм... и давно я модератором стал? Надо бы ТМ сообщить, а то они не в курсе :D
Я ведь не для себя стараюсь, вдруг кто-то захочет ответить, но не поймёт, что тут вообще происходит, в итоге - без помощи остаёшься ты, не я.
Михаил Захаров, не знаю, сколь полезным вам будет приведенные мою отрезки кода, но в моей реализации они работают.
Что и для чего я использую у себя ffmpeg
Имею у себя в локальной сети несколько ip и аналоговых камер, от которых я получаю rtsp.
Банально и не интересно просматривать эти камеры из приложения, или кривого родного веб-приложения, которые они предоставляют. Я взялся и написал свой микро-сервер, который будет выводить по web-socket видео на страницу сайта. Появилось соединение -> запустил ffmpeg который принимает с камер куски информации, перекодирует это в другой формат и шлет прямиком в WebSocket
модуль, который спавнит ffmpeg процесс
let child_process = require('child_process'),
winston = require('../../config/winston')({filePath: 'log/ffmpeg.log', label: "develop"});
/**
* Сервис приема и декодирования RTS потока от видеорегистратора,
* и отправка его по потоку на указанный адрес.
* @param options
* ip_out - адрес, на котором находится приемник декодированного потока
* url - адрес расположения rtsp вешателя
* port_out - принимающий порт
* serverNumber - порядковый номер сервера, на котором запускается данный сервис
* @constructor
*/
function CreateFFMpegStream(options) {
this.url = options.url;
this.options = options;
this.ip_out = options.ip_out || '127.0.0.1';
this.port_out = options.port_out;
this.secret = options.secret;
this.serverNumber = options.serverNumber;
this.createStream();
}
CreateFFMpegStream.prototype.createStream = function() {
winston.info(`FFMpeg ['${this.serverNumber}'] stream was started.`);
this.out_url = `http://${this.ip_out}:${this.port_out}/${this.secret}`;
this.ffmpeg_stream = child_process.spawn('ffmpeg', ["-rtsp_transport", "tcp", "-i", this.url, '-f', 'mpegts', '-codec:v', 'mpeg1video', '-r', '30', '-b:v', '800k', this.out_url], {cwd: __dirname}); //убрал декодировку видео '-codec:a', 'mp2', '-ar', '44100',
this.ffmpeg_stream.stderr.addListener('data', function(data) {
});
};
CreateFFMpegStream.prototype.closeStream = function() {
this.ffmpeg_stream.kill()
};
exports.FFMpegStream = CreateFFMpegStream;
код сервера, который будет принимать декодированные куски от ffmpeg и писать их в файл
// HTTP Server to accept incomming MPEG-TS Stream from ffmpeg
let streamServer = http.createServer( function(request, response) {
let params = request.url.substr(1).split('/');
winston.info('HTTP Server ['+ SERVNUMBER +'] to accept incomming MPEG-TS Stream from ffmpeg started.');
if (params[0] !== STREAM_SECRET) {
winston.warn('Failed Stream Connection ['+ SERVNUMBER +']: '+ request.socket.remoteAddress + ':' + request.socket.remotePort + ' - wrong secret.');
response.end();
}
response.connection.setTimeout(0);
winston.info(
'Stream Connected: ' +
request.socket.remoteAddress + ':' +
request.socket.remotePort
);
request.on('data', function(data){
socketServer.broadcast(data);
if (request.socket.recording) {
request.socket.recording.write(data);
}
});
request.on('end',function(){
winston.info('Close stream.');
if (request.socket.recording) {
request.socket.recording.close();
}
});
// Record the stream to a local file?
if (RECORD_STREAM) {
let path = 'recordings/' + "-" + SERVNUMBER+ "-"+ Date.now() + '.ts';
request.socket.recording = fs.createWriteStream(path);
}
}).listen(STREAM_PORT);
ну и собственно вывоз модуля, порождающего ffmpeg
ffmpeg = new FFMpeg_relay({
url: 'rtsp://<--тут лежит ваш url к камере с даннами логина-пароля-->&channel=' + CHANNEL + '&stream=0.sdp',
ip_out: '127.0.0.1', // адрес, на который будет потправляться декодированные части видео
port_out: STREAM_PORT,
secret: STREAM_SECRET,
serverNumber: SERVNUMBER
});
В дополнении ко всему: я намеренно сейчас заставил работать ffmpeg и декодировать видео. И обрубал серверу доступ к камерам. Физически. Процесс ffmepg не останавливал свою работу. После востановления доступа к камерам, для 2 из 3 камер автоматически продолжилось вещание. (Не могу сказать точно, какие это камеры, аналогивые или ip, но суть сохраняется).
Если смотреть по запущенным процессам во время обрыва доступам к камерам, то процессы ffmpeg продолжа.т свою работу(один процесс для каждой камеры).
Если вы дочитали до этого момента, могу предложить следующее решение:
Посколюку основопологающим является данный кусок кода:
request.on('data', function(data){
socketServer.broadcast(data);
if (request.socket.recording) {
request.socket.recording.write(data);
}
То можно предположить, что если в течении 5-10 секунд не поступало ни одного чанка информации, то скорей всего камера сдохла. А значит надо попробовать убить модуль порождающий ffmpeg и запустить его снова (если после восстановления соединение, не было продолжено вещание автоматически)
p.s. Если вы это все прочитали, и вас заинтересовало, могу дать доступ к закрытому репозиторию, где лежат исходники, привыденные выше.
p.s.s. Особо тапками не кидайтесь, код не очень изящный, но что есть то есть.
p.s.s. Надеюсь это то, что вы искали
Максим Сохряков, я очень благодарен тебе за то, что пытаешься мне помочь. Предлагаю обмениваться опытом и поддерживать оперативную связь в телеграме - @uffome