Failed Conditions
Push — master ( 898d32...e0e3f0 )
by Sébastien
03:39
created

VideoThumbService   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 84
Duplicated Lines 0 %

Test Coverage

Coverage 85.71%

Importance

Changes 0
Metric Value
wmc 11
eloc 36
dl 0
loc 84
ccs 24
cts 28
cp 0.8571
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
B makeThumbnail() 0 19 7
A getSymfonyProcess() 0 27 3
A __construct() 0 4 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Soluble\MediaTools;
6
7
use Soluble\MediaTools\Config\FFMpegConfigInterface;
8
use Soluble\MediaTools\Exception\FileNotFoundException;
9
use Soluble\MediaTools\Exception\UnsupportedParamException;
10
use Soluble\MediaTools\Exception\UnsupportedParamValueException;
11
use Soluble\MediaTools\Util\Assert\PathAssertionsTrait;
12
use Soluble\MediaTools\Video\Converter\FFMpegAdapter;
13
use Soluble\MediaTools\Video\Exception\ConversionExceptionInterface;
14
use Soluble\MediaTools\Video\Exception\ConversionProcessExceptionInterface;
15
use Soluble\MediaTools\Video\Exception\InvalidParamException;
16
use Soluble\MediaTools\Video\Exception\MissingInputFileException;
17
use Soluble\MediaTools\Video\Exception\ProcessFailedException;
18
use Soluble\MediaTools\Video\Exception\ProcessSignaledException;
19
use Soluble\MediaTools\Video\Exception\ProcessTimeOutException;
20
use Soluble\MediaTools\Video\Exception\RuntimeException;
21
use Soluble\MediaTools\Video\Filter\Type\VideoFilterInterface;
22
use Soluble\MediaTools\Video\SeekTime;
23
use Soluble\MediaTools\Video\ThumbServiceInterface;
24
use Symfony\Component\Process\Exception as SPException;
25
use Symfony\Component\Process\Process;
26
27 3
class VideoThumbService implements ThumbServiceInterface
28
{
29 3
    use PathAssertionsTrait;
30 3
31 3
    /** @var FFMpegConfigInterface */
32
    protected $ffmpegConfig;
33
34
    /** @var FFMpegAdapter */
35
    protected $adapter;
36
37
    public function __construct(FFMpegConfigInterface $ffmpegConfig)
38
    {
39
        $this->ffmpegConfig = $ffmpegConfig;
40
        $this->adapter      = new FFMpegAdapter($ffmpegConfig);
41
    }
42 3
43
    /**
44 3
     * Return ready-to-run symfony process object that you can use
45
     * to `run()` or `start()` programmatically. Useful if you want
46 2
     * handle the process your way...
47
     *
48 2
     * @see https://symfony.com/doc/current/components/process.html
49
     *
50
     * @throws UnsupportedParamException
51 2
     * @throws UnsupportedParamValueException
52
     */
53 2
    public function getSymfonyProcess(string $videoFile, string $thumbnailFile, ?SeekTime $time = null, ?VideoFilterInterface $videoFilter = null): Process
54
    {
55 2
        $params = (new VideoConversionParams());
56 1
57
        if ($time !== null) {
58
            // For performance reasons time seek must be
59
            // made at the beginning of options
60 2
            $params = $params->withSeekStart($time);
61
        }
62 2
        $params = $params->withVideoFrames(1);
63 2
64
        if ($videoFilter !== null) {
65 2
            $params = $params->withVideoFilter($videoFilter);
66 2
        }
67 2
68 2
        // Quality scale for the mjpeg encoder
69
        $params->withVideoQualityScale(2);
70 2
71
        $arguments = $this->adapter->getMappedConversionParams($params);
72
        $ffmpegCmd = $this->adapter->getCliCommand($arguments, $videoFile, $thumbnailFile);
73
74
        $process = new Process($ffmpegCmd);
75
        $process->setTimeout($this->ffmpegConfig->getTimeout());
76
        $process->setIdleTimeout($this->ffmpegConfig->getIdleTimeout());
77 3
        $process->setEnv($this->ffmpegConfig->getEnv());
78
79 3
        return $process;
80
    }
81 2
82
    /**
83
     * @throws ConversionExceptionInterface        Base exception class for conversion exceptions
84
     * @throws ConversionProcessExceptionInterface Base exception class for process conversion exceptions
85
     * @throws MissingInputFileException
86
     * @throws ProcessTimeOutException
87
     * @throws ProcessFailedException
88 2
     * @throws ProcessSignaledException
89
     * @throws RuntimeException
90
     * @throws InvalidParamException
91
     */
92
    public function makeThumbnail(string $videoFile, string $thumbnailFile, ?SeekTime $time = null, ?VideoFilterInterface $videoFilter = null, ?callable $callback = null): void
93
    {
94
        try {
95
            $this->ensureFileExists($videoFile);
96
97
            $process = $this->getSymfonyProcess($videoFile, $thumbnailFile, $time, $videoFilter);
98
            $process->mustRun($callback);
99
        } catch (FileNotFoundException $e) {
100
            throw new MissingInputFileException($e->getMessage());
101
        } catch (UnsupportedParamValueException | UnsupportedParamException $e) {
102
            throw new InvalidParamException($e->getMessage());
103
        } catch (SPException\ProcessTimedOutException $e) {
104
            throw new ProcessTimeOutException($e->getProcess(), $e);
105
        } catch (SPException\ProcessSignaledException $e) {
106
            throw new ProcessSignaledException($e->getProcess(), $e);
107
        } catch (SPException\ProcessFailedException $e) {
108
            throw new ProcessFailedException($e->getProcess(), $e);
109
        } catch (SPException\RuntimeException $e) {
110
            throw new RuntimeException($e->getMessage());
111
        }
112
    }
113
}
114