Skip to content

Commit 75f229f

Browse files
Add terminateTimeout option (#8)
Co-authored-by: Riccardo Fiorenza <r.fiorenza@cedat85.com>
1 parent 9cf484a commit 75f229f

File tree

3 files changed

+51
-7
lines changed

3 files changed

+51
-7
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ var command = ffmpeg('/path/to/file.avi', { option: "value", ... });
8888

8989
The following options are available:
9090
* `source`: input file name or readable stream (ignored if an input file is passed to the constructor)
91-
* `timeout`: ffmpeg timeout in seconds (defaults to no timeout)
91+
* `timeout`: ffmpeg process timeout in seconds (defaults to no timeout)
92+
* `terminateTimeout`: ffmpeg terminate timeout in milliseconds (defaults to 20 milliseconds)
9293
* `preset` or `presets`: directory to load module presets from (defaults to the `lib/presets` directory in fluent-ffmpeg tree)
9394
* `niceness` or `priority`: ffmpeg niceness value, between -20 and 20; ignored on Windows platforms (defaults to 0)
9495
* `logger`: logger object with `debug()`, `info()`, `warn()` and `error()` methods (defaults to no logging)

lib/processor.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -483,13 +483,14 @@ module.exports = function(proto) {
483483
self.logger.debug('Output stream closed, scheduling kill for ffmpeg process');
484484

485485
// Don't kill process yet, to give a chance to ffmpeg to
486-
// terminate successfully first This is necessary because
486+
// terminate successfully first. This is necessary because
487487
// under load, the process 'exit' event sometimes happens
488488
// after the output stream 'close' event.
489+
const terminateTimeout = (self.options && self.options.terminateTimeout > 0) ? self.options.terminateTimeout : 20
489490
setTimeout(function() {
490-
emitEnd(new Error('Output stream closed'));
491+
emitEnd(new Error('Output stream closed, try increasing terminateTimeout option (' + terminateTimeout + ' ms)'));
491492
ffmpegProc.kill();
492-
}, 20);
493+
}, terminateTimeout);
493494
});
494495

495496
outputStream.target.on('error', function(err) {

test/processor.test.js

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,6 @@ describe('Processor', function() {
232232
.on('end', function() {
233233
console.log('end was called, expected a timeout');
234234
assert.ok(false);
235-
done();
236235
})
237236
.saveToFile(testFile);
238237
});
@@ -279,6 +278,51 @@ describe('Processor', function() {
279278
.saveToFile(testFile);
280279
});
281280

281+
it('should kill the process on terminate timeout (terminateTimeout option)', function(done) {
282+
this.timeout(60000);
283+
284+
var testFile = path.join(__dirname, 'assets', 'testTerminateTimeout.avi');
285+
this.files.push(testFile);
286+
287+
const terminateTimeout = 1000 // set terminateTimeout to 1000 ms
288+
var command = this.getCommand({
289+
source: this.testfilebig,
290+
logger: testhelper.logger,
291+
terminateTimeout: terminateTimeout
292+
});
293+
294+
var startCalled = false;
295+
var outputStreamClosed = false;
296+
297+
// Mock output stream
298+
var outputStream = new stream.PassThrough();
299+
outputStream.close = function() {
300+
outputStreamClosed = true;
301+
this.emit('close');
302+
};
303+
304+
command
305+
.usingPreset('divx')
306+
.output(outputStream)
307+
.on('start', function() {
308+
startCalled = true;
309+
setTimeout(function() { outputStream.close(); }, 500); // close the output stream after 500ms (emit 'close' event on output stream before 'exit' event, to simulate a under load system)
310+
})
311+
.on('error', function(err) {
312+
command.kill();
313+
assert.ok(startCalled);
314+
assert.ok(outputStreamClosed);
315+
assert.equal(err.message, 'Output stream closed, try increasing terminateTimeout option (' + terminateTimeout + ' ms)');
316+
// Wait for kill completation before to call done()
317+
setTimeout(function() { done(); }, 500);
318+
})
319+
.on('end', function() {
320+
console.log('end was called, expected an error');
321+
assert.ok(false);
322+
})
323+
.saveToFile(testFile);
324+
});
325+
282326
it('should not keep node process running on completion', function(done) {
283327
var script = `
284328
var ffmpeg = require('.');
@@ -320,7 +364,6 @@ describe('Processor', function() {
320364
.on('end', function() {
321365
console.log('end was called, expected an error');
322366
assert.ok(false);
323-
done();
324367
})
325368
.saveToFile(testFile);
326369
});
@@ -357,7 +400,6 @@ describe('Processor', function() {
357400
.on('end', function() {
358401
console.log('end was called, expected a timeout');
359402
assert.ok(false);
360-
done();
361403
})
362404
.saveToFile(testFile);
363405

0 commit comments

Comments
 (0)