Skip to content

Commit

Permalink
added kill() and version bump
Browse files Browse the repository at this point in the history
  • Loading branch information
binarykitchen committed Oct 23, 2013
1 parent e6930e8 commit 9500139
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 49 deletions.
39 changes: 39 additions & 0 deletions .jshintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
// Example: https://github.com/jshint/jshint/blob/master/examples/.jshintrc
// Documentation: http://www.jshint.com/docs/

"maxerr" : 30, // {int} Maximum error before stopping

// Enforcing

"indent" : 4, // {int} Number of spaces to use for indentation
"latedef" : true, // true: Require variables/functions to be defined before being used
"newcap" : true, // true: Require capitalization of all constructor functions e.g. `new F()`
"strict" : false, // Require `use strict` pragma in every file.
"quotmark" : false, // Quotation mark consistency

// Relaxing
"shadow" : true, // true: Allows re-define variables later in code e.g. `var x=1; x=2;`
"supernew" : true, // true: Tolerate `new function () { ... };` and `new Object;`


"loopfunc" : true, // true: Tolerate functions being defined in loops

// Environments
"browser" : true, // Web Browser (window, document, etc)
"devel" : true, // Development/debugging (alert, confirm, etc)
"node" : true, // Node.js
"-W008" : true, // A leading decimal point can be confused with a dot

// mh: disabled for now because of switch case block issue:
// https://github.com/jshint/jshint/issues/935
"indent": false,

// Custom globals
"predef": [
"define",
"suite",
"suiteSetup",
"test"
]
}
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ stream.on('error', function(data) {
process.stderr.write(data);
});
stream.once('end', function(exitCode) {
stream.once('end', function(exitCode, signal) {
// here you knows the avconv process is finished
...
});
Expand Down Expand Up @@ -96,7 +96,8 @@ __return value__
* `.on('data', function(data) {...})` - a chunk of data with useful information, depending on the log level. Any warnings or errors from avconv are there too.
* `.on('progress', function(progress) {...})` - a floating number, 0 means conversion progress is at 0%, 1 is 100% and means, it's done. Very useful if you want to show the conversion progress on an user interface,
* `.on('error', function(data) {...})` - rarely used. Would contain issues related to the OS itself.
* `.once('end', function(exitCode) {...})` - any integer where 0 means OK. Anything above 0 indicates a problem (exit code).
* `.once('end', function(exitCode, signal) {...})` - for the exit code any integer where 0 means OK. Anything above 0 indicates a problem (exit code). The signal tells how the process ended, i.E. can be a SIGTERM you killed it with `stream.kill()`. If it's null, then it ended normally.
* `.kill()` - call that if you want to abort avconv in the middle. It will kill the process and fire an `end` event for the stream.

## License

Expand Down
52 changes: 27 additions & 25 deletions avconv.js
Original file line number Diff line number Diff line change
@@ -1,39 +1,37 @@
"use strict";

module.exports = avconv;

var spawn = require('child_process').spawn
, Stream = require('stream');
var spawn = require('child_process').spawn,
Stream = require('stream');

// Converts a avconv time format to milliseconds
function toMilliSeconds(time) {
var d = time.split(/[:.]/)
, ms = 0;
var d = time.split(/[:.]/),
ms = 0;

if (d.length === 4) {
ms += parseInt(d[0]) * 3600 * 1000;
ms += parseInt(d[1]) * 60 * 1000;
ms += parseInt(d[2]) * 1000;
ms += parseInt(d[3]);
ms += parseInt(d[0], 10) * 3600 * 1000;
ms += parseInt(d[1], 10) * 60 * 1000;
ms += parseInt(d[2], 10) * 1000;
ms += parseInt(d[3], 10);
} else {
ms += parseInt(d[0]) * 1000;
ms += parseInt(d[1]);
ms += parseInt(d[0], 10) * 1000;
ms += parseInt(d[1], 10);
}

return ms;
}

// Extract duration from avconv data
function findDuration(data) {
var result = /duration: (\d+:\d+:\d+.\d+)/i.exec(data)
, duration;
var result = /duration: (\d+:\d+:\d+.\d+)/i.exec(data),
duration;

if (result && result[1]) {
duration = toMilliSeconds(result[1]);
}

return duration;
};
}

// Extract time frame from avconv data
function findTime(data) {
Expand All @@ -48,12 +46,12 @@ function findTime(data) {
}

return time;
};
}

function avconv(params) {
module.exports = function avconv(params) {

var stream = new Stream()
, avconv = spawn('avconv', params);
var stream = new Stream(),
avconv = spawn('avconv', params);

stream.readable = true;

Expand All @@ -62,9 +60,9 @@ function avconv(params) {

avconv.stderr.setEncoding('utf8');

var duration
, time
, progress;
var duration,
time,
progress;

avconv.stderr.on('data', function(data) {

Expand Down Expand Up @@ -106,9 +104,13 @@ function avconv(params) {
// New stdio api introduced the exit event not waiting for open pipes
var eventType = avconv.stdio ? 'close' : 'exit';

avconv.on(eventType, function(exitCode) {
stream.emit('end', exitCode);
avconv.on(eventType, function(exitCode, signal) {
stream.emit('end', exitCode, signal);
});

stream.kill = function() {
avconv.kill();
};

return stream;
}
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "avconv",
"version": "0.2.5",
"version": "0.2.6",
"description": "Simply spawns an avconv process with any parameters and *streams* the result + conversion progress to you. Very small, fast, clean and does only this.",
"main": "avconv.js",
"author": "Michael Heuberger <michael.heuberger@binarykitchen.com>",
Expand Down
75 changes: 54 additions & 21 deletions tests/basics.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
"use strict";

var testCase = require('nodeunit').testCase
, path = require('path')
, fs = require('fs')
, avconv;
var testCase = require('nodeunit').testCase,
path = require('path'),
fs = require('fs'),
avconv;

function read(stream, callback) {
var output = []
, err = [];
var output = [],
err = [];

stream.on('data', function(data) {
output.push(data);
Expand All @@ -17,8 +17,8 @@ function read(stream, callback) {
err.push(data);
});

stream.once('end', function(exitCode) {
callback(exitCode, output, err);
stream.once('end', function(exitCode, signal) {
callback(exitCode, signal, output, err);
});
}

Expand All @@ -35,14 +35,15 @@ module.exports = testCase({
},

'run without parameters (null) 1': function(t) {
t.expect(3);
t.expect(4);

var stream = avconv(null);

read(stream, function(exitCode, output, err) {
read(stream, function(exitCode, signal, output, err) {
t.strictEqual(exitCode, 1, 'avconv did nothing');
t.notEqual(output.length, 0, 'output is not empty');
t.strictEqual(err.length, 0, 'err is empty');
t.strictEqual(signal, null, 'Signal is null');

t.done();
});
Expand All @@ -53,7 +54,7 @@ module.exports = testCase({

var stream = avconv([]);

read(stream, function(exitCode, output, err) {
read(stream, function(exitCode, signal, output, err) {
t.strictEqual(exitCode, 1, 'avconv did nothing');
t.notEqual(output.length, 0, 'output is not empty');
t.strictEqual(err.length, 0, 'err is empty');
Expand Down Expand Up @@ -81,7 +82,7 @@ module.exports = testCase({

var stream = avconv(['fdsfdsfsdf']);

read(stream, function(exitCode, output, err) {
read(stream, function(exitCode, signal, output, err) {

t.strictEqual(exitCode, 1, 'avconv did nothing');
t.notEqual(output.length, 0, 'stdout is not empty and contains a warning about the wrong parameter');
Expand All @@ -97,7 +98,7 @@ module.exports = testCase({

var stream = avconv(['--help']);

read(stream, function(exitCode, output, err) {
read(stream, function(exitCode, signal, output, err) {

t.strictEqual(exitCode, 0, 'avconv returned help');
t.notEqual(output.length, 0, 'stdout contains help');
Expand Down Expand Up @@ -127,15 +128,15 @@ module.exports = testCase({
'convert pokemon flv to webm': function(t) {

var params = [
'-i', path.join(this.exampleDir, 'pokemon_card.flv')
, '-c:v', 'libvpx'
, '-deadline', 'realtime'
, '-y', path.join(this.exampleDir, 'pokemon_card.webm')
'-i', path.join(this.exampleDir, 'pokemon_card.flv'),
'-c:v', 'libvpx',
'-deadline', 'realtime',
'-y', path.join(this.exampleDir, 'pokemon_card.webm')
];

var errors = ''
, datas = ''
, previousProgress = 0;
var errors = '',
datas = '',
previousProgress = 0;

var stream = avconv(params);

Expand All @@ -154,15 +155,47 @@ module.exports = testCase({
errors += data;
});

stream.once('end', function(exitCode) {
stream.once('end', function(exitCode, signal) {

t.strictEqual(exitCode, 0, 'Video has been successfully generated');
t.strictEqual(errors, '', 'No errors occured at all');
t.strictEqual(signal, null, 'Signal is null');

t.ok(datas.length > 0, 'There is data');

t.done();
});
},

'convert and kill in the middle': function(t) {

var params = [
'-i', path.join(this.exampleDir, 'pokemon_card.flv'),
'-c:v', 'libvpx',
'-deadline', 'realtime',
'-y', path.join(this.exampleDir, 'pokemon_card.webm')
];

var errors = '';

var stream = avconv(params);

stream.on('error', function(data) {
errors += data;
});

stream.once('end', function(exitCode, signal) {

t.strictEqual(exitCode, null, 'There is no exit code when killed');
t.strictEqual(errors, '', 'No errors occured at all');
t.strictEqual(signal, 'SIGTERM', 'Signal is SIGTERM');

t.done();
});

setTimeout(function() {
stream.kill();
}, 10);
}
})
});

0 comments on commit 9500139

Please sign in to comment.