Passed
Push — master ( 4bc7af...ac0e9d )
by Amin
02:25
created

Stream::save()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 2
dl 0
loc 7
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * This file is part of the PHP-FFmpeg-video-streaming package.
5
 *
6
 * (c) Amin Yazdanpanah <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Streaming;
13
14
use FFMpeg\Exception\ExceptionInterface;
15
use Streaming\Clouds\Cloud;
16
use Streaming\Exception\InvalidArgumentException;
17
use Streaming\Exception\RuntimeException;
18
use Streaming\Filters\StreamFilterInterface;
19
use Streaming\Traits\Formats;
20
21
22
abstract class Stream implements StreamInterface
23
{
24
    use Formats;
25
26
    /** @var object */
27
    protected $media;
28
29
    /** @var string */
30
    protected $path;
31
32
    /** @var string */
33
    protected $tmp_dir;
34
35
    /** @var string */
36
    protected $uri;
37
38
    /**
39
     * Stream constructor.
40
     * @param Media $media
41
     */
42
    public function __construct(Media $media)
43
    {
44
        $this->media = $media;
45
        $this->path = $media->getPath();
46
    }
47
48
    /**
49
     * @return object|Media
50
     */
51
    public function getMedia(): Media
52
    {
53
        return $this->media;
54
    }
55
56
    /**
57
     * @return bool
58
     */
59
    public function isTmpDir(): bool
60
    {
61
        return (bool)$this->tmp_dir;
62
    }
63
64
    /**
65
     * @param int $option
66
     * @return string
67
     */
68
    public function getPathInfo(int $option): string
69
    {
70
        return pathinfo($this->path, $option);
71
    }
72
73
    /**
74
     * @param string|null $path
75
     */
76
    private function moveTmp(?string $path): void
77
    {
78
        if ($this->isTmpDir() && !is_null($path)) {
79
            File::move($this->tmp_dir, dirname($path));
80
            $this->path = $path;
81
            $this->tmp_dir = '';
82
        }
83
    }
84
85
    /**
86
     * @param array $clouds
87
     * @param string $path
88
     */
89
    private function clouds(array $clouds, ?string $path): void
90
    {
91
        if (!empty($clouds)) {
92
            Cloud::uploadDirectory($clouds, $this->tmp_dir);
93
            $this->moveTmp($path);
94
        }
95
    }
96
97
    /**
98
     * @return string
99
     */
100
    protected function getFilePath(): string
101
    {
102
        return str_replace(
103
            "\\",
104
            "/",
105
            $this->getPathInfo(PATHINFO_DIRNAME) . "/" . $this->getPathInfo(PATHINFO_FILENAME)
106
        );
107
    }
108
109
    /**
110
     * @return string
111
     */
112
    abstract protected function getPath(): string;
113
114
    /**
115
     * @return StreamFilterInterface
116
     */
117
    abstract protected function getFilter(): StreamFilterInterface;
118
119
    /**
120
     * Run FFmpeg to package media content
121
     */
122
    private function run(): void
123
    {
124
        try {
125
            $this->media
126
                ->addFilter($this->getFilter())
127
                ->save($this->getFormat(), $this->getPath());
128
        } catch (ExceptionInterface $e) {
129
            throw new RuntimeException("An error occurred while saving files: " . $e->getMessage(), $e->getCode(), $e);
130
        }
131
    }
132
133
    /**
134
     * @param $path
135
     * @param $clouds
136
     */
137
    private function paths(?string $path, array $clouds): void
138
    {
139
        if (!empty($clouds)) {
140
            $this->tmp_dir = File::tmpDir();
141
            $this->path = $this->tmp_dir . basename($path ?? $this->path);
142
        } elseif (!is_null($path)) {
143
            if (strlen($path) > PHP_MAXPATHLEN) {
144
                throw new InvalidArgumentException("The path is too long");
145
            }
146
147
            File::makeDir(dirname($path));
148
            $this->path = $path;
149
        } elseif ($this->media->isTmp()) {
150
            throw new InvalidArgumentException("You need to specify a path. It is not possible to save to a tmp directory");
151
        }
152
    }
153
154
    /**
155
     * @param string $path
156
     * @param array $clouds
157
     * @return mixed
158
     */
159
    public function save(string $path = null, array $clouds = []): Stream
160
    {
161
        $this->paths($path, $clouds);
162
        $this->run();
163
        $this->clouds($clouds, $path);
164
165
        return $this;
166
    }
167
168
    /**
169
     * @param string $url
170
     */
171
    public function live(string $url): void
172
    {
173
        $this->path = $this->uri = $url;
174
        $this->run();
175
    }
176
177
    /**
178
     * @return Metadata
179
     */
180
    public function metadata(): Metadata
181
    {
182
        return new Metadata($this);
183
    }
184
185
    /**
186
     * clear tmp files
187
     */
188
    public function __destruct()
189
    {
190
        // make sure that FFmpeg process has benn terminated
191
        sleep(1);
192
193
        if ($this->media->isTmp()) {
194
            File::remove($this->media->getPath());
195
        }
196
197
        if ($this->tmp_dir) {
198
            File::remove($this->tmp_dir);
199
        }
200
201
        if ($this instanceof HLS && $this->tmp_key_info_file) {
202
            File::remove($this->getHlsKeyInfoFile());
203
        }
204
    }
205
}