Passed
Push — master ( bf86e6...5ea322 )
by Sébastien
07:21
created

ThumbService   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 84
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 36
dl 0
loc 84
rs 10
c 0
b 0
f 0
wmc 11

3 Methods

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