Passed
Pull Request — master (#273)
by Pascal
14:52
created

PHPFFMpeg::getFFMpegDriver()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace ProtoneMedia\LaravelFFMpeg\Drivers;
4
5
use Alchemy\BinaryDriver\Listeners\ListenerInterface;
6
use Exception;
7
use FFMpeg\Coordinate\TimeCode;
8
use FFMpeg\Driver\FFMpegDriver;
9
use FFMpeg\FFMpeg;
10
use FFMpeg\Media\AbstractMediaType;
11
use FFMpeg\Media\AdvancedMedia as BaseAdvancedMedia;
12
use FFMpeg\Media\Concat;
13
use FFMpeg\Media\Frame;
14
use FFMpeg\Media\Video;
15
use Illuminate\Support\Arr;
16
use Illuminate\Support\Collection;
17
use Illuminate\Support\Traits\ForwardsCalls;
18
use ProtoneMedia\LaravelFFMpeg\FFMpeg\AdvancedMedia;
19
use ProtoneMedia\LaravelFFMpeg\FFMpeg\AudioMedia;
20
use ProtoneMedia\LaravelFFMpeg\FFMpeg\FFProbe;
21
use ProtoneMedia\LaravelFFMpeg\FFMpeg\VideoMedia;
22
use ProtoneMedia\LaravelFFMpeg\Filesystem\MediaCollection;
23
24
/**
25
 * @mixin \FFMpeg\Media\AbstractMediaType
26
 */
27
class PHPFFMpeg
28
{
29
    use ForwardsCalls;
30
    use InteractsWithFilters;
31
    use InteractsWithMediaStreams;
32
33
    /**
34
     * @var \FFMpeg\FFMpeg
35
     */
36
    private $ffmpeg;
37
38
    /**
39
     * @var \ProtoneMedia\LaravelFFMpeg\Filesystem\MediaCollection
40
     */
41
    private $mediaCollection;
42
43
    /**
44
     * @var boolean
45
     */
46
    private $forceAdvanced = false;
47
48
    /**
49
     * @var \FFMpeg\Media\AbstractMediaType
50
     */
51
    private $media;
52
53
    /**
54
     * Callbacks that should be called just before the
55
     * underlying library hits the save method.
56
     *
57
     * @var array
58
     */
59
    private $beforeSavingCallbacks = [];
60
61
    public function __construct(FFMpeg $ffmpeg)
62
    {
63
        $this->ffmpeg                = $ffmpeg;
64
        $this->pendingComplexFilters = new Collection;
65
    }
66
67
    /**
68
     * Returns a fresh instance of itself with only the underlying FFMpeg instance.
69
     */
70
    public function fresh(): self
71
    {
72
        return new static($this->ffmpeg);
73
    }
74
75
    public function get(): AbstractMediaType
76
    {
77
        return $this->media;
78
    }
79
80
    private function isAdvancedMedia(): bool
0 ignored issues
show
Unused Code introduced by
The method isAdvancedMedia() 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...
81
    {
82
        return $this->get() instanceof BaseAdvancedMedia;
83
    }
84
85
    public function isFrame(): bool
86
    {
87
        return $this->get() instanceof Frame;
88
    }
89
90
    public function isConcat(): bool
91
    {
92
        return $this->get() instanceof Concat;
93
    }
94
95
    public function isVideo(): bool
96
    {
97
        return $this->get() instanceof Video;
98
    }
99
100
    public function getMediaCollection(): MediaCollection
101
    {
102
        return $this->mediaCollection;
103
    }
104
105
    /**
106
     * Opens the MediaCollection if it's not been instanciated yet.
107
     */
108
    public function open(MediaCollection $mediaCollection): self
109
    {
110
        if ($this->media) {
111
            return $this;
112
        }
113
114
        $this->mediaCollection = $mediaCollection;
115
116
        if ($mediaCollection->count() === 1 && !$this->forceAdvanced) {
117
            $media = Arr::first($mediaCollection->collection());
118
119
            $this->ffmpeg->setFFProbe(
120
                FFProbe::make($this->ffmpeg->getFFProbe())->setMedia($media)
121
            );
122
123
            $ffmpegMedia = $this->ffmpeg->open($media->getLocalPath());
124
125
            $this->media = $ffmpegMedia instanceof Video
126
                ? VideoMedia::make($ffmpegMedia)
127
                : AudioMedia::make($ffmpegMedia);
128
129
            $this->media->setHeaders(Arr::first($mediaCollection->getHeaders()) ?: []);
130
        } else {
131
            $ffmpegMedia = $this->ffmpeg->openAdvanced($mediaCollection->getLocalPaths());
132
133
            $this->media = AdvancedMedia::make($ffmpegMedia)
134
                ->setHeaders($mediaCollection->getHeaders());
135
        }
136
137
        return $this;
138
    }
139
140
    public function frame(TimeCode $timecode)
141
    {
142
        if (!$this->isVideo()) {
143
            throw new Exception('Opened media is not a video file.');
144
        }
145
146
        $this->media = $this->media->frame($timecode);
0 ignored issues
show
Bug introduced by
The method frame() does not exist on FFMpeg\Media\AbstractMediaType. It seems like you code against a sub-type of FFMpeg\Media\AbstractMediaType such as FFMpeg\Media\Video. ( Ignorable by Annotation )

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

146
        /** @scrutinizer ignore-call */ 
147
        $this->media = $this->media->frame($timecode);
Loading history...
147
148
        return $this;
149
    }
150
151
    public function concatWithoutTranscoding()
152
    {
153
        $localPaths = $this->mediaCollection->getLocalPaths();
154
155
        $this->media = $this->ffmpeg->open(Arr::first($localPaths))
156
            ->concat($localPaths);
157
158
        return $this;
159
    }
160
161
    /**
162
     * Force 'openAdvanced' when opening the MediaCollection
163
     */
164
    public function openAdvanced(MediaCollection $mediaCollection): self
165
    {
166
        $this->forceAdvanced = true;
167
168
        return $this->open($mediaCollection);
169
    }
170
171
    /**
172
     * Returns the FFMpegDriver of the underlying library.
173
     *
174
     * @return \FFMpeg\Driver\FFMpegDriver
175
     */
176
    private function getFFMpegDriver(): FFMpegDriver
177
    {
178
        return $this->get()->getFFMpegDriver();
179
    }
180
181
    /**
182
     * Add a Listener to the underlying library.
183
     *
184
     * @param \Alchemy\BinaryDriver\Listeners\ListenerInterface $listener
185
     * @return self
186
     */
187
    public function addListener(ListenerInterface $listener): self
188
    {
189
        $this->getFFMpegDriver()->listen($listener);
190
191
        return $this;
192
    }
193
194
    /**
195
     * Adds a callable to the callbacks array.
196
     *
197
     * @param callable $callback
198
     * @return self
199
     */
200
    public function beforeSaving(callable $callback): self
201
    {
202
        $this->beforeSavingCallbacks[] = $callback;
203
204
        return $this;
205
    }
206
207
    /**
208
     * Set the callbacks on the Media.
209
     *
210
     * @return self
211
     */
212
    public function applyBeforeSavingCallbacks(): self
213
    {
214
        $this->get()->setBeforeSavingCallbacks($this->beforeSavingCallbacks);
0 ignored issues
show
Bug introduced by
The method setBeforeSavingCallbacks() does not exist on FFMpeg\Media\AbstractMediaType. It seems like you code against a sub-type of FFMpeg\Media\AbstractMediaType such as ProtoneMedia\LaravelFFMpeg\FFMpeg\AdvancedMedia or ProtoneMedia\LaravelFFMpeg\FFMpeg\AudioMedia or ProtoneMedia\LaravelFFMpeg\FFMpeg\VideoMedia. ( Ignorable by Annotation )

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

214
        $this->get()->/** @scrutinizer ignore-call */ setBeforeSavingCallbacks($this->beforeSavingCallbacks);
Loading history...
215
216
        return $this;
217
    }
218
219
    /**
220
     * Add an event handler to the underlying library.
221
     *
222
     * @param string $event
223
     * @param callable $callback
224
     * @return self
225
     */
226
    public function onEvent(string $event, callable $callback): self
227
    {
228
        $this->getFFMpegDriver()->on($event, $callback);
229
230
        return $this;
231
    }
232
233
    /**
234
     * Returns the underlying media object itself.
235
     */
236
    public function __invoke(): AbstractMediaType
237
    {
238
        return $this->get();
239
    }
240
241
    /**
242
     * Forwards the call to the underling media object and returns the result
243
     * if it's something different than the media object itself.
244
     */
245
    public function __call($method, $arguments)
246
    {
247
        $result = $this->forwardCallTo($media = $this->get(), $method, $arguments);
248
249
        return ($result === $media) ? $this : $result;
250
    }
251
}
252