Passed
Push — master ( c491f6...ec8dab )
by Sébastien
02:19
created

ScanCommand   A

Complexity

Total Complexity 19

Size/Duplication

Total Lines 186
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 0
Metric Value
eloc 103
dl 0
loc 186
ccs 0
cts 125
cp 0
rs 10
c 0
b 0
f 0
wmc 19

5 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
A getVideoFiles() 0 17 2
A configure() 0 8 1
A outputTable() 0 2 1
F execute() 0 117 14
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Soluble\MediaTools\Cli\Command;
6
7
use ScriptFUSION\Byte\ByteFormatter;
8
use ScriptFUSION\Byte\Unit\SymbolDecorator;
9
use Soluble\MediaTools\Video\Exception\InfoReaderExceptionInterface;
10
use Soluble\MediaTools\Video\SeekTime;
11
use Soluble\MediaTools\Video\VideoInfoReaderInterface;
12
use Symfony\Component\Console\Command\Command;
13
use Symfony\Component\Console\Helper\ProgressBar;
14
use Symfony\Component\Console\Helper\Table;
15
use Symfony\Component\Console\Helper\TableCell;
16
use Symfony\Component\Console\Helper\TableSeparator;
17
use Symfony\Component\Console\Helper\TableStyle;
18
use Symfony\Component\Console\Input\InputDefinition;
19
use Symfony\Component\Console\Input\InputInterface;
20
use Symfony\Component\Console\Input\InputOption;
21
use Symfony\Component\Console\Output\OutputInterface;
22
use Symfony\Component\Finder\Finder;
23
24
class ScanCommand extends Command
25
{
26
    /**
27
     * @var VideoInfoReaderInterface
28
     */
29
    private $reader;
30
31
    /** @var string[] */
32
    private $supportedVideoExtensions = [
33
        'mov',
34
        'mp4',
35
        'm4v',
36
        'mkv',
37
        'flv',
38
        'webm',
39
    ];
40
41
    public function __construct(VideoInfoReaderInterface $videoInfoReader)
42
    {
43
        $this->reader = $videoInfoReader;
44
        parent::__construct();
45
    }
46
47
    /**
48
     * Configures the command.
49
     */
50
    protected function configure(): void
51
    {
52
        $this
53
            ->setName('scan:videos')
54
            ->setDescription('Scan for video')
55
            ->setDefinition(
56
                new InputDefinition([
57
                    new InputOption('dir', 'd', InputOption::VALUE_REQUIRED),
58
                ])
59
            );
60
    }
61
62
    /**
63
     * {@inheritdoc}
64
     */
65
    protected function execute(InputInterface $input, OutputInterface $output)
66
    {
67
        if (!$input->hasOption('dir')) {
68
            throw new \Exception('Missing dir argument, use <command> <dir>');
69
        }
70
        $videoPath = $input->hasOption('dir') ? $input->getOption('dir') : '';
71
        if (!is_string($videoPath) || !is_dir($videoPath)) {
72
            throw new \Exception(sprintf(
73
                'Video dir %s does not exists',
74
                is_string($videoPath) ? $videoPath : ''
75
            ));
76
        }
77
78
        $output->writeln(sprintf('Scanning %s', $videoPath));
79
80
        // Get the videos in path
81
        $videos = $this->getVideoFiles($videoPath);
82
83
        $progressBar = new ProgressBar($output, count($videos));
84
        $progressBar->start();
85
86
        $bitRateFormatter = new ByteFormatter();
87
        //$bitRateFormatter->setUnitDecorator(new SymbolDecorator(SymbolDecorator::SUFFIX_NONE));
88
89
        $sizeFormatter = new ByteFormatter();
90
91
        $rows      = [];
92
        $warnings  = [];
93
        $totalSize = 0;
94
95
        /** @var \SplFileInfo $video */
96
        foreach ($videos as $video) {
97
            $videoFile = $video->getPathname();
98
            try {
99
                $info     = $this->reader->getInfo($videoFile);
100
                $vStream  = $info->getVideoStreams()->getFirst();
101
                $pixFmt   = $vStream->getPixFmt();
102
                $bitRate  = $vStream->getBitRate();
103
                $fileSize = (int) filesize($videoFile);
104
                $row      = [
105
                    $video,
106
                    preg_replace('/\.([0-9])+$/', '', SeekTime::convertSecondsToHMSs(round($info->getDuration(), 1))),
107
                    $vStream->getCodecName(),
108
                    sprintf('%sx%s', $vStream->getWidth(), $vStream->getHeight()),
109
                    ($bitRate > 0 ? $bitRateFormatter->format((int) $bitRate) . '/s' : ''),
110
                    $sizeFormatter->format($fileSize),
111
                    $pixFmt,
112
                ];
113
                $rows[] = $row;
114
                $totalSize += $fileSize;
115
            } catch (InfoReaderExceptionInterface $e) {
116
                $warnings[] = [$videoFile];
117
            }
118
119
            $progressBar->advance();
120
        }
121
122
        $output->writeln('');
123
124
        $table = new Table($output);
125
126
        $rightAlignstyle = new TableStyle();
127
        $rightAlignstyle->setPadType(STR_PAD_LEFT);
128
129
        //$table->setStyle($tableStyle);
130
        $table->setStyle('box');
131
        $table->setHeaders([
132
            'file',
133
            'duration',
134
            'codec',
135
            'size',
136
            'bitrate',
137
            'filesize',
138
            'pix_fmt',
139
        ]);
140
141
        $previousPath = null;
142
        $first        = true;
143
144
        foreach ($rows as $row) {
145
            /** @var \SplFileInfo $file */
146
            $file   = $row[0];
147
            $row[0] = $file->getBasename();
148
            if ($previousPath !== $file->getPath()) {
149
                if (!$first) {
150
                    $table->addRow(new TableSeparator(['colspan' => count($row)]));
151
                }
152
                //$table->addRow([new TableCell(sprintf('<fg=yellow>%s</>', $file->getPath()), ['colspan' => count($row)])]);
153
                $table->addRow([new TableCell(sprintf('<fg=yellow>%s</>', $file->getPath()))]);
154
                $table->addRow(new TableSeparator(['colspan' => count($row)]));
155
                $previousPath = $file->getPath();
156
            }
157
            $table->addRow($row);
158
            $first = false;
159
        }
160
        foreach ($colIndexes = [1, 2, 3, 4, 5, 6] as $idx) {
0 ignored issues
show
Unused Code introduced by
The assignment to $colIndexes is dead and can be removed.
Loading history...
161
            $table->setColumnStyle($idx, $rightAlignstyle);
162
        }
163
        $table->addRow(new TableSeparator());
164
        $table->addRow(['<fg=cyan>Total</>', '', '', '', '', sprintf('<fg=cyan>%s</>', $sizeFormatter->format($totalSize))]);
165
166
        $table->render();
167
168
        // display warnings
169
        if (count($warnings) > 0) {
170
            $table = new Table($output);
171
            $table->setHeaders([
172
                'Unsupported files'
173
            ]);
174
            $table->setStyle('box');
175
            $table->setRows($warnings);
176
            $table->render();
177
        }
178
179
        $output->writeln("\nFinished");
180
181
        return 1;
182
    }
183
184
    private function outputTable(array $rows): void
0 ignored issues
show
Unused Code introduced by
The parameter $rows is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

184
    private function outputTable(/** @scrutinizer ignore-unused */ array $rows): void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The method outputTable() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
185
    {
186
    }
187
188
    /**
189
     * @param string $videoPath
190
     *
191
     * @return array<\SplFileInfo>
192
     */
193
    public function getVideoFiles(string $videoPath): array
194
    {
195
        $files = (new Finder())->files()
196
            ->in($videoPath)
197
            ->name(sprintf(
198
                '/\.(%s)$/',
199
                implode('|', $this->supportedVideoExtensions)
200
            ));
201
202
        $videos = [];
203
204
        /** @var \SplFileInfo $file */
205
        foreach ($files as $file) {
206
            $videos[] = $file;
207
        }
208
209
        return $videos;
210
    }
211
}
212