Added error handling to FFmpeg (to prevent process shutdown)

Files are now written to a '.recording' file first and moved afterwards
This commit is contained in:
Mark van Renswoude 2016-08-07 10:05:18 +02:00
parent 8d3ce97474
commit 93b5e9d7c6
5 changed files with 59 additions and 15 deletions

3
.gitignore vendored
View File

@ -1,3 +1,4 @@
/config.js /config.js
/node_modules/ /node_modules/
*.sublime-workspace *.sublime-workspace
ipcam_cgi_sdk.pdf

View File

@ -51,7 +51,7 @@ app.get('/capture/:camId', function(req, res)
if (config.cams.hasOwnProperty(camId)) if (config.cams.hasOwnProperty(camId))
{ {
capture.start(config.cams[camId], moment()); capture.start(camId, config.cams[camId], moment());
console.log('Started capture for: ' + camId); console.log('Started capture for: ' + camId);
res.send(JSON.stringify([camId])); res.send(JSON.stringify([camId]));

View File

@ -20,6 +20,22 @@ util.inherits(FFMPEGProcessor, BaseProcessor);
FFMPEGProcessor.prototype.run = function() FFMPEGProcessor.prototype.run = function()
{ {
var self = this; var self = this;
var filename = helpers.createVariableFilename(this.cam.options.filename, this.now,
{
camId: this.camId
});
var tempFilename = filename + '.recording';
var cleanup = function()
{
fs.rename(tempFilename, filename, function(err)
{
console.log('Error: could not move ' + tempFilename + ' to ' + filename + ': ' + err.message);
self.doEnd();
});
}
var command = new FfmpegCommand(); var command = new FfmpegCommand();
command command
.input(this.cam.options.input) .input(this.cam.options.input)
@ -33,16 +49,19 @@ FFMPEGProcessor.prototype.run = function()
} }
command command
.output(helpers.createVariableFilename(this.cam.options.filename, this.now, .output(tempFilename)
{
camId: this.camId
}))
.videoCodec(this.cam.options.videoCodec) .videoCodec(this.cam.options.videoCodec)
.outputFormat(this.cam.options.outputFormat); .outputFormat(this.cam.options.outputFormat);
command.on('error', function(err, stdout, stderr)
{
console.log('Error: FFmpeg output:' + err.message);
cleanup();
});
command.on('end', function() command.on('end', function()
{ {
self.doEnd(); cleanup();
}); });
self.doStart(); self.doStart();

View File

@ -20,6 +20,14 @@ util.inherits(HTTPFFMPEGProcessor, BaseHTTPStreamProcessor);
HTTPFFMPEGProcessor.prototype.run = function() HTTPFFMPEGProcessor.prototype.run = function()
{ {
this.output = new stream.PassThrough(); this.output = new stream.PassThrough();
this.filename = helpers.createVariableFilename(this.cam.options.filename, this.now,
{
camId: this.camId
});
this.tempFilename = filename + '.recording';
var command = new FfmpegCommand(); var command = new FfmpegCommand();
command command
.input(this.output) .input(this.output)
@ -29,13 +37,16 @@ HTTPFFMPEGProcessor.prototype.run = function()
command.inputOption('-use_wallclock_as_timestamps 1'); command.inputOption('-use_wallclock_as_timestamps 1');
command command
.output(helpers.createVariableFilename(this.cam.options.filename, this.now, .output(this.tempFilename)
{
camId: this.camId
}))
.videoCodec(this.cam.options.videoCodec) .videoCodec(this.cam.options.videoCodec)
.outputFormat(this.cam.options.outputFormat) .outputFormat(this.cam.options.outputFormat);
.run();
command.on('error', function(err, stdout, stderr)
{
console.log('Error: FFmpeg output:' + err.message);
});
command.run();
HTTPFFMPEGProcessor.super_.prototype.run.call(this); HTTPFFMPEGProcessor.super_.prototype.run.call(this);
} }
@ -54,6 +65,11 @@ HTTPFFMPEGProcessor.prototype.cleanup = function()
this.output.end(); this.output.end();
this.output = null; this.output = null;
} }
fs.rename(this.tempFilename, this.filename, function(err)
{
console.log('Error: could not move ' + this.tempFilename + ' to ' + this.filename + ': ' + err.message);
});
} }
module.exports = HTTPFFMPEGProcessor; module.exports = HTTPFFMPEGProcessor;

View File

@ -15,10 +15,13 @@ util.inherits(HTTPRawProcessor, BaseHTTPStreamProcessor);
HTTPRawProcessor.prototype.run = function() HTTPRawProcessor.prototype.run = function()
{ {
this.output = fs.createWriteStream(helpers.createVariableFilename(this.cam.options.filename, this.now, this.filename = helpers.createVariableFilename(this.cam.options.filename, this.now,
{ {
camId: this.camId camId: this.camId
})); });
this.tempFilename = this.filename + '.recording';
this.output = fs.createWriteStream(this.tempFilename);
HTTPRawProcessor.super_.prototype.run.call(this); HTTPRawProcessor.super_.prototype.run.call(this);
} }
@ -41,6 +44,11 @@ HTTPRawProcessor.prototype.cleanup = function()
this.output.end(); this.output.end();
this.output = null; this.output = null;
} }
fs.rename(this.tempFilename, this.filename, function(err)
{
console.log('Error: could not move ' + this.tempFilename + ' to ' + this.filename + ': ' + err.message);
});
} }
module.exports = HTTPRawProcessor; module.exports = HTTPRawProcessor;