schaermu/node-fluent-ffmpeg — pull request #241 by njoyard (2014-04-30 20:56:34+00:00)
Title: [RFC] Arguments overhaul and quite major cleanup

Once again, this is more of a request for comments for now, this is definitely not ready for production.

This PR is quite a major code refactor. The core of the processing code has not changed, but all ffmpeg argument handling has been rewritten (with inspiration from [Aaron Heckmann's gm module](https://github.com/aheckmann/gm)).

This version is _mostly_ compatible with current master but there are a few exceptions.

### Arguments overhaul

* ffmpeg argument lists (this is intentionnaly plural, see next point) are now built directly when FfmpegCommand methods are called, not just before actually running ffmpeg.
* As in the gm module, we are now using helper objects to build and store argument lists. There are two lists for each input, one for video, one for audio, one for output-specific options and even more to handle filters. All those lists are concatenated in the right order before running the command.
* Methods that generate arguments are now grouped into submodules by category (audio, video, video size, inputs, output, custom and misc).
* I added a **LOT** of method aliases (up to 12 for some methods). This enables more flexibility and error-proof usage, as well as shorter command lines. Current method names are still there, of course. For example you can now write:
```js
new Ffmpeg().input('file.avi').size('320x200').fps(24).stream();
```

On the whole, this gives fluent-ffmpeg greater maintainability and extensibility, I think. If you wanted to add a new video option for example, just add the following to `lib/options/video.js`:
```js
proto.withCrf =
proto.withCRF =
proto.crf = function(crf) {
this._video('-crf', crf);
return this;
};
```

Even fluent-ffmpeg users can do this easily in their apps if they feel the need to (just replace proto with Ffmpeg.prototype).

### Code cleanup

I got rid of unused code (debug methods), moved prototype definition outside the constructor and globally reorganized code modules. We now have:
- fluent-ffmpeg.js: entry point, now only contains the constructor (and imports other modules)
- ffprobe.js: ffprobe-related methods
- capabilities.js: capability checks and queries
- processor.js: processing (saveToFile/writeToStream/renice...)
- utils.js: misc utilities (ffmpeg output parsing, mainly)
- options/*.js: as stated above, categorized methods to populate ffmpeg argument lists

I got rid of the Registry object, it is now replaced by simple key-value cache objects where necessary.

### New features

I added a small new feature to `writeToStream` (which can now also be called `stream` and `pipe`): passing a readable stream is now optional. If there is none, we create a PassThrough stream, pipe ffmpeg output to it and return it.

I also rewrote how we look for executables (in capabilities.js); we're now able to use FLVMETA_PATH/FLVTOOL2_PATH env variables and ffprobe is looked for in the same directory as ffmpeg if not found elsewhere. Those checks now also work on windows platforms (using the 'where' command as a 'which' substitute).

And last but not least, I added JSDoc comments everywhere. This is not quite finished because it does not generate correct doc for all method aliases, but that's a start. I think this is actually a big addition, as it enhances code readability a _lot_ and will hopefully enable automating documentation generation soon.

### Compatibility

One of my main goals with this rewrite was to keep compatibility and have the current test suite run without errors. I had to fix minor things in the test suite (such as implementing some methods that were pruned from the main library, but only because those were only used for testing purposes) and remove deprecated tests (Registry tests for example), but it now mostly succeeds (I still have 2 tests to fix, and quite ironically they are testing code that did not change).

However, I decided to get rid of the Metadata object, because it is unreliable and flawed. I'm not completely against putting it back in, but I think this kind of rewrite is a good opportunity to get rid of such dirty hacks.

### What remains to be done

The following is IMO mandatory for this to be production-ready:

* Fix the 2 remaining test failures
* Re-add flvmeta/flvtool2 calls and add tests for it (this is untested in current master).
* Re-add capability checks: I did not have time to put them back, but this won't be hard as capability methods were not changed. This is also untested in current master, we should also add tests for that.
* Add tests for new features and method aliases (all tests only run with current method names for now).
* Write documentation (having JSDoc ready would be nice, but that's not mandatory IMO)

Maybe this PR best place, when it is closer to ready, would be in a new 2.x branch.

Oh, and last note: since there were a _lot_ of changes, you're better off reading the code from [my branch](https://github.com/njoyard/node-fluent-ffmpeg/tree/fluent2) instead of reading diffs!

Thanks in advance for your comments on this.