Passed
Push — master ( 7e62d3...3c4375 )
by Pascal
02:25
created

PHPFFMpeg::removeListener()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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

154
        /** @scrutinizer ignore-call */ 
155
        $this->media = $this->media->frame($timecode);
Loading history...
155
156
        return $this;
157
    }
158
159
    public function concatWithoutTranscoding()
160
    {
161
        $localPaths = $this->mediaCollection->getLocalPaths();
162
163
        $this->media = $this->ffmpeg->open(Arr::first($localPaths))
164
            ->concat($localPaths);
165
166
        return $this;
167
    }
168
169
    /**
170
     * Force 'openAdvanced' when opening the MediaCollection
171
     */
172
    public function openAdvanced(MediaCollection $mediaCollection): self
173
    {
174
        $this->forceAdvanced = true;
175
176
        return $this->open($mediaCollection);
177
    }
178
179
    /**
180
     * Returns the FFMpegDriver of the underlying library.
181
     *
182
     * @return \FFMpeg\Driver\FFMpegDriver
183
     */
184
    private function getFFMpegDriver(): FFMpegDriver
185
    {
186
        return $this->get()->getFFMpegDriver();
187
    }
188
189
    /**
190
     * Add a Listener to the underlying library.
191
     *
192
     * @param \Alchemy\BinaryDriver\Listeners\ListenerInterface $listener
193
     * @return self
194
     */
195
    public function addListener(ListenerInterface $listener): self
196
    {
197
        $this->getFFMpegDriver()->listen($listener);
198
199
        return $this;
200
    }
201
202
    /**
203
     * Remove the Listener from the underlying library.
204
     *
205
     * @param \Alchemy\BinaryDriver\Listeners\ListenerInterface $listener
206
     * @return self
207
     */
208
    public function removeListener(ListenerInterface $listener): self
209
    {
210
        $this->getFFMpegDriver()->unlisten($listener);
211
212
        return $this;
213
    }
214
215
    /**
216
     * Adds a callable to the callbacks array.
217
     *
218
     * @param callable $callback
219
     * @return self
220
     */
221
    public function beforeSaving(callable $callback): self
222
    {
223
        $this->beforeSavingCallbacks[] = $callback;
224
225
        return $this;
226
    }
227
228
    /**
229
     * Set the callbacks on the Media.
230
     *
231
     * @return self
232
     */
233
    public function applyBeforeSavingCallbacks(): self
234
    {
235
        $media = $this->get();
236
237
        if (method_exists($media, 'setBeforeSavingCallbacks')) {
238
            $media->setBeforeSavingCallbacks($this->beforeSavingCallbacks);
239
        }
240
241
        return $this;
242
    }
243
244
    /**
245
     * Add an event handler to the underlying library.
246
     *
247
     * @param string $event
248
     * @param callable $callback
249
     * @return self
250
     */
251
    public function onEvent(string $event, callable $callback): self
252
    {
253
        $this->getFFMpegDriver()->on($event, $callback);
254
255
        return $this;
256
    }
257
258
    /**
259
     * Returns the underlying media object itself.
260
     */
261
    public function __invoke(): AbstractMediaType
262
    {
263
        return $this->get();
264
    }
265
266
    /**
267
     * Forwards the call to the underling media object and returns the result
268
     * if it's something different than the media object itself.
269
     */
270
    public function __call($method, $arguments)
271
    {
272
        $result = $this->forwardCallTo($media = $this->get(), $method, $arguments);
273
274
        return ($result === $media) ? $this : $result;
275
    }
276
}
277