Passed
Push — master ( 1e8bfe...85c284 )
by Sébastien
03:02
created

VideoConversionService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Soluble\MediaTools;
6
7
use Soluble\MediaTools\Config\FFMpegConfig;
8
use Soluble\MediaTools\Exception\FileNotFoundException;
9
use Soluble\MediaTools\Exception\ProcessConversionException;
10
use Soluble\MediaTools\Util\Assert\PathAssertionsTrait;
11
use Soluble\MediaTools\Video\ConversionParamsInterface;
12
use Soluble\MediaTools\Video\ConversionServiceInterface;
13
use Symfony\Component\Process\Exception as ProcessException;
14
use Symfony\Component\Process\Process;
15
16
class VideoConversionService implements ConversionServiceInterface
17
{
18
    use PathAssertionsTrait;
19
20
    /** @var FFMpegConfig */
21
    protected $ffmpegConfig;
22
23 5
    public function __construct(FFMpegConfig $ffmpegConfig)
24
    {
25 5
        $this->ffmpegConfig = $ffmpegConfig;
26 5
        $this->ffmpegConfig->getProcess()->ensureBinaryExists();
27 5
    }
28
29
    /**
30
     * Return ready-to-run symfony process object that you can use
31
     * to `run()` or `start()` programmatically. Useful if you want to make
32
     * things async...
33
     *
34
     * @see https://symfony.com/doc/current/components/process.html
35
     *
36
     * @throws FileNotFoundException when inputFile does not exists
37
     */
38 5
    public function getConversionProcess(string $inputFile, string $outputFile, VideoConversionParams $convertParams): Process
39
    {
40 5
        $this->ensureFileExists($inputFile);
41
42 4
        $process = $this->ffmpegConfig->getProcess();
43
44 4
        if (!$convertParams->hasOption(ConversionParamsInterface::PARAM_THREADS) && $this->ffmpegConfig->getThreads() !== null) {
45
            $convertParams = $convertParams->withThreads($this->ffmpegConfig->getThreads());
46
        }
47
48 4
        $ffmpegCmd = $process->buildCommand(
49 4
            array_merge(
50
                [
51 4
                    sprintf('-i %s', escapeshellarg($inputFile)), // input filename
52
                ],
53 4
                $convertParams->getFFMpegArguments(),
54
                [
55 4
                    '-y', // tell to overwrite
56 4
                    sprintf('%s', escapeshellarg($outputFile)),
57
                ]
58
            )
59
        );
60
61 4
        $process = new Process($ffmpegCmd);
62 4
        $process->setTimeout($this->ffmpegConfig->getConversionTimeout());
63 4
        $process->setIdleTimeout($this->ffmpegConfig->getConversionIdleTimeout());
64
65 4
        return $process;
66
    }
67
68
    /**
69
     * Run a conversion, throw exception on error.
70
     *
71
     * @param callable|null                 $callback A PHP callback to run whenever there is some
72
     *                                                tmp available on STDOUT or STDERR
73
     * @param array<string,string|int>|null $env      An array of env vars to set
74
     *                                                when running the process
75
     *
76
     * @throws FileNotFoundException      When inputFile does not exists
77
     * @throws ProcessConversionException When the ffmpeg process conversion failed
78
     */
79 5
    public function convert(string $inputFile, string $outputFile, VideoConversionParams $convertParams, ?callable $callback = null, ?array $env = null): void
80
    {
81 5
        $process = $this->getConversionProcess($inputFile, $outputFile, $convertParams);
82
83
        try {
84 4
            $process->mustRun($callback, (is_array($env) ? $env : $this->ffmpegConfig->getConversionEnv()));
85 2
        } catch (ProcessException\RuntimeException $symfonyProcessException) {
86
            // will include: ProcessFailedException|ProcessTimedOutException|ProcessSignaledException
0 ignored issues
show
Unused Code Comprehensibility introduced by
37% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
87 2
            throw new ProcessConversionException($process, $symfonyProcessException);
88
        } catch (FileNotFoundException $e) {
89
            throw $e;
90
        }
91 2
    }
92
93
    /*
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
94
     * FOR LATER REFERENCE !!!
95
    public function convertMultiPass(string $videoFile, string $outputFile, VideoConversionParams $convertParams, VideoFilterInterface $videoFilter=null): void {
96
97
        $this->ensureFileExists($videoFile);
98
        if ($videoFilter === null) {
99
            $videoFilter = new EmptyVideoFilter();
100
        }
101
102
103
        $threads = $convertParams->getOption(VideoConversionParams::OPTION_THREADS, $this->ffmpegConfig->getThreads());
104
105
        $ffmpegBin = $this->ffmpegConfig->getBinary();
106
107
        $commonArgs = array_merge([
108
                $ffmpegBin,
109
                sprintf('-i %s', escapeshellarg($videoFile)), // input filename
110
                $videoFilter->getFFMpegCliArgument(), // add -vf yadif,nlmeans
111
                ($threads === null) ? '' : sprintf('-threads %s', $threads),
112
        ], $convertParams->getFFMpegArguments());
113
114
        $pass1Cmd = implode(' ', array_merge(
115
            $commonArgs,
116
            [
117
                '-pass 1',
118
                // tells VP9 to encode really fast, sacrificing quality. Useful to speed up the first pass.
119
                '-speed 4',
120
                '-y /dev/null',
121
            ]
122
        ));
123
124
        $pass2Cmd = implode( ' ', array_merge(
125
            $commonArgs,
126
            [
127
                '-pass 2',
128
                // speed 1 is a good speed vs. quality compromise.
129
                // Produces tmp quality typically very close to speed 0, but usually encodes much faster.
130
                '-speed 1',
131
                '-y',
132
                sprintf("%s", escapeshellarg($outputFile))
133
            ]
134
        ));
135
136
137
        $process = new Process($pass1Cmd);
138
        $process->setTimeout(null);
139
        $process->setIdleTimeout(60); // 60 seconds without tmp will stop the process
140
        $process->start();
141
        foreach ($process as $type => $data) {
142
            if ($process::OUT === $type) {
143
                echo "\nRead from stdout: ".$data;
144
            } else { // $process::ERR === $type
145
                echo "\nRead from stderr: ".$data;
146
            }
147
        }
148
149
        $process = new Process($pass2Cmd);
150
        $process->setTimeout(null);
151
        $process->setIdleTimeout(60); // 60 seconds without tmp will stop the process
152
        $process->start();
153
        foreach ($process as $type => $data) {
154
            if ($process::OUT === $type) {
155
                echo "\nRead from stdout: ".$data;
156
            } else { // $process::ERR === $type
157
                echo "\nRead from stderr: ".$data;
158
            }
159
        }
160
161
    }
162
    */
163
}
164