forked from fluent-ffmpeg/node-fluent-ffmpeg
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcoverage.html
355 lines (308 loc) · 344 KB
/
coverage.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
make[1]: entrant dans le répertoire « /home/niko/dev/forks/node-fluent-ffmpeg »
<!DOCTYPE html><html><head><title>Coverage</title><script>
headings = [];
onload = function(){
headings = document.querySelectorAll('h2');
};
onscroll = function(e){
var heading = find(window.scrollY);
if (!heading) return;
var links = document.querySelectorAll('#menu a')
, link;
for (var i = 0, len = links.length; i < len; ++i) {
link = links[i];
link.className = link.getAttribute('href') == '#' + heading.id
? 'active'
: '';
}
};
function find(y) {
var i = headings.length
, heading;
while (i--) {
heading = headings[i];
if (y >= heading.offsetTop) {
return heading;
}
}
}
</script>
<style>
body {
font: 14px/1.6 "Helvetica Neue", Helvetica, Arial, sans-serif;
margin: 0;
color: #2C2C2C;
border-top: 2px solid #ddd;
}
#coverage {
padding: 60px;
}
h1 a {
color: inherit;
font-weight: inherit;
}
h1 a:hover {
text-decoration: none;
}
.onload h1 {
opacity: 1;
}
h2 {
width: 80%;
margin-top: 80px;
margin-bottom: 0;
font-weight: 100;
letter-spacing: 1px;
border-bottom: 1px solid #eee;
}
a {
color: #8A6343;
font-weight: bold;
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
ul {
margin-top: 20px;
padding: 0 15px;
width: 100%;
}
ul li {
float: left;
width: 40%;
margin-top: 5px;
margin-right: 60px;
list-style: none;
border-bottom: 1px solid #eee;
padding: 5px 0;
font-size: 12px;
}
ul::after {
content: '.';
height: 0;
display: block;
visibility: hidden;
clear: both;
}
code {
font: 12px monaco, monospace;
}
pre {
margin: 30px;
padding: 30px;
border: 1px solid #eee;
border-bottom-color: #ddd;
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
-webkit-box-shadow: inset 0 0 10px #eee;
-moz-box-shadow: inset 0 0 10px #eee;
box-shadow: inset 0 0 10px #eee;
overflow-x: auto;
}
img {
margin: 30px;
padding: 1px;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
-webkit-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
-moz-box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
box-shadow: 0 3px 10px #dedede, 0 1px 5px #888;
max-width: 100%;
}
footer {
background: #eee;
width: 100%;
padding: 50px 0;
text-align: right;
border-top: 1px solid #ddd;
}
footer span {
display: block;
margin-right: 30px;
color: #888;
font-size: 12px;
}
#menu {
position: fixed;
font-size: 12px;
overflow-y: auto;
top: 0;
right: 0;
margin: 0;
height: 100%;
padding: 15px 0;
text-align: right;
border-left: 1px solid #eee;
-moz-box-shadow: 0 0 2px #888
, inset 5px 0 20px rgba(0,0,0,.5)
, inset 5px 0 3px rgba(0,0,0,.3);
-webkit-box-shadow: 0 0 2px #888
, inset 5px 0 20px rgba(0,0,0,.5)
, inset 5px 0 3px rgba(0,0,0,.3);
box-shadow: 0 0 2px #888
, inset 5px 0 20px rgba(0,0,0,.5)
, inset 5px 0 3px rgba(0,0,0,.3);
-webkit-font-smoothing: antialiased;
background: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAGYAAABmCAMAAAAOARRQAAABelBMVEUjJSU6OzshIyM5OjoqKy02NjgsLS01NTYjJCUzNTUgISMlJSc0NTUvMDA6PDwlJyg1NjYoKis2NjYrLS02ODkpKyw0NDYrLC04ODovLzA4Ojo0NDUtLy86OjwjIyU4OTosLS82ODgtLS8hIyQvMTEnKCooKSsrKy0qLCwkJSUnKCkrLCwpKiwwMjIxMzMqLC0tLS0pKissLC00NTYwMDIwMTQpKysoKSovMDEtLzA2OTkxMzUrKywvLy8qKyszNTY5OzsqKiw6OjswMDExNDUoKiozNDUvMDIyNDY1Njg2Njk5OTozMzU0NjY4ODkiIyUiIyQ4OTkuMDEmKCowMjQwMTErLS4qKywwMTMhIiMpKiopKy0tLjAkJScxNDQvLzExNDYyNDQmKCk5OTslJig5OjskJSYxMzQrLS8gISIwMTIoKCk1NTUlJSUnJygwMDA4ODgiIiMhISI8PDw6Ojo5OTkpKSojIyQ7OzsyMjIpKSssLCw6Ozw1NjlrfLakAAAg2UlEQVR42jR6i3ea6rYvPgANIAhVXh8WvkQlioUiFlFcBtAmoiRNdzxqu9p0J7vrdK29zuPeex77nnvO/35n1r1ndHRktI0jTOacv/l7lCBK5UqVpOha/YxmWK7BC4TQFKVXrbYsnimqxuuMVlOQ0XltWjUdCwRJ1M+tC1KudOs9q6+da2adUewG0SC0SwELfHtgDds93VEuydEbl3QMWeNoYkR7b/0x1ZRobGI3mLwzAhePqTAwhg6aogjNsGy7/jwQ4rkdqe7CWLxF8k9LfMVFyRS7VJqtkrW8Vt/bkR8FZJao16ipknbC3Yw2lM7laO6HBEOadEZ2tpf65c4v8e3u7FyU6qbiNNyCuzXZ6pawgnwgmrpTT/Q7w2EZmiIJ0dzWDI7mhQ80IfRnMu2kzA5r5r1pIFoia+/d93HRYp1GV8TbrkWoU/+jdI0Ff6yGwTjT1Hn8J+8m1rKpGiYPuNiHnMtNMIv+zpsk84MYTNW1/+DpwXLvckdOCMYowVNPREe0QlM8xRHXXFhcNDzupwsSmb5pH+0t0RP2Qk+QtI7F1Qm6JRC6ZPBtPq/dq/kH+jxtCljn9TIpW6rQIgmSVyj6lPICIw4N/taka41PFUInth0je9+jO6Kt1G4/a7V2LEgG02B0pHVuCZrgltSKMuIl5SyufUv9mYuQi+mFgzbBEtFo2g+Dh4sSTrLNu8JPh00sQydpb00tqXBvqRN7Q7kqzcnIxCGnvZt/WmJacoOEO6Dcn8Qre03pOCSQxbMOXUuDNx9SxuLz4W1I18gvjViQ67zV0rxdWL8Te/TQkuo8STS41DR48W7L6YP2uWIqiUV8rd6Gbf/rnegKZeG8TpAM6afhGze9JAOxbLjsnUXEbrZ9vLYd7MT32cPF5mKKxmjy7huaoD9n62GOxni3iIJwv0IzZAZjdZkUtolCNLVfYZNaquFjGszVVf+J0vrz4CawoKdHnOzb0NMH7CDBOybfYNJ4rfeMyFNjkFYVTzMFs87rnPGXLUOeNKRVc0LnU7/UIgelzsy3CMuth0YfvnY0wsD3vODUL3eJcKqHQpm8yM3XZQWJxO6Un9iYloyyLpOwN2obHy6W6gbpcb44XmyC+mg+itAcaprGcrwZCqMj/GmtKn0zPvpTz/Cv1dw21XwP3cRupg3H3MF/S71eTKj1YrdwKdc2Mw0fRmb2sFf8lW3aU6JbIZSEPqvXvjM7G/aApyXlXeqKfMq0g/Su3rUGJPSPrtGElgknrZM3xUXqsAP6zMCNVn5u8aJnSNpJv2uru7t2jfRziW2+GuhqfldUNbPk71olwo+46ePUo1U3WKk/e5YK07F/wGRgcpODmQnIlVeHCWBE4puBi2jq28UKpqiN1/4UOrGz59TNYrrQHtd+11sG40BGD+pXdelNqGOg4NXe8W4eacJV/NS9/2Umtym6WQqveqR9xdCMElpxnbkalM4Vf9uaEcWZaKdyibEIjWKxJZPN95niCL3GiaXyssIrHxoLkqkzLCXULN46/f2h3tQJgyip+Tk9EAjJ9aJshq7t8X45aowSKspMSvPf7r9R8yxNptIaHS5ozuEm6luPDApugyNP8OaqiQ4BjaequXA54SLC83eHIY2r+CZp4409Xqw8Aa2oI7XkCrQi+in0w5AqF/kLNrcUz+qkl/lAobY1jSnx5OJNhyXIz3qfNFlXc0TKaglNwdWkWYt9QQ1Kr6W8zue21iNrdJk+N5oCr2O9nEtWKC7IS5J/zdDEYrmnAYfg6agCy+qcgz7ZofeDc4PbUWSvkshWuAc7OjiUyLkj+RAtdlwXJcjxdpkTTHDhK8lBCi8+JtvDVL1W6elmOM++YS0LuSlaP1oUvAeiW3cFnvTr8EbTz1tsSMYdGeZe40sRWu5uAfj7q+ZoKv2FNQ0p5XY1lmlcigHZqTPpabufEVrNuNPi165w3uCVQJHyJqmSJ7ZHnguqwtCmwViIJijj04ba2JNYtB+yORf5gg1/9t9iw4vUpeqiunSAbf+IBdj/b+iG2qrHvuNP0Vd/+ThVZT/lrvHYjjgDbbyxaqgHNM2uhxa1GW3UedZYhMMwM4mQhltouK+IV4NdbIQNM+8Yv311RZk9kT4tiYR4LkyFcuPpdcjuhUuFqBAWRZa11lcZ3gEBlXywsNhrt+plISZP5DlsV9l4EgY6J3yZPTUcMrgaWAT3oI79eSbGEbcJpr6BD8kyDiVt+G0/hXosQN4NFXKlfWIfsIs0BHODVok1/IGnKFHJYIquh8Xo+2+bkQNTGgWmN/fZ0Y33LSj6lr1GyV7mWIKg7ZTRZPGuhF/zjRNcQ1UPtSYgnWQxSs0yrVhwNDcdGMNSNe2JT3WuzbAM3HykyAajS3Uphf6STKEqxLas9EnmnhA/lyj9Uj+JoY7SVgVmGLl46Rm2u98sbkap2lzAdKBG4r6LgulQOSSjQv1GWdQ0jtDUK/mAaqM1Uqjpu4k3Rvfvxv7YTxLSK+wN3E5jVIzmF23uZ7hiH/sVP49D7tvoKp4S8b1LuvRlivVB/algbhcFITYVXvDpLzpDfplR2uD5V4XJFxpjmIpLc9Y5sB2TpBRix7Bme6GZIq+06v3XzNeTcA4obQIKxrnT4C2JpOqD92dbmSX8MGazly5EsZVMvSU1f4RZwyu8iQXbVdeLlZrjuTT1jrY1uk5c7iZ7RsvhhluqAkq4JpVQAg7RJFtSu+xgJ8Pv6O1j5DkLxT8mkbfyRW5DrQmG7hiDIjCgBsADbjuof6YHLGeV6a5Q1Smx9joUXPpdaaDx97A/Wq00oJkdR7ZYuQRfS533JtxO1erduqWOYIt3wh0wpbLuCNIYkwxbswbikCUu2CDCS+Q+7rgVtfRcm+SOcdKPRlZ/rE7wNVUEE39KTS5uvUKN1PUnkloPkyzhyGQ8qkouEjJ3H/VXdqG6asSRiw3ecMlBvDDt8dDhBHXMwZ2Cajzjr7/76T+IavqPYvz6r7//E/3X3+N//h/0QozbjPgPiir69P/8X3/9F/yv8b/827/++98WItPu5/Hvwd8YPf5bp/2/lX/T/+Of/0MJ/lYTa+L/Ef+d9vN/3/2T6P/+jyTzu/evf6U7vxN7B6pJkRtAF6jUr8I+P8RsP/ptGhfqFk+pQ/DgAy6NJtRYJdXmp4gK7WLqLKJ+MaKhGjOojvL+SnIWrkpy0SLHDe4QuyNzaEA15mLMCcmE8Em+4HdOihW4/ZWuppJEmzeAwcDtv7MuLc9y2V5atvxXNe3S4DUMt5/Qy2LM9kSYKiVWBuKlfp4nxTntpuW03JbIlkiRvBXmT23g1I2OYe6IizUHPIq6zm6mbfsbteKmi/sg9J+ocQBMctGFO7iljo8TPN+z3jxw4do+ZwfqoR9dkNTKHyM305GpTkfhcHexVkPVGEbUOjuo9f0UMPHBFlGEx0SLvJvVRKTwW7PSew5oPme+E42+frJa9cGt2njS3dK5kIif2eYbhuSEQXEqMVfUjhGIuin0G0/W5ezJyJQy3SpMLai4M0JUWb5u1k9tny5bd1pPwYBpQuDCXZl62xg4CdVEAtflXHs6JKmP/pH6mOl796Lgopj0o8d5kKh00hxG3OSdEE/QBo9Hgr8JJqAeLDwJohG5j/DGh61Rc/+tf22/8kEnxHNCEjo0ElvvGfESZkqmz2BDcKV1H1buSkhkdg7p1IMGs2s17nYjpblrWuE2K9WEO/hcRp5e9oOF/QBmOaDtgil+oaU6szPrdwW65fOB0KUTsVUn7LFU7J8e6cxJIl9+FHw5MQMzuQJ+4oxMH3iW/5GK+hWuG0T+gTLs+fAjdtUd58TmIUq04EeyRCYCjkldow234aIgR5bqwrtZosZ+6YEqAmDqatJ9lWasz4IquKALPtd92hGI3Z2BdzzZue+REl1Om4DIWD+RrtUTOJLI+S0jHowXXdAxsGLSd40zYNuEUlOGhrwL6c7tcOtUOvpJCP7QBQS19H+GvZn05ewjlVLz+IGKoC9TyfQjLMBNmXCuqqtTdOSukZW48B0HqgSTCBrBnlFvF4CG2Su7yFzqmJFURK3UmTT3ru050r0ptUpMilYnBJWfl2Bv6kPlUuE1kxxpdzui9AubsR2N2boVSu81OulAwBqoSr1LZ0LLYOomyZHmjqnXlP72s8LnDouEJjtodBvdHaG1jMySYO7crWd90MpCRyCG14vb5IE7Arupw/y/RcCm/Tm3zK6zYj8PYNaGldiUfkB/LHWcmf2lVM+mwyU27a0qq2tscrQ/vzBjN26DnntIrOyGizzXK35yKQdYnUABkyN4saz3WD/viF+eCcsXnIajdWYJWaYHRstIis9CS+tqnFGmz2j5uzfr3Z4prqgK4XOT/PyftvjZqIm8lhkfxJ7Ol3CJF1piYBGAG8wtAk56Drw1YwmOpcz+NdfkSpSLplRXLXHL0Rquj6YW/gabqgK7Dgr6NwtH0B/AN7XrN+MVJ6AmXmUuqmQulrNNYPmH0RoDogydOKLo/QbfYNARSQQKISRCzRXU+q9WWJFL3LZW6u34CkeG97xC0NNGaJ0bvK6SnZS3zPskr5EtuCgjMWR5o2x5BqhKmDWJPRe7JMEOyRb5uUKlHaGVtq5ivSOaSliSXp9SQm2qk8MRJh10MAp9QQ2H5t59J8rjiwSZtoIfMGjlLPVNdYl/LBR0AO6WLGDmkLkIPRE45Y9MftdAK/yNu1Hn6tzOQTesgQ+8fSzB19wO91vCnO23vOWQdwJ63SJrYjdfKFW6W281PKs2k8iT9ai1cgJ4sa3xqdvmtxR8/+D1B8AKc2u+6JftryRhMWSQtoSBgIyyQGyxcnELuAasXN12oSriU4RMz1DD6RL0TSV+om7i1Yt+jEE/jnawM8cX/UhN4nkiv/w9eALrzNhXuQfOzFL0Fi6SjF7/4Qn8rLYBoa85cvgAnkCEBP+HPbEnquVXCZsMS/yzYw2Vru60P/+nJPYKkzZFjmbykzUoEqV836T5q3fP/L383dF82tx18/AZgZczMAgyeWYKmSZIqtHL+e+O4ZRcq9VI3g/qPeCoiK4pcgEqdbS0S/Be54sbVQOuJVPNBblIghzeasNu7h/g+Sz1IdhI5lCwq1nUb3Ji4OCIcqQZqtqJ5w7rXrg/DA9IgVmEGhDgGecEwnCTHffXcXs0V3OCEVzYDKS1vp/oX+ng+6XVU86UjA6FMO2RXOOOrqY1GgPvrAk9HV/BXtCu5RuwF8qgdGDLsBcui4E33ymdBip1X8uKyhIWT8qNRDsXz+gvO9UiEC0d8RG4Tf2x8H4slljgHtCBcxHLTWOYJm5H/fCPCzOgf9qgOUxTRZ0Pc6ha5yLuLVT9ntvIa6gacE99mCovdUumTQdRP4RPsS9129eEe2uSvvGh0bV4Y3QPPhPZMqhZWSMa5R0Hc1SGO4IVOQc0FrirlibTVfKRrYkD8kz3b+X65/QkUNaZdrdl3mCap0Hf3YcCw/LiouJYNbqz88UqeDYv93yO7vvXtgl4XCyAO4ODkY6W+83+LZU//p3/zXNGGrUKClCiOnL27iJZbNWDF02XXAOeFlB7IaADoMH1Yqr+UP9biyZDEa/iJt4MDeIz6GKTdLVBfWGVtRN4fdT2rgReX8UXwF2zOrradm4J0nyTgdPnai3RvzpZvCKDUqjOwD/QA6EDaMCLewX6QWYVnHY1sx1bd8ovYnPm1ZvPH+rE20lWjOCnZ66/xDt0QAl15FjfBcZp+i9OU0RNPQ0t3x2pSNWo8eiYudwsnuP1Hq6iH1LJCJynkYsfgJ0p3pF6SoQk2l+jqE8CPk+ziGJRSKjs+W5AO185umPdkYzlK4wl7TC9NxyyDP7ZoyYVoXiuS6SjnInlLWrwz1i8bGTKXX0AVQWkSfIlglW3zRJRJ8bg5VgE6ZEnqNu9B++0GNQvDQJvFize4ESNKBJP+8vA3LM4AX5SIBq08Mob+7QMTCZx4nwP/64+4BnlZC+8WtlP/CXw6t1PwMwkJ3jhP1FiXLhDF/3I6FGUzO2DSi9ABxKyyL9paZxSEz40ZCPQToDAJu1959k7QdbVxgB4icsu2s4zsTPJhcEDo+N1GX4zSk/wriRh8AqwL62972i9HJHd1ydaLXVzvKvOfGGw5RVcUVMiKXFH4APdkQU/dc5BX0YfKTNZYXCW9mb8bc8mufoQP6BbdQmT99ZjoYfr/go4TgQX9IDgztim7wyFeGMfbNaeqj8Dzs38pgcqwSv2hbqB3oSGKWKy+sesY7p57wAHldqE6NDudk/W7s/zjrK4rZFlFvaGxnSZdHbc1y47qDN6xkoK8O3bfr2j41dlJZ71rB4dlDqapPFa8N6xBrprUdtenUCHwxKNhw1uuTBh+9uU45k4REpQABN2bAO9DSLqoIL26gNroWgup5pUMxHUNSq4Gyz47vBPvilpo5f9OYI2ddAqTqmnxXERxQJ3UK8fHbVE9HagHi3+tqNRoNsArdmAxHA5LwtQo9ZAaNKUTljnokljo2x8scqVpEEIPc01fPCdHOCg0DeWBz8D5TVAAfx8aRH5X2ZYNI3ebKDZdeJ+oBDAxmRqJ30Eh2/DaeAy5diVNMpEDmXiPDsGTzBLXy8eVDdJoIafgx/gxMyQi454QrW56nCyeELgSuNNEmYkflF+t3CZQOVRWjKhIuCclmQSlAXT3+4JGG75B4t/5hQ+ldMP4LsAW6z3XmU6IJJwpnGVnsgUZhoY1fZlwTR8wSU7xRejf2uCx9Z5trVTRRJP9KnEb134dEieil6eCOGWgboI7xsqsqM99jfJLTePjygKlH2CVxxsse9QRzTBFjD/Kjqitr/CCTBt/SJ6nLxz7cKP9pFqBpp0lN5y+adKNsZjrPuroemZauH9aTTFD3EKHW8S55XBLFQAt1jgxTQCTwxmx/JyfsZDN1RroN3VaxpSenpIX7K+ZbL8VdlQDcI4Cbzg3QJLa9yVqNxUelu+EtxLVqeekaAvSJkO6sSVqbUajxqhKshNpvZqoeApF0k/0P0ikkwUcbdwc4A1ejN7Oo0O15kG7hTMoK3hZRBCX7YYeLW0wvcXx/18n/u37yLgzBYVBUvORGli+sfRcX/74uD6P4hq+7xu54TlWJLFzT63uwUDwuEDdOjJQqx7JV+ZjaEAPi7t0MMrR4Q8Rkf18uxD6RK0RKh0hL8YU+DeL97i4pa5ZSyAfXKwZRS/8gXcxdZXm62RBDj8U3sN8x95b5PpPs/mCBKYvpaA50pN5Ct/499AFTtwQ5vgeSh+NHrKIi4NVpwM/XzRaNfJD856lPE6M21zWPguFsH7jbLVyEDfRmt4VwrhCJ5VTYmcSPfGgO5clfN+vbaDZ7sakU5+2vZ2WCDY031NxJarVytfDDVtiafcTGO2rJ/taoL3zChN2qmjxofczTOYQPPVQPh0JVtYgdUQINcSiNEEy58UdYXX1MpWUCEBx7LbcGtAm8XWRQTVOaoV3ySri4RShhs/B/0m4jX6OAwXOvcA09bNSG4czEGv/Wey6V/jbTCNTW6awXdNTcA1GsPe1E9fZdGl7R0vyoVpIdJtfC6d32NNErrvq/R+d65VG+YOwRXppXxOCYyGNSf1K3x6VxAW/vtz4EC1SgCOSPdN62sLsoIzuDfg8GwZAbquVO8HIuFP/ToVoeUB7nnwMF35a1wK1tI6fkrqFKhQdeJpwyls0pIy8AZde3/6LUUbFaYJthyUJSU/kqDXTLQElnn0Jr4B2RVghNrmNmoEn7pXIeshPguXVsvwoTdmClq49JJU3LWhHyWTrJL9bRP6VKv3tZoA/th77p5Jw++OEENvyvWy/pNeExiDUVQaXIRGh8xySZTI36yueFaSXo1uJY0RnXYgEOoWWOJHeaVuX/bGNhHsh2yinznl/++NJcE9j6fBPRcBdq9hb8awNw8U7Bl6GM7x69EDOIIbX/npZ++amlHR9L/35mE/2Ss4gb0xCcY4VyTFLRE796vHysLAamqcyO+aFQyJIDBNslbH2/MrAvZiSEIedc/cqjmv4fbda2pXbv+F5a2szSsdkm9noiNURXt8edUhGUF6fSZWd1IJaXKFwD+49R6eCXD4Bkef7j9tRtNMVgW8BhRz/Qpy1TmeYk0doyjZoJSbePOReVHgkFsCFuQJ+Lgc4BxeAsK/cOiNDRmdNw0ctYhn/nQ498dYI5znzGLoJi1rav7Cn88rL3wLePVtDK5gl77Tki3gHEsIAQ2+IKgarj7Y8W1IQzV5V9N+0TjLqbg68WfKcOmBCOj3JkwJhVIkwDhc+JorXuZEPMEh0vvH3x7iqf+VAwXgd4diZiaJD1zHL9Snx6Wfg4IugreyhabQkcir+y5XgDtdx3Avs7lkeeCBwDvZoTUCXx5QrZkcEqWfYEiEYRs/EphmRALSNGR1Iclgdr5VFoELpzF4++f35w3/j0t5ucW3n2ch4PQCLuUXupsPRR7UA5FjSKrMtPcKAZJfagO4lGE7FH3YKMjorpK0ZxAv+i2JkJhtAMWWWFej4RhPR/cJ3DxwocCvXDi4SGZU4cu+K32XndiFWgopAl+0GApcwf1XvymJcFs39jExIBO4yUjU9MExBLQYc9H+W7+IgdESPRpciT+rKZPebVtaVq+1GYO/5xTAL3HASjNTGIgMvdjWbgc7JvdE1zIFpuC0U9ESiZyzBixzxWxj4Kwh8My34q+FK3KNLtmsA1qyrmKSNQOXCPUZd+ONelBTvFoUI/CYsqa/RhtKiyMf2CgSFqEPk59Y3uqnlZ8gFpswfSYyko23yVZYxzKGxGm49Zqxg1l8oz5Ra9XaRwHkuxepmgyhm0SoNy2KlbcEqK+9QqS9PNx9Ihm9U7gsR55SSJ1FBDNnkuWKxIZ0SDpXuOGwZdoUbOMDPHP4vBAgz2VlSEJAHZGJVbYIg7l/FO5KfIVvxC8pPPxMGcNMoevFDeStt2iqztE10n2TA4dgJH76YS9HDhKHD3iCx6ieFX84BAI3QQnngh76f5ruPQVbr5qZmck/5UjDc26lfrOvUBWy0Ogl8bCoOkMOns81TnC3cuUS9KW8+9A+fe3XYZOFUPG1u5epSSmDLw0s5s2F0W30ANeo+zJkJQz9SPZgzwYpEoktofhGVfmLOAB20boCbW1QWq/NpET/hnMecw/uSyAH4NJc3ECOU4nnkK1fj3S/i5dwb3R7k00AqQQUwt7Ie1qV0aY/VQX0J8hLPy7eBNXMHYZYDNxHZ2Qh6AuXJxq+AeRec/Q+JLhZV6hpXwQEzw7bf5v9uUf2vpq3qlhmy0IIGTkwYdCfSAFmqbdo+3XvDTDjFJde0mbeQLcn2n31xaAqJ0ixO/CLsT4I4G4DoncVTgRGNBtsCcjISWT+oeXZ4Iedw/8OsJI1aPnNKLX/60VvcZb94uasRxCkqlPQ11u1Sa2hHvB80WQENxVyzjns0/PiEByyil21Te6oisk3mNCEMrhouCFO3yEZTHHOCMy9eb/4Tmi8cVf3Lf7P53SY2hX3PSN033As3ETIMLHWumWEO9JXHA2y2SIBlIPpLGG2qvNsCIlIr+B1SWAqRKm2w6Blf7U+zCSBwJrfHG5i8J5Gax/cVonMlon7aHJX/gSvucIncRP93XCqkv7D8IFKFsLiBgHqUpXhE3pYjEcV1dk/JD9zFVCfEaQIVX8Jmfz7IIofcBKQ4OaG+C3xC2veX9CD+iAFXDNaGg9eTVxvkbJRJlW4Nk9Wk13kn696jWppRDe/8pDrYMO9ZyxZ98ReKSz9kWKLLyk2zCZgAniCkLJVX3n1M9DYbomyahWiv/KixRIV9hj/oFz87I+HLznbPTjpa+D+bZQnMuRsljTpv90vQUt/pK7jCFnA30B/jtroSF2/m/gpWn1aQs5WeA6ghzF8SdqWI20fghdSeDOCSCmLgTkfaGgGDmw7nHFkRzGtag57IHS2na06I+gzEphXo1w/Zx2BM/jKL2nZoFjHggtFQjYi8nSVRSXIE58RPbBObXk7uuIL9+rs/5Zo7suJInEUxgsiZZAWS25iBtpEiZeBgDtghEoAE0sjcayNq85M4tbu/LF5h51335PsGzQ09O875+vUS89lkWMyNOFoip2PuyWyMP/iU2XIZdfCCJNDjebDoBLQdpy7QQZC7s9c0wjHJervQNDu2jWzBW5MSAJMr7bP+Iv92BkS/GGgzjEn7MF1IRKFwwzbjbS4/slGOmhx9cZrFu7HSEefojNv3r0UaKfKOWzXsq1zEugbzlMDFsacRJJI/iJlK3vtkZ+PLZIVMFlKA32wbq2Kd5T0uCLZ1CPkAfCdzkz2EYscjDcZq2AWfziN2covN4kXE1lQXPPLTNM1xx3tbiepcO/t3SWm4w87qfh99SL0ZnY+LKFPLPeXVM2mIIoVWt+9Nk0I7nY4O79iGYqxZ8RVz289an6NVdJWnSKZvJQCAuHNiVaDxPAFoH392t9wot5t0/qmU95eEWNbU2udUW5sN9JVqcYlvAIfLeYC33oUzzxZgSktsv21mA7Uly1FA5VnoJFh6N244Wmv3YJGFv/TCPryaw+ZORlpZjQdq/2DYXr3EZskfed0G61P09ipTKmlTQ1067Rg5+PAk5FlQ9e0SWbGf2B/08kqymOTMVOznsALHHNFH4LFRKl2F/NOiYFl9khNHnSu9Ak5sq26Ynl/i2fdTle29Y1ugqmR5Yj4YT9pvslFyYCbw0mNFr5rVQm1LvkG27QMq9ph3t8fmn6r6SQ4oSbr5tz+J1kIawGzDxb6VYOvvWhobDTXfBeNv3b4aNm5XUinsCGqG2q/45m3+LoCOsddFceYhRx1Tsss9PLdPfJdErFMjYd3gddjiP0+XQjcRadZP6bwNLySvunFf20Czy6JqdEW2a96KxdYdOryBv1BjbuUq2yCHeh+6sk7fGmmPi50pe/1l5TyPe5oHW9oPnhPswLyf2TFDdCyYlhwBCstv5C1HwlW7xWoGT9XZt4qVj5WryLPLLD6h/5cMLEjWzgCeAIKNsLak92aBqBsHl4AJwl2N4jfvbSkBExGimv0nFvv09uDScQbjx+w4kPQjgjlW+g9ws9VEJvI2k8N6XxVu0uIwovgTFdunG24gBtaDi+y1YLQwZ8mwbip5fVlO3k0n0AEr/ETbtu8Vjkm+nNSiEb7X/3fMjBL5A8PdgG+/FnbexbFFExmEfetXAnisEKy5z44WVPpQZjSy/jzeGn4yDRsFGqhh87QPaDBWhlo37IFbe/C0xynS91d2tP/AJoJS0sVF6iwAAAAAElFTkSuQmCC");
}
#menu::after {
display: block;
content: '';
padding-top: 80px;
}
#logo {
position: fixed;
bottom: 10px;
right: 10px;
background: rgba(255,255,255,.1);
font-size: 11px;
display: block;
width: 20px;
height: 20px;
line-height: 20px;
text-align: center;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
border-radius: 20px;
-webkit-box-shadow: 0 0 3px rgba(0,0,0,.2);
-moz-box-shadow: 0 0 3px rgba(0,0,0,.2);
box-shadow: 0 0 3px rgba(0,0,0,.2);
color: inherit;
}
#menu li a {
display: block;
color: white;
padding: 0 35px 0 25px;
-webkit-transition: background 300ms;
-moz-transition: background 300ms;
}
#menu li {
position: relative;
list-style: none;
}
#menu a:hover,
#menu a.active {
text-decoration: none;
background: rgba(255,255,255,.1);
}
#menu li:hover .cov {
opacity: 1;
}
#menu li .dirname {
opacity: .60;
padding-right: 2px;
}
#menu li .basename {
opacity: 1;
}
#menu .cov {
background: rgba(0,0,0,.4);
position: absolute;
top: 0;
right: 8px;
font-size: 9px;
opacity: .6;
text-align: left;
width: 17px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
padding: 2px 3px;
text-align: center;
}
#stats:nth-child(2n) {
display: inline-block;
margin-top: 15px;
border: 1px solid #eee;
padding: 10px;
-webkit-box-shadow: inset 0 0 2px #eee;
-moz-box-shadow: inset 0 0 2px #eee;
box-shadow: inset 0 0 2px #eee;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
#stats div {
float: left;
padding: 0 5px;
}
#stats::after {
display: block;
content: '';
clear: both;
}
#stats .sloc::after {
content: ' SLOC';
color: #b6b6b6;
}
#stats .percentage::after {
content: ' coverage';
color: #b6b6b6;
}
#stats .hits,
#stats .misses {
display: none;
}
.high {
color: #00d4b4;
}
.medium {
color: #e87d0d;
}
.low {
color: #d4081a;
}
.terrible {
color: #d4081a;
font-weight: bold;
}
table {
width: 80%;
margin-top: 10px;
border-collapse: collapse;
border: 1px solid #cbcbcb;
color: #363636;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
table thead {
display: none;
}
table td.line,
table td.hits {
width: 20px;
background: #eaeaea;
text-align: center;
font-size: 11px;
padding: 0 10px;
color: #949494;
}
table td.hits {
width: 10px;
padding: 2px 5px;
color: rgba(0,0,0,.2);
background: #f0f0f0;
}
tr.miss td.line,
tr.miss td.hits {
background: #e6c3c7;
}
tr.miss td {
background: #f8d5d8;
}
td.source {
padding-left: 15px;
line-height: 15px;
white-space: pre;
font: 12px monaco, monospace;
}
code .comment { color: #ddd }
code .init { color: #2F6FAD }
code .string { color: #5890AD }
code .keyword { color: #8A6343 }
code .number { color: #2F6FAD }
</style></head><body><div id="coverage"><h1 id="overview">Coverage</h1><div id="menu"><li><a href="#overview">overview</a></li><li><span class="cov high">86</span><a href="#lib/capabilities.js"><span class="dirname">lib/</span><span class="basename">capabilities.js</span></a></li><li><span class="cov high">80</span><a href="#lib/ffprobe.js"><span class="dirname">lib/</span><span class="basename">ffprobe.js</span></a></li><li><span class="cov high">100</span><a href="#lib/fluent-ffmpeg.js"><span class="dirname">lib/</span><span class="basename">fluent-ffmpeg.js</span></a></li><li><span class="cov high">100</span><a href="#lib/options/audio.js"><span class="dirname">lib/options/</span><span class="basename">audio.js</span></a></li><li><span class="cov high">100</span><a href="#lib/options/custom.js"><span class="dirname">lib/options/</span><span class="basename">custom.js</span></a></li><li><span class="cov high">100</span><a href="#lib/options/inputs.js"><span class="dirname">lib/options/</span><span class="basename">inputs.js</span></a></li><li><span class="cov high">100</span><a href="#lib/options/misc.js"><span class="dirname">lib/options/</span><span class="basename">misc.js</span></a></li><li><span class="cov high">100</span><a href="#lib/options/output.js"><span class="dirname">lib/options/</span><span class="basename">output.js</span></a></li><li><span class="cov high">100</span><a href="#lib/options/video.js"><span class="dirname">lib/options/</span><span class="basename">video.js</span></a></li><li><span class="cov high">100</span><a href="#lib/options/videosize.js"><span class="dirname">lib/options/</span><span class="basename">videosize.js</span></a></li><li><span class="cov high">100</span><a href="#lib/presets/flashvideo.js"><span class="dirname">lib/presets/</span><span class="basename">flashvideo.js</span></a></li><li><span class="cov high">100</span><a href="#lib/presets/podcast.js"><span class="dirname">lib/presets/</span><span class="basename">podcast.js</span></a></li><li><span class="cov high">85</span><a href="#lib/processor.js"><span class="dirname">lib/</span><span class="basename">processor.js</span></a></li><li><span class="cov high">92</span><a href="#lib/utils.js"><span class="dirname">lib/</span><span class="basename">utils.js</span></a></li><a id="logo" href="http://visionmedia.github.io/mocha/">m</a></div><div id="stats" class="high"><div class="percentage">89%</div><div class="sloc">945</div><div class="hits">848</div><div class="misses">97</div></div><div id="files"><div class="file"><h2 id="lib/capabilities.js">lib/capabilities.js</h2><div id="stats" class="high"><div class="percentage">86%</div><div class="sloc">179</div><div class="hits">154</div><div class="misses">25</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true*/</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">4</td><td class="hits">1</td><td class="source">var fs = require('fs');</td></tr><tr class="hit"><td class="line">5</td><td class="hits">1</td><td class="source">var path = require('path');</td></tr><tr class="hit"><td class="line">6</td><td class="hits">1</td><td class="source">var async = require('async');</td></tr><tr class="hit"><td class="line">7</td><td class="hits">1</td><td class="source">var utils = require('./utils');</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source">/*</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> *! Capability helpers</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">13</td><td class="hits">1</td><td class="source">var avCodecRegexp = /^\s*([D ])([E ])([VAS])([S ])([D ])([T ]) ([^ ]+) +(.*)$/;</td></tr><tr class="hit"><td class="line">14</td><td class="hits">1</td><td class="source">var ffCodecRegexp = /^\s*([D\.])([E\.])([VAS])([I\.])([L\.])([S\.]) ([^ ]+) +(.*)$/;</td></tr><tr class="hit"><td class="line">15</td><td class="hits">1</td><td class="source">var ffEncodersRegexp = /\(encoders:([^\)]+)\)/;</td></tr><tr class="hit"><td class="line">16</td><td class="hits">1</td><td class="source">var ffDecodersRegexp = /\(decoders:([^\)]+)\)/;</td></tr><tr class="hit"><td class="line">17</td><td class="hits">1</td><td class="source">var formatRegexp = /^\s*([D ])([E ]) ([^ ]+) +(.*)$/;</td></tr><tr class="hit"><td class="line">18</td><td class="hits">1</td><td class="source">var lineBreakRegexp = /\r\n|\r|\n/;</td></tr><tr class="hit"><td class="line">19</td><td class="hits">1</td><td class="source">var filterRegexp = /^(?: [T\.][S\.][C\.] )?([^ ]+) +(AA?|VV?|\|)->(AA?|VV?|\|) +(.*)$/;</td></tr><tr><td class="line">20</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">21</td><td class="hits">1</td><td class="source">var cache = {};</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source">function copy(src, dest) {</td></tr><tr class="hit"><td class="line">24</td><td class="hits">125</td><td class="source"> Object.keys(src).forEach(function(k) {</td></tr><tr class="hit"><td class="line">25</td><td class="hits">741</td><td class="source"> dest[k] = src[k];</td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">29</td><td class="hits">1</td><td class="source">module.exports = function(proto) {</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">31</td><td class="hits"></td><td class="source"> * Forget executable paths</td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> * (only used for testing purposes)</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">35</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#_forgetPaths</td></tr><tr><td class="line">36</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">38</td><td class="hits">1</td><td class="source"> proto._forgetPaths = function() {</td></tr><tr class="hit"><td class="line">39</td><td class="hits">8</td><td class="source"> delete cache.ffmpegPath;</td></tr><tr class="hit"><td class="line">40</td><td class="hits">8</td><td class="source"> delete cache.ffprobePath;</td></tr><tr class="hit"><td class="line">41</td><td class="hits">8</td><td class="source"> delete cache.flvtoolPath;</td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">45</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">46</td><td class="hits"></td><td class="source"> * Check for ffmpeg availability</td></tr><tr><td class="line">47</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> * If the FFMPEG_PATH environment variable is set, try to use it.</td></tr><tr><td class="line">49</td><td class="hits"></td><td class="source"> * If it is unset or incorrect, try to find ffmpeg in the PATH instead.</td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">51</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#_getFfmpegPath</td></tr><tr><td class="line">52</td><td class="hits"></td><td class="source"> * @param {Function} callback callback with signature (err, path)</td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">55</td><td class="hits">1</td><td class="source"> proto._getFfmpegPath = function(callback) {</td></tr><tr class="hit"><td class="line">56</td><td class="hits">35</td><td class="source"> if ('ffmpegPath' in cache) {</td></tr><tr class="hit"><td class="line">57</td><td class="hits">29</td><td class="source"> return callback(null, cache.ffmpegPath);</td></tr><tr><td class="line">58</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">59</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">60</td><td class="hits">6</td><td class="source"> async.waterfall([</td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> // Try FFMPEG_PATH</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> function(cb) {</td></tr><tr class="hit"><td class="line">63</td><td class="hits">6</td><td class="source"> if (process.env.FFMPEG_PATH) {</td></tr><tr class="hit"><td class="line">64</td><td class="hits">3</td><td class="source"> fs.exists(process.env.FFMPEG_PATH, function(exists) {</td></tr><tr class="hit"><td class="line">65</td><td class="hits">3</td><td class="source"> if (exists) {</td></tr><tr class="hit"><td class="line">66</td><td class="hits">1</td><td class="source"> cb(null, process.env.FFMPEG_PATH);</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">68</td><td class="hits">2</td><td class="source"> cb(null, '');</td></tr><tr><td class="line">69</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">70</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">71</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">72</td><td class="hits">3</td><td class="source"> cb(null, '');</td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">75</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source"> // Search in the PATH</td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> function(ffmpeg, cb) {</td></tr><tr class="hit"><td class="line">78</td><td class="hits">6</td><td class="source"> if (ffmpeg.length) {</td></tr><tr class="hit"><td class="line">79</td><td class="hits">1</td><td class="source"> return cb(null, ffmpeg);</td></tr><tr><td class="line">80</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">81</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">82</td><td class="hits">5</td><td class="source"> utils.which('ffmpeg', function(err, ffmpeg) {</td></tr><tr class="hit"><td class="line">83</td><td class="hits">5</td><td class="source"> cb(err, ffmpeg);</td></tr><tr><td class="line">84</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">85</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">86</td><td class="hits"></td><td class="source"> ], function(err, ffmpeg) {</td></tr><tr class="hit"><td class="line">87</td><td class="hits">6</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">88</td><td class="hits">0</td><td class="source"> callback(err);</td></tr><tr><td class="line">89</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">90</td><td class="hits">6</td><td class="source"> callback(null, cache.ffmpegPath = (ffmpeg || ''));</td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">92</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">93</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">94</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">95</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">96</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">97</td><td class="hits"></td><td class="source"> * Check for ffprobe availability</td></tr><tr><td class="line">98</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">99</td><td class="hits"></td><td class="source"> * If the FFPROBE_PATH environment variable is set, try to use it.</td></tr><tr><td class="line">100</td><td class="hits"></td><td class="source"> * If it is unset or incorrect, try to find ffprobe in the PATH instead.</td></tr><tr><td class="line">101</td><td class="hits"></td><td class="source"> * If this still fails, try to find ffprobe in the same directory as ffmpeg.</td></tr><tr><td class="line">102</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">103</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#_getFfprobePath</td></tr><tr><td class="line">104</td><td class="hits"></td><td class="source"> * @param {Function} callback callback with signature (err, path)</td></tr><tr><td class="line">105</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">106</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">107</td><td class="hits">1</td><td class="source"> proto._getFfprobePath = function(callback) {</td></tr><tr class="hit"><td class="line">108</td><td class="hits">13</td><td class="source"> if ('ffprobePath' in cache) {</td></tr><tr class="hit"><td class="line">109</td><td class="hits">9</td><td class="source"> return callback(null, cache.ffprobePath);</td></tr><tr><td class="line">110</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">111</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">112</td><td class="hits">4</td><td class="source"> var self = this;</td></tr><tr class="hit"><td class="line">113</td><td class="hits">4</td><td class="source"> async.waterfall([</td></tr><tr><td class="line">114</td><td class="hits"></td><td class="source"> // Try FFPROBE_PATH</td></tr><tr><td class="line">115</td><td class="hits"></td><td class="source"> function(cb) {</td></tr><tr class="hit"><td class="line">116</td><td class="hits">4</td><td class="source"> if (process.env.FFPROBE_PATH) {</td></tr><tr class="hit"><td class="line">117</td><td class="hits">2</td><td class="source"> fs.exists(process.env.FFPROBE_PATH, function(exists) {</td></tr><tr class="hit"><td class="line">118</td><td class="hits">2</td><td class="source"> cb(null, exists ? process.env.FFPROBE_PATH : '');</td></tr><tr><td class="line">119</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">120</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">121</td><td class="hits">2</td><td class="source"> cb(null, '');</td></tr><tr><td class="line">122</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">123</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">124</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">125</td><td class="hits"></td><td class="source"> // Search in the PATH</td></tr><tr><td class="line">126</td><td class="hits"></td><td class="source"> function(ffprobe, cb) {</td></tr><tr class="hit"><td class="line">127</td><td class="hits">4</td><td class="source"> if (ffprobe.length) {</td></tr><tr class="hit"><td class="line">128</td><td class="hits">1</td><td class="source"> return cb(null, ffprobe);</td></tr><tr><td class="line">129</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">130</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">131</td><td class="hits">3</td><td class="source"> utils.which('ffprobe', function(err, ffprobe) {</td></tr><tr class="hit"><td class="line">132</td><td class="hits">3</td><td class="source"> cb(err, ffprobe);</td></tr><tr><td class="line">133</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">134</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">135</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">136</td><td class="hits"></td><td class="source"> // Search in the same directory as ffmpeg</td></tr><tr><td class="line">137</td><td class="hits"></td><td class="source"> function(ffprobe, cb) {</td></tr><tr class="hit"><td class="line">138</td><td class="hits">4</td><td class="source"> if (ffprobe.length) {</td></tr><tr class="hit"><td class="line">139</td><td class="hits">4</td><td class="source"> return cb(null, ffprobe);</td></tr><tr><td class="line">140</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">141</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">142</td><td class="hits">0</td><td class="source"> self._getFfmpegPath(function(err, ffmpeg) {</td></tr><tr class="miss"><td class="line">143</td><td class="hits">0</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">144</td><td class="hits">0</td><td class="source"> cb(err);</td></tr><tr class="miss"><td class="line">145</td><td class="hits">0</td><td class="source"> } else if (ffmpeg.length) {</td></tr><tr class="miss"><td class="line">146</td><td class="hits">0</td><td class="source"> var name = utils.isWindows ? 'ffprobe.exe' : 'ffprobe';</td></tr><tr class="miss"><td class="line">147</td><td class="hits">0</td><td class="source"> var ffprobe = path.join(path.dirname(ffmpeg), name);</td></tr><tr class="miss"><td class="line">148</td><td class="hits">0</td><td class="source"> fs.exists(ffprobe, function(exists) {</td></tr><tr class="miss"><td class="line">149</td><td class="hits">0</td><td class="source"> cb(null, exists ? ffprobe : '');</td></tr><tr><td class="line">150</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">151</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="miss"><td class="line">152</td><td class="hits">0</td><td class="source"> cb(null, '');</td></tr><tr><td class="line">153</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">154</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">155</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">156</td><td class="hits"></td><td class="source"> ], function(err, ffprobe) {</td></tr><tr class="hit"><td class="line">157</td><td class="hits">4</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">158</td><td class="hits">0</td><td class="source"> callback(err);</td></tr><tr><td class="line">159</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">160</td><td class="hits">4</td><td class="source"> callback(null, cache.ffprobePath = (ffprobe || ''));</td></tr><tr><td class="line">161</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">162</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">163</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">164</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">165</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">166</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">167</td><td class="hits"></td><td class="source"> * Check for flvtool2/flvmeta availability</td></tr><tr><td class="line">168</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">169</td><td class="hits"></td><td class="source"> * If the FLVTOOL2_PATH or FLVMETA_PATH environment variable are set, try to use them.</td></tr><tr><td class="line">170</td><td class="hits"></td><td class="source"> * If both are either unset or incorrect, try to find flvtool2 or flvmeta in the PATH instead.</td></tr><tr><td class="line">171</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">172</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#_getFlvtoolPath</td></tr><tr><td class="line">173</td><td class="hits"></td><td class="source"> * @param {Function} callback callback with signature (err, path)</td></tr><tr><td class="line">174</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">175</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">176</td><td class="hits">1</td><td class="source"> proto._getFlvtoolPath = function(callback) {</td></tr><tr class="hit"><td class="line">177</td><td class="hits">29</td><td class="source"> if ('flvtoolPath' in cache) {</td></tr><tr class="hit"><td class="line">178</td><td class="hits">28</td><td class="source"> return callback(null, cache.flvtoolPath);</td></tr><tr><td class="line">179</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">180</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">181</td><td class="hits">1</td><td class="source"> async.waterfall([</td></tr><tr><td class="line">182</td><td class="hits"></td><td class="source"> // Try FLVMETA_PATH</td></tr><tr><td class="line">183</td><td class="hits"></td><td class="source"> function(cb) {</td></tr><tr class="hit"><td class="line">184</td><td class="hits">1</td><td class="source"> if (process.env.FLVMETA_PATH) {</td></tr><tr class="miss"><td class="line">185</td><td class="hits">0</td><td class="source"> fs.exists(process.env.FLVMETA_PATH, function(exists) {</td></tr><tr class="miss"><td class="line">186</td><td class="hits">0</td><td class="source"> cb(null, exists ? process.env.FLVMETA_PATH : '');</td></tr><tr><td class="line">187</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">188</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">189</td><td class="hits">1</td><td class="source"> cb(null, '');</td></tr><tr><td class="line">190</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">191</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">192</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">193</td><td class="hits"></td><td class="source"> // Try FLVTOOL2_PATH</td></tr><tr><td class="line">194</td><td class="hits"></td><td class="source"> function(flvtool, cb) {</td></tr><tr class="hit"><td class="line">195</td><td class="hits">1</td><td class="source"> if (flvtool.length) {</td></tr><tr class="miss"><td class="line">196</td><td class="hits">0</td><td class="source"> return cb(null, flvtool);</td></tr><tr><td class="line">197</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">198</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">199</td><td class="hits">1</td><td class="source"> if (process.env.FLVTOOL2_PATH) {</td></tr><tr class="miss"><td class="line">200</td><td class="hits">0</td><td class="source"> fs.exists(process.env.FLVTOOL2_PATH, function(exists) {</td></tr><tr class="miss"><td class="line">201</td><td class="hits">0</td><td class="source"> cb(null, exists ? process.env.FLVTOOL2_PATH : '');</td></tr><tr><td class="line">202</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">203</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">204</td><td class="hits">1</td><td class="source"> cb(null, '');</td></tr><tr><td class="line">205</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">206</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">207</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">208</td><td class="hits"></td><td class="source"> // Search for flvmeta in the PATH</td></tr><tr><td class="line">209</td><td class="hits"></td><td class="source"> function(flvtool, cb) {</td></tr><tr class="hit"><td class="line">210</td><td class="hits">1</td><td class="source"> if (flvtool.length) {</td></tr><tr class="miss"><td class="line">211</td><td class="hits">0</td><td class="source"> return cb(null, flvtool);</td></tr><tr><td class="line">212</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">213</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">214</td><td class="hits">1</td><td class="source"> utils.which('flvmeta', function(err, flvmeta) {</td></tr><tr class="hit"><td class="line">215</td><td class="hits">1</td><td class="source"> cb(err, flvmeta);</td></tr><tr><td class="line">216</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">217</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">218</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">219</td><td class="hits"></td><td class="source"> // Search for flvtool2 in the PATH</td></tr><tr><td class="line">220</td><td class="hits"></td><td class="source"> function(flvtool, cb) {</td></tr><tr class="hit"><td class="line">221</td><td class="hits">1</td><td class="source"> if (flvtool.length) {</td></tr><tr class="hit"><td class="line">222</td><td class="hits">1</td><td class="source"> return cb(null, flvtool);</td></tr><tr><td class="line">223</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">224</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">225</td><td class="hits">0</td><td class="source"> utils.which('flvtool2', function(err, flvtool2) {</td></tr><tr class="miss"><td class="line">226</td><td class="hits">0</td><td class="source"> cb(err, flvtool2);</td></tr><tr><td class="line">227</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">228</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">229</td><td class="hits"></td><td class="source"> ], function(err, flvtool) {</td></tr><tr class="hit"><td class="line">230</td><td class="hits">1</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">231</td><td class="hits">0</td><td class="source"> callback(err);</td></tr><tr><td class="line">232</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">233</td><td class="hits">1</td><td class="source"> callback(null, cache.flvtoolPath = (flvtool || ''));</td></tr><tr><td class="line">234</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">235</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">236</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">237</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">238</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">239</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">240</td><td class="hits"></td><td class="source"> * Query ffmpeg for available filters</td></tr><tr><td class="line">241</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">242</td><td class="hits"></td><td class="source"> * Calls 'callback' with a filters object as its second argument. This</td></tr><tr><td class="line">243</td><td class="hits"></td><td class="source"> * object has keys for every available filter, and values are object</td></tr><tr><td class="line">244</td><td class="hits"></td><td class="source"> * with filter data:</td></tr><tr><td class="line">245</td><td class="hits"></td><td class="source"> * - 'description': filter description</td></tr><tr><td class="line">246</td><td class="hits"></td><td class="source"> * - 'input': input type ('audio', 'video' or 'none')</td></tr><tr><td class="line">247</td><td class="hits"></td><td class="source"> * - 'multipleInputs': bool, whether the filter supports multiple inputs</td></tr><tr><td class="line">248</td><td class="hits"></td><td class="source"> * - 'output': output type ('audio', 'video' or 'none')</td></tr><tr><td class="line">249</td><td class="hits"></td><td class="source"> * - 'multipleOutputs': bool, whether the filter supports multiple outputs</td></tr><tr><td class="line">250</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">251</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#availableFilters</td></tr><tr><td class="line">252</td><td class="hits"></td><td class="source"> * @category Capabilities</td></tr><tr><td class="line">253</td><td class="hits"></td><td class="source"> * @aliases getAvailableFilters</td></tr><tr><td class="line">254</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">255</td><td class="hits"></td><td class="source"> * @param {Function} callback callback with signature (err, filters)</td></tr><tr><td class="line">256</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">257</td><td class="hits">1</td><td class="source"> proto.availableFilters =</td></tr><tr><td class="line">258</td><td class="hits"></td><td class="source"> proto.getAvailableFilters = function(callback) {</td></tr><tr class="hit"><td class="line">259</td><td class="hits">2</td><td class="source"> if ('filters' in cache) {</td></tr><tr class="hit"><td class="line">260</td><td class="hits">1</td><td class="source"> return callback(null, cache.filters);</td></tr><tr><td class="line">261</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">262</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">263</td><td class="hits">1</td><td class="source"> this._spawnFfmpeg(['-filters'], { captureStdout: true }, function (err, stdout) {</td></tr><tr class="hit"><td class="line">264</td><td class="hits">1</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">265</td><td class="hits">0</td><td class="source"> return callback(err);</td></tr><tr><td class="line">266</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">267</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">268</td><td class="hits">1</td><td class="source"> var lines = stdout.split('\n');</td></tr><tr class="hit"><td class="line">269</td><td class="hits">1</td><td class="source"> var data = {};</td></tr><tr class="hit"><td class="line">270</td><td class="hits">1</td><td class="source"> var types = { A: 'audio', V: 'video', '|': 'none' };</td></tr><tr><td class="line">271</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">272</td><td class="hits">1</td><td class="source"> lines.forEach(function(line) {</td></tr><tr class="hit"><td class="line">273</td><td class="hits">137</td><td class="source"> var match = line.match(filterRegexp);</td></tr><tr class="hit"><td class="line">274</td><td class="hits">137</td><td class="source"> if (match) {</td></tr><tr class="hit"><td class="line">275</td><td class="hits">135</td><td class="source"> data[match[1]] = {</td></tr><tr><td class="line">276</td><td class="hits"></td><td class="source"> description: match[4],</td></tr><tr><td class="line">277</td><td class="hits"></td><td class="source"> input: types[match[2].charAt(0)],</td></tr><tr><td class="line">278</td><td class="hits"></td><td class="source"> multipleInputs: match[2].length > 1,</td></tr><tr><td class="line">279</td><td class="hits"></td><td class="source"> output: types[match[3].charAt(0)],</td></tr><tr><td class="line">280</td><td class="hits"></td><td class="source"> multipleOutputs: match[3].length > 1</td></tr><tr><td class="line">281</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">282</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">283</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">284</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">285</td><td class="hits">1</td><td class="source"> callback(null, cache.filters = data);</td></tr><tr><td class="line">286</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">287</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">288</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">289</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">290</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">291</td><td class="hits"></td><td class="source"> * Query ffmpeg for available codecs</td></tr><tr><td class="line">292</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">293</td><td class="hits"></td><td class="source"> * Calls 'callback' with a codecs object as its second argument. This</td></tr><tr><td class="line">294</td><td class="hits"></td><td class="source"> * object has keys for every available codec, and values are object</td></tr><tr><td class="line">295</td><td class="hits"></td><td class="source"> * with codec data:</td></tr><tr><td class="line">296</td><td class="hits"></td><td class="source"> * - 'description': codec description</td></tr><tr><td class="line">297</td><td class="hits"></td><td class="source"> * - 'canEncode': bool, whether the codec can encode streams</td></tr><tr><td class="line">298</td><td class="hits"></td><td class="source"> * - 'canDecode': bool, whether the codec can decode streams</td></tr><tr><td class="line">299</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">300</td><td class="hits"></td><td class="source"> * Depending on the ffmpeg version, more keys can be available.</td></tr><tr><td class="line">301</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">302</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#availableCodecs</td></tr><tr><td class="line">303</td><td class="hits"></td><td class="source"> * @category Capabilities</td></tr><tr><td class="line">304</td><td class="hits"></td><td class="source"> * @aliases getAvailableCodecs</td></tr><tr><td class="line">305</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">306</td><td class="hits"></td><td class="source"> * @param {Function} callback callback with signature (err, codecs)</td></tr><tr><td class="line">307</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">308</td><td class="hits">1</td><td class="source"> proto.availableCodecs =</td></tr><tr><td class="line">309</td><td class="hits"></td><td class="source"> proto.getAvailableCodecs = function(callback) {</td></tr><tr class="hit"><td class="line">310</td><td class="hits">25</td><td class="source"> if ('codecs' in cache) {</td></tr><tr class="hit"><td class="line">311</td><td class="hits">24</td><td class="source"> return callback(null, cache.codecs);</td></tr><tr><td class="line">312</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">313</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">314</td><td class="hits">1</td><td class="source"> this._spawnFfmpeg(['-codecs'], { captureStdout: true }, function(err, stdout) {</td></tr><tr class="hit"><td class="line">315</td><td class="hits">1</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">316</td><td class="hits">0</td><td class="source"> return callback(err);</td></tr><tr><td class="line">317</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">318</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">319</td><td class="hits">1</td><td class="source"> var lines = stdout.split(lineBreakRegexp);</td></tr><tr class="hit"><td class="line">320</td><td class="hits">1</td><td class="source"> var data = {};</td></tr><tr><td class="line">321</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">322</td><td class="hits">1</td><td class="source"> lines.forEach(function(line) {</td></tr><tr class="hit"><td class="line">323</td><td class="hits">369</td><td class="source"> var match = line.match(avCodecRegexp);</td></tr><tr class="hit"><td class="line">324</td><td class="hits">369</td><td class="source"> if (match && match[7] !== '=') {</td></tr><tr class="miss"><td class="line">325</td><td class="hits">0</td><td class="source"> data[match[7]] = {</td></tr><tr><td class="line">326</td><td class="hits"></td><td class="source"> type: { 'V': 'video', 'A': 'audio', 'S': 'subtitle' }[match[3]],</td></tr><tr><td class="line">327</td><td class="hits"></td><td class="source"> description: match[8],</td></tr><tr><td class="line">328</td><td class="hits"></td><td class="source"> canDecode: match[1] === 'D',</td></tr><tr><td class="line">329</td><td class="hits"></td><td class="source"> canEncode: match[2] === 'E',</td></tr><tr><td class="line">330</td><td class="hits"></td><td class="source"> drawHorizBand: match[4] === 'S',</td></tr><tr><td class="line">331</td><td class="hits"></td><td class="source"> directRendering: match[5] === 'D',</td></tr><tr><td class="line">332</td><td class="hits"></td><td class="source"> weirdFrameTruncation: match[6] === 'T'</td></tr><tr><td class="line">333</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">334</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">335</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">336</td><td class="hits">369</td><td class="source"> match = line.match(ffCodecRegexp);</td></tr><tr class="hit"><td class="line">337</td><td class="hits">369</td><td class="source"> if (match && match[7] !== '=') {</td></tr><tr class="hit"><td class="line">338</td><td class="hits">357</td><td class="source"> var codecData = data[match[7]] = {</td></tr><tr><td class="line">339</td><td class="hits"></td><td class="source"> type: { 'V': 'video', 'A': 'audio', 'S': 'subtitle' }[match[3]],</td></tr><tr><td class="line">340</td><td class="hits"></td><td class="source"> description: match[8],</td></tr><tr><td class="line">341</td><td class="hits"></td><td class="source"> canDecode: match[1] === 'D',</td></tr><tr><td class="line">342</td><td class="hits"></td><td class="source"> canEncode: match[2] === 'E',</td></tr><tr><td class="line">343</td><td class="hits"></td><td class="source"> intraFrameOnly: match[4] === 'I',</td></tr><tr><td class="line">344</td><td class="hits"></td><td class="source"> isLossy: match[5] === 'L',</td></tr><tr><td class="line">345</td><td class="hits"></td><td class="source"> isLossless: match[6] === 'S'</td></tr><tr><td class="line">346</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">347</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">348</td><td class="hits">357</td><td class="source"> var encoders = codecData.description.match(ffEncodersRegexp);</td></tr><tr class="hit"><td class="line">349</td><td class="hits">357</td><td class="source"> encoders = encoders ? encoders[1].trim().split(' ') : [];</td></tr><tr><td class="line">350</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">351</td><td class="hits">357</td><td class="source"> var decoders = codecData.description.match(ffDecodersRegexp);</td></tr><tr class="hit"><td class="line">352</td><td class="hits">357</td><td class="source"> decoders = decoders ? decoders[1].trim().split(' ') : [];</td></tr><tr><td class="line">353</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">354</td><td class="hits">357</td><td class="source"> if (encoders.length || decoders.length) {</td></tr><tr class="hit"><td class="line">355</td><td class="hits">58</td><td class="source"> var coderData = {};</td></tr><tr class="hit"><td class="line">356</td><td class="hits">58</td><td class="source"> copy(codecData, coderData);</td></tr><tr class="hit"><td class="line">357</td><td class="hits">58</td><td class="source"> delete coderData.canEncode;</td></tr><tr class="hit"><td class="line">358</td><td class="hits">58</td><td class="source"> delete coderData.canDecode;</td></tr><tr><td class="line">359</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">360</td><td class="hits">58</td><td class="source"> encoders.forEach(function(name) {</td></tr><tr class="hit"><td class="line">361</td><td class="hits">32</td><td class="source"> data[name] = {};</td></tr><tr class="hit"><td class="line">362</td><td class="hits">32</td><td class="source"> copy(coderData, data[name]);</td></tr><tr class="hit"><td class="line">363</td><td class="hits">32</td><td class="source"> data[name].canEncode = true;</td></tr><tr><td class="line">364</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">365</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">366</td><td class="hits">58</td><td class="source"> decoders.forEach(function(name) {</td></tr><tr class="hit"><td class="line">367</td><td class="hits">73</td><td class="source"> if (name in data) {</td></tr><tr class="hit"><td class="line">368</td><td class="hits">38</td><td class="source"> data[name].canDecode = true;</td></tr><tr><td class="line">369</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">370</td><td class="hits">35</td><td class="source"> data[name] = {};</td></tr><tr class="hit"><td class="line">371</td><td class="hits">35</td><td class="source"> copy(coderData, data[name]);</td></tr><tr class="hit"><td class="line">372</td><td class="hits">35</td><td class="source"> data[name].canDecode = true;</td></tr><tr><td class="line">373</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">374</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">375</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">376</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">377</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">378</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">379</td><td class="hits">1</td><td class="source"> callback(null, cache.codecs = data);</td></tr><tr><td class="line">380</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">381</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">382</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">383</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">384</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">385</td><td class="hits"></td><td class="source"> * Query ffmpeg for available formats</td></tr><tr><td class="line">386</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">387</td><td class="hits"></td><td class="source"> * Calls 'callback' with a formats object as its second argument. This</td></tr><tr><td class="line">388</td><td class="hits"></td><td class="source"> * object has keys for every available format, and values are object</td></tr><tr><td class="line">389</td><td class="hits"></td><td class="source"> * with format data:</td></tr><tr><td class="line">390</td><td class="hits"></td><td class="source"> * - 'description': format description</td></tr><tr><td class="line">391</td><td class="hits"></td><td class="source"> * - 'canMux': bool, whether the format can mux streams into an output file</td></tr><tr><td class="line">392</td><td class="hits"></td><td class="source"> * - 'canDemux': bool, whether the format can demux streams from an input file</td></tr><tr><td class="line">393</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">394</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#availableFormats</td></tr><tr><td class="line">395</td><td class="hits"></td><td class="source"> * @category Capabilities</td></tr><tr><td class="line">396</td><td class="hits"></td><td class="source"> * @aliases getAvailableFormats</td></tr><tr><td class="line">397</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">398</td><td class="hits"></td><td class="source"> * @param {Function} callback callback with signature (err, formats)</td></tr><tr><td class="line">399</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">400</td><td class="hits">1</td><td class="source"> proto.availableFormats =</td></tr><tr><td class="line">401</td><td class="hits"></td><td class="source"> proto.getAvailableFormats = function(callback) {</td></tr><tr class="hit"><td class="line">402</td><td class="hits">28</td><td class="source"> if ('formats' in cache) {</td></tr><tr class="hit"><td class="line">403</td><td class="hits">27</td><td class="source"> return callback(null, cache.formats);</td></tr><tr><td class="line">404</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">405</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">406</td><td class="hits"></td><td class="source"> // Run ffmpeg -formats</td></tr><tr class="hit"><td class="line">407</td><td class="hits">1</td><td class="source"> this._spawnFfmpeg(['-formats'], { captureStdout: true }, function (err, stdout) {</td></tr><tr class="hit"><td class="line">408</td><td class="hits">1</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">409</td><td class="hits">0</td><td class="source"> return callback(err);</td></tr><tr><td class="line">410</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">411</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">412</td><td class="hits"></td><td class="source"> // Parse output</td></tr><tr class="hit"><td class="line">413</td><td class="hits">1</td><td class="source"> var lines = stdout.split(lineBreakRegexp);</td></tr><tr class="hit"><td class="line">414</td><td class="hits">1</td><td class="source"> var data = {};</td></tr><tr><td class="line">415</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">416</td><td class="hits">1</td><td class="source"> lines.forEach(function(line) {</td></tr><tr class="hit"><td class="line">417</td><td class="hits">252</td><td class="source"> var match = line.match(formatRegexp);</td></tr><tr class="hit"><td class="line">418</td><td class="hits">252</td><td class="source"> if (match) {</td></tr><tr class="hit"><td class="line">419</td><td class="hits">247</td><td class="source"> data[match[3]] = {</td></tr><tr><td class="line">420</td><td class="hits"></td><td class="source"> description: match[4],</td></tr><tr><td class="line">421</td><td class="hits"></td><td class="source"> canDemux: match[1] === 'D',</td></tr><tr><td class="line">422</td><td class="hits"></td><td class="source"> canMux: match[2] === 'E'</td></tr><tr><td class="line">423</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">424</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">425</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">426</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">427</td><td class="hits">1</td><td class="source"> callback(null, cache.formats = data);</td></tr><tr><td class="line">428</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">429</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">430</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">431</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">432</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">433</td><td class="hits"></td><td class="source"> * Check capabilities before executing a command</td></tr><tr><td class="line">434</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">435</td><td class="hits"></td><td class="source"> * Checks whether all used codecs and formats are indeed available</td></tr><tr><td class="line">436</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">437</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#_checkCapabilities</td></tr><tr><td class="line">438</td><td class="hits"></td><td class="source"> * @param {Function} callback callback with signature (err)</td></tr><tr><td class="line">439</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">440</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">441</td><td class="hits">1</td><td class="source"> proto._checkCapabilities = function(callback) {</td></tr><tr class="hit"><td class="line">442</td><td class="hits">26</td><td class="source"> var self = this;</td></tr><tr class="hit"><td class="line">443</td><td class="hits">26</td><td class="source"> async.waterfall([</td></tr><tr><td class="line">444</td><td class="hits"></td><td class="source"> // Get available formats</td></tr><tr><td class="line">445</td><td class="hits"></td><td class="source"> function(cb) {</td></tr><tr class="hit"><td class="line">446</td><td class="hits">26</td><td class="source"> self.availableFormats(cb);</td></tr><tr><td class="line">447</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">448</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">449</td><td class="hits"></td><td class="source"> // Check whether specified formats are available</td></tr><tr><td class="line">450</td><td class="hits"></td><td class="source"> function(formats, cb) {</td></tr><tr><td class="line">451</td><td class="hits"></td><td class="source"> // Output format</td></tr><tr class="hit"><td class="line">452</td><td class="hits">26</td><td class="source"> var format = self._output.find('-f', 1);</td></tr><tr><td class="line">453</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">454</td><td class="hits">26</td><td class="source"> if (format) {</td></tr><tr class="hit"><td class="line">455</td><td class="hits">24</td><td class="source"> if (!(format[0] in formats) || !(formats[format[0]].canMux)) {</td></tr><tr class="hit"><td class="line">456</td><td class="hits">2</td><td class="source"> return cb(new Error('Output format ' + format[0] + ' is not available'));</td></tr><tr><td class="line">457</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">458</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">459</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">460</td><td class="hits"></td><td class="source"> // Input format(s)</td></tr><tr class="hit"><td class="line">461</td><td class="hits">24</td><td class="source"> var unavailable = self._inputs.reduce(function(fmts, input) {</td></tr><tr class="hit"><td class="line">462</td><td class="hits">24</td><td class="source"> var format = input.before.find('-f', 1);</td></tr><tr class="hit"><td class="line">463</td><td class="hits">24</td><td class="source"> if (format) {</td></tr><tr class="hit"><td class="line">464</td><td class="hits">4</td><td class="source"> if (!(format[0] in formats) || !(formats[format[0]].canDemux)) {</td></tr><tr class="hit"><td class="line">465</td><td class="hits">1</td><td class="source"> fmts.push(format[0]);</td></tr><tr><td class="line">466</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">467</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">468</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">469</td><td class="hits">24</td><td class="source"> return fmts;</td></tr><tr><td class="line">470</td><td class="hits"></td><td class="source"> }, []);</td></tr><tr><td class="line">471</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">472</td><td class="hits">24</td><td class="source"> if (unavailable.length === 1) {</td></tr><tr class="hit"><td class="line">473</td><td class="hits">1</td><td class="source"> cb(new Error('Input format ' + unavailable[0] + ' is not available'));</td></tr><tr class="hit"><td class="line">474</td><td class="hits">23</td><td class="source"> } else if (unavailable.length > 1) {</td></tr><tr class="miss"><td class="line">475</td><td class="hits">0</td><td class="source"> cb(new Error('Input formats ' + unavailable.join(', ') + ' are not available'));</td></tr><tr><td class="line">476</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">477</td><td class="hits">23</td><td class="source"> cb();</td></tr><tr><td class="line">478</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">479</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">480</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">481</td><td class="hits"></td><td class="source"> // Get available codecs</td></tr><tr><td class="line">482</td><td class="hits"></td><td class="source"> function(cb) {</td></tr><tr class="hit"><td class="line">483</td><td class="hits">23</td><td class="source"> self.availableCodecs(cb);</td></tr><tr><td class="line">484</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">485</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">486</td><td class="hits"></td><td class="source"> // Check whether specified codecs are available</td></tr><tr><td class="line">487</td><td class="hits"></td><td class="source"> function(codecs, cb) {</td></tr><tr><td class="line">488</td><td class="hits"></td><td class="source"> // Audio codec</td></tr><tr class="hit"><td class="line">489</td><td class="hits">23</td><td class="source"> var acodec = self._audio.find('-acodec', 1);</td></tr><tr class="hit"><td class="line">490</td><td class="hits">23</td><td class="source"> if (acodec && acodec[0] !== 'copy') {</td></tr><tr class="hit"><td class="line">491</td><td class="hits">21</td><td class="source"> if (!(acodec[0] in codecs) || codecs[acodec[0]].type !== 'audio' || !(codecs[acodec[0]].canEncode)) {</td></tr><tr class="hit"><td class="line">492</td><td class="hits">1</td><td class="source"> return cb(new Error('Audio codec ' + acodec[0] + ' is not available'));</td></tr><tr><td class="line">493</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">494</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">495</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">496</td><td class="hits"></td><td class="source"> // Video codec</td></tr><tr class="hit"><td class="line">497</td><td class="hits">22</td><td class="source"> var vcodec = self._video.find('-vcodec', 1);</td></tr><tr class="hit"><td class="line">498</td><td class="hits">22</td><td class="source"> if (vcodec && vcodec[0] !== 'copy') {</td></tr><tr class="hit"><td class="line">499</td><td class="hits">20</td><td class="source"> if (!(vcodec[0] in codecs) || codecs[vcodec[0]].type !== 'video' || !(codecs[vcodec[0]].canEncode)) {</td></tr><tr class="hit"><td class="line">500</td><td class="hits">1</td><td class="source"> return cb(new Error('Video codec ' + vcodec[0] + ' is not available'));</td></tr><tr><td class="line">501</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">502</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">503</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">504</td><td class="hits">21</td><td class="source"> cb();</td></tr><tr><td class="line">505</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">506</td><td class="hits"></td><td class="source"> ], callback);</td></tr><tr><td class="line">507</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">508</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">509</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div><div class="file"><h2 id="lib/ffprobe.js">lib/ffprobe.js</h2><div id="stats" class="high"><div class="percentage">80%</div><div class="sloc">66</div><div class="hits">53</div><div class="misses">13</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true, laxcomma:true*/</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">4</td><td class="hits">1</td><td class="source">var spawn = require('child_process').spawn;</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">7</td><td class="hits">263</td><td class="source">function legacyTag(key) { return key.match(/^TAG:/); }</td></tr><tr class="hit"><td class="line">8</td><td class="hits">263</td><td class="source">function legacyDisposition(key) { return key.match(/^DISPOSITION:/); }</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">11</td><td class="hits">1</td><td class="source">module.exports = function(proto) {</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> * Run ffprobe on last specified input</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> * Callback will receive an object as its second argument. This object</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> * has the same format as what the following command returns:</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> * ffprobe -print_format json -show_streams -show_format INPUTFILE</td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">20</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#ffprobe</td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> * @category Metadata</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source"> * @param {Function} callback callback with signature (err, ffprobeData)</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">26</td><td class="hits">1</td><td class="source"> proto.ffprobe = function(callback) {</td></tr><tr class="hit"><td class="line">27</td><td class="hits">10</td><td class="source"> if (!this._currentInput) {</td></tr><tr class="hit"><td class="line">28</td><td class="hits">1</td><td class="source"> return callback(new Error('No input specified'));</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">31</td><td class="hits">9</td><td class="source"> if (typeof this._currentInput.source !== 'string') {</td></tr><tr class="hit"><td class="line">32</td><td class="hits">1</td><td class="source"> return callback(new Error('Cannot run ffprobe on non-file input'));</td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">35</td><td class="hits"></td><td class="source"> // Find ffprobe</td></tr><tr class="hit"><td class="line">36</td><td class="hits">8</td><td class="source"> var self = this;</td></tr><tr class="hit"><td class="line">37</td><td class="hits">8</td><td class="source"> this._getFfprobePath(function(err, path) {</td></tr><tr class="hit"><td class="line">38</td><td class="hits">8</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">39</td><td class="hits">0</td><td class="source"> return callback(err);</td></tr><tr class="hit"><td class="line">40</td><td class="hits">8</td><td class="source"> } else if (!path) {</td></tr><tr class="miss"><td class="line">41</td><td class="hits">0</td><td class="source"> return callback(new Error('Cannot find ffprobe'));</td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">44</td><td class="hits">8</td><td class="source"> var stdout = '';</td></tr><tr class="hit"><td class="line">45</td><td class="hits">8</td><td class="source"> var stdoutClosed = false;</td></tr><tr class="hit"><td class="line">46</td><td class="hits">8</td><td class="source"> var stderr = '';</td></tr><tr class="hit"><td class="line">47</td><td class="hits">8</td><td class="source"> var stderrClosed = false;</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">49</td><td class="hits"></td><td class="source"> // Spawn ffprobe</td></tr><tr class="hit"><td class="line">50</td><td class="hits">8</td><td class="source"> var ffprobe = spawn(path, [</td></tr><tr><td class="line">51</td><td class="hits"></td><td class="source"> '-print_format', 'json',</td></tr><tr><td class="line">52</td><td class="hits"></td><td class="source"> '-show_streams',</td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> '-show_format',</td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> self._currentInput.source</td></tr><tr><td class="line">55</td><td class="hits"></td><td class="source"> ]);</td></tr><tr><td class="line">56</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">57</td><td class="hits">8</td><td class="source"> ffprobe.on('error', function(err) {</td></tr><tr class="miss"><td class="line">58</td><td class="hits">0</td><td class="source"> callback(err);</td></tr><tr><td class="line">59</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">60</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> // Ensure we wait for captured streams to end before calling callback</td></tr><tr class="hit"><td class="line">62</td><td class="hits">8</td><td class="source"> var exitError = null;</td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> function handleExit(err) {</td></tr><tr class="hit"><td class="line">64</td><td class="hits">24</td><td class="source"> if (err) {</td></tr><tr class="hit"><td class="line">65</td><td class="hits">1</td><td class="source"> exitError = err;</td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">68</td><td class="hits">24</td><td class="source"> if (processExited && stdoutClosed && stderrClosed) {</td></tr><tr class="hit"><td class="line">69</td><td class="hits">8</td><td class="source"> if (exitError) {</td></tr><tr class="hit"><td class="line">70</td><td class="hits">1</td><td class="source"> if (stderr) {</td></tr><tr class="hit"><td class="line">71</td><td class="hits">1</td><td class="source"> exitError.message += '\n' + stderr;</td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">74</td><td class="hits">1</td><td class="source"> return callback(exitError);</td></tr><tr><td class="line">75</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> // Process output</td></tr><tr class="hit"><td class="line">78</td><td class="hits">7</td><td class="source"> var data;</td></tr><tr><td class="line">79</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">80</td><td class="hits">7</td><td class="source"> try {</td></tr><tr class="hit"><td class="line">81</td><td class="hits">7</td><td class="source"> data = JSON.parse(stdout);</td></tr><tr><td class="line">82</td><td class="hits"></td><td class="source"> } catch(e) {</td></tr><tr class="miss"><td class="line">83</td><td class="hits">0</td><td class="source"> return callback(e);</td></tr><tr><td class="line">84</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">85</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">86</td><td class="hits"></td><td class="source"> // Handle legacy output with "TAG:x" and "DISPOSITION:x" keys</td></tr><tr class="hit"><td class="line">87</td><td class="hits">7</td><td class="source"> [data.format].concat(data.streams).forEach(function(target) {</td></tr><tr class="hit"><td class="line">88</td><td class="hits">15</td><td class="source"> var legacyTagKeys = Object.keys(target).filter(legacyTag);</td></tr><tr><td class="line">89</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">90</td><td class="hits">15</td><td class="source"> if (legacyTagKeys.length) {</td></tr><tr class="miss"><td class="line">91</td><td class="hits">0</td><td class="source"> target.tags = target.tags || {};</td></tr><tr><td class="line">92</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">93</td><td class="hits">0</td><td class="source"> legacyTagKeys.forEach(function(tagKey) {</td></tr><tr class="miss"><td class="line">94</td><td class="hits">0</td><td class="source"> target.tags[tagKey.substr(4)] = target[tagKey];</td></tr><tr class="miss"><td class="line">95</td><td class="hits">0</td><td class="source"> delete target[tagKey];</td></tr><tr><td class="line">96</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">97</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">98</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">99</td><td class="hits">15</td><td class="source"> var legacyDispositionKeys = Object.keys(target).filter(legacyDisposition);</td></tr><tr><td class="line">100</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">101</td><td class="hits">15</td><td class="source"> if (legacyDispositionKeys.length) {</td></tr><tr class="miss"><td class="line">102</td><td class="hits">0</td><td class="source"> target.disposition = target.disposition || {};</td></tr><tr><td class="line">103</td><td class="hits"></td><td class="source"> </td></tr><tr class="miss"><td class="line">104</td><td class="hits">0</td><td class="source"> legacyDispositionKeys.forEach(function(dispositionKey) {</td></tr><tr class="miss"><td class="line">105</td><td class="hits">0</td><td class="source"> target.disposition[dispositionKey.substr(12)] = target[dispositionKey];</td></tr><tr class="miss"><td class="line">106</td><td class="hits">0</td><td class="source"> delete target[dispositionKey];</td></tr><tr><td class="line">107</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">108</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">109</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">110</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">111</td><td class="hits">7</td><td class="source"> callback(null, data);</td></tr><tr><td class="line">112</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">113</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">114</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">115</td><td class="hits"></td><td class="source"> // Handle ffprobe exit</td></tr><tr class="hit"><td class="line">116</td><td class="hits">8</td><td class="source"> var processExited = false;</td></tr><tr class="hit"><td class="line">117</td><td class="hits">8</td><td class="source"> ffprobe.on('exit', function(code, signal) {</td></tr><tr class="hit"><td class="line">118</td><td class="hits">8</td><td class="source"> processExited = true;</td></tr><tr><td class="line">119</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">120</td><td class="hits">8</td><td class="source"> if (code) {</td></tr><tr class="hit"><td class="line">121</td><td class="hits">1</td><td class="source"> handleExit(new Error('ffprobe exited with code ' + code));</td></tr><tr class="hit"><td class="line">122</td><td class="hits">7</td><td class="source"> } else if (signal) {</td></tr><tr class="miss"><td class="line">123</td><td class="hits">0</td><td class="source"> handleExit(new Error('ffprobe was killed with signal ' + signal));</td></tr><tr><td class="line">124</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">125</td><td class="hits">7</td><td class="source"> handleExit();</td></tr><tr><td class="line">126</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">127</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">128</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">129</td><td class="hits"></td><td class="source"> // Handle stdout/stderr streams</td></tr><tr class="hit"><td class="line">130</td><td class="hits">8</td><td class="source"> ffprobe.stdout.on('data', function(data) {</td></tr><tr class="hit"><td class="line">131</td><td class="hits">18</td><td class="source"> stdout += data;</td></tr><tr><td class="line">132</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">133</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">134</td><td class="hits">8</td><td class="source"> ffprobe.stdout.on('close', function() {</td></tr><tr class="hit"><td class="line">135</td><td class="hits">8</td><td class="source"> stdoutClosed = true;</td></tr><tr class="hit"><td class="line">136</td><td class="hits">8</td><td class="source"> handleExit();</td></tr><tr><td class="line">137</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">138</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">139</td><td class="hits">8</td><td class="source"> ffprobe.stderr.on('data', function(data) {</td></tr><tr class="hit"><td class="line">140</td><td class="hits">33</td><td class="source"> stderr += data;</td></tr><tr><td class="line">141</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">142</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">143</td><td class="hits">8</td><td class="source"> ffprobe.stderr.on('close', function() {</td></tr><tr class="hit"><td class="line">144</td><td class="hits">8</td><td class="source"> stderrClosed = true;</td></tr><tr class="hit"><td class="line">145</td><td class="hits">8</td><td class="source"> handleExit();</td></tr><tr><td class="line">146</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">147</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">148</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">149</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">150</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">151</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div><div class="file"><h2 id="lib/fluent-ffmpeg.js">lib/fluent-ffmpeg.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">44</div><div class="hits">44</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true*/</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">4</td><td class="hits">1</td><td class="source">var path = require('path');</td></tr><tr class="hit"><td class="line">5</td><td class="hits">1</td><td class="source">var util = require('util');</td></tr><tr class="hit"><td class="line">6</td><td class="hits">1</td><td class="source">var EventEmitter = require('events').EventEmitter;</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">8</td><td class="hits">1</td><td class="source">var utils = require('./utils');</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> * Create an ffmpeg command</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> * Can be called with or without the 'new' operator, and the 'input' parameter</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> * may be specified as 'options.source' instead (or passed later with the</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> * addInput method).</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> * @constructor</td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> * @param {String|ReadableStream} [input] input file path or readable stream</td></tr><tr><td class="line">20</td><td class="hits"></td><td class="source"> * @param {Object} [options] command options</td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> * @param {Object} [options.logger=<no logging>] logger object with 'error', 'warning', 'info' and 'debug' methods</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> * @param {Number} [options.niceness=0] ffmpeg process niceness, ignored on Windows</td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source"> * @param {Number} [options.priority=0] alias for `niceness`</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> * @param {String} [options.presets="fluent-ffmpeg/lib/presets"] directory to load presets from</td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> * @param {String} [options.preset="fluent-ffmpeg/lib/presets"] alias for `presets`</td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> * @param {Number} [options.timeout=<no timeout>] ffmpeg processing timeout in seconds</td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source"> * @param {String|ReadableStream} [options.source=<no input>] alias for the `input` parameter</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source">function FfmpegCommand(input, options) {</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> // Make 'new' optional</td></tr><tr class="hit"><td class="line">31</td><td class="hits">207</td><td class="source"> if (!(this instanceof FfmpegCommand)) {</td></tr><tr class="hit"><td class="line">32</td><td class="hits">1</td><td class="source"> return new FfmpegCommand(input, options);</td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">35</td><td class="hits">206</td><td class="source"> EventEmitter.call(this);</td></tr><tr><td class="line">36</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">37</td><td class="hits">206</td><td class="source"> if (typeof input === 'object' && !('readable' in input)) {</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> // Options object passed directly</td></tr><tr class="hit"><td class="line">39</td><td class="hits">89</td><td class="source"> options = input;</td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> } else {</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> // Input passed first</td></tr><tr class="hit"><td class="line">42</td><td class="hits">117</td><td class="source"> options = options || {};</td></tr><tr class="hit"><td class="line">43</td><td class="hits">117</td><td class="source"> options.source = input;</td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">45</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">46</td><td class="hits"></td><td class="source"> // Add input if present</td></tr><tr class="hit"><td class="line">47</td><td class="hits">206</td><td class="source"> this._inputs = [];</td></tr><tr class="hit"><td class="line">48</td><td class="hits">206</td><td class="source"> if (options.source) {</td></tr><tr class="hit"><td class="line">49</td><td class="hits">94</td><td class="source"> this.addInput(options.source);</td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">51</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">52</td><td class="hits"></td><td class="source"> // Create argument lists</td></tr><tr class="hit"><td class="line">53</td><td class="hits">206</td><td class="source"> this._audio = utils.args();</td></tr><tr class="hit"><td class="line">54</td><td class="hits">206</td><td class="source"> this._audioFilters = utils.args();</td></tr><tr class="hit"><td class="line">55</td><td class="hits">206</td><td class="source"> this._video = utils.args();</td></tr><tr class="hit"><td class="line">56</td><td class="hits">206</td><td class="source"> this._videoFilters = utils.args();</td></tr><tr class="hit"><td class="line">57</td><td class="hits">206</td><td class="source"> this._sizeFilters = utils.args();</td></tr><tr class="hit"><td class="line">58</td><td class="hits">206</td><td class="source"> this._output = utils.args();</td></tr><tr><td class="line">59</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">60</td><td class="hits"></td><td class="source"> // Set default option values</td></tr><tr class="hit"><td class="line">61</td><td class="hits">206</td><td class="source"> options.presets = options.presets || options.preset || path.join(__dirname, 'presets');</td></tr><tr class="hit"><td class="line">62</td><td class="hits">206</td><td class="source"> options.niceness = options.niceness || options.priority || 0;</td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> // Save options</td></tr><tr class="hit"><td class="line">65</td><td class="hits">206</td><td class="source"> this.options = options;</td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> // Setup logger</td></tr><tr class="hit"><td class="line">68</td><td class="hits">206</td><td class="source"> this.logger = options.logger || {</td></tr><tr><td class="line">69</td><td class="hits"></td><td class="source"> debug: function() {},</td></tr><tr><td class="line">70</td><td class="hits"></td><td class="source"> info: function() {},</td></tr><tr><td class="line">71</td><td class="hits"></td><td class="source"> warn: function() {},</td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> error: function() {}</td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source">}</td></tr><tr class="hit"><td class="line">75</td><td class="hits">1</td><td class="source">util.inherits(FfmpegCommand, EventEmitter);</td></tr><tr class="hit"><td class="line">76</td><td class="hits">1</td><td class="source">module.exports = FfmpegCommand;</td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">78</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">79</td><td class="hits"></td><td class="source">/* Add methods from options submodules */</td></tr><tr><td class="line">80</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">81</td><td class="hits">1</td><td class="source">require('./options/inputs')(FfmpegCommand.prototype);</td></tr><tr class="hit"><td class="line">82</td><td class="hits">1</td><td class="source">require('./options/audio')(FfmpegCommand.prototype);</td></tr><tr class="hit"><td class="line">83</td><td class="hits">1</td><td class="source">require('./options/video')(FfmpegCommand.prototype);</td></tr><tr class="hit"><td class="line">84</td><td class="hits">1</td><td class="source">require('./options/videosize')(FfmpegCommand.prototype);</td></tr><tr class="hit"><td class="line">85</td><td class="hits">1</td><td class="source">require('./options/output')(FfmpegCommand.prototype);</td></tr><tr class="hit"><td class="line">86</td><td class="hits">1</td><td class="source">require('./options/custom')(FfmpegCommand.prototype);</td></tr><tr class="hit"><td class="line">87</td><td class="hits">1</td><td class="source">require('./options/misc')(FfmpegCommand.prototype);</td></tr><tr><td class="line">88</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">89</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">90</td><td class="hits"></td><td class="source">/* Add processor methods */</td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">92</td><td class="hits">1</td><td class="source">require('./processor')(FfmpegCommand.prototype);</td></tr><tr><td class="line">93</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">94</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">95</td><td class="hits"></td><td class="source">/* Add capabilities methods */</td></tr><tr><td class="line">96</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">97</td><td class="hits">1</td><td class="source">require('./capabilities')(FfmpegCommand.prototype);</td></tr><tr><td class="line">98</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">99</td><td class="hits">1</td><td class="source">FfmpegCommand.availableFilters =</td></tr><tr><td class="line">100</td><td class="hits"></td><td class="source">FfmpegCommand.getAvailableFilters = function(callback) {</td></tr><tr class="hit"><td class="line">101</td><td class="hits">1</td><td class="source"> (new FfmpegCommand()).availableFilters(callback);</td></tr><tr><td class="line">102</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">103</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">104</td><td class="hits">1</td><td class="source">FfmpegCommand.availableCodecs =</td></tr><tr><td class="line">105</td><td class="hits"></td><td class="source">FfmpegCommand.getAvailableCodecs = function(callback) {</td></tr><tr class="hit"><td class="line">106</td><td class="hits">1</td><td class="source"> (new FfmpegCommand()).availableCodecs(callback);</td></tr><tr><td class="line">107</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">108</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">109</td><td class="hits">1</td><td class="source">FfmpegCommand.availableFormats =</td></tr><tr><td class="line">110</td><td class="hits"></td><td class="source">FfmpegCommand.getAvailableFormats = function(callback) {</td></tr><tr class="hit"><td class="line">111</td><td class="hits">1</td><td class="source"> (new FfmpegCommand()).availableFormats(callback);</td></tr><tr><td class="line">112</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">113</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">114</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">115</td><td class="hits"></td><td class="source">/* Add ffprobe methods */</td></tr><tr><td class="line">116</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">117</td><td class="hits">1</td><td class="source">require('./ffprobe')(FfmpegCommand.prototype);</td></tr><tr><td class="line">118</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">119</td><td class="hits">1</td><td class="source">FfmpegCommand.ffprobe = function(file, callback) {</td></tr><tr class="hit"><td class="line">120</td><td class="hits">4</td><td class="source"> (new FfmpegCommand(file)).ffprobe(callback);</td></tr><tr><td class="line">121</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">122</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">123</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div><div class="file"><h2 id="lib/options/audio.js">lib/options/audio.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">25</div><div class="hits">25</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true*/</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">/*</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source"> *! Audio-related methods</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">8</td><td class="hits">1</td><td class="source">module.exports = function(proto) {</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> * Disable audio in the output</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#noAudio</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> * @category Audio</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> * @aliases withNoAudio</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">17</td><td class="hits">1</td><td class="source"> proto.withNoAudio =</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> proto.noAudio = function() {</td></tr><tr class="hit"><td class="line">19</td><td class="hits">2</td><td class="source"> this._audio.clear();</td></tr><tr class="hit"><td class="line">20</td><td class="hits">2</td><td class="source"> this._audio('-an');</td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">22</td><td class="hits">2</td><td class="source"> return this;</td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source"> * Specify audio codec</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#audioCodec</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> * @category Audio</td></tr><tr><td class="line">31</td><td class="hits"></td><td class="source"> * @aliases withAudioCodec</td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> * @param {String} codec audio codec name</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">35</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">36</td><td class="hits">1</td><td class="source"> proto.withAudioCodec =</td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source"> proto.audioCodec = function(codec) {</td></tr><tr class="hit"><td class="line">38</td><td class="hits">26</td><td class="source"> this._audio('-acodec', codec);</td></tr><tr class="hit"><td class="line">39</td><td class="hits">26</td><td class="source"> return this;</td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> * Specify audio bitrate</td></tr><tr><td class="line">45</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">46</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#audioBitrate</td></tr><tr><td class="line">47</td><td class="hits"></td><td class="source"> * @category Audio</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> * @aliases withAudioBitrate</td></tr><tr><td class="line">49</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> * @param {String|Number} bitrate audio bitrate in kbps (with an optional 'k' suffix)</td></tr><tr><td class="line">51</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">52</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">53</td><td class="hits">1</td><td class="source"> proto.withAudioBitrate =</td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> proto.audioBitrate = function(bitrate) {</td></tr><tr class="hit"><td class="line">55</td><td class="hits">22</td><td class="source"> this._audio('-b:a', ('' + bitrate).replace(/k?$/, 'k'));</td></tr><tr class="hit"><td class="line">56</td><td class="hits">22</td><td class="source"> return this;</td></tr><tr><td class="line">57</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">58</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">59</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">60</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> * Specify audio channel count</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#audioChannels</td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> * @category Audio</td></tr><tr><td class="line">65</td><td class="hits"></td><td class="source"> * @aliases withAudioChannels</td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> * @param {Number} channels channel count</td></tr><tr><td class="line">68</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">69</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">70</td><td class="hits">1</td><td class="source"> proto.withAudioChannels =</td></tr><tr><td class="line">71</td><td class="hits"></td><td class="source"> proto.audioChannels = function(channels) {</td></tr><tr class="hit"><td class="line">72</td><td class="hits">22</td><td class="source"> this._audio('-ac', channels);</td></tr><tr class="hit"><td class="line">73</td><td class="hits">22</td><td class="source"> return this;</td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">75</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">78</td><td class="hits"></td><td class="source"> * Specify audio frequency</td></tr><tr><td class="line">79</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">80</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#audioFrequency</td></tr><tr><td class="line">81</td><td class="hits"></td><td class="source"> * @category Audio</td></tr><tr><td class="line">82</td><td class="hits"></td><td class="source"> * @aliases withAudioFrequency</td></tr><tr><td class="line">83</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">84</td><td class="hits"></td><td class="source"> * @param {Number} freq audio frequency in Hz</td></tr><tr><td class="line">85</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">86</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">87</td><td class="hits">1</td><td class="source"> proto.withAudioFrequency =</td></tr><tr><td class="line">88</td><td class="hits"></td><td class="source"> proto.audioFrequency = function(freq) {</td></tr><tr class="hit"><td class="line">89</td><td class="hits">20</td><td class="source"> this._audio('-ar', freq);</td></tr><tr class="hit"><td class="line">90</td><td class="hits">20</td><td class="source"> return this;</td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">92</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">93</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">94</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">95</td><td class="hits"></td><td class="source"> * Specify audio quality</td></tr><tr><td class="line">96</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">97</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#audioQuality</td></tr><tr><td class="line">98</td><td class="hits"></td><td class="source"> * @category Audio</td></tr><tr><td class="line">99</td><td class="hits"></td><td class="source"> * @aliases withAudioQuality</td></tr><tr><td class="line">100</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">101</td><td class="hits"></td><td class="source"> * @param {Number} quality audio quality factor</td></tr><tr><td class="line">102</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">103</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">104</td><td class="hits">1</td><td class="source"> proto.withAudioQuality =</td></tr><tr><td class="line">105</td><td class="hits"></td><td class="source"> proto.audioQuality = function(quality) {</td></tr><tr class="hit"><td class="line">106</td><td class="hits">1</td><td class="source"> this._audio('-aq', quality);</td></tr><tr class="hit"><td class="line">107</td><td class="hits">1</td><td class="source"> return this;</td></tr><tr><td class="line">108</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">109</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">110</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">111</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">112</td><td class="hits"></td><td class="source"> * Specify custom audio filter(s)</td></tr><tr><td class="line">113</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">114</td><td class="hits"></td><td class="source"> * Can be called both with one or many filters, or a filter array.</td></tr><tr><td class="line">115</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">116</td><td class="hits"></td><td class="source"> * @example</td></tr><tr><td class="line">117</td><td class="hits"></td><td class="source"> * command.audioFilters('filter1');</td></tr><tr><td class="line">118</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">119</td><td class="hits"></td><td class="source"> * @example</td></tr><tr><td class="line">120</td><td class="hits"></td><td class="source"> * command.audioFilters('filter1', 'filter2');</td></tr><tr><td class="line">121</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">122</td><td class="hits"></td><td class="source"> * @example</td></tr><tr><td class="line">123</td><td class="hits"></td><td class="source"> * command.audioFilters(['filter1', 'filter2']);</td></tr><tr><td class="line">124</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">125</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#audioFilters</td></tr><tr><td class="line">126</td><td class="hits"></td><td class="source"> * @aliases withAudioFilter,withAudioFilters,audioFilter</td></tr><tr><td class="line">127</td><td class="hits"></td><td class="source"> * @category Audio</td></tr><tr><td class="line">128</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">129</td><td class="hits"></td><td class="source"> * @param {String|Array} filters... audio filter strings or string array</td></tr><tr><td class="line">130</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">131</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">132</td><td class="hits">1</td><td class="source"> proto.withAudioFilter =</td></tr><tr><td class="line">133</td><td class="hits"></td><td class="source"> proto.withAudioFilters =</td></tr><tr><td class="line">134</td><td class="hits"></td><td class="source"> proto.audioFilter =</td></tr><tr><td class="line">135</td><td class="hits"></td><td class="source"> proto.audioFilters = function(filters) {</td></tr><tr class="hit"><td class="line">136</td><td class="hits">3</td><td class="source"> if (arguments.length > 1) {</td></tr><tr class="hit"><td class="line">137</td><td class="hits">1</td><td class="source"> filters = [].slice.call(arguments);</td></tr><tr><td class="line">138</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">139</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">140</td><td class="hits">3</td><td class="source"> this._audioFilters(filters);</td></tr><tr class="hit"><td class="line">141</td><td class="hits">3</td><td class="source"> return this;</td></tr><tr><td class="line">142</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">143</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">144</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div><div class="file"><h2 id="lib/options/custom.js">lib/options/custom.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">31</div><div class="hits">31</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true*/</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">/*</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source"> *! Custom options methods</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">8</td><td class="hits">1</td><td class="source">module.exports = function(proto) {</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> * Add custom input option(s)</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> * When passing a single string or an array, each string containing two</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> * words is split (eg. inputOptions('-option value') is supported) for</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> * compatibility reasons. This is not the case when passing more than</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> * one argument.</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> * @example</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> * command.inputOptions('option1');</td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">20</td><td class="hits"></td><td class="source"> * @example</td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> * command.inputOptions('option1', 'option2');</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source"> * @example</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> * command.inputOptions(['option1', 'option2']);</td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#inputOptions</td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source"> * @category Custom options</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> * @aliases addInputOption,addInputOptions,withInputOption,withInputOptions,inputOption</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> * @param {...String} options option string(s) or string array</td></tr><tr><td class="line">31</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">33</td><td class="hits">1</td><td class="source"> proto.addInputOption =</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> proto.addInputOptions =</td></tr><tr><td class="line">35</td><td class="hits"></td><td class="source"> proto.withInputOption =</td></tr><tr><td class="line">36</td><td class="hits"></td><td class="source"> proto.withInputOptions =</td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source"> proto.inputOption =</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> proto.inputOptions = function(options) {</td></tr><tr class="hit"><td class="line">39</td><td class="hits">5</td><td class="source"> if (!this._currentInput) {</td></tr><tr class="hit"><td class="line">40</td><td class="hits">1</td><td class="source"> throw new Error('No input specified');</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">43</td><td class="hits">4</td><td class="source"> var doSplit = true;</td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">45</td><td class="hits">4</td><td class="source"> if (arguments.length > 1) {</td></tr><tr class="hit"><td class="line">46</td><td class="hits">2</td><td class="source"> options = [].slice.call(arguments);</td></tr><tr class="hit"><td class="line">47</td><td class="hits">2</td><td class="source"> doSplit = false;</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">49</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">50</td><td class="hits">4</td><td class="source"> if (!Array.isArray(options)) {</td></tr><tr class="hit"><td class="line">51</td><td class="hits">1</td><td class="source"> options = [options];</td></tr><tr><td class="line">52</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">54</td><td class="hits">4</td><td class="source"> this._currentInput.before(options.reduce(function(options, option) {</td></tr><tr class="hit"><td class="line">55</td><td class="hits">7</td><td class="source"> var split = option.split(' ');</td></tr><tr><td class="line">56</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">57</td><td class="hits">7</td><td class="source"> if (doSplit && split.length === 2) {</td></tr><tr class="hit"><td class="line">58</td><td class="hits">3</td><td class="source"> options.push(split[0], split[1]);</td></tr><tr><td class="line">59</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">60</td><td class="hits">4</td><td class="source"> options.push(option);</td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">63</td><td class="hits">7</td><td class="source"> return options;</td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> }, []));</td></tr><tr class="hit"><td class="line">65</td><td class="hits">4</td><td class="source"> return this;</td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">68</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">69</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">70</td><td class="hits"></td><td class="source"> * Add custom output option(s)</td></tr><tr><td class="line">71</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> * @example</td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> * command.outputOptions('option1');</td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">75</td><td class="hits"></td><td class="source"> * @example</td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source"> * command.outputOptions('option1', 'option2');</td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">78</td><td class="hits"></td><td class="source"> * @example</td></tr><tr><td class="line">79</td><td class="hits"></td><td class="source"> * command.outputOptions(['option1', 'option2']);</td></tr><tr><td class="line">80</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">81</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#outputOptions</td></tr><tr><td class="line">82</td><td class="hits"></td><td class="source"> * @category Custom options</td></tr><tr><td class="line">83</td><td class="hits"></td><td class="source"> * @aliases addOutputOption,addOutputOptions,addOption,addOptions,withOutputOption,withOutputOptions,withOption,withOptions,outputOption</td></tr><tr><td class="line">84</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">85</td><td class="hits"></td><td class="source"> * @param {...String} options option string(s) or string array</td></tr><tr><td class="line">86</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">87</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">88</td><td class="hits">1</td><td class="source"> proto.addOutputOption =</td></tr><tr><td class="line">89</td><td class="hits"></td><td class="source"> proto.addOutputOptions =</td></tr><tr><td class="line">90</td><td class="hits"></td><td class="source"> proto.addOption =</td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source"> proto.addOptions =</td></tr><tr><td class="line">92</td><td class="hits"></td><td class="source"> proto.withOutputOption =</td></tr><tr><td class="line">93</td><td class="hits"></td><td class="source"> proto.withOutputOptions =</td></tr><tr><td class="line">94</td><td class="hits"></td><td class="source"> proto.withOption =</td></tr><tr><td class="line">95</td><td class="hits"></td><td class="source"> proto.withOptions =</td></tr><tr><td class="line">96</td><td class="hits"></td><td class="source"> proto.outputOption =</td></tr><tr><td class="line">97</td><td class="hits"></td><td class="source"> proto.outputOptions = function(options) {</td></tr><tr class="hit"><td class="line">98</td><td class="hits">6</td><td class="source"> var doSplit = true;</td></tr><tr><td class="line">99</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">100</td><td class="hits">6</td><td class="source"> if (arguments.length > 1) {</td></tr><tr class="hit"><td class="line">101</td><td class="hits">2</td><td class="source"> options = [].slice.call(arguments);</td></tr><tr class="hit"><td class="line">102</td><td class="hits">2</td><td class="source"> doSplit = false;</td></tr><tr><td class="line">103</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">104</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">105</td><td class="hits">6</td><td class="source"> if (!Array.isArray(options)) {</td></tr><tr class="hit"><td class="line">106</td><td class="hits">1</td><td class="source"> options = [options];</td></tr><tr><td class="line">107</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">108</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">109</td><td class="hits">6</td><td class="source"> this._output(options.reduce(function(options, option) {</td></tr><tr class="hit"><td class="line">110</td><td class="hits">45</td><td class="source"> var split = option.split(' ');</td></tr><tr><td class="line">111</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">112</td><td class="hits">45</td><td class="source"> if (doSplit && split.length === 2) {</td></tr><tr class="hit"><td class="line">113</td><td class="hits">19</td><td class="source"> options.push(split[0], split[1]);</td></tr><tr><td class="line">114</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">115</td><td class="hits">26</td><td class="source"> options.push(option);</td></tr><tr><td class="line">116</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">117</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">118</td><td class="hits">45</td><td class="source"> return options;</td></tr><tr><td class="line">119</td><td class="hits"></td><td class="source"> }, []));</td></tr><tr class="hit"><td class="line">120</td><td class="hits">6</td><td class="source"> return this;</td></tr><tr><td class="line">121</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">122</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">123</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div><div class="file"><h2 id="lib/options/inputs.js">lib/options/inputs.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">39</div><div class="hits">39</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true*/</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">4</td><td class="hits">1</td><td class="source">var utils = require('../utils');</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source">/*</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source"> *! Input-related methods</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">10</td><td class="hits">1</td><td class="source">module.exports = function(proto) {</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> * Add an input to command</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> * Also switches "current input", that is the input that will be affected</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> * by subsequent input-related methods.</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> * Note: only one stream input is supported for now.</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#input</td></tr><tr><td class="line">20</td><td class="hits"></td><td class="source"> * @category Input</td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> * @aliases mergeAdd,addInput</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source"> * @param {String|Readable} source input file path or readable stream</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">26</td><td class="hits">1</td><td class="source"> proto.mergeAdd =</td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source"> proto.addInput =</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> proto.input = function(source) {</td></tr><tr class="hit"><td class="line">29</td><td class="hits">101</td><td class="source"> if (typeof source !== 'string') {</td></tr><tr class="hit"><td class="line">30</td><td class="hits">6</td><td class="source"> if (!('readable' in source)) {</td></tr><tr class="hit"><td class="line">31</td><td class="hits">1</td><td class="source"> throw new Error('Invalid input');</td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">34</td><td class="hits">5</td><td class="source"> var hasInputStream = this._inputs.some(function(input) {</td></tr><tr class="hit"><td class="line">35</td><td class="hits">1</td><td class="source"> return typeof input.source !== 'string';</td></tr><tr><td class="line">36</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">38</td><td class="hits">5</td><td class="source"> if (hasInputStream) {</td></tr><tr class="hit"><td class="line">39</td><td class="hits">1</td><td class="source"> throw new Error('Only one input stream is supported');</td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">42</td><td class="hits">4</td><td class="source"> source.pause();</td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">45</td><td class="hits">99</td><td class="source"> this._inputs.push(this._currentInput = {</td></tr><tr><td class="line">46</td><td class="hits"></td><td class="source"> source: source,</td></tr><tr><td class="line">47</td><td class="hits"></td><td class="source"> before: utils.args(),</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> after: utils.args(),</td></tr><tr><td class="line">49</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">51</td><td class="hits">99</td><td class="source"> return this;</td></tr><tr><td class="line">52</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">55</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">56</td><td class="hits"></td><td class="source"> * Specify input format for the last specified input</td></tr><tr><td class="line">57</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">58</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#inputFormat</td></tr><tr><td class="line">59</td><td class="hits"></td><td class="source"> * @category Input</td></tr><tr><td class="line">60</td><td class="hits"></td><td class="source"> * @aliases withInputFormat,fromFormat</td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> * @param {String} format input format</td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">65</td><td class="hits">1</td><td class="source"> proto.withInputFormat =</td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> proto.inputFormat =</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> proto.fromFormat = function(format) {</td></tr><tr class="hit"><td class="line">68</td><td class="hits">6</td><td class="source"> if (!this._currentInput) {</td></tr><tr class="hit"><td class="line">69</td><td class="hits">1</td><td class="source"> throw new Error('No input specified');</td></tr><tr><td class="line">70</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">71</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">72</td><td class="hits">5</td><td class="source"> this._currentInput.before('-f', format);</td></tr><tr class="hit"><td class="line">73</td><td class="hits">5</td><td class="source"> return this;</td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">75</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">78</td><td class="hits"></td><td class="source"> * Specify input FPS for the last specified input</td></tr><tr><td class="line">79</td><td class="hits"></td><td class="source"> * (only valid for raw video formats)</td></tr><tr><td class="line">80</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">81</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#inputFps</td></tr><tr><td class="line">82</td><td class="hits"></td><td class="source"> * @category Input</td></tr><tr><td class="line">83</td><td class="hits"></td><td class="source"> * @aliases withInputFps,withInputFPS,withFpsInput,withFPSInput,inputFPS,inputFps,fpsInput</td></tr><tr><td class="line">84</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">85</td><td class="hits"></td><td class="source"> * @param {Number} fps input FPS</td></tr><tr><td class="line">86</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">87</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">88</td><td class="hits">1</td><td class="source"> proto.withInputFps =</td></tr><tr><td class="line">89</td><td class="hits"></td><td class="source"> proto.withInputFPS =</td></tr><tr><td class="line">90</td><td class="hits"></td><td class="source"> proto.withFpsInput =</td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source"> proto.withFPSInput =</td></tr><tr><td class="line">92</td><td class="hits"></td><td class="source"> proto.inputFPS =</td></tr><tr><td class="line">93</td><td class="hits"></td><td class="source"> proto.inputFps =</td></tr><tr><td class="line">94</td><td class="hits"></td><td class="source"> proto.fpsInput =</td></tr><tr><td class="line">95</td><td class="hits"></td><td class="source"> proto.FPSInput = function(fps) {</td></tr><tr class="hit"><td class="line">96</td><td class="hits">2</td><td class="source"> if (!this._currentInput) {</td></tr><tr class="hit"><td class="line">97</td><td class="hits">1</td><td class="source"> throw new Error('No input specified');</td></tr><tr><td class="line">98</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">99</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">100</td><td class="hits">1</td><td class="source"> this._currentInput.before('-r', fps);</td></tr><tr class="hit"><td class="line">101</td><td class="hits">1</td><td class="source"> return this;</td></tr><tr><td class="line">102</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">103</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">104</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">105</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">106</td><td class="hits"></td><td class="source"> * Specify input seek time for the last specified input</td></tr><tr><td class="line">107</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">108</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#seek</td></tr><tr><td class="line">109</td><td class="hits"></td><td class="source"> * @category Input</td></tr><tr><td class="line">110</td><td class="hits"></td><td class="source"> * @aliases setStartTime,seekTo</td></tr><tr><td class="line">111</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">112</td><td class="hits"></td><td class="source"> * @param {String|Number} seek seek time in seconds or as a '[hh:[mm:]]ss[.xxx]' string</td></tr><tr><td class="line">113</td><td class="hits"></td><td class="source"> * @param {Boolean} [fast=false] use fast (but inexact) seek</td></tr><tr><td class="line">114</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">115</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">116</td><td class="hits">1</td><td class="source"> proto.setStartTime =</td></tr><tr><td class="line">117</td><td class="hits"></td><td class="source"> proto.seekTo =</td></tr><tr><td class="line">118</td><td class="hits"></td><td class="source"> proto.seek = function(seek, fast) {</td></tr><tr class="hit"><td class="line">119</td><td class="hits">4</td><td class="source"> if (!this._currentInput) {</td></tr><tr class="hit"><td class="line">120</td><td class="hits">2</td><td class="source"> throw new Error('No input specified');</td></tr><tr><td class="line">121</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">122</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">123</td><td class="hits">2</td><td class="source"> if (fast) {</td></tr><tr class="hit"><td class="line">124</td><td class="hits">1</td><td class="source"> this._currentInput.before('-ss', seek);</td></tr><tr><td class="line">125</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">126</td><td class="hits">1</td><td class="source"> this._currentInput.after('-ss', seek);</td></tr><tr><td class="line">127</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">128</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">129</td><td class="hits">2</td><td class="source"> return this;</td></tr><tr><td class="line">130</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">131</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">132</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">133</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">134</td><td class="hits"></td><td class="source"> * Specify input fast-seek time for the last specified input</td></tr><tr><td class="line">135</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">136</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#fastSeek</td></tr><tr><td class="line">137</td><td class="hits"></td><td class="source"> * @category Input</td></tr><tr><td class="line">138</td><td class="hits"></td><td class="source"> * @aliases fastSeekTo</td></tr><tr><td class="line">139</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">140</td><td class="hits"></td><td class="source"> * @param {String|Number} seek fast-seek time in seconds or as a '[[hh:]mm:]ss[.xxx]' string</td></tr><tr><td class="line">141</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">142</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">143</td><td class="hits">1</td><td class="source"> proto.fastSeek =</td></tr><tr><td class="line">144</td><td class="hits"></td><td class="source"> proto.fastSeekTo = function(seek) {</td></tr><tr class="hit"><td class="line">145</td><td class="hits">1</td><td class="source"> return this.seek(seek, true);</td></tr><tr><td class="line">146</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">147</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">148</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">149</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">150</td><td class="hits"></td><td class="source"> * Loop over the last specified input</td></tr><tr><td class="line">151</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">152</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#loop</td></tr><tr><td class="line">153</td><td class="hits"></td><td class="source"> * @category Input</td></tr><tr><td class="line">154</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">155</td><td class="hits"></td><td class="source"> * @param {String|Number} [duration] loop duration in seconds or as a '[[hh:]mm:]ss[.xxx]' string</td></tr><tr><td class="line">156</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">157</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">158</td><td class="hits">1</td><td class="source"> proto.loop = function(duration) {</td></tr><tr class="hit"><td class="line">159</td><td class="hits">4</td><td class="source"> if (!this._currentInput) {</td></tr><tr class="hit"><td class="line">160</td><td class="hits">1</td><td class="source"> throw new Error('No input specified');</td></tr><tr><td class="line">161</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">162</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">163</td><td class="hits">3</td><td class="source"> this._currentInput.before('-loop', '1');</td></tr><tr><td class="line">164</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">165</td><td class="hits">3</td><td class="source"> if (typeof duration !== 'undefined') {</td></tr><tr class="hit"><td class="line">166</td><td class="hits">2</td><td class="source"> this.duration(duration);</td></tr><tr><td class="line">167</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">168</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">169</td><td class="hits">3</td><td class="source"> return this;</td></tr><tr><td class="line">170</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">171</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">172</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div><div class="file"><h2 id="lib/options/misc.js">lib/options/misc.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">19</div><div class="hits">19</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true*/</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">4</td><td class="hits">1</td><td class="source">var path = require('path');</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source">/*</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source"> *! Miscellaneous methods</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">10</td><td class="hits">1</td><td class="source">module.exports = function(proto) {</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> * Use preset</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#preset</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> * @category Miscellaneous</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> * @aliases usingPreset</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> * @param {String|Function} preset preset name or preset function</td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">20</td><td class="hits">1</td><td class="source"> proto.usingPreset =</td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> proto.preset = function(preset) {</td></tr><tr class="hit"><td class="line">22</td><td class="hits">23</td><td class="source"> if (typeof preset === 'function') {</td></tr><tr class="hit"><td class="line">23</td><td class="hits">1</td><td class="source"> preset(this);</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">25</td><td class="hits">22</td><td class="source"> try {</td></tr><tr class="hit"><td class="line">26</td><td class="hits">22</td><td class="source"> var modulePath = path.join(this.options.presets, preset);</td></tr><tr class="hit"><td class="line">27</td><td class="hits">22</td><td class="source"> var module = require(modulePath);</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">29</td><td class="hits">21</td><td class="source"> if (typeof module.load === 'function') {</td></tr><tr class="hit"><td class="line">30</td><td class="hits">20</td><td class="source"> module.load(this);</td></tr><tr><td class="line">31</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">32</td><td class="hits">1</td><td class="source"> throw new Error('preset ' + modulePath + ' has no load() function');</td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> } catch (err) {</td></tr><tr class="hit"><td class="line">35</td><td class="hits">2</td><td class="source"> throw new Error('preset ' + modulePath + ' could not be loaded: ' + err.message);</td></tr><tr><td class="line">36</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">39</td><td class="hits">21</td><td class="source"> return this;</td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> * Enable experimental codecs</td></tr><tr><td class="line">45</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">46</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#strict</td></tr><tr><td class="line">47</td><td class="hits"></td><td class="source"> * @category Miscellaneous</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> * @aliases withStrictExperimental</td></tr><tr><td class="line">49</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">51</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">52</td><td class="hits">1</td><td class="source"> proto.withStrictExperimental =</td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> proto.strict = function() {</td></tr><tr class="hit"><td class="line">54</td><td class="hits">20</td><td class="source"> this._output('-strict', 'experimental');</td></tr><tr class="hit"><td class="line">55</td><td class="hits">20</td><td class="source"> return this;</td></tr><tr><td class="line">56</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">57</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">58</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">59</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">60</td><td class="hits"></td><td class="source"> * Run flvtool2/flvmeta on output</td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#flvmeta</td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> * @category Miscellaneous</td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> * @aliases updateFlvMetadata</td></tr><tr><td class="line">65</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">68</td><td class="hits">1</td><td class="source"> proto.updateFlvMetadata =</td></tr><tr><td class="line">69</td><td class="hits"></td><td class="source"> proto.flvmeta = function() {</td></tr><tr class="hit"><td class="line">70</td><td class="hits">18</td><td class="source"> this.options.flvmeta = true;</td></tr><tr class="hit"><td class="line">71</td><td class="hits">18</td><td class="source"> return this;</td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div><div class="file"><h2 id="lib/options/output.js">lib/options/output.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">7</div><div class="hits">7</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true*/</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">/*</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source"> *! Output-related methods</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">8</td><td class="hits">1</td><td class="source">module.exports = function(proto) {</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> * Set output duration</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#duration</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> * @category Output</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> * @aliases withDuration,setDuration</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> * @param {String|Number} duration duration in seconds or as a '[[hh:]mm:]ss[.xxx]' string</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">19</td><td class="hits">1</td><td class="source"> proto.withDuration =</td></tr><tr><td class="line">20</td><td class="hits"></td><td class="source"> proto.setDuration =</td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> proto.duration = function(duration) {</td></tr><tr class="hit"><td class="line">22</td><td class="hits">3</td><td class="source"> this._output('-t', duration);</td></tr><tr class="hit"><td class="line">23</td><td class="hits">3</td><td class="source"> return this;</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> * Set output format</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#format</td></tr><tr><td class="line">31</td><td class="hits"></td><td class="source"> * @category Output</td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> * @aliases toFormat,withOutputFormat,outputFormat</td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> * @param {String} format output format name</td></tr><tr><td class="line">35</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">36</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">37</td><td class="hits">1</td><td class="source"> proto.toFormat =</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> proto.withOutputFormat =</td></tr><tr><td class="line">39</td><td class="hits"></td><td class="source"> proto.outputFormat =</td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> proto.format = function(format) {</td></tr><tr class="hit"><td class="line">41</td><td class="hits">27</td><td class="source"> this._output('-f', format);</td></tr><tr class="hit"><td class="line">42</td><td class="hits">27</td><td class="source"> return this;</td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">45</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div><div class="file"><h2 id="lib/options/video.js">lib/options/video.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">27</div><div class="hits">27</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true*/</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">/*</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source"> *! Video-related methods</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">8</td><td class="hits">1</td><td class="source">module.exports = function(proto) {</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> * Disable video in the output</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#noVideo</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> * @category Video</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> * @aliases withNoVideo</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">18</td><td class="hits">1</td><td class="source"> proto.withNoVideo =</td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> proto.noVideo = function() {</td></tr><tr class="hit"><td class="line">20</td><td class="hits">2</td><td class="source"> this._video.clear();</td></tr><tr class="hit"><td class="line">21</td><td class="hits">2</td><td class="source"> this._video('-vn');</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">23</td><td class="hits">2</td><td class="source"> return this;</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">27</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> * Specify video codec</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#videoCodec</td></tr><tr><td class="line">31</td><td class="hits"></td><td class="source"> * @category Video</td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> * @aliases withVideoCodec</td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> * @param {String} codec video codec name</td></tr><tr><td class="line">35</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">36</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">37</td><td class="hits">1</td><td class="source"> proto.withVideoCodec =</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> proto.videoCodec = function(codec) {</td></tr><tr class="hit"><td class="line">39</td><td class="hits">27</td><td class="source"> this._video('-vcodec', codec);</td></tr><tr class="hit"><td class="line">40</td><td class="hits">27</td><td class="source"> return this;</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">45</td><td class="hits"></td><td class="source"> * Specify video bitrate</td></tr><tr><td class="line">46</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">47</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#videoBitrate</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> * @category Video</td></tr><tr><td class="line">49</td><td class="hits"></td><td class="source"> * @aliases withVideoBitrate</td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">51</td><td class="hits"></td><td class="source"> * @param {String|Number} bitrate video bitrate in kbps (with an optional 'k' suffix)</td></tr><tr><td class="line">52</td><td class="hits"></td><td class="source"> * @param {Boolean} [constant=false] enforce constant bitrate</td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">55</td><td class="hits">1</td><td class="source"> proto.withVideoBitrate =</td></tr><tr><td class="line">56</td><td class="hits"></td><td class="source"> proto.videoBitrate = function(bitrate, constant) {</td></tr><tr class="hit"><td class="line">57</td><td class="hits">22</td><td class="source"> bitrate = ('' + bitrate).replace(/k?$/, 'k');</td></tr><tr><td class="line">58</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">59</td><td class="hits">22</td><td class="source"> this._video('-b:v', bitrate);</td></tr><tr class="hit"><td class="line">60</td><td class="hits">22</td><td class="source"> if (constant) {</td></tr><tr class="hit"><td class="line">61</td><td class="hits">1</td><td class="source"> this._video(</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> '-maxrate', bitrate,</td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> '-minrate', bitrate,</td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> '-bufsize', '3M'</td></tr><tr><td class="line">65</td><td class="hits"></td><td class="source"> );</td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">68</td><td class="hits">22</td><td class="source"> return this;</td></tr><tr><td class="line">69</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">70</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">71</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> * Specify custom video filter(s)</td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">75</td><td class="hits"></td><td class="source"> * Can be called both with one or many filters, or a filter array.</td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> * @example</td></tr><tr><td class="line">78</td><td class="hits"></td><td class="source"> * command.videoFilters('filter1');</td></tr><tr><td class="line">79</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">80</td><td class="hits"></td><td class="source"> * @example</td></tr><tr><td class="line">81</td><td class="hits"></td><td class="source"> * command.videoFilters('filter1', 'filter2');</td></tr><tr><td class="line">82</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">83</td><td class="hits"></td><td class="source"> * @example</td></tr><tr><td class="line">84</td><td class="hits"></td><td class="source"> * command.videoFilters(['filter1', 'filter2']);</td></tr><tr><td class="line">85</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">86</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#videoFilters</td></tr><tr><td class="line">87</td><td class="hits"></td><td class="source"> * @category Video</td></tr><tr><td class="line">88</td><td class="hits"></td><td class="source"> * @aliases withVideoFilter,withVideoFilters,videoFilter</td></tr><tr><td class="line">89</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">90</td><td class="hits"></td><td class="source"> * @param {String|Array} filters... video filter strings or string array</td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">92</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">93</td><td class="hits">1</td><td class="source"> proto.withVideoFilter =</td></tr><tr><td class="line">94</td><td class="hits"></td><td class="source"> proto.withVideoFilters =</td></tr><tr><td class="line">95</td><td class="hits"></td><td class="source"> proto.videoFilter =</td></tr><tr><td class="line">96</td><td class="hits"></td><td class="source"> proto.videoFilters = function(filters) {</td></tr><tr class="hit"><td class="line">97</td><td class="hits">4</td><td class="source"> if (arguments.length > 1) {</td></tr><tr class="hit"><td class="line">98</td><td class="hits">2</td><td class="source"> filters = [].slice.call(arguments);</td></tr><tr><td class="line">99</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">100</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">101</td><td class="hits">4</td><td class="source"> if (Array.isArray(filters)) {</td></tr><tr class="hit"><td class="line">102</td><td class="hits">2</td><td class="source"> this._videoFilters.apply(null, filters);</td></tr><tr><td class="line">103</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">104</td><td class="hits">2</td><td class="source"> this._videoFilters(filters);</td></tr><tr><td class="line">105</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">106</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">107</td><td class="hits">4</td><td class="source"> return this;</td></tr><tr><td class="line">108</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">109</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">110</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">111</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">112</td><td class="hits"></td><td class="source"> * Specify output FPS</td></tr><tr><td class="line">113</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">114</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#fps</td></tr><tr><td class="line">115</td><td class="hits"></td><td class="source"> * @category Video</td></tr><tr><td class="line">116</td><td class="hits"></td><td class="source"> * @aliases withOutputFps,withOutputFPS,withFpsOutput,withFPSOutput,withFps,withFPS,outputFPS,outputFps,fpsOutput,FPSOutput,FPS</td></tr><tr><td class="line">117</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">118</td><td class="hits"></td><td class="source"> * @param {Number} fps output FPS</td></tr><tr><td class="line">119</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">120</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">121</td><td class="hits">1</td><td class="source"> proto.withOutputFps =</td></tr><tr><td class="line">122</td><td class="hits"></td><td class="source"> proto.withOutputFPS =</td></tr><tr><td class="line">123</td><td class="hits"></td><td class="source"> proto.withFpsOutput =</td></tr><tr><td class="line">124</td><td class="hits"></td><td class="source"> proto.withFPSOutput =</td></tr><tr><td class="line">125</td><td class="hits"></td><td class="source"> proto.withFps =</td></tr><tr><td class="line">126</td><td class="hits"></td><td class="source"> proto.withFPS =</td></tr><tr><td class="line">127</td><td class="hits"></td><td class="source"> proto.outputFPS =</td></tr><tr><td class="line">128</td><td class="hits"></td><td class="source"> proto.outputFps =</td></tr><tr><td class="line">129</td><td class="hits"></td><td class="source"> proto.fpsOutput =</td></tr><tr><td class="line">130</td><td class="hits"></td><td class="source"> proto.FPSOutput =</td></tr><tr><td class="line">131</td><td class="hits"></td><td class="source"> proto.fps =</td></tr><tr><td class="line">132</td><td class="hits"></td><td class="source"> proto.FPS = function(fps) {</td></tr><tr class="hit"><td class="line">133</td><td class="hits">19</td><td class="source"> this._video('-r', fps);</td></tr><tr class="hit"><td class="line">134</td><td class="hits">19</td><td class="source"> return this;</td></tr><tr><td class="line">135</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">136</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">137</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">138</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">139</td><td class="hits"></td><td class="source"> * Only transcode a certain number of frames</td></tr><tr><td class="line">140</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">141</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#frames</td></tr><tr><td class="line">142</td><td class="hits"></td><td class="source"> * @category Video</td></tr><tr><td class="line">143</td><td class="hits"></td><td class="source"> * @aliases takeFrames,withFrames</td></tr><tr><td class="line">144</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">145</td><td class="hits"></td><td class="source"> * @param {Number} frames frame count</td></tr><tr><td class="line">146</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">147</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">148</td><td class="hits">1</td><td class="source"> proto.takeFrames =</td></tr><tr><td class="line">149</td><td class="hits"></td><td class="source"> proto.withFrames =</td></tr><tr><td class="line">150</td><td class="hits"></td><td class="source"> proto.frames = function(frames) {</td></tr><tr class="hit"><td class="line">151</td><td class="hits">5</td><td class="source"> this._video('-vframes', frames);</td></tr><tr class="hit"><td class="line">152</td><td class="hits">5</td><td class="source"> return this;</td></tr><tr><td class="line">153</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">154</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">155</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div><div class="file"><h2 id="lib/options/videosize.js">lib/options/videosize.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">62</div><div class="hits">62</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true*/</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">4</td><td class="hits"></td><td class="source">/*</td></tr><tr><td class="line">5</td><td class="hits"></td><td class="source"> *! Size helpers</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> * Return filters to pad video to width*height,</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> * @param {Number} width output width</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> * @param {Number} height output height</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> * @param {Number} aspect video aspect ratio (without padding)</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> * @param {Number} color padding color</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> * @return scale/pad filters</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source">function getScalePadFilters(width, height, aspect, color) {</td></tr><tr><td class="line">20</td><td class="hits"></td><td class="source"> /*</td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> let a be the input aspect ratio, A be the requested aspect ratio</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source"> if a > A, padding is done on top and bottom</td></tr><tr><td class="line">24</td><td class="hits"></td><td class="source"> if a < A, padding is done on left and right</td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">26</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">27</td><td class="hits">10</td><td class="source"> return [</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> /*</td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source"> In both cases, we first have to scale the input to match the requested size.</td></tr><tr><td class="line">30</td><td class="hits"></td><td class="source"> When using computed width/height, we truncate them to multiples of 2</td></tr><tr><td class="line">31</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> scale=</td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> w=if(gt(a, A), width, trunc(height*a/2)*2):</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> h=if(lt(a, A), height, trunc(width/a/2)*2)</td></tr><tr><td class="line">35</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">36</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source"> 'scale=\'' +</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> 'w=if(gt(a,' + aspect + '),' + width + ',trunc(' + height + '*a/2)*2):' +</td></tr><tr><td class="line">39</td><td class="hits"></td><td class="source"> 'h=if(lt(a,' + aspect + '),' + height + ',trunc(' + width + '/a/2)*2)\'',</td></tr><tr><td class="line">40</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> /*</td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> Then we pad the scaled input to match the target size</td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> pad=</td></tr><tr><td class="line">45</td><td class="hits"></td><td class="source"> w=width:</td></tr><tr><td class="line">46</td><td class="hits"></td><td class="source"> h=height:</td></tr><tr><td class="line">47</td><td class="hits"></td><td class="source"> x=if(gt(a, A), 0, (width - iw)/2):</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> y=if(lt(a, A), 0, (height - ih)/2)</td></tr><tr><td class="line">49</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> (here iw and ih refer to the padding input, i.e the scaled output)</td></tr><tr><td class="line">51</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">52</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> 'pad=\'' +</td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> 'w=' + width + ':' +</td></tr><tr><td class="line">55</td><td class="hits"></td><td class="source"> 'h=' + height + ':' +</td></tr><tr><td class="line">56</td><td class="hits"></td><td class="source"> 'x=if(gt(a,' + aspect + '),0,(' + width + '-iw)/2):' +</td></tr><tr><td class="line">57</td><td class="hits"></td><td class="source"> 'y=if(lt(a,' + aspect + '),0,(' + height + '-ih)/2):' +</td></tr><tr><td class="line">58</td><td class="hits"></td><td class="source"> 'color=' + color + '\''</td></tr><tr><td class="line">59</td><td class="hits"></td><td class="source"> ];</td></tr><tr><td class="line">60</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> * Recompute size filters</td></tr><tr><td class="line">65</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> * @param {FfmpegCommand} command</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> * @param {String} key newly-added parameter name ('size', 'aspect' or 'pad')</td></tr><tr><td class="line">68</td><td class="hits"></td><td class="source"> * @param {String} value newly-added parameter value</td></tr><tr><td class="line">69</td><td class="hits"></td><td class="source"> * @return filter string array</td></tr><tr><td class="line">70</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">71</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source">function createSizeFilters(command, key, value) {</td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> // Store parameters</td></tr><tr class="hit"><td class="line">74</td><td class="hits">80</td><td class="source"> var data = command._sizeData = command._sizeData || {};</td></tr><tr class="hit"><td class="line">75</td><td class="hits">80</td><td class="source"> data[key] = value;</td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">77</td><td class="hits">80</td><td class="source"> if (!('size' in data)) {</td></tr><tr><td class="line">78</td><td class="hits"></td><td class="source"> // No size requested, keep original size</td></tr><tr class="hit"><td class="line">79</td><td class="hits">2</td><td class="source"> return [];</td></tr><tr><td class="line">80</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">81</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">82</td><td class="hits"></td><td class="source"> // Try to match the different size string formats</td></tr><tr class="hit"><td class="line">83</td><td class="hits">78</td><td class="source"> var fixedSize = data.size.match(/([0-9]+)x([0-9]+)/);</td></tr><tr class="hit"><td class="line">84</td><td class="hits">78</td><td class="source"> var fixedWidth = data.size.match(/([0-9]+)x\?/);</td></tr><tr class="hit"><td class="line">85</td><td class="hits">78</td><td class="source"> var fixedHeight = data.size.match(/\?x([0-9]+)/);</td></tr><tr class="hit"><td class="line">86</td><td class="hits">78</td><td class="source"> var percentRatio = data.size.match(/\b([0-9]{1,3})%/);</td></tr><tr class="hit"><td class="line">87</td><td class="hits">78</td><td class="source"> var width, height, aspect;</td></tr><tr><td class="line">88</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">89</td><td class="hits">78</td><td class="source"> if (percentRatio) {</td></tr><tr class="hit"><td class="line">90</td><td class="hits">5</td><td class="source"> var ratio = Number(percentRatio[1]) / 100;</td></tr><tr class="hit"><td class="line">91</td><td class="hits">5</td><td class="source"> return ['scale=trunc(iw*' + ratio + '/2)*2:trunc(ih*' + ratio + '/2)*2'];</td></tr><tr class="hit"><td class="line">92</td><td class="hits">73</td><td class="source"> } else if (fixedSize) {</td></tr><tr><td class="line">93</td><td class="hits"></td><td class="source"> // Round target size to multiples of 2</td></tr><tr class="hit"><td class="line">94</td><td class="hits">21</td><td class="source"> width = Math.round(Number(fixedSize[1]) / 2) * 2;</td></tr><tr class="hit"><td class="line">95</td><td class="hits">21</td><td class="source"> height = Math.round(Number(fixedSize[2]) / 2) * 2;</td></tr><tr><td class="line">96</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">97</td><td class="hits">21</td><td class="source"> aspect = width / height;</td></tr><tr><td class="line">98</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">99</td><td class="hits">21</td><td class="source"> if (data.pad) {</td></tr><tr class="hit"><td class="line">100</td><td class="hits">5</td><td class="source"> return getScalePadFilters(width, height, aspect, data.pad);</td></tr><tr><td class="line">101</td><td class="hits"></td><td class="source"> } else {</td></tr><tr><td class="line">102</td><td class="hits"></td><td class="source"> // No autopad requested, rescale to target size</td></tr><tr class="hit"><td class="line">103</td><td class="hits">16</td><td class="source"> return ['scale=' + width + ':' + height];</td></tr><tr><td class="line">104</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">105</td><td class="hits">52</td><td class="source"> } else if (fixedWidth || fixedHeight) {</td></tr><tr class="hit"><td class="line">106</td><td class="hits">51</td><td class="source"> if ('aspect' in data) {</td></tr><tr><td class="line">107</td><td class="hits"></td><td class="source"> // Specified aspect ratio</td></tr><tr class="hit"><td class="line">108</td><td class="hits">14</td><td class="source"> width = fixedWidth ? fixedWidth[1] : Math.round(Number(fixedHeight[1]) * data.aspect);</td></tr><tr class="hit"><td class="line">109</td><td class="hits">14</td><td class="source"> height = fixedHeight ? fixedHeight[1] : Math.round(Number(fixedWidth[1]) / data.aspect);</td></tr><tr><td class="line">110</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">111</td><td class="hits"></td><td class="source"> // Round to multiples of 2</td></tr><tr class="hit"><td class="line">112</td><td class="hits">14</td><td class="source"> width = Math.round(width / 2) * 2;</td></tr><tr class="hit"><td class="line">113</td><td class="hits">14</td><td class="source"> height = Math.round(height / 2) * 2;</td></tr><tr><td class="line">114</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">115</td><td class="hits">14</td><td class="source"> if (data.pad) {</td></tr><tr class="hit"><td class="line">116</td><td class="hits">5</td><td class="source"> return getScalePadFilters(width, height, data.aspect, data.pad);</td></tr><tr><td class="line">117</td><td class="hits"></td><td class="source"> } else {</td></tr><tr><td class="line">118</td><td class="hits"></td><td class="source"> // No autopad requested, rescale to target size</td></tr><tr class="hit"><td class="line">119</td><td class="hits">9</td><td class="source"> return ['scale=' + width + ':' + height];</td></tr><tr><td class="line">120</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">121</td><td class="hits"></td><td class="source"> } else {</td></tr><tr><td class="line">122</td><td class="hits"></td><td class="source"> // Keep input aspect ratio</td></tr><tr><td class="line">123</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">124</td><td class="hits">37</td><td class="source"> if (fixedWidth) {</td></tr><tr class="hit"><td class="line">125</td><td class="hits">31</td><td class="source"> return ['scale=' + (Math.round(Number(fixedWidth[1]) / 2) * 2) + ':trunc(ow/a/2)*2'];</td></tr><tr><td class="line">126</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">127</td><td class="hits">6</td><td class="source"> return ['scale=trunc(oh*a/2)*2:' + (Math.round(Number(fixedHeight[1]) / 2) * 2)];</td></tr><tr><td class="line">128</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">129</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">130</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">131</td><td class="hits">1</td><td class="source"> throw new Error('Invalid size specified: ' + data.size);</td></tr><tr><td class="line">132</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">133</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">134</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">135</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">136</td><td class="hits"></td><td class="source">/*</td></tr><tr><td class="line">137</td><td class="hits"></td><td class="source"> *! Video size-related methods</td></tr><tr><td class="line">138</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">139</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">140</td><td class="hits">1</td><td class="source">module.exports = function(proto) {</td></tr><tr><td class="line">141</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">142</td><td class="hits"></td><td class="source"> * Keep display aspect ratio</td></tr><tr><td class="line">143</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">144</td><td class="hits"></td><td class="source"> * This method is useful when converting an input with non-square pixels to an output format</td></tr><tr><td class="line">145</td><td class="hits"></td><td class="source"> * that does not support non-square pixels. It rescales the input so that the display aspect</td></tr><tr><td class="line">146</td><td class="hits"></td><td class="source"> * ratio is the same.</td></tr><tr><td class="line">147</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">148</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#keepDAR</td></tr><tr><td class="line">149</td><td class="hits"></td><td class="source"> * @category Video size</td></tr><tr><td class="line">150</td><td class="hits"></td><td class="source"> * @aliases keepPixelAspect,keepDisplayAspect,keepDisplayAspectRatio</td></tr><tr><td class="line">151</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">152</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">153</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">154</td><td class="hits">1</td><td class="source"> proto.keepPixelAspect = // Only for compatibility, this is not about keeping _pixel_ aspect ratio</td></tr><tr><td class="line">155</td><td class="hits"></td><td class="source"> proto.keepDisplayAspect =</td></tr><tr><td class="line">156</td><td class="hits"></td><td class="source"> proto.keepDisplayAspectRatio =</td></tr><tr><td class="line">157</td><td class="hits"></td><td class="source"> proto.keepDAR = function() {</td></tr><tr class="hit"><td class="line">158</td><td class="hits">1</td><td class="source"> return this.videoFilters(</td></tr><tr><td class="line">159</td><td class="hits"></td><td class="source"> 'scale=\'w=if(gt(sar,1),iw*sar,iw):h=if(lt(sar,1),ih/sar,ih)\'',</td></tr><tr><td class="line">160</td><td class="hits"></td><td class="source"> 'setsar=1'</td></tr><tr><td class="line">161</td><td class="hits"></td><td class="source"> );</td></tr><tr><td class="line">162</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">163</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">164</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">165</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">166</td><td class="hits"></td><td class="source"> * Set output size</td></tr><tr><td class="line">167</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">168</td><td class="hits"></td><td class="source"> * The 'size' parameter can have one of 4 forms:</td></tr><tr><td class="line">169</td><td class="hits"></td><td class="source"> * - 'X%': rescale to xx % of the original size</td></tr><tr><td class="line">170</td><td class="hits"></td><td class="source"> * - 'WxH': specify width and height</td></tr><tr><td class="line">171</td><td class="hits"></td><td class="source"> * - 'Wx?': specify width and compute height from input aspect ratio</td></tr><tr><td class="line">172</td><td class="hits"></td><td class="source"> * - '?xH': specify height and compute width from input aspect ratio</td></tr><tr><td class="line">173</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">174</td><td class="hits"></td><td class="source"> * Note: both dimensions will be truncated to multiples of 2.</td></tr><tr><td class="line">175</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">176</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#size</td></tr><tr><td class="line">177</td><td class="hits"></td><td class="source"> * @category Video size</td></tr><tr><td class="line">178</td><td class="hits"></td><td class="source"> * @aliases withSize,setSize</td></tr><tr><td class="line">179</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">180</td><td class="hits"></td><td class="source"> * @param {String} size size string, eg. '33%', '320x240', '320x?', '?x240'</td></tr><tr><td class="line">181</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">182</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">183</td><td class="hits">1</td><td class="source"> proto.withSize =</td></tr><tr><td class="line">184</td><td class="hits"></td><td class="source"> proto.setSize =</td></tr><tr><td class="line">185</td><td class="hits"></td><td class="source"> proto.size = function(size) {</td></tr><tr class="hit"><td class="line">186</td><td class="hits">52</td><td class="source"> var filters = createSizeFilters(this, 'size', size);</td></tr><tr><td class="line">187</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">188</td><td class="hits">51</td><td class="source"> this._sizeFilters.clear();</td></tr><tr class="hit"><td class="line">189</td><td class="hits">51</td><td class="source"> this._sizeFilters(filters);</td></tr><tr><td class="line">190</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">191</td><td class="hits">51</td><td class="source"> return this;</td></tr><tr><td class="line">192</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">193</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">194</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">195</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">196</td><td class="hits"></td><td class="source"> * Set output aspect ratio</td></tr><tr><td class="line">197</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">198</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#aspect</td></tr><tr><td class="line">199</td><td class="hits"></td><td class="source"> * @category Video size</td></tr><tr><td class="line">200</td><td class="hits"></td><td class="source"> * @aliases withAspect,withAspectRatio,setAspect,setAspectRatio,aspectRatio</td></tr><tr><td class="line">201</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">202</td><td class="hits"></td><td class="source"> * @param {String|Number} aspect aspect ratio (number or 'X:Y' string)</td></tr><tr><td class="line">203</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">204</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">205</td><td class="hits">1</td><td class="source"> proto.withAspect =</td></tr><tr><td class="line">206</td><td class="hits"></td><td class="source"> proto.withAspectRatio =</td></tr><tr><td class="line">207</td><td class="hits"></td><td class="source"> proto.setAspect =</td></tr><tr><td class="line">208</td><td class="hits"></td><td class="source"> proto.setAspectRatio =</td></tr><tr><td class="line">209</td><td class="hits"></td><td class="source"> proto.aspect =</td></tr><tr><td class="line">210</td><td class="hits"></td><td class="source"> proto.aspectRatio = function(aspect) {</td></tr><tr class="hit"><td class="line">211</td><td class="hits">15</td><td class="source"> var a = Number(aspect);</td></tr><tr class="hit"><td class="line">212</td><td class="hits">15</td><td class="source"> if (isNaN(a)) {</td></tr><tr class="hit"><td class="line">213</td><td class="hits">3</td><td class="source"> var match = aspect.match(/^(\d+):(\d+)$/);</td></tr><tr class="hit"><td class="line">214</td><td class="hits">3</td><td class="source"> if (match) {</td></tr><tr class="hit"><td class="line">215</td><td class="hits">2</td><td class="source"> a = Number(match[1]) / Number(match[2]);</td></tr><tr><td class="line">216</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">217</td><td class="hits">1</td><td class="source"> throw new Error('Invalid aspect ratio: ' + aspect);</td></tr><tr><td class="line">218</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">219</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">220</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">221</td><td class="hits">14</td><td class="source"> var filters = createSizeFilters(this, 'aspect', a);</td></tr><tr><td class="line">222</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">223</td><td class="hits">14</td><td class="source"> this._sizeFilters.clear();</td></tr><tr class="hit"><td class="line">224</td><td class="hits">14</td><td class="source"> this._sizeFilters(filters);</td></tr><tr><td class="line">225</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">226</td><td class="hits">14</td><td class="source"> return this;</td></tr><tr><td class="line">227</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">228</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">229</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">230</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">231</td><td class="hits"></td><td class="source"> * Enable auto-padding the output</td></tr><tr><td class="line">232</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">233</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#autopad</td></tr><tr><td class="line">234</td><td class="hits"></td><td class="source"> * @category Video size</td></tr><tr><td class="line">235</td><td class="hits"></td><td class="source"> * @aliases applyAutopadding,applyAutoPadding,applyAutopad,applyAutoPad,withAutopadding,withAutoPadding,withAutopad,withAutoPad,autoPad</td></tr><tr><td class="line">236</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">237</td><td class="hits"></td><td class="source"> * @param {Boolean} [pad=true] enable/disable auto-padding</td></tr><tr><td class="line">238</td><td class="hits"></td><td class="source"> * @param {String} [color='black'] pad color</td></tr><tr><td class="line">239</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">240</td><td class="hits">1</td><td class="source"> proto.applyAutopadding =</td></tr><tr><td class="line">241</td><td class="hits"></td><td class="source"> proto.applyAutoPadding =</td></tr><tr><td class="line">242</td><td class="hits"></td><td class="source"> proto.applyAutopad =</td></tr><tr><td class="line">243</td><td class="hits"></td><td class="source"> proto.applyAutoPad =</td></tr><tr><td class="line">244</td><td class="hits"></td><td class="source"> proto.withAutopadding =</td></tr><tr><td class="line">245</td><td class="hits"></td><td class="source"> proto.withAutoPadding =</td></tr><tr><td class="line">246</td><td class="hits"></td><td class="source"> proto.withAutopad =</td></tr><tr><td class="line">247</td><td class="hits"></td><td class="source"> proto.withAutoPad =</td></tr><tr><td class="line">248</td><td class="hits"></td><td class="source"> proto.autoPad =</td></tr><tr><td class="line">249</td><td class="hits"></td><td class="source"> proto.autopad = function(pad, color) {</td></tr><tr><td class="line">250</td><td class="hits"></td><td class="source"> // Allow autopad(color)</td></tr><tr class="hit"><td class="line">251</td><td class="hits">14</td><td class="source"> if (typeof pad === 'string') {</td></tr><tr class="hit"><td class="line">252</td><td class="hits">1</td><td class="source"> color = pad;</td></tr><tr class="hit"><td class="line">253</td><td class="hits">1</td><td class="source"> pad = true;</td></tr><tr><td class="line">254</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">255</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">256</td><td class="hits"></td><td class="source"> // Allow autopad() and autopad(undefined, color)</td></tr><tr class="hit"><td class="line">257</td><td class="hits">14</td><td class="source"> if (typeof pad === 'undefined') {</td></tr><tr class="hit"><td class="line">258</td><td class="hits">1</td><td class="source"> pad = true;</td></tr><tr><td class="line">259</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">260</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">261</td><td class="hits">14</td><td class="source"> var filters = createSizeFilters(this, 'pad', pad ? color || 'black' : false);</td></tr><tr><td class="line">262</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">263</td><td class="hits">14</td><td class="source"> this._sizeFilters.clear();</td></tr><tr class="hit"><td class="line">264</td><td class="hits">14</td><td class="source"> this._sizeFilters(filters);</td></tr><tr><td class="line">265</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">266</td><td class="hits">14</td><td class="source"> return this;</td></tr><tr><td class="line">267</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">268</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">269</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div><div class="file"><h2 id="lib/presets/flashvideo.js">lib/presets/flashvideo.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">2</div><div class="hits">2</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true */</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">4</td><td class="hits">1</td><td class="source">exports.load = function(ffmpeg) {</td></tr><tr class="hit"><td class="line">5</td><td class="hits">18</td><td class="source"> ffmpeg</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source"> .format('flv')</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source"> .flvmeta()</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source"> .size('320x?')</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> .videoBitrate('512k')</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> .videoCodec('libx264')</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> .fps(24)</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> .audioBitrate('96k')</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> .audioCodec('aac')</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> .strict()</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> .audioFrequency(22050)</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> .audioChannels(2);</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div><div class="file"><h2 id="lib/presets/podcast.js">lib/presets/podcast.js</h2><div id="stats" class="high"><div class="percentage">100%</div><div class="sloc">2</div><div class="hits">2</div><div class="misses">0</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true */</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">4</td><td class="hits">1</td><td class="source">exports.load = function(ffmpeg) {</td></tr><tr class="hit"><td class="line">5</td><td class="hits">1</td><td class="source"> ffmpeg</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source"> .format('m4v')</td></tr><tr><td class="line">7</td><td class="hits"></td><td class="source"> .videoBitrate('512k')</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source"> .videoCodec('libx264')</td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source"> .size('320x176')</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> .audioBitrate('128k')</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> .audioCodec('aac')</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> .strict()</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> .audioChannels(1)</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> .outputOptions(['-flags', '+loop', '-cmp', '+chroma', '-partitions','+parti4x4+partp8x8+partb8x8', '-flags2',</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> '+mixed_refs', '-me_method umh', '-subq 5', '-bufsize 2M', '-rc_eq \'blurCplx^(1-qComp)\'',</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> '-qcomp 0.6', '-qmin 10', '-qmax 51', '-qdiff 4', '-level 13' ]);</td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div><div class="file"><h2 id="lib/processor.js">lib/processor.js</h2><div id="stats" class="high"><div class="percentage">85%</div><div class="sloc">360</div><div class="hits">307</div><div class="misses">53</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true*/</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">4</td><td class="hits">1</td><td class="source">var spawn = require('child_process').spawn;</td></tr><tr class="hit"><td class="line">5</td><td class="hits">1</td><td class="source">var PassThrough = require('stream').PassThrough;</td></tr><tr class="hit"><td class="line">6</td><td class="hits">1</td><td class="source">var path = require('path');</td></tr><tr class="hit"><td class="line">7</td><td class="hits">1</td><td class="source">var fs = require('fs');</td></tr><tr class="hit"><td class="line">8</td><td class="hits">1</td><td class="source">var async = require('async');</td></tr><tr class="hit"><td class="line">9</td><td class="hits">1</td><td class="source">var utils = require('./utils');</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source">/*</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> *! Processor methods</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">17</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> * @param {FfmpegCommand} command</td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> * @param {String|Writable} target</td></tr><tr><td class="line">20</td><td class="hits"></td><td class="source"> * @param {Object} [pipeOptions]</td></tr><tr><td class="line">21</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source">function _process(command, target, pipeOptions) {</td></tr><tr class="hit"><td class="line">24</td><td class="hits">19</td><td class="source"> var isStream;</td></tr><tr><td class="line">25</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">26</td><td class="hits">19</td><td class="source"> if (typeof target === 'string') {</td></tr><tr class="hit"><td class="line">27</td><td class="hits">16</td><td class="source"> isStream = false;</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">29</td><td class="hits">3</td><td class="source"> isStream = true;</td></tr><tr class="hit"><td class="line">30</td><td class="hits">3</td><td class="source"> pipeOptions = pipeOptions || {};</td></tr><tr><td class="line">31</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">33</td><td class="hits"></td><td class="source"> // Ensure we send 'end' or 'error' only once</td></tr><tr class="hit"><td class="line">34</td><td class="hits">19</td><td class="source"> var ended = false;</td></tr><tr><td class="line">35</td><td class="hits"></td><td class="source"> function emitEnd(err, stdout, stderr) {</td></tr><tr class="hit"><td class="line">36</td><td class="hits">24</td><td class="source"> if (!ended) {</td></tr><tr class="hit"><td class="line">37</td><td class="hits">19</td><td class="source"> ended = true;</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">39</td><td class="hits">19</td><td class="source"> if (err) {</td></tr><tr class="hit"><td class="line">40</td><td class="hits">5</td><td class="source"> command.emit('error', err, stdout, stderr);</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">42</td><td class="hits">14</td><td class="source"> command.emit('end', stdout, stderr);</td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">45</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">46</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">47</td><td class="hits">19</td><td class="source"> command._prepare(function(err, args) {</td></tr><tr class="hit"><td class="line">48</td><td class="hits">19</td><td class="source"> if (err) {</td></tr><tr class="hit"><td class="line">49</td><td class="hits">1</td><td class="source"> return emitEnd(err);</td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">51</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">52</td><td class="hits">18</td><td class="source"> if (isStream) {</td></tr><tr class="hit"><td class="line">53</td><td class="hits">3</td><td class="source"> args.push('pipe:1');</td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">55</td><td class="hits">3</td><td class="source"> if (command.options.flvmeta) {</td></tr><tr class="hit"><td class="line">56</td><td class="hits">3</td><td class="source"> command.logger.warn('Updating flv metadata is not supported for streams');</td></tr><tr class="hit"><td class="line">57</td><td class="hits">3</td><td class="source"> command.options.flvmeta = false;</td></tr><tr><td class="line">58</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">59</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">60</td><td class="hits">15</td><td class="source"> args.push('-y', target);</td></tr><tr><td class="line">61</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> // Get input stream if any</td></tr><tr class="hit"><td class="line">64</td><td class="hits">18</td><td class="source"> var inputStream = command._inputs.filter(function(input) {</td></tr><tr class="hit"><td class="line">65</td><td class="hits">18</td><td class="source"> return typeof input.source !== 'string';</td></tr><tr><td class="line">66</td><td class="hits"></td><td class="source"> })[0];</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">68</td><td class="hits"></td><td class="source"> // Run ffmpeg</td></tr><tr class="hit"><td class="line">69</td><td class="hits">18</td><td class="source"> var stdout = null;</td></tr><tr class="hit"><td class="line">70</td><td class="hits">18</td><td class="source"> var stderr = '';</td></tr><tr class="hit"><td class="line">71</td><td class="hits">18</td><td class="source"> command._spawnFfmpeg(</td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> args,</td></tr><tr><td class="line">73</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">74</td><td class="hits"></td><td class="source"> { niceness: command.options.niceness },</td></tr><tr><td class="line">75</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">76</td><td class="hits"></td><td class="source"> function processCB(ffmpegProc) {</td></tr><tr class="hit"><td class="line">77</td><td class="hits">18</td><td class="source"> command.ffmpegProc = ffmpegProc;</td></tr><tr class="hit"><td class="line">78</td><td class="hits">18</td><td class="source"> command.emit('start', 'ffmpeg ' + args.join(' '));</td></tr><tr><td class="line">79</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">80</td><td class="hits"></td><td class="source"> // Pipe input stream if any</td></tr><tr class="hit"><td class="line">81</td><td class="hits">18</td><td class="source"> if (inputStream) {</td></tr><tr class="hit"><td class="line">82</td><td class="hits">2</td><td class="source"> inputStream.source.on('error', function(err) {</td></tr><tr class="miss"><td class="line">83</td><td class="hits">0</td><td class="source"> emitEnd(new Error('Input stream error: ' + err.message));</td></tr><tr class="miss"><td class="line">84</td><td class="hits">0</td><td class="source"> ffmpegProc.kill();</td></tr><tr><td class="line">85</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">86</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">87</td><td class="hits">2</td><td class="source"> inputStream.source.resume();</td></tr><tr class="hit"><td class="line">88</td><td class="hits">2</td><td class="source"> inputStream.source.pipe(ffmpegProc.stdin);</td></tr><tr><td class="line">89</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">90</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source"> // Setup timeout if requested</td></tr><tr class="hit"><td class="line">92</td><td class="hits">18</td><td class="source"> var processTimer;</td></tr><tr class="hit"><td class="line">93</td><td class="hits">18</td><td class="source"> if (command.options.timeout) {</td></tr><tr class="hit"><td class="line">94</td><td class="hits">4</td><td class="source"> processTimer = setTimeout(function() {</td></tr><tr class="hit"><td class="line">95</td><td class="hits">3</td><td class="source"> var msg = 'process ran into a timeout (' + command.options.timeout + 's)';</td></tr><tr><td class="line">96</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">97</td><td class="hits">3</td><td class="source"> emitEnd(new Error(msg), stdout, stderr);</td></tr><tr class="hit"><td class="line">98</td><td class="hits">3</td><td class="source"> ffmpegProc.kill();</td></tr><tr><td class="line">99</td><td class="hits"></td><td class="source"> }, command.options.timeout * 1000);</td></tr><tr><td class="line">100</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">101</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">102</td><td class="hits">18</td><td class="source"> if (isStream) {</td></tr><tr><td class="line">103</td><td class="hits"></td><td class="source"> // Pipe ffmpeg stdout to output stream</td></tr><tr class="hit"><td class="line">104</td><td class="hits">3</td><td class="source"> ffmpegProc.stdout.pipe(target, pipeOptions);</td></tr><tr><td class="line">105</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">106</td><td class="hits"></td><td class="source"> // Handle output stream events</td></tr><tr class="hit"><td class="line">107</td><td class="hits">3</td><td class="source"> target.on('close', function() {</td></tr><tr class="hit"><td class="line">108</td><td class="hits">2</td><td class="source"> command.logger.debug('Output stream closed, scheduling kill for ffmpgeg process');</td></tr><tr><td class="line">109</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">110</td><td class="hits"></td><td class="source"> // Don't kill process yet, to give a chance to ffmpeg to</td></tr><tr><td class="line">111</td><td class="hits"></td><td class="source"> // terminate successfully first This is necessary because</td></tr><tr><td class="line">112</td><td class="hits"></td><td class="source"> // under load, the process 'exit' event sometimes happens</td></tr><tr><td class="line">113</td><td class="hits"></td><td class="source"> // after the output stream 'close' event.</td></tr><tr class="hit"><td class="line">114</td><td class="hits">2</td><td class="source"> setTimeout(function() {</td></tr><tr class="hit"><td class="line">115</td><td class="hits">2</td><td class="source"> emitEnd(new Error('Output stream closed'));</td></tr><tr class="hit"><td class="line">116</td><td class="hits">2</td><td class="source"> ffmpegProc.kill();</td></tr><tr><td class="line">117</td><td class="hits"></td><td class="source"> }, 20);</td></tr><tr><td class="line">118</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">119</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">120</td><td class="hits">3</td><td class="source"> target.on('error', function(err) {</td></tr><tr class="miss"><td class="line">121</td><td class="hits">0</td><td class="source"> command.logger.debug('Output stream error, killing ffmpgeg process');</td></tr><tr class="miss"><td class="line">122</td><td class="hits">0</td><td class="source"> emitEnd(new Error('Output stream error: ' + err.message));</td></tr><tr class="miss"><td class="line">123</td><td class="hits">0</td><td class="source"> ffmpegProc.kill();</td></tr><tr><td class="line">124</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">125</td><td class="hits"></td><td class="source"> } else {</td></tr><tr><td class="line">126</td><td class="hits"></td><td class="source"> // Gather ffmpeg stdout</td></tr><tr class="hit"><td class="line">127</td><td class="hits">15</td><td class="source"> stdout = '';</td></tr><tr class="hit"><td class="line">128</td><td class="hits">15</td><td class="source"> ffmpegProc.stdout.on('data', function (data) {</td></tr><tr class="miss"><td class="line">129</td><td class="hits">0</td><td class="source"> stdout += data;</td></tr><tr><td class="line">130</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">131</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">132</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">133</td><td class="hits"></td><td class="source"> // Process ffmpeg stderr data</td></tr><tr class="hit"><td class="line">134</td><td class="hits">18</td><td class="source"> command._codecDataSent = false;</td></tr><tr class="hit"><td class="line">135</td><td class="hits">18</td><td class="source"> ffmpegProc.stderr.on('data', function (data) {</td></tr><tr class="hit"><td class="line">136</td><td class="hits">324</td><td class="source"> stderr += data;</td></tr><tr><td class="line">137</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">138</td><td class="hits">324</td><td class="source"> if (!command._codecDataSent && command.listeners('codecData').length) {</td></tr><tr class="hit"><td class="line">139</td><td class="hits">11</td><td class="source"> utils.extractCodecData(command, stderr);</td></tr><tr><td class="line">140</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">141</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">142</td><td class="hits">324</td><td class="source"> if (command.listeners('progress').length) {</td></tr><tr class="hit"><td class="line">143</td><td class="hits">26</td><td class="source"> var duration = 0;</td></tr><tr><td class="line">144</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">145</td><td class="hits">26</td><td class="source"> if (command._ffprobeData && command._ffprobeData.format && command._ffprobeData.format.duration) {</td></tr><tr class="hit"><td class="line">146</td><td class="hits">21</td><td class="source"> duration = Number(command._ffprobeData.format.duration);</td></tr><tr><td class="line">147</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">148</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">149</td><td class="hits">26</td><td class="source"> utils.extractProgress(command, stderr, duration);</td></tr><tr><td class="line">150</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">151</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">152</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">153</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">154</td><td class="hits"></td><td class="source"> function endCB(err) {</td></tr><tr class="hit"><td class="line">155</td><td class="hits">18</td><td class="source"> delete command.ffmpegProc;</td></tr><tr><td class="line">156</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">157</td><td class="hits">18</td><td class="source"> if (err) {</td></tr><tr class="hit"><td class="line">158</td><td class="hits">4</td><td class="source"> emitEnd(err, stdout, stderr);</td></tr><tr><td class="line">159</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">160</td><td class="hits">14</td><td class="source"> if (command.options.flvmeta) {</td></tr><tr class="hit"><td class="line">161</td><td class="hits">11</td><td class="source"> command._getFlvtoolPath(function(err, flvtool) {</td></tr><tr><td class="line">162</td><td class="hits"></td><td class="source"> // No error possible here, _getFlvtoolPath was called by _prepare</td></tr><tr><td class="line">163</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">164</td><td class="hits">11</td><td class="source"> spawn(flvtool, ['-U', target])</td></tr><tr><td class="line">165</td><td class="hits"></td><td class="source"> .on('error', function(err) {</td></tr><tr class="miss"><td class="line">166</td><td class="hits">0</td><td class="source"> emitEnd(new Error('Error running ' + flvtool + ': ' + err.message));</td></tr><tr><td class="line">167</td><td class="hits"></td><td class="source"> })</td></tr><tr><td class="line">168</td><td class="hits"></td><td class="source"> .on('exit', function(code, signal) {</td></tr><tr class="hit"><td class="line">169</td><td class="hits">11</td><td class="source"> if (code !== 0 || signal) {</td></tr><tr class="miss"><td class="line">170</td><td class="hits">0</td><td class="source"> emitEnd(</td></tr><tr><td class="line">171</td><td class="hits"></td><td class="source"> new Error(flvtool + ' ' +</td></tr><tr><td class="line">172</td><td class="hits"></td><td class="source"> (signal ? 'received signal ' + signal</td></tr><tr><td class="line">173</td><td class="hits"></td><td class="source"> : 'exited with code ' + code))</td></tr><tr><td class="line">174</td><td class="hits"></td><td class="source"> );</td></tr><tr><td class="line">175</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">176</td><td class="hits">11</td><td class="source"> emitEnd(null, stdout, stderr);</td></tr><tr><td class="line">177</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">178</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">179</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">180</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">181</td><td class="hits">3</td><td class="source"> emitEnd(null, stdout, stderr);</td></tr><tr><td class="line">182</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">183</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">184</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">185</td><td class="hits"></td><td class="source"> );</td></tr><tr><td class="line">186</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">187</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">188</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">189</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">190</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">191</td><td class="hits"></td><td class="source"> * Run ffprobe asynchronously and store data in command</td></tr><tr><td class="line">192</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">193</td><td class="hits"></td><td class="source"> * @param {FfmpegCommand} command</td></tr><tr><td class="line">194</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">195</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">196</td><td class="hits"></td><td class="source">function runFfprobe(command) {</td></tr><tr class="hit"><td class="line">197</td><td class="hits">1</td><td class="source"> command.ffprobe(function(err, data) {</td></tr><tr class="hit"><td class="line">198</td><td class="hits">1</td><td class="source"> command._ffprobeData = data;</td></tr><tr><td class="line">199</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">200</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">201</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">202</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">203</td><td class="hits">1</td><td class="source">module.exports = function(proto) {</td></tr><tr><td class="line">204</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">205</td><td class="hits"></td><td class="source"> * Emitted just after ffmpeg has been spawned.</td></tr><tr><td class="line">206</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">207</td><td class="hits"></td><td class="source"> * @event FfmpegCommand#start</td></tr><tr><td class="line">208</td><td class="hits"></td><td class="source"> * @param {String} command ffmpeg command line</td></tr><tr><td class="line">209</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">210</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">211</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">212</td><td class="hits"></td><td class="source"> * Emitted when ffmpeg reports progress information</td></tr><tr><td class="line">213</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">214</td><td class="hits"></td><td class="source"> * @event FfmpegCommand#progress</td></tr><tr><td class="line">215</td><td class="hits"></td><td class="source"> * @param {Object} progress progress object</td></tr><tr><td class="line">216</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">217</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">218</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">219</td><td class="hits"></td><td class="source"> * Emitted when ffmpeg reports input codec data</td></tr><tr><td class="line">220</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">221</td><td class="hits"></td><td class="source"> * @event FfmpegCommand#codecData</td></tr><tr><td class="line">222</td><td class="hits"></td><td class="source"> * @param {Object} codecData codec data object</td></tr><tr><td class="line">223</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">224</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">225</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">226</td><td class="hits"></td><td class="source"> * Emitted when an error happens when preparing or running a command</td></tr><tr><td class="line">227</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">228</td><td class="hits"></td><td class="source"> * @event FfmpegCommand#error</td></tr><tr><td class="line">229</td><td class="hits"></td><td class="source"> * @param {Error} error error</td></tr><tr><td class="line">230</td><td class="hits"></td><td class="source"> * @param {String|null} stdout ffmpeg stdout, unless outputting to a stream</td></tr><tr><td class="line">231</td><td class="hits"></td><td class="source"> * @param {String|null} stderr ffmpeg stderr</td></tr><tr><td class="line">232</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">233</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">234</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">235</td><td class="hits"></td><td class="source"> * Emitted when a command finishes processing</td></tr><tr><td class="line">236</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">237</td><td class="hits"></td><td class="source"> * @event FfmpegCommand#end</td></tr><tr><td class="line">238</td><td class="hits"></td><td class="source"> * @param {Array|null} [filenames] generated filenames when taking screenshots, null otherwise</td></tr><tr><td class="line">239</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">240</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">241</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">242</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">243</td><td class="hits"></td><td class="source"> * Spawn an ffmpeg process</td></tr><tr><td class="line">244</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">245</td><td class="hits"></td><td class="source"> * The 'options' argument may contain the following keys:</td></tr><tr><td class="line">246</td><td class="hits"></td><td class="source"> * - 'niceness': specify process niceness, ignored on Windows (default: 0)</td></tr><tr><td class="line">247</td><td class="hits"></td><td class="source"> * - 'captureStdout': capture stdout and pass it to 'endCB' as its 2nd argument (default: false)</td></tr><tr><td class="line">248</td><td class="hits"></td><td class="source"> * - 'captureStderr': capture stderr and pass it to 'endCB' as its 3rd argument (default: false)</td></tr><tr><td class="line">249</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">250</td><td class="hits"></td><td class="source"> * The 'processCB' callback, if present, is called as soon as the process is created and</td></tr><tr><td class="line">251</td><td class="hits"></td><td class="source"> * receives a nodejs ChildProcess object. It may not be called at all if an error happens</td></tr><tr><td class="line">252</td><td class="hits"></td><td class="source"> * before spawning the process.</td></tr><tr><td class="line">253</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">254</td><td class="hits"></td><td class="source"> * The 'endCB' callback is called either when an error occurs or when the ffmpeg process finishes.</td></tr><tr><td class="line">255</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">256</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#_spawnFfmpeg</td></tr><tr><td class="line">257</td><td class="hits"></td><td class="source"> * @param {Array} args ffmpeg command line argument list</td></tr><tr><td class="line">258</td><td class="hits"></td><td class="source"> * @param {Object} [options] spawn options (see above)</td></tr><tr><td class="line">259</td><td class="hits"></td><td class="source"> * @param {Function} [processCB] callback called with process object when it has been created</td></tr><tr><td class="line">260</td><td class="hits"></td><td class="source"> * @param {Function} endCB callback with signature (err, stdout, stderr)</td></tr><tr><td class="line">261</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">262</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">263</td><td class="hits">1</td><td class="source"> proto._spawnFfmpeg = function(args, options, processCB, endCB) {</td></tr><tr><td class="line">264</td><td class="hits"></td><td class="source"> // Enable omitting options</td></tr><tr class="hit"><td class="line">265</td><td class="hits">30</td><td class="source"> if (typeof options === 'function') {</td></tr><tr class="hit"><td class="line">266</td><td class="hits">8</td><td class="source"> endCB = processCB;</td></tr><tr class="hit"><td class="line">267</td><td class="hits">8</td><td class="source"> processCB = options;</td></tr><tr class="hit"><td class="line">268</td><td class="hits">8</td><td class="source"> options = {};</td></tr><tr><td class="line">269</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">270</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">271</td><td class="hits"></td><td class="source"> // Enable omitting processCB</td></tr><tr class="hit"><td class="line">272</td><td class="hits">30</td><td class="source"> if (typeof endCB === 'undefined') {</td></tr><tr class="hit"><td class="line">273</td><td class="hits">12</td><td class="source"> endCB = processCB;</td></tr><tr class="hit"><td class="line">274</td><td class="hits">12</td><td class="source"> processCB = function() {};</td></tr><tr><td class="line">275</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">276</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">277</td><td class="hits"></td><td class="source"> // Find ffmpeg</td></tr><tr class="hit"><td class="line">278</td><td class="hits">30</td><td class="source"> this._getFfmpegPath(function(err, command) {</td></tr><tr class="hit"><td class="line">279</td><td class="hits">30</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">280</td><td class="hits">0</td><td class="source"> return endCB(err);</td></tr><tr class="hit"><td class="line">281</td><td class="hits">30</td><td class="source"> } else if (!command || command.length === 0) {</td></tr><tr class="miss"><td class="line">282</td><td class="hits">0</td><td class="source"> return endCB(new Error('Cannot find ffmpeg'));</td></tr><tr><td class="line">283</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">284</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">285</td><td class="hits"></td><td class="source"> // Apply niceness</td></tr><tr class="hit"><td class="line">286</td><td class="hits">30</td><td class="source"> if (options.niceness && options.niceness !== 0 && !utils.isWindows) {</td></tr><tr class="miss"><td class="line">287</td><td class="hits">0</td><td class="source"> args.unshift('-n', options.niceness, command);</td></tr><tr class="miss"><td class="line">288</td><td class="hits">0</td><td class="source"> command = 'nice';</td></tr><tr><td class="line">289</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">290</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">291</td><td class="hits">30</td><td class="source"> var stdout = null;</td></tr><tr class="hit"><td class="line">292</td><td class="hits">30</td><td class="source"> var stdoutClosed = false;</td></tr><tr><td class="line">293</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">294</td><td class="hits">30</td><td class="source"> var stderr = null;</td></tr><tr class="hit"><td class="line">295</td><td class="hits">30</td><td class="source"> var stderrClosed = false;</td></tr><tr><td class="line">296</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">297</td><td class="hits"></td><td class="source"> // Spawn process</td></tr><tr class="hit"><td class="line">298</td><td class="hits">30</td><td class="source"> var ffmpegProc = spawn(command, args, options);</td></tr><tr><td class="line">299</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">300</td><td class="hits">30</td><td class="source"> if (ffmpegProc.stderr && options.captureStderr) {</td></tr><tr class="hit"><td class="line">301</td><td class="hits">1</td><td class="source"> ffmpegProc.stderr.setEncoding('utf8');</td></tr><tr><td class="line">302</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">303</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">304</td><td class="hits">30</td><td class="source"> ffmpegProc.on('error', function(err) {</td></tr><tr class="miss"><td class="line">305</td><td class="hits">0</td><td class="source"> endCB(err);</td></tr><tr><td class="line">306</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">307</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">308</td><td class="hits"></td><td class="source"> // Ensure we wait for captured streams to end before calling endCB</td></tr><tr class="hit"><td class="line">309</td><td class="hits">30</td><td class="source"> var exitError = null;</td></tr><tr><td class="line">310</td><td class="hits"></td><td class="source"> function handleExit(err) {</td></tr><tr class="hit"><td class="line">311</td><td class="hits">35</td><td class="source"> if (err) {</td></tr><tr class="hit"><td class="line">312</td><td class="hits">4</td><td class="source"> exitError = err;</td></tr><tr><td class="line">313</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">314</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">315</td><td class="hits">35</td><td class="source"> if (processExited &&</td></tr><tr><td class="line">316</td><td class="hits"></td><td class="source"> (stdoutClosed || !options.captureStdout) &&</td></tr><tr><td class="line">317</td><td class="hits"></td><td class="source"> (stderrClosed || !options.captureStderr)) {</td></tr><tr class="hit"><td class="line">318</td><td class="hits">30</td><td class="source"> endCB(exitError, stdout, stderr);</td></tr><tr><td class="line">319</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">320</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">321</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">322</td><td class="hits"></td><td class="source"> // Handle process exit</td></tr><tr class="hit"><td class="line">323</td><td class="hits">30</td><td class="source"> var processExited = false;</td></tr><tr class="hit"><td class="line">324</td><td class="hits">30</td><td class="source"> ffmpegProc.on('exit', function(code, signal) {</td></tr><tr class="hit"><td class="line">325</td><td class="hits">30</td><td class="source"> processExited = true;</td></tr><tr><td class="line">326</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">327</td><td class="hits">30</td><td class="source"> if (code) {</td></tr><tr class="hit"><td class="line">328</td><td class="hits">3</td><td class="source"> handleExit(new Error('ffmpeg exited with code ' + code));</td></tr><tr class="hit"><td class="line">329</td><td class="hits">27</td><td class="source"> } else if (signal) {</td></tr><tr class="hit"><td class="line">330</td><td class="hits">1</td><td class="source"> handleExit(new Error('ffmpeg was killed with signal ' + signal));</td></tr><tr><td class="line">331</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">332</td><td class="hits">26</td><td class="source"> handleExit();</td></tr><tr><td class="line">333</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">334</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">335</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">336</td><td class="hits"></td><td class="source"> // Capture stdout if specified</td></tr><tr class="hit"><td class="line">337</td><td class="hits">30</td><td class="source"> if (options.captureStdout) {</td></tr><tr class="hit"><td class="line">338</td><td class="hits">4</td><td class="source"> stdout = '';</td></tr><tr><td class="line">339</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">340</td><td class="hits">4</td><td class="source"> ffmpegProc.stdout.on('data', function(data) {</td></tr><tr class="hit"><td class="line">341</td><td class="hits">11</td><td class="source"> stdout += data;</td></tr><tr><td class="line">342</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">343</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">344</td><td class="hits">4</td><td class="source"> ffmpegProc.stdout.on('close', function() {</td></tr><tr class="hit"><td class="line">345</td><td class="hits">4</td><td class="source"> stdoutClosed = true;</td></tr><tr class="hit"><td class="line">346</td><td class="hits">4</td><td class="source"> handleExit();</td></tr><tr><td class="line">347</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">348</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">349</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">350</td><td class="hits"></td><td class="source"> // Capture stderr if specified</td></tr><tr class="hit"><td class="line">351</td><td class="hits">30</td><td class="source"> if (options.captureStderr) {</td></tr><tr class="hit"><td class="line">352</td><td class="hits">1</td><td class="source"> stderr = '';</td></tr><tr><td class="line">353</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">354</td><td class="hits">1</td><td class="source"> ffmpegProc.stderr.on('data', function(data) {</td></tr><tr class="miss"><td class="line">355</td><td class="hits">0</td><td class="source"> stderr += data;</td></tr><tr><td class="line">356</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">357</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">358</td><td class="hits">1</td><td class="source"> ffmpegProc.stderr.on('close', function() {</td></tr><tr class="hit"><td class="line">359</td><td class="hits">1</td><td class="source"> stderrClosed = true;</td></tr><tr class="hit"><td class="line">360</td><td class="hits">1</td><td class="source"> handleExit();</td></tr><tr><td class="line">361</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">362</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">363</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">364</td><td class="hits"></td><td class="source"> // Call process callback</td></tr><tr class="hit"><td class="line">365</td><td class="hits">30</td><td class="source"> processCB(ffmpegProc);</td></tr><tr><td class="line">366</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">367</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">368</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">369</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">370</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">371</td><td class="hits"></td><td class="source"> * Build the argument list for an ffmpeg command</td></tr><tr><td class="line">372</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">373</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#_getArguments</td></tr><tr><td class="line">374</td><td class="hits"></td><td class="source"> * @return argument list</td></tr><tr><td class="line">375</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">376</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">377</td><td class="hits">1</td><td class="source"> proto._getArguments = function() {</td></tr><tr class="hit"><td class="line">378</td><td class="hits">53</td><td class="source"> var audioFilters = this._audioFilters.get();</td></tr><tr class="hit"><td class="line">379</td><td class="hits">53</td><td class="source"> var videoFilters = this._videoFilters.get().concat(this._sizeFilters.get());</td></tr><tr><td class="line">380</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">381</td><td class="hits">53</td><td class="source"> return this._inputs.reduce(function(args, input) {</td></tr><tr class="hit"><td class="line">382</td><td class="hits">54</td><td class="source"> var source = (typeof input.source === 'string') ? input.source : '-';</td></tr><tr><td class="line">383</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">384</td><td class="hits">54</td><td class="source"> return args.concat(</td></tr><tr><td class="line">385</td><td class="hits"></td><td class="source"> input.before.get(),</td></tr><tr><td class="line">386</td><td class="hits"></td><td class="source"> ['-i', source],</td></tr><tr><td class="line">387</td><td class="hits"></td><td class="source"> input.after.get()</td></tr><tr><td class="line">388</td><td class="hits"></td><td class="source"> );</td></tr><tr><td class="line">389</td><td class="hits"></td><td class="source"> }, [])</td></tr><tr><td class="line">390</td><td class="hits"></td><td class="source"> .concat(</td></tr><tr><td class="line">391</td><td class="hits"></td><td class="source"> this._audio.get(),</td></tr><tr><td class="line">392</td><td class="hits"></td><td class="source"> audioFilters.length ? ['-filter:a', audioFilters.join(',')] : [],</td></tr><tr><td class="line">393</td><td class="hits"></td><td class="source"> this._video.get(),</td></tr><tr><td class="line">394</td><td class="hits"></td><td class="source"> videoFilters.length ? ['-filter:v', videoFilters.join(',')] : [],</td></tr><tr><td class="line">395</td><td class="hits"></td><td class="source"> this._output.get()</td></tr><tr><td class="line">396</td><td class="hits"></td><td class="source"> );</td></tr><tr><td class="line">397</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">398</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">399</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">400</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">401</td><td class="hits"></td><td class="source"> * Prepare execution of an ffmpeg command</td></tr><tr><td class="line">402</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">403</td><td class="hits"></td><td class="source"> * Checks prerequisites for the execution of the command (codec/format availability, flvtool...),</td></tr><tr><td class="line">404</td><td class="hits"></td><td class="source"> * then builds the argument list for ffmpeg and pass them to 'callback'.</td></tr><tr><td class="line">405</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">406</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#_prepare</td></tr><tr><td class="line">407</td><td class="hits"></td><td class="source"> * @param {Function} callback callback with signature (err, args)</td></tr><tr><td class="line">408</td><td class="hits"></td><td class="source"> * @param {Boolean} [readMetadata=false] read metadata before processing</td></tr><tr><td class="line">409</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">410</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">411</td><td class="hits">1</td><td class="source"> proto._prepare = function(callback, readMetadata) {</td></tr><tr class="hit"><td class="line">412</td><td class="hits">21</td><td class="source"> var self = this;</td></tr><tr><td class="line">413</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">414</td><td class="hits">21</td><td class="source"> async.waterfall([</td></tr><tr><td class="line">415</td><td class="hits"></td><td class="source"> // Check codecs and formats</td></tr><tr><td class="line">416</td><td class="hits"></td><td class="source"> function(cb) {</td></tr><tr class="hit"><td class="line">417</td><td class="hits">21</td><td class="source"> self._checkCapabilities(cb);</td></tr><tr><td class="line">418</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">419</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">420</td><td class="hits"></td><td class="source"> // Read metadata if required</td></tr><tr><td class="line">421</td><td class="hits"></td><td class="source"> function(cb) {</td></tr><tr class="hit"><td class="line">422</td><td class="hits">20</td><td class="source"> if (!readMetadata) {</td></tr><tr class="hit"><td class="line">423</td><td class="hits">18</td><td class="source"> return cb();</td></tr><tr><td class="line">424</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">425</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">426</td><td class="hits">2</td><td class="source"> self.ffprobe(function(err, data) {</td></tr><tr class="hit"><td class="line">427</td><td class="hits">2</td><td class="source"> if (!err) {</td></tr><tr class="hit"><td class="line">428</td><td class="hits">2</td><td class="source"> self._ffprobeData = data;</td></tr><tr><td class="line">429</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">430</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">431</td><td class="hits">2</td><td class="source"> cb();</td></tr><tr><td class="line">432</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">433</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">434</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">435</td><td class="hits"></td><td class="source"> // Check for flvtool2/flvmeta if necessary</td></tr><tr><td class="line">436</td><td class="hits"></td><td class="source"> function(cb) {</td></tr><tr class="hit"><td class="line">437</td><td class="hits">20</td><td class="source"> if (self.options.flvmeta) {</td></tr><tr class="hit"><td class="line">438</td><td class="hits">18</td><td class="source"> self._getFlvtoolPath(function(err) {</td></tr><tr class="hit"><td class="line">439</td><td class="hits">18</td><td class="source"> cb(err);</td></tr><tr><td class="line">440</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">441</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">442</td><td class="hits">2</td><td class="source"> cb();</td></tr><tr><td class="line">443</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">444</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">445</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">446</td><td class="hits"></td><td class="source"> // Build argument list</td></tr><tr><td class="line">447</td><td class="hits"></td><td class="source"> function(cb) {</td></tr><tr class="hit"><td class="line">448</td><td class="hits">20</td><td class="source"> var args;</td></tr><tr class="hit"><td class="line">449</td><td class="hits">20</td><td class="source"> try {</td></tr><tr class="hit"><td class="line">450</td><td class="hits">20</td><td class="source"> args = self._getArguments();</td></tr><tr><td class="line">451</td><td class="hits"></td><td class="source"> } catch(e) {</td></tr><tr class="miss"><td class="line">452</td><td class="hits">0</td><td class="source"> return cb(e);</td></tr><tr><td class="line">453</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">454</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">455</td><td class="hits">20</td><td class="source"> cb(null, args);</td></tr><tr><td class="line">456</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">457</td><td class="hits"></td><td class="source"> ], callback);</td></tr><tr><td class="line">458</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">459</td><td class="hits">21</td><td class="source"> if (!readMetadata) {</td></tr><tr><td class="line">460</td><td class="hits"></td><td class="source"> // Read metadata as soon as 'progress' listeners are added</td></tr><tr><td class="line">461</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">462</td><td class="hits">19</td><td class="source"> if (this.listeners('progress').length > 0) {</td></tr><tr><td class="line">463</td><td class="hits"></td><td class="source"> // Read metadata in parallel</td></tr><tr class="hit"><td class="line">464</td><td class="hits">1</td><td class="source"> runFfprobe(this);</td></tr><tr><td class="line">465</td><td class="hits"></td><td class="source"> } else {</td></tr><tr><td class="line">466</td><td class="hits"></td><td class="source"> // Read metadata as soon as the first 'progress' listener is added</td></tr><tr class="hit"><td class="line">467</td><td class="hits">18</td><td class="source"> this.once('newListener', function(event) {</td></tr><tr class="miss"><td class="line">468</td><td class="hits">0</td><td class="source"> if (event === 'progress') {</td></tr><tr class="miss"><td class="line">469</td><td class="hits">0</td><td class="source"> runFfprobe(this);</td></tr><tr><td class="line">470</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">471</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">472</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">473</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">474</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">475</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">476</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">477</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">478</td><td class="hits"></td><td class="source"> * Execute ffmpeg command and save output to a file</td></tr><tr><td class="line">479</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">480</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#save</td></tr><tr><td class="line">481</td><td class="hits"></td><td class="source"> * @category Processing</td></tr><tr><td class="line">482</td><td class="hits"></td><td class="source"> * @aliases saveToFile</td></tr><tr><td class="line">483</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">484</td><td class="hits"></td><td class="source"> * @param {String} output file path</td></tr><tr><td class="line">485</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">486</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">487</td><td class="hits">1</td><td class="source"> proto.saveToFile =</td></tr><tr><td class="line">488</td><td class="hits"></td><td class="source"> proto.save = function(output) {</td></tr><tr class="hit"><td class="line">489</td><td class="hits">16</td><td class="source"> _process(this, output);</td></tr><tr><td class="line">490</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">491</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">492</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">493</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">494</td><td class="hits"></td><td class="source"> * Execute ffmpeg command and save output to a stream</td></tr><tr><td class="line">495</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">496</td><td class="hits"></td><td class="source"> * If 'stream' is not specified, a PassThrough stream is created and returned.</td></tr><tr><td class="line">497</td><td class="hits"></td><td class="source"> * 'options' will be used when piping ffmpeg output to the output stream</td></tr><tr><td class="line">498</td><td class="hits"></td><td class="source"> * (@see http://nodejs.org/api/stream.html#stream_readable_pipe_destination_options)</td></tr><tr><td class="line">499</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">500</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#pipe</td></tr><tr><td class="line">501</td><td class="hits"></td><td class="source"> * @category Processing</td></tr><tr><td class="line">502</td><td class="hits"></td><td class="source"> * @aliases stream,writeToStream</td></tr><tr><td class="line">503</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">504</td><td class="hits"></td><td class="source"> * @param {stream.Writable} [stream] output stream</td></tr><tr><td class="line">505</td><td class="hits"></td><td class="source"> * @param {Object} [options={}] pipe options</td></tr><tr><td class="line">506</td><td class="hits"></td><td class="source"> * @return Output stream</td></tr><tr><td class="line">507</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">508</td><td class="hits">1</td><td class="source"> proto.writeToStream =</td></tr><tr><td class="line">509</td><td class="hits"></td><td class="source"> proto.pipe =</td></tr><tr><td class="line">510</td><td class="hits"></td><td class="source"> proto.stream = function(stream, options) {</td></tr><tr class="hit"><td class="line">511</td><td class="hits">3</td><td class="source"> if (stream && !('writable' in stream)) {</td></tr><tr class="hit"><td class="line">512</td><td class="hits">1</td><td class="source"> options = stream;</td></tr><tr class="hit"><td class="line">513</td><td class="hits">1</td><td class="source"> stream = undefined;</td></tr><tr><td class="line">514</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">515</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">516</td><td class="hits">3</td><td class="source"> if (!stream) {</td></tr><tr class="hit"><td class="line">517</td><td class="hits">1</td><td class="source"> if (process.version.match(/v0\.8\./)) {</td></tr><tr class="miss"><td class="line">518</td><td class="hits">0</td><td class="source"> throw new Error('PassThrough stream is not supported on node v0.8');</td></tr><tr><td class="line">519</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">520</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">521</td><td class="hits">1</td><td class="source"> stream = new PassThrough();</td></tr><tr><td class="line">522</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">523</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">524</td><td class="hits">3</td><td class="source"> _process(this, stream, options);</td></tr><tr class="hit"><td class="line">525</td><td class="hits">3</td><td class="source"> return stream;</td></tr><tr><td class="line">526</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">527</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">528</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">529</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">530</td><td class="hits"></td><td class="source"> * Merge (concatenate) inputs to a single file</td></tr><tr><td class="line">531</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">532</td><td class="hits"></td><td class="source"> * Warning: soon to be deprecated</td></tr><tr><td class="line">533</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">534</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#mergeToFile</td></tr><tr><td class="line">535</td><td class="hits"></td><td class="source"> * @category Processing</td></tr><tr><td class="line">536</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">537</td><td class="hits"></td><td class="source"> * @param {String} targetfile output file path</td></tr><tr><td class="line">538</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">539</td><td class="hits">1</td><td class="source"> proto.mergeToFile = function(targetfile) {</td></tr><tr class="hit"><td class="line">540</td><td class="hits">1</td><td class="source"> var outputfile = path.normalize(targetfile);</td></tr><tr class="hit"><td class="line">541</td><td class="hits">1</td><td class="source"> if(fs.existsSync(outputfile)){</td></tr><tr class="miss"><td class="line">542</td><td class="hits">0</td><td class="source"> return this.emit('error', new Error('Output file already exists, merge aborted'));</td></tr><tr><td class="line">543</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">544</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">545</td><td class="hits">1</td><td class="source"> var self = this;</td></tr><tr><td class="line">546</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">547</td><td class="hits"></td><td class="source"> // creates intermediate copies of each video.</td></tr><tr><td class="line">548</td><td class="hits"></td><td class="source"> function makeIntermediateFile(_mergeSource,_callback) {</td></tr><tr class="hit"><td class="line">549</td><td class="hits">3</td><td class="source"> var fname = _mergeSource + '.temp.mpg';</td></tr><tr class="hit"><td class="line">550</td><td class="hits">3</td><td class="source"> var args = self._output.get().concat(['-i', _mergeSource, '-qscale:v', 1, fname]);</td></tr><tr><td class="line">551</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">552</td><td class="hits">3</td><td class="source"> self._spawnFfmpeg(args, function(err) {</td></tr><tr class="hit"><td class="line">553</td><td class="hits">3</td><td class="source"> _callback(err, fname);</td></tr><tr><td class="line">554</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">555</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">556</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">557</td><td class="hits"></td><td class="source"> // concat all created intermediate copies</td></tr><tr><td class="line">558</td><td class="hits"></td><td class="source"> function concatIntermediates(target, intermediatesList, _callback) {</td></tr><tr class="hit"><td class="line">559</td><td class="hits">1</td><td class="source"> var fname = path.normalize(target) + '.temp.merged.mpg';</td></tr><tr><td class="line">560</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">561</td><td class="hits">1</td><td class="source"> var args = [</td></tr><tr><td class="line">562</td><td class="hits"></td><td class="source"> // avoid too many log messages from ffmpeg</td></tr><tr><td class="line">563</td><td class="hits"></td><td class="source"> '-loglevel', 'panic',</td></tr><tr><td class="line">564</td><td class="hits"></td><td class="source"> '-i', 'concat:' + intermediatesList.join('|'),</td></tr><tr><td class="line">565</td><td class="hits"></td><td class="source"> '-c', 'copy',</td></tr><tr><td class="line">566</td><td class="hits"></td><td class="source"> fname</td></tr><tr><td class="line">567</td><td class="hits"></td><td class="source"> ];</td></tr><tr><td class="line">568</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">569</td><td class="hits">1</td><td class="source"> self._spawnFfmpeg(args, {captureStdout:true,captureStderr:true}, function(err) {</td></tr><tr class="hit"><td class="line">570</td><td class="hits">1</td><td class="source"> _callback(err, fname);</td></tr><tr><td class="line">571</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">572</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">573</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">574</td><td class="hits"></td><td class="source"> function quantizeConcat(concatResult, numFiles, _callback) {</td></tr><tr class="hit"><td class="line">575</td><td class="hits">1</td><td class="source"> var args = [</td></tr><tr><td class="line">576</td><td class="hits"></td><td class="source"> '-i', concatResult,</td></tr><tr><td class="line">577</td><td class="hits"></td><td class="source"> '-qscale:v',numFiles,</td></tr><tr><td class="line">578</td><td class="hits"></td><td class="source"> targetfile</td></tr><tr><td class="line">579</td><td class="hits"></td><td class="source"> ];</td></tr><tr><td class="line">580</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">581</td><td class="hits">1</td><td class="source"> self._spawnFfmpeg(args, function(err) {</td></tr><tr class="hit"><td class="line">582</td><td class="hits">1</td><td class="source"> _callback(err);</td></tr><tr><td class="line">583</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">584</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">585</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">586</td><td class="hits"></td><td class="source"> function deleteIntermediateFiles(intermediates, callback) {</td></tr><tr class="hit"><td class="line">587</td><td class="hits">2</td><td class="source"> async.each(intermediates, function(item,cb){</td></tr><tr class="hit"><td class="line">588</td><td class="hits">8</td><td class="source"> fs.exists(item,function(exists){</td></tr><tr class="hit"><td class="line">589</td><td class="hits">8</td><td class="source"> if(exists){</td></tr><tr class="hit"><td class="line">590</td><td class="hits">4</td><td class="source"> fs.unlink(item ,cb);</td></tr><tr><td class="line">591</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">592</td><td class="hits"></td><td class="source"> else{</td></tr><tr class="hit"><td class="line">593</td><td class="hits">4</td><td class="source"> cb();</td></tr><tr><td class="line">594</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">595</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">596</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">597</td><td class="hits"></td><td class="source"> }, callback);</td></tr><tr><td class="line">598</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">599</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">600</td><td class="hits"></td><td class="source"> function makeProgress() {</td></tr><tr class="hit"><td class="line">601</td><td class="hits">5</td><td class="source"> progress.createdFiles = progress.createdFiles + 1;</td></tr><tr class="hit"><td class="line">602</td><td class="hits">5</td><td class="source"> progress.percent = progress.createdFiles / progress.totalFiles * 100;</td></tr><tr class="hit"><td class="line">603</td><td class="hits">5</td><td class="source"> self.emit('progress', progress);</td></tr><tr><td class="line">604</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">605</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">606</td><td class="hits">1</td><td class="source"> if (this._inputs.length < 2) {</td></tr><tr class="miss"><td class="line">607</td><td class="hits">0</td><td class="source"> return this.emit('error', new Error('No file added to be merged'));</td></tr><tr><td class="line">608</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">609</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">610</td><td class="hits">4</td><td class="source"> var mergeList = this._inputs.map(function(input) { return input.source; });</td></tr><tr><td class="line">611</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">612</td><td class="hits">1</td><td class="source"> var progress = {frames : 0,</td></tr><tr><td class="line">613</td><td class="hits"></td><td class="source"> currentFps: 0,</td></tr><tr><td class="line">614</td><td class="hits"></td><td class="source"> currentKbps: 0,</td></tr><tr><td class="line">615</td><td class="hits"></td><td class="source"> targetSize: 0,</td></tr><tr><td class="line">616</td><td class="hits"></td><td class="source"> timemark: 0,</td></tr><tr><td class="line">617</td><td class="hits"></td><td class="source"> percent: 0,</td></tr><tr><td class="line">618</td><td class="hits"></td><td class="source"> totalFiles: mergeList.length + 2,</td></tr><tr><td class="line">619</td><td class="hits"></td><td class="source"> createdFiles: 0};</td></tr><tr><td class="line">620</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">621</td><td class="hits">4</td><td class="source"> var toDelete = mergeList.map(function(name) { return name + '.temp.mpg'; });</td></tr><tr class="hit"><td class="line">622</td><td class="hits">1</td><td class="source"> toDelete.push(outputfile + '.temp.merged.mpg');</td></tr><tr class="hit"><td class="line">623</td><td class="hits">1</td><td class="source"> deleteIntermediateFiles(toDelete);</td></tr><tr><td class="line">624</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">625</td><td class="hits">1</td><td class="source"> var intermediateFiles = [];</td></tr><tr><td class="line">626</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">627</td><td class="hits">1</td><td class="source"> async.whilst(</td></tr><tr><td class="line">628</td><td class="hits"></td><td class="source"> function(){</td></tr><tr class="hit"><td class="line">629</td><td class="hits">4</td><td class="source"> return (mergeList.length !== 0);</td></tr><tr><td class="line">630</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">631</td><td class="hits"></td><td class="source"> function (callback){</td></tr><tr class="hit"><td class="line">632</td><td class="hits">3</td><td class="source"> makeIntermediateFile(mergeList.shift(), function(err, createdIntermediateFile) {</td></tr><tr class="hit"><td class="line">633</td><td class="hits">3</td><td class="source"> if(err) {</td></tr><tr class="miss"><td class="line">634</td><td class="hits">0</td><td class="source"> return callback(err);</td></tr><tr><td class="line">635</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">636</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">637</td><td class="hits">3</td><td class="source"> if(!createdIntermediateFile) {</td></tr><tr class="miss"><td class="line">638</td><td class="hits">0</td><td class="source"> return callback(new Error('Invalid intermediate file'));</td></tr><tr><td class="line">639</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">640</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">641</td><td class="hits">3</td><td class="source"> intermediateFiles.push(createdIntermediateFile);</td></tr><tr class="hit"><td class="line">642</td><td class="hits">3</td><td class="source"> makeProgress();</td></tr><tr class="hit"><td class="line">643</td><td class="hits">3</td><td class="source"> callback();</td></tr><tr><td class="line">644</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">645</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">646</td><td class="hits"></td><td class="source"> function(err) {</td></tr><tr class="hit"><td class="line">647</td><td class="hits">1</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">648</td><td class="hits">0</td><td class="source"> return self.emit('error', err);</td></tr><tr><td class="line">649</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">650</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">651</td><td class="hits">1</td><td class="source"> concatIntermediates(targetfile, intermediateFiles, function(err, concatResult) {</td></tr><tr class="hit"><td class="line">652</td><td class="hits">1</td><td class="source"> if(err) {</td></tr><tr class="miss"><td class="line">653</td><td class="hits">0</td><td class="source"> return self.emit('error', err);</td></tr><tr><td class="line">654</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">655</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">656</td><td class="hits">1</td><td class="source"> if(!concatResult) {</td></tr><tr class="miss"><td class="line">657</td><td class="hits">0</td><td class="source"> return self.emit('error', new Error('Invalid concat result file'));</td></tr><tr><td class="line">658</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">659</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">660</td><td class="hits">1</td><td class="source"> makeProgress();</td></tr><tr class="hit"><td class="line">661</td><td class="hits">1</td><td class="source"> quantizeConcat(concatResult, intermediateFiles.length, function() {</td></tr><tr class="hit"><td class="line">662</td><td class="hits">1</td><td class="source"> makeProgress();</td></tr><tr><td class="line">663</td><td class="hits"></td><td class="source"> // add concatResult to intermediates list so it can be deleted too.</td></tr><tr class="hit"><td class="line">664</td><td class="hits">1</td><td class="source"> intermediateFiles.push(concatResult);</td></tr><tr class="hit"><td class="line">665</td><td class="hits">1</td><td class="source"> deleteIntermediateFiles(intermediateFiles, function(err) {</td></tr><tr class="hit"><td class="line">666</td><td class="hits">1</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">667</td><td class="hits">0</td><td class="source"> self.emit('error', err);</td></tr><tr><td class="line">668</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">669</td><td class="hits">1</td><td class="source"> self.emit('end');</td></tr><tr><td class="line">670</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">671</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">672</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">673</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">674</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">675</td><td class="hits"></td><td class="source"> );</td></tr><tr><td class="line">676</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">677</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">678</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">679</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">680</td><td class="hits"></td><td class="source"> * Take screenshots</td></tr><tr><td class="line">681</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">682</td><td class="hits"></td><td class="source"> * The 'config' parameter may either be the number of screenshots to take or an object</td></tr><tr><td class="line">683</td><td class="hits"></td><td class="source"> * with the following keys:</td></tr><tr><td class="line">684</td><td class="hits"></td><td class="source"> * - 'count': screenshot count</td></tr><tr><td class="line">685</td><td class="hits"></td><td class="source"> * - 'timemarks': array of screenshot timestamps in seconds (defaults to taking screenshots at regular intervals)</td></tr><tr><td class="line">686</td><td class="hits"></td><td class="source"> * - 'filename': screenshot filename pattern (defaults to 'tn_%ss' or 'tn_%ss_%i' for multiple screenshots)</td></tr><tr><td class="line">687</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">688</td><td class="hits"></td><td class="source"> * The 'filename' option may contain tokens that will be replaced for each screenshot taken:</td></tr><tr><td class="line">689</td><td class="hits"></td><td class="source"> * - '%s': offset in seconds</td></tr><tr><td class="line">690</td><td class="hits"></td><td class="source"> * - '%w': screenshot width</td></tr><tr><td class="line">691</td><td class="hits"></td><td class="source"> * - '%h': screenshot height</td></tr><tr><td class="line">692</td><td class="hits"></td><td class="source"> * - '%r': screenshot resolution (eg. '320x240')</td></tr><tr><td class="line">693</td><td class="hits"></td><td class="source"> * - '%f': input filename</td></tr><tr><td class="line">694</td><td class="hits"></td><td class="source"> * - '%b': input basename (filename w/o extension)</td></tr><tr><td class="line">695</td><td class="hits"></td><td class="source"> * - '%i': index of screenshot in timemark array (can be zero-padded by using it like `%000i`)</td></tr><tr><td class="line">696</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">697</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#takeScreenshots</td></tr><tr><td class="line">698</td><td class="hits"></td><td class="source"> * @category Processing</td></tr><tr><td class="line">699</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">700</td><td class="hits"></td><td class="source"> * @param {Number|Object} config screenshot count or configuration object (see above)</td></tr><tr><td class="line">701</td><td class="hits"></td><td class="source"> * @param {String} [folder='.'] output directory</td></tr><tr><td class="line">702</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">703</td><td class="hits">1</td><td class="source"> proto.takeScreenshots = function(config, folder) {</td></tr><tr class="hit"><td class="line">704</td><td class="hits">2</td><td class="source"> var width, height;</td></tr><tr class="hit"><td class="line">705</td><td class="hits">2</td><td class="source"> var self = this;</td></tr><tr><td class="line">706</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">707</td><td class="hits"></td><td class="source"> function _computeSize(size) {</td></tr><tr><td class="line">708</td><td class="hits"></td><td class="source"> // Select video stream with biggest resolution</td></tr><tr class="hit"><td class="line">709</td><td class="hits">2</td><td class="source"> var vstream = self._ffprobeData.streams.reduce(function(max, stream) {</td></tr><tr class="hit"><td class="line">710</td><td class="hits">2</td><td class="source"> if (stream.codec_type !== 'video') return max;</td></tr><tr class="hit"><td class="line">711</td><td class="hits">2</td><td class="source"> return max.width * max.height < stream.width * stream.height ? stream : max;</td></tr><tr><td class="line">712</td><td class="hits"></td><td class="source"> }, { width: 0, height: 0 });</td></tr><tr><td class="line">713</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">714</td><td class="hits">2</td><td class="source"> var w = vstream.width;</td></tr><tr class="hit"><td class="line">715</td><td class="hits">2</td><td class="source"> var h = vstream.height;</td></tr><tr class="hit"><td class="line">716</td><td class="hits">2</td><td class="source"> var a = w / h;</td></tr><tr><td class="line">717</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">718</td><td class="hits">2</td><td class="source"> var fixedSize = size.match(/([0-9]+)x([0-9]+)/);</td></tr><tr class="hit"><td class="line">719</td><td class="hits">2</td><td class="source"> var fixedWidth = size.match(/([0-9]+)x\?/);</td></tr><tr class="hit"><td class="line">720</td><td class="hits">2</td><td class="source"> var fixedHeight = size.match(/\?x([0-9]+)/);</td></tr><tr class="hit"><td class="line">721</td><td class="hits">2</td><td class="source"> var percentRatio = size.match(/\b([0-9]{1,3})%/);</td></tr><tr><td class="line">722</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">723</td><td class="hits">2</td><td class="source"> if (fixedSize) {</td></tr><tr class="miss"><td class="line">724</td><td class="hits">0</td><td class="source"> width = Number(fixedSize[1]);</td></tr><tr class="miss"><td class="line">725</td><td class="hits">0</td><td class="source"> height = Number(fixedSize[2]);</td></tr><tr class="hit"><td class="line">726</td><td class="hits">2</td><td class="source"> } else if (fixedWidth) {</td></tr><tr class="hit"><td class="line">727</td><td class="hits">2</td><td class="source"> width = Number(fixedWidth[1]);</td></tr><tr class="hit"><td class="line">728</td><td class="hits">2</td><td class="source"> height = width / a;</td></tr><tr class="miss"><td class="line">729</td><td class="hits">0</td><td class="source"> } else if (fixedHeight) {</td></tr><tr class="miss"><td class="line">730</td><td class="hits">0</td><td class="source"> height = Number(fixedHeight[1]);</td></tr><tr class="miss"><td class="line">731</td><td class="hits">0</td><td class="source"> width = height * a;</td></tr><tr><td class="line">732</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="miss"><td class="line">733</td><td class="hits">0</td><td class="source"> var pc = Number(percentRatio[0]) / 100;</td></tr><tr class="miss"><td class="line">734</td><td class="hits">0</td><td class="source"> width = w * pc;</td></tr><tr class="miss"><td class="line">735</td><td class="hits">0</td><td class="source"> height = h * pc;</td></tr><tr><td class="line">736</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">737</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">738</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">739</td><td class="hits"></td><td class="source"> function _zeroPad(number, len) {</td></tr><tr class="hit"><td class="line">740</td><td class="hits">4</td><td class="source"> len = len-String(number).length+2;</td></tr><tr class="hit"><td class="line">741</td><td class="hits">4</td><td class="source"> return new Array(len<0?0:len).join('0')+number;</td></tr><tr><td class="line">742</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">743</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">744</td><td class="hits"></td><td class="source"> function _renderOutputName(j, offset) {</td></tr><tr class="hit"><td class="line">745</td><td class="hits">4</td><td class="source"> var result = filename;</td></tr><tr class="hit"><td class="line">746</td><td class="hits">4</td><td class="source"> if(/%0*i/.test(result)) {</td></tr><tr class="hit"><td class="line">747</td><td class="hits">4</td><td class="source"> var numlen = String(result.match(/%(0*)i/)[1]).length;</td></tr><tr class="hit"><td class="line">748</td><td class="hits">4</td><td class="source"> result = result.replace(/%0*i/, _zeroPad(j, numlen));</td></tr><tr><td class="line">749</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">750</td><td class="hits">4</td><td class="source"> result = result.replace('%s', offset);</td></tr><tr class="hit"><td class="line">751</td><td class="hits">4</td><td class="source"> result = result.replace('%w', width);</td></tr><tr class="hit"><td class="line">752</td><td class="hits">4</td><td class="source"> result = result.replace('%h', height);</td></tr><tr class="hit"><td class="line">753</td><td class="hits">4</td><td class="source"> result = result.replace('%r', width+'x'+height);</td></tr><tr class="hit"><td class="line">754</td><td class="hits">4</td><td class="source"> result = result.replace('%f', path.basename(inputfile));</td></tr><tr class="hit"><td class="line">755</td><td class="hits">4</td><td class="source"> result = result.replace('%b', path.basename(inputfile, path.extname(inputfile)));</td></tr><tr class="hit"><td class="line">756</td><td class="hits">4</td><td class="source"> return result;</td></tr><tr><td class="line">757</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">758</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">759</td><td class="hits"></td><td class="source"> function _screenShotInternal() {</td></tr><tr class="hit"><td class="line">760</td><td class="hits">2</td><td class="source"> self._prepare(function(err, args) {</td></tr><tr class="hit"><td class="line">761</td><td class="hits">2</td><td class="source"> if(err) {</td></tr><tr class="miss"><td class="line">762</td><td class="hits">0</td><td class="source"> return self.emit('error', err);</td></tr><tr><td class="line">763</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">764</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">765</td><td class="hits">2</td><td class="source"> _computeSize(self._sizeData.size);</td></tr><tr><td class="line">766</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">767</td><td class="hits">2</td><td class="source"> var duration = 0;</td></tr><tr class="hit"><td class="line">768</td><td class="hits">2</td><td class="source"> if (self._ffprobeData && self._ffprobeData.format && self._ffprobeData.format.duration) {</td></tr><tr class="hit"><td class="line">769</td><td class="hits">2</td><td class="source"> duration = Number(self._ffprobeData.format.duration);</td></tr><tr><td class="line">770</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">771</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">772</td><td class="hits">2</td><td class="source"> if (!duration) {</td></tr><tr class="miss"><td class="line">773</td><td class="hits">0</td><td class="source"> var errString = 'meta data contains no duration, aborting screenshot creation';</td></tr><tr class="miss"><td class="line">774</td><td class="hits">0</td><td class="source"> return self.emit('error', new Error(errString));</td></tr><tr><td class="line">775</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">776</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">777</td><td class="hits"></td><td class="source"> // check if all timemarks are inside duration</td></tr><tr class="hit"><td class="line">778</td><td class="hits">2</td><td class="source"> if (Array.isArray(timemarks)) {</td></tr><tr class="hit"><td class="line">779</td><td class="hits">2</td><td class="source"> for (var i = 0; i < timemarks.length; i++) {</td></tr><tr><td class="line">780</td><td class="hits"></td><td class="source"> /* convert percentage to seconds */</td></tr><tr class="hit"><td class="line">781</td><td class="hits">4</td><td class="source"> if( timemarks[i].indexOf('%') > 0 ) {</td></tr><tr class="miss"><td class="line">782</td><td class="hits">0</td><td class="source"> timemarks[i] = (parseInt(timemarks[i], 10) / 100) * duration;</td></tr><tr><td class="line">783</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">784</td><td class="hits">4</td><td class="source"> if (parseInt(timemarks[i], 10) > duration) {</td></tr><tr><td class="line">785</td><td class="hits"></td><td class="source"> // remove timemark from array</td></tr><tr class="miss"><td class="line">786</td><td class="hits">0</td><td class="source"> timemarks.splice(i, 1);</td></tr><tr class="miss"><td class="line">787</td><td class="hits">0</td><td class="source"> --i;</td></tr><tr><td class="line">788</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">789</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">790</td><td class="hits"></td><td class="source"> // if there are no more timemarks around, add one at end of the file</td></tr><tr class="hit"><td class="line">791</td><td class="hits">2</td><td class="source"> if (timemarks.length === 0) {</td></tr><tr class="miss"><td class="line">792</td><td class="hits">0</td><td class="source"> timemarks[0] = (duration * 0.9);</td></tr><tr><td class="line">793</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">794</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">795</td><td class="hits"></td><td class="source"> // get positions for screenshots (using duration of file minus 10% to remove fade-in/fade-out)</td></tr><tr class="hit"><td class="line">796</td><td class="hits">2</td><td class="source"> var secondOffset = (duration * 0.9) / screenshotcount;</td></tr><tr><td class="line">797</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">798</td><td class="hits"></td><td class="source"> // reset iterator</td></tr><tr class="hit"><td class="line">799</td><td class="hits">2</td><td class="source"> var j = 1;</td></tr><tr><td class="line">800</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">801</td><td class="hits">2</td><td class="source"> var filenames = [];</td></tr><tr><td class="line">802</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">803</td><td class="hits"></td><td class="source"> // use async helper function to generate all screenshots and</td></tr><tr><td class="line">804</td><td class="hits"></td><td class="source"> // fire callback just once after work is done</td></tr><tr class="hit"><td class="line">805</td><td class="hits">2</td><td class="source"> async.until(</td></tr><tr><td class="line">806</td><td class="hits"></td><td class="source"> function() {</td></tr><tr class="hit"><td class="line">807</td><td class="hits">6</td><td class="source"> return j > screenshotcount;</td></tr><tr><td class="line">808</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">809</td><td class="hits"></td><td class="source"> function(taskcallback) {</td></tr><tr class="hit"><td class="line">810</td><td class="hits">4</td><td class="source"> var offset;</td></tr><tr class="hit"><td class="line">811</td><td class="hits">4</td><td class="source"> if (Array.isArray(timemarks)) {</td></tr><tr><td class="line">812</td><td class="hits"></td><td class="source"> // get timemark for current iteration</td></tr><tr class="hit"><td class="line">813</td><td class="hits">4</td><td class="source"> offset = timemarks[(j - 1)];</td></tr><tr><td class="line">814</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="miss"><td class="line">815</td><td class="hits">0</td><td class="source"> offset = secondOffset * j;</td></tr><tr><td class="line">816</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">817</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">818</td><td class="hits">4</td><td class="source"> var fname = _renderOutputName(j, offset) + (fileextension ? fileextension : '.jpg');</td></tr><tr class="hit"><td class="line">819</td><td class="hits">4</td><td class="source"> var target = path.join(folder, fname);</td></tr><tr><td class="line">820</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">821</td><td class="hits"></td><td class="source"> // build screenshot command</td></tr><tr class="hit"><td class="line">822</td><td class="hits">4</td><td class="source"> var allArgs = [</td></tr><tr><td class="line">823</td><td class="hits"></td><td class="source"> '-ss', Math.floor(offset * 100) / 100</td></tr><tr><td class="line">824</td><td class="hits"></td><td class="source"> ]</td></tr><tr><td class="line">825</td><td class="hits"></td><td class="source"> .concat(args)</td></tr><tr><td class="line">826</td><td class="hits"></td><td class="source"> .concat([</td></tr><tr><td class="line">827</td><td class="hits"></td><td class="source"> '-vframes', '1',</td></tr><tr><td class="line">828</td><td class="hits"></td><td class="source"> '-an',</td></tr><tr><td class="line">829</td><td class="hits"></td><td class="source"> '-vcodec', 'mjpeg',</td></tr><tr><td class="line">830</td><td class="hits"></td><td class="source"> '-f', 'rawvideo',</td></tr><tr><td class="line">831</td><td class="hits"></td><td class="source"> '-y', target</td></tr><tr><td class="line">832</td><td class="hits"></td><td class="source"> ]);</td></tr><tr><td class="line">833</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">834</td><td class="hits">4</td><td class="source"> j++;</td></tr><tr><td class="line">835</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">836</td><td class="hits">4</td><td class="source"> self._spawnFfmpeg(allArgs, taskcallback);</td></tr><tr class="hit"><td class="line">837</td><td class="hits">4</td><td class="source"> filenames.push(fname);</td></tr><tr><td class="line">838</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">839</td><td class="hits"></td><td class="source"> function(err) {</td></tr><tr class="hit"><td class="line">840</td><td class="hits">2</td><td class="source"> if (err) {</td></tr><tr class="miss"><td class="line">841</td><td class="hits">0</td><td class="source"> self.emit('error', err);</td></tr><tr><td class="line">842</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">843</td><td class="hits">2</td><td class="source"> self.emit('end', filenames);</td></tr><tr><td class="line">844</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">845</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">846</td><td class="hits"></td><td class="source"> );</td></tr><tr><td class="line">847</td><td class="hits"></td><td class="source"> }, true);</td></tr><tr><td class="line">848</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">849</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">850</td><td class="hits">2</td><td class="source"> var timemarks, screenshotcount, filename, fileextension;</td></tr><tr class="hit"><td class="line">851</td><td class="hits">2</td><td class="source"> if (typeof config === 'object') {</td></tr><tr><td class="line">852</td><td class="hits"></td><td class="source"> // use json object as config</td></tr><tr class="hit"><td class="line">853</td><td class="hits">2</td><td class="source"> if (config.count) {</td></tr><tr class="hit"><td class="line">854</td><td class="hits">2</td><td class="source"> screenshotcount = config.count;</td></tr><tr><td class="line">855</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">856</td><td class="hits">2</td><td class="source"> if (config.timemarks) {</td></tr><tr class="hit"><td class="line">857</td><td class="hits">2</td><td class="source"> timemarks = config.timemarks;</td></tr><tr><td class="line">858</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">859</td><td class="hits">2</td><td class="source"> if (config.fileextension){</td></tr><tr class="miss"><td class="line">860</td><td class="hits">0</td><td class="source"> fileextension = config.fileextension;</td></tr><tr><td class="line">861</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">862</td><td class="hits"></td><td class="source"> } else {</td></tr><tr><td class="line">863</td><td class="hits"></td><td class="source"> // assume screenshot count as parameter</td></tr><tr class="miss"><td class="line">864</td><td class="hits">0</td><td class="source"> screenshotcount = config;</td></tr><tr class="miss"><td class="line">865</td><td class="hits">0</td><td class="source"> timemarks = null;</td></tr><tr><td class="line">866</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">867</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">868</td><td class="hits">2</td><td class="source"> if (!this._sizeData || !this._sizeData.size) {</td></tr><tr class="miss"><td class="line">869</td><td class="hits">0</td><td class="source"> throw new Error('Size must be specified');</td></tr><tr><td class="line">870</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">871</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">872</td><td class="hits">2</td><td class="source"> var inputfile = this._currentInput.source;</td></tr><tr><td class="line">873</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">874</td><td class="hits">2</td><td class="source"> filename = config.filename || 'tn_%ss';</td></tr><tr class="hit"><td class="line">875</td><td class="hits">2</td><td class="source"> if(!/%0*i/.test(filename) && Array.isArray(timemarks) && timemarks.length > 1 ) {</td></tr><tr><td class="line">876</td><td class="hits"></td><td class="source"> // if there are multiple timemarks but no %i in filename add one</td></tr><tr><td class="line">877</td><td class="hits"></td><td class="source"> // so we won't overwrite the same thumbnail with each timemark</td></tr><tr class="hit"><td class="line">878</td><td class="hits">1</td><td class="source"> filename += '_%i';</td></tr><tr><td class="line">879</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">880</td><td class="hits">2</td><td class="source"> folder = folder || '.';</td></tr><tr><td class="line">881</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">882</td><td class="hits"></td><td class="source"> // check target folder</td></tr><tr class="hit"><td class="line">883</td><td class="hits">2</td><td class="source"> fs.exists(folder, function(exists) {</td></tr><tr class="hit"><td class="line">884</td><td class="hits">2</td><td class="source"> if (!exists) {</td></tr><tr class="hit"><td class="line">885</td><td class="hits">2</td><td class="source"> fs.mkdir(folder, '0755', function(err) {</td></tr><tr class="hit"><td class="line">886</td><td class="hits">2</td><td class="source"> if (err !== null) {</td></tr><tr class="miss"><td class="line">887</td><td class="hits">0</td><td class="source"> self.emit('error', err);</td></tr><tr><td class="line">888</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">889</td><td class="hits">2</td><td class="source"> _screenShotInternal();</td></tr><tr><td class="line">890</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">891</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">892</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="miss"><td class="line">893</td><td class="hits">0</td><td class="source"> _screenShotInternal();</td></tr><tr><td class="line">894</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">895</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">896</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">897</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">898</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">899</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">900</td><td class="hits"></td><td class="source"> * Renice current and/or future ffmpeg processes</td></tr><tr><td class="line">901</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">902</td><td class="hits"></td><td class="source"> * Ignored on Windows platforms.</td></tr><tr><td class="line">903</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">904</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#renice</td></tr><tr><td class="line">905</td><td class="hits"></td><td class="source"> * @category Processing</td></tr><tr><td class="line">906</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">907</td><td class="hits"></td><td class="source"> * @param {Number} [niceness=0] niceness value between -20 (highest priority) and 20 (lowest priority)</td></tr><tr><td class="line">908</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">909</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">910</td><td class="hits">1</td><td class="source"> proto.renice = function(niceness) {</td></tr><tr class="hit"><td class="line">911</td><td class="hits">2</td><td class="source"> if (!utils.isWindows) {</td></tr><tr class="hit"><td class="line">912</td><td class="hits">2</td><td class="source"> niceness = niceness || 0;</td></tr><tr><td class="line">913</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">914</td><td class="hits">2</td><td class="source"> if (niceness < -20 || niceness > 20) {</td></tr><tr class="hit"><td class="line">915</td><td class="hits">1</td><td class="source"> this.logger.warn('Invalid niceness value: ' + niceness + ', must be between -20 and 20');</td></tr><tr><td class="line">916</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">917</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">918</td><td class="hits">2</td><td class="source"> niceness = Math.min(20, Math.max(-20, niceness));</td></tr><tr class="hit"><td class="line">919</td><td class="hits">2</td><td class="source"> this.options.niceness = niceness;</td></tr><tr><td class="line">920</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">921</td><td class="hits">2</td><td class="source"> if (this.ffmpegProc) {</td></tr><tr class="hit"><td class="line">922</td><td class="hits">1</td><td class="source"> var logger = this.logger;</td></tr><tr class="hit"><td class="line">923</td><td class="hits">1</td><td class="source"> var pid = this.ffmpegProc.pid;</td></tr><tr class="hit"><td class="line">924</td><td class="hits">1</td><td class="source"> var renice = spawn('renice', [niceness, '-p', pid]);</td></tr><tr><td class="line">925</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">926</td><td class="hits">1</td><td class="source"> renice.on('error', function(err) {</td></tr><tr class="miss"><td class="line">927</td><td class="hits">0</td><td class="source"> logger.warn('could not renice process ' + pid + ': ' + err.message);</td></tr><tr><td class="line">928</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">929</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">930</td><td class="hits">1</td><td class="source"> renice.on('exit', function(code, signal) {</td></tr><tr class="hit"><td class="line">931</td><td class="hits">1</td><td class="source"> if (code) {</td></tr><tr class="miss"><td class="line">932</td><td class="hits">0</td><td class="source"> logger.warn('could not renice process ' + pid + ': renice exited with ' + code);</td></tr><tr class="hit"><td class="line">933</td><td class="hits">1</td><td class="source"> } else if (signal) {</td></tr><tr class="miss"><td class="line">934</td><td class="hits">0</td><td class="source"> logger.warn('could not renice process ' + pid + ': renice was killed by signal ' + signal);</td></tr><tr><td class="line">935</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">936</td><td class="hits">1</td><td class="source"> logger.info('successfully reniced process ' + pid + ' to ' + niceness + ' niceness');</td></tr><tr><td class="line">937</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">938</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">939</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">940</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">941</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">942</td><td class="hits">2</td><td class="source"> return this;</td></tr><tr><td class="line">943</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">944</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">945</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">946</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">947</td><td class="hits"></td><td class="source"> * Kill current ffmpeg process, if any</td></tr><tr><td class="line">948</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">949</td><td class="hits"></td><td class="source"> * @method FfmpegCommand#kill</td></tr><tr><td class="line">950</td><td class="hits"></td><td class="source"> * @category Processing</td></tr><tr><td class="line">951</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">952</td><td class="hits"></td><td class="source"> * @param {String} [signal=SIGKILL] signal name</td></tr><tr><td class="line">953</td><td class="hits"></td><td class="source"> * @return FfmpegCommand</td></tr><tr><td class="line">954</td><td class="hits"></td><td class="source"> */</td></tr><tr class="hit"><td class="line">955</td><td class="hits">1</td><td class="source"> proto.kill = function(signal) {</td></tr><tr class="hit"><td class="line">956</td><td class="hits">3</td><td class="source"> if (!this.ffmpegProc) {</td></tr><tr class="miss"><td class="line">957</td><td class="hits">0</td><td class="source"> this.options.logger.warn('No running ffmpeg process, cannot send signal');</td></tr><tr><td class="line">958</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">959</td><td class="hits">3</td><td class="source"> this.ffmpegProc.kill(signal || 'SIGKILL');</td></tr><tr><td class="line">960</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">961</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">962</td><td class="hits">3</td><td class="source"> return this;</td></tr><tr><td class="line">963</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">964</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">965</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div><div class="file"><h2 id="lib/utils.js">lib/utils.js</h2><div id="stats" class="high"><div class="percentage">92%</div><div class="sloc">82</div><div class="hits">76</div><div class="misses">6</div></div><table id="source"><thead><tr><th>Line</th><th>Hits</th><th>Source</th></tr></thead><tbody><tr><td class="line">1</td><td class="hits"></td><td class="source">/*jshint node:true*/</td></tr><tr><td class="line">2</td><td class="hits"></td><td class="source">'use strict';</td></tr><tr><td class="line">3</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">4</td><td class="hits">1</td><td class="source">var exec = require('child_process').exec;</td></tr><tr class="hit"><td class="line">5</td><td class="hits">1</td><td class="source">var isWindows = require('os').platform().match(/win(32|64)/);</td></tr><tr><td class="line">6</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">7</td><td class="hits">1</td><td class="source">var whichCache = {};</td></tr><tr><td class="line">8</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">9</td><td class="hits"></td><td class="source">/**</td></tr><tr><td class="line">10</td><td class="hits"></td><td class="source"> * Parse progress line from ffmpeg stderr</td></tr><tr><td class="line">11</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">12</td><td class="hits"></td><td class="source"> * @param {String} line progress line</td></tr><tr><td class="line">13</td><td class="hits"></td><td class="source"> * @return progress object</td></tr><tr><td class="line">14</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">15</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">16</td><td class="hits"></td><td class="source">function parseProgressLine(line) {</td></tr><tr class="hit"><td class="line">17</td><td class="hits">26</td><td class="source"> var progress = {};</td></tr><tr><td class="line">18</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">19</td><td class="hits"></td><td class="source"> // Remove all spaces after = and trim</td></tr><tr class="hit"><td class="line">20</td><td class="hits">26</td><td class="source"> line = line.replace(/=\s+/g, '=').trim();</td></tr><tr class="hit"><td class="line">21</td><td class="hits">26</td><td class="source"> var progressParts = line.split(' ');</td></tr><tr><td class="line">22</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">23</td><td class="hits"></td><td class="source"> // Split every progress part by "=" to get key and value</td></tr><tr class="hit"><td class="line">24</td><td class="hits">26</td><td class="source"> for(var i = 0; i < progressParts.length; i++) {</td></tr><tr class="hit"><td class="line">25</td><td class="hits">110</td><td class="source"> var progressSplit = progressParts[i].split('=', 2);</td></tr><tr class="hit"><td class="line">26</td><td class="hits">110</td><td class="source"> var key = progressSplit[0];</td></tr><tr class="hit"><td class="line">27</td><td class="hits">110</td><td class="source"> var value = progressSplit[1];</td></tr><tr><td class="line">28</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">29</td><td class="hits"></td><td class="source"> // This is not a progress line</td></tr><tr class="hit"><td class="line">30</td><td class="hits">110</td><td class="source"> if(typeof value === 'undefined')</td></tr><tr class="hit"><td class="line">31</td><td class="hits">14</td><td class="source"> return null;</td></tr><tr><td class="line">32</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">33</td><td class="hits">96</td><td class="source"> progress[key] = value;</td></tr><tr><td class="line">34</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">35</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">36</td><td class="hits">12</td><td class="source"> return progress;</td></tr><tr><td class="line">37</td><td class="hits"></td><td class="source">}</td></tr><tr><td class="line">38</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">39</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">40</td><td class="hits">1</td><td class="source">var utils = module.exports = {</td></tr><tr><td class="line">41</td><td class="hits"></td><td class="source"> isWindows: isWindows,</td></tr><tr><td class="line">42</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">43</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">44</td><td class="hits"></td><td class="source"> * Create an argument list</td></tr><tr><td class="line">45</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">46</td><td class="hits"></td><td class="source"> * Returns a function that adds new arguments to the list.</td></tr><tr><td class="line">47</td><td class="hits"></td><td class="source"> * It also has the following methods:</td></tr><tr><td class="line">48</td><td class="hits"></td><td class="source"> * - clear() empties the argument list</td></tr><tr><td class="line">49</td><td class="hits"></td><td class="source"> * - get() returns the argument list</td></tr><tr><td class="line">50</td><td class="hits"></td><td class="source"> * - find(arg, count) finds 'arg' in the list and return the following 'count' items, or undefined if not found</td></tr><tr><td class="line">51</td><td class="hits"></td><td class="source"> * - remove(arg, count) remove 'arg' in the list as well as the following 'count' items</td></tr><tr><td class="line">52</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">53</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">54</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">55</td><td class="hits"></td><td class="source"> args: function() {</td></tr><tr class="hit"><td class="line">56</td><td class="hits">1434</td><td class="source"> var list = [];</td></tr><tr class="hit"><td class="line">57</td><td class="hits">1434</td><td class="source"> var argfunc = function() {</td></tr><tr class="hit"><td class="line">58</td><td class="hits">326</td><td class="source"> if (arguments.length === 1 && Array.isArray(arguments[0])) {</td></tr><tr class="hit"><td class="line">59</td><td class="hits">90</td><td class="source"> list = list.concat(arguments[0]);</td></tr><tr><td class="line">60</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">61</td><td class="hits">236</td><td class="source"> list = list.concat([].slice.call(arguments));</td></tr><tr><td class="line">62</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">63</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">64</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">65</td><td class="hits">1434</td><td class="source"> argfunc.clear = function() {</td></tr><tr class="hit"><td class="line">66</td><td class="hits">83</td><td class="source"> list = [];</td></tr><tr><td class="line">67</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">68</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">69</td><td class="hits">1434</td><td class="source"> argfunc.get = function() {</td></tr><tr class="hit"><td class="line">70</td><td class="hits">485</td><td class="source"> return list;</td></tr><tr><td class="line">71</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">72</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">73</td><td class="hits">1434</td><td class="source"> argfunc.find = function(arg, count) {</td></tr><tr class="hit"><td class="line">74</td><td class="hits">95</td><td class="source"> var index = list.indexOf(arg);</td></tr><tr class="hit"><td class="line">75</td><td class="hits">95</td><td class="source"> if (index !== -1) {</td></tr><tr class="hit"><td class="line">76</td><td class="hits">69</td><td class="source"> return list.slice(index + 1, index + 1 + (count || 0));</td></tr><tr><td class="line">77</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">78</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">79</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">80</td><td class="hits">1434</td><td class="source"> argfunc.remove = function(arg, count) {</td></tr><tr class="miss"><td class="line">81</td><td class="hits">0</td><td class="source"> var index = list.indexOf(arg);</td></tr><tr class="miss"><td class="line">82</td><td class="hits">0</td><td class="source"> if (index !== -1) {</td></tr><tr class="miss"><td class="line">83</td><td class="hits">0</td><td class="source"> list.splice(index, (count || 0) + 1);</td></tr><tr><td class="line">84</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">85</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">86</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">87</td><td class="hits">1434</td><td class="source"> return argfunc;</td></tr><tr><td class="line">88</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">89</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">90</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">91</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">92</td><td class="hits"></td><td class="source"> * Search for an executable</td></tr><tr><td class="line">93</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">94</td><td class="hits"></td><td class="source"> * Uses 'which' or 'where' depending on platform</td></tr><tr><td class="line">95</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">96</td><td class="hits"></td><td class="source"> * @param {String} name executable name</td></tr><tr><td class="line">97</td><td class="hits"></td><td class="source"> * @param {Function} callback callback with signature (err, path)</td></tr><tr><td class="line">98</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">99</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">100</td><td class="hits"></td><td class="source"> which: function(name, callback) {</td></tr><tr class="hit"><td class="line">101</td><td class="hits">9</td><td class="source"> if (name in whichCache) {</td></tr><tr class="hit"><td class="line">102</td><td class="hits">6</td><td class="source"> return callback(null, whichCache[name]);</td></tr><tr><td class="line">103</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">104</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">105</td><td class="hits">3</td><td class="source"> var cmd = 'which ' + name;</td></tr><tr class="hit"><td class="line">106</td><td class="hits">3</td><td class="source"> if (isWindows) {</td></tr><tr class="miss"><td class="line">107</td><td class="hits">0</td><td class="source"> cmd = 'where ' + name + '.exe';</td></tr><tr><td class="line">108</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">109</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">110</td><td class="hits">3</td><td class="source"> exec(cmd, function(err, stdout) {</td></tr><tr class="hit"><td class="line">111</td><td class="hits">3</td><td class="source"> if (err) {</td></tr><tr><td class="line">112</td><td class="hits"></td><td class="source"> // Treat errors as not found</td></tr><tr class="miss"><td class="line">113</td><td class="hits">0</td><td class="source"> callback(null, whichCache[name] = '');</td></tr><tr><td class="line">114</td><td class="hits"></td><td class="source"> } else {</td></tr><tr class="hit"><td class="line">115</td><td class="hits">3</td><td class="source"> callback(null, whichCache[name] = stdout.replace(/\n$/, ''));</td></tr><tr><td class="line">116</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">117</td><td class="hits"></td><td class="source"> });</td></tr><tr><td class="line">118</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">119</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">120</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">121</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">122</td><td class="hits"></td><td class="source"> * Convert a [[hh:]mm:]ss[.xxx] timemark into seconds</td></tr><tr><td class="line">123</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">124</td><td class="hits"></td><td class="source"> * @param {String} timemark timemark string</td></tr><tr><td class="line">125</td><td class="hits"></td><td class="source"> * @return Number</td></tr><tr><td class="line">126</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">127</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">128</td><td class="hits"></td><td class="source"> timemarkToSeconds: function(timemark) {</td></tr><tr class="hit"><td class="line">129</td><td class="hits">12</td><td class="source"> if(timemark.indexOf(':') === -1 && timemark.indexOf('.') >= 0)</td></tr><tr class="miss"><td class="line">130</td><td class="hits">0</td><td class="source"> return Number(timemark);</td></tr><tr><td class="line">131</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">132</td><td class="hits">12</td><td class="source"> var parts = timemark.split(':');</td></tr><tr><td class="line">133</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">134</td><td class="hits"></td><td class="source"> // add seconds</td></tr><tr class="hit"><td class="line">135</td><td class="hits">12</td><td class="source"> var secs = Number(parts.pop());</td></tr><tr><td class="line">136</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">137</td><td class="hits">12</td><td class="source"> if (parts.length) {</td></tr><tr><td class="line">138</td><td class="hits"></td><td class="source"> // add minutes</td></tr><tr class="hit"><td class="line">139</td><td class="hits">12</td><td class="source"> secs += Number(parts.pop()) * 60;</td></tr><tr><td class="line">140</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">141</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">142</td><td class="hits">12</td><td class="source"> if (parts.length) {</td></tr><tr><td class="line">143</td><td class="hits"></td><td class="source"> // add hours</td></tr><tr class="hit"><td class="line">144</td><td class="hits">12</td><td class="source"> secs += Number(parts.pop()) * 3600;</td></tr><tr><td class="line">145</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">146</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">147</td><td class="hits">12</td><td class="source"> return secs;</td></tr><tr><td class="line">148</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">149</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">150</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">151</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">152</td><td class="hits"></td><td class="source"> * Extract codec data from ffmpeg stderr and emit 'codecData' event if appropriate</td></tr><tr><td class="line">153</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">154</td><td class="hits"></td><td class="source"> * @param {FfmpegCommand} command event emitter</td></tr><tr><td class="line">155</td><td class="hits"></td><td class="source"> * @param {String} stderr ffmpeg stderr output</td></tr><tr><td class="line">156</td><td class="hits"></td><td class="source"> * @private</td></tr><tr><td class="line">157</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">158</td><td class="hits"></td><td class="source"> extractCodecData: function(command, stderr) {</td></tr><tr class="hit"><td class="line">159</td><td class="hits">11</td><td class="source"> var format= /Input #[0-9]+, ([^ ]+),/.exec(stderr);</td></tr><tr class="hit"><td class="line">160</td><td class="hits">11</td><td class="source"> var dur = /Duration\: ([^,]+)/.exec(stderr);</td></tr><tr class="hit"><td class="line">161</td><td class="hits">11</td><td class="source"> var audio = /Audio\: (.*)/.exec(stderr);</td></tr><tr class="hit"><td class="line">162</td><td class="hits">11</td><td class="source"> var video = /Video\: (.*)/.exec(stderr);</td></tr><tr class="hit"><td class="line">163</td><td class="hits">11</td><td class="source"> var codecObject = { format: '', audio: '', video: '', duration: '' };</td></tr><tr><td class="line">164</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">165</td><td class="hits">11</td><td class="source"> if (format && format.length > 1) {</td></tr><tr class="hit"><td class="line">166</td><td class="hits">8</td><td class="source"> codecObject.format = format[1];</td></tr><tr><td class="line">167</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">168</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">169</td><td class="hits">11</td><td class="source"> if (dur && dur.length > 1) {</td></tr><tr class="hit"><td class="line">170</td><td class="hits">8</td><td class="source"> codecObject.duration = dur[1];</td></tr><tr><td class="line">171</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">172</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">173</td><td class="hits">11</td><td class="source"> if (audio && audio.length > 1) {</td></tr><tr class="hit"><td class="line">174</td><td class="hits">7</td><td class="source"> audio = audio[1].split(', ');</td></tr><tr class="hit"><td class="line">175</td><td class="hits">7</td><td class="source"> codecObject.audio = audio[0];</td></tr><tr class="hit"><td class="line">176</td><td class="hits">7</td><td class="source"> codecObject.audio_details = audio;</td></tr><tr><td class="line">177</td><td class="hits"></td><td class="source"> }</td></tr><tr class="hit"><td class="line">178</td><td class="hits">11</td><td class="source"> if (video && video.length > 1) {</td></tr><tr class="hit"><td class="line">179</td><td class="hits">7</td><td class="source"> video = video[1].split(', ');</td></tr><tr class="hit"><td class="line">180</td><td class="hits">7</td><td class="source"> codecObject.video = video[0];</td></tr><tr class="hit"><td class="line">181</td><td class="hits">7</td><td class="source"> codecObject.video_details = video;</td></tr><tr><td class="line">182</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">183</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">184</td><td class="hits">11</td><td class="source"> var codecInfoPassed = /Press (\[q\]|ctrl-c) to stop/.test(stderr);</td></tr><tr class="hit"><td class="line">185</td><td class="hits">11</td><td class="source"> if (codecInfoPassed) {</td></tr><tr class="hit"><td class="line">186</td><td class="hits">1</td><td class="source"> command.emit('codecData', codecObject);</td></tr><tr class="hit"><td class="line">187</td><td class="hits">1</td><td class="source"> command._codecDataSent = true;</td></tr><tr><td class="line">188</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">189</td><td class="hits"></td><td class="source"> },</td></tr><tr><td class="line">190</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">191</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">192</td><td class="hits"></td><td class="source"> /**</td></tr><tr><td class="line">193</td><td class="hits"></td><td class="source"> * Extract progress data from ffmpeg stderr and emit 'progress' event if appropriate</td></tr><tr><td class="line">194</td><td class="hits"></td><td class="source"> *</td></tr><tr><td class="line">195</td><td class="hits"></td><td class="source"> * @param {FfmpegCommand} command event emitter</td></tr><tr><td class="line">196</td><td class="hits"></td><td class="source"> * @param {Number} [duration=0] expected output duration in seconds</td></tr><tr><td class="line">197</td><td class="hits"></td><td class="source"> */</td></tr><tr><td class="line">198</td><td class="hits"></td><td class="source"> extractProgress: function(command, stderr, duration) {</td></tr><tr class="hit"><td class="line">199</td><td class="hits">26</td><td class="source"> var lines = stderr.split(/\r\n|\r|\n/g);</td></tr><tr class="hit"><td class="line">200</td><td class="hits">26</td><td class="source"> var lastline = lines[lines.length - 2];</td></tr><tr class="hit"><td class="line">201</td><td class="hits">26</td><td class="source"> var progress;</td></tr><tr><td class="line">202</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">203</td><td class="hits">26</td><td class="source"> if (lastline) {</td></tr><tr class="hit"><td class="line">204</td><td class="hits">26</td><td class="source"> progress = parseProgressLine(lastline);</td></tr><tr><td class="line">205</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">206</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">207</td><td class="hits">26</td><td class="source"> if (progress) {</td></tr><tr><td class="line">208</td><td class="hits"></td><td class="source"> // build progress report object</td></tr><tr class="hit"><td class="line">209</td><td class="hits">12</td><td class="source"> var ret = {</td></tr><tr><td class="line">210</td><td class="hits"></td><td class="source"> frames: parseInt(progress.frame, 10),</td></tr><tr><td class="line">211</td><td class="hits"></td><td class="source"> currentFps: parseInt(progress.fps, 10),</td></tr><tr><td class="line">212</td><td class="hits"></td><td class="source"> currentKbps: parseFloat(progress.bitrate.replace('kbits/s', '')),</td></tr><tr><td class="line">213</td><td class="hits"></td><td class="source"> targetSize: parseInt(progress.size, 10),</td></tr><tr><td class="line">214</td><td class="hits"></td><td class="source"> timemark: progress.time</td></tr><tr><td class="line">215</td><td class="hits"></td><td class="source"> };</td></tr><tr><td class="line">216</td><td class="hits"></td><td class="source"> </td></tr><tr><td class="line">217</td><td class="hits"></td><td class="source"> // calculate percent progress using duration</td></tr><tr class="hit"><td class="line">218</td><td class="hits">12</td><td class="source"> if (duration && duration > 0) {</td></tr><tr class="hit"><td class="line">219</td><td class="hits">12</td><td class="source"> ret.percent = (utils.timemarkToSeconds(ret.timemark) / duration) * 100;</td></tr><tr><td class="line">220</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">221</td><td class="hits"></td><td class="source"> </td></tr><tr class="hit"><td class="line">222</td><td class="hits">12</td><td class="source"> command.emit('progress', ret);</td></tr><tr><td class="line">223</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">224</td><td class="hits"></td><td class="source"> }</td></tr><tr><td class="line">225</td><td class="hits"></td><td class="source">};</td></tr><tr><td class="line">226</td><td class="hits"></td><td class="source"> </td></tr></tbody></table></div></div></div></body></html>make[1]: quittant le répertoire « /home/niko/dev/forks/node-fluent-ffmpeg »