videosize.js.html 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>JSDoc: Source: options/videosize.js</title>
  6. <script src="scripts/prettify/prettify.js"> </script>
  7. <script src="scripts/prettify/lang-css.js"> </script>
  8. <!--[if lt IE 9]>
  9. <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
  10. <![endif]-->
  11. <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
  12. <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
  13. </head>
  14. <body>
  15. <div id="main">
  16. <h1 class="page-title">Source: options/videosize.js</h1>
  17. <section>
  18. <article>
  19. <pre class="prettyprint source linenums"><code>/*jshint node:true*/
  20. 'use strict';
  21. /*
  22. *! Size helpers
  23. */
  24. /**
  25. * Return filters to pad video to width*height,
  26. *
  27. * @param {Number} width output width
  28. * @param {Number} height output height
  29. * @param {Number} aspect video aspect ratio (without padding)
  30. * @param {Number} color padding color
  31. * @return scale/pad filters
  32. * @private
  33. */
  34. function getScalePadFilters(width, height, aspect, color) {
  35. /*
  36. let a be the input aspect ratio, A be the requested aspect ratio
  37. if a > A, padding is done on top and bottom
  38. if a &lt; A, padding is done on left and right
  39. */
  40. return [
  41. /*
  42. In both cases, we first have to scale the input to match the requested size.
  43. When using computed width/height, we truncate them to multiples of 2
  44. */
  45. {
  46. filter: 'scale',
  47. options: {
  48. w: 'if(gt(a,' + aspect + '),' + width + ',trunc(' + height + '*a/2)*2)',
  49. h: 'if(lt(a,' + aspect + '),' + height + ',trunc(' + width + '/a/2)*2)'
  50. }
  51. },
  52. /*
  53. Then we pad the scaled input to match the target size
  54. (here iw and ih refer to the padding input, i.e the scaled output)
  55. */
  56. {
  57. filter: 'pad',
  58. options: {
  59. w: width,
  60. h: height,
  61. x: 'if(gt(a,' + aspect + '),0,(' + width + '-iw)/2)',
  62. y: 'if(lt(a,' + aspect + '),0,(' + height + '-ih)/2)',
  63. color: color
  64. }
  65. }
  66. ];
  67. }
  68. /**
  69. * Recompute size filters
  70. *
  71. * @param {Object} output
  72. * @param {String} key newly-added parameter name ('size', 'aspect' or 'pad')
  73. * @param {String} value newly-added parameter value
  74. * @return filter string array
  75. * @private
  76. */
  77. function createSizeFilters(output, key, value) {
  78. // Store parameters
  79. var data = output.sizeData = output.sizeData || {};
  80. data[key] = value;
  81. if (!('size' in data)) {
  82. // No size requested, keep original size
  83. return [];
  84. }
  85. // Try to match the different size string formats
  86. var fixedSize = data.size.match(/([0-9]+)x([0-9]+)/);
  87. var fixedWidth = data.size.match(/([0-9]+)x\?/);
  88. var fixedHeight = data.size.match(/\?x([0-9]+)/);
  89. var percentRatio = data.size.match(/\b([0-9]{1,3})%/);
  90. var width, height, aspect;
  91. if (percentRatio) {
  92. var ratio = Number(percentRatio[1]) / 100;
  93. return [{
  94. filter: 'scale',
  95. options: {
  96. w: 'trunc(iw*' + ratio + '/2)*2',
  97. h: 'trunc(ih*' + ratio + '/2)*2'
  98. }
  99. }];
  100. } else if (fixedSize) {
  101. // Round target size to multiples of 2
  102. width = Math.round(Number(fixedSize[1]) / 2) * 2;
  103. height = Math.round(Number(fixedSize[2]) / 2) * 2;
  104. aspect = width / height;
  105. if (data.pad) {
  106. return getScalePadFilters(width, height, aspect, data.pad);
  107. } else {
  108. // No autopad requested, rescale to target size
  109. return [{ filter: 'scale', options: { w: width, h: height }}];
  110. }
  111. } else if (fixedWidth || fixedHeight) {
  112. if ('aspect' in data) {
  113. // Specified aspect ratio
  114. width = fixedWidth ? fixedWidth[1] : Math.round(Number(fixedHeight[1]) * data.aspect);
  115. height = fixedHeight ? fixedHeight[1] : Math.round(Number(fixedWidth[1]) / data.aspect);
  116. // Round to multiples of 2
  117. width = Math.round(width / 2) * 2;
  118. height = Math.round(height / 2) * 2;
  119. if (data.pad) {
  120. return getScalePadFilters(width, height, data.aspect, data.pad);
  121. } else {
  122. // No autopad requested, rescale to target size
  123. return [{ filter: 'scale', options: { w: width, h: height }}];
  124. }
  125. } else {
  126. // Keep input aspect ratio
  127. if (fixedWidth) {
  128. return [{
  129. filter: 'scale',
  130. options: {
  131. w: Math.round(Number(fixedWidth[1]) / 2) * 2,
  132. h: 'trunc(ow/a/2)*2'
  133. }
  134. }];
  135. } else {
  136. return [{
  137. filter: 'scale',
  138. options: {
  139. w: 'trunc(oh*a/2)*2',
  140. h: Math.round(Number(fixedHeight[1]) / 2) * 2
  141. }
  142. }];
  143. }
  144. }
  145. } else {
  146. throw new Error('Invalid size specified: ' + data.size);
  147. }
  148. }
  149. /*
  150. *! Video size-related methods
  151. */
  152. module.exports = function(proto) {
  153. /**
  154. * Keep display aspect ratio
  155. *
  156. * This method is useful when converting an input with non-square pixels to an output format
  157. * that does not support non-square pixels. It rescales the input so that the display aspect
  158. * ratio is the same.
  159. *
  160. * @method FfmpegCommand#keepDAR
  161. * @category Video size
  162. * @aliases keepPixelAspect,keepDisplayAspect,keepDisplayAspectRatio
  163. *
  164. * @return FfmpegCommand
  165. */
  166. proto.keepPixelAspect = // Only for compatibility, this is not about keeping _pixel_ aspect ratio
  167. proto.keepDisplayAspect =
  168. proto.keepDisplayAspectRatio =
  169. proto.keepDAR = function() {
  170. return this.videoFilters([
  171. {
  172. filter: 'scale',
  173. options: {
  174. w: 'if(gt(sar,1),iw*sar,iw)',
  175. h: 'if(lt(sar,1),ih/sar,ih)'
  176. }
  177. },
  178. {
  179. filter: 'setsar',
  180. options: '1'
  181. }
  182. ]);
  183. };
  184. /**
  185. * Set output size
  186. *
  187. * The 'size' parameter can have one of 4 forms:
  188. * - 'X%': rescale to xx % of the original size
  189. * - 'WxH': specify width and height
  190. * - 'Wx?': specify width and compute height from input aspect ratio
  191. * - '?xH': specify height and compute width from input aspect ratio
  192. *
  193. * Note: both dimensions will be truncated to multiples of 2.
  194. *
  195. * @method FfmpegCommand#size
  196. * @category Video size
  197. * @aliases withSize,setSize
  198. *
  199. * @param {String} size size string, eg. '33%', '320x240', '320x?', '?x240'
  200. * @return FfmpegCommand
  201. */
  202. proto.withSize =
  203. proto.setSize =
  204. proto.size = function(size) {
  205. var filters = createSizeFilters(this._currentOutput, 'size', size);
  206. this._currentOutput.sizeFilters.clear();
  207. this._currentOutput.sizeFilters(filters);
  208. return this;
  209. };
  210. /**
  211. * Set output aspect ratio
  212. *
  213. * @method FfmpegCommand#aspect
  214. * @category Video size
  215. * @aliases withAspect,withAspectRatio,setAspect,setAspectRatio,aspectRatio
  216. *
  217. * @param {String|Number} aspect aspect ratio (number or 'X:Y' string)
  218. * @return FfmpegCommand
  219. */
  220. proto.withAspect =
  221. proto.withAspectRatio =
  222. proto.setAspect =
  223. proto.setAspectRatio =
  224. proto.aspect =
  225. proto.aspectRatio = function(aspect) {
  226. var a = Number(aspect);
  227. if (isNaN(a)) {
  228. var match = aspect.match(/^(\d+):(\d+)$/);
  229. if (match) {
  230. a = Number(match[1]) / Number(match[2]);
  231. } else {
  232. throw new Error('Invalid aspect ratio: ' + aspect);
  233. }
  234. }
  235. var filters = createSizeFilters(this._currentOutput, 'aspect', a);
  236. this._currentOutput.sizeFilters.clear();
  237. this._currentOutput.sizeFilters(filters);
  238. return this;
  239. };
  240. /**
  241. * Enable auto-padding the output
  242. *
  243. * @method FfmpegCommand#autopad
  244. * @category Video size
  245. * @aliases applyAutopadding,applyAutoPadding,applyAutopad,applyAutoPad,withAutopadding,withAutoPadding,withAutopad,withAutoPad,autoPad
  246. *
  247. * @param {Boolean} [pad=true] enable/disable auto-padding
  248. * @param {String} [color='black'] pad color
  249. */
  250. proto.applyAutopadding =
  251. proto.applyAutoPadding =
  252. proto.applyAutopad =
  253. proto.applyAutoPad =
  254. proto.withAutopadding =
  255. proto.withAutoPadding =
  256. proto.withAutopad =
  257. proto.withAutoPad =
  258. proto.autoPad =
  259. proto.autopad = function(pad, color) {
  260. // Allow autopad(color)
  261. if (typeof pad === 'string') {
  262. color = pad;
  263. pad = true;
  264. }
  265. // Allow autopad() and autopad(undefined, color)
  266. if (typeof pad === 'undefined') {
  267. pad = true;
  268. }
  269. var filters = createSizeFilters(this._currentOutput, 'pad', pad ? color || 'black' : false);
  270. this._currentOutput.sizeFilters.clear();
  271. this._currentOutput.sizeFilters(filters);
  272. return this;
  273. };
  274. };
  275. </code></pre>
  276. </article>
  277. </section>
  278. </div>
  279. <nav>
  280. <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>
  281. </nav>
  282. <br clear="both">
  283. <footer>
  284. 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)
  285. </footer>
  286. <script> prettyPrint(); </script>
  287. <script src="scripts/linenumber.js"> </script>
  288. </body>
  289. </html>