Skip to content
Browse files

moved past proof of concept, now using safer spawn method, cleaner fi…

…le, with descriptive comments.
  • Loading branch information...
1 parent d90ea80 commit 147c7535e0babc26563986e184d1fecd15a8a346 @xonecas committed Feb 2, 2011
Showing with 181 additions and 138 deletions.
  1. +3 −25 README
  2. +170 −80 ffmpeg-node.js
  3. +8 −33 test.js
View
28 README
@@ -1,32 +1,10 @@
Node.js module to control ffmpeg
- Documentation and webm convenience method comming asap.
-
usage:
- var ffmpeg = require('/path/to/ffmpeg-node.js');
-
- ffmpeg.command(
- input file, // string representing a path
- audio options, // json-like object of ffmpeg audio options [strings]
- video options, // json-like object of ffmpeg video options [strings]
- video format, // json-like object of width and height values [strings]
- output file, // string with the target /path/file.ext
- callback // function to call after video conversion
- );
-
-convenience methods:
-
- ffmpeg.toMp4(
- input file, // string representing a path
- video format, // json-like object of width and height values [strings]
- callback // function to call after video conversion
- );
-
- ffmpeg.toOgg(
- input file, // string representing a path
- video format, // json-like object of width and height values [strings]
- callback // function to call after video conversion
+ ffmpeg.call(
+ [ ... ], // array of ffmpeg flags
+ callback // function to call after ffmpeg is done
);
Examples:
View
250 ffmpeg-node.js
@@ -1,94 +1,184 @@
-// doc missing, dog ate it
+
+/**
+ * Module to drive ffmpeg video enconding library with shortcuts
+ * for web video. Requires a ffmpeg compiled with support for mp4/ogg/webm.
+ */
var path = require('path'),
- exec = require('child_process').exec;
-
-exports.command = function (input, audio, video, format, output, callback) {
- path.exists(input, function (exists) {
- if (exists) {
- var command = 'ffmpeg -i '+ input +' ';
-
- if (typeof audio === 'object') {
- for (flag in audio) {
- command += '-'+ flag +' '+ audio[flag] +' ';
- }
- }
-
- if (typeof video === 'object') {
- for (flag in video) {
- var value = video[flag];
-
- if (flag === 'vpre' && typeof value === 'object') {
- value.forEach(function (preset) {
- command += '-vpre '+ preset +' ';
- });
- }
- else if (typeof value === 'string') {
- command += '-'+ flag +' '+ value +' ';
- }
- else
- throw new TypeError('Presets must be a string or an array of strings.');
- }
- }
-
- if (typeof format === 'object' &&
- typeof format.width === 'string' &&
- typeof format.height === 'string') {
-
- command += '-s '+ format.width +'x'+ format.height +' ';
- }
-
- if (typeof output === 'string') {
- command += output;
- }
- else
- throw new SyntaxError('Output must be a fileName.containerFormat: '+ output);
-
- exec(command , function (error, stdout, stderr) {
- if (error)
- throw new Error('ffmpeg didn\'t finish successfully: '+ stderr);
- else
- callback();
- });
- }
- else
- throw new ReferenceError('File not found: '+ input);
- });
+ spawn = require('child_process').spawn;
+
+/**
+ * Description:
+ * calls ffmpeg with the specified flags and returns the output
+ * to the callback function.
+ *
+ * Parameters:
+ * params - an array of ffmpeg options, ex: ['-i','./test.3gp']
+ * callback - a function to call when ffmpeg is done, ex:
+ * function (stderr, stdout, exitCode) { ... }
+ */
+
+exports.call = function (params, callback) {
+
+ if (params instanceof Array && params.length > 2) {
+
+ var stderr = '', stdout = '',
+ ffmpeg = spawn('ffmpeg', params);
+
+ ffmpeg.stderr.on('data', function (err) {
+ stderr += err;
+ });
+
+ ffmpeg.stdout.on('data', function (output) {
+ stdout += output;
+ });
+
+ ffmpeg.on('exit', function (code) {
+ callback(stderr, stdout, code);
+ });
+
+ }
+
}
-exports.toMp4 = function (input, format, callback) {
-
- var output = path.dirname(input) +'/'+
- path.basename(input, path.extname(input)) +'.mp4';
-
- this.command(input, {
- 'acodec': 'libfaac',
- 'ab': '128k',
- 'ar': '41000'
- }, {
- 'vcodec': 'libx264',
- 'vpre': ['slow', 'baseline'],
- 'r': '25'
- }, format, output, callback);
+
+/**
+ * Description:
+ * serves as middle man for convenience method, required to
+ * avoid code repetition.
+ *
+ * Parameters:
+ * type - one of 'mp4', 'ogg', 'webm' as a string.
+ * file - path/to/the/inputFile.ext as a string.
+ * params - an array of ffmpeg options to be added to the predefined ones (optional).
+ * output - path/to/the/outputFile.ext as a string (optional).
+ * callback - function to call when ffmpeg is done, ex:
+ * function (stderr, stdout, exitCode) { ... }
+ */
+
+exports.convert = function (/* overloaded */) {
+
+ var type = arguments[0], file = arguments[1],
+ params = [], output = '', callback = false;
+
+ if (arguments.length === 3) {
+ params = [],
+ output = path.basename(
+ file, path.extname(file)) +'.'+ type,
+ callback = arguments[2];
+ }
+ else if (arguments.length > 3) {
+ var err = false;
+
+ if (arguments[2] instanceof Array)
+ params = arguments[2];
+ else if (typeof arguments[2] === 'string')
+ output = arguments[2];
+ else if (arguments[2] instanceof Function)
+ callback = arguments[2];
+ else
+ err = true;
+
+ if (typeof arguments[3] === 'string')
+ output = arguments[3];
+ else if (arguments[3] instanceof Function)
+ callback = arguments[3];
+ else
+ err = true;
+
+ if (arguments[4] instanceof Function)
+ var callback = arguments[4];
+ else
+ err = true;
+
+ if (err)
+ throw new Error('Could not parse arguments');
+ }
+ else
+ throw new Error('Not enough arguments');
+
+ switch(type) {
+ case 'mp4':
+ params = [
+ '-i', file,
+ '-acodec', 'libfaac',
+ '-ab', '128k',
+ '-ar', '41000',
+ '-vcodec', 'libx264',
+ '-vpre', 'slow',
+ '-vpre', 'baseline',
+ '-r', '25',
+ '-y', output
+ ].concat(params);
+ break;
+
+ case 'ogg':
+ params = [
+ '-i', file,
+ '-acodec', 'libvorbis',
+ '-ab', '128k',
+ '-ar', '41000',
+ '-vodec', 'libtheora',
+ '-r', '25',
+ '-y', output
+ ].concat(params);
+ break;
+
+ case 'webm':
+ params = [
+ '-i', file,
+ '-acodec', 'libvorbis',
+ '-ab', '128k',
+ '-ar', '41000',
+ '-vcodec', 'libvpx',
+ '-b', '614400',
+ '-aspect', '16:9',
+ '-y', output
+ ].concat(params);
+ break;
+ }
+
+ this.call(params, callback);
+
}
-exports.toOgg = function(input, format, callback) {
- var output = path.dirname(input) +'/'+
- path.basename(input, path.extname(input)) +'.ogg';
-
- this.command(input, {
- 'acodec': 'libvorbis',
- 'ab': '128k',
- 'ar': '41000'
- }, {
- 'vcodec': 'libtheora',
- 'r': '25'
- }, format, output, callback);
+/**
+ * Description:
+ * Convenience methods to convert to popular web formats (flash/html5)
+ * If you know how to improve these default options, let me know.
+ *
+ * Parameters:
+ * file - path/to/the/inputFile.ext as a string.
+ * params - an array of ffmpeg options to be added to the predefined ones (optional).
+ * output - path/to/the/outputFile.ext as a string (optional).
+ * callback - function to call when ffmpeg is done, ex:
+ * function (stderr, stdout, exitCode) { ... }
+ */
+
+exports.mp4 = function (/* overloaded */) {
+
+ var unshift = Array.prototype.unshift;
+ unshift.call(arguments, 'mp4');
+
+ this.convert.apply(this, arguments);
+
}
+exports.ogg = function (/* overloaded */) {
+
+ var unshift = Array.prototype.unshift;
+ unshift.call(arguments, 'ogg');
+ this.convert.apply(this, arguments);
+}
+exports.webm = function (/* overloaded */) {
+ var unshift = Array.prototype.unshift;
+ unshift.call(arguments, 'webm');
+ this.convert.apply(this, arguments);
+
+}
View
41 test.js
@@ -1,36 +1,11 @@
var ffmpeg = require('./ffmpeg-node.js');
-ffmpeg.command('./test.3gp', {
- 'acodec': 'libfaac',
- 'ab': '128k',
- 'ar': '41000'
- }, {
- 'vcodec': 'libx264',
- 'vpre': ['slow', 'baseline'],
- 'r': '25'
- }, {
- 'width': '640',
- 'height': '360'
- }, './test.mp4', function () {
+ffmpeg.mp4(
+ './test.3gp',
+ ['-s', '720x480'],
+ './test.mp4',
+ function (err, out, code) {
+ console.log(err, out, code);
+ }
+);
- console.log('it worked');
-
- });
-
-ffmpeg.toMp4('./test.3gp', {
- 'width': '640',
- 'height': '360'
- }, function () {
-
- console.log('it worked');
-
- });
-
-ffmpeg.toOgg('./test.3gp', {
- 'width': '640',
- 'height': '360'
- }, function () {
-
- console.log('it worked');
-
- });

0 comments on commit 147c753

Please sign in to comment.
Something went wrong with that request. Please try again.