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\Video\Filter\EmptyVideoFilter; |
10
|
|
|
use Soluble\MediaTools\Video\Filter\VideoFilterChain; |
11
|
|
|
use Soluble\MediaTools\Video\Filter\VideoFilterInterface; |
12
|
|
|
use Soluble\MediaTools\Video\Filter\VideoFilterTypeDenoiseInterface; |
13
|
|
|
use Soluble\MediaTools\Video\Filter\YadifVideoFilter; |
14
|
|
|
use Soluble\MediaTools\Video\ProbeServiceInterface; |
15
|
|
|
|
16
|
|
|
class VideoThumb |
17
|
|
|
{ |
18
|
|
|
/** @var FFMpegConfig */ |
19
|
|
|
protected $ffmpegConfig; |
20
|
|
|
|
21
|
|
|
/** @var ProbeServiceInterface */ |
22
|
|
|
protected $videoProbe; |
23
|
|
|
|
24
|
|
|
public function __construct(FFMpegConfig $ffmpegConfig, ProbeServiceInterface $videoProbe) |
25
|
|
|
{ |
26
|
|
|
$this->videoProbe = $videoProbe; |
27
|
|
|
$this->ffmpegConfig = $ffmpegConfig; |
28
|
|
|
$this->ffmpegConfig->getProcess()->ensureBinaryExists(); |
29
|
|
|
} |
30
|
|
|
|
31
|
|
|
/** |
32
|
|
|
* Try to guess if the original video is interlaced (bff, tff) and |
33
|
|
|
* return ffmpeg yadif filter argument and add denoise filter if any. |
34
|
|
|
* |
35
|
|
|
* @see https://ffmpeg.org/ffmpeg-filters.html (section yadif) |
36
|
|
|
* @see https://askubuntu.com/a/867203 |
37
|
|
|
* |
38
|
|
|
* @return VideoFilterInterface|VideoFilterChain|EmptyVideoFilter|YadifVideoFilter |
39
|
|
|
*/ |
40
|
|
|
/* |
|
|
|
|
41
|
|
|
public function getDeintFilter(string $videoFile, ?VideoFilterTypeDenoiseInterface $denoiseFilter = null): VideoFilterInterface |
42
|
|
|
{ |
43
|
|
|
$guess = $this->videoProbe->guessInterlacing($videoFile); |
44
|
|
|
$deintFilter = $guess->getDeinterlaceVideoFilter(); |
45
|
|
|
// skip all filters if video is not interlaces |
46
|
|
|
if ($deintFilter instanceof EmptyVideoFilter) { |
47
|
|
|
return $deintFilter; |
48
|
|
|
} |
49
|
|
|
if ($denoiseFilter !== null) { |
50
|
|
|
$videoFilterChain = new VideoFilterChain(); |
51
|
|
|
$videoFilterChain->addFilter($deintFilter); |
52
|
|
|
$videoFilterChain->addFilter($denoiseFilter); |
53
|
|
|
|
54
|
|
|
return $videoFilterChain; |
55
|
|
|
} |
56
|
|
|
|
57
|
|
|
return $deintFilter; |
58
|
|
|
}*/ |
59
|
|
|
|
60
|
|
|
public function makeThumbnails(string $videoFile, string $outputFile, float $time = 0.0, ?VideoFilterInterface $videoFilter = null): void |
61
|
|
|
{ |
62
|
|
|
$this->ensureFileExists($videoFile); |
63
|
|
|
|
64
|
|
|
if ($videoFilter === null) { |
65
|
|
|
$videoFilter = new EmptyVideoFilter(); |
66
|
|
|
} |
67
|
|
|
|
68
|
|
|
$process = $this->ffmpegConfig->getProcess(); |
69
|
|
|
|
70
|
|
|
$ffmpegCmd = $process->buildCommand( |
71
|
|
|
[ |
72
|
|
|
($time > 0.0) ? sprintf('-ss %s', $time) : '', // putting time in front is much more efficient |
73
|
|
|
sprintf('-i %s', escapeshellarg($videoFile)), // input filename |
74
|
|
|
$videoFilter->getFFMpegCLIArgument(), // add -vf yadif,nlmeans |
75
|
|
|
'-frames:v 1', |
76
|
|
|
'-q:v 2', |
77
|
|
|
'-y', // tell to overwrite |
78
|
|
|
sprintf('%s', escapeshellarg($outputFile)), |
79
|
|
|
] |
80
|
|
|
); |
81
|
|
|
|
82
|
|
|
$process->runCommand($ffmpegCmd); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
protected function ensureFileExists(string $file): void |
86
|
|
|
{ |
87
|
|
|
if (!file_exists($file)) { |
88
|
|
|
throw new FileNotFoundException(sprintf('File "%s" does not exists or is not readable', $file)); |
89
|
|
|
} |
90
|
|
|
} |
91
|
|
|
} |
92
|
|
|
|
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.