Failed Conditions
Push — master ( c58e29...ead145 )
by Sébastien
03:32
created

FFMpegAdapter   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 178
Duplicated Lines 0 %

Test Coverage

Coverage 87.67%

Importance

Changes 0
Metric Value
wmc 17
eloc 97
dl 0
loc 178
ccs 64
cts 73
cp 0.8767
rs 10
c 0
b 0
f 0

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
B getMappedConversionParams() 0 35 9
A getCliCommand() 0 27 6
A getParamsOptions() 0 84 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Soluble\MediaTools\Video\Converter;
6
7
use Soluble\MediaTools\Config\FFMpegConfig;
8
use Soluble\MediaTools\Exception\InvalidArgumentException;
9
use Soluble\MediaTools\Exception\UnsupportedParamException;
10
use Soluble\MediaTools\Exception\UnsupportedParamValueException;
11
use Soluble\MediaTools\Util\PlatformNullFile;
12
use Soluble\MediaTools\Video\ConversionParamsInterface;
13
use Soluble\MediaTools\Video\Filter\Type\FFMpegVideoFilterInterface;
14
15
class FFMpegAdapter implements AdapterInterface
16
{
17
    /** @var FFMpegConfig */
18
    protected $ffmpegConfig;
19
20 13
    public function __construct(FFMpegConfig $ffmpegConfig)
21
    {
22 13
        $this->ffmpegConfig = $ffmpegConfig;
23 13
    }
24
25
    /**
26
     * @return array<string, array<string, string>>
27
     */
28 10
    public function getParamsOptions(): array
29
    {
30
        return [
31 10
            ConversionParamsInterface::PARAM_OUTPUT_FORMAT => [
32
                'cli_pattern' => '-f %s',
33
            ],
34
35 10
            ConversionParamsInterface::PARAM_VIDEO_CODEC => [
36
                'cli_pattern' => '-c:v %s',
37
            ],
38 10
            ConversionParamsInterface::PARAM_VIDEO_BITRATE => [
39
                'cli_pattern' => '-b:v %s',
40
            ],
41 10
            ConversionParamsInterface::PARAM_VIDEO_MIN_BITRATE => [
42
                'cli_pattern' => '-minrate %s',
43
            ],
44 10
            ConversionParamsInterface::PARAM_VIDEO_MAX_BITRATE => [
45
                'cli_pattern' => '-maxrate %s',
46
            ],
47
48 10
            ConversionParamsInterface::PARAM_AUDIO_CODEC => [
49
                'cli_pattern' => '-c:a %s',
50
            ],
51 10
            ConversionParamsInterface::PARAM_AUDIO_BITRATE => [
52
                'cli_pattern' => '-b:a %s',
53
            ],
54 10
            ConversionParamsInterface::PARAM_PIX_FMT => [
55
                'cli_pattern' => '-pix_fmt %s',
56
            ],
57 10
            ConversionParamsInterface::PARAM_PRESET => [
58
                'cli_pattern' => '-preset %s',
59
            ],
60 10
            ConversionParamsInterface::PARAM_SPEED => [
61
                'cli_pattern' => '-speed %d',
62
            ],
63 10
            ConversionParamsInterface::PARAM_THREADS => [
64
                'cli_pattern' => '-threads %d',
65
            ],
66 10
            ConversionParamsInterface::PARAM_KEYFRAME_SPACING => [
67
                'cli_pattern' => '-g %d',
68
            ],
69 10
            ConversionParamsInterface::PARAM_QUALITY => [
70
                'cli_pattern' => '-quality %s',
71
            ],
72
73 10
            ConversionParamsInterface::PARAM_VIDEO_QUALITY_SCALE => [
74
                'cli_pattern' => '-qscale:v %d',
75
            ],
76
77 10
            ConversionParamsInterface::PARAM_CRF => [
78
                'cli_pattern' => '-crf %d',
79
            ],
80 10
            ConversionParamsInterface::PARAM_STREAMABLE => [
81
                'cli_pattern' => '-movflags +faststart',
82
            ],
83
84 10
            ConversionParamsInterface::PARAM_FRAME_PARALLEL => [
85
                'cli_pattern' => '-frame-parallel %s',
86
            ],
87 10
            ConversionParamsInterface::PARAM_TILE_COLUMNS => [
88
                'cli_pattern' => '-tile-columns %s',
89
            ],
90 10
            ConversionParamsInterface::PARAM_TUNE => [
91
                'cli_pattern' => '-tune %s',
92
            ],
93 10
            ConversionParamsInterface::PARAM_VIDEO_FILTER => [
94
                'cli_pattern' => '-vf %s',
95
            ],
96 10
            ConversionParamsInterface::PARAM_OVERWRITE => [
97
                'cli_pattern' => '-y',
98
            ],
99 10
            ConversionParamsInterface::PARAM_VIDEO_FRAMES => [
100
                'cli_pattern' => '-frames:v %d',
101
            ],
102 10
            ConversionParamsInterface::PARAM_NOAUDIO => [
103
                'cli_pattern' => '-an',
104
            ],
105
106 10
            ConversionParamsInterface::PARAM_SEEK_START => [
107
                'cli_pattern' => '-ss %s',
108
            ],
109
110 10
            ConversionParamsInterface::PARAM_SEEK_END => [
111
                'cli_pattern' => '-to %s',
112
            ],
113
        ];
114
    }
115
116
    /**
117
     * @return array<string, string>
118
     *
119
     * @throws UnsupportedParamException
120
     * @throws UnsupportedParamValueException
121
     */
122 10
    public function getMappedConversionParams(ConversionParamsInterface $conversionParams): array
123
    {
124 10
        $args             = [];
125 10
        $supportedOptions = $this->getParamsOptions();
126
127 10
        foreach ($conversionParams->toArray() as $paramName => $value) {
128 10
            if (!array_key_exists($paramName, $supportedOptions)) {
129
                throw new UnsupportedParamException(
130
                    sprintf(
131
                        'FFMpegAdapter does not support param \'%s\'',
132
                        $paramName
133
                    )
134
                );
135
            }
136 10
            $ffmpeg_pattern = $supportedOptions[$paramName]['cli_pattern'];
137 10
            if (is_bool($value)) {
138 3
                $args[$paramName] = $ffmpeg_pattern;
139 10
            } elseif ($value instanceof FFMpegCLIValueInterface) {
140 7
                $args[$paramName] = sprintf($ffmpeg_pattern, $value->getFFmpegCLIValue());
141 8
            } elseif ($value instanceof FFMpegVideoFilterInterface) {
142
                $args[$paramName] = sprintf($ffmpeg_pattern, $value->getFFmpegCLIValue());
143 8
            } elseif (is_string($value) || is_int($value)) {
144 7
                $args[$paramName] = sprintf($ffmpeg_pattern, $value);
145
            } else {
146 1
                throw new UnsupportedParamValueException(
147 1
                    sprintf(
148 1
                        'Param \'%s\' has an unsupported type: \'%s\'',
149 1
                        $paramName,
150 10
                        is_object($value) ? get_class($value) : gettype($value)
151
                    )
152
                );
153
            }
154
        }
155
156 9
        return $args;
157
    }
158
159
    /**
160
     * @param array<int|string, string>    $arguments
161
     * @param string|null                  $inputFile  if <null> will not prepend '-i inputFile' in args
162
     * @param null|string|PlatformNullFile $outputFile
163
     *
164
     * @throws InvalidArgumentException
165
     */
166 6
    public function getCliCommand(array $arguments, ?string $inputFile, $outputFile = null): string
167
    {
168 6
        $inputArg = ($inputFile !== null && $inputFile !== '')
169 6
                        ? sprintf('-i %s', escapeshellarg($inputFile))
170 6
                        : '';
171
172 6
        $outputArg = '';
173 6
        if ($outputFile instanceof PlatformNullFile) {
174 1
            $outputArg = $outputFile->getNullFile();
175 5
        } elseif (is_string($outputFile)) {
176 5
            $outputArg = sprintf('%s', escapeshellarg($outputFile));
177
        } elseif ($outputFile !== null) {
0 ignored issues
show
introduced by
The condition $outputFile !== null is always false.
Loading history...
178
            throw new InvalidArgumentException(sprintf(
179
                'Output file must be either a non empty string, null or PlatformNullFile (type %s)',
180
                gettype($outputFile)
181
            ));
182
        }
183
184 6
        $ffmpegCmd = trim(sprintf(
185 6
            '%s %s %s %s',
186 6
            $this->ffmpegConfig->getBinary(),
187 6
            $inputArg,
188 6
            implode(' ', $arguments),
189 6
            $outputArg
190
        ));
191
192 6
        return $ffmpegCmd;
193
    }
194
}
195