Passed
Pull Request — master (#262)
by Pascal
02:27
created

PHPFFMpeg::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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

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