From 7e18e922747a64566f48f37e844ba9fd30a898db Mon Sep 17 00:00:00 2001 From: Michael Heuberger Date: Wed, 10 Apr 2013 01:45:01 +1200 Subject: [PATCH] 0.2 release --- README.md | 45 ++++++++++++++++++++----------- avconv.js | 26 +++++++++--------- package.json | 4 +-- tests/basics.js | 71 ++++++++++++++++++++++++++++++++++++------------- 4 files changed, 98 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index 03d1bb6..8aace34 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ simply spawns an avconv process with any parameters and returns the result to yo ## installation -to install find-delete, use [npm](http://github.com/isaacs/npm): +to install avconv, use [npm](http://github.com/isaacs/npm): $ npm install avconv @@ -26,39 +26,54 @@ var params = [ '-y', '/tmp/output.avi' ]; -avconv(params, callback); +var stream = avconv(params); // returns a readable stream +stream.pipe(process.stdout); // anytime avconv outputs anything, forward these results to process.stdout ``` -(avconv consultation is not subject of this module. if you need help with parameters, have a look at http://libav.org/avconv.html) +* avconv consultation is not subject of this module. if you need help with parameters, have a look at http://libav.org/avconv.html +* same goes with node streams. you can do anything with them you want. pipe them or write data inside callbacks. easy. -### callback(code, stdout, stderr) +### how to watch for results (output, errors, exit code) -three parameters are always passed onto the callback: +if you want to watch for errors or for exit codes from the avconv process then you should add event listeners like that: ``` -function callback(code, stdout, stderr) { - // add your logic here -} +var stream = avconv(params); + +stream.on('data', function(data) { + process.stdout.write(data); +}); + +stream.on('error', function(data) { + process.stderr.write(data); +}); + +stream.once('end', function(exitCode) { + // here you knows the avconv process is finished + ... +}); ``` an exit code = 0 (zero) means there was no problem. an exit code of 127 means the program avconv could not be found. i recommend you to use a switch block to deal with various exit codes. -depending on the log level, stdout might contain any useful information. beware that stdout may contain warnings or errors coming from avconv. -stderr is rarely filled. only if there was an unix-related problem about spawning processes, memory etc. +depending on the log level you have passed onto the avconv process, the output might contain any useful information. beware that warnings or errors from within the avconv process are still shown as normal output (on 'data'). errors from the stream are rarely filled. they will happen only if there was an unix-related problem about spawning processes, memory etc. ## api -### avconv(params, callback) +### avconv(params) avconv spawns a new avconv process with any given parameters. it does not validate the parameters nor mess with the results. that's all up to you. __arguments__ * params - any array list with string arguments -* callback - the callback function to be called when process is finished. it passes three parameters: - * code - any integer where 0 means OK. anything above 0 indicates a problem (exit code). - * stdout - a string with useful information, depending on the log level. any warnings or errors from avconv are there too. - * stderr - rarely used. would contain issues related to the OS itself. + +__return value__ + +* stream - a readable stream where you can attach three well-known events: + * data - a string with useful information, depending on the log level. any warnings or errors from avconv are there too. + * error - rarely used. would contain issues related to the OS itself. + * end - any integer where 0 means OK. anything above 0 indicates a problem (exit code). ## license diff --git a/avconv.js b/avconv.js index 5fd756b..9706852 100644 --- a/avconv.js +++ b/avconv.js @@ -1,37 +1,37 @@ module.exports = avconv; -var spawn = require('child_process').spawn; +var spawn = require('child_process').spawn + , Stream = require('stream'); -function avconv(params, callback) { +function avconv(params) { - var stdout = '' - , stderr = '' + var stream = new Stream() , avconv = spawn('avconv', params); + stream.readable = true; + // general avconv output is always written into stderr if (avconv.stderr) avconv.stderr.on('data', function(data) { - // write it into stdout instead - stdout += data; + stream.emit('data', data); }); // just in case if there is something interesting if (avconv.stdout) avconv.stdout.on('data', function(data) { - stdout += data; + stream.emit('data', data); }); avconv.on('error', function(data) { - if (data.length) - data += ' '; - - stderr += data; + stream.emit('error', data); }); // new stdio api introduced the exit event not waiting for open pipes var eventType = avconv.stdio ? 'close' : 'exit'; - avconv.on(eventType, function(code) { - callback(code, stdout, stderr); + avconv.on(eventType, function(exitCode) { + stream.emit('end', exitCode); }); + + return stream; } \ No newline at end of file diff --git a/package.json b/package.json index 774b977..647cd48 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "avconv", - "version": "0.1.0", - "description": "simply spawns an avconv process with any parameters and returns the result to you. very small, fast, clean and does only this.", + "version": "0.2.0", + "description": "simply spawns an avconv process with any parameters and *streams* the result to you. very small, fast, clean and does only this.", "main": "avconv.js", "author": "Michael Heuberger ", "keywords": [ diff --git a/tests/basics.js b/tests/basics.js index b0a9aa6..7b61fc3 100644 --- a/tests/basics.js +++ b/tests/basics.js @@ -1,39 +1,66 @@ var testCase = require('nodeunit').testCase , avconv; +function read(stream, callback) { + var output = [] + , err = []; + + stream.on('data', function(data) { + output.push(data); + }); + + stream.on('error', function(data) { + err.push(data); + }); + + stream.once('end', function(exitCode) { + callback(exitCode, output, err); + }); +} + module.exports = testCase({ 'TC 1: stability tests': testCase({ 'loading avconv function (require)': function(t) { + t.expect(1); + avconv = require('../avconv.js'); t.ok(avconv, 'avconv is loaded.'); t.done(); }, - 'run without parameters (null)': function(t) { - avconv(null, function(code, stdout, stderr) { + 'run without parameters (null) 1': function(t) { + t.expect(3); + + var stream = avconv(null); + + read(stream, function(exitCode, 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(code, 1, 'avconv did nothing'); - t.notEqual(stdout, "", 'stdout is not empty'); - t.equal(stderr, "", 'stderr is empty'); - t.done(); }); }, 'run with empty array ([])': function(t) { - avconv([], function(code, stdout, stderr) { + t.expect(3); + + var stream = avconv([]); - t.strictEqual(code, 1, 'avconv did nothing'); - t.notEqual(stdout, "", 'stdout is not empty'); - t.equal(stderr, "", 'stderr is empty'); + read(stream, function(exitCode, 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.done(); }); }, 'run with invalid string parameter (fdsfdsfsdf)': function(t) { + t.expect(1); + t.throws( function() { avconv('fdsfdsfsdf'); @@ -46,11 +73,15 @@ module.exports = testCase({ }, 'run with invalid array parameters ([fdsfdsfsdf])': function(t) { - avconv(['fdsfdsfsdf'], function(code, stdout, stderr) { + t.expect(3); + + var stream = avconv(['fdsfdsfsdf']); + + read(stream, function(exitCode, output, err) { - t.strictEqual(code, 1, 'avconv did nothing'); - t.notEqual(stdout, "", 'stdout is not empty and contains a warning about the wrong parameter'); - t.strictEqual(stderr, "", 'stderr is still empty'); + t.strictEqual(exitCode, 1, 'avconv did nothing'); + t.notEqual(output.length, 0, 'stdout is not empty and contains a warning about the wrong parameter'); + t.strictEqual(err.length, 0, 'stderr is still empty'); t.done(); }); } @@ -58,11 +89,15 @@ module.exports = testCase({ 'TC 2: real tests': testCase({ 'loading help (--help)': function(t) { - avconv(['--help'], function(code, stdout, stderr) { + t.expect(3); + + var stream = avconv(['--help']); + + read(stream, function(exitCode, output, err) { - t.strictEqual(code, 0, 'avconv returned help'); - t.notEqual(stdout, "", 'stdout contains help'); - t.strictEqual(stderr, "", 'stderr is still empty'); + t.strictEqual(exitCode, 0, 'avconv returned help'); + t.notEqual(output.length, 0, 'stdout contains help'); + t.strictEqual(err.length, 0, 'stderr is still empty'); t.done(); }); }