Failed Conditions
Push — master ( 85c284...561f65 )
by Sébastien
02:44
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 Soluble\MediaTools\Video\Converter\FFMpegAdapter;
14
use Symfony\Component\Process\Exception as SPException;
15
use Symfony\Component\Process\Process;
16
17
class VideoConversionService implements ConversionServiceInterface
18
{
19
    use PathAssertionsTrait;
20
21
    /** @var FFMpegConfig */
22
    protected $ffmpegConfig;
23
24
    /** @var FFMpegAdapter */
25
    protected $converter;
26
27 5
    public function __construct(FFMpegConfig $ffmpegConfig)
28
    {
29 5
        $this->ffmpegConfig = $ffmpegConfig;
30 5
        $this->converter    = new FFMpegAdapter($ffmpegConfig);
31 5
    }
32
33
    /**
34
     * Return ready-to-run symfony process object that you can use
35
     * to `run()` or `start()` programmatically. Useful if you want to make
36
     * things async...
37
     *
38
     * @see https://symfony.com/doc/current/components/process.html
39
     *
40
     * @throws FileNotFoundException when inputFile does not exists
41
     */
42 5
    public function getConversionProcess(string $inputFile, string $outputFile, VideoConversionParams $convertParams): Process
43
    {
44 5
        $this->ensureFileExists($inputFile);
45
46 4
        if (!$convertParams->hasParam(ConversionParamsInterface::PARAM_THREADS) && $this->ffmpegConfig->getThreads() !== null) {
47
            $convertParams = $convertParams->withThreads($this->ffmpegConfig->getThreads());
48
        }
49
50 4
        $arguments = $this->converter->getMappedConversionParams($convertParams);
51 4
        $ffmpegCmd = $this->converter->getCliCommand($arguments, $inputFile, $outputFile);
52
53 4
        $process = new Process($ffmpegCmd);
54 4
        $process->setTimeout($this->ffmpegConfig->getConversionTimeout());
55 4
        $process->setIdleTimeout($this->ffmpegConfig->getConversionIdleTimeout());
56 4
        $process->setEnv($this->ffmpegConfig->getConversionEnv());
57
58 4
        return $process;
59
    }
60
61
    /**
62
     * Run a conversion, throw exception on error.
63
     *
64
     * @param callable|null $callback A PHP callback to run whenever there is some
65
     *                                tmp available on STDOUT or STDERR
66
     *
67
     * @throws FileNotFoundException      When inputFile does not exists
68
     * @throws ProcessConversionException When the ffmpeg process conversion failed
69
     */
70 5
    public function convert(string $inputFile, string $outputFile, VideoConversionParams $convertParams, ?callable $callback = null): void
71
    {
72 5
        $process = $this->getConversionProcess($inputFile, $outputFile, $convertParams);
73
74
        try {
75 4
            $process->mustRun($callback);
76 2
        } catch (SPException\RuntimeException $symfonyProcessException) {
77
            // 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...
78 2
            throw new ProcessConversionException($process, $symfonyProcessException);
79
        } catch (FileNotFoundException $e) {
80
            throw $e;
81
        }
82 2
    }
83
84
    /*
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...
85
     * FOR LATER REFERENCE !!!
86
    public function convertMultiPass(string $videoFile, string $outputFile, VideoConversionParams $convertParams, VideoFilterInterface $videoFilter=null): void {
87
88
        $this->ensureFileExists($videoFile);
89
        if ($videoFilter === null) {
90
            $videoFilter = new EmptyVideoFilter();
91
        }
92
93
94
        $threads = $convertParams->getOption(VideoConversionParams::OPTION_THREADS, $this->ffmpegConfig->getThreads());
95
96
        $ffmpegBin = $this->ffmpegConfig->getBinary();
97
98
        $commonArgs = array_merge([
99
                $ffmpegBin,
100
                sprintf('-i %s', escapeshellarg($videoFile)), // input filename
101
                $videoFilter->getFFMpegCliArgument(), // add -vf yadif,nlmeans
102
                ($threads === null) ? '' : sprintf('-threads %s', $threads),
103
        ], $convertParams->getFFMpegArguments());
104
105
        $pass1Cmd = implode(' ', array_merge(
106
            $commonArgs,
107
            [
108
                '-pass 1',
109
                // tells VP9 to encode really fast, sacrificing quality. Useful to speed up the first pass.
110
                '-speed 4',
111
                '-y /dev/null',
112
            ]
113
        ));
114
115
        $pass2Cmd = implode( ' ', array_merge(
116
            $commonArgs,
117
            [
118
                '-pass 2',
119
                // speed 1 is a good speed vs. quality compromise.
120
                // Produces tmp quality typically very close to speed 0, but usually encodes much faster.
121
                '-speed 1',
122
                '-y',
123
                sprintf("%s", escapeshellarg($outputFile))
124
            ]
125
        ));
126
127
128
        $process = new Process($pass1Cmd);
129
        $process->setTimeout(null);
130
        $process->setIdleTimeout(60); // 60 seconds without tmp will stop the process
131
        $process->start();
132
        foreach ($process as $type => $data) {
133
            if ($process::OUT === $type) {
134
                echo "\nRead from stdout: ".$data;
135
            } else { // $process::ERR === $type
136
                echo "\nRead from stderr: ".$data;
137
            }
138
        }
139
140
        $process = new Process($pass2Cmd);
141
        $process->setTimeout(null);
142
        $process->setIdleTimeout(60); // 60 seconds without tmp will stop the process
143
        $process->start();
144
        foreach ($process as $type => $data) {
145
            if ($process::OUT === $type) {
146
                echo "\nRead from stdout: ".$data;
147
            } else { // $process::ERR === $type
148
                echo "\nRead from stderr: ".$data;
149
            }
150
        }
151
152
    }
153
    */
154
}
155