// instrument by jscoverage, do not modifly this file
(function () {
  var BASE;
  if (typeof global === 'object') {
    BASE = global;
  } else if (typeof window === 'object') {
    BASE = window;
  } else {
    throw new Error('[jscoverage] unknow ENV!');
  }
  if (!BASE._$jscoverage) {
    BASE._$jscoverage = {};
    BASE._$jscoverage_cond = {};
    BASE._$jscoverage_done = function (file, line, express) {
      if (arguments.length === 2) {
        BASE._$jscoverage[file][line] ++;
      } else {
        BASE._$jscoverage_cond[file][line] ++;
        return express;
      }
    };
    BASE._$jscoverage_init = function (base, file, lines) {
      var tmp = [];
      for (var i = 0; i < lines.length; i ++) {
        tmp[lines[i]] = 0;
      }
      base[file] = tmp;
    };
  }
})();
_$jscoverage_init(_$jscoverage, "lib/recipes.js",[4,5,6,7,8,15,26,28,29,48,51,52,53,56,57,58,61,64,65,97,102,103,104,107,108,114,115,119,122,123,124,127,128,129,130,135,136,137,138,139,141,142,147,149,150,152,153,154,159,162,162,163,164,167,168,169,171,173,174,177,178,179,181,185,189,195,197,198,201,202,203,206,211,212,213,216,221,226,227,228,231,232,233,236,237,238,240,244,245,248,249,251,252,253,254,255,256,257,258,259,262,265,271,276,281,282,285,286,290,295,296,297,298,299,301,305,310,311,314,315,317,318,319,321,326,327,331,332,335,350,354,355,358,359,360,361,364,365,368,369,373,385]);
_$jscoverage_init(_$jscoverage_cond, "lib/recipes.js",[51,51,56,57,107,114,122,123,135,141,141,141,141,149,162,163,168,173,178,197,201,201,211,212,226,227,232,237,237,244,251,254,257,296,298,310,326,360]);
_$jscoverage["lib/recipes.js"].source = ["/*jshint node:true*/","'use strict';","","var fs = require('fs');","var path = require('path');","var PassThrough = require('stream').PassThrough;","var async = require('async');","var utils = require('./utils');","","","/*"," * Useful recipes for commands"," */","","module.exports = function recipes(proto) {","  /**","   * Execute ffmpeg command and save output to a file","   *","   * @method FfmpegCommand#save","   * @category Processing","   * @aliases saveToFile","   *","   * @param {String} output file path","   * @return FfmpegCommand","   */","  proto.saveToFile =","  proto.save = function(output) {","    this.output(output).run();","    return this;","  };","","","  /**","   * Execute ffmpeg command and save output to a stream","   *","   * If 'stream' is not specified, a PassThrough stream is created and returned.","   * 'options' will be used when piping ffmpeg output to the output stream","   * (@see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options)","   *","   * @method FfmpegCommand#pipe","   * @category Processing","   * @aliases stream,writeToStream","   *","   * @param {stream.Writable} [stream] output stream","   * @param {Object} [options={}] pipe options","   * @return Output stream","   */","  proto.writeToStream =","  proto.pipe =","  proto.stream = function(stream, options) {","    if (stream && !('writable' in stream)) {","      options = stream;","      stream = undefined;","    }","","    if (!stream) {","      if (process.version.match(/v0\\.8\\./)) {","        throw new Error('PassThrough stream is not supported on node v0.8');","      }","","      stream = new PassThrough();","    }","","    this.output(stream, options).run();","    return stream;","  };","","","  /**","   * @method FfmpegCommand#screenshots","   * @category Processing","   * @aliases takeScreenshots,thumbnail,thumbnails,screenshot","   *","   * @param {Number|Object} [config=1] screenshot count or configuration object with","   *   the following keys:","   * @param {Number} [config.count] number of screenshots to take; using this option","   *   takes screenshots at regular intervals (eg. count=4 would take screens at 20%, 40%,","   *   60% and 80% of the video length).","   * @param {String} [config.folder='.'] output folder","   * @param {String} [config.filename='tn.png'] output filename pattern, may contain the following","   *   tokens:","   *   - '%s': offset in seconds","   *   - '%w': screenshot width","   *   - '%h': screenshot height","   *   - '%r': screenshot resolution (same as '%wx%h')","   *   - '%f': input filename","   *   - '%b': input basename (filename w/o extension)","   *   - '%i': index of screenshot in timemark array (can be zero-padded by using it like `%000i`)","   * @param {Number[]|String[]} [config.timemarks] array of timemarks to take screenshots","   *   at; each timemark may be a number of seconds, a '[[hh:]mm:]ss[.xxx]' string or a","   *   'XX%' string.  Overrides 'count' if present.","   * @param {Number[]|String[]} [config.timestamps] alias for 'timemarks'","   * @param {String} [config.size] screenshot size, with the same syntax as {@link FfmpegCommand#size}","   * @param {String} [folder] output folder (legacy alias for 'config.folder')","   * @return FfmpegCommand","   */","  proto.takeScreenshots =","  proto.thumbnail =","  proto.thumbnails =","  proto.screenshot =","  proto.screenshots = function(config, folder) {","    var self = this;","    var source = this._currentInput.source;","    config = config || { count: 1 };","","    // Accept a number of screenshots instead of a config object","    if (typeof config === 'number') {","      config = {","        count: config","      };","    }","","    // Accept a second 'folder' parameter instead of config.folder","    if (!('folder' in config)) {","      config.folder = folder || '.';","    }","","    // Accept 'timestamps' instead of 'timemarks'","    config.timemarks = config.timemarks || config.timestamps;","","    // Compute timemarks from count if not present","    if (!('timemarks' in config)) {","      if (!config.count) {","        throw new Error('Cannot take screenshots: neither a count nor a timemark list are specified');","      }","","      var interval = 100 / (1 + config.count);","      config.timemarks = [];","      for (var i = 0; i <= config.count; i++) {","        config.timemarks.push((interval * (i + 1)) + '%');","      }","    }","","    // Parse size option","    if ('size' in config) {","      var fixedSize = config.size.match(/^(\\d+)x(\\d+)$/);","      var fixedWidth = config.size.match(/^(\\d+)x\\?$/);","      var fixedHeight = config.size.match(/^\\?x(\\d+)$/);","      var percentSize = config.size.match(/^(\\d+)%$/);","","      if (!fixedSize && !fixedWidth && !fixedHeight && !percentSize) {","        throw new Error('Invalid size parameter: ' + config.size);","      }","    }","","    // Metadata helper","    var metadata;","    function getMetadata(cb) {","      if (metadata) {","        cb(null, metadata);","      } else {","        self.ffprobe(function(err, meta) {","          metadata = meta;","          cb(err, meta);","        });","      }","    }","","    async.waterfall([","      // Compute percent timemarks if any","      function computeTimemarks(next) {","        if (config.timemarks.some(function(t) { return ('' + t).match(/^[\\d.]+%$/); })) {","          if (typeof source !== 'string') {","            return next(new Error('Cannot compute screenshot timemarks with an input stream, please specify fixed timemarks'));","          }","","          getMetadata(function(err, meta) {","            if (err) {","              next(err);","            } else {","              var duration = Number(meta.format.duration);","","              if (isNaN(duration)) {","                return next(new Error('Could not get input duration, please specify fixed timemarks'));","              }","","              config.timemarks = config.timemarks.map(function(mark) {","                if (('' + mark).match(/^([\\d.]+)%$/)) {","                  return duration * parseFloat(mark) / 100;","                } else {","                  return mark;","                }","              });","","              next();","            }","          });","        } else {","          next();","        }","      },","","      // Add '_%i' to pattern when requesting multiple screenshots and no variable token is present","      function fixPattern(next) {","        var pattern = config.filename || 'tn.png';","","        if (pattern.indexOf('.') === -1) {","          pattern += '.png';","        }","","        if (config.timemarks.length > 0 && !pattern.match(/%(s|0*i)/)) {","          var ext = path.extname(pattern);","          pattern = path.join(path.dirname(pattern), path.basename(pattern, ext) + '_%i' + ext);","        }","","        next(null, pattern);","      },","","      // Replace filename tokens (%f, %b) in pattern","      function replaceFilenameTokens(pattern, next) {","        if (pattern.match(/%[bf]/)) {","          if (typeof source !== 'string') {","            return next(new Error('Cannot replace %f or %b when using an input stream'));","          }","","          pattern = pattern","            .replace(/%f/g, path.basename(source))","            .replace(/%b/g, path.basename(source, path.extname(source)));","        }","","        next(null, pattern);","      },","","      // Compute size if needed","      function getSize(pattern, next) {","        if (pattern.match(/%[whr]/)) {","          if (fixedSize) {","            return next(null, pattern, fixedSize[1], fixedSize[2]);","          }","","          getMetadata(function(err, meta) {","            if (err) {","              return next(new Error('Could not determine video resolution to replace %w, %h or %r'));","            }","","            var vstream = meta.streams.reduce(function(biggest, stream) {","              if (stream.codec_type === 'video' && stream.width * stream.height > biggest.width * biggest.height) {","                return stream;","              } else {","                return biggest;","              }","            }, { width: 0, height: 0 });","","            if (vstream.width === 0) {","              return next(new Error('No video stream in input, cannot replace %w, %h or %r'));","            }","","            var width = vstream.width;","            var height = vstream.height;","","            if (fixedWidth) {","              height = height * Number(fixedWidth[1]) / width;","              width = Number(fixedWidth[1]);","            } else if (fixedHeight) {","              width = width * Number(fixedHeight[1]) / height;","              height = Number(fixedHeight[1]);","            } else if (percentSize) {","              width = width * Number(percentSize[1]) / 100;","              height = height * Number(percentSize[1]) / 100;","            }","","            next(null, pattern, width, height);","          });","        } else {","          next(null, pattern, -1, -1);","        }","      },","","      // Replace size tokens (%w, %h, %r) in pattern","      function replaceSizeTokens(pattern, width, height, next) {","        pattern = pattern","          .replace(/%r/g, '%wx%h')","          .replace(/%w/g, width)","          .replace(/%h/g, height);","","        next(null, pattern);","      },","","      // Replace variable tokens in pattern (%s, %i) and generate filename list","      function replaceVariableTokens(pattern, next) {","        var filenames = config.timemarks.map(function(t, i) {","          return pattern","            .replace(/%s/g, utils.timemarkToSeconds(t))","            .replace(/%(0*)i/g, function(match, padding) {","              var idx = '' + (i + 1);","              return padding.substr(0, Math.max(0, padding.length + 1 - idx.length)) + idx;","            });","        });","","        next(null, filenames);","      },","","      // Create output directory","      function createDirectory(filenames, next) {","        fs.exists(config.folder, function(exists) {","          if (!exists) {","            fs.mkdir(config.folder, function(err) {","              if (err) {","                next(err);","              } else {","                next(null, filenames);","              }","            });","          } else {","            next(null, filenames);","          }","        });","      }","    ], function runCommand(err, filenames) {","      if (err) {","        return self.emit('error', err);","      }","","      var count = config.timemarks.length;","      var split = 'split=' + count;","","      for (var i = 0; i < count; i++) {","        var stream = '[screen' + i + ']';","        split += stream;","","        self.output(path.join(config.folder, filenames[i]))","          .seek(config.timemarks[i])","          .frames(1)","          .map(stream);","","        if ('size' in config) {","          self.size(config.size);","        }","      }","","      self.complexFilter(split);","      self.run();","    });","","    return this;","  };","","","  /**","   * Merge (concatenate) inputs to a single file","   *","   * @method FfmpegCommand#concat","   * @category Processing","   * @aliases concatenate,mergeToFile","   *","   * @param {String|Writable} target output file or writable stream","   * @param {Object} [options] pipe options (only used when outputting to a writable stream)","   * @return FfmpegCommand","   */","  proto.mergeToFile =","  proto.concatenate =","  proto.concat = function(target, options) {","    // Find out which streams are present in the first file input","    var fileInput = this._inputs.filter(function(input) {","      return input.isFile;","    })[0];","","    var self = this;","    this.ffprobe(this._inputs.indexOf(fileInput), function(err, data) {","      if (err) {","        return self.emit('error', err);","      }","","      var hasAudioStreams = data.streams.some(function(stream) {","        return stream.codec_type === 'audio';","      });","","      var hasVideoStreams = data.streams.some(function(stream) {","        return stream.codec_type === 'video';","      });","","      // Setup concat filter and start processing","      self.output(target, options)","        .complexFilter({","          filter: 'concat',","          options: {","            n: self._inputs.length,","            v: hasVideoStreams ? 1 : 0,","            a: hasAudioStreams ? 1 : 0","          }","        })","        .run();","    });","","    return this;","  };","};"];
"use strict";

_$jscoverage_done("lib/recipes.js", 4);
var fs = require("fs");

_$jscoverage_done("lib/recipes.js", 5);
var path = require("path");

_$jscoverage_done("lib/recipes.js", 6);
var PassThrough = require("stream").PassThrough;

_$jscoverage_done("lib/recipes.js", 7);
var async = require("async");

_$jscoverage_done("lib/recipes.js", 8);
var utils = require("./utils");

_$jscoverage_done("lib/recipes.js", 15);
module.exports = function recipes(proto) {
    _$jscoverage_done("lib/recipes.js", 26);
    proto.saveToFile = proto.save = function(output) {
        _$jscoverage_done("lib/recipes.js", 28);
        this.output(output).run();
        _$jscoverage_done("lib/recipes.js", 29);
        return this;
    };
    _$jscoverage_done("lib/recipes.js", 48);
    proto.writeToStream = proto.pipe = proto.stream = function(stream, options) {
        _$jscoverage_done("lib/recipes.js", 51);
        if (_$jscoverage_done("lib/recipes.js", 51, stream) && _$jscoverage_done("lib/recipes.js", 51, !("writable" in stream))) {
            _$jscoverage_done("lib/recipes.js", 52);
            options = stream;
            _$jscoverage_done("lib/recipes.js", 53);
            stream = undefined;
        }
        _$jscoverage_done("lib/recipes.js", 56);
        if (_$jscoverage_done("lib/recipes.js", 56, !stream)) {
            _$jscoverage_done("lib/recipes.js", 57);
            if (_$jscoverage_done("lib/recipes.js", 57, process.version.match(/v0\.8\./))) {
                _$jscoverage_done("lib/recipes.js", 58);
                throw new Error("PassThrough stream is not supported on node v0.8");
            }
            _$jscoverage_done("lib/recipes.js", 61);
            stream = new PassThrough;
        }
        _$jscoverage_done("lib/recipes.js", 64);
        this.output(stream, options).run();
        _$jscoverage_done("lib/recipes.js", 65);
        return stream;
    };
    _$jscoverage_done("lib/recipes.js", 97);
    proto.takeScreenshots = proto.thumbnail = proto.thumbnails = proto.screenshot = proto.screenshots = function(config, folder) {
        _$jscoverage_done("lib/recipes.js", 102);
        var self = this;
        _$jscoverage_done("lib/recipes.js", 103);
        var source = this._currentInput.source;
        _$jscoverage_done("lib/recipes.js", 104);
        config = config || {
            count: 1
        };
        _$jscoverage_done("lib/recipes.js", 107);
        if (_$jscoverage_done("lib/recipes.js", 107, typeof config === "number")) {
            _$jscoverage_done("lib/recipes.js", 108);
            config = {
                count: config
            };
        }
        _$jscoverage_done("lib/recipes.js", 114);
        if (_$jscoverage_done("lib/recipes.js", 114, !("folder" in config))) {
            _$jscoverage_done("lib/recipes.js", 115);
            config.folder = folder || ".";
        }
        _$jscoverage_done("lib/recipes.js", 119);
        config.timemarks = config.timemarks || config.timestamps;
        _$jscoverage_done("lib/recipes.js", 122);
        if (_$jscoverage_done("lib/recipes.js", 122, !("timemarks" in config))) {
            _$jscoverage_done("lib/recipes.js", 123);
            if (_$jscoverage_done("lib/recipes.js", 123, !config.count)) {
                _$jscoverage_done("lib/recipes.js", 124);
                throw new Error("Cannot take screenshots: neither a count nor a timemark list are specified");
            }
            _$jscoverage_done("lib/recipes.js", 127);
            var interval = 100 / (1 + config.count);
            _$jscoverage_done("lib/recipes.js", 128);
            config.timemarks = [];
            _$jscoverage_done("lib/recipes.js", 129);
            for (var i = 0; i <= config.count; i++) {
                _$jscoverage_done("lib/recipes.js", 130);
                config.timemarks.push(interval * (i + 1) + "%");
            }
        }
        _$jscoverage_done("lib/recipes.js", 135);
        if (_$jscoverage_done("lib/recipes.js", 135, "size" in config)) {
            _$jscoverage_done("lib/recipes.js", 136);
            var fixedSize = config.size.match(/^(\d+)x(\d+)$/);
            _$jscoverage_done("lib/recipes.js", 137);
            var fixedWidth = config.size.match(/^(\d+)x\?$/);
            _$jscoverage_done("lib/recipes.js", 138);
            var fixedHeight = config.size.match(/^\?x(\d+)$/);
            _$jscoverage_done("lib/recipes.js", 139);
            var percentSize = config.size.match(/^(\d+)%$/);
            _$jscoverage_done("lib/recipes.js", 141);
            if (_$jscoverage_done("lib/recipes.js", 141, !fixedSize) && _$jscoverage_done("lib/recipes.js", 141, !fixedWidth) && _$jscoverage_done("lib/recipes.js", 141, !fixedHeight) && _$jscoverage_done("lib/recipes.js", 141, !percentSize)) {
                _$jscoverage_done("lib/recipes.js", 142);
                throw new Error("Invalid size parameter: " + config.size);
            }
        }
        _$jscoverage_done("lib/recipes.js", 147);
        var metadata;
        function getMetadata(cb) {
            _$jscoverage_done("lib/recipes.js", 149);
            if (_$jscoverage_done("lib/recipes.js", 149, metadata)) {
                _$jscoverage_done("lib/recipes.js", 150);
                cb(null, metadata);
            } else {
                _$jscoverage_done("lib/recipes.js", 152);
                self.ffprobe(function(err, meta) {
                    _$jscoverage_done("lib/recipes.js", 153);
                    metadata = meta;
                    _$jscoverage_done("lib/recipes.js", 154);
                    cb(err, meta);
                });
            }
        }
        _$jscoverage_done("lib/recipes.js", 159);
        async.waterfall([ function computeTimemarks(next) {
            _$jscoverage_done("lib/recipes.js", 162);
            if (_$jscoverage_done("lib/recipes.js", 162, config.timemarks.some(function(t) {
                _$jscoverage_done("lib/recipes.js", 162);
                return ("" + t).match(/^[\d.]+%$/);
            }))) {
                _$jscoverage_done("lib/recipes.js", 163);
                if (_$jscoverage_done("lib/recipes.js", 163, typeof source !== "string")) {
                    _$jscoverage_done("lib/recipes.js", 164);
                    return next(new Error("Cannot compute screenshot timemarks with an input stream, please specify fixed timemarks"));
                }
                _$jscoverage_done("lib/recipes.js", 167);
                getMetadata(function(err, meta) {
                    _$jscoverage_done("lib/recipes.js", 168);
                    if (_$jscoverage_done("lib/recipes.js", 168, err)) {
                        _$jscoverage_done("lib/recipes.js", 169);
                        next(err);
                    } else {
                        _$jscoverage_done("lib/recipes.js", 171);
                        var duration = Number(meta.format.duration);
                        _$jscoverage_done("lib/recipes.js", 173);
                        if (_$jscoverage_done("lib/recipes.js", 173, isNaN(duration))) {
                            _$jscoverage_done("lib/recipes.js", 174);
                            return next(new Error("Could not get input duration, please specify fixed timemarks"));
                        }
                        _$jscoverage_done("lib/recipes.js", 177);
                        config.timemarks = config.timemarks.map(function(mark) {
                            _$jscoverage_done("lib/recipes.js", 178);
                            if (_$jscoverage_done("lib/recipes.js", 178, ("" + mark).match(/^([\d.]+)%$/))) {
                                _$jscoverage_done("lib/recipes.js", 179);
                                return duration * parseFloat(mark) / 100;
                            } else {
                                _$jscoverage_done("lib/recipes.js", 181);
                                return mark;
                            }
                        });
                        _$jscoverage_done("lib/recipes.js", 185);
                        next();
                    }
                });
            } else {
                _$jscoverage_done("lib/recipes.js", 189);
                next();
            }
        }, function fixPattern(next) {
            _$jscoverage_done("lib/recipes.js", 195);
            var pattern = config.filename || "tn.png";
            _$jscoverage_done("lib/recipes.js", 197);
            if (_$jscoverage_done("lib/recipes.js", 197, pattern.indexOf(".") === -1)) {
                _$jscoverage_done("lib/recipes.js", 198);
                pattern += ".png";
            }
            _$jscoverage_done("lib/recipes.js", 201);
            if (_$jscoverage_done("lib/recipes.js", 201, config.timemarks.length > 0) && _$jscoverage_done("lib/recipes.js", 201, !pattern.match(/%(s|0*i)/))) {
                _$jscoverage_done("lib/recipes.js", 202);
                var ext = path.extname(pattern);
                _$jscoverage_done("lib/recipes.js", 203);
                pattern = path.join(path.dirname(pattern), path.basename(pattern, ext) + "_%i" + ext);
            }
            _$jscoverage_done("lib/recipes.js", 206);
            next(null, pattern);
        }, function replaceFilenameTokens(pattern, next) {
            _$jscoverage_done("lib/recipes.js", 211);
            if (_$jscoverage_done("lib/recipes.js", 211, pattern.match(/%[bf]/))) {
                _$jscoverage_done("lib/recipes.js", 212);
                if (_$jscoverage_done("lib/recipes.js", 212, typeof source !== "string")) {
                    _$jscoverage_done("lib/recipes.js", 213);
                    return next(new Error("Cannot replace %f or %b when using an input stream"));
                }
                _$jscoverage_done("lib/recipes.js", 216);
                pattern = pattern.replace(/%f/g, path.basename(source)).replace(/%b/g, path.basename(source, path.extname(source)));
            }
            _$jscoverage_done("lib/recipes.js", 221);
            next(null, pattern);
        }, function getSize(pattern, next) {
            _$jscoverage_done("lib/recipes.js", 226);
            if (_$jscoverage_done("lib/recipes.js", 226, pattern.match(/%[whr]/))) {
                _$jscoverage_done("lib/recipes.js", 227);
                if (_$jscoverage_done("lib/recipes.js", 227, fixedSize)) {
                    _$jscoverage_done("lib/recipes.js", 228);
                    return next(null, pattern, fixedSize[1], fixedSize[2]);
                }
                _$jscoverage_done("lib/recipes.js", 231);
                getMetadata(function(err, meta) {
                    _$jscoverage_done("lib/recipes.js", 232);
                    if (_$jscoverage_done("lib/recipes.js", 232, err)) {
                        _$jscoverage_done("lib/recipes.js", 233);
                        return next(new Error("Could not determine video resolution to replace %w, %h or %r"));
                    }
                    _$jscoverage_done("lib/recipes.js", 236);
                    var vstream = meta.streams.reduce(function(biggest, stream) {
                        _$jscoverage_done("lib/recipes.js", 237);
                        if (_$jscoverage_done("lib/recipes.js", 237, stream.codec_type === "video") && _$jscoverage_done("lib/recipes.js", 237, stream.width * stream.height > biggest.width * biggest.height)) {
                            _$jscoverage_done("lib/recipes.js", 238);
                            return stream;
                        } else {
                            _$jscoverage_done("lib/recipes.js", 240);
                            return biggest;
                        }
                    }, {
                        width: 0,
                        height: 0
                    });
                    _$jscoverage_done("lib/recipes.js", 244);
                    if (_$jscoverage_done("lib/recipes.js", 244, vstream.width === 0)) {
                        _$jscoverage_done("lib/recipes.js", 245);
                        return next(new Error("No video stream in input, cannot replace %w, %h or %r"));
                    }
                    _$jscoverage_done("lib/recipes.js", 248);
                    var width = vstream.width;
                    _$jscoverage_done("lib/recipes.js", 249);
                    var height = vstream.height;
                    _$jscoverage_done("lib/recipes.js", 251);
                    if (_$jscoverage_done("lib/recipes.js", 251, fixedWidth)) {
                        _$jscoverage_done("lib/recipes.js", 252);
                        height = height * Number(fixedWidth[1]) / width;
                        _$jscoverage_done("lib/recipes.js", 253);
                        width = Number(fixedWidth[1]);
                    } else {
                        _$jscoverage_done("lib/recipes.js", 254);
                        if (_$jscoverage_done("lib/recipes.js", 254, fixedHeight)) {
                            _$jscoverage_done("lib/recipes.js", 255);
                            width = width * Number(fixedHeight[1]) / height;
                            _$jscoverage_done("lib/recipes.js", 256);
                            height = Number(fixedHeight[1]);
                        } else {
                            _$jscoverage_done("lib/recipes.js", 257);
                            if (_$jscoverage_done("lib/recipes.js", 257, percentSize)) {
                                _$jscoverage_done("lib/recipes.js", 258);
                                width = width * Number(percentSize[1]) / 100;
                                _$jscoverage_done("lib/recipes.js", 259);
                                height = height * Number(percentSize[1]) / 100;
                            }
                        }
                    }
                    _$jscoverage_done("lib/recipes.js", 262);
                    next(null, pattern, width, height);
                });
            } else {
                _$jscoverage_done("lib/recipes.js", 265);
                next(null, pattern, -1, -1);
            }
        }, function replaceSizeTokens(pattern, width, height, next) {
            _$jscoverage_done("lib/recipes.js", 271);
            pattern = pattern.replace(/%r/g, "%wx%h").replace(/%w/g, width).replace(/%h/g, height);
            _$jscoverage_done("lib/recipes.js", 276);
            next(null, pattern);
        }, function replaceVariableTokens(pattern, next) {
            _$jscoverage_done("lib/recipes.js", 281);
            var filenames = config.timemarks.map(function(t, i) {
                _$jscoverage_done("lib/recipes.js", 282);
                return pattern.replace(/%s/g, utils.timemarkToSeconds(t)).replace(/%(0*)i/g, function(match, padding) {
                    _$jscoverage_done("lib/recipes.js", 285);
                    var idx = "" + (i + 1);
                    _$jscoverage_done("lib/recipes.js", 286);
                    return padding.substr(0, Math.max(0, padding.length + 1 - idx.length)) + idx;
                });
            });
            _$jscoverage_done("lib/recipes.js", 290);
            next(null, filenames);
        }, function createDirectory(filenames, next) {
            _$jscoverage_done("lib/recipes.js", 295);
            fs.exists(config.folder, function(exists) {
                _$jscoverage_done("lib/recipes.js", 296);
                if (_$jscoverage_done("lib/recipes.js", 296, !exists)) {
                    _$jscoverage_done("lib/recipes.js", 297);
                    fs.mkdir(config.folder, function(err) {
                        _$jscoverage_done("lib/recipes.js", 298);
                        if (_$jscoverage_done("lib/recipes.js", 298, err)) {
                            _$jscoverage_done("lib/recipes.js", 299);
                            next(err);
                        } else {
                            _$jscoverage_done("lib/recipes.js", 301);
                            next(null, filenames);
                        }
                    });
                } else {
                    _$jscoverage_done("lib/recipes.js", 305);
                    next(null, filenames);
                }
            });
        } ], function runCommand(err, filenames) {
            _$jscoverage_done("lib/recipes.js", 310);
            if (_$jscoverage_done("lib/recipes.js", 310, err)) {
                _$jscoverage_done("lib/recipes.js", 311);
                return self.emit("error", err);
            }
            _$jscoverage_done("lib/recipes.js", 314);
            var count = config.timemarks.length;
            _$jscoverage_done("lib/recipes.js", 315);
            var split = "split=" + count;
            _$jscoverage_done("lib/recipes.js", 317);
            for (var i = 0; i < count; i++) {
                _$jscoverage_done("lib/recipes.js", 318);
                var stream = "[screen" + i + "]";
                _$jscoverage_done("lib/recipes.js", 319);
                split += stream;
                _$jscoverage_done("lib/recipes.js", 321);
                self.output(path.join(config.folder, filenames[i])).seek(config.timemarks[i]).frames(1).map(stream);
                _$jscoverage_done("lib/recipes.js", 326);
                if (_$jscoverage_done("lib/recipes.js", 326, "size" in config)) {
                    _$jscoverage_done("lib/recipes.js", 327);
                    self.size(config.size);
                }
            }
            _$jscoverage_done("lib/recipes.js", 331);
            self.complexFilter(split);
            _$jscoverage_done("lib/recipes.js", 332);
            self.run();
        });
        _$jscoverage_done("lib/recipes.js", 335);
        return this;
    };
    _$jscoverage_done("lib/recipes.js", 350);
    proto.mergeToFile = proto.concatenate = proto.concat = function(target, options) {
        _$jscoverage_done("lib/recipes.js", 354);
        var fileInput = this._inputs.filter(function(input) {
            _$jscoverage_done("lib/recipes.js", 355);
            return input.isFile;
        })[0];
        _$jscoverage_done("lib/recipes.js", 358);
        var self = this;
        _$jscoverage_done("lib/recipes.js", 359);
        this.ffprobe(this._inputs.indexOf(fileInput), function(err, data) {
            _$jscoverage_done("lib/recipes.js", 360);
            if (_$jscoverage_done("lib/recipes.js", 360, err)) {
                _$jscoverage_done("lib/recipes.js", 361);
                return self.emit("error", err);
            }
            _$jscoverage_done("lib/recipes.js", 364);
            var hasAudioStreams = data.streams.some(function(stream) {
                _$jscoverage_done("lib/recipes.js", 365);
                return stream.codec_type === "audio";
            });
            _$jscoverage_done("lib/recipes.js", 368);
            var hasVideoStreams = data.streams.some(function(stream) {
                _$jscoverage_done("lib/recipes.js", 369);
                return stream.codec_type === "video";
            });
            _$jscoverage_done("lib/recipes.js", 373);
            self.output(target, options).complexFilter({
                filter: "concat",
                options: {
                    n: self._inputs.length,
                    v: hasVideoStreams ? 1 : 0,
                    a: hasAudioStreams ? 1 : 0
                }
            }).run();
        });
        _$jscoverage_done("lib/recipes.js", 385);
        return this;
    };
};