Passed
Pull Request — master (#262)
by Pascal
03:33
created

PHPFFMpeg::onEvent()   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
c 0
b 0
f 0
nc 1
nop 2
dl 0
loc 5
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
    public function __construct(FFMpeg $ffmpeg)
54
    {
55
        $this->ffmpeg                = $ffmpeg;
56
        $this->pendingComplexFilters = new Collection;
57
    }
58
59
    /**
60
     * Returns a fresh instance of itself with only the underlying FFMpeg instance.
61
     */
62
    public function fresh(): self
63
    {
64
        return new static($this->ffmpeg);
65
    }
66
67
    public function get(): AbstractMediaType
68
    {
69
        return $this->media;
70
    }
71
72
    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...
73
    {
74
        return $this->get() instanceof BaseAdvancedMedia;
75
    }
76
77
    public function isFrame(): bool
78
    {
79
        return $this->get() instanceof Frame;
80
    }
81
82
    public function isConcat(): bool
83
    {
84
        return $this->get() instanceof Concat;
85
    }
86
87
    public function isVideo(): bool
88
    {
89
        return $this->get() instanceof Video;
90
    }
91
92
    public function getMediaCollection(): MediaCollection
93
    {
94
        return $this->mediaCollection;
95
    }
96
97
    /**
98
     * Opens the MediaCollection if it's not been instanciated yet.
99
     */
100
    public function open(MediaCollection $mediaCollection): self
101
    {
102
        if ($this->media) {
103
            return $this;
104
        }
105
106
        $this->mediaCollection = $mediaCollection;
107
108
        if ($mediaCollection->count() === 1 && !$this->forceAdvanced) {
109
            $media = Arr::first($mediaCollection->collection());
110
111
            $this->ffmpeg->setFFProbe(
112
                FFProbe::make($this->ffmpeg->getFFProbe())->setMedia($media)
113
            );
114
115
            $ffmpegMedia = $this->ffmpeg->open($media->getLocalPath());
116
117
            $this->media = $ffmpegMedia instanceof Video
118
                ? VideoMedia::make($ffmpegMedia)
119
                : AudioMedia::make($ffmpegMedia);
120
121
            $this->media->setHeaders(Arr::first($mediaCollection->getHeaders()) ?: []);
122
        } else {
123
            $ffmpegMedia = $this->ffmpeg->openAdvanced($mediaCollection->getLocalPaths());
124
125
            $this->media = AdvancedMedia::make($ffmpegMedia)
126
                ->setHeaders($mediaCollection->getHeaders());
127
        }
128
129
        return $this;
130
    }
131
132
    public function frame(TimeCode $timecode)
133
    {
134
        if (!$this->isVideo()) {
135
            throw new Exception('Opened media is not a video file.');
136
        }
137
138
        $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

138
        /** @scrutinizer ignore-call */ 
139
        $this->media = $this->media->frame($timecode);
Loading history...
139
140
        return $this;
141
    }
142
143
    public function concatWithoutTranscoding()
144
    {
145
        $localPaths = $this->mediaCollection->getLocalPaths();
146
147
        $this->media = $this->ffmpeg->open(Arr::first($localPaths))
148
            ->concat($localPaths);
149
150
        return $this;
151
    }
152
153
    /**
154
     * Force 'openAdvanced' when opening the MediaCollection
155
     */
156
    public function openAdvanced(MediaCollection $mediaCollection): self
157
    {
158
        $this->forceAdvanced = true;
159
160
        return $this->open($mediaCollection);
161
    }
162
163
    /**
164
     * Returns the FFMpegDriver of the underlying library.
165
     *
166
     * @return \FFMpeg\Driver\FFMpegDriver
167
     */
168
    private function getFFMpegDriver(): FFMpegDriver
169
    {
170
        return $this->get()->getFFMpegDriver();
171
    }
172
173
    /**
174
     * Add a Listener to the underlying library.
175
     *
176
     * @param \Alchemy\BinaryDriver\Listeners\ListenerInterface $listener
177
     * @return self
178
     */
179
    public function addListener(ListenerInterface $listener): self
180
    {
181
        $this->getFFMpegDriver()->listen($listener);
182
183
        return $this;
184
    }
185
186
    /**
187
     * Add an event handler to the underlying library.
188
     *
189
     * @param string $event
190
     * @param callable $callback
191
     * @return self
192
     */
193
    public function onEvent(string $event, callable $callback): self
194
    {
195
        $this->getFFMpegDriver()->on($event, $callback);
196
197
        return $this;
198
    }
199
200
    /**
201
     * Returns the underlying media object itself.
202
     */
203
    public function __invoke(): AbstractMediaType
204
    {
205
        return $this->get();
206
    }
207
208
    /**
209
     * Forwards the call to the underling media object and returns the result
210
     * if it's something different than the media object itself.
211
     */
212
    public function __call($method, $arguments)
213
    {
214
        $result = $this->forwardCallTo($media = $this->get(), $method, $arguments);
215
216
        return ($result === $media) ? $this : $result;
217
    }
218
}
219