The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .github
    ├── CONTRIBUTING.md
    ├── ISSUE_TEMPLATE.md
    └── workflows
    │   └── ci.yml
├── .gitignore
├── .npmignore
├── LICENSE
├── Makefile
├── README.md
├── doc
    ├── FfmpegCommand.html
    ├── audio.js.html
    ├── capabilities.js.html
    ├── custom.js.html
    ├── ffprobe.js.html
    ├── fluent-ffmpeg.js.html
    ├── global.html
    ├── index.html
    ├── inputs.js.html
    ├── misc.js.html
    ├── options_audio.js.html
    ├── options_custom.js.html
    ├── options_inputs.js.html
    ├── options_misc.js.html
    ├── options_output.js.html
    ├── options_video.js.html
    ├── options_videosize.js.html
    ├── output.js.html
    ├── processor.js.html
    ├── recipes.js.html
    ├── scripts
    │   ├── linenumber.js
    │   └── prettify
    │   │   ├── Apache-License-2.0.txt
    │   │   ├── lang-css.js
    │   │   └── prettify.js
    ├── styles
    │   ├── jsdoc-default.css
    │   ├── prettify-jsdoc.css
    │   └── prettify-tomorrow.css
    ├── utils.js.html
    ├── video.js.html
    └── videosize.js.html
├── examples
    ├── any-to-mp4-steam.js
    ├── express-stream.js
    ├── flowplayer
    │   ├── flowplayer.controls.swf
    │   ├── flowplayer.min.js
    │   ├── flowplayer.swf
    │   └── index.html
    ├── full.js
    ├── image2video.js
    ├── input-stream.js
    ├── livertmp2hls.js
    ├── mergeVideos.js
    ├── metadata.js
    ├── preset.js
    ├── progress.js
    ├── stream.js
    └── thumbnails.js
├── index.js
├── lib
    ├── capabilities.js
    ├── ffprobe.js
    ├── fluent-ffmpeg.js
    ├── options
    │   ├── audio.js
    │   ├── custom.js
    │   ├── inputs.js
    │   ├── misc.js
    │   ├── output.js
    │   ├── video.js
    │   └── videosize.js
    ├── presets
    │   ├── divx.js
    │   ├── flashvideo.js
    │   └── podcast.js
    ├── processor.js
    ├── recipes.js
    └── utils.js
├── package.json
├── test
    ├── aliases.test.js
    ├── args.test.js
    ├── assets
    │   ├── ffserver.conf
    │   ├── presets
    │   │   └── custompreset.js
    │   ├── te[s]t_ video ' _ .flv
    │   ├── testaudio-one.wav
    │   ├── testaudio-three.wav
    │   ├── testaudio-two.wav
    │   ├── teststream.ffm
    │   ├── testvideo-169.avi
    │   ├── testvideo-43.avi
    │   └── testvideo-5m.mpg
    ├── capabilities.test.js
    ├── helpers.js
    ├── metadata.test.js
    ├── processor.test.js
    └── utils.test.js
├── tools
    ├── jsdoc-aliases.js
    ├── jsdoc-conf.json
    └── jsdoc-template
    │   ├── README.md
    │   ├── publish.js
    │   ├── static
    │       ├── scripts
    │       │   ├── linenumber.js
    │       │   └── prettify
    │       │   │   ├── Apache-License-2.0.txt
    │       │   │   ├── lang-css.js
    │       │   │   └── prettify.js
    │       └── styles
    │       │   ├── jsdoc-default.css
    │       │   ├── prettify-jsdoc.css
    │       │   └── prettify-tomorrow.css
    │   └── tmpl
    │       ├── aliases.tmpl
    │       ├── container.tmpl
    │       ├── details.tmpl
    │       ├── example.tmpl
    │       ├── examples.tmpl
    │       ├── exceptions.tmpl
    │       ├── layout.tmpl
    │       ├── mainpage.tmpl
    │       ├── members.tmpl
    │       ├── method.tmpl
    │       ├── params.tmpl
    │       ├── properties.tmpl
    │       ├── returns.tmpl
    │       ├── source.tmpl
    │       ├── tutorial.tmpl
    │       └── type.tmpl
└── yarn.lock


/.github/CONTRIBUTING.md:
--------------------------------------------------------------------------------
 1 | # How to contribute
 2 | 
 3 | ## Reporting issues
 4 | 
 5 | Please start by [reading the FAQ][faq] first.  If your question is not answered, here are some guidelines on how to effectively report issues.
 6 | 
 7 | ### Required information
 8 | 
 9 | When reporting issues be sure to include at least:
10 | 
11 | * Some code that may be used to reproduce the problem
12 | * Which version of fluent-ffmpeg, of ffmpeg and which OS you're using
13 | * If the problem only happens with some input sources, please include a link to a source that may be used to reproduce the problem
14 | * Be sure to include the full error message when there is one
15 | * When an ffmpeg error happens (eg. 'ffmpeg exited with code 1'), you should also include the full output from ffmpeg (stdout and stderr), as it may contain useful information about what whent wrong.  You can do that by looking at the 2nd and 3rd parameters of the `error` event handler on an FfmpegCommand,  for example:
16 | 
17 | ```js
18 | ffmpeg('some/input.mp4')
19 |   .on('error', function(err, stdout, stderr) {
20 |     console.log('An error happened: ' + err.message);
21 |     console.log('ffmpeg standard output:\n' + stdout);
22 |     console.log('ffmpeg standard error:\n' + stderr);
23 |   });
24 | ```
25 | 
26 | ### Ffmpeg usage
27 | 
28 | If your command ends up with an ffmpeg error (eg. 'ffmpeg exited with code X : ...'), be sure to try the command manually from command line.  You can get the ffmpeg command line that is executed for a specific Fluent-ffmpeg command by using the `start` event:
29 | 
30 | ```js
31 | ffmpeg('some/input.mp4')
32 |   .on('start', function(cmdline) {
33 |     console.log('Command line: ' + cmdline);
34 |   })
35 |   ...
36 | ```
37 | 
38 | If it does not work, you most likely have a ffmpeg-related problem that does not fit as a fluent-ffmpeg issue; in that case head to the [ffmpeg documentation](ffmpeg.org/documentation.html) to find out what you did wrong.
39 | 
40 | If it _does_ work, please double-check how you escaped arguments and options when passing them to fluent-ffmpeg.  For example, when running from command line, you may have to quote arguments to tell your shell that a space is indeed part of a filename or option.  When using fluent-ffmpeg, you don't have to do that, as you're already passing options and arguments separately.  Here's a (dumb) example:
41 | 
42 | ```sh
43 | $ ffmpeg -i video with spaces.avi
44 | Cannot find "video", or unknown option "with", etc...
45 | $ ffmpeg -i "video with spaces.avi"
46 | Works
47 | ```
48 | 
49 | ```js
50 | // Works
51 | ffmpeg('video with spaces.avi')...;
52 | 
53 | // Fails, looks for a file with actual double quotes in its name
54 | ffmpeg('"video with spaces.avi"')...;
55 | ```
56 | 
57 | [faq]: https://github.com/fluent-ffmpeg/node-fluent-ffmpeg/wiki/FAQ
58 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
 1 | <!-- Please fill the following template -->
 2 | 
 3 | ### Version information
 4 | 
 5 | * fluent-ffmpeg version:
 6 | * ffmpeg version:
 7 | * OS:
 8 | 
 9 | ### Code to reproduce
10 | 
11 | ```js
12 | 
13 | 
14 | ```
15 | 
16 | (note: if the problem only happens with some inputs, include a link to such an input file)
17 | 
18 | ### Expected results
19 | 
20 | 
21 | 
22 | ### Observed results
23 | 
24 | 
25 | 
26 | ### Checklist
27 | 
28 | <!-- you may delete that checklist when you have checked everything -->
29 | 
30 | * [ ] I have read the [FAQ](https://github.com/fluent-ffmpeg/node-fluent-ffmpeg/wiki/FAQ)
31 | * [ ] I tried the same with command line ffmpeg and it works correctly (hint: if the problem also happens this way, this is an ffmpeg problem and you're not reporting it to the right place)
32 | * [ ] I have included full stderr/stdout output from ffmpeg
33 | 


--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
 1 | name: CI Testing
 2 | on:
 3 |   pull_request:
 4 |   push:
 5 |     branches:
 6 |       - master
 7 | jobs:
 8 |   test:
 9 |     name: Run tests
10 |     runs-on: ubuntu-latest
11 |     strategy:
12 |       matrix:
13 |         node: [18, 20, 21]
14 |     steps:
15 |       - name: Checkout
16 |         uses: actions/checkout@v4
17 |       - name: Install flvtool2
18 |         run: sudo gem install flvtool2
19 |       - name: Install ffmpeg
20 |         run: sudo apt install -y ffmpeg
21 |       - name: Setup node
22 |         uses: actions/setup-node@v3
23 |         with:
24 |           node-version: ${{ matrix.node }}
25 |           cache: yarn
26 |       - name: Install dependencies
27 |         run: yarn
28 |       - name: Run tests
29 |         run: yarn test
30 |       - name: Generate coverage report
31 |         run: yarn coverage
32 |       - name: Store coveralls coverage
33 |         uses: coverallsapp/github-action@v2
34 |         with:
35 |           flag-name: linux-node-${{ matrix.node }}
36 |           parallel: true
37 |       - name: Upload to codecov
38 |         uses: codecov/codecov-action@v3
39 |         env:
40 |           CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
41 |         with:
42 |           files: coverage/lcov.info
43 |           name: ubuntu-latest-node-${{ matrix.node }}
44 | 
45 |   upload-coverage:
46 |     name: Upload coverage
47 |     needs: test
48 |     if: ${{ always() }}
49 |     runs-on: ubuntu-latest
50 |     steps:
51 |       - name: Upload to coveralls
52 |         uses: coverallsapp/github-action@v2
53 |         with:
54 |           parallel-finished: true
55 |           carryforward: "linux-node-18,linux-node-20,linux-node-21"
56 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.project
2 | node_modules
3 | .nyc_output
4 | *.swp
5 | .idea
6 | *.iml
7 | coverage
8 | 


--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | *.md
2 | .git*
3 | test/
4 | examples/


--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
 1 | (The MIT License)
 2 | 
 3 | Copyright (c) 2011-2015 The fluent-ffmpeg contributors
 4 | 
 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
 6 | 
 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
 8 | 
 9 | THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
10 | 


--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
 1 | REPORTER = spec
 2 | MOCHA = node_modules/.bin/mocha
 3 | 
 4 | test:
 5 | 	@NODE_ENV=test $(MOCHA) --require should --reporter $(REPORTER)
 6 | 
 7 | test-colors:
 8 | 	@NODE_ENV=test $(MOCHA) --require should --reporter $(REPORTER) --colors
 9 | 
10 | publish:
11 | 	@npm version patch -m "version bump"
12 | 	@npm publish
13 | 
14 | JSDOC = node_modules/.bin/jsdoc
15 | JSDOC_CONF = tools/jsdoc-conf.json
16 | 
17 | doc:
18 | 	$(JSDOC) --configure $(JSDOC_CONF)
19 | 
20 | .PHONY: test test-colors publish doc


--------------------------------------------------------------------------------
/doc/audio.js.html:
--------------------------------------------------------------------------------
  1 | <!DOCTYPE html>
  2 | <html lang="en">
  3 | <head>
  4 |     <meta charset="utf-8">
  5 |     <title>JSDoc: Source: options/audio.js</title>
  6 | 
  7 |     <script src="scripts/prettify/prettify.js"> </script>
  8 |     <script src="scripts/prettify/lang-css.js"> </script>
  9 |     <!--[if lt IE 9]>
 10 |       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
 11 |     <![endif]-->
 12 |     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
 13 |     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
 14 | </head>
 15 | 
 16 | <body>
 17 | 
 18 | <div id="main">
 19 | 
 20 |     <h1 class="page-title">Source: options/audio.js</h1>
 21 | 
 22 |     
 23 | 
 24 | 
 25 |     
 26 |     <section>
 27 |         <article>
 28 |             <pre class="prettyprint source linenums"><code>/*jshint node:true*/
 29 | 'use strict';
 30 | 
 31 | var utils = require('../utils');
 32 | 
 33 | 
 34 | /*
 35 |  *! Audio-related methods
 36 |  */
 37 | 
 38 | module.exports = function(proto) {
 39 |   /**
 40 |    * Disable audio in the output
 41 |    *
 42 |    * @method FfmpegCommand#noAudio
 43 |    * @category Audio
 44 |    * @aliases withNoAudio
 45 |    * @return FfmpegCommand
 46 |    */
 47 |   proto.withNoAudio =
 48 |   proto.noAudio = function() {
 49 |     this._currentOutput.audio.clear();
 50 |     this._currentOutput.audioFilters.clear();
 51 |     this._currentOutput.audio('-an');
 52 | 
 53 |     return this;
 54 |   };
 55 | 
 56 | 
 57 |   /**
 58 |    * Specify audio codec
 59 |    *
 60 |    * @method FfmpegCommand#audioCodec
 61 |    * @category Audio
 62 |    * @aliases withAudioCodec
 63 |    *
 64 |    * @param {String} codec audio codec name
 65 |    * @return FfmpegCommand
 66 |    */
 67 |   proto.withAudioCodec =
 68 |   proto.audioCodec = function(codec) {
 69 |     this._currentOutput.audio('-acodec', codec);
 70 | 
 71 |     return this;
 72 |   };
 73 | 
 74 | 
 75 |   /**
 76 |    * Specify audio bitrate
 77 |    *
 78 |    * @method FfmpegCommand#audioBitrate
 79 |    * @category Audio
 80 |    * @aliases withAudioBitrate
 81 |    *
 82 |    * @param {String|Number} bitrate audio bitrate in kbps (with an optional 'k' suffix)
 83 |    * @return FfmpegCommand
 84 |    */
 85 |   proto.withAudioBitrate =
 86 |   proto.audioBitrate = function(bitrate) {
 87 |     this._currentOutput.audio('-b:a', ('' + bitrate).replace(/k?$/, 'k'));
 88 |     return this;
 89 |   };
 90 | 
 91 | 
 92 |   /**
 93 |    * Specify audio channel count
 94 |    *
 95 |    * @method FfmpegCommand#audioChannels
 96 |    * @category Audio
 97 |    * @aliases withAudioChannels
 98 |    *
 99 |    * @param {Number} channels channel count
100 |    * @return FfmpegCommand
101 |    */
102 |   proto.withAudioChannels =
103 |   proto.audioChannels = function(channels) {
104 |     this._currentOutput.audio('-ac', channels);
105 |     return this;
106 |   };
107 | 
108 | 
109 |   /**
110 |    * Specify audio frequency
111 |    *
112 |    * @method FfmpegCommand#audioFrequency
113 |    * @category Audio
114 |    * @aliases withAudioFrequency
115 |    *
116 |    * @param {Number} freq audio frequency in Hz
117 |    * @return FfmpegCommand
118 |    */
119 |   proto.withAudioFrequency =
120 |   proto.audioFrequency = function(freq) {
121 |     this._currentOutput.audio('-ar', freq);
122 |     return this;
123 |   };
124 | 
125 | 
126 |   /**
127 |    * Specify audio quality
128 |    *
129 |    * @method FfmpegCommand#audioQuality
130 |    * @category Audio
131 |    * @aliases withAudioQuality
132 |    *
133 |    * @param {Number} quality audio quality factor
134 |    * @return FfmpegCommand
135 |    */
136 |   proto.withAudioQuality =
137 |   proto.audioQuality = function(quality) {
138 |     this._currentOutput.audio('-aq', quality);
139 |     return this;
140 |   };
141 | 
142 | 
143 |   /**
144 |    * Specify custom audio filter(s)
145 |    *
146 |    * Can be called both with one or many filters, or a filter array.
147 |    *
148 |    * @example
149 |    * command.audioFilters('filter1');
150 |    *
151 |    * @example
152 |    * command.audioFilters('filter1', 'filter2=param1=value1:param2=value2');
153 |    *
154 |    * @example
155 |    * command.audioFilters(['filter1', 'filter2']);
156 |    *
157 |    * @example
158 |    * command.audioFilters([
159 |    *   {
160 |    *     filter: 'filter1'
161 |    *   },
162 |    *   {
163 |    *     filter: 'filter2',
164 |    *     options: 'param=value:param=value'
165 |    *   }
166 |    * ]);
167 |    *
168 |    * @example
169 |    * command.audioFilters(
170 |    *   {
171 |    *     filter: 'filter1',
172 |    *     options: ['value1', 'value2']
173 |    *   },
174 |    *   {
175 |    *     filter: 'filter2',
176 |    *     options: { param1: 'value1', param2: 'value2' }
177 |    *   }
178 |    * );
179 |    *
180 |    * @method FfmpegCommand#audioFilters
181 |    * @aliases withAudioFilter,withAudioFilters,audioFilter
182 |    * @category Audio
183 |    *
184 |    * @param {...String|String[]|Object[]} filters audio filter strings, string array or
185 |    *   filter specification array, each with the following properties:
186 |    * @param {String} filters.filter filter name
187 |    * @param {String|String[]|Object} [filters.options] filter option string, array, or object
188 |    * @return FfmpegCommand
189 |    */
190 |   proto.withAudioFilter =
191 |   proto.withAudioFilters =
192 |   proto.audioFilter =
193 |   proto.audioFilters = function(filters) {
194 |     if (arguments.length > 1) {
195 |       filters = [].slice.call(arguments);
196 |     }
197 | 
198 |     if (!Array.isArray(filters)) {
199 |       filters = [filters];
200 |     }
201 | 
202 |     this._currentOutput.audioFilters(utils.makeFilterStrings(filters));
203 |     return this;
204 |   };
205 | };
206 | </code></pre>
207 |         </article>
208 |     </section>
209 | 
210 | 
211 | 
212 | 
213 | </div>
214 | 
215 | <nav>
216 |     <h2><a href="index.html">Index</a></h2><ul><li><a href="index.html#installation">Installation</a></li><ul></ul><li><a href="index.html#usage">Usage</a></li><ul><li><a href="index.html#prerequisites">Prerequisites</a></li><li><a href="index.html#creating-an-ffmpeg-command">Creating an FFmpeg command</a></li><li><a href="index.html#specifying-inputs">Specifying inputs</a></li><li><a href="index.html#input-options">Input options</a></li><li><a href="index.html#audio-options">Audio options</a></li><li><a href="index.html#video-options">Video options</a></li><li><a href="index.html#video-frame-size-options">Video frame size options</a></li><li><a href="index.html#specifying-multiple-outputs">Specifying multiple outputs</a></li><li><a href="index.html#output-options">Output options</a></li><li><a href="index.html#miscellaneous-options">Miscellaneous options</a></li><li><a href="index.html#setting-event-handlers">Setting event handlers</a></li><li><a href="index.html#starting-ffmpeg-processing">Starting FFmpeg processing</a></li><li><a href="index.html#controlling-the-ffmpeg-process">Controlling the FFmpeg process</a></li><li><a href="index.html#reading-video-metadata">Reading video metadata</a></li><li><a href="index.html#querying-ffmpeg-capabilities">Querying ffmpeg capabilities</a></li><li><a href="index.html#cloning-an-ffmpegcommand">Cloning an FfmpegCommand</a></li></ul><li><a href="index.html#contributing">Contributing</a></li><ul><li><a href="index.html#code-contributions">Code contributions</a></li><li><a href="index.html#documentation-contributions">Documentation contributions</a></li><li><a href="index.html#updating-the-documentation">Updating the documentation</a></li><li><a href="index.html#running-tests">Running tests</a></li></ul><li><a href="index.html#main-contributors">Main contributors</a></li><ul></ul><li><a href="index.html#license">License</a></li><ul></ul></ul><h3>Classes</h3><ul><li><a href="FfmpegCommand.html">FfmpegCommand</a></li><ul><li> <a href="FfmpegCommand.html#audio-methods">Audio methods</a></li><li> <a href="FfmpegCommand.html#capabilities-methods">Capabilities methods</a></li><li> <a href="FfmpegCommand.html#custom-options-methods">Custom options methods</a></li><li> <a href="FfmpegCommand.html#input-methods">Input methods</a></li><li> <a href="FfmpegCommand.html#metadata-methods">Metadata methods</a></li><li> <a href="FfmpegCommand.html#miscellaneous-methods">Miscellaneous methods</a></li><li> <a href="FfmpegCommand.html#other-methods">Other methods</a></li><li> <a href="FfmpegCommand.html#output-methods">Output methods</a></li><li> <a href="FfmpegCommand.html#processing-methods">Processing methods</a></li><li> <a href="FfmpegCommand.html#video-methods">Video methods</a></li><li> <a href="FfmpegCommand.html#video-size-methods">Video size methods</a></li></ul></ul>
217 | </nav>
218 | 
219 | <br clear="both">
220 | 
221 | <footer>
222 |     Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.0-alpha5</a> on Tue Jul 08 2014 21:22:19 GMT+0200 (CEST)
223 | </footer>
224 | 
225 | <script> prettyPrint(); </script>
226 | <script src="scripts/linenumber.js"> </script>
227 | </body>
228 | </html>
229 | 


--------------------------------------------------------------------------------
/doc/inputs.js.html:
--------------------------------------------------------------------------------
  1 | <!DOCTYPE html>
  2 | <html lang="en">
  3 | <head>
  4 |     <meta charset="utf-8">
  5 |     <title>JSDoc: Source: options/inputs.js</title>
  6 | 
  7 |     <script src="scripts/prettify/prettify.js"> </script>
  8 |     <script src="scripts/prettify/lang-css.js"> </script>
  9 |     <!--[if lt IE 9]>
 10 |       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
 11 |     <![endif]-->
 12 |     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
 13 |     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
 14 | </head>
 15 | 
 16 | <body>
 17 | 
 18 | <div id="main">
 19 | 
 20 |     <h1 class="page-title">Source: options/inputs.js</h1>
 21 | 
 22 |     
 23 | 
 24 | 
 25 |     
 26 |     <section>
 27 |         <article>
 28 |             <pre class="prettyprint source linenums"><code>/*jshint node:true*/
 29 | 'use strict';
 30 | 
 31 | var utils = require('../utils');
 32 | 
 33 | /*
 34 |  *! Input-related methods
 35 |  */
 36 | 
 37 | module.exports = function(proto) {
 38 |   /**
 39 |    * Add an input to command
 40 |    *
 41 |    * Also switches "current input", that is the input that will be affected
 42 |    * by subsequent input-related methods.
 43 |    *
 44 |    * Note: only one stream input is supported for now.
 45 |    *
 46 |    * @method FfmpegCommand#input
 47 |    * @category Input
 48 |    * @aliases mergeAdd,addInput
 49 |    *
 50 |    * @param {String|Readable} source input file path or readable stream
 51 |    * @return FfmpegCommand
 52 |    */
 53 |   proto.mergeAdd =
 54 |   proto.addInput =
 55 |   proto.input = function(source) {
 56 |     var isFile = false;
 57 | 
 58 |     if (typeof source !== 'string') {
 59 |       if (!('readable' in source) || !(source.readable)) {
 60 |         throw new Error('Invalid input');
 61 |       }
 62 | 
 63 |       var hasInputStream = this._inputs.some(function(input) {
 64 |         return typeof input.source !== 'string';
 65 |       });
 66 | 
 67 |       if (hasInputStream) {
 68 |         throw new Error('Only one input stream is supported');
 69 |       }
 70 | 
 71 |       source.pause();
 72 |     } else {
 73 |       var protocol = source.match(/^([a-z]{2,}):/i);
 74 |       isFile = !protocol || protocol[0] === 'file';
 75 |     }
 76 | 
 77 |     this._inputs.push(this._currentInput = {
 78 |       source: source,
 79 |       isFile: isFile,
 80 |       options: utils.args()
 81 |     });
 82 | 
 83 |     return this;
 84 |   };
 85 | 
 86 | 
 87 |   /**
 88 |    * Specify input format for the last specified input
 89 |    *
 90 |    * @method FfmpegCommand#inputFormat
 91 |    * @category Input
 92 |    * @aliases withInputFormat,fromFormat
 93 |    *
 94 |    * @param {String} format input format
 95 |    * @return FfmpegCommand
 96 |    */
 97 |   proto.withInputFormat =
 98 |   proto.inputFormat =
 99 |   proto.fromFormat = function(format) {
100 |     if (!this._currentInput) {
101 |       throw new Error('No input specified');
102 |     }
103 | 
104 |     this._currentInput.options('-f', format);
105 |     return this;
106 |   };
107 | 
108 | 
109 |   /**
110 |    * Specify input FPS for the last specified input
111 |    * (only valid for raw video formats)
112 |    *
113 |    * @method FfmpegCommand#inputFps
114 |    * @category Input
115 |    * @aliases withInputFps,withInputFPS,withFpsInput,withFPSInput,inputFPS,inputFps,fpsInput
116 |    *
117 |    * @param {Number} fps input FPS
118 |    * @return FfmpegCommand
119 |    */
120 |   proto.withInputFps =
121 |   proto.withInputFPS =
122 |   proto.withFpsInput =
123 |   proto.withFPSInput =
124 |   proto.inputFPS =
125 |   proto.inputFps =
126 |   proto.fpsInput =
127 |   proto.FPSInput = function(fps) {
128 |     if (!this._currentInput) {
129 |       throw new Error('No input specified');
130 |     }
131 | 
132 |     this._currentInput.options('-r', fps);
133 |     return this;
134 |   };
135 | 
136 | 
137 |   /**
138 |    * Use native framerate for the last specified input
139 |    *
140 |    * @method FfmpegCommand#native
141 |    * @category Input
142 |    * @aliases nativeFramerate,withNativeFramerate
143 |    *
144 |    * @return FfmmegCommand
145 |    */
146 |   proto.nativeFramerate =
147 |   proto.withNativeFramerate =
148 |   proto.native = function() {
149 |     if (!this._currentInput) {
150 |       throw new Error('No input specified');
151 |     }
152 | 
153 |     this._currentInput.options('-re');
154 |     return this;
155 |   };
156 | 
157 | 
158 |   /**
159 |    * Specify input seek time for the last specified input
160 |    *
161 |    * @method FfmpegCommand#seekInput
162 |    * @category Input
163 |    * @aliases setStartTime,seekTo
164 |    *
165 |    * @param {String|Number} seek seek time in seconds or as a '[hh:[mm:]]ss[.xxx]' string
166 |    * @return FfmpegCommand
167 |    */
168 |   proto.setStartTime =
169 |   proto.seekInput = function(seek) {
170 |     if (!this._currentInput) {
171 |       throw new Error('No input specified');
172 |     }
173 | 
174 |     this._currentInput.options('-ss', seek);
175 | 
176 |     return this;
177 |   };
178 | 
179 | 
180 |   /**
181 |    * Loop over the last specified input
182 |    *
183 |    * @method FfmpegCommand#loop
184 |    * @category Input
185 |    *
186 |    * @param {String|Number} [duration] loop duration in seconds or as a '[[hh:]mm:]ss[.xxx]' string
187 |    * @return FfmpegCommand
188 |    */
189 |   proto.loop = function(duration) {
190 |     if (!this._currentInput) {
191 |       throw new Error('No input specified');
192 |     }
193 | 
194 |     this._currentInput.options('-loop', '1');
195 | 
196 |     if (typeof duration !== 'undefined') {
197 |       this.duration(duration);
198 |     }
199 | 
200 |     return this;
201 |   };
202 | };
203 | </code></pre>
204 |         </article>
205 |     </section>
206 | 
207 | 
208 | 
209 | 
210 | </div>
211 | 
212 | <nav>
213 |     <h2><a href="index.html">Index</a></h2><ul><li><a href="index.html#installation">Installation</a></li><ul></ul><li><a href="index.html#usage">Usage</a></li><ul><li><a href="index.html#prerequisites">Prerequisites</a></li><li><a href="index.html#creating-an-ffmpeg-command">Creating an FFmpeg command</a></li><li><a href="index.html#specifying-inputs">Specifying inputs</a></li><li><a href="index.html#input-options">Input options</a></li><li><a href="index.html#audio-options">Audio options</a></li><li><a href="index.html#video-options">Video options</a></li><li><a href="index.html#video-frame-size-options">Video frame size options</a></li><li><a href="index.html#specifying-multiple-outputs">Specifying multiple outputs</a></li><li><a href="index.html#output-options">Output options</a></li><li><a href="index.html#miscellaneous-options">Miscellaneous options</a></li><li><a href="index.html#setting-event-handlers">Setting event handlers</a></li><li><a href="index.html#starting-ffmpeg-processing">Starting FFmpeg processing</a></li><li><a href="index.html#controlling-the-ffmpeg-process">Controlling the FFmpeg process</a></li><li><a href="index.html#reading-video-metadata">Reading video metadata</a></li><li><a href="index.html#querying-ffmpeg-capabilities">Querying ffmpeg capabilities</a></li><li><a href="index.html#cloning-an-ffmpegcommand">Cloning an FfmpegCommand</a></li></ul><li><a href="index.html#contributing">Contributing</a></li><ul><li><a href="index.html#code-contributions">Code contributions</a></li><li><a href="index.html#documentation-contributions">Documentation contributions</a></li><li><a href="index.html#updating-the-documentation">Updating the documentation</a></li><li><a href="index.html#running-tests">Running tests</a></li></ul><li><a href="index.html#main-contributors">Main contributors</a></li><ul></ul><li><a href="index.html#license">License</a></li><ul></ul></ul><h3>Classes</h3><ul><li><a href="FfmpegCommand.html">FfmpegCommand</a></li><ul><li> <a href="FfmpegCommand.html#audio-methods">Audio methods</a></li><li> <a href="FfmpegCommand.html#capabilities-methods">Capabilities methods</a></li><li> <a href="FfmpegCommand.html#custom-options-methods">Custom options methods</a></li><li> <a href="FfmpegCommand.html#input-methods">Input methods</a></li><li> <a href="FfmpegCommand.html#metadata-methods">Metadata methods</a></li><li> <a href="FfmpegCommand.html#miscellaneous-methods">Miscellaneous methods</a></li><li> <a href="FfmpegCommand.html#other-methods">Other methods</a></li><li> <a href="FfmpegCommand.html#output-methods">Output methods</a></li><li> <a href="FfmpegCommand.html#processing-methods">Processing methods</a></li><li> <a href="FfmpegCommand.html#video-methods">Video methods</a></li><li> <a href="FfmpegCommand.html#video-size-methods">Video size methods</a></li></ul></ul>
214 | </nav>
215 | 
216 | <br clear="both">
217 | 
218 | <footer>
219 |     Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.0-alpha5</a> on Tue Jul 08 2014 21:22:19 GMT+0200 (CEST)
220 | </footer>
221 | 
222 | <script> prettyPrint(); </script>
223 | <script src="scripts/linenumber.js"> </script>
224 | </body>
225 | </html>
226 | 


--------------------------------------------------------------------------------
/doc/misc.js.html:
--------------------------------------------------------------------------------
 1 | <!DOCTYPE html>
 2 | <html lang="en">
 3 | <head>
 4 |     <meta charset="utf-8">
 5 |     <title>JSDoc: Source: options/misc.js</title>
 6 | 
 7 |     <script src="scripts/prettify/prettify.js"> </script>
 8 |     <script src="scripts/prettify/lang-css.js"> </script>
 9 |     <!--[if lt IE 9]>
10 |       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
11 |     <![endif]-->
12 |     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
13 |     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
14 | </head>
15 | 
16 | <body>
17 | 
18 | <div id="main">
19 | 
20 |     <h1 class="page-title">Source: options/misc.js</h1>
21 | 
22 |     
23 | 
24 | 
25 |     
26 |     <section>
27 |         <article>
28 |             <pre class="prettyprint source linenums"><code>/*jshint node:true*/
29 | 'use strict';
30 | 
31 | var path = require('path');
32 | 
33 | /*
34 |  *! Miscellaneous methods
35 |  */
36 | 
37 | module.exports = function(proto) {
38 |   /**
39 |    * Use preset
40 |    *
41 |    * @method FfmpegCommand#preset
42 |    * @category Miscellaneous
43 |    * @aliases usingPreset
44 |    *
45 |    * @param {String|Function} preset preset name or preset function
46 |    */
47 |   proto.usingPreset =
48 |   proto.preset = function(preset) {
49 |     if (typeof preset === 'function') {
50 |       preset(this);
51 |     } else {
52 |       try {
53 |         var modulePath = path.join(this.options.presets, preset);
54 |         var module = require(modulePath);
55 | 
56 |         if (typeof module.load === 'function') {
57 |           module.load(this);
58 |         } else {
59 |           throw new Error('preset ' + modulePath + ' has no load() function');
60 |         }
61 |       } catch (err) {
62 |         throw new Error('preset ' + modulePath + ' could not be loaded: ' + err.message);
63 |       }
64 |     }
65 | 
66 |     return this;
67 |   };
68 | };
69 | </code></pre>
70 |         </article>
71 |     </section>
72 | 
73 | 
74 | 
75 | 
76 | </div>
77 | 
78 | <nav>
79 |     <h2><a href="index.html">Index</a></h2><ul><li><a href="index.html#installation">Installation</a></li><ul></ul><li><a href="index.html#usage">Usage</a></li><ul><li><a href="index.html#prerequisites">Prerequisites</a></li><li><a href="index.html#creating-an-ffmpeg-command">Creating an FFmpeg command</a></li><li><a href="index.html#specifying-inputs">Specifying inputs</a></li><li><a href="index.html#input-options">Input options</a></li><li><a href="index.html#audio-options">Audio options</a></li><li><a href="index.html#video-options">Video options</a></li><li><a href="index.html#video-frame-size-options">Video frame size options</a></li><li><a href="index.html#specifying-multiple-outputs">Specifying multiple outputs</a></li><li><a href="index.html#output-options">Output options</a></li><li><a href="index.html#miscellaneous-options">Miscellaneous options</a></li><li><a href="index.html#setting-event-handlers">Setting event handlers</a></li><li><a href="index.html#starting-ffmpeg-processing">Starting FFmpeg processing</a></li><li><a href="index.html#controlling-the-ffmpeg-process">Controlling the FFmpeg process</a></li><li><a href="index.html#reading-video-metadata">Reading video metadata</a></li><li><a href="index.html#querying-ffmpeg-capabilities">Querying ffmpeg capabilities</a></li><li><a href="index.html#cloning-an-ffmpegcommand">Cloning an FfmpegCommand</a></li></ul><li><a href="index.html#contributing">Contributing</a></li><ul><li><a href="index.html#code-contributions">Code contributions</a></li><li><a href="index.html#documentation-contributions">Documentation contributions</a></li><li><a href="index.html#updating-the-documentation">Updating the documentation</a></li><li><a href="index.html#running-tests">Running tests</a></li></ul><li><a href="index.html#main-contributors">Main contributors</a></li><ul></ul><li><a href="index.html#license">License</a></li><ul></ul></ul><h3>Classes</h3><ul><li><a href="FfmpegCommand.html">FfmpegCommand</a></li><ul><li> <a href="FfmpegCommand.html#audio-methods">Audio methods</a></li><li> <a href="FfmpegCommand.html#capabilities-methods">Capabilities methods</a></li><li> <a href="FfmpegCommand.html#custom-options-methods">Custom options methods</a></li><li> <a href="FfmpegCommand.html#input-methods">Input methods</a></li><li> <a href="FfmpegCommand.html#metadata-methods">Metadata methods</a></li><li> <a href="FfmpegCommand.html#miscellaneous-methods">Miscellaneous methods</a></li><li> <a href="FfmpegCommand.html#other-methods">Other methods</a></li><li> <a href="FfmpegCommand.html#output-methods">Output methods</a></li><li> <a href="FfmpegCommand.html#processing-methods">Processing methods</a></li><li> <a href="FfmpegCommand.html#video-methods">Video methods</a></li><li> <a href="FfmpegCommand.html#video-size-methods">Video size methods</a></li></ul></ul>
80 | </nav>
81 | 
82 | <br clear="both">
83 | 
84 | <footer>
85 |     Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.0-alpha5</a> on Tue Jul 08 2014 21:22:19 GMT+0200 (CEST)
86 | </footer>
87 | 
88 | <script> prettyPrint(); </script>
89 | <script src="scripts/linenumber.js"> </script>
90 | </body>
91 | </html>
92 | 


--------------------------------------------------------------------------------
/doc/options_audio.js.html:
--------------------------------------------------------------------------------
  1 | <!DOCTYPE html>
  2 | <html lang="en">
  3 | <head>
  4 |     <meta charset="utf-8">
  5 |     <title>JSDoc: Source: options/audio.js</title>
  6 | 
  7 |     <script src="scripts/prettify/prettify.js"> </script>
  8 |     <script src="scripts/prettify/lang-css.js"> </script>
  9 |     <!--[if lt IE 9]>
 10 |       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
 11 |     <![endif]-->
 12 |     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
 13 |     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
 14 | </head>
 15 | 
 16 | <body>
 17 | 
 18 | <div id="main">
 19 | 
 20 |     <h1 class="page-title">Source: options/audio.js</h1>
 21 | 
 22 |     
 23 | 
 24 | 
 25 |     
 26 |     <section>
 27 |         <article>
 28 |             <pre class="prettyprint source linenums"><code>/*jshint node:true*/
 29 | 'use strict';
 30 | 
 31 | var utils = require('../utils');
 32 | 
 33 | 
 34 | /*
 35 |  *! Audio-related methods
 36 |  */
 37 | 
 38 | module.exports = function(proto) {
 39 |   /**
 40 |    * Disable audio in the output
 41 |    *
 42 |    * @method FfmpegCommand#noAudio
 43 |    * @category Audio
 44 |    * @aliases withNoAudio
 45 |    * @return FfmpegCommand
 46 |    */
 47 |   proto.withNoAudio =
 48 |   proto.noAudio = function() {
 49 |     this._currentOutput.audio.clear();
 50 |     this._currentOutput.audioFilters.clear();
 51 |     this._currentOutput.audio('-an');
 52 | 
 53 |     return this;
 54 |   };
 55 | 
 56 | 
 57 |   /**
 58 |    * Specify audio codec
 59 |    *
 60 |    * @method FfmpegCommand#audioCodec
 61 |    * @category Audio
 62 |    * @aliases withAudioCodec
 63 |    *
 64 |    * @param {String} codec audio codec name
 65 |    * @return FfmpegCommand
 66 |    */
 67 |   proto.withAudioCodec =
 68 |   proto.audioCodec = function(codec) {
 69 |     this._currentOutput.audio('-acodec', codec);
 70 | 
 71 |     return this;
 72 |   };
 73 | 
 74 | 
 75 |   /**
 76 |    * Specify audio bitrate
 77 |    *
 78 |    * @method FfmpegCommand#audioBitrate
 79 |    * @category Audio
 80 |    * @aliases withAudioBitrate
 81 |    *
 82 |    * @param {String|Number} bitrate audio bitrate in kbps (with an optional 'k' suffix)
 83 |    * @return FfmpegCommand
 84 |    */
 85 |   proto.withAudioBitrate =
 86 |   proto.audioBitrate = function(bitrate) {
 87 |     this._currentOutput.audio('-b:a', ('' + bitrate).replace(/k?$/, 'k'));
 88 |     return this;
 89 |   };
 90 | 
 91 | 
 92 |   /**
 93 |    * Specify audio channel count
 94 |    *
 95 |    * @method FfmpegCommand#audioChannels
 96 |    * @category Audio
 97 |    * @aliases withAudioChannels
 98 |    *
 99 |    * @param {Number} channels channel count
100 |    * @return FfmpegCommand
101 |    */
102 |   proto.withAudioChannels =
103 |   proto.audioChannels = function(channels) {
104 |     this._currentOutput.audio('-ac', channels);
105 |     return this;
106 |   };
107 | 
108 | 
109 |   /**
110 |    * Specify audio frequency
111 |    *
112 |    * @method FfmpegCommand#audioFrequency
113 |    * @category Audio
114 |    * @aliases withAudioFrequency
115 |    *
116 |    * @param {Number} freq audio frequency in Hz
117 |    * @return FfmpegCommand
118 |    */
119 |   proto.withAudioFrequency =
120 |   proto.audioFrequency = function(freq) {
121 |     this._currentOutput.audio('-ar', freq);
122 |     return this;
123 |   };
124 | 
125 | 
126 |   /**
127 |    * Specify audio quality
128 |    *
129 |    * @method FfmpegCommand#audioQuality
130 |    * @category Audio
131 |    * @aliases withAudioQuality
132 |    *
133 |    * @param {Number} quality audio quality factor
134 |    * @return FfmpegCommand
135 |    */
136 |   proto.withAudioQuality =
137 |   proto.audioQuality = function(quality) {
138 |     this._currentOutput.audio('-aq', quality);
139 |     return this;
140 |   };
141 | 
142 | 
143 |   /**
144 |    * Specify custom audio filter(s)
145 |    *
146 |    * Can be called both with one or many filters, or a filter array.
147 |    *
148 |    * @example
149 |    * command.audioFilters('filter1');
150 |    *
151 |    * @example
152 |    * command.audioFilters('filter1', 'filter2=param1=value1:param2=value2');
153 |    *
154 |    * @example
155 |    * command.audioFilters(['filter1', 'filter2']);
156 |    *
157 |    * @example
158 |    * command.audioFilters([
159 |    *   {
160 |    *     filter: 'filter1'
161 |    *   },
162 |    *   {
163 |    *     filter: 'filter2',
164 |    *     options: 'param=value:param=value'
165 |    *   }
166 |    * ]);
167 |    *
168 |    * @example
169 |    * command.audioFilters(
170 |    *   {
171 |    *     filter: 'filter1',
172 |    *     options: ['value1', 'value2']
173 |    *   },
174 |    *   {
175 |    *     filter: 'filter2',
176 |    *     options: { param1: 'value1', param2: 'value2' }
177 |    *   }
178 |    * );
179 |    *
180 |    * @method FfmpegCommand#audioFilters
181 |    * @aliases withAudioFilter,withAudioFilters,audioFilter
182 |    * @category Audio
183 |    *
184 |    * @param {...String|String[]|Object[]} filters audio filter strings, string array or
185 |    *   filter specification array, each with the following properties:
186 |    * @param {String} filters.filter filter name
187 |    * @param {String|String[]|Object} [filters.options] filter option string, array, or object
188 |    * @return FfmpegCommand
189 |    */
190 |   proto.withAudioFilter =
191 |   proto.withAudioFilters =
192 |   proto.audioFilter =
193 |   proto.audioFilters = function(filters) {
194 |     if (arguments.length > 1) {
195 |       filters = [].slice.call(arguments);
196 |     }
197 | 
198 |     if (!Array.isArray(filters)) {
199 |       filters = [filters];
200 |     }
201 | 
202 |     this._currentOutput.audioFilters(utils.makeFilterStrings(filters));
203 |     return this;
204 |   };
205 | };
206 | </code></pre>
207 |         </article>
208 |     </section>
209 | 
210 | 
211 | 
212 | 
213 | </div>
214 | 
215 | <nav>
216 |     <h2><a href="index.html">Index</a></h2><ul><li><a href="index.html#installation">Installation</a></li><ul></ul><li><a href="index.html#usage">Usage</a></li><ul><li><a href="index.html#prerequisites">Prerequisites</a></li><li><a href="index.html#creating-an-ffmpeg-command">Creating an FFmpeg command</a></li><li><a href="index.html#specifying-inputs">Specifying inputs</a></li><li><a href="index.html#input-options">Input options</a></li><li><a href="index.html#audio-options">Audio options</a></li><li><a href="index.html#video-options">Video options</a></li><li><a href="index.html#video-frame-size-options">Video frame size options</a></li><li><a href="index.html#specifying-multiple-outputs">Specifying multiple outputs</a></li><li><a href="index.html#output-options">Output options</a></li><li><a href="index.html#miscellaneous-options">Miscellaneous options</a></li><li><a href="index.html#setting-event-handlers">Setting event handlers</a></li><li><a href="index.html#starting-ffmpeg-processing">Starting FFmpeg processing</a></li><li><a href="index.html#controlling-the-ffmpeg-process">Controlling the FFmpeg process</a></li><li><a href="index.html#reading-video-metadata">Reading video metadata</a></li><li><a href="index.html#querying-ffmpeg-capabilities">Querying ffmpeg capabilities</a></li><li><a href="index.html#cloning-an-ffmpegcommand">Cloning an FfmpegCommand</a></li></ul><li><a href="index.html#contributing">Contributing</a></li><ul><li><a href="index.html#code-contributions">Code contributions</a></li><li><a href="index.html#documentation-contributions">Documentation contributions</a></li><li><a href="index.html#updating-the-documentation">Updating the documentation</a></li><li><a href="index.html#running-tests">Running tests</a></li></ul><li><a href="index.html#main-contributors">Main contributors</a></li><ul></ul><li><a href="index.html#license">License</a></li><ul></ul></ul><h3>Classes</h3><ul><li><a href="FfmpegCommand.html">FfmpegCommand</a></li><ul><li> <a href="FfmpegCommand.html#audio-methods">Audio methods</a></li><li> <a href="FfmpegCommand.html#capabilities-methods">Capabilities methods</a></li><li> <a href="FfmpegCommand.html#custom-options-methods">Custom options methods</a></li><li> <a href="FfmpegCommand.html#input-methods">Input methods</a></li><li> <a href="FfmpegCommand.html#metadata-methods">Metadata methods</a></li><li> <a href="FfmpegCommand.html#miscellaneous-methods">Miscellaneous methods</a></li><li> <a href="FfmpegCommand.html#other-methods">Other methods</a></li><li> <a href="FfmpegCommand.html#output-methods">Output methods</a></li><li> <a href="FfmpegCommand.html#processing-methods">Processing methods</a></li><li> <a href="FfmpegCommand.html#video-methods">Video methods</a></li><li> <a href="FfmpegCommand.html#video-size-methods">Video size methods</a></li></ul></ul>
217 | </nav>
218 | 
219 | <br clear="both">
220 | 
221 | <footer>
222 |     Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Sun May 01 2016 12:10:37 GMT+0200 (CEST)
223 | </footer>
224 | 
225 | <script> prettyPrint(); </script>
226 | <script src="scripts/linenumber.js"> </script>
227 | </body>
228 | </html>
229 | 


--------------------------------------------------------------------------------
/doc/options_inputs.js.html:
--------------------------------------------------------------------------------
  1 | <!DOCTYPE html>
  2 | <html lang="en">
  3 | <head>
  4 |     <meta charset="utf-8">
  5 |     <title>JSDoc: Source: options/inputs.js</title>
  6 | 
  7 |     <script src="scripts/prettify/prettify.js"> </script>
  8 |     <script src="scripts/prettify/lang-css.js"> </script>
  9 |     <!--[if lt IE 9]>
 10 |       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
 11 |     <![endif]-->
 12 |     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
 13 |     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
 14 | </head>
 15 | 
 16 | <body>
 17 | 
 18 | <div id="main">
 19 | 
 20 |     <h1 class="page-title">Source: options/inputs.js</h1>
 21 | 
 22 |     
 23 | 
 24 | 
 25 |     
 26 |     <section>
 27 |         <article>
 28 |             <pre class="prettyprint source linenums"><code>/*jshint node:true*/
 29 | 'use strict';
 30 | 
 31 | var utils = require('../utils');
 32 | 
 33 | /*
 34 |  *! Input-related methods
 35 |  */
 36 | 
 37 | module.exports = function(proto) {
 38 |   /**
 39 |    * Add an input to command
 40 |    *
 41 |    * Also switches "current input", that is the input that will be affected
 42 |    * by subsequent input-related methods.
 43 |    *
 44 |    * Note: only one stream input is supported for now.
 45 |    *
 46 |    * @method FfmpegCommand#input
 47 |    * @category Input
 48 |    * @aliases mergeAdd,addInput
 49 |    *
 50 |    * @param {String|Readable} source input file path or readable stream
 51 |    * @return FfmpegCommand
 52 |    */
 53 |   proto.mergeAdd =
 54 |   proto.addInput =
 55 |   proto.input = function(source) {
 56 |     var isFile = false;
 57 |     var isStream = false;
 58 | 
 59 |     if (typeof source !== 'string') {
 60 |       if (!('readable' in source) || !(source.readable)) {
 61 |         throw new Error('Invalid input');
 62 |       }
 63 | 
 64 |       var hasInputStream = this._inputs.some(function(input) {
 65 |         return input.isStream;
 66 |       });
 67 | 
 68 |       if (hasInputStream) {
 69 |         throw new Error('Only one input stream is supported');
 70 |       }
 71 | 
 72 |       isStream = true;
 73 |       source.pause();
 74 |     } else {
 75 |       var protocol = source.match(/^([a-z]{2,}):/i);
 76 |       isFile = !protocol || protocol[0] === 'file';
 77 |     }
 78 | 
 79 |     this._inputs.push(this._currentInput = {
 80 |       source: source,
 81 |       isFile: isFile,
 82 |       isStream: isStream,
 83 |       options: utils.args()
 84 |     });
 85 | 
 86 |     return this;
 87 |   };
 88 | 
 89 | 
 90 |   /**
 91 |    * Specify input format for the last specified input
 92 |    *
 93 |    * @method FfmpegCommand#inputFormat
 94 |    * @category Input
 95 |    * @aliases withInputFormat,fromFormat
 96 |    *
 97 |    * @param {String} format input format
 98 |    * @return FfmpegCommand
 99 |    */
100 |   proto.withInputFormat =
101 |   proto.inputFormat =
102 |   proto.fromFormat = function(format) {
103 |     if (!this._currentInput) {
104 |       throw new Error('No input specified');
105 |     }
106 | 
107 |     this._currentInput.options('-f', format);
108 |     return this;
109 |   };
110 | 
111 | 
112 |   /**
113 |    * Specify input FPS for the last specified input
114 |    * (only valid for raw video formats)
115 |    *
116 |    * @method FfmpegCommand#inputFps
117 |    * @category Input
118 |    * @aliases withInputFps,withInputFPS,withFpsInput,withFPSInput,inputFPS,inputFps,fpsInput
119 |    *
120 |    * @param {Number} fps input FPS
121 |    * @return FfmpegCommand
122 |    */
123 |   proto.withInputFps =
124 |   proto.withInputFPS =
125 |   proto.withFpsInput =
126 |   proto.withFPSInput =
127 |   proto.inputFPS =
128 |   proto.inputFps =
129 |   proto.fpsInput =
130 |   proto.FPSInput = function(fps) {
131 |     if (!this._currentInput) {
132 |       throw new Error('No input specified');
133 |     }
134 | 
135 |     this._currentInput.options('-r', fps);
136 |     return this;
137 |   };
138 | 
139 | 
140 |   /**
141 |    * Use native framerate for the last specified input
142 |    *
143 |    * @method FfmpegCommand#native
144 |    * @category Input
145 |    * @aliases nativeFramerate,withNativeFramerate
146 |    *
147 |    * @return FfmmegCommand
148 |    */
149 |   proto.nativeFramerate =
150 |   proto.withNativeFramerate =
151 |   proto.native = function() {
152 |     if (!this._currentInput) {
153 |       throw new Error('No input specified');
154 |     }
155 | 
156 |     this._currentInput.options('-re');
157 |     return this;
158 |   };
159 | 
160 | 
161 |   /**
162 |    * Specify input seek time for the last specified input
163 |    *
164 |    * @method FfmpegCommand#seekInput
165 |    * @category Input
166 |    * @aliases setStartTime,seekTo
167 |    *
168 |    * @param {String|Number} seek seek time in seconds or as a '[hh:[mm:]]ss[.xxx]' string
169 |    * @return FfmpegCommand
170 |    */
171 |   proto.setStartTime =
172 |   proto.seekInput = function(seek) {
173 |     if (!this._currentInput) {
174 |       throw new Error('No input specified');
175 |     }
176 | 
177 |     this._currentInput.options('-ss', seek);
178 | 
179 |     return this;
180 |   };
181 | 
182 | 
183 |   /**
184 |    * Loop over the last specified input
185 |    *
186 |    * @method FfmpegCommand#loop
187 |    * @category Input
188 |    *
189 |    * @param {String|Number} [duration] loop duration in seconds or as a '[[hh:]mm:]ss[.xxx]' string
190 |    * @return FfmpegCommand
191 |    */
192 |   proto.loop = function(duration) {
193 |     if (!this._currentInput) {
194 |       throw new Error('No input specified');
195 |     }
196 | 
197 |     this._currentInput.options('-loop', '1');
198 | 
199 |     if (typeof duration !== 'undefined') {
200 |       this.duration(duration);
201 |     }
202 | 
203 |     return this;
204 |   };
205 | };
206 | </code></pre>
207 |         </article>
208 |     </section>
209 | 
210 | 
211 | 
212 | 
213 | </div>
214 | 
215 | <nav>
216 |     <h2><a href="index.html">Index</a></h2><ul><li><a href="index.html#installation">Installation</a></li><ul></ul><li><a href="index.html#usage">Usage</a></li><ul><li><a href="index.html#prerequisites">Prerequisites</a></li><li><a href="index.html#creating-an-ffmpeg-command">Creating an FFmpeg command</a></li><li><a href="index.html#specifying-inputs">Specifying inputs</a></li><li><a href="index.html#input-options">Input options</a></li><li><a href="index.html#audio-options">Audio options</a></li><li><a href="index.html#video-options">Video options</a></li><li><a href="index.html#video-frame-size-options">Video frame size options</a></li><li><a href="index.html#specifying-multiple-outputs">Specifying multiple outputs</a></li><li><a href="index.html#output-options">Output options</a></li><li><a href="index.html#miscellaneous-options">Miscellaneous options</a></li><li><a href="index.html#setting-event-handlers">Setting event handlers</a></li><li><a href="index.html#starting-ffmpeg-processing">Starting FFmpeg processing</a></li><li><a href="index.html#controlling-the-ffmpeg-process">Controlling the FFmpeg process</a></li><li><a href="index.html#reading-video-metadata">Reading video metadata</a></li><li><a href="index.html#querying-ffmpeg-capabilities">Querying ffmpeg capabilities</a></li><li><a href="index.html#cloning-an-ffmpegcommand">Cloning an FfmpegCommand</a></li></ul><li><a href="index.html#contributing">Contributing</a></li><ul><li><a href="index.html#code-contributions">Code contributions</a></li><li><a href="index.html#documentation-contributions">Documentation contributions</a></li><li><a href="index.html#updating-the-documentation">Updating the documentation</a></li><li><a href="index.html#running-tests">Running tests</a></li></ul><li><a href="index.html#main-contributors">Main contributors</a></li><ul></ul><li><a href="index.html#license">License</a></li><ul></ul></ul><h3>Classes</h3><ul><li><a href="FfmpegCommand.html">FfmpegCommand</a></li><ul><li> <a href="FfmpegCommand.html#audio-methods">Audio methods</a></li><li> <a href="FfmpegCommand.html#capabilities-methods">Capabilities methods</a></li><li> <a href="FfmpegCommand.html#custom-options-methods">Custom options methods</a></li><li> <a href="FfmpegCommand.html#input-methods">Input methods</a></li><li> <a href="FfmpegCommand.html#metadata-methods">Metadata methods</a></li><li> <a href="FfmpegCommand.html#miscellaneous-methods">Miscellaneous methods</a></li><li> <a href="FfmpegCommand.html#other-methods">Other methods</a></li><li> <a href="FfmpegCommand.html#output-methods">Output methods</a></li><li> <a href="FfmpegCommand.html#processing-methods">Processing methods</a></li><li> <a href="FfmpegCommand.html#video-methods">Video methods</a></li><li> <a href="FfmpegCommand.html#video-size-methods">Video size methods</a></li></ul></ul>
217 | </nav>
218 | 
219 | <br clear="both">
220 | 
221 | <footer>
222 |     Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Sun May 01 2016 12:10:37 GMT+0200 (CEST)
223 | </footer>
224 | 
225 | <script> prettyPrint(); </script>
226 | <script src="scripts/linenumber.js"> </script>
227 | </body>
228 | </html>
229 | 


--------------------------------------------------------------------------------
/doc/options_misc.js.html:
--------------------------------------------------------------------------------
 1 | <!DOCTYPE html>
 2 | <html lang="en">
 3 | <head>
 4 |     <meta charset="utf-8">
 5 |     <title>JSDoc: Source: options/misc.js</title>
 6 | 
 7 |     <script src="scripts/prettify/prettify.js"> </script>
 8 |     <script src="scripts/prettify/lang-css.js"> </script>
 9 |     <!--[if lt IE 9]>
10 |       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
11 |     <![endif]-->
12 |     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
13 |     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
14 | </head>
15 | 
16 | <body>
17 | 
18 | <div id="main">
19 | 
20 |     <h1 class="page-title">Source: options/misc.js</h1>
21 | 
22 |     
23 | 
24 | 
25 |     
26 |     <section>
27 |         <article>
28 |             <pre class="prettyprint source linenums"><code>/*jshint node:true*/
29 | 'use strict';
30 | 
31 | var path = require('path');
32 | 
33 | /*
34 |  *! Miscellaneous methods
35 |  */
36 | 
37 | module.exports = function(proto) {
38 |   /**
39 |    * Use preset
40 |    *
41 |    * @method FfmpegCommand#preset
42 |    * @category Miscellaneous
43 |    * @aliases usingPreset
44 |    *
45 |    * @param {String|Function} preset preset name or preset function
46 |    */
47 |   proto.usingPreset =
48 |   proto.preset = function(preset) {
49 |     if (typeof preset === 'function') {
50 |       preset(this);
51 |     } else {
52 |       try {
53 |         var modulePath = path.join(this.options.presets, preset);
54 |         var module = require(modulePath);
55 | 
56 |         if (typeof module.load === 'function') {
57 |           module.load(this);
58 |         } else {
59 |           throw new Error('preset ' + modulePath + ' has no load() function');
60 |         }
61 |       } catch (err) {
62 |         throw new Error('preset ' + modulePath + ' could not be loaded: ' + err.message);
63 |       }
64 |     }
65 | 
66 |     return this;
67 |   };
68 | };
69 | </code></pre>
70 |         </article>
71 |     </section>
72 | 
73 | 
74 | 
75 | 
76 | </div>
77 | 
78 | <nav>
79 |     <h2><a href="index.html">Index</a></h2><ul><li><a href="index.html#installation">Installation</a></li><ul></ul><li><a href="index.html#usage">Usage</a></li><ul><li><a href="index.html#prerequisites">Prerequisites</a></li><li><a href="index.html#creating-an-ffmpeg-command">Creating an FFmpeg command</a></li><li><a href="index.html#specifying-inputs">Specifying inputs</a></li><li><a href="index.html#input-options">Input options</a></li><li><a href="index.html#audio-options">Audio options</a></li><li><a href="index.html#video-options">Video options</a></li><li><a href="index.html#video-frame-size-options">Video frame size options</a></li><li><a href="index.html#specifying-multiple-outputs">Specifying multiple outputs</a></li><li><a href="index.html#output-options">Output options</a></li><li><a href="index.html#miscellaneous-options">Miscellaneous options</a></li><li><a href="index.html#setting-event-handlers">Setting event handlers</a></li><li><a href="index.html#starting-ffmpeg-processing">Starting FFmpeg processing</a></li><li><a href="index.html#controlling-the-ffmpeg-process">Controlling the FFmpeg process</a></li><li><a href="index.html#reading-video-metadata">Reading video metadata</a></li><li><a href="index.html#querying-ffmpeg-capabilities">Querying ffmpeg capabilities</a></li><li><a href="index.html#cloning-an-ffmpegcommand">Cloning an FfmpegCommand</a></li></ul><li><a href="index.html#contributing">Contributing</a></li><ul><li><a href="index.html#code-contributions">Code contributions</a></li><li><a href="index.html#documentation-contributions">Documentation contributions</a></li><li><a href="index.html#updating-the-documentation">Updating the documentation</a></li><li><a href="index.html#running-tests">Running tests</a></li></ul><li><a href="index.html#main-contributors">Main contributors</a></li><ul></ul><li><a href="index.html#license">License</a></li><ul></ul></ul><h3>Classes</h3><ul><li><a href="FfmpegCommand.html">FfmpegCommand</a></li><ul><li> <a href="FfmpegCommand.html#audio-methods">Audio methods</a></li><li> <a href="FfmpegCommand.html#capabilities-methods">Capabilities methods</a></li><li> <a href="FfmpegCommand.html#custom-options-methods">Custom options methods</a></li><li> <a href="FfmpegCommand.html#input-methods">Input methods</a></li><li> <a href="FfmpegCommand.html#metadata-methods">Metadata methods</a></li><li> <a href="FfmpegCommand.html#miscellaneous-methods">Miscellaneous methods</a></li><li> <a href="FfmpegCommand.html#other-methods">Other methods</a></li><li> <a href="FfmpegCommand.html#output-methods">Output methods</a></li><li> <a href="FfmpegCommand.html#processing-methods">Processing methods</a></li><li> <a href="FfmpegCommand.html#video-methods">Video methods</a></li><li> <a href="FfmpegCommand.html#video-size-methods">Video size methods</a></li></ul></ul>
80 | </nav>
81 | 
82 | <br clear="both">
83 | 
84 | <footer>
85 |     Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Sun May 01 2016 12:10:37 GMT+0200 (CEST)
86 | </footer>
87 | 
88 | <script> prettyPrint(); </script>
89 | <script src="scripts/linenumber.js"> </script>
90 | </body>
91 | </html>
92 | 


--------------------------------------------------------------------------------
/doc/options_output.js.html:
--------------------------------------------------------------------------------
  1 | <!DOCTYPE html>
  2 | <html lang="en">
  3 | <head>
  4 |     <meta charset="utf-8">
  5 |     <title>JSDoc: Source: options/output.js</title>
  6 | 
  7 |     <script src="scripts/prettify/prettify.js"> </script>
  8 |     <script src="scripts/prettify/lang-css.js"> </script>
  9 |     <!--[if lt IE 9]>
 10 |       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
 11 |     <![endif]-->
 12 |     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
 13 |     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
 14 | </head>
 15 | 
 16 | <body>
 17 | 
 18 | <div id="main">
 19 | 
 20 |     <h1 class="page-title">Source: options/output.js</h1>
 21 | 
 22 |     
 23 | 
 24 | 
 25 |     
 26 |     <section>
 27 |         <article>
 28 |             <pre class="prettyprint source linenums"><code>/*jshint node:true*/
 29 | 'use strict';
 30 | 
 31 | var utils = require('../utils');
 32 | 
 33 | 
 34 | /*
 35 |  *! Output-related methods
 36 |  */
 37 | 
 38 | module.exports = function(proto) {
 39 |   /**
 40 |    * Add output
 41 |    *
 42 |    * @method FfmpegCommand#output
 43 |    * @category Output
 44 |    * @aliases addOutput
 45 |    *
 46 |    * @param {String|Writable} target target file path or writable stream
 47 |    * @param {Object} [pipeopts={}] pipe options (only applies to streams)
 48 |    * @return FfmpegCommand
 49 |    */
 50 |   proto.addOutput =
 51 |   proto.output = function(target, pipeopts) {
 52 |     var isFile = false;
 53 | 
 54 |     if (!target &amp;&amp; this._currentOutput) {
 55 |       // No target is only allowed when called from constructor
 56 |       throw new Error('Invalid output');
 57 |     }
 58 | 
 59 |     if (target &amp;&amp; typeof target !== 'string') {
 60 |       if (!('writable' in target) || !(target.writable)) {
 61 |         throw new Error('Invalid output');
 62 |       }
 63 |     } else if (typeof target === 'string') {
 64 |       var protocol = target.match(/^([a-z]{2,}):/i);
 65 |       isFile = !protocol || protocol[0] === 'file';
 66 |     }
 67 | 
 68 |     if (target &amp;&amp; !('target' in this._currentOutput)) {
 69 |       // For backwards compatibility, set target for first output
 70 |       this._currentOutput.target = target;
 71 |       this._currentOutput.isFile = isFile;
 72 |       this._currentOutput.pipeopts = pipeopts || {};
 73 |     } else {
 74 |       if (target &amp;&amp; typeof target !== 'string') {
 75 |         var hasOutputStream = this._outputs.some(function(output) {
 76 |           return typeof output.target !== 'string';
 77 |         });
 78 | 
 79 |         if (hasOutputStream) {
 80 |           throw new Error('Only one output stream is supported');
 81 |         }
 82 |       }
 83 | 
 84 |       this._outputs.push(this._currentOutput = {
 85 |         target: target,
 86 |         isFile: isFile,
 87 |         flags: {},
 88 |         pipeopts: pipeopts || {}
 89 |       });
 90 | 
 91 |       var self = this;
 92 |       ['audio', 'audioFilters', 'video', 'videoFilters', 'sizeFilters', 'options'].forEach(function(key) {
 93 |         self._currentOutput[key] = utils.args();
 94 |       });
 95 | 
 96 |       if (!target) {
 97 |         // Call from constructor: remove target key
 98 |         delete this._currentOutput.target;
 99 |       }
100 |     }
101 | 
102 |     return this;
103 |   };
104 | 
105 | 
106 |   /**
107 |    * Specify output seek time
108 |    *
109 |    * @method FfmpegCommand#seek
110 |    * @category Input
111 |    * @aliases seekOutput
112 |    *
113 |    * @param {String|Number} seek seek time in seconds or as a '[hh:[mm:]]ss[.xxx]' string
114 |    * @return FfmpegCommand
115 |    */
116 |   proto.seekOutput =
117 |   proto.seek = function(seek) {
118 |     this._currentOutput.options('-ss', seek);
119 |     return this;
120 |   };
121 | 
122 | 
123 |   /**
124 |    * Set output duration
125 |    *
126 |    * @method FfmpegCommand#duration
127 |    * @category Output
128 |    * @aliases withDuration,setDuration
129 |    *
130 |    * @param {String|Number} duration duration in seconds or as a '[[hh:]mm:]ss[.xxx]' string
131 |    * @return FfmpegCommand
132 |    */
133 |   proto.withDuration =
134 |   proto.setDuration =
135 |   proto.duration = function(duration) {
136 |     this._currentOutput.options('-t', duration);
137 |     return this;
138 |   };
139 | 
140 | 
141 |   /**
142 |    * Set output format
143 |    *
144 |    * @method FfmpegCommand#format
145 |    * @category Output
146 |    * @aliases toFormat,withOutputFormat,outputFormat
147 |    *
148 |    * @param {String} format output format name
149 |    * @return FfmpegCommand
150 |    */
151 |   proto.toFormat =
152 |   proto.withOutputFormat =
153 |   proto.outputFormat =
154 |   proto.format = function(format) {
155 |     this._currentOutput.options('-f', format);
156 |     return this;
157 |   };
158 | 
159 | 
160 |   /**
161 |    * Add stream mapping to output
162 |    *
163 |    * @method FfmpegCommand#map
164 |    * @category Output
165 |    *
166 |    * @param {String} spec stream specification string, with optional square brackets
167 |    * @return FfmpegCommand
168 |    */
169 |   proto.map = function(spec) {
170 |     this._currentOutput.options('-map', spec.replace(utils.streamRegexp, '[$1]'));
171 |     return this;
172 |   };
173 | 
174 | 
175 |   /**
176 |    * Run flvtool2/flvmeta on output
177 |    *
178 |    * @method FfmpegCommand#flvmeta
179 |    * @category Output
180 |    * @aliases updateFlvMetadata
181 |    *
182 |    * @return FfmpegCommand
183 |    */
184 |   proto.updateFlvMetadata =
185 |   proto.flvmeta = function() {
186 |     this._currentOutput.flags.flvmeta = true;
187 |     return this;
188 |   };
189 | };
190 | </code></pre>
191 |         </article>
192 |     </section>
193 | 
194 | 
195 | 
196 | 
197 | </div>
198 | 
199 | <nav>
200 |     <h2><a href="index.html">Index</a></h2><ul><li><a href="index.html#installation">Installation</a></li><ul></ul><li><a href="index.html#usage">Usage</a></li><ul><li><a href="index.html#prerequisites">Prerequisites</a></li><li><a href="index.html#creating-an-ffmpeg-command">Creating an FFmpeg command</a></li><li><a href="index.html#specifying-inputs">Specifying inputs</a></li><li><a href="index.html#input-options">Input options</a></li><li><a href="index.html#audio-options">Audio options</a></li><li><a href="index.html#video-options">Video options</a></li><li><a href="index.html#video-frame-size-options">Video frame size options</a></li><li><a href="index.html#specifying-multiple-outputs">Specifying multiple outputs</a></li><li><a href="index.html#output-options">Output options</a></li><li><a href="index.html#miscellaneous-options">Miscellaneous options</a></li><li><a href="index.html#setting-event-handlers">Setting event handlers</a></li><li><a href="index.html#starting-ffmpeg-processing">Starting FFmpeg processing</a></li><li><a href="index.html#controlling-the-ffmpeg-process">Controlling the FFmpeg process</a></li><li><a href="index.html#reading-video-metadata">Reading video metadata</a></li><li><a href="index.html#querying-ffmpeg-capabilities">Querying ffmpeg capabilities</a></li><li><a href="index.html#cloning-an-ffmpegcommand">Cloning an FfmpegCommand</a></li></ul><li><a href="index.html#contributing">Contributing</a></li><ul><li><a href="index.html#code-contributions">Code contributions</a></li><li><a href="index.html#documentation-contributions">Documentation contributions</a></li><li><a href="index.html#updating-the-documentation">Updating the documentation</a></li><li><a href="index.html#running-tests">Running tests</a></li></ul><li><a href="index.html#main-contributors">Main contributors</a></li><ul></ul><li><a href="index.html#license">License</a></li><ul></ul></ul><h3>Classes</h3><ul><li><a href="FfmpegCommand.html">FfmpegCommand</a></li><ul><li> <a href="FfmpegCommand.html#audio-methods">Audio methods</a></li><li> <a href="FfmpegCommand.html#capabilities-methods">Capabilities methods</a></li><li> <a href="FfmpegCommand.html#custom-options-methods">Custom options methods</a></li><li> <a href="FfmpegCommand.html#input-methods">Input methods</a></li><li> <a href="FfmpegCommand.html#metadata-methods">Metadata methods</a></li><li> <a href="FfmpegCommand.html#miscellaneous-methods">Miscellaneous methods</a></li><li> <a href="FfmpegCommand.html#other-methods">Other methods</a></li><li> <a href="FfmpegCommand.html#output-methods">Output methods</a></li><li> <a href="FfmpegCommand.html#processing-methods">Processing methods</a></li><li> <a href="FfmpegCommand.html#video-methods">Video methods</a></li><li> <a href="FfmpegCommand.html#video-size-methods">Video size methods</a></li></ul></ul>
201 | </nav>
202 | 
203 | <br clear="both">
204 | 
205 | <footer>
206 |     Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Sun May 01 2016 12:10:37 GMT+0200 (CEST)
207 | </footer>
208 | 
209 | <script> prettyPrint(); </script>
210 | <script src="scripts/linenumber.js"> </script>
211 | </body>
212 | </html>
213 | 


--------------------------------------------------------------------------------
/doc/options_video.js.html:
--------------------------------------------------------------------------------
  1 | <!DOCTYPE html>
  2 | <html lang="en">
  3 | <head>
  4 |     <meta charset="utf-8">
  5 |     <title>JSDoc: Source: options/video.js</title>
  6 | 
  7 |     <script src="scripts/prettify/prettify.js"> </script>
  8 |     <script src="scripts/prettify/lang-css.js"> </script>
  9 |     <!--[if lt IE 9]>
 10 |       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
 11 |     <![endif]-->
 12 |     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
 13 |     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
 14 | </head>
 15 | 
 16 | <body>
 17 | 
 18 | <div id="main">
 19 | 
 20 |     <h1 class="page-title">Source: options/video.js</h1>
 21 | 
 22 |     
 23 | 
 24 | 
 25 |     
 26 |     <section>
 27 |         <article>
 28 |             <pre class="prettyprint source linenums"><code>/*jshint node:true*/
 29 | 'use strict';
 30 | 
 31 | var utils = require('../utils');
 32 | 
 33 | 
 34 | /*
 35 |  *! Video-related methods
 36 |  */
 37 | 
 38 | module.exports = function(proto) {
 39 |   /**
 40 |    * Disable video in the output
 41 |    *
 42 |    * @method FfmpegCommand#noVideo
 43 |    * @category Video
 44 |    * @aliases withNoVideo
 45 |    *
 46 |    * @return FfmpegCommand
 47 |    */
 48 |   proto.withNoVideo =
 49 |   proto.noVideo = function() {
 50 |     this._currentOutput.video.clear();
 51 |     this._currentOutput.videoFilters.clear();
 52 |     this._currentOutput.video('-vn');
 53 | 
 54 |     return this;
 55 |   };
 56 | 
 57 | 
 58 |   /**
 59 |    * Specify video codec
 60 |    *
 61 |    * @method FfmpegCommand#videoCodec
 62 |    * @category Video
 63 |    * @aliases withVideoCodec
 64 |    *
 65 |    * @param {String} codec video codec name
 66 |    * @return FfmpegCommand
 67 |    */
 68 |   proto.withVideoCodec =
 69 |   proto.videoCodec = function(codec) {
 70 |     this._currentOutput.video('-vcodec', codec);
 71 |     return this;
 72 |   };
 73 | 
 74 | 
 75 |   /**
 76 |    * Specify video bitrate
 77 |    *
 78 |    * @method FfmpegCommand#videoBitrate
 79 |    * @category Video
 80 |    * @aliases withVideoBitrate
 81 |    *
 82 |    * @param {String|Number} bitrate video bitrate in kbps (with an optional 'k' suffix)
 83 |    * @param {Boolean} [constant=false] enforce constant bitrate
 84 |    * @return FfmpegCommand
 85 |    */
 86 |   proto.withVideoBitrate =
 87 |   proto.videoBitrate = function(bitrate, constant) {
 88 |     bitrate = ('' + bitrate).replace(/k?$/, 'k');
 89 | 
 90 |     this._currentOutput.video('-b:v', bitrate);
 91 |     if (constant) {
 92 |       this._currentOutput.video(
 93 |         '-maxrate', bitrate,
 94 |         '-minrate', bitrate,
 95 |         '-bufsize', '3M'
 96 |       );
 97 |     }
 98 | 
 99 |     return this;
100 |   };
101 | 
102 | 
103 |   /**
104 |    * Specify custom video filter(s)
105 |    *
106 |    * Can be called both with one or many filters, or a filter array.
107 |    *
108 |    * @example
109 |    * command.videoFilters('filter1');
110 |    *
111 |    * @example
112 |    * command.videoFilters('filter1', 'filter2=param1=value1:param2=value2');
113 |    *
114 |    * @example
115 |    * command.videoFilters(['filter1', 'filter2']);
116 |    *
117 |    * @example
118 |    * command.videoFilters([
119 |    *   {
120 |    *     filter: 'filter1'
121 |    *   },
122 |    *   {
123 |    *     filter: 'filter2',
124 |    *     options: 'param=value:param=value'
125 |    *   }
126 |    * ]);
127 |    *
128 |    * @example
129 |    * command.videoFilters(
130 |    *   {
131 |    *     filter: 'filter1',
132 |    *     options: ['value1', 'value2']
133 |    *   },
134 |    *   {
135 |    *     filter: 'filter2',
136 |    *     options: { param1: 'value1', param2: 'value2' }
137 |    *   }
138 |    * );
139 |    *
140 |    * @method FfmpegCommand#videoFilters
141 |    * @category Video
142 |    * @aliases withVideoFilter,withVideoFilters,videoFilter
143 |    *
144 |    * @param {...String|String[]|Object[]} filters video filter strings, string array or
145 |    *   filter specification array, each with the following properties:
146 |    * @param {String} filters.filter filter name
147 |    * @param {String|String[]|Object} [filters.options] filter option string, array, or object
148 |    * @return FfmpegCommand
149 |    */
150 |   proto.withVideoFilter =
151 |   proto.withVideoFilters =
152 |   proto.videoFilter =
153 |   proto.videoFilters = function(filters) {
154 |     if (arguments.length > 1) {
155 |       filters = [].slice.call(arguments);
156 |     }
157 | 
158 |     if (!Array.isArray(filters)) {
159 |       filters = [filters];
160 |     }
161 | 
162 |     this._currentOutput.videoFilters(utils.makeFilterStrings(filters));
163 | 
164 |     return this;
165 |   };
166 | 
167 | 
168 |   /**
169 |    * Specify output FPS
170 |    *
171 |    * @method FfmpegCommand#fps
172 |    * @category Video
173 |    * @aliases withOutputFps,withOutputFPS,withFpsOutput,withFPSOutput,withFps,withFPS,outputFPS,outputFps,fpsOutput,FPSOutput,FPS
174 |    *
175 |    * @param {Number} fps output FPS
176 |    * @return FfmpegCommand
177 |    */
178 |   proto.withOutputFps =
179 |   proto.withOutputFPS =
180 |   proto.withFpsOutput =
181 |   proto.withFPSOutput =
182 |   proto.withFps =
183 |   proto.withFPS =
184 |   proto.outputFPS =
185 |   proto.outputFps =
186 |   proto.fpsOutput =
187 |   proto.FPSOutput =
188 |   proto.fps =
189 |   proto.FPS = function(fps) {
190 |     this._currentOutput.video('-r', fps);
191 |     return this;
192 |   };
193 | 
194 | 
195 |   /**
196 |    * Only transcode a certain number of frames
197 |    *
198 |    * @method FfmpegCommand#frames
199 |    * @category Video
200 |    * @aliases takeFrames,withFrames
201 |    *
202 |    * @param {Number} frames frame count
203 |    * @return FfmpegCommand
204 |    */
205 |   proto.takeFrames =
206 |   proto.withFrames =
207 |   proto.frames = function(frames) {
208 |     this._currentOutput.video('-vframes', frames);
209 |     return this;
210 |   };
211 | };
212 | </code></pre>
213 |         </article>
214 |     </section>
215 | 
216 | 
217 | 
218 | 
219 | </div>
220 | 
221 | <nav>
222 |     <h2><a href="index.html">Index</a></h2><ul><li><a href="index.html#installation">Installation</a></li><ul></ul><li><a href="index.html#usage">Usage</a></li><ul><li><a href="index.html#prerequisites">Prerequisites</a></li><li><a href="index.html#creating-an-ffmpeg-command">Creating an FFmpeg command</a></li><li><a href="index.html#specifying-inputs">Specifying inputs</a></li><li><a href="index.html#input-options">Input options</a></li><li><a href="index.html#audio-options">Audio options</a></li><li><a href="index.html#video-options">Video options</a></li><li><a href="index.html#video-frame-size-options">Video frame size options</a></li><li><a href="index.html#specifying-multiple-outputs">Specifying multiple outputs</a></li><li><a href="index.html#output-options">Output options</a></li><li><a href="index.html#miscellaneous-options">Miscellaneous options</a></li><li><a href="index.html#setting-event-handlers">Setting event handlers</a></li><li><a href="index.html#starting-ffmpeg-processing">Starting FFmpeg processing</a></li><li><a href="index.html#controlling-the-ffmpeg-process">Controlling the FFmpeg process</a></li><li><a href="index.html#reading-video-metadata">Reading video metadata</a></li><li><a href="index.html#querying-ffmpeg-capabilities">Querying ffmpeg capabilities</a></li><li><a href="index.html#cloning-an-ffmpegcommand">Cloning an FfmpegCommand</a></li></ul><li><a href="index.html#contributing">Contributing</a></li><ul><li><a href="index.html#code-contributions">Code contributions</a></li><li><a href="index.html#documentation-contributions">Documentation contributions</a></li><li><a href="index.html#updating-the-documentation">Updating the documentation</a></li><li><a href="index.html#running-tests">Running tests</a></li></ul><li><a href="index.html#main-contributors">Main contributors</a></li><ul></ul><li><a href="index.html#license">License</a></li><ul></ul></ul><h3>Classes</h3><ul><li><a href="FfmpegCommand.html">FfmpegCommand</a></li><ul><li> <a href="FfmpegCommand.html#audio-methods">Audio methods</a></li><li> <a href="FfmpegCommand.html#capabilities-methods">Capabilities methods</a></li><li> <a href="FfmpegCommand.html#custom-options-methods">Custom options methods</a></li><li> <a href="FfmpegCommand.html#input-methods">Input methods</a></li><li> <a href="FfmpegCommand.html#metadata-methods">Metadata methods</a></li><li> <a href="FfmpegCommand.html#miscellaneous-methods">Miscellaneous methods</a></li><li> <a href="FfmpegCommand.html#other-methods">Other methods</a></li><li> <a href="FfmpegCommand.html#output-methods">Output methods</a></li><li> <a href="FfmpegCommand.html#processing-methods">Processing methods</a></li><li> <a href="FfmpegCommand.html#video-methods">Video methods</a></li><li> <a href="FfmpegCommand.html#video-size-methods">Video size methods</a></li></ul></ul>
223 | </nav>
224 | 
225 | <br clear="both">
226 | 
227 | <footer>
228 |     Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.4.0</a> on Sun May 01 2016 12:10:37 GMT+0200 (CEST)
229 | </footer>
230 | 
231 | <script> prettyPrint(); </script>
232 | <script src="scripts/linenumber.js"> </script>
233 | </body>
234 | </html>
235 | 


--------------------------------------------------------------------------------
/doc/output.js.html:
--------------------------------------------------------------------------------
  1 | <!DOCTYPE html>
  2 | <html lang="en">
  3 | <head>
  4 |     <meta charset="utf-8">
  5 |     <title>JSDoc: Source: options/output.js</title>
  6 | 
  7 |     <script src="scripts/prettify/prettify.js"> </script>
  8 |     <script src="scripts/prettify/lang-css.js"> </script>
  9 |     <!--[if lt IE 9]>
 10 |       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
 11 |     <![endif]-->
 12 |     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
 13 |     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
 14 | </head>
 15 | 
 16 | <body>
 17 | 
 18 | <div id="main">
 19 | 
 20 |     <h1 class="page-title">Source: options/output.js</h1>
 21 | 
 22 |     
 23 | 
 24 | 
 25 |     
 26 |     <section>
 27 |         <article>
 28 |             <pre class="prettyprint source linenums"><code>/*jshint node:true*/
 29 | 'use strict';
 30 | 
 31 | var utils = require('../utils');
 32 | 
 33 | 
 34 | /*
 35 |  *! Output-related methods
 36 |  */
 37 | 
 38 | module.exports = function(proto) {
 39 |   /**
 40 |    * Add output
 41 |    *
 42 |    * @method FfmpegCommand#output
 43 |    * @category Output
 44 |    * @aliases addOutput
 45 |    *
 46 |    * @param {String|Writable} target target file path or writable stream
 47 |    * @param {Object} [pipeopts={}] pipe options (only applies to streams)
 48 |    * @return FfmpegCommand
 49 |    */
 50 |   proto.addOutput =
 51 |   proto.output = function(target, pipeopts) {
 52 |     var isFile = false;
 53 | 
 54 |     if (!target &amp;&amp; this._currentOutput) {
 55 |       // No target is only allowed when called from constructor
 56 |       throw new Error('Invalid output');
 57 |     }
 58 | 
 59 |     if (target &amp;&amp; typeof target !== 'string') {
 60 |       if (!('writable' in target) || !(target.writable)) {
 61 |         throw new Error('Invalid output');
 62 |       }
 63 |     } else if (typeof target === 'string') {
 64 |       var protocol = target.match(/^([a-z]{2,}):/i);
 65 |       isFile = !protocol || protocol[0] === 'file';
 66 |     }
 67 | 
 68 |     if (target &amp;&amp; !('target' in this._currentOutput)) {
 69 |       // For backwards compatibility, set target for first output
 70 |       this._currentOutput.target = target;
 71 |       this._currentOutput.isFile = isFile;
 72 |       this._currentOutput.pipeopts = pipeopts || {};
 73 |     } else {
 74 |       if (target &amp;&amp; typeof target !== 'string') {
 75 |         var hasOutputStream = this._outputs.some(function(output) {
 76 |           return typeof output.target !== 'string';
 77 |         });
 78 | 
 79 |         if (hasOutputStream) {
 80 |           throw new Error('Only one output stream is supported');
 81 |         }
 82 |       }
 83 | 
 84 |       this._outputs.push(this._currentOutput = {
 85 |         target: target,
 86 |         isFile: isFile,
 87 |         flags: {},
 88 |         pipeopts: pipeopts || {}
 89 |       });
 90 | 
 91 |       var self = this;
 92 |       ['audio', 'audioFilters', 'video', 'videoFilters', 'sizeFilters', 'options'].forEach(function(key) {
 93 |         self._currentOutput[key] = utils.args();
 94 |       });
 95 | 
 96 |       if (!target) {
 97 |         // Call from constructor: remove target key
 98 |         delete this._currentOutput.target;
 99 |       }
100 |     }
101 | 
102 |     return this;
103 |   };
104 | 
105 | 
106 |   /**
107 |    * Specify output seek time
108 |    *
109 |    * @method FfmpegCommand#seek
110 |    * @category Input
111 |    * @aliases seekOutput
112 |    *
113 |    * @param {String|Number} seek seek time in seconds or as a '[hh:[mm:]]ss[.xxx]' string
114 |    * @return FfmpegCommand
115 |    */
116 |   proto.seekOutput =
117 |   proto.seek = function(seek) {
118 |     this._currentOutput.options('-ss', seek);
119 |     return this;
120 |   };
121 | 
122 | 
123 |   /**
124 |    * Set output duration
125 |    *
126 |    * @method FfmpegCommand#duration
127 |    * @category Output
128 |    * @aliases withDuration,setDuration
129 |    *
130 |    * @param {String|Number} duration duration in seconds or as a '[[hh:]mm:]ss[.xxx]' string
131 |    * @return FfmpegCommand
132 |    */
133 |   proto.withDuration =
134 |   proto.setDuration =
135 |   proto.duration = function(duration) {
136 |     this._currentOutput.options('-t', duration);
137 |     return this;
138 |   };
139 | 
140 | 
141 |   /**
142 |    * Set output format
143 |    *
144 |    * @method FfmpegCommand#format
145 |    * @category Output
146 |    * @aliases toFormat,withOutputFormat,outputFormat
147 |    *
148 |    * @param {String} format output format name
149 |    * @return FfmpegCommand
150 |    */
151 |   proto.toFormat =
152 |   proto.withOutputFormat =
153 |   proto.outputFormat =
154 |   proto.format = function(format) {
155 |     this._currentOutput.options('-f', format);
156 |     return this;
157 |   };
158 | 
159 | 
160 |   /**
161 |    * Add stream mapping to output
162 |    *
163 |    * @method FfmpegCommand#map
164 |    * @category Output
165 |    *
166 |    * @param {String} spec stream specification string, with optional square brackets
167 |    * @return FfmpegCommand
168 |    */
169 |   proto.map = function(spec) {
170 |     this._currentOutput.options('-map', spec.replace(utils.streamRegexp, '[$1]'));
171 |     return this;
172 |   };
173 | 
174 | 
175 |   /**
176 |    * Run flvtool2/flvmeta on output
177 |    *
178 |    * @method FfmpegCommand#flvmeta
179 |    * @category Output
180 |    * @aliases updateFlvMetadata
181 |    *
182 |    * @return FfmpegCommand
183 |    */
184 |   proto.updateFlvMetadata =
185 |   proto.flvmeta = function() {
186 |     this._currentOutput.flags.flvmeta = true;
187 |     return this;
188 |   };
189 | };
190 | </code></pre>
191 |         </article>
192 |     </section>
193 | 
194 | 
195 | 
196 | 
197 | </div>
198 | 
199 | <nav>
200 |     <h2><a href="index.html">Index</a></h2><ul><li><a href="index.html#installation">Installation</a></li><ul></ul><li><a href="index.html#usage">Usage</a></li><ul><li><a href="index.html#prerequisites">Prerequisites</a></li><li><a href="index.html#creating-an-ffmpeg-command">Creating an FFmpeg command</a></li><li><a href="index.html#specifying-inputs">Specifying inputs</a></li><li><a href="index.html#input-options">Input options</a></li><li><a href="index.html#audio-options">Audio options</a></li><li><a href="index.html#video-options">Video options</a></li><li><a href="index.html#video-frame-size-options">Video frame size options</a></li><li><a href="index.html#specifying-multiple-outputs">Specifying multiple outputs</a></li><li><a href="index.html#output-options">Output options</a></li><li><a href="index.html#miscellaneous-options">Miscellaneous options</a></li><li><a href="index.html#setting-event-handlers">Setting event handlers</a></li><li><a href="index.html#starting-ffmpeg-processing">Starting FFmpeg processing</a></li><li><a href="index.html#controlling-the-ffmpeg-process">Controlling the FFmpeg process</a></li><li><a href="index.html#reading-video-metadata">Reading video metadata</a></li><li><a href="index.html#querying-ffmpeg-capabilities">Querying ffmpeg capabilities</a></li><li><a href="index.html#cloning-an-ffmpegcommand">Cloning an FfmpegCommand</a></li></ul><li><a href="index.html#contributing">Contributing</a></li><ul><li><a href="index.html#code-contributions">Code contributions</a></li><li><a href="index.html#documentation-contributions">Documentation contributions</a></li><li><a href="index.html#updating-the-documentation">Updating the documentation</a></li><li><a href="index.html#running-tests">Running tests</a></li></ul><li><a href="index.html#main-contributors">Main contributors</a></li><ul></ul><li><a href="index.html#license">License</a></li><ul></ul></ul><h3>Classes</h3><ul><li><a href="FfmpegCommand.html">FfmpegCommand</a></li><ul><li> <a href="FfmpegCommand.html#audio-methods">Audio methods</a></li><li> <a href="FfmpegCommand.html#capabilities-methods">Capabilities methods</a></li><li> <a href="FfmpegCommand.html#custom-options-methods">Custom options methods</a></li><li> <a href="FfmpegCommand.html#input-methods">Input methods</a></li><li> <a href="FfmpegCommand.html#metadata-methods">Metadata methods</a></li><li> <a href="FfmpegCommand.html#miscellaneous-methods">Miscellaneous methods</a></li><li> <a href="FfmpegCommand.html#other-methods">Other methods</a></li><li> <a href="FfmpegCommand.html#output-methods">Output methods</a></li><li> <a href="FfmpegCommand.html#processing-methods">Processing methods</a></li><li> <a href="FfmpegCommand.html#video-methods">Video methods</a></li><li> <a href="FfmpegCommand.html#video-size-methods">Video size methods</a></li></ul></ul>
201 | </nav>
202 | 
203 | <br clear="both">
204 | 
205 | <footer>
206 |     Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.0-alpha5</a> on Tue Jul 08 2014 21:22:19 GMT+0200 (CEST)
207 | </footer>
208 | 
209 | <script> prettyPrint(); </script>
210 | <script src="scripts/linenumber.js"> </script>
211 | </body>
212 | </html>
213 | 


--------------------------------------------------------------------------------
/doc/scripts/linenumber.js:
--------------------------------------------------------------------------------
 1 | /*global document */
 2 | (function() {
 3 |     var source = document.getElementsByClassName('prettyprint source linenums');
 4 |     var i = 0;
 5 |     var lineNumber = 0;
 6 |     var lineId;
 7 |     var lines;
 8 |     var totalLines;
 9 |     var anchorHash;
10 | 
11 |     if (source && source[0]) {
12 |         anchorHash = document.location.hash.substring(1);
13 |         lines = source[0].getElementsByTagName('li');
14 |         totalLines = lines.length;
15 | 
16 |         for (; i < totalLines; i++) {
17 |             lineNumber++;
18 |             lineId = 'line' + lineNumber;
19 |             lines[i].id = lineId;
20 |             if (lineId === anchorHash) {
21 |                 lines[i].className += ' selected';
22 |             }
23 |         }
24 |     }
25 | })();
26 | 


--------------------------------------------------------------------------------
/doc/scripts/prettify/lang-css.js:
--------------------------------------------------------------------------------
1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);
3 | 


--------------------------------------------------------------------------------
/doc/styles/jsdoc-default.css:
--------------------------------------------------------------------------------
  1 | html
  2 | {
  3 |     overflow: auto;
  4 |     background-color: #fff;
  5 | }
  6 | 
  7 | body
  8 | {
  9 |     font: 14px "DejaVu Sans Condensed", "Liberation Sans", "Nimbus Sans L", Tahoma, Geneva, "Helvetica Neue", Helvetica, Arial, sans-serif;
 10 |     line-height: 130%;
 11 |     color: #000;
 12 |     background-color: #fff;
 13 | }
 14 | 
 15 | a {
 16 |     color: #444;
 17 | }
 18 | 
 19 | a:visited {
 20 |     color: #444;
 21 | }
 22 | 
 23 | a:active {
 24 |     color: #444;
 25 | }
 26 | 
 27 | header
 28 | {
 29 |     display: block;
 30 |     padding: 6px 4px;
 31 | }
 32 | 
 33 | .class-description {
 34 |     font-style: italic;
 35 |     font-family: Palatino, 'Palatino Linotype', serif;
 36 |     font-size: 130%;
 37 |     line-height: 140%;
 38 |     margin-bottom: 1em;
 39 |     margin-top: 1em;
 40 | }
 41 | 
 42 | #main {
 43 |     float: left;
 44 |     width: 100%;
 45 | }
 46 | 
 47 | section
 48 | {
 49 |     display: block;
 50 | 
 51 |     background-color: #fff;
 52 |     padding: 12px 24px;
 53 |     border-bottom: 1px solid #ccc;
 54 |     margin-right: 240px;
 55 | }
 56 | 
 57 | .variation {
 58 |     display: none;
 59 | }
 60 | 
 61 | .optional:after {
 62 |     content: "opt";
 63 |     font-size: 60%;
 64 |     color: #aaa;
 65 |     font-style: italic;
 66 |     font-weight: lighter;
 67 | }
 68 | 
 69 | nav
 70 | {
 71 |     display: block;
 72 |     width: 220px;
 73 |     border-left: 1px solid #ccc;
 74 |     padding-left: 9px;
 75 | 
 76 |     position: fixed;
 77 |     top: 28px;
 78 |     right: 0;
 79 | }
 80 | 
 81 | nav ul {
 82 |     font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif;
 83 |     font-size: 100%;
 84 |     line-height: 17px;
 85 |     padding:0;
 86 |     margin:0;
 87 |     list-style-type:none;
 88 | }
 89 | 
 90 | nav ul ul {
 91 |     margin-left: 10px;
 92 |     font-size: 90%;
 93 | }
 94 | 
 95 | nav h2 a, nav h2 a:visited {
 96 |     color: #526492;
 97 |     text-decoration: none;
 98 | }
 99 | 
100 | nav h3 {
101 |     margin-top: 12px;
102 | }
103 | 
104 | nav li {
105 |     margin-top: 2px;
106 | }
107 | 
108 | nav a {
109 |     color: #5C5954;
110 | }
111 | 
112 | nav a:visited {
113 |     color: #5C5954;
114 | }
115 | 
116 | nav a:active {
117 |     color: #5C5954;
118 | }
119 | 
120 | footer {
121 |     display: block;
122 |     padding: 6px;
123 |     margin-top: 12px;
124 |     font-style: italic;
125 |     font-size: 90%;
126 | }
127 | 
128 | h1
129 | {
130 |     font-size: 200%;
131 |     font-weight: bold;
132 |     letter-spacing: -0.01em;
133 |     margin: 6px 0 9px 0;
134 | }
135 | 
136 | h2
137 | {
138 |     font-size: 170%;
139 |     font-weight: bold;
140 |     letter-spacing: -0.01em;
141 |     margin: 50px 0 3px 0;
142 | }
143 | 
144 | nav > h2 {
145 |     margin-top: 6px;
146 | }
147 | 
148 | h3
149 | {
150 |     font-size: 150%;
151 |     font-weight: bold;
152 |     letter-spacing: -0.01em;
153 |     margin-top: 16px;
154 |     margin: 50px 0 3px 0;
155 | }
156 | 
157 | h4
158 | {
159 |     font-size: 130%;
160 |     font-weight: bold;
161 |     letter-spacing: -0.01em;
162 |     margin-top: 16px;
163 |     margin: 18px 0 3px 0;
164 |     color: #526492;
165 | }
166 | 
167 | h5, .container-overview .subsection-title
168 | {
169 |     font-size: 120%;
170 |     font-weight: bold;
171 |     letter-spacing: -0.01em;
172 |     margin: 8px 0 3px -16px;
173 | }
174 | 
175 | h6
176 | {
177 |     font-size: 100%;
178 |     letter-spacing: -0.01em;
179 |     margin: 6px 0 3px 0;
180 |     font-style: italic;
181 | }
182 | 
183 | article > dl, article > pre {
184 |     margin-left: 2em;
185 | }
186 | 
187 | .ancestors { color: #999; }
188 | .ancestors a
189 | {
190 |     color: #999 !important;
191 |     text-decoration: none;
192 | }
193 | 
194 | .important
195 | {
196 |     font-weight: bold;
197 |     color: #950B02;
198 | }
199 | 
200 | .yes-def {
201 |     text-indent: -1000px;
202 | }
203 | 
204 | .type-signature {
205 |     color: #aaa;
206 | }
207 | 
208 | .name, .signature {
209 |     font-family: Consolas, "Lucida Console", Monaco, monospace;
210 | }
211 | 
212 | .details { margin-top: 14px; border-left: 2px solid #DDD; }
213 | .details dt { width:100px; float:left; padding-left: 10px;  padding-top: 6px; }
214 | .details dd { margin-left: 50px; }
215 | .details ul { margin: 0; }
216 | .details ul { list-style-type: none; }
217 | .details li { margin-left: 30px; padding-top: 6px; }
218 | .details pre.prettyprint { margin: 0 }
219 | .details .object-value { padding-top: 0; }
220 | 
221 | .description {
222 |     margin-bottom: 1em;
223 |     margin-left: -16px;
224 |     margin-top: 1em;
225 | }
226 | 
227 | .code-caption
228 | {
229 |     font-style: italic;
230 |     font-family: Palatino, 'Palatino Linotype', serif;
231 |     font-size: 107%;
232 |     margin: 0;
233 | }
234 | 
235 | .prettyprint
236 | {
237 |     border: 1px solid #ddd;
238 |     width: 80%;
239 |     overflow: auto;
240 | }
241 | 
242 | .prettyprint.source {
243 |     width: inherit;
244 | }
245 | 
246 | .prettyprint code
247 | {
248 |     font-family: Consolas, 'Lucida Console', Monaco, monospace;
249 |     font-size: 100%;
250 |     line-height: 18px;
251 |     display: block;
252 |     padding: 4px 12px;
253 |     margin: 0;
254 |     background-color: #fff;
255 |     color: #000;
256 | }
257 | 
258 | .prettyprint code span.line
259 | {
260 |   display: inline-block;
261 | }
262 | 
263 | .prettyprint.linenums
264 | {
265 |   padding-left: 70px;
266 |   -webkit-user-select: none;
267 |   -moz-user-select: none;
268 |   -ms-user-select: none;
269 |   user-select: none;
270 | }
271 | 
272 | .prettyprint.linenums ol
273 | {
274 |   padding-left: 0;
275 | }
276 | 
277 | .prettyprint.linenums li
278 | {
279 |   border-left: 3px #ddd solid;
280 | }
281 | 
282 | .prettyprint.linenums li.selected,
283 | .prettyprint.linenums li.selected *
284 | {
285 |   background-color: lightyellow;
286 | }
287 | 
288 | .prettyprint.linenums li *
289 | {
290 |   -webkit-user-select: text;
291 |   -moz-user-select: text;
292 |   -ms-user-select: text;
293 |   user-select: text;
294 | }
295 | 
296 | .params, .props
297 | {
298 |     border-spacing: 0;
299 |     border: 0;
300 |     border-collapse: collapse;
301 | }
302 | 
303 | .params .name, .props .name, .name code {
304 |     color: #526492;
305 |     font-family: Consolas, 'Lucida Console', Monaco, monospace;
306 |     font-size: 100%;
307 | }
308 | 
309 | .params td, .params th, .props td, .props th
310 | {
311 |     border: 1px solid #ddd;
312 |     margin: 0px;
313 |     text-align: left;
314 |     vertical-align: top;
315 |     padding: 4px 6px;
316 |     display: table-cell;
317 | }
318 | 
319 | .params thead tr, .props thead tr
320 | {
321 |     background-color: #ddd;
322 |     font-weight: bold;
323 | }
324 | 
325 | .params .params thead tr, .props .props thead tr
326 | {
327 |     background-color: #fff;
328 |     font-weight: bold;
329 | }
330 | 
331 | .params th, .props th { border-right: 1px solid #aaa; }
332 | .params thead .last, .props thead .last { border-right: 1px solid #ddd; }
333 | 
334 | .params td.description > p:first-child
335 | {
336 |     margin-top: 0;
337 |     padding-top: 0;
338 | }
339 | 
340 | .params td.description > p:last-child
341 | {
342 |     margin-bottom: 0;
343 |     padding-bottom: 0;
344 | }
345 | 
346 | .disabled {
347 |     color: #454545;
348 | }
349 | 


--------------------------------------------------------------------------------
/doc/styles/prettify-jsdoc.css:
--------------------------------------------------------------------------------
  1 | /* JSDoc prettify.js theme */
  2 | 
  3 | /* plain text */
  4 | .pln {
  5 |   color: #000000;
  6 |   font-weight: normal;
  7 |   font-style: normal;
  8 | }
  9 | 
 10 | /* string content */
 11 | .str {
 12 |   color: #006400;
 13 |   font-weight: normal;
 14 |   font-style: normal;
 15 | }
 16 | 
 17 | /* a keyword */
 18 | .kwd {
 19 |   color: #000000;
 20 |   font-weight: bold;
 21 |   font-style: normal;
 22 | }
 23 | 
 24 | /* a comment */
 25 | .com {
 26 |   font-weight: normal;
 27 |   font-style: italic;
 28 | }
 29 | 
 30 | /* a type name */
 31 | .typ {
 32 |   color: #000000;
 33 |   font-weight: normal;
 34 |   font-style: normal;
 35 | }
 36 | 
 37 | /* a literal value */
 38 | .lit {
 39 |   color: #006400;
 40 |   font-weight: normal;
 41 |   font-style: normal;
 42 | }
 43 | 
 44 | /* punctuation */
 45 | .pun {
 46 |   color: #000000;
 47 |   font-weight: bold;
 48 |   font-style: normal;
 49 | }
 50 | 
 51 | /* lisp open bracket */
 52 | .opn {
 53 |   color: #000000;
 54 |   font-weight: bold;
 55 |   font-style: normal;
 56 | }
 57 | 
 58 | /* lisp close bracket */
 59 | .clo {
 60 |   color: #000000;
 61 |   font-weight: bold;
 62 |   font-style: normal;
 63 | }
 64 | 
 65 | /* a markup tag name */
 66 | .tag {
 67 |   color: #006400;
 68 |   font-weight: normal;
 69 |   font-style: normal;
 70 | }
 71 | 
 72 | /* a markup attribute name */
 73 | .atn {
 74 |   color: #006400;
 75 |   font-weight: normal;
 76 |   font-style: normal;
 77 | }
 78 | 
 79 | /* a markup attribute value */
 80 | .atv {
 81 |   color: #006400;
 82 |   font-weight: normal;
 83 |   font-style: normal;
 84 | }
 85 | 
 86 | /* a declaration */
 87 | .dec {
 88 |   color: #000000;
 89 |   font-weight: bold;
 90 |   font-style: normal;
 91 | }
 92 | 
 93 | /* a variable name */
 94 | .var {
 95 |   color: #000000;
 96 |   font-weight: normal;
 97 |   font-style: normal;
 98 | }
 99 | 
100 | /* a function name */
101 | .fun {
102 |   color: #000000;
103 |   font-weight: bold;
104 |   font-style: normal;
105 | }
106 | 
107 | /* Specify class=linenums on a pre to get line numbering */
108 | ol.linenums {
109 |   margin-top: 0;
110 |   margin-bottom: 0;
111 | }
112 | 


--------------------------------------------------------------------------------
/doc/styles/prettify-tomorrow.css:
--------------------------------------------------------------------------------
  1 | /* Tomorrow Theme */
  2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */
  3 | /* Pretty printing styles. Used with prettify.js. */
  4 | /* SPAN elements with the classes below are added by prettyprint. */
  5 | /* plain text */
  6 | .pln {
  7 |   color: #4d4d4c; }
  8 | 
  9 | @media screen {
 10 |   /* string content */
 11 |   .str {
 12 |     color: #718c00; }
 13 | 
 14 |   /* a keyword */
 15 |   .kwd {
 16 |     color: #8959a8; }
 17 | 
 18 |   /* a comment */
 19 |   .com {
 20 |     color: #8e908c; }
 21 | 
 22 |   /* a type name */
 23 |   .typ {
 24 |     color: #4271ae; }
 25 | 
 26 |   /* a literal value */
 27 |   .lit {
 28 |     color: #f5871f; }
 29 | 
 30 |   /* punctuation */
 31 |   .pun {
 32 |     color: #4d4d4c; }
 33 | 
 34 |   /* lisp open bracket */
 35 |   .opn {
 36 |     color: #4d4d4c; }
 37 | 
 38 |   /* lisp close bracket */
 39 |   .clo {
 40 |     color: #4d4d4c; }
 41 | 
 42 |   /* a markup tag name */
 43 |   .tag {
 44 |     color: #c82829; }
 45 | 
 46 |   /* a markup attribute name */
 47 |   .atn {
 48 |     color: #f5871f; }
 49 | 
 50 |   /* a markup attribute value */
 51 |   .atv {
 52 |     color: #3e999f; }
 53 | 
 54 |   /* a declaration */
 55 |   .dec {
 56 |     color: #f5871f; }
 57 | 
 58 |   /* a variable name */
 59 |   .var {
 60 |     color: #c82829; }
 61 | 
 62 |   /* a function name */
 63 |   .fun {
 64 |     color: #4271ae; } }
 65 | /* Use higher contrast and text-weight for printable form. */
 66 | @media print, projection {
 67 |   .str {
 68 |     color: #060; }
 69 | 
 70 |   .kwd {
 71 |     color: #006;
 72 |     font-weight: bold; }
 73 | 
 74 |   .com {
 75 |     color: #600;
 76 |     font-style: italic; }
 77 | 
 78 |   .typ {
 79 |     color: #404;
 80 |     font-weight: bold; }
 81 | 
 82 |   .lit {
 83 |     color: #044; }
 84 | 
 85 |   .pun, .opn, .clo {
 86 |     color: #440; }
 87 | 
 88 |   .tag {
 89 |     color: #006;
 90 |     font-weight: bold; }
 91 | 
 92 |   .atn {
 93 |     color: #404; }
 94 | 
 95 |   .atv {
 96 |     color: #060; } }
 97 | /* Style */
 98 | /*
 99 | pre.prettyprint {
100 |   background: white;
101 |   font-family: Menlo, Monaco, Consolas, monospace;
102 |   font-size: 12px;
103 |   line-height: 1.5;
104 |   border: 1px solid #ccc;
105 |   padding: 10px; }
106 | */
107 | 
108 | /* Specify class=linenums on a pre to get line numbering */
109 | ol.linenums {
110 |   margin-top: 0;
111 |   margin-bottom: 0; }
112 | 
113 | /* IE indents via margin-left */
114 | li.L0,
115 | li.L1,
116 | li.L2,
117 | li.L3,
118 | li.L4,
119 | li.L5,
120 | li.L6,
121 | li.L7,
122 | li.L8,
123 | li.L9 {
124 |   /* */ }
125 | 
126 | /* Alternate shading for lines */
127 | li.L1,
128 | li.L3,
129 | li.L5,
130 | li.L7,
131 | li.L9 {
132 |   /* */ }
133 | 


--------------------------------------------------------------------------------
/doc/video.js.html:
--------------------------------------------------------------------------------
  1 | <!DOCTYPE html>
  2 | <html lang="en">
  3 | <head>
  4 |     <meta charset="utf-8">
  5 |     <title>JSDoc: Source: options/video.js</title>
  6 | 
  7 |     <script src="scripts/prettify/prettify.js"> </script>
  8 |     <script src="scripts/prettify/lang-css.js"> </script>
  9 |     <!--[if lt IE 9]>
 10 |       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
 11 |     <![endif]-->
 12 |     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
 13 |     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
 14 | </head>
 15 | 
 16 | <body>
 17 | 
 18 | <div id="main">
 19 | 
 20 |     <h1 class="page-title">Source: options/video.js</h1>
 21 | 
 22 |     
 23 | 
 24 | 
 25 |     
 26 |     <section>
 27 |         <article>
 28 |             <pre class="prettyprint source linenums"><code>/*jshint node:true*/
 29 | 'use strict';
 30 | 
 31 | var utils = require('../utils');
 32 | 
 33 | 
 34 | /*
 35 |  *! Video-related methods
 36 |  */
 37 | 
 38 | module.exports = function(proto) {
 39 |   /**
 40 |    * Disable video in the output
 41 |    *
 42 |    * @method FfmpegCommand#noVideo
 43 |    * @category Video
 44 |    * @aliases withNoVideo
 45 |    *
 46 |    * @return FfmpegCommand
 47 |    */
 48 |   proto.withNoVideo =
 49 |   proto.noVideo = function() {
 50 |     this._currentOutput.video.clear();
 51 |     this._currentOutput.videoFilters.clear();
 52 |     this._currentOutput.video('-vn');
 53 | 
 54 |     return this;
 55 |   };
 56 | 
 57 | 
 58 |   /**
 59 |    * Specify video codec
 60 |    *
 61 |    * @method FfmpegCommand#videoCodec
 62 |    * @category Video
 63 |    * @aliases withVideoCodec
 64 |    *
 65 |    * @param {String} codec video codec name
 66 |    * @return FfmpegCommand
 67 |    */
 68 |   proto.withVideoCodec =
 69 |   proto.videoCodec = function(codec) {
 70 |     this._currentOutput.video('-vcodec', codec);
 71 |     return this;
 72 |   };
 73 | 
 74 | 
 75 |   /**
 76 |    * Specify video bitrate
 77 |    *
 78 |    * @method FfmpegCommand#videoBitrate
 79 |    * @category Video
 80 |    * @aliases withVideoBitrate
 81 |    *
 82 |    * @param {String|Number} bitrate video bitrate in kbps (with an optional 'k' suffix)
 83 |    * @param {Boolean} [constant=false] enforce constant bitrate
 84 |    * @return FfmpegCommand
 85 |    */
 86 |   proto.withVideoBitrate =
 87 |   proto.videoBitrate = function(bitrate, constant) {
 88 |     bitrate = ('' + bitrate).replace(/k?$/, 'k');
 89 | 
 90 |     this._currentOutput.video('-b:v', bitrate);
 91 |     if (constant) {
 92 |       this._currentOutput.video(
 93 |         '-maxrate', bitrate,
 94 |         '-minrate', bitrate,
 95 |         '-bufsize', '3M'
 96 |       );
 97 |     }
 98 | 
 99 |     return this;
100 |   };
101 | 
102 | 
103 |   /**
104 |    * Specify custom video filter(s)
105 |    *
106 |    * Can be called both with one or many filters, or a filter array.
107 |    *
108 |    * @example
109 |    * command.videoFilters('filter1');
110 |    *
111 |    * @example
112 |    * command.videoFilters('filter1', 'filter2=param1=value1:param2=value2');
113 |    *
114 |    * @example
115 |    * command.videoFilters(['filter1', 'filter2']);
116 |    *
117 |    * @example
118 |    * command.videoFilters([
119 |    *   {
120 |    *     filter: 'filter1'
121 |    *   },
122 |    *   {
123 |    *     filter: 'filter2',
124 |    *     options: 'param=value:param=value'
125 |    *   }
126 |    * ]);
127 |    *
128 |    * @example
129 |    * command.videoFilters(
130 |    *   {
131 |    *     filter: 'filter1',
132 |    *     options: ['value1', 'value2']
133 |    *   },
134 |    *   {
135 |    *     filter: 'filter2',
136 |    *     options: { param1: 'value1', param2: 'value2' }
137 |    *   }
138 |    * );
139 |    *
140 |    * @method FfmpegCommand#videoFilters
141 |    * @category Video
142 |    * @aliases withVideoFilter,withVideoFilters,videoFilter
143 |    *
144 |    * @param {...String|String[]|Object[]} filters video filter strings, string array or
145 |    *   filter specification array, each with the following properties:
146 |    * @param {String} filters.filter filter name
147 |    * @param {String|String[]|Object} [filters.options] filter option string, array, or object
148 |    * @return FfmpegCommand
149 |    */
150 |   proto.withVideoFilter =
151 |   proto.withVideoFilters =
152 |   proto.videoFilter =
153 |   proto.videoFilters = function(filters) {
154 |     if (arguments.length > 1) {
155 |       filters = [].slice.call(arguments);
156 |     }
157 | 
158 |     if (!Array.isArray(filters)) {
159 |       filters = [filters];
160 |     }
161 | 
162 |     this._currentOutput.videoFilters(utils.makeFilterStrings(filters));
163 | 
164 |     return this;
165 |   };
166 | 
167 | 
168 |   /**
169 |    * Specify output FPS
170 |    *
171 |    * @method FfmpegCommand#fps
172 |    * @category Video
173 |    * @aliases withOutputFps,withOutputFPS,withFpsOutput,withFPSOutput,withFps,withFPS,outputFPS,outputFps,fpsOutput,FPSOutput,FPS
174 |    *
175 |    * @param {Number} fps output FPS
176 |    * @return FfmpegCommand
177 |    */
178 |   proto.withOutputFps =
179 |   proto.withOutputFPS =
180 |   proto.withFpsOutput =
181 |   proto.withFPSOutput =
182 |   proto.withFps =
183 |   proto.withFPS =
184 |   proto.outputFPS =
185 |   proto.outputFps =
186 |   proto.fpsOutput =
187 |   proto.FPSOutput =
188 |   proto.fps =
189 |   proto.FPS = function(fps) {
190 |     this._currentOutput.video('-r', fps);
191 |     return this;
192 |   };
193 | 
194 | 
195 |   /**
196 |    * Only transcode a certain number of frames
197 |    *
198 |    * @method FfmpegCommand#frames
199 |    * @category Video
200 |    * @aliases takeFrames,withFrames
201 |    *
202 |    * @param {Number} frames frame count
203 |    * @return FfmpegCommand
204 |    */
205 |   proto.takeFrames =
206 |   proto.withFrames =
207 |   proto.frames = function(frames) {
208 |     this._currentOutput.video('-vframes', frames);
209 |     return this;
210 |   };
211 | };
212 | </code></pre>
213 |         </article>
214 |     </section>
215 | 
216 | 
217 | 
218 | 
219 | </div>
220 | 
221 | <nav>
222 |     <h2><a href="index.html">Index</a></h2><ul><li><a href="index.html#installation">Installation</a></li><ul></ul><li><a href="index.html#usage">Usage</a></li><ul><li><a href="index.html#prerequisites">Prerequisites</a></li><li><a href="index.html#creating-an-ffmpeg-command">Creating an FFmpeg command</a></li><li><a href="index.html#specifying-inputs">Specifying inputs</a></li><li><a href="index.html#input-options">Input options</a></li><li><a href="index.html#audio-options">Audio options</a></li><li><a href="index.html#video-options">Video options</a></li><li><a href="index.html#video-frame-size-options">Video frame size options</a></li><li><a href="index.html#specifying-multiple-outputs">Specifying multiple outputs</a></li><li><a href="index.html#output-options">Output options</a></li><li><a href="index.html#miscellaneous-options">Miscellaneous options</a></li><li><a href="index.html#setting-event-handlers">Setting event handlers</a></li><li><a href="index.html#starting-ffmpeg-processing">Starting FFmpeg processing</a></li><li><a href="index.html#controlling-the-ffmpeg-process">Controlling the FFmpeg process</a></li><li><a href="index.html#reading-video-metadata">Reading video metadata</a></li><li><a href="index.html#querying-ffmpeg-capabilities">Querying ffmpeg capabilities</a></li><li><a href="index.html#cloning-an-ffmpegcommand">Cloning an FfmpegCommand</a></li></ul><li><a href="index.html#contributing">Contributing</a></li><ul><li><a href="index.html#code-contributions">Code contributions</a></li><li><a href="index.html#documentation-contributions">Documentation contributions</a></li><li><a href="index.html#updating-the-documentation">Updating the documentation</a></li><li><a href="index.html#running-tests">Running tests</a></li></ul><li><a href="index.html#main-contributors">Main contributors</a></li><ul></ul><li><a href="index.html#license">License</a></li><ul></ul></ul><h3>Classes</h3><ul><li><a href="FfmpegCommand.html">FfmpegCommand</a></li><ul><li> <a href="FfmpegCommand.html#audio-methods">Audio methods</a></li><li> <a href="FfmpegCommand.html#capabilities-methods">Capabilities methods</a></li><li> <a href="FfmpegCommand.html#custom-options-methods">Custom options methods</a></li><li> <a href="FfmpegCommand.html#input-methods">Input methods</a></li><li> <a href="FfmpegCommand.html#metadata-methods">Metadata methods</a></li><li> <a href="FfmpegCommand.html#miscellaneous-methods">Miscellaneous methods</a></li><li> <a href="FfmpegCommand.html#other-methods">Other methods</a></li><li> <a href="FfmpegCommand.html#output-methods">Output methods</a></li><li> <a href="FfmpegCommand.html#processing-methods">Processing methods</a></li><li> <a href="FfmpegCommand.html#video-methods">Video methods</a></li><li> <a href="FfmpegCommand.html#video-size-methods">Video size methods</a></li></ul></ul>
223 | </nav>
224 | 
225 | <br clear="both">
226 | 
227 | <footer>
228 |     Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.3.0-alpha5</a> on Tue Jul 08 2014 21:22:19 GMT+0200 (CEST)
229 | </footer>
230 | 
231 | <script> prettyPrint(); </script>
232 | <script src="scripts/linenumber.js"> </script>
233 | </body>
234 | </html>
235 | 


--------------------------------------------------------------------------------
/examples/any-to-mp4-steam.js:
--------------------------------------------------------------------------------
 1 | // The solution based on adding -movflags for mp4 output
 2 | // For more movflags details check ffmpeg docs
 3 | // https://ffmpeg.org/ffmpeg-formats.html#toc-Options-9
 4 | 
 5 | var fs = require('fs');
 6 | var path = require('path');
 7 | var ffmpeg = require('../index');
 8 | 
 9 | var pathToSourceFile = path.resolve(__dirname, '../test/assets/testvideo-169.avi');
10 | var readStream = fs.createReadStream(pathToSourceFile);
11 | var writeStream = fs.createWriteStream('./output.mp4');
12 | 
13 | ffmpeg(readStream)
14 |   .addOutputOptions('-movflags +frag_keyframe+separate_moof+omit_tfhd_offset+empty_moov')
15 |   .format('mp4')
16 |   .pipe(writeStream);
17 | 


--------------------------------------------------------------------------------
/examples/express-stream.js:
--------------------------------------------------------------------------------
 1 | var express = require('express'),
 2 |   ffmpeg = require('../index');
 3 | 
 4 | var app = express();
 5 | 
 6 | app.use(express.static(__dirname + '/flowplayer'));
 7 | 
 8 | app.get('/', function(req, res) {
 9 |   res.send('index.html');
10 | });
11 | 
12 | app.get('/video/:filename', function(req, res) {
13 |   res.contentType('flv');
14 |   // make sure you set the correct path to your video file storage
15 |   var pathToMovie = '/path/to/storage/' + req.params.filename;
16 |   var proc = ffmpeg(pathToMovie)
17 |     // use the 'flashvideo' preset (located in /lib/presets/flashvideo.js)
18 |     .preset('flashvideo')
19 |     // setup event handlers
20 |     .on('end', function() {
21 |       console.log('file has been converted succesfully');
22 |     })
23 |     .on('error', function(err) {
24 |       console.log('an error happened: ' + err.message);
25 |     })
26 |     // save to stream
27 |     .pipe(res, {end:true});
28 | });
29 | 
30 | app.listen(4000);
31 | 


--------------------------------------------------------------------------------
/examples/flowplayer/flowplayer.controls.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluent-ffmpeg/node-fluent-ffmpeg/7a701f560f6cd0f152cdef22c8a03132c56afc7b/examples/flowplayer/flowplayer.controls.swf


--------------------------------------------------------------------------------
/examples/flowplayer/flowplayer.swf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluent-ffmpeg/node-fluent-ffmpeg/7a701f560f6cd0f152cdef22c8a03132c56afc7b/examples/flowplayer/flowplayer.swf


--------------------------------------------------------------------------------
/examples/flowplayer/index.html:
--------------------------------------------------------------------------------
 1 | <html>
 2 | 	<head>
 3 | 		<meta http-equiv="content-type" content="text/html; charset=UTF-8">
 4 | 		<script type="text/javascript" src="/flowplayer.min.js"></script>
 5 | 		<title>node-fluent-ffmpeg</title>
 6 | 	</head>
 7 | 	<body>
 8 | 
 9 | 		<!-- this A tag is where your Flowplayer will be placed. it can be anywhere -->
10 | 		<a  
11 | 			 href="/video/your_movie.avi"
12 | 			 style="display:block;width:520px;height:330px"  
13 | 			 id="player"> 
14 | 		</a> 
15 | 	
16 | 		<!-- this will install flowplayer inside previous A- tag. -->
17 | 		<script>
18 | 			flowplayer("player", "/flowplayer.swf");
19 | 		</script>
20 | 	</body>
21 | </html>


--------------------------------------------------------------------------------
/examples/full.js:
--------------------------------------------------------------------------------
 1 | var ffmpeg = require('../index');
 2 | 
 3 | // make sure you set the correct path to your video file
 4 | var proc = ffmpeg('/path/to/your_movie.avi')
 5 |   // set video bitrate
 6 |   .videoBitrate(1024)
 7 |   // set target codec
 8 |   .videoCodec('divx')
 9 |   // set aspect ratio
10 |   .aspect('16:9')
11 |   // set size in percent
12 |   .size('50%')
13 |   // set fps
14 |   .fps(24)
15 |   // set audio bitrate
16 |   .audioBitrate('128k')
17 |   // set audio codec
18 |   .audioCodec('libmp3lame')
19 |   // set number of audio channels
20 |   .audioChannels(2)
21 |   // set custom option
22 |   .addOption('-vtag', 'DIVX')
23 |   // set output format to force
24 |   .format('avi')
25 |   // setup event handlers
26 |   .on('end', function() {
27 |     console.log('file has been converted succesfully');
28 |   })
29 |   .on('error', function(err) {
30 |     console.log('an error happened: ' + err.message);
31 |   })
32 |   // save to file
33 |   .save('/path/to/your_target.avi');
34 | 


--------------------------------------------------------------------------------
/examples/image2video.js:
--------------------------------------------------------------------------------
 1 | var ffmpeg = require('fluent-ffmpeg');
 2 | 
 3 | // make sure you set the correct path to your video file
 4 | var proc = ffmpeg('/path/to/your_image.jpg')
 5 |   // loop for 5 seconds
 6 |   .loop(5)
 7 |   // using 25 fps
 8 |   .fps(25)
 9 |   // setup event handlers
10 |   .on('end', function() {
11 |     console.log('file has been converted succesfully');
12 |   })
13 |   .on('error', function(err) {
14 |     console.log('an error happened: ' + err.message);
15 |   })
16 |   // save to file
17 |   .save('/path/to/your_target.m4v');
18 | 


--------------------------------------------------------------------------------
/examples/input-stream.js:
--------------------------------------------------------------------------------
 1 | var fs = require('fs'),
 2 |   ffmpeg = require('../index');
 3 | 
 4 | // open input stream
 5 | var infs = fs.createReadStream(__dirname + '/test/assets/testvideo-43.avi');
 6 | 
 7 | infs.on('error', function(err) {
 8 |   console.log(err);
 9 | });
10 | 
11 | // create new ffmpeg processor instance using input stream
12 | // instead of file path (can be any ReadableStream)
13 | var proc = ffmpeg(infs)
14 |   .preset('flashvideo')
15 |   // setup event handlers
16 |   .on('end', function() {
17 |     console.log('done processing input stream');
18 |   })
19 |   .on('error', function(err) {
20 |     console.log('an error happened: ' + err.message);
21 |   })
22 |   // save to file
23 |   .save('/path/to/your_target.flv');
24 | 


--------------------------------------------------------------------------------
/examples/livertmp2hls.js:
--------------------------------------------------------------------------------
 1 | var ffmpeg = require('../index');
 2 | 
 3 | // make sure you set the correct path to your video file
 4 | var proc = ffmpeg('rtmp://path/to/live/stream', { timeout: 432000 })
 5 |   // set video bitrate
 6 |   .videoBitrate(1024)
 7 |   // set h264 preset
 8 |   .addOption('preset','superfast')
 9 |   // set target codec
10 |   .videoCodec('libx264')
11 |   // set audio bitrate
12 |   .audioBitrate('128k')
13 |   // set audio codec
14 |   .audioCodec('libfaac')
15 |   // set number of audio channels
16 |   .audioChannels(2)
17 |   // set hls segments time
18 |   .addOption('-hls_time', 10)
19 |   // include all the segments in the list
20 |   .addOption('-hls_list_size',0)
21 |   // setup event handlers
22 |   .on('end', function() {
23 |     console.log('file has been converted succesfully');
24 |   })
25 |   .on('error', function(err) {
26 |     console.log('an error happened: ' + err.message);
27 |   })
28 |   // save to file
29 |   .save('/path/to/your_target.m3u8');
30 | 


--------------------------------------------------------------------------------
/examples/mergeVideos.js:
--------------------------------------------------------------------------------
 1 | var ffmpeg = require('../index');
 2 | 
 3 | /*
 4 |  replicates this sequence of commands:
 5 | 
 6 |  ffmpeg -i title.mp4 -qscale:v 1 intermediate1.mpg
 7 |  ffmpeg -i source.mp4 -qscale:v 1 intermediate2.mpg
 8 |  ffmpeg -i concat:"intermediate1.mpg|intermediate2.mpg" -c copy intermediate_all.mpg
 9 |  ffmpeg -i intermediate_all.mpg -qscale:v 2 output.mp4
10 | 
11 |  Create temporary .mpg files for each video and deletes them after merge is completed.
12 |  These files are created by filename pattern like [videoFilename.ext].temp.mpg [outputFilename.ext].temp.merged.mp4
13 |  */
14 | 
15 | var firstFile = "title.mp4";
16 | var secondFile = "source.mp4";
17 | var thirdFile = "third.mov";
18 | var outPath = "out.mp4";
19 | 
20 | var proc = ffmpeg(firstFile)
21 |     .input(secondFile)
22 |     .input(thirdFile)
23 |     //.input(fourthFile)
24 |     //.input(...)
25 |     .on('end', function() {
26 |       console.log('files have been merged succesfully');
27 |     })
28 |     .on('error', function(err) {
29 |       console.log('an error happened: ' + err.message);
30 |     })
31 |     .mergeToFile(outPath);


--------------------------------------------------------------------------------
/examples/metadata.js:
--------------------------------------------------------------------------------
1 | var ffmpeg = require('../index');
2 | 
3 | // make sure you set the correct path to your video file
4 | ffmpeg.ffprobe('/path/to/your_movie.avi',function(err, metadata) {
5 |   console.log(require('util').inspect(metadata, false, null));
6 | });
7 | 


--------------------------------------------------------------------------------
/examples/preset.js:
--------------------------------------------------------------------------------
 1 | var ffmpeg = require('../index');
 2 | 
 3 | // make sure you set the correct path to your video file
 4 | var proc = ffmpeg('/path/to/your_movie.avi')
 5 |   // use the 'podcast' preset (located in /lib/presets/podcast.js)
 6 |   .preset('podcast')
 7 |   // in case you want to override the preset's setting, just keep chaining
 8 |   .videoBitrate('512k')
 9 |   // setup event handlers
10 |   .on('end', function() {
11 |     console.log('file has been converted succesfully');
12 |   })
13 |   .on('error', function(err) {
14 |     console.log('an error happened: ' + err.message);
15 |   })
16 |   // save to file
17 |   .save('/path/to/your_target.m4v');
18 | 


--------------------------------------------------------------------------------
/examples/progress.js:
--------------------------------------------------------------------------------
 1 | var fs = require('fs'),
 2 |   ffmpeg = require('../index');
 3 | 
 4 | // open input stream
 5 | var infs = fs.createReadStream(__dirname + '/test/assets/testvideo-43.avi');
 6 | 
 7 | infs.on('error', function(err) {
 8 |   console.log(err);
 9 | });
10 | 
11 | var proc = ffmpeg(infs)
12 |   .preset('flashvideo')
13 |   // setup event handlers
14 |   .on('progress', function(info) {
15 |     console.log('progress ' + info.percent + '%');
16 |   })
17 |   .on('end', function() {
18 |     console.log('done processing input stream');
19 |   })
20 |   .on('error', function(err) {
21 |     console.log('an error happened: ' + err.message);
22 |   })
23 |   .save('/path/to/your_target.flv');


--------------------------------------------------------------------------------
/examples/stream.js:
--------------------------------------------------------------------------------
 1 | var ffmpeg = require('../index'),
 2 |   fs = require('fs');
 3 | 
 4 | // create the target stream (can be any WritableStream)
 5 | var stream = fs.createWriteStream('/path/to/yout_target.flv')
 6 | 
 7 | // make sure you set the correct path to your video file
 8 | var proc = ffmpeg('/path/to/your_movie.avi')
 9 |   // use the 'flashvideo' preset (located in /lib/presets/flashvideo.js)
10 |   .preset('flashvideo')
11 |   // setup event handlers
12 |   .on('end', function() {
13 |     console.log('file has been converted succesfully');
14 |   })
15 |   .on('error', function(err) {
16 |     console.log('an error happened: ' + err.message);
17 |   })
18 |   // save to stream
19 |   .pipe(stream, {end:true}); //end = true, close output stream after writing
20 | 


--------------------------------------------------------------------------------
/examples/thumbnails.js:
--------------------------------------------------------------------------------
 1 | var ffmpeg = require('../index');
 2 | 
 3 | var proc = ffmpeg('/path/to/your_movie.avi')
 4 |   // setup event handlers
 5 |   .on('filenames', function(filenames) {
 6 |     console.log('screenshots are ' + filenames.join(', '));
 7 |   })
 8 |   .on('end', function() {
 9 |     console.log('screenshots were saved');
10 |   })
11 |   .on('error', function(err) {
12 |     console.log('an error happened: ' + err.message);
13 |   })
14 |   // take 2 screenshots at predefined timemarks and size
15 |   .takeScreenshots({ count: 2, timemarks: [ '00:00:02.000', '6' ], size: '150x100' }, '/path/to/thumbnail/folder');
16 | 


--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./lib/fluent-ffmpeg');
2 | 


--------------------------------------------------------------------------------
/lib/ffprobe.js:
--------------------------------------------------------------------------------
  1 | /*jshint node:true, laxcomma:true*/
  2 | 'use strict';
  3 | 
  4 | var spawn = require('child_process').spawn;
  5 | 
  6 | 
  7 | function legacyTag(key) { return key.match(/^TAG:/); }
  8 | function legacyDisposition(key) { return key.match(/^DISPOSITION:/); }
  9 | 
 10 | function parseFfprobeOutput(out) {
 11 |   var lines = out.split(/\r\n|\r|\n/);
 12 | 
 13 |   lines = lines.filter(function (line) {
 14 |     return line.length > 0;
 15 |   });
 16 | 
 17 |   var data = {
 18 |     streams: [],
 19 |     format: {},
 20 |     chapters: []
 21 |   };
 22 | 
 23 |   function parseBlock(name) {
 24 |     var data = {};
 25 | 
 26 |     var line = lines.shift();
 27 |     while (typeof line !== 'undefined') {
 28 |       if (line.toLowerCase() == '[/'+name+']') {
 29 |         return data;
 30 |       } else if (line.match(/^\[/)) {
 31 |         line = lines.shift();
 32 |         continue;
 33 |       }
 34 | 
 35 |       var kv = line.match(/^([^=]+)=(.*)$/);
 36 |       if (kv) {
 37 |         if (!(kv[1].match(/^TAG:/)) && kv[2].match(/^[0-9]+(\.[0-9]+)?$/)) {
 38 |           data[kv[1]] = Number(kv[2]);
 39 |         } else {
 40 |           data[kv[1]] = kv[2];
 41 |         }
 42 |       }
 43 | 
 44 |       line = lines.shift();
 45 |     }
 46 | 
 47 |     return data;
 48 |   }
 49 | 
 50 |   var line = lines.shift();
 51 |   while (typeof line !== 'undefined') {
 52 |     if (line.match(/^\[stream/i)) {
 53 |       var stream = parseBlock('stream');
 54 |       data.streams.push(stream);
 55 |     } else if (line.match(/^\[chapter/i)) {
 56 |       var chapter = parseBlock('chapter');
 57 |       data.chapters.push(chapter);
 58 |     } else if (line.toLowerCase() === '[format]') {
 59 |       data.format = parseBlock('format');
 60 |     }
 61 | 
 62 |     line = lines.shift();
 63 |   }
 64 | 
 65 |   return data;
 66 | }
 67 | 
 68 | 
 69 | 
 70 | module.exports = function(proto) {
 71 |   /**
 72 |    * A callback passed to the {@link FfmpegCommand#ffprobe} method.
 73 |    *
 74 |    * @callback FfmpegCommand~ffprobeCallback
 75 |    *
 76 |    * @param {Error|null} err error object or null if no error happened
 77 |    * @param {Object} ffprobeData ffprobe output data; this object
 78 |    *   has the same format as what the following command returns:
 79 |    *
 80 |    *     `ffprobe -print_format json -show_streams -show_format INPUTFILE`
 81 |    * @param {Array} ffprobeData.streams stream information
 82 |    * @param {Object} ffprobeData.format format information
 83 |    */
 84 | 
 85 |   /**
 86 |    * Run ffprobe on last specified input
 87 |    *
 88 |    * @method FfmpegCommand#ffprobe
 89 |    * @category Metadata
 90 |    *
 91 |    * @param {?Number} [index] 0-based index of input to probe (defaults to last input)
 92 |    * @param {?String[]} [options] array of output options to return
 93 |    * @param {FfmpegCommand~ffprobeCallback} callback callback function
 94 |    *
 95 |    */
 96 |   proto.ffprobe = function() {
 97 |     var input, index = null, options = [], callback;
 98 | 
 99 |     // the last argument should be the callback
100 |     var callback = arguments[arguments.length - 1];
101 | 
102 |     var ended = false
103 |     function handleCallback(err, data) {
104 |       if (!ended) {
105 |         ended = true;
106 |         callback(err, data);
107 |       }
108 |     };
109 | 
110 |     // map the arguments to the correct variable names
111 |     switch (arguments.length) {
112 |       case 3:
113 |         index = arguments[0];
114 |         options = arguments[1];
115 |         break;
116 |       case 2:
117 |         if (typeof arguments[0] === 'number') {
118 |           index = arguments[0];
119 |         } else if (Array.isArray(arguments[0])) {
120 |           options = arguments[0];
121 |         }
122 |         break;
123 |     }
124 | 
125 | 
126 |     if (index === null) {
127 |       if (!this._currentInput) {
128 |         return handleCallback(new Error('No input specified'));
129 |       }
130 | 
131 |       input = this._currentInput;
132 |     } else {
133 |       input = this._inputs[index];
134 | 
135 |       if (!input) {
136 |         return handleCallback(new Error('Invalid input index'));
137 |       }
138 |     }
139 | 
140 |     // Find ffprobe
141 |     this._getFfprobePath(function(err, path) {
142 |       if (err) {
143 |         return handleCallback(err);
144 |       } else if (!path) {
145 |         return handleCallback(new Error('Cannot find ffprobe'));
146 |       }
147 | 
148 |       var stdout = '';
149 |       var stdoutClosed = false;
150 |       var stderr = '';
151 |       var stderrClosed = false;
152 | 
153 |       // Spawn ffprobe
154 |       var src = input.isStream ? 'pipe:0' : input.source;
155 |       var ffprobe = spawn(path, ['-show_streams', '-show_format'].concat(options, src), {windowsHide: true});
156 | 
157 |       if (input.isStream) {
158 |         // Skip errors on stdin. These get thrown when ffprobe is complete and
159 |         // there seems to be no way hook in and close stdin before it throws.
160 |         ffprobe.stdin.on('error', function(err) {
161 |           if (['ECONNRESET', 'EPIPE', 'EOF'].indexOf(err.code) >= 0) { return; }
162 |           handleCallback(err);
163 |         });
164 | 
165 |         // Once ffprobe's input stream closes, we need no more data from the
166 |         // input
167 |         ffprobe.stdin.on('close', function() {
168 |             input.source.pause();
169 |             input.source.unpipe(ffprobe.stdin);
170 |         });
171 | 
172 |         input.source.pipe(ffprobe.stdin);
173 |       }
174 | 
175 |       ffprobe.on('error', callback);
176 | 
177 |       // Ensure we wait for captured streams to end before calling callback
178 |       var exitError = null;
179 |       function handleExit(err) {
180 |         if (err) {
181 |           exitError = err;
182 |         }
183 | 
184 |         if (processExited && stdoutClosed && stderrClosed) {
185 |           if (exitError) {
186 |             if (stderr) {
187 |               exitError.message += '\n' + stderr;
188 |             }
189 | 
190 |             return handleCallback(exitError);
191 |           }
192 | 
193 |           // Process output
194 |           var data = parseFfprobeOutput(stdout);
195 | 
196 |           // Handle legacy output with "TAG:x" and "DISPOSITION:x" keys
197 |           [data.format].concat(data.streams).forEach(function(target) {
198 |             if (target) {
199 |               var legacyTagKeys = Object.keys(target).filter(legacyTag);
200 | 
201 |               if (legacyTagKeys.length) {
202 |                 target.tags = target.tags || {};
203 | 
204 |                 legacyTagKeys.forEach(function(tagKey) {
205 |                   target.tags[tagKey.substr(4)] = target[tagKey];
206 |                   delete target[tagKey];
207 |                 });
208 |               }
209 | 
210 |               var legacyDispositionKeys = Object.keys(target).filter(legacyDisposition);
211 | 
212 |               if (legacyDispositionKeys.length) {
213 |                 target.disposition = target.disposition || {};
214 | 
215 |                 legacyDispositionKeys.forEach(function(dispositionKey) {
216 |                   target.disposition[dispositionKey.substr(12)] = target[dispositionKey];
217 |                   delete target[dispositionKey];
218 |                 });
219 |               }
220 |             }
221 |           });
222 | 
223 |           handleCallback(null, data);
224 |         }
225 |       }
226 | 
227 |       // Handle ffprobe exit
228 |       var processExited = false;
229 |       ffprobe.on('exit', function(code, signal) {
230 |         processExited = true;
231 | 
232 |         if (code) {
233 |           handleExit(new Error('ffprobe exited with code ' + code));
234 |         } else if (signal) {
235 |           handleExit(new Error('ffprobe was killed with signal ' + signal));
236 |         } else {
237 |           handleExit();
238 |         }
239 |       });
240 | 
241 |       // Handle stdout/stderr streams
242 |       ffprobe.stdout.on('data', function(data) {
243 |         stdout += data;
244 |       });
245 | 
246 |       ffprobe.stdout.on('close', function() {
247 |         stdoutClosed = true;
248 |         handleExit();
249 |       });
250 | 
251 |       ffprobe.stderr.on('data', function(data) {
252 |         stderr += data;
253 |       });
254 | 
255 |       ffprobe.stderr.on('close', function() {
256 |         stderrClosed = true;
257 |         handleExit();
258 |       });
259 |     });
260 |   };
261 | };
262 | 


--------------------------------------------------------------------------------
/lib/fluent-ffmpeg.js:
--------------------------------------------------------------------------------
  1 | /*jshint node:true*/
  2 | 'use strict';
  3 | 
  4 | var path = require('path');
  5 | var util = require('util');
  6 | var EventEmitter = require('events').EventEmitter;
  7 | 
  8 | var utils = require('./utils');
  9 | var ARGLISTS = ['_global', '_audio', '_audioFilters', '_video', '_videoFilters', '_sizeFilters', '_complexFilters'];
 10 | 
 11 | 
 12 | /**
 13 |  * Create an ffmpeg command
 14 |  *
 15 |  * Can be called with or without the 'new' operator, and the 'input' parameter
 16 |  * may be specified as 'options.source' instead (or passed later with the
 17 |  * addInput method).
 18 |  *
 19 |  * @constructor
 20 |  * @param {String|ReadableStream} [input] input file path or readable stream
 21 |  * @param {Object} [options] command options
 22 |  * @param {Object} [options.logger=<no logging>] logger object with 'error', 'warning', 'info' and 'debug' methods
 23 |  * @param {Number} [options.niceness=0] ffmpeg process niceness, ignored on Windows
 24 |  * @param {Number} [options.priority=0] alias for `niceness`
 25 |  * @param {String} [options.presets="fluent-ffmpeg/lib/presets"] directory to load presets from
 26 |  * @param {String} [options.preset="fluent-ffmpeg/lib/presets"] alias for `presets`
 27 |  * @param {String} [options.stdoutLines=100] maximum lines of ffmpeg output to keep in memory, use 0 for unlimited
 28 |  * @param {Number} [options.timeout=<no timeout>] ffmpeg processing timeout in seconds
 29 |  * @param {String|ReadableStream} [options.source=<no input>] alias for the `input` parameter
 30 |  */
 31 | function FfmpegCommand(input, options) {
 32 |   // Make 'new' optional
 33 |   if (!(this instanceof FfmpegCommand)) {
 34 |     return new FfmpegCommand(input, options);
 35 |   }
 36 | 
 37 |   EventEmitter.call(this);
 38 | 
 39 |   if (typeof input === 'object' && !('readable' in input)) {
 40 |     // Options object passed directly
 41 |     options = input;
 42 |   } else {
 43 |     // Input passed first
 44 |     options = options || {};
 45 |     options.source = input;
 46 |   }
 47 | 
 48 |   // Add input if present
 49 |   this._inputs = [];
 50 |   if (options.source) {
 51 |     this.input(options.source);
 52 |   }
 53 | 
 54 |   // Add target-less output for backwards compatibility
 55 |   this._outputs = [];
 56 |   this.output();
 57 | 
 58 |   // Create argument lists
 59 |   var self = this;
 60 |   ['_global', '_complexFilters'].forEach(function(prop) {
 61 |     self[prop] = utils.args();
 62 |   });
 63 | 
 64 |   // Set default option values
 65 |   options.stdoutLines = 'stdoutLines' in options ? options.stdoutLines : 100;
 66 |   options.presets = options.presets || options.preset || path.join(__dirname, 'presets');
 67 |   options.niceness = options.niceness || options.priority || 0;
 68 | 
 69 |   // Save options
 70 |   this.options = options;
 71 | 
 72 |   // Setup logger
 73 |   this.logger = options.logger || {
 74 |     debug: function() {},
 75 |     info: function() {},
 76 |     warn: function() {},
 77 |     error: function() {}
 78 |   };
 79 | }
 80 | util.inherits(FfmpegCommand, EventEmitter);
 81 | module.exports = FfmpegCommand;
 82 | 
 83 | 
 84 | /**
 85 |  * Clone an ffmpeg command
 86 |  *
 87 |  * This method is useful when you want to process the same input multiple times.
 88 |  * It returns a new FfmpegCommand instance with the exact same options.
 89 |  *
 90 |  * All options set _after_ the clone() call will only be applied to the instance
 91 |  * it has been called on.
 92 |  *
 93 |  * @example
 94 |  *   var command = ffmpeg('/path/to/source.avi')
 95 |  *     .audioCodec('libfaac')
 96 |  *     .videoCodec('libx264')
 97 |  *     .format('mp4');
 98 |  *
 99 |  *   command.clone()
100 |  *     .size('320x200')
101 |  *     .save('/path/to/output-small.mp4');
102 |  *
103 |  *   command.clone()
104 |  *     .size('640x400')
105 |  *     .save('/path/to/output-medium.mp4');
106 |  *
107 |  *   command.save('/path/to/output-original-size.mp4');
108 |  *
109 |  * @method FfmpegCommand#clone
110 |  * @return FfmpegCommand
111 |  */
112 | FfmpegCommand.prototype.clone = function() {
113 |   var clone = new FfmpegCommand();
114 |   var self = this;
115 | 
116 |   // Clone options and logger
117 |   clone.options = this.options;
118 |   clone.logger = this.logger;
119 | 
120 |   // Clone inputs
121 |   clone._inputs = this._inputs.map(function(input) {
122 |     return {
123 |       source: input.source,
124 |       options: input.options.clone()
125 |     };
126 |   });
127 | 
128 |   // Create first output
129 |   if ('target' in this._outputs[0]) {
130 |     // We have outputs set, don't clone them and create first output
131 |     clone._outputs = [];
132 |     clone.output();
133 |   } else {
134 |     // No outputs set, clone first output options
135 |     clone._outputs = [
136 |       clone._currentOutput = {
137 |         flags: {}
138 |       }
139 |     ];
140 | 
141 |     ['audio', 'audioFilters', 'video', 'videoFilters', 'sizeFilters', 'options'].forEach(function(key) {
142 |       clone._currentOutput[key] = self._currentOutput[key].clone();
143 |     });
144 | 
145 |     if (this._currentOutput.sizeData) {
146 |       clone._currentOutput.sizeData = {};
147 |       utils.copy(this._currentOutput.sizeData, clone._currentOutput.sizeData);
148 |     }
149 | 
150 |     utils.copy(this._currentOutput.flags, clone._currentOutput.flags);
151 |   }
152 | 
153 |   // Clone argument lists
154 |   ['_global', '_complexFilters'].forEach(function(prop) {
155 |     clone[prop] = self[prop].clone();
156 |   });
157 | 
158 |   return clone;
159 | };
160 | 
161 | 
162 | /* Add methods from options submodules */
163 | 
164 | require('./options/inputs')(FfmpegCommand.prototype);
165 | require('./options/audio')(FfmpegCommand.prototype);
166 | require('./options/video')(FfmpegCommand.prototype);
167 | require('./options/videosize')(FfmpegCommand.prototype);
168 | require('./options/output')(FfmpegCommand.prototype);
169 | require('./options/custom')(FfmpegCommand.prototype);
170 | require('./options/misc')(FfmpegCommand.prototype);
171 | 
172 | 
173 | /* Add processor methods */
174 | 
175 | require('./processor')(FfmpegCommand.prototype);
176 | 
177 | 
178 | /* Add capabilities methods */
179 | 
180 | require('./capabilities')(FfmpegCommand.prototype);
181 | 
182 | FfmpegCommand.setFfmpegPath = function(path) {
183 |   (new FfmpegCommand()).setFfmpegPath(path);
184 | };
185 | 
186 | FfmpegCommand.setFfprobePath = function(path) {
187 |   (new FfmpegCommand()).setFfprobePath(path);
188 | };
189 | 
190 | FfmpegCommand.setFlvtoolPath = function(path) {
191 |   (new FfmpegCommand()).setFlvtoolPath(path);
192 | };
193 | 
194 | FfmpegCommand.availableFilters =
195 | FfmpegCommand.getAvailableFilters = function(callback) {
196 |   (new FfmpegCommand()).availableFilters(callback);
197 | };
198 | 
199 | FfmpegCommand.availableCodecs =
200 | FfmpegCommand.getAvailableCodecs = function(callback) {
201 |   (new FfmpegCommand()).availableCodecs(callback);
202 | };
203 | 
204 | FfmpegCommand.availableFormats =
205 | FfmpegCommand.getAvailableFormats = function(callback) {
206 |   (new FfmpegCommand()).availableFormats(callback);
207 | };
208 | 
209 | FfmpegCommand.availableEncoders =
210 | FfmpegCommand.getAvailableEncoders = function(callback) {
211 |   (new FfmpegCommand()).availableEncoders(callback);
212 | };
213 | 
214 | 
215 | /* Add ffprobe methods */
216 | 
217 | require('./ffprobe')(FfmpegCommand.prototype);
218 | 
219 | FfmpegCommand.ffprobe = function(file) {
220 |   var instance = new FfmpegCommand(file);
221 |   instance.ffprobe.apply(instance, Array.prototype.slice.call(arguments, 1));
222 | };
223 | 
224 | /* Add processing recipes */
225 | 
226 | require('./recipes')(FfmpegCommand.prototype);
227 | 


--------------------------------------------------------------------------------
/lib/options/audio.js:
--------------------------------------------------------------------------------
  1 | /*jshint node:true*/
  2 | 'use strict';
  3 | 
  4 | var utils = require('../utils');
  5 | 
  6 | 
  7 | /*
  8 |  *! Audio-related methods
  9 |  */
 10 | 
 11 | module.exports = function(proto) {
 12 |   /**
 13 |    * Disable audio in the output
 14 |    *
 15 |    * @method FfmpegCommand#noAudio
 16 |    * @category Audio
 17 |    * @aliases withNoAudio
 18 |    * @return FfmpegCommand
 19 |    */
 20 |   proto.withNoAudio =
 21 |   proto.noAudio = function() {
 22 |     this._currentOutput.audio.clear();
 23 |     this._currentOutput.audioFilters.clear();
 24 |     this._currentOutput.audio('-an');
 25 | 
 26 |     return this;
 27 |   };
 28 | 
 29 | 
 30 |   /**
 31 |    * Specify audio codec
 32 |    *
 33 |    * @method FfmpegCommand#audioCodec
 34 |    * @category Audio
 35 |    * @aliases withAudioCodec
 36 |    *
 37 |    * @param {String} codec audio codec name
 38 |    * @return FfmpegCommand
 39 |    */
 40 |   proto.withAudioCodec =
 41 |   proto.audioCodec = function(codec) {
 42 |     this._currentOutput.audio('-acodec', codec);
 43 | 
 44 |     return this;
 45 |   };
 46 | 
 47 | 
 48 |   /**
 49 |    * Specify audio bitrate
 50 |    *
 51 |    * @method FfmpegCommand#audioBitrate
 52 |    * @category Audio
 53 |    * @aliases withAudioBitrate
 54 |    *
 55 |    * @param {String|Number} bitrate audio bitrate in kbps (with an optional 'k' suffix)
 56 |    * @return FfmpegCommand
 57 |    */
 58 |   proto.withAudioBitrate =
 59 |   proto.audioBitrate = function(bitrate) {
 60 |     this._currentOutput.audio('-b:a', ('' + bitrate).replace(/k?$/, 'k'));
 61 |     return this;
 62 |   };
 63 | 
 64 | 
 65 |   /**
 66 |    * Specify audio channel count
 67 |    *
 68 |    * @method FfmpegCommand#audioChannels
 69 |    * @category Audio
 70 |    * @aliases withAudioChannels
 71 |    *
 72 |    * @param {Number} channels channel count
 73 |    * @return FfmpegCommand
 74 |    */
 75 |   proto.withAudioChannels =
 76 |   proto.audioChannels = function(channels) {
 77 |     this._currentOutput.audio('-ac', channels);
 78 |     return this;
 79 |   };
 80 | 
 81 | 
 82 |   /**
 83 |    * Specify audio frequency
 84 |    *
 85 |    * @method FfmpegCommand#audioFrequency
 86 |    * @category Audio
 87 |    * @aliases withAudioFrequency
 88 |    *
 89 |    * @param {Number} freq audio frequency in Hz
 90 |    * @return FfmpegCommand
 91 |    */
 92 |   proto.withAudioFrequency =
 93 |   proto.audioFrequency = function(freq) {
 94 |     this._currentOutput.audio('-ar', freq);
 95 |     return this;
 96 |   };
 97 | 
 98 | 
 99 |   /**
100 |    * Specify audio quality
101 |    *
102 |    * @method FfmpegCommand#audioQuality
103 |    * @category Audio
104 |    * @aliases withAudioQuality
105 |    *
106 |    * @param {Number} quality audio quality factor
107 |    * @return FfmpegCommand
108 |    */
109 |   proto.withAudioQuality =
110 |   proto.audioQuality = function(quality) {
111 |     this._currentOutput.audio('-aq', quality);
112 |     return this;
113 |   };
114 | 
115 | 
116 |   /**
117 |    * Specify custom audio filter(s)
118 |    *
119 |    * Can be called both with one or many filters, or a filter array.
120 |    *
121 |    * @example
122 |    * command.audioFilters('filter1');
123 |    *
124 |    * @example
125 |    * command.audioFilters('filter1', 'filter2=param1=value1:param2=value2');
126 |    *
127 |    * @example
128 |    * command.audioFilters(['filter1', 'filter2']);
129 |    *
130 |    * @example
131 |    * command.audioFilters([
132 |    *   {
133 |    *     filter: 'filter1'
134 |    *   },
135 |    *   {
136 |    *     filter: 'filter2',
137 |    *     options: 'param=value:param=value'
138 |    *   }
139 |    * ]);
140 |    *
141 |    * @example
142 |    * command.audioFilters(
143 |    *   {
144 |    *     filter: 'filter1',
145 |    *     options: ['value1', 'value2']
146 |    *   },
147 |    *   {
148 |    *     filter: 'filter2',
149 |    *     options: { param1: 'value1', param2: 'value2' }
150 |    *   }
151 |    * );
152 |    *
153 |    * @method FfmpegCommand#audioFilters
154 |    * @aliases withAudioFilter,withAudioFilters,audioFilter
155 |    * @category Audio
156 |    *
157 |    * @param {...String|String[]|Object[]} filters audio filter strings, string array or
158 |    *   filter specification array, each with the following properties:
159 |    * @param {String} filters.filter filter name
160 |    * @param {String|String[]|Object} [filters.options] filter option string, array, or object
161 |    * @return FfmpegCommand
162 |    */
163 |   proto.withAudioFilter =
164 |   proto.withAudioFilters =
165 |   proto.audioFilter =
166 |   proto.audioFilters = function(filters) {
167 |     if (arguments.length > 1) {
168 |       filters = [].slice.call(arguments);
169 |     }
170 | 
171 |     if (!Array.isArray(filters)) {
172 |       filters = [filters];
173 |     }
174 | 
175 |     this._currentOutput.audioFilters(utils.makeFilterStrings(filters));
176 |     return this;
177 |   };
178 | };
179 | 


--------------------------------------------------------------------------------
/lib/options/custom.js:
--------------------------------------------------------------------------------
  1 | /*jshint node:true*/
  2 | 'use strict';
  3 | 
  4 | var utils = require('../utils');
  5 | 
  6 | 
  7 | /*
  8 |  *! Custom options methods
  9 |  */
 10 | 
 11 | module.exports = function(proto) {
 12 |   /**
 13 |    * Add custom input option(s)
 14 |    *
 15 |    * When passing a single string or an array, each string containing two
 16 |    * words is split (eg. inputOptions('-option value') is supported) for
 17 |    * compatibility reasons.  This is not the case when passing more than
 18 |    * one argument.
 19 |    *
 20 |    * @example
 21 |    * command.inputOptions('option1');
 22 |    *
 23 |    * @example
 24 |    * command.inputOptions('option1', 'option2');
 25 |    *
 26 |    * @example
 27 |    * command.inputOptions(['option1', 'option2']);
 28 |    *
 29 |    * @method FfmpegCommand#inputOptions
 30 |    * @category Custom options
 31 |    * @aliases addInputOption,addInputOptions,withInputOption,withInputOptions,inputOption
 32 |    *
 33 |    * @param {...String} options option string(s) or string array
 34 |    * @return FfmpegCommand
 35 |    */
 36 |   proto.addInputOption =
 37 |   proto.addInputOptions =
 38 |   proto.withInputOption =
 39 |   proto.withInputOptions =
 40 |   proto.inputOption =
 41 |   proto.inputOptions = function(options) {
 42 |     if (!this._currentInput) {
 43 |       throw new Error('No input specified');
 44 |     }
 45 | 
 46 |     var doSplit = true;
 47 | 
 48 |     if (arguments.length > 1) {
 49 |       options = [].slice.call(arguments);
 50 |       doSplit = false;
 51 |     }
 52 | 
 53 |     if (!Array.isArray(options)) {
 54 |       options = [options];
 55 |     }
 56 | 
 57 |     this._currentInput.options(options.reduce(function(options, option) {
 58 |       var split = String(option).split(' ');
 59 | 
 60 |       if (doSplit && split.length === 2) {
 61 |         options.push(split[0], split[1]);
 62 |       } else {
 63 |         options.push(option);
 64 |       }
 65 | 
 66 |       return options;
 67 |     }, []));
 68 |     return this;
 69 |   };
 70 | 
 71 | 
 72 |   /**
 73 |    * Add custom output option(s)
 74 |    *
 75 |    * @example
 76 |    * command.outputOptions('option1');
 77 |    *
 78 |    * @example
 79 |    * command.outputOptions('option1', 'option2');
 80 |    *
 81 |    * @example
 82 |    * command.outputOptions(['option1', 'option2']);
 83 |    *
 84 |    * @method FfmpegCommand#outputOptions
 85 |    * @category Custom options
 86 |    * @aliases addOutputOption,addOutputOptions,addOption,addOptions,withOutputOption,withOutputOptions,withOption,withOptions,outputOption
 87 |    *
 88 |    * @param {...String} options option string(s) or string array
 89 |    * @return FfmpegCommand
 90 |    */
 91 |   proto.addOutputOption =
 92 |   proto.addOutputOptions =
 93 |   proto.addOption =
 94 |   proto.addOptions =
 95 |   proto.withOutputOption =
 96 |   proto.withOutputOptions =
 97 |   proto.withOption =
 98 |   proto.withOptions =
 99 |   proto.outputOption =
100 |   proto.outputOptions = function(options) {
101 |     var doSplit = true;
102 | 
103 |     if (arguments.length > 1) {
104 |       options = [].slice.call(arguments);
105 |       doSplit = false;
106 |     }
107 | 
108 |     if (!Array.isArray(options)) {
109 |       options = [options];
110 |     }
111 | 
112 |     this._currentOutput.options(options.reduce(function(options, option) {
113 |       var split = String(option).split(' ');
114 | 
115 |       if (doSplit && split.length === 2) {
116 |         options.push(split[0], split[1]);
117 |       } else {
118 |         options.push(option);
119 |       }
120 | 
121 |       return options;
122 |     }, []));
123 |     return this;
124 |   };
125 | 
126 | 
127 |   /**
128 |    * Specify a complex filtergraph
129 |    *
130 |    * Calling this method will override any previously set filtergraph, but you can set
131 |    * as many filters as needed in one call.
132 |    *
133 |    * @example <caption>Overlay an image over a video (using a filtergraph string)</caption>
134 |    *   ffmpeg()
135 |    *     .input('video.avi')
136 |    *     .input('image.png')
137 |    *     .complexFilter('[0:v][1:v]overlay[out]', ['out']);
138 |    *
139 |    * @example <caption>Overlay an image over a video (using a filter array)</caption>
140 |    *   ffmpeg()
141 |    *     .input('video.avi')
142 |    *     .input('image.png')
143 |    *     .complexFilter([{
144 |    *       filter: 'overlay',
145 |    *       inputs: ['0:v', '1:v'],
146 |    *       outputs: ['out']
147 |    *     }], ['out']);
148 |    *
149 |    * @example <caption>Split video into RGB channels and output a 3x1 video with channels side to side</caption>
150 |    *  ffmpeg()
151 |    *    .input('video.avi')
152 |    *    .complexFilter([
153 |    *      // Duplicate video stream 3 times into streams a, b, and c
154 |    *      { filter: 'split', options: '3', outputs: ['a', 'b', 'c'] },
155 |    *
156 |    *      // Create stream 'red' by cancelling green and blue channels from stream 'a'
157 |    *      { filter: 'lutrgb', options: { g: 0, b: 0 }, inputs: 'a', outputs: 'red' },
158 |    *
159 |    *      // Create stream 'green' by cancelling red and blue channels from stream 'b'
160 |    *      { filter: 'lutrgb', options: { r: 0, b: 0 }, inputs: 'b', outputs: 'green' },
161 |    *
162 |    *      // Create stream 'blue' by cancelling red and green channels from stream 'c'
163 |    *      { filter: 'lutrgb', options: { r: 0, g: 0 }, inputs: 'c', outputs: 'blue' },
164 |    *
165 |    *      // Pad stream 'red' to 3x width, keeping the video on the left, and name output 'padded'
166 |    *      { filter: 'pad', options: { w: 'iw*3', h: 'ih' }, inputs: 'red', outputs: 'padded' },
167 |    *
168 |    *      // Overlay 'green' onto 'padded', moving it to the center, and name output 'redgreen'
169 |    *      { filter: 'overlay', options: { x: 'w', y: 0 }, inputs: ['padded', 'green'], outputs: 'redgreen'},
170 |    *
171 |    *      // Overlay 'blue' onto 'redgreen', moving it to the right
172 |    *      { filter: 'overlay', options: { x: '2*w', y: 0 }, inputs: ['redgreen', 'blue']},
173 |    *    ]);
174 |    *
175 |    * @method FfmpegCommand#complexFilter
176 |    * @category Custom options
177 |    * @aliases filterGraph
178 |    *
179 |    * @param {String|Array} spec filtergraph string or array of filter specification
180 |    *   objects, each having the following properties:
181 |    * @param {String} spec.filter filter name
182 |    * @param {String|Array} [spec.inputs] (array of) input stream specifier(s) for the filter,
183 |    *   defaults to ffmpeg automatically choosing the first unused matching streams
184 |    * @param {String|Array} [spec.outputs] (array of) output stream specifier(s) for the filter,
185 |    *   defaults to ffmpeg automatically assigning the output to the output file
186 |    * @param {Object|String|Array} [spec.options] filter options, can be omitted to not set any options
187 |    * @param {Array} [map] (array of) stream specifier(s) from the graph to include in
188 |    *   ffmpeg output, defaults to ffmpeg automatically choosing the first matching streams.
189 |    * @return FfmpegCommand
190 |    */
191 |   proto.filterGraph =
192 |   proto.complexFilter = function(spec, map) {
193 |     this._complexFilters.clear();
194 | 
195 |     if (!Array.isArray(spec)) {
196 |       spec = [spec];
197 |     }
198 | 
199 |     this._complexFilters('-filter_complex', utils.makeFilterStrings(spec).join(';'));
200 | 
201 |     if (Array.isArray(map)) {
202 |       var self = this;
203 |       map.forEach(function(streamSpec) {
204 |         self._complexFilters('-map', streamSpec.replace(utils.streamRegexp, '[$1]'));
205 |       });
206 |     } else if (typeof map === 'string') {
207 |       this._complexFilters('-map', map.replace(utils.streamRegexp, '[$1]'));
208 |     }
209 | 
210 |     return this;
211 |   };
212 | };
213 | 


--------------------------------------------------------------------------------
/lib/options/inputs.js:
--------------------------------------------------------------------------------
  1 | /*jshint node:true*/
  2 | 'use strict';
  3 | 
  4 | var utils = require('../utils');
  5 | 
  6 | /*
  7 |  *! Input-related methods
  8 |  */
  9 | 
 10 | module.exports = function(proto) {
 11 |   /**
 12 |    * Add an input to command
 13 |    *
 14 |    * Also switches "current input", that is the input that will be affected
 15 |    * by subsequent input-related methods.
 16 |    *
 17 |    * Note: only one stream input is supported for now.
 18 |    *
 19 |    * @method FfmpegCommand#input
 20 |    * @category Input
 21 |    * @aliases mergeAdd,addInput
 22 |    *
 23 |    * @param {String|Readable} source input file path or readable stream
 24 |    * @return FfmpegCommand
 25 |    */
 26 |   proto.mergeAdd =
 27 |   proto.addInput =
 28 |   proto.input = function(source) {
 29 |     var isFile = false;
 30 |     var isStream = false;
 31 | 
 32 |     if (typeof source !== 'string') {
 33 |       if (!('readable' in source) || !(source.readable)) {
 34 |         throw new Error('Invalid input');
 35 |       }
 36 | 
 37 |       var hasInputStream = this._inputs.some(function(input) {
 38 |         return input.isStream;
 39 |       });
 40 | 
 41 |       if (hasInputStream) {
 42 |         throw new Error('Only one input stream is supported');
 43 |       }
 44 | 
 45 |       isStream = true;
 46 |       source.pause();
 47 |     } else {
 48 |       var protocol = source.match(/^([a-z]{2,}):/i);
 49 |       isFile = !protocol || protocol[0] === 'file';
 50 |     }
 51 | 
 52 |     this._inputs.push(this._currentInput = {
 53 |       source: source,
 54 |       isFile: isFile,
 55 |       isStream: isStream,
 56 |       options: utils.args()
 57 |     });
 58 | 
 59 |     return this;
 60 |   };
 61 | 
 62 | 
 63 |   /**
 64 |    * Specify input format for the last specified input
 65 |    *
 66 |    * @method FfmpegCommand#inputFormat
 67 |    * @category Input
 68 |    * @aliases withInputFormat,fromFormat
 69 |    *
 70 |    * @param {String} format input format
 71 |    * @return FfmpegCommand
 72 |    */
 73 |   proto.withInputFormat =
 74 |   proto.inputFormat =
 75 |   proto.fromFormat = function(format) {
 76 |     if (!this._currentInput) {
 77 |       throw new Error('No input specified');
 78 |     }
 79 | 
 80 |     this._currentInput.options('-f', format);
 81 |     return this;
 82 |   };
 83 | 
 84 | 
 85 |   /**
 86 |    * Specify input FPS for the last specified input
 87 |    * (only valid for raw video formats)
 88 |    *
 89 |    * @method FfmpegCommand#inputFps
 90 |    * @category Input
 91 |    * @aliases withInputFps,withInputFPS,withFpsInput,withFPSInput,inputFPS,inputFps,fpsInput
 92 |    *
 93 |    * @param {Number} fps input FPS
 94 |    * @return FfmpegCommand
 95 |    */
 96 |   proto.withInputFps =
 97 |   proto.withInputFPS =
 98 |   proto.withFpsInput =
 99 |   proto.withFPSInput =
100 |   proto.inputFPS =
101 |   proto.inputFps =
102 |   proto.fpsInput =
103 |   proto.FPSInput = function(fps) {
104 |     if (!this._currentInput) {
105 |       throw new Error('No input specified');
106 |     }
107 | 
108 |     this._currentInput.options('-r', fps);
109 |     return this;
110 |   };
111 | 
112 | 
113 |   /**
114 |    * Use native framerate for the last specified input
115 |    *
116 |    * @method FfmpegCommand#native
117 |    * @category Input
118 |    * @aliases nativeFramerate,withNativeFramerate
119 |    *
120 |    * @return FfmmegCommand
121 |    */
122 |   proto.nativeFramerate =
123 |   proto.withNativeFramerate =
124 |   proto.native = function() {
125 |     if (!this._currentInput) {
126 |       throw new Error('No input specified');
127 |     }
128 | 
129 |     this._currentInput.options('-re');
130 |     return this;
131 |   };
132 | 
133 | 
134 |   /**
135 |    * Specify input seek time for the last specified input
136 |    *
137 |    * @method FfmpegCommand#seekInput
138 |    * @category Input
139 |    * @aliases setStartTime,seekTo
140 |    *
141 |    * @param {String|Number} seek seek time in seconds or as a '[hh:[mm:]]ss[.xxx]' string
142 |    * @return FfmpegCommand
143 |    */
144 |   proto.setStartTime =
145 |   proto.seekInput = function(seek) {
146 |     if (!this._currentInput) {
147 |       throw new Error('No input specified');
148 |     }
149 | 
150 |     this._currentInput.options('-ss', seek);
151 | 
152 |     return this;
153 |   };
154 | 
155 | 
156 |   /**
157 |    * Loop over the last specified input
158 |    *
159 |    * @method FfmpegCommand#loop
160 |    * @category Input
161 |    *
162 |    * @param {String|Number} [duration] loop duration in seconds or as a '[[hh:]mm:]ss[.xxx]' string
163 |    * @return FfmpegCommand
164 |    */
165 |   proto.loop = function(duration) {
166 |     if (!this._currentInput) {
167 |       throw new Error('No input specified');
168 |     }
169 | 
170 |     this._currentInput.options('-loop', '1');
171 | 
172 |     if (typeof duration !== 'undefined') {
173 |       this.duration(duration);
174 |     }
175 | 
176 |     return this;
177 |   };
178 | };
179 | 


--------------------------------------------------------------------------------
/lib/options/misc.js:
--------------------------------------------------------------------------------
 1 | /*jshint node:true*/
 2 | 'use strict';
 3 | 
 4 | var path = require('path');
 5 | 
 6 | /*
 7 |  *! Miscellaneous methods
 8 |  */
 9 | 
10 | module.exports = function(proto) {
11 |   /**
12 |    * Use preset
13 |    *
14 |    * @method FfmpegCommand#preset
15 |    * @category Miscellaneous
16 |    * @aliases usingPreset
17 |    *
18 |    * @param {String|Function} preset preset name or preset function
19 |    */
20 |   proto.usingPreset =
21 |   proto.preset = function(preset) {
22 |     if (typeof preset === 'function') {
23 |       preset(this);
24 |     } else {
25 |       try {
26 |         var modulePath = path.join(this.options.presets, preset);
27 |         var module = require(modulePath);
28 | 
29 |         if (typeof module.load === 'function') {
30 |           module.load(this);
31 |         } else {
32 |           throw new Error('preset ' + modulePath + ' has no load() function');
33 |         }
34 |       } catch (err) {
35 |         throw new Error('preset ' + modulePath + ' could not be loaded: ' + err.message);
36 |       }
37 |     }
38 | 
39 |     return this;
40 |   };
41 | };
42 | 


--------------------------------------------------------------------------------
/lib/options/output.js:
--------------------------------------------------------------------------------
  1 | /*jshint node:true*/
  2 | 'use strict';
  3 | 
  4 | var utils = require('../utils');
  5 | 
  6 | 
  7 | /*
  8 |  *! Output-related methods
  9 |  */
 10 | 
 11 | module.exports = function(proto) {
 12 |   /**
 13 |    * Add output
 14 |    *
 15 |    * @method FfmpegCommand#output
 16 |    * @category Output
 17 |    * @aliases addOutput
 18 |    *
 19 |    * @param {String|Writable} target target file path or writable stream
 20 |    * @param {Object} [pipeopts={}] pipe options (only applies to streams)
 21 |    * @return FfmpegCommand
 22 |    */
 23 |   proto.addOutput =
 24 |   proto.output = function(target, pipeopts) {
 25 |     var isFile = false;
 26 | 
 27 |     if (!target && this._currentOutput) {
 28 |       // No target is only allowed when called from constructor
 29 |       throw new Error('Invalid output');
 30 |     }
 31 | 
 32 |     if (target && typeof target !== 'string') {
 33 |       if (!('writable' in target) || !(target.writable)) {
 34 |         throw new Error('Invalid output');
 35 |       }
 36 |     } else if (typeof target === 'string') {
 37 |       var protocol = target.match(/^([a-z]{2,}):/i);
 38 |       isFile = !protocol || protocol[0] === 'file';
 39 |     }
 40 | 
 41 |     if (target && !('target' in this._currentOutput)) {
 42 |       // For backwards compatibility, set target for first output
 43 |       this._currentOutput.target = target;
 44 |       this._currentOutput.isFile = isFile;
 45 |       this._currentOutput.pipeopts = pipeopts || {};
 46 |     } else {
 47 |       if (target && typeof target !== 'string') {
 48 |         var hasOutputStream = this._outputs.some(function(output) {
 49 |           return typeof output.target !== 'string';
 50 |         });
 51 | 
 52 |         if (hasOutputStream) {
 53 |           throw new Error('Only one output stream is supported');
 54 |         }
 55 |       }
 56 | 
 57 |       this._outputs.push(this._currentOutput = {
 58 |         target: target,
 59 |         isFile: isFile,
 60 |         flags: {},
 61 |         pipeopts: pipeopts || {}
 62 |       });
 63 | 
 64 |       var self = this;
 65 |       ['audio', 'audioFilters', 'video', 'videoFilters', 'sizeFilters', 'options'].forEach(function(key) {
 66 |         self._currentOutput[key] = utils.args();
 67 |       });
 68 | 
 69 |       if (!target) {
 70 |         // Call from constructor: remove target key
 71 |         delete this._currentOutput.target;
 72 |       }
 73 |     }
 74 | 
 75 |     return this;
 76 |   };
 77 | 
 78 | 
 79 |   /**
 80 |    * Specify output seek time
 81 |    *
 82 |    * @method FfmpegCommand#seek
 83 |    * @category Input
 84 |    * @aliases seekOutput
 85 |    *
 86 |    * @param {String|Number} seek seek time in seconds or as a '[hh:[mm:]]ss[.xxx]' string
 87 |    * @return FfmpegCommand
 88 |    */
 89 |   proto.seekOutput =
 90 |   proto.seek = function(seek) {
 91 |     this._currentOutput.options('-ss', seek);
 92 |     return this;
 93 |   };
 94 | 
 95 | 
 96 |   /**
 97 |    * Set output duration
 98 |    *
 99 |    * @method FfmpegCommand#duration
100 |    * @category Output
101 |    * @aliases withDuration,setDuration
102 |    *
103 |    * @param {String|Number} duration duration in seconds or as a '[[hh:]mm:]ss[.xxx]' string
104 |    * @return FfmpegCommand
105 |    */
106 |   proto.withDuration =
107 |   proto.setDuration =
108 |   proto.duration = function(duration) {
109 |     this._currentOutput.options('-t', duration);
110 |     return this;
111 |   };
112 | 
113 | 
114 |   /**
115 |    * Set output format
116 |    *
117 |    * @method FfmpegCommand#format
118 |    * @category Output
119 |    * @aliases toFormat,withOutputFormat,outputFormat
120 |    *
121 |    * @param {String} format output format name
122 |    * @return FfmpegCommand
123 |    */
124 |   proto.toFormat =
125 |   proto.withOutputFormat =
126 |   proto.outputFormat =
127 |   proto.format = function(format) {
128 |     this._currentOutput.options('-f', format);
129 |     return this;
130 |   };
131 | 
132 | 
133 |   /**
134 |    * Add stream mapping to output
135 |    *
136 |    * @method FfmpegCommand#map
137 |    * @category Output
138 |    *
139 |    * @param {String} spec stream specification string, with optional square brackets
140 |    * @return FfmpegCommand
141 |    */
142 |   proto.map = function(spec) {
143 |     this._currentOutput.options('-map', spec.replace(utils.streamRegexp, '[$1]'));
144 |     return this;
145 |   };
146 | 
147 | 
148 |   /**
149 |    * Run flvtool2/flvmeta on output
150 |    *
151 |    * @method FfmpegCommand#flvmeta
152 |    * @category Output
153 |    * @aliases updateFlvMetadata
154 |    *
155 |    * @return FfmpegCommand
156 |    */
157 |   proto.updateFlvMetadata =
158 |   proto.flvmeta = function() {
159 |     this._currentOutput.flags.flvmeta = true;
160 |     return this;
161 |   };
162 | };
163 | 


--------------------------------------------------------------------------------
/lib/options/video.js:
--------------------------------------------------------------------------------
  1 | /*jshint node:true*/
  2 | 'use strict';
  3 | 
  4 | var utils = require('../utils');
  5 | 
  6 | 
  7 | /*
  8 |  *! Video-related methods
  9 |  */
 10 | 
 11 | module.exports = function(proto) {
 12 |   /**
 13 |    * Disable video in the output
 14 |    *
 15 |    * @method FfmpegCommand#noVideo
 16 |    * @category Video
 17 |    * @aliases withNoVideo
 18 |    *
 19 |    * @return FfmpegCommand
 20 |    */
 21 |   proto.withNoVideo =
 22 |   proto.noVideo = function() {
 23 |     this._currentOutput.video.clear();
 24 |     this._currentOutput.videoFilters.clear();
 25 |     this._currentOutput.video('-vn');
 26 | 
 27 |     return this;
 28 |   };
 29 | 
 30 | 
 31 |   /**
 32 |    * Specify video codec
 33 |    *
 34 |    * @method FfmpegCommand#videoCodec
 35 |    * @category Video
 36 |    * @aliases withVideoCodec
 37 |    *
 38 |    * @param {String} codec video codec name
 39 |    * @return FfmpegCommand
 40 |    */
 41 |   proto.withVideoCodec =
 42 |   proto.videoCodec = function(codec) {
 43 |     this._currentOutput.video('-vcodec', codec);
 44 |     return this;
 45 |   };
 46 | 
 47 | 
 48 |   /**
 49 |    * Specify video bitrate
 50 |    *
 51 |    * @method FfmpegCommand#videoBitrate
 52 |    * @category Video
 53 |    * @aliases withVideoBitrate
 54 |    *
 55 |    * @param {String|Number} bitrate video bitrate in kbps (with an optional 'k' suffix)
 56 |    * @param {Boolean} [constant=false] enforce constant bitrate
 57 |    * @return FfmpegCommand
 58 |    */
 59 |   proto.withVideoBitrate =
 60 |   proto.videoBitrate = function(bitrate, constant) {
 61 |     bitrate = ('' + bitrate).replace(/k?$/, 'k');
 62 | 
 63 |     this._currentOutput.video('-b:v', bitrate);
 64 |     if (constant) {
 65 |       this._currentOutput.video(
 66 |         '-maxrate', bitrate,
 67 |         '-minrate', bitrate,
 68 |         '-bufsize', '3M'
 69 |       );
 70 |     }
 71 | 
 72 |     return this;
 73 |   };
 74 | 
 75 | 
 76 |   /**
 77 |    * Specify custom video filter(s)
 78 |    *
 79 |    * Can be called both with one or many filters, or a filter array.
 80 |    *
 81 |    * @example
 82 |    * command.videoFilters('filter1');
 83 |    *
 84 |    * @example
 85 |    * command.videoFilters('filter1', 'filter2=param1=value1:param2=value2');
 86 |    *
 87 |    * @example
 88 |    * command.videoFilters(['filter1', 'filter2']);
 89 |    *
 90 |    * @example
 91 |    * command.videoFilters([
 92 |    *   {
 93 |    *     filter: 'filter1'
 94 |    *   },
 95 |    *   {
 96 |    *     filter: 'filter2',
 97 |    *     options: 'param=value:param=value'
 98 |    *   }
 99 |    * ]);
100 |    *
101 |    * @example
102 |    * command.videoFilters(
103 |    *   {
104 |    *     filter: 'filter1',
105 |    *     options: ['value1', 'value2']
106 |    *   },
107 |    *   {
108 |    *     filter: 'filter2',
109 |    *     options: { param1: 'value1', param2: 'value2' }
110 |    *   }
111 |    * );
112 |    *
113 |    * @method FfmpegCommand#videoFilters
114 |    * @category Video
115 |    * @aliases withVideoFilter,withVideoFilters,videoFilter
116 |    *
117 |    * @param {...String|String[]|Object[]} filters video filter strings, string array or
118 |    *   filter specification array, each with the following properties:
119 |    * @param {String} filters.filter filter name
120 |    * @param {String|String[]|Object} [filters.options] filter option string, array, or object
121 |    * @return FfmpegCommand
122 |    */
123 |   proto.withVideoFilter =
124 |   proto.withVideoFilters =
125 |   proto.videoFilter =
126 |   proto.videoFilters = function(filters) {
127 |     if (arguments.length > 1) {
128 |       filters = [].slice.call(arguments);
129 |     }
130 | 
131 |     if (!Array.isArray(filters)) {
132 |       filters = [filters];
133 |     }
134 | 
135 |     this._currentOutput.videoFilters(utils.makeFilterStrings(filters));
136 | 
137 |     return this;
138 |   };
139 | 
140 | 
141 |   /**
142 |    * Specify output FPS
143 |    *
144 |    * @method FfmpegCommand#fps
145 |    * @category Video
146 |    * @aliases withOutputFps,withOutputFPS,withFpsOutput,withFPSOutput,withFps,withFPS,outputFPS,outputFps,fpsOutput,FPSOutput,FPS
147 |    *
148 |    * @param {Number} fps output FPS
149 |    * @return FfmpegCommand
150 |    */
151 |   proto.withOutputFps =
152 |   proto.withOutputFPS =
153 |   proto.withFpsOutput =
154 |   proto.withFPSOutput =
155 |   proto.withFps =
156 |   proto.withFPS =
157 |   proto.outputFPS =
158 |   proto.outputFps =
159 |   proto.fpsOutput =
160 |   proto.FPSOutput =
161 |   proto.fps =
162 |   proto.FPS = function(fps) {
163 |     this._currentOutput.video('-r', fps);
164 |     return this;
165 |   };
166 | 
167 | 
168 |   /**
169 |    * Only transcode a certain number of frames
170 |    *
171 |    * @method FfmpegCommand#frames
172 |    * @category Video
173 |    * @aliases takeFrames,withFrames
174 |    *
175 |    * @param {Number} frames frame count
176 |    * @return FfmpegCommand
177 |    */
178 |   proto.takeFrames =
179 |   proto.withFrames =
180 |   proto.frames = function(frames) {
181 |     this._currentOutput.video('-vframes', frames);
182 |     return this;
183 |   };
184 | };
185 | 


--------------------------------------------------------------------------------
/lib/presets/divx.js:
--------------------------------------------------------------------------------
 1 | /*jshint node:true */
 2 | 'use strict';
 3 | 
 4 | exports.load = function(ffmpeg) {
 5 |   ffmpeg
 6 |     .format('avi')
 7 |     .videoBitrate('1024k')
 8 |     .videoCodec('mpeg4')
 9 |     .size('720x?')
10 |     .audioBitrate('128k')
11 |     .audioChannels(2)
12 |     .audioCodec('libmp3lame')
13 |     .outputOptions(['-vtag DIVX']);
14 | };


--------------------------------------------------------------------------------
/lib/presets/flashvideo.js:
--------------------------------------------------------------------------------
 1 | /*jshint node:true */
 2 | 'use strict';
 3 | 
 4 | exports.load = function(ffmpeg) {
 5 |   ffmpeg
 6 |     .format('flv')
 7 |     .flvmeta()
 8 |     .size('320x?')
 9 |     .videoBitrate('512k')
10 |     .videoCodec('libx264')
11 |     .fps(24)
12 |     .audioBitrate('96k')
13 |     .audioCodec('aac')
14 |     .audioFrequency(22050)
15 |     .audioChannels(2);
16 | };
17 | 


--------------------------------------------------------------------------------
/lib/presets/podcast.js:
--------------------------------------------------------------------------------
 1 | /*jshint node:true */
 2 | 'use strict';
 3 | 
 4 | exports.load = function(ffmpeg) {
 5 |   ffmpeg
 6 |     .format('m4v')
 7 |     .videoBitrate('512k')
 8 |     .videoCodec('libx264')
 9 |     .size('320x176')
10 |     .audioBitrate('128k')
11 |     .audioCodec('aac')
12 |     .audioChannels(1)
13 |     .outputOptions(['-flags', '+loop', '-cmp', '+chroma', '-partitions','+parti4x4+partp8x8+partb8x8', '-flags2',
14 |       '+mixed_refs', '-me_method umh', '-subq 5', '-bufsize 2M', '-rc_eq \'blurCplx^(1-qComp)\'',
15 |       '-qcomp 0.6', '-qmin 10', '-qmax 51', '-qdiff 4', '-level 13' ]);
16 | };
17 | 


--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "fluent-ffmpeg",
 3 |   "version": "2.1.3",
 4 |   "description": "A fluent API to FFMPEG (http://www.ffmpeg.org)",
 5 |   "keywords": [
 6 |     "ffmpeg"
 7 |   ],
 8 |   "author": "Stefan Schaermeli <schaermu@gmail.com>",
 9 |   "contributors": [
10 |     {
11 |       "name": "Felix Fichte",
12 |       "email": "spruce@space-ships.de"
13 |     }
14 |   ],
15 |   "license": "MIT",
16 |   "bugs": {
17 |     "mail": "schaermu@gmail.com",
18 |     "url": "http://github.com/fluent-ffmpeg/node-fluent-ffmpeg/issues"
19 |   },
20 |   "repository": "git://github.com/fluent-ffmpeg/node-fluent-ffmpeg.git",
21 |   "devDependencies": {
22 |     "jsdoc": "^4.0.0",
23 |     "mocha": "^10.0.0",
24 |     "nyc": "^15.1.0",
25 |     "should": "^13.0.0"
26 |   },
27 |   "dependencies": {
28 |     "async": "^0.2.9",
29 |     "which": "^1.1.1"
30 |   },
31 |   "engines": {
32 |     "node": ">=18"
33 |   },
34 |   "main": "index",
35 |   "scripts": {
36 |     "test": "NODE_ENV=test nyc mocha --require should --reporter spec",
37 |     "coverage": "nyc report --reporter=lcov"
38 |   }
39 | }
40 | 


--------------------------------------------------------------------------------
/test/aliases.test.js:
--------------------------------------------------------------------------------
 1 | /*jshint node:true*/
 2 | /*global describe,it*/
 3 | 'use strict';
 4 | 
 5 | var Ffmpeg = require('../index');
 6 | 
 7 | var aliases = {
 8 |   audio: {
 9 |     withNoAudio: ['noAudio'],
10 |     withAudioCodec: ['audioCodec'],
11 |     withAudioBitrate: ['audioBitrate'],
12 |     withAudioChannels: ['audioChannels'],
13 |     withAudioFrequency: ['audioFrequency'],
14 |     withAudioQuality: ['audioQuality'],
15 |     withAudioFilter: ['withAudioFilters','audioFilter','audioFilters']
16 |   },
17 | 
18 |   custom: {
19 |     addInputOption: ['addInputOptions','withInputOption','withInputOptions','inputOption','inputOptions'],
20 |     addOutputOption: ['addOutputOptions','addOption','addOptions','withOutputOption','withOutputOptions','withOption','withOptions','outputOption','outputOptions'],
21 |     complexFilter: ['filterGraph']
22 |   },
23 | 
24 |   inputs: {
25 |     addInput: ['input','mergeAdd'],
26 |     fromFormat: ['withInputFormat','inputFormat'],
27 |     withInputFps: ['withInputFPS','withFpsInput','withFPSInput','inputFPS','inputFps','fpsInput','FPSInput'],
28 |     native: ['withNativeFramerate','nativeFramerate'],
29 |     setStartTime: ['seekInput']
30 |   },
31 | 
32 |   misc: {
33 |     usingPreset: ['preset']
34 |   },
35 | 
36 |   output: {
37 |     addOutput: ['output'],
38 |     withDuration: ['duration','setDuration'],
39 |     toFormat: ['withOutputFormat','outputFormat','format'],
40 |     seek: ['seekOutput'],
41 |     updateFlvMetadata: ['flvmeta']
42 |   },
43 | 
44 |   video: {
45 |     withNoVideo: ['noVideo'],
46 |     withVideoCodec: ['videoCodec'],
47 |     withVideoBitrate: ['videoBitrate'],
48 |     withVideoFilter: ['withVideoFilters','videoFilter','videoFilters'],
49 |     withOutputFps: ['withOutputFPS','withFpsOutput','withFPSOutput','withFps','withFPS','outputFPS','outputFps','fpsOutput','FPSOutput','fps','FPS'],
50 |     takeFrames: ['withFrames','frames']
51 |   },
52 | 
53 |   videosize: {
54 |     keepPixelAspect: ['keepDisplayAspect','keepDisplayAspectRatio','keepDAR'],
55 |     withSize: ['setSize', 'size'],
56 |     withAspect: ['withAspectRatio','setAspect','setAspectRatio','aspect','aspectRatio'],
57 |     applyAutopadding: ['applyAutoPadding','applyAutopad','applyAutoPad','withAutopadding','withAutoPadding','withAutopad','withAutoPad','autoPad','autopad']
58 |   },
59 | 
60 |   processing: {
61 |     saveToFile: ['save'],
62 |     writeToStream: ['stream', 'pipe'],
63 |     run: ['exec', 'execute'],
64 |     concat: ['concatenate', 'mergeToFile'],
65 |     screenshots: ['screenshot', 'thumbnails', 'thumbnail', 'takeScreenshots']
66 |   }
67 | };
68 | 
69 | describe('Method aliases', function() {
70 |   Object.keys(aliases).forEach(function(category) {
71 |     describe(category + ' methods', function() {
72 |       Object.keys(aliases[category]).forEach(function(method) {
73 |         describe('FfmpegCommand#' + method, function() {
74 |           aliases[category][method].forEach(function(alias) {
75 |             it('should have a \'' + alias + '\' alias', function() {
76 |               var ff = new Ffmpeg();
77 | 
78 |               (typeof ff[method]).should.equal('function');
79 |               ff[method].should.equal(ff[alias]);
80 |             });
81 |           });
82 |         });
83 |       });
84 |     });
85 |   });
86 | });


--------------------------------------------------------------------------------
/test/assets/ffserver.conf:
--------------------------------------------------------------------------------
 1 | Port 8090
 2 | BindAddress 127.0.0.1
 3 | RTSPPort 5540
 4 | RTSPBindAddress 127.0.0.1
 5 | MaxHTTPConnections 1000
 6 | MaxClients 10
 7 | MaxBandwidth 1000000
 8 | 
 9 | <Stream test.mpg>
10 | ReadOnlyFile teststream.ffm
11 | ACL allow 127.0.0.1
12 | Format mpegts
13 | AudioCodec mp2
14 | VideoCodec libx264
15 | </Stream>
16 | 
17 | <Stream test-rtp.mpg>
18 | ReadOnlyFile teststream.ffm
19 | ACL allow 127.0.0.1
20 | Format rtp
21 | </Stream>
22 | 
23 | <Stream input.mpg>
24 | File testinput.ffm
25 | ACL allow 127.0.0.1
26 | Format mpegts
27 | AudioCodec mp2
28 | VideoCodec libx264
29 | </Stream>
30 | 


--------------------------------------------------------------------------------
/test/assets/presets/custompreset.js:
--------------------------------------------------------------------------------
 1 | exports.load = function(ffmpeg) {
 2 |   ffmpeg
 3 |     .toFormat('m4v')
 4 |     .withVideoBitrate('512k')
 5 |     .withVideoCodec('libx264')
 6 |     .withSize('320x176')
 7 |     .withAudioBitrate('128k')
 8 |     .withAudioCodec('aac')
 9 |     .withAudioChannels(1)
10 |     .addOptions(['-flags', '+loop', '-cmp', '+chroma', '-partitions','+parti4x4+partp8x8+partb8x8', '-flags2',
11 |       '+mixed_refs', '-me_method umh', '-subq 5', '-bufsize 2M', '-rc_eq \'blurCplx^(1-qComp)\'',
12 |       '-qcomp 0.6', '-qmin 10', '-qmax 51', '-qdiff 4', '-level 13' ]);
13 |   return ffmpeg;
14 | };
15 | 


--------------------------------------------------------------------------------
/test/assets/te[s]t_ video ' _ .flv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluent-ffmpeg/node-fluent-ffmpeg/7a701f560f6cd0f152cdef22c8a03132c56afc7b/test/assets/te[s]t_ video ' _ .flv


--------------------------------------------------------------------------------
/test/assets/testaudio-one.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluent-ffmpeg/node-fluent-ffmpeg/7a701f560f6cd0f152cdef22c8a03132c56afc7b/test/assets/testaudio-one.wav


--------------------------------------------------------------------------------
/test/assets/testaudio-three.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluent-ffmpeg/node-fluent-ffmpeg/7a701f560f6cd0f152cdef22c8a03132c56afc7b/test/assets/testaudio-three.wav


--------------------------------------------------------------------------------
/test/assets/testaudio-two.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluent-ffmpeg/node-fluent-ffmpeg/7a701f560f6cd0f152cdef22c8a03132c56afc7b/test/assets/testaudio-two.wav


--------------------------------------------------------------------------------
/test/assets/teststream.ffm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluent-ffmpeg/node-fluent-ffmpeg/7a701f560f6cd0f152cdef22c8a03132c56afc7b/test/assets/teststream.ffm


--------------------------------------------------------------------------------
/test/assets/testvideo-169.avi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluent-ffmpeg/node-fluent-ffmpeg/7a701f560f6cd0f152cdef22c8a03132c56afc7b/test/assets/testvideo-169.avi


--------------------------------------------------------------------------------
/test/assets/testvideo-43.avi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluent-ffmpeg/node-fluent-ffmpeg/7a701f560f6cd0f152cdef22c8a03132c56afc7b/test/assets/testvideo-43.avi


--------------------------------------------------------------------------------
/test/assets/testvideo-5m.mpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/fluent-ffmpeg/node-fluent-ffmpeg/7a701f560f6cd0f152cdef22c8a03132c56afc7b/test/assets/testvideo-5m.mpg


--------------------------------------------------------------------------------
/test/helpers.js:
--------------------------------------------------------------------------------
 1 | /*jshint node:true*/
 2 | 'use strict';
 3 | 
 4 | var TestHelpers;
 5 | 
 6 | exports = module.exports = TestHelpers = {
 7 |   getFfmpegCheck: function() {
 8 |     var platform = require('os').platform();
 9 | 
10 |     if (!platform.match(/win(32|64)/)) {
11 |       // linux/mac, use which
12 |       return 'which ffmpeg';
13 |     } else {
14 |       // windows, use where (> windows server 2003 / windows 7)
15 |       return 'where /Q ffmpeg';
16 |     }
17 |   },
18 | 
19 |   logger: {
20 |     debug: function(arg) { if (process.env.FLUENTFFMPEG_COV !== '1') console.log('          [DEBUG] ' + arg); },
21 |     info: function(arg) { if (process.env.FLUENTFFMPEG_COV !== '1') console.log('          [INFO] ' + arg); },
22 |     warn: function(arg) { if (process.env.FLUENTFFMPEG_COV !== '1') console.log('          [WARN] ' + arg); },
23 |     error: function(arg) { if (process.env.FLUENTFFMPEG_COV !== '1') console.log('          [ERROR] ' + arg); }
24 |   },
25 | 
26 |   logArgError: function(err) {
27 |     if (err) {
28 |       console.log('got error: ' + (err.stack || err));
29 |       if (err.ffmpegOut) {
30 |         console.log('---stdout---');
31 |         console.log(err.ffmpegOut);
32 |       }
33 |       if (err.ffmpegErr) {
34 |         console.log('---stderr---');
35 |         console.log(err.ffmpegErr);
36 |       }
37 |       if (err.spawnErr) {
38 |         console.log('---spawn error---');
39 |         console.log(err.spawnErr.stack || err.spawnErr);
40 |       }
41 |     }
42 |   },
43 | 
44 |   logError: function(err, stdout, stderr) {
45 |     if (err) {
46 |       console.log('got error: ' + (err.stack || err));
47 |       if (err.ffmpegOut) {
48 |         console.log('---metadata stdout---');
49 |         console.log(err.ffmpegOut);
50 |       }
51 |       if (err.ffmpegErr) {
52 |         console.log('---metadata stderr---');
53 |         console.log(err.ffmpegErr);
54 |       }
55 |       if (err.spawnErr) {
56 |         console.log('---metadata spawn error---');
57 |         console.log(err.spawnErr.stack || err.spawnErr);
58 |       }
59 |       if (stdout) {
60 |         console.log('---stdout---');
61 |         console.log(stdout);
62 |       }
63 |       if (stderr) {
64 |         console.log('---stderr---');
65 |         console.log(stderr);
66 |       }
67 |     }
68 |   },
69 | 
70 |   logOutput: function(stdout, stderr) {
71 |     if (stdout) {
72 |       console.log('---stdout---');
73 |       console.log(stdout);
74 |     }
75 |     if (stderr) {
76 |       console.log('---stderr---');
77 |       console.log(stderr);
78 |     }
79 |   }
80 | };
81 | 


--------------------------------------------------------------------------------
/test/metadata.test.js:
--------------------------------------------------------------------------------
  1 | /*jshint node:true*/
  2 | /*global describe,it,before*/
  3 | 'use strict';
  4 | 
  5 | var Ffmpeg = require('../index'),
  6 |   path = require('path'),
  7 |   fs = require('fs'),
  8 |   Readable = require('stream').Readable,
  9 |   assert = require('assert'),
 10 |   exec = require('child_process').exec,
 11 |   testhelper = require('./helpers');
 12 | 
 13 | 
 14 | describe('Metadata', function() {
 15 |   before(function(done) {
 16 |     // check for ffmpeg installation
 17 |     this.testfile = path.join(__dirname, 'assets', 'testvideo-43.avi');
 18 | 
 19 |     var self = this;
 20 |     exec(testhelper.getFfmpegCheck(), function(err) {
 21 |       if (!err) {
 22 |         // check if file exists
 23 |         fs.exists(self.testfile, function(exists) {
 24 |           if (exists) {
 25 |             done();
 26 |           } else {
 27 |             done(new Error('test video file does not exist, check path (' + self.testfile + ')'));
 28 |           }
 29 |         });
 30 |       } else {
 31 |         done(new Error('cannot run test without ffmpeg installed, aborting test...'));
 32 |       }
 33 |     });
 34 |   });
 35 | 
 36 |   it('should provide an ffprobe entry point', function(done) {
 37 |     (typeof Ffmpeg.ffprobe).should.equal('function');
 38 |     done();
 39 |   });
 40 | 
 41 |   it('should return ffprobe data as an object', function(done) {
 42 |     Ffmpeg.ffprobe(this.testfile, function(err, data) {
 43 |       testhelper.logError(err);
 44 |       assert.ok(!err);
 45 | 
 46 |       (typeof data).should.equal('object');
 47 |       done();
 48 |     });
 49 |   });
 50 | 
 51 |   it('should provide ffprobe format information', function(done) {
 52 |     Ffmpeg.ffprobe(this.testfile, function(err, data) {
 53 |       testhelper.logError(err);
 54 |       assert.ok(!err);
 55 | 
 56 |       ('format' in data).should.equal(true);
 57 |       (typeof data.format).should.equal('object');
 58 |       Number(data.format.duration).should.equal(2);
 59 |       data.format.format_name.should.equal('avi');
 60 | 
 61 |       done();
 62 |     });
 63 |   });
 64 | 
 65 |   it('should provide ffprobe stream information', function(done) {
 66 |     Ffmpeg.ffprobe(this.testfile, function(err, data) {
 67 |       testhelper.logError(err);
 68 |       assert.ok(!err);
 69 | 
 70 |       ('streams' in data).should.equal(true);
 71 |       Array.isArray(data.streams).should.equal(true);
 72 |       data.streams.length.should.equal(1);
 73 |       data.streams[0].codec_type.should.equal('video');
 74 |       data.streams[0].codec_name.should.equal('mpeg4');
 75 |       Number(data.streams[0].width).should.equal(1024);
 76 | 
 77 |       done();
 78 |     });
 79 |   });
 80 | 
 81 |   it('should provide ffprobe stream information with units', function(done) {
 82 |     Ffmpeg.ffprobe(this.testfile, ['-unit'], function(err, data) {
 83 |       testhelper.logError(err);
 84 |       assert.ok(!err);
 85 | 
 86 |       ('streams' in data).should.equal(true);
 87 |       Array.isArray(data.streams).should.equal(true);
 88 |       data.streams.length.should.equal(1);
 89 |       data.streams[0].bit_rate.should.equal('322427 bit/s');
 90 |       done();
 91 |     });
 92 |   });
 93 | 
 94 |   it('should return ffprobe errors', function(done) {
 95 |     Ffmpeg.ffprobe('/path/to/missing/file', function(err) {
 96 |       assert.ok(!!err);
 97 |       done();
 98 |     });
 99 |   });
100 | 
101 |   it('should enable calling ffprobe on a command with an input file', function(done) {
102 |     new Ffmpeg({ source: this.testfile })
103 |       .ffprobe(function(err, data) {
104 |         testhelper.logError(err);
105 |         assert.ok(!err);
106 | 
107 |         (typeof data).should.equal('object');
108 |         ('format' in data).should.equal(true);
109 |         (typeof data.format).should.equal('object');
110 |         ('streams' in data).should.equal(true);
111 |         Array.isArray(data.streams).should.equal(true);
112 | 
113 |         done();
114 |       });
115 |   });
116 | 
117 |   it('should fail calling ffprobe on a command without input', function(done) {
118 |     new Ffmpeg().ffprobe(function(err) {
119 |       assert.ok(!!err);
120 |       err.message.should.match(/No input specified/);
121 |       done();
122 |     });
123 |   });
124 | 
125 |   it('should allow calling ffprobe on stream input', function(done) {
126 |     var stream = fs.createReadStream(this.testfile);
127 | 
128 |     new Ffmpeg()
129 |       .addInput(stream)
130 |       .ffprobe(function(err, data) {
131 |         assert.ok(!err);
132 |         data.streams.length.should.equal(1);
133 |         data.format.filename.should.equal('pipe:0');
134 |         done();
135 |       });
136 |   });
137 | });
138 | 


--------------------------------------------------------------------------------
/test/utils.test.js:
--------------------------------------------------------------------------------
  1 | /*jshint node:true*/
  2 | /*global describe,it*/
  3 | 'use strict';
  4 | 
  5 | var utils = require('../lib/utils');
  6 | 
  7 | describe('Utilities', function() {
  8 | 
  9 |   describe('Argument list helper', function() {
 10 |     it('Should add arguments to the list', function() {
 11 |       var args = utils.args();
 12 | 
 13 |       args('-one');
 14 |       args('-two', 'two-param');
 15 |       args('-three', 'three-param1', 'three-param2');
 16 |       args(['-four', 'four-param', '-five', '-five-param']);
 17 | 
 18 |       args.get().length.should.equal(10);
 19 |     });
 20 | 
 21 |     it('Should return the argument list', function() {
 22 |       var args = utils.args();
 23 | 
 24 |       args('-one');
 25 |       args('-two', 'two-param');
 26 |       args('-three', 'three-param1', 'three-param2');
 27 |       args(['-four', 'four-param', '-five', '-five-param']);
 28 | 
 29 |       var arr = args.get();
 30 |       Array.isArray(arr).should.equal(true);
 31 |       arr.length.should.equal(10);
 32 |       arr.indexOf('-three').should.equal(3);
 33 |       arr.indexOf('four-param').should.equal(7);
 34 |     });
 35 | 
 36 |     it('Should clear the argument list', function() {
 37 |       var args = utils.args();
 38 | 
 39 |       args('-one');
 40 |       args('-two', 'two-param');
 41 |       args('-three', 'three-param1', 'three-param2');
 42 |       args(['-four', 'four-param', '-five', '-five-param']);
 43 |       args.clear();
 44 | 
 45 |       args.get().length.should.equal(0);
 46 |     });
 47 | 
 48 |     it('Should retrieve arguments from the list', function() {
 49 |       var args = utils.args();
 50 | 
 51 |       args('-one');
 52 |       args('-two', 'two-param');
 53 |       args('-three', 'three-param1', 'three-param2');
 54 |       args(['-four', 'four-param', '-five', '-five-param']);
 55 | 
 56 |       var one = args.find('-one');
 57 |       Array.isArray(one).should.equal(true);
 58 |       one.length.should.equal(0);
 59 | 
 60 |       var two = args.find('-two', 1);
 61 |       Array.isArray(two).should.equal(true);
 62 |       two.length.should.equal(1);
 63 |       two[0].should.equal('two-param');
 64 | 
 65 |       var three = args.find('-three', 2);
 66 |       Array.isArray(three).should.equal(true);
 67 |       three.length.should.equal(2);
 68 |       three[0].should.equal('three-param1');
 69 |       three[1].should.equal('three-param2');
 70 | 
 71 |       var nope = args.find('-nope', 2);
 72 |       (typeof nope).should.equal('undefined');
 73 |     });
 74 | 
 75 |     it('Should remove arguments from the list', function() {
 76 |       var args = utils.args();
 77 | 
 78 |       args('-one');
 79 |       args('-two', 'two-param');
 80 |       args('-three', 'three-param1', 'three-param2');
 81 |       args(['-four', 'four-param', '-five', '-five-param']);
 82 | 
 83 |       args.remove('-four', 1);
 84 |       var arr = args.get();
 85 |       arr.length.should.equal(8);
 86 |       arr[5].should.equal('three-param2');
 87 |       arr[6].should.equal('-five');
 88 | 
 89 |       args.remove('-one');
 90 |       arr = args.get();
 91 |       arr.length.should.equal(7);
 92 |       arr[0].should.equal('-two');
 93 | 
 94 |       args.remove('-three', 2);
 95 |       arr = args.get();
 96 |       arr.length.should.equal(4);
 97 |       arr[1].should.equal('two-param');
 98 |       arr[2].should.equal('-five');
 99 |     });
100 |   });
101 | 
102 |   describe('timemarkToSeconds', function() {
103 |     it('should correctly convert a simple timestamp', function() {
104 |       utils.timemarkToSeconds('00:02:00.00').should.be.equal(120);
105 |     });
106 |     it('should correctly convert a complex timestamp', function() {
107 |       utils.timemarkToSeconds('00:08:09.10').should.be.equal(489.1);
108 |     });
109 |     it('should correclty convert a simple float string timestamp', function() {
110 |       utils.timemarkToSeconds('132.44').should.be.equal(132.44);
111 |     });
112 |     it('should correclty convert a simple float timestamp', function() {
113 |       utils.timemarkToSeconds(132.44).should.be.equal(132.44);
114 |     });
115 |   });
116 | 
117 |   describe('Lines ring buffer', function() {
118 |     it('should append lines', function() {
119 |       var ring = utils.linesRing(100);
120 |       ring.append('foo\nbar\nbaz\n');
121 |       ring.append('foo\nbar\nbaz\n');
122 |       ring.get().should.equal('foo\nbar\nbaz\nfoo\nbar\nbaz\n');
123 |     });
124 | 
125 |     it('should append partial lines', function() {
126 |       var ring = utils.linesRing(100);
127 |       ring.append('foo');
128 |       ring.append('bar\nbaz');
129 |       ring.append('moo');
130 |       ring.get().should.equal('foobar\nbazmoo');
131 |     });
132 | 
133 |     it('should call line callbacks', function() {
134 |       var lines = [];
135 |       function cb(l) {
136 |         lines.push(l);
137 |       }
138 | 
139 |       var lines2 = [];
140 |       function cb2(l) {
141 |         lines2.push(l);
142 |       }
143 | 
144 |       var ring = utils.linesRing(100);
145 |       ring.callback(cb);
146 |       ring.callback(cb2);
147 | 
148 |       ring.append('foo\nbar\nbaz');
149 |       lines.length.should.equal(2);
150 |       lines[0].should.equal('foo');
151 |       lines[1].should.equal('bar');
152 | 
153 |       lines2.length.should.equal(2);
154 |       lines2[0].should.equal('foo');
155 |       lines2[1].should.equal('bar');
156 | 
157 |       ring.append('moo\nmeow\n');
158 |       lines.length.should.equal(4);
159 |       lines[2].should.equal('bazmoo');
160 |       lines[3].should.equal('meow');
161 | 
162 |       lines2.length.should.equal(4);
163 |       lines2[2].should.equal('bazmoo');
164 |       lines2[3].should.equal('meow');
165 |     });
166 | 
167 |     it('should close correctly', function() {
168 |       var lines = [];
169 |       function cb(l) {
170 |         lines.push(l);
171 |       }
172 | 
173 |       var ring = utils.linesRing(100);
174 |       ring.callback(cb);
175 | 
176 |       ring.append('foo\nbar\nbaz');
177 |       lines.length.should.equal(2);
178 |       lines[0].should.equal('foo');
179 |       lines[1].should.equal('bar');
180 | 
181 |       ring.close();
182 |       lines.length.should.equal(3);
183 |       lines[2].should.equal('baz');
184 | 
185 |       ring.append('moo\nmeow\n');
186 |       lines.length.should.equal(3);
187 |       ring.get().should.equal('foo\nbar\nbaz');
188 |     });
189 | 
190 |     it('should limit lines', function() {
191 |       var ring = utils.linesRing(2);
192 |       ring.append('foo\nbar\nbaz');
193 |       ring.get().should.equal('bar\nbaz');
194 |       ring.append('foo\nbar');
195 |       ring.get().should.equal('bazfoo\nbar');
196 |     });
197 | 
198 |     it('should allow unlimited lines', function() {
199 |       var ring = utils.linesRing(0);
200 |       ring.append('foo\nbar\nbaz');
201 |       ring.get().should.equal('foo\nbar\nbaz');
202 |       ring.append('foo\nbar');
203 |       ring.get().should.equal('foo\nbar\nbazfoo\nbar');
204 |     });
205 |   });
206 | });
207 | 


--------------------------------------------------------------------------------
/tools/jsdoc-aliases.js:
--------------------------------------------------------------------------------
 1 | /*jshint node:true*/
 2 | 'use strict';
 3 | 
 4 | function createAlias(doclet, alias) {
 5 | 	var clone = {};
 6 | 
 7 | 	Object.keys(doclet).forEach(function(key) {
 8 | 		clone[key] = doclet[key];
 9 | 	});
10 | 
11 | 	if (alias.indexOf('#') !== -1) {
12 | 		clone.longname = alias;
13 | 		clone.memberof = alias.split('#')[0];
14 | 		clone.name = alias.split('#')[1];
15 | 	} else {
16 | 		clone.longname = clone.memberof + '#' + alias;
17 | 		clone.name = alias;
18 | 	}
19 | 
20 | 	delete clone.returns;
21 | 	delete clone.examples;
22 | 	delete clone.meta;
23 | 	delete clone.aliases;
24 | 
25 | 	clone.isAlias = true;
26 | 	clone.description = 'Alias for <a href="#' + doclet.name + '">' + doclet.longname + '</a>';
27 | 
28 | 	return clone;
29 | }
30 | 
31 | exports.handlers = {
32 | 	parseComplete: function(e) {
33 | 		var doclets = e.doclets.slice();
34 | 
35 | 		doclets.forEach(function(doclet) {
36 | 			// Duplicate doclets with aliases
37 | 			if (doclet.aliases) {
38 | 				doclet.aliases.forEach(function(alias) {
39 | 					e.doclets.push(createAlias(doclet, alias));
40 | 				});
41 | 			}
42 | 		});
43 | 	}
44 | };
45 | 
46 | exports.defineTags = function(dict) {
47 | 	dict.defineTag('aliases', {
48 | 		onTagged: function(doclet, tag) {
49 | 			doclet.aliases = tag.text.split(',');
50 | 		}
51 | 	});
52 | 
53 | 	dict.defineTag('category', {
54 | 		onTagged: function(doclet, tag) {
55 | 			doclet.category = tag.text;
56 | 		}
57 | 	});
58 | };


--------------------------------------------------------------------------------
/tools/jsdoc-conf.json:
--------------------------------------------------------------------------------
 1 | {
 2 | 	"opts": {
 3 | 		"recurse": true,
 4 | 		"verbose": true,
 5 | 		"destination": "doc",
 6 | 		"template": "tools/jsdoc-template"
 7 | 	},
 8 | 
 9 | 	"source": {
10 | 		"include": ["README.md", "lib"],
11 | 		"excludePattern": "lib\/presets"
12 | 	},
13 | 
14 | 	"plugins": [
15 | 		"plugins/markdown",
16 | 		"tools/jsdoc-aliases.js"
17 | 	],
18 | 
19 | 	"markdown": {
20 | 		"parser": "evilstreak",
21 | 		"dialect": "Markuru"
22 | 	}
23 | }


--------------------------------------------------------------------------------
/tools/jsdoc-template/README.md:
--------------------------------------------------------------------------------
1 | The default template for JSDoc 3 uses: [the Taffy Database library](http://taffydb.com/) and the [Underscore Template library](http://documentcloud.github.com/underscore/#template).
2 | 
3 | Updated for node-fluent-ffmpeg to handle @aliases and @category tags.


--------------------------------------------------------------------------------
/tools/jsdoc-template/static/scripts/linenumber.js:
--------------------------------------------------------------------------------
 1 | /*global document */
 2 | (function() {
 3 |     var source = document.getElementsByClassName('prettyprint source linenums');
 4 |     var i = 0;
 5 |     var lineNumber = 0;
 6 |     var lineId;
 7 |     var lines;
 8 |     var totalLines;
 9 |     var anchorHash;
10 | 
11 |     if (source && source[0]) {
12 |         anchorHash = document.location.hash.substring(1);
13 |         lines = source[0].getElementsByTagName('li');
14 |         totalLines = lines.length;
15 | 
16 |         for (; i < totalLines; i++) {
17 |             lineNumber++;
18 |             lineId = 'line' + lineNumber;
19 |             lines[i].id = lineId;
20 |             if (lineId === anchorHash) {
21 |                 lines[i].className += ' selected';
22 |             }
23 |         }
24 |     }
25 | })();
26 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/static/scripts/prettify/lang-css.js:
--------------------------------------------------------------------------------
1 | PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n"]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
2 | /^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);
3 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/static/styles/jsdoc-default.css:
--------------------------------------------------------------------------------
  1 | html
  2 | {
  3 |     overflow: auto;
  4 |     background-color: #fff;
  5 | }
  6 | 
  7 | body
  8 | {
  9 |     font: 14px "DejaVu Sans Condensed", "Liberation Sans", "Nimbus Sans L", Tahoma, Geneva, "Helvetica Neue", Helvetica, Arial, sans-serif;
 10 |     line-height: 130%;
 11 |     color: #000;
 12 |     background-color: #fff;
 13 | }
 14 | 
 15 | a {
 16 |     color: #444;
 17 | }
 18 | 
 19 | a:visited {
 20 |     color: #444;
 21 | }
 22 | 
 23 | a:active {
 24 |     color: #444;
 25 | }
 26 | 
 27 | header
 28 | {
 29 |     display: block;
 30 |     padding: 6px 4px;
 31 | }
 32 | 
 33 | .class-description {
 34 |     font-style: italic;
 35 |     font-family: Palatino, 'Palatino Linotype', serif;
 36 |     font-size: 130%;
 37 |     line-height: 140%;
 38 |     margin-bottom: 1em;
 39 |     margin-top: 1em;
 40 | }
 41 | 
 42 | #main {
 43 |     float: left;
 44 |     width: 100%;
 45 | }
 46 | 
 47 | section
 48 | {
 49 |     display: block;
 50 | 
 51 |     background-color: #fff;
 52 |     padding: 12px 24px;
 53 |     border-bottom: 1px solid #ccc;
 54 |     margin-right: 240px;
 55 | }
 56 | 
 57 | .variation {
 58 |     display: none;
 59 | }
 60 | 
 61 | .optional:after {
 62 |     content: "opt";
 63 |     font-size: 60%;
 64 |     color: #aaa;
 65 |     font-style: italic;
 66 |     font-weight: lighter;
 67 | }
 68 | 
 69 | nav
 70 | {
 71 |     display: block;
 72 |     width: 220px;
 73 |     border-left: 1px solid #ccc;
 74 |     padding-left: 9px;
 75 | 
 76 |     position: fixed;
 77 |     top: 28px;
 78 |     right: 0;
 79 | }
 80 | 
 81 | nav ul {
 82 |     font-family: 'Lucida Grande', 'Lucida Sans Unicode', arial, sans-serif;
 83 |     font-size: 100%;
 84 |     line-height: 17px;
 85 |     padding:0;
 86 |     margin:0;
 87 |     list-style-type:none;
 88 | }
 89 | 
 90 | nav ul ul {
 91 |     margin-left: 10px;
 92 |     font-size: 90%;
 93 | }
 94 | 
 95 | nav h2 a, nav h2 a:visited {
 96 |     color: #526492;
 97 |     text-decoration: none;
 98 | }
 99 | 
100 | nav h3 {
101 |     margin-top: 12px;
102 | }
103 | 
104 | nav li {
105 |     margin-top: 2px;
106 | }
107 | 
108 | nav a {
109 |     color: #5C5954;
110 | }
111 | 
112 | nav a:visited {
113 |     color: #5C5954;
114 | }
115 | 
116 | nav a:active {
117 |     color: #5C5954;
118 | }
119 | 
120 | footer {
121 |     display: block;
122 |     padding: 6px;
123 |     margin-top: 12px;
124 |     font-style: italic;
125 |     font-size: 90%;
126 | }
127 | 
128 | h1
129 | {
130 |     font-size: 200%;
131 |     font-weight: bold;
132 |     letter-spacing: -0.01em;
133 |     margin: 6px 0 9px 0;
134 | }
135 | 
136 | h2
137 | {
138 |     font-size: 170%;
139 |     font-weight: bold;
140 |     letter-spacing: -0.01em;
141 |     margin: 50px 0 3px 0;
142 | }
143 | 
144 | nav > h2 {
145 |     margin-top: 6px;
146 | }
147 | 
148 | h3
149 | {
150 |     font-size: 150%;
151 |     font-weight: bold;
152 |     letter-spacing: -0.01em;
153 |     margin-top: 16px;
154 |     margin: 50px 0 3px 0;
155 | }
156 | 
157 | h4
158 | {
159 |     font-size: 130%;
160 |     font-weight: bold;
161 |     letter-spacing: -0.01em;
162 |     margin-top: 16px;
163 |     margin: 18px 0 3px 0;
164 |     color: #526492;
165 | }
166 | 
167 | h5, .container-overview .subsection-title
168 | {
169 |     font-size: 120%;
170 |     font-weight: bold;
171 |     letter-spacing: -0.01em;
172 |     margin: 8px 0 3px -16px;
173 | }
174 | 
175 | h6
176 | {
177 |     font-size: 100%;
178 |     letter-spacing: -0.01em;
179 |     margin: 6px 0 3px 0;
180 |     font-style: italic;
181 | }
182 | 
183 | article > dl, article > pre {
184 |     margin-left: 2em;
185 | }
186 | 
187 | .ancestors { color: #999; }
188 | .ancestors a
189 | {
190 |     color: #999 !important;
191 |     text-decoration: none;
192 | }
193 | 
194 | .important
195 | {
196 |     font-weight: bold;
197 |     color: #950B02;
198 | }
199 | 
200 | .yes-def {
201 |     text-indent: -1000px;
202 | }
203 | 
204 | .type-signature {
205 |     color: #aaa;
206 | }
207 | 
208 | .name, .signature {
209 |     font-family: Consolas, "Lucida Console", Monaco, monospace;
210 | }
211 | 
212 | .details { margin-top: 14px; border-left: 2px solid #DDD; }
213 | .details dt { width:100px; float:left; padding-left: 10px;  padding-top: 6px; }
214 | .details dd { margin-left: 50px; }
215 | .details ul { margin: 0; }
216 | .details ul { list-style-type: none; }
217 | .details li { margin-left: 30px; padding-top: 6px; }
218 | .details pre.prettyprint { margin: 0 }
219 | .details .object-value { padding-top: 0; }
220 | 
221 | .description {
222 |     margin-bottom: 1em;
223 |     margin-left: -16px;
224 |     margin-top: 1em;
225 | }
226 | 
227 | .code-caption
228 | {
229 |     font-style: italic;
230 |     font-family: Palatino, 'Palatino Linotype', serif;
231 |     font-size: 107%;
232 |     margin: 0;
233 | }
234 | 
235 | .prettyprint
236 | {
237 |     border: 1px solid #ddd;
238 |     width: 80%;
239 |     overflow: auto;
240 | }
241 | 
242 | .prettyprint.source {
243 |     width: inherit;
244 | }
245 | 
246 | .prettyprint code
247 | {
248 |     font-family: Consolas, 'Lucida Console', Monaco, monospace;
249 |     font-size: 100%;
250 |     line-height: 18px;
251 |     display: block;
252 |     padding: 4px 12px;
253 |     margin: 0;
254 |     background-color: #fff;
255 |     color: #000;
256 | }
257 | 
258 | .prettyprint code span.line
259 | {
260 |   display: inline-block;
261 | }
262 | 
263 | .prettyprint.linenums
264 | {
265 |   padding-left: 70px;
266 |   -webkit-user-select: none;
267 |   -moz-user-select: none;
268 |   -ms-user-select: none;
269 |   user-select: none;
270 | }
271 | 
272 | .prettyprint.linenums ol
273 | {
274 |   padding-left: 0;
275 | }
276 | 
277 | .prettyprint.linenums li
278 | {
279 |   border-left: 3px #ddd solid;
280 | }
281 | 
282 | .prettyprint.linenums li.selected,
283 | .prettyprint.linenums li.selected *
284 | {
285 |   background-color: lightyellow;
286 | }
287 | 
288 | .prettyprint.linenums li *
289 | {
290 |   -webkit-user-select: text;
291 |   -moz-user-select: text;
292 |   -ms-user-select: text;
293 |   user-select: text;
294 | }
295 | 
296 | .params, .props
297 | {
298 |     border-spacing: 0;
299 |     border: 0;
300 |     border-collapse: collapse;
301 | }
302 | 
303 | .params .name, .props .name, .name code {
304 |     color: #526492;
305 |     font-family: Consolas, 'Lucida Console', Monaco, monospace;
306 |     font-size: 100%;
307 | }
308 | 
309 | .params td, .params th, .props td, .props th
310 | {
311 |     border: 1px solid #ddd;
312 |     margin: 0px;
313 |     text-align: left;
314 |     vertical-align: top;
315 |     padding: 4px 6px;
316 |     display: table-cell;
317 | }
318 | 
319 | .params thead tr, .props thead tr
320 | {
321 |     background-color: #ddd;
322 |     font-weight: bold;
323 | }
324 | 
325 | .params .params thead tr, .props .props thead tr
326 | {
327 |     background-color: #fff;
328 |     font-weight: bold;
329 | }
330 | 
331 | .params th, .props th { border-right: 1px solid #aaa; }
332 | .params thead .last, .props thead .last { border-right: 1px solid #ddd; }
333 | 
334 | .params td.description > p:first-child
335 | {
336 |     margin-top: 0;
337 |     padding-top: 0;
338 | }
339 | 
340 | .params td.description > p:last-child
341 | {
342 |     margin-bottom: 0;
343 |     padding-bottom: 0;
344 | }
345 | 
346 | .disabled {
347 |     color: #454545;
348 | }
349 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/static/styles/prettify-jsdoc.css:
--------------------------------------------------------------------------------
  1 | /* JSDoc prettify.js theme */
  2 | 
  3 | /* plain text */
  4 | .pln {
  5 |   color: #000000;
  6 |   font-weight: normal;
  7 |   font-style: normal;
  8 | }
  9 | 
 10 | /* string content */
 11 | .str {
 12 |   color: #006400;
 13 |   font-weight: normal;
 14 |   font-style: normal;
 15 | }
 16 | 
 17 | /* a keyword */
 18 | .kwd {
 19 |   color: #000000;
 20 |   font-weight: bold;
 21 |   font-style: normal;
 22 | }
 23 | 
 24 | /* a comment */
 25 | .com {
 26 |   font-weight: normal;
 27 |   font-style: italic;
 28 | }
 29 | 
 30 | /* a type name */
 31 | .typ {
 32 |   color: #000000;
 33 |   font-weight: normal;
 34 |   font-style: normal;
 35 | }
 36 | 
 37 | /* a literal value */
 38 | .lit {
 39 |   color: #006400;
 40 |   font-weight: normal;
 41 |   font-style: normal;
 42 | }
 43 | 
 44 | /* punctuation */
 45 | .pun {
 46 |   color: #000000;
 47 |   font-weight: bold;
 48 |   font-style: normal;
 49 | }
 50 | 
 51 | /* lisp open bracket */
 52 | .opn {
 53 |   color: #000000;
 54 |   font-weight: bold;
 55 |   font-style: normal;
 56 | }
 57 | 
 58 | /* lisp close bracket */
 59 | .clo {
 60 |   color: #000000;
 61 |   font-weight: bold;
 62 |   font-style: normal;
 63 | }
 64 | 
 65 | /* a markup tag name */
 66 | .tag {
 67 |   color: #006400;
 68 |   font-weight: normal;
 69 |   font-style: normal;
 70 | }
 71 | 
 72 | /* a markup attribute name */
 73 | .atn {
 74 |   color: #006400;
 75 |   font-weight: normal;
 76 |   font-style: normal;
 77 | }
 78 | 
 79 | /* a markup attribute value */
 80 | .atv {
 81 |   color: #006400;
 82 |   font-weight: normal;
 83 |   font-style: normal;
 84 | }
 85 | 
 86 | /* a declaration */
 87 | .dec {
 88 |   color: #000000;
 89 |   font-weight: bold;
 90 |   font-style: normal;
 91 | }
 92 | 
 93 | /* a variable name */
 94 | .var {
 95 |   color: #000000;
 96 |   font-weight: normal;
 97 |   font-style: normal;
 98 | }
 99 | 
100 | /* a function name */
101 | .fun {
102 |   color: #000000;
103 |   font-weight: bold;
104 |   font-style: normal;
105 | }
106 | 
107 | /* Specify class=linenums on a pre to get line numbering */
108 | ol.linenums {
109 |   margin-top: 0;
110 |   margin-bottom: 0;
111 | }
112 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/static/styles/prettify-tomorrow.css:
--------------------------------------------------------------------------------
  1 | /* Tomorrow Theme */
  2 | /* Original theme - https://github.com/chriskempson/tomorrow-theme */
  3 | /* Pretty printing styles. Used with prettify.js. */
  4 | /* SPAN elements with the classes below are added by prettyprint. */
  5 | /* plain text */
  6 | .pln {
  7 |   color: #4d4d4c; }
  8 | 
  9 | @media screen {
 10 |   /* string content */
 11 |   .str {
 12 |     color: #718c00; }
 13 | 
 14 |   /* a keyword */
 15 |   .kwd {
 16 |     color: #8959a8; }
 17 | 
 18 |   /* a comment */
 19 |   .com {
 20 |     color: #8e908c; }
 21 | 
 22 |   /* a type name */
 23 |   .typ {
 24 |     color: #4271ae; }
 25 | 
 26 |   /* a literal value */
 27 |   .lit {
 28 |     color: #f5871f; }
 29 | 
 30 |   /* punctuation */
 31 |   .pun {
 32 |     color: #4d4d4c; }
 33 | 
 34 |   /* lisp open bracket */
 35 |   .opn {
 36 |     color: #4d4d4c; }
 37 | 
 38 |   /* lisp close bracket */
 39 |   .clo {
 40 |     color: #4d4d4c; }
 41 | 
 42 |   /* a markup tag name */
 43 |   .tag {
 44 |     color: #c82829; }
 45 | 
 46 |   /* a markup attribute name */
 47 |   .atn {
 48 |     color: #f5871f; }
 49 | 
 50 |   /* a markup attribute value */
 51 |   .atv {
 52 |     color: #3e999f; }
 53 | 
 54 |   /* a declaration */
 55 |   .dec {
 56 |     color: #f5871f; }
 57 | 
 58 |   /* a variable name */
 59 |   .var {
 60 |     color: #c82829; }
 61 | 
 62 |   /* a function name */
 63 |   .fun {
 64 |     color: #4271ae; } }
 65 | /* Use higher contrast and text-weight for printable form. */
 66 | @media print, projection {
 67 |   .str {
 68 |     color: #060; }
 69 | 
 70 |   .kwd {
 71 |     color: #006;
 72 |     font-weight: bold; }
 73 | 
 74 |   .com {
 75 |     color: #600;
 76 |     font-style: italic; }
 77 | 
 78 |   .typ {
 79 |     color: #404;
 80 |     font-weight: bold; }
 81 | 
 82 |   .lit {
 83 |     color: #044; }
 84 | 
 85 |   .pun, .opn, .clo {
 86 |     color: #440; }
 87 | 
 88 |   .tag {
 89 |     color: #006;
 90 |     font-weight: bold; }
 91 | 
 92 |   .atn {
 93 |     color: #404; }
 94 | 
 95 |   .atv {
 96 |     color: #060; } }
 97 | /* Style */
 98 | /*
 99 | pre.prettyprint {
100 |   background: white;
101 |   font-family: Menlo, Monaco, Consolas, monospace;
102 |   font-size: 12px;
103 |   line-height: 1.5;
104 |   border: 1px solid #ccc;
105 |   padding: 10px; }
106 | */
107 | 
108 | /* Specify class=linenums on a pre to get line numbering */
109 | ol.linenums {
110 |   margin-top: 0;
111 |   margin-bottom: 0; }
112 | 
113 | /* IE indents via margin-left */
114 | li.L0,
115 | li.L1,
116 | li.L2,
117 | li.L3,
118 | li.L4,
119 | li.L5,
120 | li.L6,
121 | li.L7,
122 | li.L8,
123 | li.L9 {
124 |   /* */ }
125 | 
126 | /* Alternate shading for lines */
127 | li.L1,
128 | li.L3,
129 | li.L5,
130 | li.L7,
131 | li.L9 {
132 |   /* */ }
133 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/aliases.tmpl:
--------------------------------------------------------------------------------
 1 | <?js
 2 | var data = obj || {};
 3 | ?>
 4 | <?js if (data.aliases.length > 1) { ?>
 5 | <ul>
 6 | 	<?js data.aliases.forEach(function(alias) { ?>
 7 | 		<li><?js= alias ?></li>
 8 | 	<?js }); ?>
 9 | </ul>
10 | <?js } else { ?>
11 | 	<?js= data.aliases[0] ?>
12 | <?js } ?>


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/container.tmpl:
--------------------------------------------------------------------------------
  1 | <?js
  2 |     var self = this;
  3 |     docs.forEach(function(doc, i) {
  4 | ?>
  5 | 
  6 | <?js if (doc.kind === 'mainpage' || (doc.kind === 'package')) { ?>
  7 |     <?js= self.partial('mainpage.tmpl', doc) ?>
  8 | <?js } else if (doc.kind === 'source') { ?>
  9 |     <?js= self.partial('source.tmpl', doc) ?>
 10 | <?js } else { ?>
 11 | 
 12 | <section>
 13 | 
 14 | <header>
 15 |     <h2><?js if (doc.ancestors && doc.ancestors.length) { ?>
 16 |         <span class="ancestors"><?js= doc.ancestors.join('') ?></span>
 17 |     <?js } ?>
 18 |     <?js= doc.name ?>
 19 |     <?js if (doc.variation) { ?>
 20 |         <sup class="variation"><?js= doc.variation ?></sup>
 21 |     <?js } ?></h2>
 22 |     <?js if (doc.classdesc) { ?>
 23 |         <div class="class-description"><?js= doc.classdesc ?></div>
 24 |     <?js } ?>
 25 | </header>
 26 | 
 27 | <article>
 28 |     <div class="container-overview">
 29 |     <?js if (doc.kind === 'module' && doc.module) { ?>
 30 |         <?js= self.partial('method.tmpl', doc.module) ?>
 31 |     <?js } ?>
 32 | 
 33 |     <?js if (doc.kind === 'class') { ?>
 34 |         <?js= self.partial('method.tmpl', doc) ?>
 35 |     <?js } else { ?>
 36 |         <?js if (doc.description) { ?>
 37 |             <div class="description"><?js= doc.description ?></div>
 38 |         <?js } ?>
 39 | 
 40 |         <?js= self.partial('details.tmpl', doc) ?>
 41 | 
 42 |         <?js if (doc.examples && doc.examples.length) { ?>
 43 |             <h3>Example<?js= doc.examples.length > 1? 's':'' ?></h3>
 44 |             <?js= self.partial('examples.tmpl', doc.examples) ?>
 45 |         <?js } ?>
 46 |     <?js } ?>
 47 |     </div>
 48 | 
 49 |     <?js if (doc.augments && doc.augments.length) { ?>
 50 |         <h3 class="subsection-title">Extends</h3>
 51 | 
 52 |         <ul><?js doc.augments.forEach(function(a) { ?>
 53 |             <li><?js= self.linkto(a, a) ?></li>
 54 |         <?js }); ?></ul>
 55 |     <?js } ?>
 56 | 
 57 |     <?js if (doc.mixes && doc.mixes.length) { ?>
 58 |         <h3 class="subsection-title">Mixes In</h3>
 59 | 
 60 |         <ul><?js doc.mixes.forEach(function(a) { ?>
 61 |             <li><?js= self.linkto(a, a) ?></li>
 62 |         <?js }); ?></ul>
 63 |     <?js } ?>
 64 | 
 65 |     <?js if (doc.requires && doc.requires.length) { ?>
 66 |         <h3 class="subsection-title">Requires</h3>
 67 | 
 68 |         <ul><?js doc.requires.forEach(function(r) { ?>
 69 |             <li><?js= self.linkto(r, r) ?></li>
 70 |         <?js }); ?></ul>
 71 |     <?js } ?>
 72 | 
 73 |     <?js
 74 |         var classes = self.find({kind: 'class', memberof: doc.longname});
 75 |         if (doc.kind !== 'globalobj' && classes && classes.length) {
 76 |     ?>
 77 |         <h3 class="subsection-title">Classes</h3>
 78 | 
 79 |         <dl><?js classes.forEach(function(c) { ?>
 80 |             <dt><?js= self.linkto(c.longname, c.name) ?></dt>
 81 |             <dd><?js if (c.summary) { ?><?js= c.summary ?><?js } ?></dd>
 82 |         <?js }); ?></dl>
 83 |     <?js } ?>
 84 | 
 85 |     <?js
 86 |         var namespaces = self.find({kind: 'namespace', memberof: doc.longname});
 87 |         if (doc.kind !== 'globalobj' && namespaces && namespaces.length) {
 88 |     ?>
 89 |         <h3 class="subsection-title">Namespaces</h3>
 90 | 
 91 |         <dl><?js namespaces.forEach(function(n) { ?>
 92 |             <dt><a href="namespaces.html#<?js= n.longname ?>"><?js= self.linkto(n.longname, n.name) ?></a></dt>
 93 |             <dd><?js if (n.summary) { ?><?js= n.summary ?><?js } ?></dd>
 94 |         <?js }); ?></dl>
 95 |     <?js } ?>
 96 | 
 97 |     <?js
 98 |         var members = self.find({kind: 'member', memberof: title === 'Global' ? {isUndefined: true} : doc.longname});
 99 |         if (members && members.length && members.forEach) {
100 |     ?>
101 |         <h3 class="subsection-title">Members</h3>
102 | 
103 |         <dl><?js members.forEach(function(p) { ?>
104 |             <?js= self.partial('members.tmpl', p) ?>
105 |         <?js }); ?></dl>
106 |     <?js } ?>
107 | 
108 |     <?js
109 |         var methods = self.find({kind: 'function', memberof: title === 'Global' ? {isUndefined: true} : doc.longname});
110 |         if (methods && methods.length && methods.forEach) {
111 |             // Categorize methods
112 |             var categories = {};
113 |             methods.forEach(function(method) {
114 |                 var category = (method.category || 'Other') + ' methods';
115 |                 if (!(category in categories)) {
116 |                     categories[category] = [];
117 |                 }
118 | 
119 |                 categories[category].push(method);
120 |             });
121 | 
122 |             if (Object.keys(categories) === 1) {
123 |                 categories = { "Methods": categories['Other methods'] };
124 |             }
125 | 
126 |             Object.keys(categories).sort().forEach(function(category) {
127 |     ?>
128 |         <h3 class="subsection-title"><a name="<?js= category.toLowerCase().replace(/[^a-z0-9]/gi, '-') ?>"></a><?js= category ?></h3>
129 | 
130 |         <dl><?js categories[category].forEach(function(m) { ?>
131 |             <?js= self.partial('method.tmpl', m) ?>
132 |         <?js }); ?></dl>
133 |     <?js
134 |             });
135 |         }
136 |     ?>
137 | 
138 |     <?js
139 |         var typedefs = self.find({kind: 'typedef', memberof: title === 'Global' ? {isUndefined: true} : doc.longname});
140 |         if (typedefs && typedefs.length && typedefs.forEach) {
141 |     ?>
142 |         <h3 class="subsection-title">Type Definitions</h3>
143 | 
144 |         <dl><?js typedefs.forEach(function(e) {
145 |                 if (e.signature) {
146 |             ?>
147 |                 <?js= self.partial('method.tmpl', e) ?>
148 |             <?js
149 |                 }
150 |                 else {
151 |             ?>
152 |                 <?js= self.partial('members.tmpl', e) ?>
153 |             <?js
154 |                 }
155 |             }); ?></dl>
156 |     <?js } ?>
157 | 
158 |     <?js
159 |         var events = self.find({kind: 'event', memberof: title === 'Global' ? {isUndefined: true} : doc.longname});
160 |         if (events && events.length && events.forEach) {
161 |     ?>
162 |         <h3 class="subsection-title">Events</h3>
163 | 
164 |         <dl><?js events.forEach(function(e) { ?>
165 |             <?js= self.partial('method.tmpl', e) ?>
166 |         <?js }); ?></dl>
167 |     <?js } ?>
168 | </article>
169 | 
170 | </section>
171 | <?js } ?>
172 | 
173 | <?js }); ?>
174 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/details.tmpl:
--------------------------------------------------------------------------------
  1 | <?js
  2 | var data = obj;
  3 | var self = this;
  4 | var defaultObjectClass = '';
  5 | 
  6 | // Check if the default value is an object, if so, apply code highlighting
  7 | if (data.defaultvalue && data.defaultvaluetype === 'object') {
  8 |     data.defaultvalue = "<pre class=\"prettyprint\"><code>" + data.defaultvalue + "</code></pre>";
  9 |     defaultObjectClass = ' class="object-value"';
 10 | }
 11 | ?>
 12 | <dl class="details">
 13 |     <?js
 14 |         var properties = data.properties;
 15 |         if (properties && properties.length && properties.forEach) {
 16 |     ?>
 17 | 
 18 |         <h5 class="subsection-title">Properties:</h5>
 19 | 
 20 |         <dl><?js= this.partial('properties.tmpl', properties) ?></dl>
 21 | 
 22 |     <?js } ?>
 23 | 
 24 |     <?js if (data.version) {?>
 25 |     <dt class="tag-version">Version:</dt>
 26 |     <dd class="tag-version"><ul class="dummy"><li><?js= version ?></li></ul></dd>
 27 |     <?js } ?>
 28 | 
 29 |     <?js if (data.since) {?>
 30 |     <dt class="tag-since">Since:</dt>
 31 |     <dd class="tag-since"><ul class="dummy"><li><?js= since ?></dd>
 32 |     <?js } ?>
 33 | 
 34 |     <?js if (data.inherited && data.inherits) { ?>
 35 |     <dt class="inherited-from">Inherited From:</dt>
 36 |     <dd class="inherited-from"><ul class="dummy"><li>
 37 |         <?js= this.linkto(data.inherits, this.htmlsafe(data.inherits)) ?>
 38 |     </li></dd>
 39 |     <?js } ?>
 40 | 
 41 |     <?js if (data.deprecated) { ?>
 42 |         <dt class="important tag-deprecated">Deprecated:</dt><?js
 43 |             if (data.deprecated === true) { ?><dd class="yes-def tag-deprecated"><ul class="dummy"><li>Yes</li></ul></dd><?js }
 44 |             else { ?><dd><ul class="dummy"><li><?js= data.deprecated ?></li><ul></dd><?js }
 45 |         ?>
 46 |     <?js } ?>
 47 | 
 48 |     <?js if (data.author && author.length) {?>
 49 |     <dt class="tag-author">Author:</dt>
 50 |     <dd class="tag-author">
 51 |         <ul><?js author.forEach(function(a) { ?>
 52 |             <li><?js= self.resolveAuthorLinks(a) ?></li>
 53 |         <?js }); ?></ul>
 54 |     </dd>
 55 |     <?js } ?>
 56 | 
 57 |     <?js if (data.copyright) {?>
 58 |     <dt class="tag-copyright">Copyright:</dt>
 59 |     <dd class="tag-copyright"><ul class="dummy"><li><?js= copyright ?></li></ul></dd>
 60 |     <?js } ?>
 61 | 
 62 |     <?js if (data.license) {?>
 63 |     <dt class="tag-license">License:</dt>
 64 |     <dd class="tag-license"><ul class="dummy"><li><?js= license ?></li></ul></dd>
 65 |     <?js } ?>
 66 | 
 67 |     <?js if (data.defaultvalue) {?>
 68 |     <dt class="tag-default">Default Value:</dt>
 69 |     <dd class="tag-default"><ul class="dummy">
 70 |             <li<?js= defaultObjectClass ?>><?js= data.defaultvalue ?></li>
 71 |         </ul></dd>
 72 |     <?js } ?>
 73 | 
 74 |     <?js if (data.meta && self.outputSourceFiles) {?>
 75 |     <dt class="tag-source">Source:</dt>
 76 |     <dd class="tag-source"><ul class="dummy"><li>
 77 |         <?js= self.linkto(meta.shortpath) ?>, <?js= self.linkto(meta.shortpath, 'line ' + meta.lineno, null, 'line' + meta.lineno) ?>
 78 |     </li></ul></dd>
 79 |     <?js } ?>
 80 | 
 81 |     <?js if (data.tutorials && tutorials.length) {?>
 82 |     <dt class="tag-tutorial">Tutorials:</dt>
 83 |     <dd class="tag-tutorial">
 84 |         <ul><?js tutorials.forEach(function(t) { ?>
 85 |             <li><?js= self.tutoriallink(t) ?></li>
 86 |         <?js }); ?></ul>
 87 |     </dd>
 88 |     <?js } ?>
 89 | 
 90 |     <?js if (data.see && see.length) {?>
 91 |     <dt class="tag-see">See:</dt>
 92 |     <dd class="tag-see">
 93 |         <ul><?js see.forEach(function(s) { ?>
 94 |             <li><?js= self.linkto(s) ?></li>
 95 |         <?js }); ?></ul>
 96 |     </dd>
 97 |     <?js } ?>
 98 | 
 99 |     <?js if (data.todo && todo.length) {?>
100 |     <dt class="tag-todo">To Do:</dt>
101 |     <dd class="tag-todo">
102 |         <ul><?js todo.forEach(function(t) { ?>
103 |             <li><?js= t ?></li>
104 |         <?js }); ?></ul>
105 |     </dd>
106 |     <?js } ?>
107 | </dl>
108 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/example.tmpl:
--------------------------------------------------------------------------------
1 | <?js var data = obj; ?>
2 | <pre><code><?js= data ?></code></pre>
3 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/examples.tmpl:
--------------------------------------------------------------------------------
 1 | <?js
 2 |     var data = obj;
 3 |     var self = this;
 4 | 
 5 |     data.forEach(function(example) {
 6 |         if (example.caption) {
 7 |     ?>
 8 |         <p class="code-caption"><?js= example.caption ?></p>
 9 |     <?js } ?>
10 |     <pre class="prettyprint"><code><?js= self.htmlsafe(example.code) ?></code></pre>
11 | <?js
12 |     });
13 | ?>


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/exceptions.tmpl:
--------------------------------------------------------------------------------
 1 | <?js
 2 |     var data = obj;
 3 | ?>
 4 | <?js if (data.description && data.type && data.type.names) { ?>
 5 | <dl>
 6 |     <dt>
 7 |         <div class="param-desc">
 8 |         <?js= data.description ?>
 9 |         </div>
10 |     </dt>
11 |     <dt>
12 |         <dl>
13 |             <dt>
14 |                 Type
15 |             </dt>
16 |             <dd>
17 |                 <?js= this.partial('type.tmpl', data.type.names) ?>
18 |             </dd>
19 |         </dl>
20 |     </dt>
21 | </dl>
22 | <?js } else { ?>
23 |     <div class="param-desc">
24 |     <?js if (data.description) { ?>
25 |         <?js= data.description ?>
26 |     <?js } else if (data.type && data.type.names) { ?>
27 |         <?js= this.partial('type.tmpl', data.type.names) ?>
28 |     <?js } ?>
29 |     </div>
30 | <?js } ?>
31 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/layout.tmpl:
--------------------------------------------------------------------------------
 1 | <!DOCTYPE html>
 2 | <html lang="en">
 3 | <head>
 4 |     <meta charset="utf-8">
 5 |     <title>JSDoc: <?js= title ?></title>
 6 | 
 7 |     <script src="scripts/prettify/prettify.js"> </script>
 8 |     <script src="scripts/prettify/lang-css.js"> </script>
 9 |     <!--[if lt IE 9]>
10 |       <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
11 |     <![endif]-->
12 |     <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
13 |     <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
14 | </head>
15 | 
16 | <body>
17 | 
18 | <div id="main">
19 | 
20 |     <h1 class="page-title"><?js= title ?></h1>
21 | 
22 |     <?js= content ?>
23 | </div>
24 | 
25 | <nav>
26 |     <?js= this.nav ?>
27 | </nav>
28 | 
29 | <br clear="both">
30 | 
31 | <footer>
32 |     Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc <?js= env.version.number ?></a> on <?js= (new Date()) ?>
33 | </footer>
34 | 
35 | <script> prettyPrint(); </script>
36 | <script src="scripts/linenumber.js"> </script>
37 | </body>
38 | </html>
39 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/mainpage.tmpl:
--------------------------------------------------------------------------------
 1 | <?js
 2 | var data = obj;
 3 | var self = this;
 4 | ?>
 5 | 
 6 | <?js if (data.kind === 'package') { ?>
 7 |     <h3><?js= data.name ?> <?js= data.version ?></h3>
 8 | <?js } ?>
 9 | 
10 | <?js if (data.readme) { ?>
11 |     <section>
12 |         <article><?js= data.readme ?></article>
13 |     </section>
14 | <?js } ?>
15 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/members.tmpl:
--------------------------------------------------------------------------------
 1 | <?js
 2 | var data = obj;
 3 | var self = this;
 4 | ?>
 5 | <dt>
 6 |     <h4 class="name" id="<?js= id ?>"><?js= data.attribs + name + (data.signature ? data.signature : '') ?></h4>
 7 | 
 8 |     <?js if (data.summary) { ?>
 9 |     <p class="summary"><?js= summary ?></p>
10 |     <?js } ?>
11 | </dt>
12 | <dd>
13 |     <?js if (data.description) { ?>
14 |     <div class="description">
15 |         <?js= data.description ?>
16 |     </div>
17 |     <?js } ?>
18 | 
19 |     <?js if (data.type && data.type.names) {?>
20 |         <h5>Type:</h5>
21 |         <ul>
22 |             <li>
23 |                 <?js= self.partial('type.tmpl', data.type.names) ?>
24 |             </li>
25 |         </ul>
26 |     <?js } ?>
27 | 
28 |     <?js= this.partial('details.tmpl', data) ?>
29 | 
30 |     <?js if (data.fires && fires.length) { ?>
31 |         <h5>Fires:</h5>
32 |         <ul><?js fires.forEach(function(f) { ?>
33 |             <li><?js= self.linkto(f) ?></li>
34 |         <?js }); ?></ul>
35 |     <?js } ?>
36 | 
37 |     <?js if (data.examples && examples.length) { ?>
38 |         <h5>Example<?js= examples.length > 1? 's':'' ?></h5>
39 |         <?js= this.partial('examples.tmpl', examples) ?>
40 |     <?js } ?>
41 | </dd>
42 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/method.tmpl:
--------------------------------------------------------------------------------
  1 | <?js
  2 | var data = obj;
  3 | var self = this;
  4 | ?>
  5 | <dt>
  6 |     <h4 class="name" id="<?js= id ?>"><?js= data.attribs + (kind === 'class' ? 'new ' : '') + name + (kind !== 'event' ? data.signature : '') ?></h4>
  7 | 
  8 |     <?js if (data.summary) { ?>
  9 |     <p class="summary"><?js= summary ?></p>
 10 |     <?js } ?>
 11 | </dt>
 12 | <dd>
 13 | 
 14 |     <?js if (data.description) { ?>
 15 |     <div class="description">
 16 |         <?js= data.description ?>
 17 |     </div>
 18 |     <?js } ?>
 19 | 
 20 |     <?js if (kind === 'event' && data.type && data.type.names) {?>
 21 |         <h5>Type:</h5>
 22 |         <ul>
 23 |             <li>
 24 |                 <?js= self.partial('type.tmpl', data.type.names) ?>
 25 |             </li>
 26 |         </ul>
 27 |     <?js } ?>
 28 | 
 29 |     <?js if (data['this']) { ?>
 30 |         <h5>This:</h5>
 31 |         <ul><li><?js= this.linkto(data['this'], data['this']) ?></li></ul>
 32 |     <?js } ?>
 33 | 
 34 |     <?js if (!data.isAlias && data.params && params.length) { ?>
 35 |         <h5>Parameters:</h5>
 36 |         <?js= this.partial('params.tmpl', params) ?>
 37 |     <?js } ?>
 38 | 
 39 |     <?js= this.partial('details.tmpl', data) ?>
 40 | 
 41 |     <?js if (data.requires && data.requires.length) { ?>
 42 |     <h5>Requires:</h5>
 43 |     <ul><?js data.requires.forEach(function(r) { ?>
 44 |         <li><?js= self.linkto(r) ?></li>
 45 |     <?js }); ?></ul>
 46 |     <?js } ?>
 47 | 
 48 |     <?js if (data.fires && fires.length) { ?>
 49 |     <h5>Fires:</h5>
 50 |     <ul><?js fires.forEach(function(f) { ?>
 51 |         <li><?js= self.linkto(f) ?></li>
 52 |     <?js }); ?></ul>
 53 |     <?js } ?>
 54 | 
 55 |     <?js if (data.listens && listens.length) { ?>
 56 |     <h5>Listens to Events:</h5>
 57 |     <ul><?js listens.forEach(function(f) { ?>
 58 |         <li><?js= self.linkto(f) ?></li>
 59 |     <?js }); ?></ul>
 60 |     <?js } ?>
 61 | 
 62 |     <?js if (data.listeners && listeners.length) { ?>
 63 |     <h5>Listeners of This Event:</h5>
 64 |     <ul><?js listeners.forEach(function(f) { ?>
 65 |         <li><?js= self.linkto(f) ?></li>
 66 |     <?js }); ?></ul>
 67 |     <?js } ?>
 68 | 
 69 |     <?js if (data.exceptions && exceptions.length) { ?>
 70 |     <h5>Throws:</h5>
 71 |     <?js if (exceptions.length > 1) { ?><ul><?js
 72 |         exceptions.forEach(function(r) { ?>
 73 |             <li><?js= self.partial('exceptions.tmpl', r) ?></li>
 74 |         <?js });
 75 |     ?></ul><?js } else {
 76 |         exceptions.forEach(function(r) { ?>
 77 |             <?js= self.partial('exceptions.tmpl', r) ?>
 78 |         <?js });
 79 |     } } ?>
 80 | 
 81 |     <?js if (data.returns && returns.length) { ?>
 82 |     <h5>Returns:</h5>
 83 |     <?js if (returns.length > 1) { ?><ul><?js
 84 |         returns.forEach(function(r) { ?>
 85 |             <li><?js= self.partial('returns.tmpl', r) ?></li>
 86 |         <?js });
 87 |     ?></ul><?js } else {
 88 |         returns.forEach(function(r) { ?>
 89 |             <?js= self.partial('returns.tmpl', r) ?>
 90 |         <?js });
 91 |     } } ?>
 92 | 
 93 |     <?js if (data.examples && examples.length) { ?>
 94 |         <h5>Example<?js= examples.length > 1? 's':'' ?>:</h5>
 95 |         <?js= this.partial('examples.tmpl', examples) ?>
 96 |     <?js } ?>
 97 | 
 98 |     <?js if (data.aliases && aliases.length) { ?>
 99 |         <h5>Alias<?js= aliases.length > 1 ? 'es' : '' ?>:</h5>
100 |         <?js= this.partial('aliases.tmpl', { memberof: data.memberof, aliases: aliases }) ?>
101 |     <?js } ?>
102 | </dd>
103 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/params.tmpl:
--------------------------------------------------------------------------------
  1 | <?js
  2 |     var params = obj;
  3 | 
  4 |     /* sort subparams under their parent params (like opts.classname) */
  5 |     var parentParam = null;
  6 |     params.forEach(function(param, i) {
  7 |         if (!param) { return; }
  8 |         if ( parentParam && param.name && param.name.indexOf(parentParam.name + '.') === 0 ) {
  9 |             param.name = param.name.substr(parentParam.name.length+1);
 10 |             parentParam.subparams = parentParam.subparams || [];
 11 |             parentParam.subparams.push(param);
 12 |             params[i] = null;
 13 |         }
 14 |         else {
 15 |             parentParam = param;
 16 |         }
 17 |     });
 18 | 
 19 |     /* determine if we need extra columns, "attributes" and "default" */
 20 |     params.hasAttributes = false;
 21 |     params.hasDefault = false;
 22 |     params.hasName = false;
 23 | 
 24 |     params.forEach(function(param) {
 25 |         if (!param) { return; }
 26 | 
 27 |         if (param.optional || param.nullable || param.variable) {
 28 |             params.hasAttributes = true;
 29 |         }
 30 | 
 31 |         if (param.name) {
 32 |             params.hasName = true;
 33 |         }
 34 | 
 35 |         if (typeof param.defaultvalue !== 'undefined') {
 36 |             params.hasDefault = true;
 37 |         }
 38 |     });
 39 | ?>
 40 | 
 41 | <table class="params">
 42 |     <thead>
 43 |     <tr>
 44 |         <?js if (params.hasName) {?>
 45 |         <th>Name</th>
 46 |         <?js } ?>
 47 | 
 48 |         <th>Type</th>
 49 | 
 50 |         <?js if (params.hasAttributes) {?>
 51 |         <th>Argument</th>
 52 |         <?js } ?>
 53 | 
 54 |         <?js if (params.hasDefault) {?>
 55 |         <th>Default</th>
 56 |         <?js } ?>
 57 | 
 58 |         <th class="last">Description</th>
 59 |     </tr>
 60 |     </thead>
 61 | 
 62 |     <tbody>
 63 |     <?js
 64 |         var self = this;
 65 |         params.forEach(function(param) {
 66 |             if (!param) { return; }
 67 |     ?>
 68 | 
 69 |         <tr>
 70 |             <?js if (params.hasName) {?>
 71 |                 <td class="name"><code><?js= param.name ?></code></td>
 72 |             <?js } ?>
 73 | 
 74 |             <td class="type">
 75 |             <?js if (param.type && param.type.names) {?>
 76 |                 <?js= self.partial('type.tmpl', param.type.names) ?>
 77 |             <?js } ?>
 78 |             </td>
 79 | 
 80 |             <?js if (params.hasAttributes) {?>
 81 |                 <td class="attributes">
 82 |                 <?js if (param.optional) { ?>
 83 |                     &lt;optional><br>
 84 |                 <?js } ?>
 85 | 
 86 |                 <?js if (param.nullable) { ?>
 87 |                     &lt;nullable><br>
 88 |                 <?js } ?>
 89 | 
 90 |                 <?js if (param.variable) { ?>
 91 |                     &lt;repeatable><br>
 92 |                 <?js } ?>
 93 |                 </td>
 94 |             <?js } ?>
 95 | 
 96 |             <?js if (params.hasDefault) {?>
 97 |                 <td class="default">
 98 |                 <?js if (typeof param.defaultvalue !== 'undefined') { ?>
 99 |                     <?js= self.htmlsafe(param.defaultvalue) ?>
100 |                 <?js } ?>
101 |                 </td>
102 |             <?js } ?>
103 | 
104 |             <td class="description last"><?js= param.description ?><?js if (param.subparams) { ?>
105 |                 <h6>Properties</h6>
106 |                 <?js= self.partial('params.tmpl', param.subparams) ?>
107 |             <?js } ?></td>
108 |         </tr>
109 | 
110 |     <?js }); ?>
111 |     </tbody>
112 | </table>


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/properties.tmpl:
--------------------------------------------------------------------------------
  1 | <?js
  2 |     var props = obj;
  3 | 
  4 |     /* sort subprops under their parent props (like opts.classname) */
  5 |     var parentProp = null;
  6 |     props.forEach(function(prop, i) {
  7 |         if (!prop) { return; }
  8 |         if ( parentProp && prop.name && prop.name.indexOf(parentProp.name + '.') === 0 ) {
  9 |             prop.name = prop.name.substr(parentProp.name.length+1);
 10 |             parentProp.subprops = parentProp.subprops || [];
 11 |             parentProp.subprops.push(prop);
 12 |             props[i] = null;
 13 |         }
 14 |         else {
 15 |             parentProp = prop;
 16 |         }
 17 |     });
 18 | 
 19 |     /* determine if we need extra columns, "attributes" and "default" */
 20 |     props.hasAttributes = false;
 21 |     props.hasDefault = false;
 22 |     props.hasName = false;
 23 | 
 24 |     props.forEach(function(prop) {
 25 |         if (!prop) { return; }
 26 | 
 27 |         if (prop.optional || prop.nullable) {
 28 |             props.hasAttributes = true;
 29 |         }
 30 | 
 31 |         if (prop.name) {
 32 |             props.hasName = true;
 33 |         }
 34 | 
 35 |         if (typeof prop.defaultvalue !== 'undefined') {
 36 |             props.hasDefault = true;
 37 |         }
 38 |     });
 39 | ?>
 40 | 
 41 | <table class="props">
 42 |     <thead>
 43 |     <tr>
 44 |         <?js if (props.hasName) {?>
 45 |         <th>Name</th>
 46 |         <?js } ?>
 47 | 
 48 |         <th>Type</th>
 49 | 
 50 |         <?js if (props.hasAttributes) {?>
 51 |         <th>Argument</th>
 52 |         <?js } ?>
 53 | 
 54 |         <?js if (props.hasDefault) {?>
 55 |         <th>Default</th>
 56 |         <?js } ?>
 57 | 
 58 |         <th class="last">Description</th>
 59 |     </tr>
 60 |     </thead>
 61 | 
 62 |     <tbody>
 63 |     <?js
 64 |         var self = this;
 65 |         props.forEach(function(prop) {
 66 |             if (!prop) { return; }
 67 |     ?>
 68 | 
 69 |         <tr>
 70 |             <?js if (props.hasName) {?>
 71 |                 <td class="name"><code><?js= prop.name ?></code></td>
 72 |             <?js } ?>
 73 | 
 74 |             <td class="type">
 75 |             <?js if (prop.type && prop.type.names) {?>
 76 |                 <?js= self.partial('type.tmpl', prop.type.names) ?>
 77 |             <?js } ?>
 78 |             </td>
 79 | 
 80 |             <?js if (props.hasAttributes) {?>
 81 |                 <td class="attributes">
 82 |                 <?js if (prop.optional) { ?>
 83 |                     &lt;optional><br>
 84 |                 <?js } ?>
 85 | 
 86 |                 <?js if (prop.nullable) { ?>
 87 |                     &lt;nullable><br>
 88 |                 <?js } ?>
 89 |                 </td>
 90 |             <?js } ?>
 91 | 
 92 |             <?js if (props.hasDefault) {?>
 93 |                 <td class="default">
 94 |                 <?js if (typeof prop.defaultvalue !== 'undefined') { ?>
 95 |                     <?js= self.htmlsafe(prop.defaultvalue) ?>
 96 |                 <?js } ?>
 97 |                 </td>
 98 |             <?js } ?>
 99 | 
100 |             <td class="description last"><?js= prop.description ?><?js if (prop.subprops) { ?>
101 |                 <h6>Properties</h6><?js= self.partial('properties.tmpl', prop.subprops) ?>
102 |             <?js } ?></td>
103 |         </tr>
104 | 
105 |     <?js }); ?>
106 |     </tbody>
107 | </table>


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/returns.tmpl:
--------------------------------------------------------------------------------
 1 | <?js
 2 | var data = obj || {};
 3 | if (data.description) {
 4 | ?>
 5 | <div class="param-desc">
 6 |     <?js= description ?>
 7 | </div>
 8 | <?js } ?>
 9 | 
10 | <?js if (data.type && data.type.names) {?>
11 | <dl>
12 |     <dt>
13 |         Type
14 |     </dt>
15 |     <dd>
16 |         <?js= this.partial('type.tmpl', data.type.names) ?>
17 |     </dd>
18 | </dl>
19 | <?js } ?>


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/source.tmpl:
--------------------------------------------------------------------------------
1 | <?js
2 |     var data = obj;
3 | ?>
4 |     <section>
5 |         <article>
6 |             <pre class="prettyprint source linenums"><code><?js= data.code ?></code></pre>
7 |         </article>
8 |     </section>


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/tutorial.tmpl:
--------------------------------------------------------------------------------
 1 | <section>
 2 | 
 3 | <header>
 4 |     <?js if (children.length > 0) { ?>
 5 |     <ul><?js
 6 |         var self = this;
 7 |         children.forEach(function(t) { ?>
 8 |         <li><?js= self.tutoriallink(t.name) ?></li>
 9 |     <?js }); ?></ul>
10 |     <?js } ?>
11 | 
12 |     <h2><?js= header ?></h2>
13 | </header>
14 | 
15 | <article>
16 |     <?js= content ?>
17 | </article>
18 | 
19 | </section>
20 | 


--------------------------------------------------------------------------------
/tools/jsdoc-template/tmpl/type.tmpl:
--------------------------------------------------------------------------------
1 | <?js
2 |     var data = obj;
3 |     var self = this;
4 |     data.forEach(function(name, i) { ?>
5 | <span class="param-type"><?js= self.linkto(name, self.htmlsafe(name)) ?></span>
6 | <?js if (i < data.length-1) { ?>|<?js } ?>
7 | <?js }); ?>


--------------------------------------------------------------------------------