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 | |||||
13 | namespace Streaming; |
||||
14 | |||||
15 | |||||
16 | use FFMpeg\FFProbe\DataMapping\Format; |
||||
17 | use FFMpeg\FFProbe\DataMapping\Stream as VideoStream; |
||||
18 | use FFMpeg\FFProbe\DataMapping\StreamCollection; |
||||
19 | use Streaming\Exception\InvalidArgumentException; |
||||
20 | |||||
21 | class Metadata |
||||
22 | { |
||||
23 | /** @var Stream */ |
||||
24 | private $stream; |
||||
25 | |||||
26 | /** @var \FFMpeg\FFProbe\DataMapping\Format */ |
||||
27 | private $format; |
||||
28 | |||||
29 | /** @var \FFMpeg\FFProbe\DataMapping\StreamCollection */ |
||||
30 | private $video_streams; |
||||
31 | |||||
32 | /** |
||||
33 | * Metadata constructor. |
||||
34 | * @param Stream $stream |
||||
35 | */ |
||||
36 | public function __construct(Stream $stream) |
||||
37 | { |
||||
38 | $this->stream = $stream; |
||||
39 | $this->format = $stream->getMedia()->getFormat(); |
||||
0 ignored issues
–
show
|
|||||
40 | $this->video_streams = $stream->getMedia()->getStreams(); |
||||
0 ignored issues
–
show
It seems like
$stream->getMedia()->getStreams() of type FFMpeg\Media\Video or Streaming\Media is incompatible with the declared type FFMpeg\FFProbe\DataMapping\StreamCollection of property $video_streams .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||||
41 | } |
||||
42 | |||||
43 | /** |
||||
44 | * @return \FFMpeg\FFProbe\DataMapping\Format |
||||
45 | */ |
||||
46 | public function getFormat(): Format |
||||
47 | { |
||||
48 | return $this->format; |
||||
49 | } |
||||
50 | |||||
51 | /** |
||||
52 | * @return \FFMpeg\FFProbe\DataMapping\StreamCollection |
||||
53 | */ |
||||
54 | public function getVideoStreams(): StreamCollection |
||||
55 | { |
||||
56 | return $this->video_streams; |
||||
57 | } |
||||
58 | |||||
59 | /** |
||||
60 | * @param VideoStream $stream |
||||
61 | * @return array |
||||
62 | */ |
||||
63 | private function streamToArray(VideoStream $stream): array |
||||
64 | { |
||||
65 | return $stream->all(); |
||||
66 | } |
||||
67 | |||||
68 | /** |
||||
69 | * @return mixed |
||||
70 | */ |
||||
71 | private function getVideoMetadata(): array |
||||
72 | { |
||||
73 | return [ |
||||
74 | 'format' => $this->getFormat()->all(), |
||||
75 | 'streams' => array_map([$this, 'streamToArray'], $this->getVideoStreams()->all()) |
||||
76 | ]; |
||||
77 | } |
||||
78 | |||||
79 | /** |
||||
80 | * @param Representation $rep |
||||
81 | * @return array |
||||
82 | */ |
||||
83 | private function repToArray(Representation $rep): array |
||||
84 | { |
||||
85 | return [ |
||||
86 | "dimension" => strtoupper($rep->size2string()), |
||||
87 | "video_kilo_bitrate" => $rep->getKiloBitrate(), |
||||
88 | "audio_kilo_bitrate" => $rep->getAudioKiloBitrate() ?? "Not specified" |
||||
89 | ]; |
||||
90 | } |
||||
91 | |||||
92 | /** |
||||
93 | * @return array |
||||
94 | */ |
||||
95 | private function getResolutions(): array |
||||
96 | { |
||||
97 | if (!method_exists($this->stream, 'getRepresentations')) { |
||||
98 | return []; |
||||
99 | } |
||||
100 | |||||
101 | return array_map([$this, 'repToArray'], $this->stream->getRepresentations()->all()); |
||||
102 | } |
||||
103 | |||||
104 | |||||
105 | /** |
||||
106 | * @return array |
||||
107 | */ |
||||
108 | public function getStreamsMetadata(): array |
||||
109 | { |
||||
110 | $dirname = $this->stream->pathInfo(PATHINFO_DIRNAME); |
||||
111 | $basename = $this->stream->pathInfo(PATHINFO_BASENAME); |
||||
112 | $filename = $dirname . DIRECTORY_SEPARATOR . $basename; |
||||
113 | |||||
114 | $technique = explode("\\", get_class($this->stream)); |
||||
115 | $format = explode("\\", get_class($this->stream->getFormat())); |
||||
116 | |||||
117 | $metadata = [ |
||||
118 | "filename" => $filename, |
||||
119 | "size_of_stream_dir" => File::directorySize($dirname), |
||||
120 | "created_at" => file_exists($filename) ? date("Y-m-d H:i:s", filemtime($filename)) : 'The file has been deleted', |
||||
121 | "resolutions" => $this->getResolutions(), |
||||
122 | "format" => end($format), |
||||
123 | "streaming_technique" => end($technique) |
||||
124 | ]; |
||||
125 | |||||
126 | if ($this->stream instanceof DASH) { |
||||
127 | $metadata = array_merge($metadata, ["seg_duration" => $this->stream->getSegDuration()]); |
||||
128 | } elseif ($this->stream instanceof HLS) { |
||||
129 | $metadata = array_merge( |
||||
130 | $metadata, |
||||
131 | [ |
||||
132 | "hls_time" => (int)$this->stream->getHlsTime(), |
||||
133 | "hls_cache" => (bool)$this->stream->isHlsAllowCache(), |
||||
134 | "encrypted_hls" => (bool)$this->stream->getHlsKeyInfoFile(), |
||||
135 | "ts_sub_directory" => $this->stream->getSegSubDirectory(), |
||||
136 | "base_url" => $this->stream->getHlsBaseUrl() |
||||
137 | ] |
||||
138 | ); |
||||
139 | } |
||||
140 | |||||
141 | return $metadata; |
||||
142 | } |
||||
143 | |||||
144 | /** |
||||
145 | * @return array |
||||
146 | */ |
||||
147 | public function get(): array |
||||
148 | { |
||||
149 | return [ |
||||
150 | "video" => $this->getVideoMetadata(), |
||||
151 | "stream" => $this->getStreamsMetadata() |
||||
152 | ]; |
||||
153 | } |
||||
154 | |||||
155 | /** |
||||
156 | * @param null $opts |
||||
0 ignored issues
–
show
|
|||||
157 | * @return string |
||||
158 | */ |
||||
159 | public function getJson($opts = null): string |
||||
160 | { |
||||
161 | return json_encode($this->get(), $opts ?? JSON_PRETTY_PRINT); |
||||
162 | } |
||||
163 | |||||
164 | /** |
||||
165 | * @param string $filename |
||||
166 | * @param int $opts |
||||
167 | * @return string |
||||
168 | */ |
||||
169 | public function saveAsJson(string $filename = null, int $opts = null): string |
||||
170 | { |
||||
171 | if (is_null($filename)) { |
||||
172 | if ($this->stream->isTmpDir()) { |
||||
173 | throw new InvalidArgumentException("It is a temp directory! It is not possible to save it"); |
||||
174 | } |
||||
175 | |||||
176 | $name = uniqid(($this->stream->pathInfo(PATHINFO_FILENAME) ?? "meta") . "-") . ".json"; |
||||
177 | $filename = $this->stream->pathInfo(PATHINFO_DIRNAME) . DIRECTORY_SEPARATOR . $name; |
||||
178 | } |
||||
179 | File::put($filename, $this->getJson($opts)); |
||||
0 ignored issues
–
show
It seems like
$opts can also be of type integer ; however, parameter $opts of Streaming\Metadata::getJson() does only seem to accept null , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
180 | |||||
181 | return $filename; |
||||
182 | } |
||||
183 | |||||
184 | /** |
||||
185 | * @param string|null $save_to |
||||
186 | * @param int|null $opts |
||||
187 | * @return array |
||||
188 | */ |
||||
189 | public function export(string $save_to = null, int $opts = null): array |
||||
190 | { |
||||
191 | return array_merge($this->get(), ['filename' => $this->saveAsJson($save_to, $opts)]); |
||||
192 | } |
||||
193 | } |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..