Flavy::sampleRate()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 7
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
1
<?php namespace Folour\Flavy;
2
3
/**
4
 *
5
 * FFmpeg layer for Laravel 5.2
6
 * This is a fully reworked fork of http://github.com/rafasamp/sonus package.
7
 *
8
 * @author Vadim Bova <[email protected]>
9
 * @link   http://github.com/folour | http://vk.com/folour
10
 *
11
 */
12
13
use \File;
14
use \Folour\Flavy\Extensions\Base;
15
use \Folour\Flavy\Exceptions\NotWritableException;
16
use \Folour\Flavy\Exceptions\FileNotFoundException;
17
18
class Flavy extends Base
19
{
20
    /**
21
     * Flavy version
22
     */
23
    const VERSION = '1.0.2';
24
25
    /**
26
     *
27
     * Array of command parameters from builder
28
     *
29
     * @var array
30
     */
31
    protected $parameters = [];
32
33
    /**
34
     *
35
     * Output file path
36
     *
37
     * @var string
38
     */
39
    protected $outputPath;
40
41
    /**
42
     *
43
     * Log path
44
     *
45
     * @var string
46
     */
47
    protected $logPath;
48
49
    /**
50
     *
51
     * Array of possible methods for execute
52
     *
53
     * @var array
54
     */
55
    private $nextContext = 'input';
56
57
    /**
58
     *
59
     * Flavy constructor.
60
     *
61
     * @param array $config
62
     */
63
    public function __construct(array $config)
64
    {
65
        parent::__construct($config);
66
    }
67
68
    /**
69
     *
70
     * Returns array (for json format) or string (for other formats) with file information
71
     *
72
     * @param string $file File path
73
     * @param string $format output format, supported json, xml and csv
74
     * @param bool   $decode decode json to array
75
     *
76
     *
77
     * @return array|string
78
     * @throws FileNotFoundException
79
     */
80
    public function info($file, $format = 'json', $decode = true)
81
    {
82
        $this->isPossible('input');
83
        if(!File::exists($file)) {
84
            throw new FileNotFoundException('The input file "'.$file.'" not exists!');
85
        }
86
87
        $format = in_array($format, ['json', 'xml', 'csv']) ? $format : 'json';
88
        $data = $this->runCmd('get_file_info', [$this->config['ffprobe_path'], $format, $file]);
89
        if($format == 'json' && $decode === true) {
90
            return json_decode($data, true);
91
        }
92
93
        return $data;
94
95
    }
96
97
    /**
98
     *
99
     * Create thumbnails from video
100
     *
101
     * @param string $file input file
102
     * @param string $outputPath output file path template
103
     * @param int $count thumbnails count
104
     * @param int|null $interval frames interval in seconds
105
     *
106
     * @return bool|string
107
     * @throws FileNotFoundException
108
     * @throws NotWritableException
109
     */
110
    public function thumbnail($file, $outputPath, $count = 1, $interval = null)
111
    {
112
        $this->isPossible('input');
113
        if(!File::exists($file)) {
114
            throw new FileNotFoundException('The input file "'.$file.'" not exists!');
115
        }
116
        if(!File::isWritable(dirname($outputPath))) {
117
            throw new NotWritableException('The output path "'.$outputPath.'" is not writable!');
118
        }
119
120
        if($interval == null) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $interval of type integer|null against null; this is ambiguous if the integer can be zero. Consider using a strict comparison === instead.
Loading history...
121
            $interval = 10;
122
            $info = $this->info($file);
123
            if(is_array($info)) {
124
                $duration = $this->timestamp(explode('.', $info['format']['duration'])[0]);
125
126
                $interval = round($duration / $count);
127
            }
128
        }
129
130
        return $this->runCmd('get_thumbnails', [
131
            $this->config['ffmpeg_path'], $file, $interval, $count, $outputPath
132
        ]);
133
    }
134
135
    /**
136
     *
137
     * Set input file
138
     *
139
     * @param $file
140
     * @return $this
141
     * @throws FileNotFoundException
142
     */
143
    public function from($file)
144
    {
145
        $this->isPossible('input');
146
        if(!File::exists($file)) {
147
            throw new FileNotFoundException('The input file "'.$file.'" not exists!');
148
        }
149
150
        $this->parameters[] = sprintf('%s -i "%s"', $this->config['ffmpeg_path'], $file);
151
        $this->nextContext = 'output';
0 ignored issues
show
Documentation Bug introduced by
It seems like 'output' of type string is incompatible with the declared type array of property $nextContext.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
152
153
        return $this;
154
    }
155
156
    /**
157
     *
158
     * Set output file
159
     *
160
     * @param string $outputPath
161
     *
162
     * @return $this
163
     * @throws NotWritableException
164
     */
165
    public function to($outputPath)
166
    {
167
        $this->isPossible('output');
168
        if(!File::isWritable(dirname($outputPath))) {
169
            throw new NotWritableException('The output path "'.$outputPath.'" is not writable!');
170
        }
171
172
        $this->outputPath = $outputPath;
173
        $this->nextContext = 'run_or_param';
0 ignored issues
show
Documentation Bug introduced by
It seems like 'run_or_param' of type string is incompatible with the declared type array of property $nextContext.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
174
175
        return $this;
176
    }
177
178
    /**
179
     *
180
     * Set audio codec
181
     *
182
     * @param string $codec
183
     * @return $this
184
     */
185
    public function aCodec($codec)
186
    {
187
        $this->isPossible('run_or_param');
188
        $this->parameters[] = sprintf('-acodec %s', $codec);
189
190
        return $this;
191
    }
192
193
    /**
194
     *
195
     * Set video codec
196
     *
197
     * @param string $codec
198
     * @return $this
199
     */
200
    public function vCodec($codec)
201
    {
202
        $this->isPossible('run_or_param');
203
204
        $this->parameters[] = sprintf('-vcodec %s', $codec);
205
206
        return $this;
207
    }
208
209
    /**
210
     *
211
     * Set audio bitrate
212
     *
213
     * @param int $bitrate
214
     * @return $this
215
     */
216
    public function aBitrate($bitrate)
217
    {
218
        $this->isPossible('run_or_param');
219
        $this->parameters[] = sprintf('-b:a %dk', $bitrate);
220
221
        return $this;
222
    }
223
224
    /**
225
     *
226
     * Set video bitrate
227
     *
228
     * @param int $bitrate
229
     * @return $this
230
     */
231
    public function vBitrate($bitrate)
232
    {
233
        $this->isPossible('run_or_param');
234
        $this->parameters[] = sprintf('-b:v %dk', $bitrate);
235
236
        return $this;
237
    }
238
239
    /**
240
     *
241
     * Set audio channels
242
     *
243
     * @param int $channels
244
     * @return $this
245
     */
246
    public function channels($channels)
247
    {
248
        $this->isPossible('run_or_param');
249
        $this->parameters[] = sprintf('-ac %d', $channels);
250
251
        return $this;
252
    }
253
254
    /**
255
     *
256
     * Set audio sample rate
257
     *
258
     * @param int $rate
259
     * @return $this
260
     */
261
    public function sampleRate($rate)
262
    {
263
        $this->isPossible('run_or_param');
264
        $this->parameters[] = sprintf('-ar %d', $rate);
265
266
        return $this;
267
    }
268
269
    /**
270
     *
271
     * Set video frame rate
272
     *
273
     * @param int $rate
274
     * @return $this
275
     */
276
    public function frameRate($rate)
277
    {
278
        $this->isPossible('run_or_param');
279
        $this->parameters[] = sprintf('-r %d', $rate);
280
281
        return $this;
282
    }
283
284
    /**
285
     *
286
     * Overwrite output file
287
     *
288
     * @return $this
289
     */
290
    public function overwrite()
291
    {
292
        $this->isPossible('run_or_param');
293
        $this->parameters[] = '-y';
294
295
        return $this;
296
    }
297
298
    public function logTo($logPath)
299
    {
300
        $this->isPossible('run_or_param');
301
        $this->logPath = $logPath;
302
303
        return $this;
304
    }
305
306
    /**
307
     *
308
     * Run a conversion process
309
     *
310
     * @throws Exceptions\CmdException
311
     */
312
    public function run()
313
    {
314
        $this->parameters[] = sprintf('"%s"', $this->outputPath);
315
        if($this->logPath !== null) {
316
            $this->parameters[] = sprintf('>"%s" 2>&1', $this->logPath);
317
        }
318
319
        $command = implode(' ', $this->parameters);
320
321
        $this->parameters = [];
322
        $this->nextContext = 'input';
0 ignored issues
show
Documentation Bug introduced by
It seems like 'input' of type string is incompatible with the declared type array of property $nextContext.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
323
        $this->logPath = $this->outputPath = null;
324
325
        $this->runCmd($command);
326
    }
327
328
    /**
329
     * @param string $context context name
330
     *
331
     * @return bool
332
     * @throws \BadMethodCallException
333
     */
334
    private function isPossible($context)
335
    {
336
        if($this->nextContext != $context) {
337
            throw new \BadMethodCallException('This method is not possible on this context');
338
        }
339
340
        return true;
341
    }
342
}
343