expo-video-metadata 1.4.0 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.oxfmtrc.json +5 -0
- package/.oxlintrc.json +6 -0
- package/.yarnrc.yml +5 -1
- package/README.md +258 -28
- package/build/ExpoVideoMetadata.types.d.ts +113 -49
- package/build/ExpoVideoMetadata.types.d.ts.map +1 -1
- package/build/ExpoVideoMetadata.types.js.map +1 -1
- package/build/ExpoVideoMetadataModule.d.ts +5 -1
- package/build/ExpoVideoMetadataModule.d.ts.map +1 -1
- package/build/ExpoVideoMetadataModule.js +5 -2
- package/build/ExpoVideoMetadataModule.js.map +1 -1
- package/build/createSourceInfo.d.ts +4 -0
- package/build/createSourceInfo.d.ts.map +1 -0
- package/build/createSourceInfo.js +42 -0
- package/build/createSourceInfo.js.map +1 -0
- package/build/createSourceInfo.web.d.ts +4 -0
- package/build/createSourceInfo.web.d.ts.map +1 -0
- package/build/createSourceInfo.web.js +12 -0
- package/build/createSourceInfo.web.js.map +1 -0
- package/build/getVideoInfo.d.ts +3 -0
- package/build/getVideoInfo.d.ts.map +1 -0
- package/build/getVideoInfo.js +304 -0
- package/build/getVideoInfo.js.map +1 -0
- package/build/index.d.ts +7 -4
- package/build/index.d.ts.map +1 -1
- package/build/index.js +5 -4
- package/build/index.js.map +1 -1
- package/build/sourceInfo.d.ts +9 -0
- package/build/sourceInfo.d.ts.map +1 -0
- package/build/sourceInfo.js +35 -0
- package/build/sourceInfo.js.map +1 -0
- package/build/utils.d.ts +4 -0
- package/build/utils.d.ts.map +1 -0
- package/build/utils.js +15 -0
- package/build/utils.js.map +1 -0
- package/expo-module.config.json +1 -7
- package/package.json +36 -23
- package/src/ExpoVideoMetadata.types.ts +124 -55
- package/src/ExpoVideoMetadataModule.ts +7 -2
- package/src/createSourceInfo.ts +53 -0
- package/src/createSourceInfo.web.ts +18 -0
- package/src/getVideoInfo.ts +417 -0
- package/src/index.ts +18 -9
- package/src/sourceInfo.ts +51 -0
- package/src/utils.ts +15 -0
- package/tsconfig.json +2 -1
- package/.eslintrc.js +0 -8
- package/.prettierrc.json +0 -3
- package/android/build.gradle +0 -89
- package/android/src/main/AndroidManifest.xml +0 -2
- package/android/src/main/java/expo/modules/videometadata/Exceptions.kt +0 -9
- package/android/src/main/java/expo/modules/videometadata/ExpoVideoMetadataModule.kt +0 -253
- package/android/src/main/java/expo/modules/videometadata/VideoMetadataOptions.kt +0 -9
- package/build/ExpoVideoMetadataModule.web.d.ts +0 -34
- package/build/ExpoVideoMetadataModule.web.d.ts.map +0 -1
- package/build/ExpoVideoMetadataModule.web.js +0 -130
- package/build/ExpoVideoMetadataModule.web.js.map +0 -1
- package/ios/ExpoVideoMetadata.podspec +0 -27
- package/ios/ExpoVideoMetadataExceptions.swift +0 -7
- package/ios/ExpoVideoMetadataModule.swift +0 -159
- package/ios/ExpoVideoMetadataOptions.swift +0 -5
- package/src/ExpoVideoMetadataModule.web.ts +0 -188
- package/tea.yaml +0 -6
package/.oxfmtrc.json
ADDED
package/.oxlintrc.json
ADDED
package/.yarnrc.yml
CHANGED
package/README.md
CHANGED
|
@@ -1,55 +1,285 @@
|
|
|
1
1
|
# expo-video-metadata
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Video metadata for Expo apps, powered by [Mediabunny](https://mediabunny.dev) on iOS, Android, and web.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
This package exposes Mediabunny-style metadata for Expo and React Native:
|
|
6
|
+
format, MIME type, start/end timestamps, per-track codecs, dimensions, rotation,
|
|
7
|
+
pixel aspect ratio, display dimensions, color space, packet statistics, audio
|
|
8
|
+
properties, metadata tags, embedded images, file size, and GPS location when the
|
|
9
|
+
file contains it.
|
|
6
10
|
|
|
7
|
-
|
|
11
|
+
It is currently maintained against **Expo SDK 57**.
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
<img src="https://raw.githubusercontent.com/hirbod/expo-video-metadata/assets/preview_2026_mediabunny.png" width="800" />
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
## Install
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
```sh
|
|
18
|
+
npx expo install expo-video-metadata
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
This package does not ship custom native code. It uses Mediabunny for parsing and `expo-file-system` for efficient local file reads on iOS and Android.
|
|
22
|
+
|
|
23
|
+
For bare React Native apps, install and configure Expo modules first:
|
|
24
|
+
|
|
25
|
+
https://docs.expo.dev/bare/installing-expo-modules/
|
|
26
|
+
|
|
27
|
+
## Platform Notes
|
|
28
|
+
|
|
29
|
+
### iOS and Android
|
|
14
30
|
|
|
31
|
+
iOS and Android use Mediabunny through a small `expo-file-system` source adapter. Local `file://` and `content://` videos are read with byte-range file handle reads, so large videos do not need to be loaded fully into memory.
|
|
32
|
+
|
|
33
|
+
Remote URLs are read through Mediabunny's URL source. Request headers can be passed through the `headers` option.
|
|
34
|
+
|
|
35
|
+
On iOS, picking videos with `expo-image-picker` is fastest when you keep the original asset representation:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
preferredAssetRepresentationMode: ImagePicker.UIImagePickerPreferredAssetRepresentationMode.Current;
|
|
15
39
|
```
|
|
16
|
-
|
|
40
|
+
|
|
41
|
+
That avoids unnecessary copying or transcoding before metadata is read.
|
|
42
|
+
|
|
43
|
+
### Web
|
|
44
|
+
|
|
45
|
+
Web uses the same Mediabunny parser. It parses the media file in the browser instead of relying on `<video>` metadata events, which keeps the result shape aligned with iOS and Android.
|
|
46
|
+
|
|
47
|
+
Local web sources can be passed as `File`, `Blob`, `blob:` URLs, or `data:` URLs.
|
|
48
|
+
|
|
49
|
+
Remote web sources are read with `fetch`, so browser rules apply:
|
|
50
|
+
|
|
51
|
+
- The server must allow CORS, for example with `Access-Control-Allow-Origin`.
|
|
52
|
+
- The server should support byte-range requests with `Accept-Ranges: bytes`.
|
|
53
|
+
- If the video needs auth, pass headers through `VideoInfoOptions`.
|
|
54
|
+
|
|
55
|
+
If a remote URL works on iOS or Android but fails on web, it is usually a CORS issue. Native networking is not subject to browser CORS.
|
|
56
|
+
|
|
57
|
+
## Usage
|
|
58
|
+
|
|
59
|
+
```ts
|
|
60
|
+
import { getVideoInfoAsync } from "expo-video-metadata";
|
|
61
|
+
|
|
62
|
+
const info = await getVideoInfoAsync(videoUri);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
With headers for a remote file:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const info = await getVideoInfoAsync("https://example.com/video.mp4", {
|
|
69
|
+
headers: {
|
|
70
|
+
Authorization: "Bearer token",
|
|
71
|
+
},
|
|
72
|
+
});
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
On web, you can also pass a `File` or `Blob`:
|
|
76
|
+
|
|
77
|
+
```ts
|
|
78
|
+
const info = await getVideoInfoAsync(file);
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
When using `expo-image-picker` on web, prefer the returned `asset.file` over
|
|
82
|
+
`asset.uri`:
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
const asset = result.assets[0];
|
|
86
|
+
const info = await getVideoInfoAsync(asset.file ?? asset.uri);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Passing the `File` lets Mediabunny read only the byte ranges it needs. Passing a
|
|
90
|
+
`blob:` URL requires loading that URL back into a `Blob` first, which can be much
|
|
91
|
+
slower for large videos.
|
|
92
|
+
|
|
93
|
+
## API
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
getVideoInfoAsync(
|
|
97
|
+
source: string | File | Blob,
|
|
98
|
+
options?: {
|
|
99
|
+
headers?: Record<string, string>;
|
|
100
|
+
exactDuration?: boolean;
|
|
101
|
+
packetStatsSampleCount?: number | null;
|
|
102
|
+
includeMetadataTags?: boolean;
|
|
103
|
+
includeVideoTracks?: boolean;
|
|
104
|
+
includeAudioTracks?: boolean;
|
|
105
|
+
}
|
|
106
|
+
): Promise<VideoInfoResult>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`source` can be:
|
|
110
|
+
|
|
111
|
+
- a local `file://` or `content://` URI on iOS and Android
|
|
112
|
+
- a remote URL
|
|
113
|
+
- a `File` or `Blob` on web
|
|
114
|
+
- a `blob:` or `data:` URL on web
|
|
115
|
+
|
|
116
|
+
Base64/data URLs work on web, but they are not ideal for large videos.
|
|
117
|
+
|
|
118
|
+
By default, durations are read from metadata when possible, video and audio
|
|
119
|
+
tracks are included, packet statistics inspect the first 30 packets of each
|
|
120
|
+
track, and metadata tags are skipped. Skipping tags avoids extra reads for title,
|
|
121
|
+
artist, comments, embedded images, raw tags, and GPS location when you only need
|
|
122
|
+
technical media metadata.
|
|
123
|
+
|
|
124
|
+
Use `includeMetadataTags: true` when you need container tags or location data:
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
const info = await getVideoInfoAsync(source, {
|
|
128
|
+
includeMetadataTags: true,
|
|
129
|
+
});
|
|
17
130
|
```
|
|
18
131
|
|
|
19
|
-
|
|
132
|
+
If you only need one media kind, disable the other one:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const info = await getVideoInfoAsync(source, {
|
|
136
|
+
includeAudioTracks: false,
|
|
137
|
+
});
|
|
138
|
+
```
|
|
20
139
|
|
|
21
|
-
|
|
140
|
+
To match Mediabunny's metadata extraction demo more closely, use:
|
|
22
141
|
|
|
23
|
-
|
|
142
|
+
```ts
|
|
143
|
+
const info = await getVideoInfoAsync(source, {
|
|
144
|
+
exactDuration: true,
|
|
145
|
+
includeMetadataTags: true,
|
|
146
|
+
packetStatsSampleCount: null,
|
|
147
|
+
});
|
|
148
|
+
```
|
|
24
149
|
|
|
25
|
-
|
|
150
|
+
Those settings can scan much more of the file.
|
|
26
151
|
|
|
27
|
-
|
|
152
|
+
## Result
|
|
28
153
|
|
|
29
154
|
```ts
|
|
30
|
-
|
|
155
|
+
type VideoInfoResult = {
|
|
156
|
+
format: string;
|
|
157
|
+
mimeType: string | null;
|
|
158
|
+
start: number;
|
|
159
|
+
end: number;
|
|
160
|
+
tracks: MediaTrackInfo[];
|
|
161
|
+
metadataTags?: MetadataTagsInfo | null;
|
|
162
|
+
fileSize: number;
|
|
31
163
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
164
|
+
// Convenience fields derived from the primary video/audio tracks:
|
|
165
|
+
duration: number;
|
|
166
|
+
hasAudio: boolean;
|
|
167
|
+
isHDR: boolean | null;
|
|
168
|
+
width: number;
|
|
169
|
+
height: number;
|
|
170
|
+
fps: number;
|
|
171
|
+
bitRate: number;
|
|
172
|
+
codec: string;
|
|
173
|
+
orientation: "Portrait" | "PortraitUpsideDown" | "Landscape" | "LandscapeRight" | "LandscapeLeft";
|
|
174
|
+
naturalOrientation: "Portrait" | "Landscape";
|
|
175
|
+
aspectRatio: number;
|
|
176
|
+
is16_9: boolean;
|
|
177
|
+
audioSampleRate: number;
|
|
178
|
+
audioChannels: number;
|
|
179
|
+
audioCodec: string;
|
|
180
|
+
location: {
|
|
181
|
+
latitude: number;
|
|
182
|
+
longitude: number;
|
|
183
|
+
altitude?: number;
|
|
184
|
+
} | null;
|
|
185
|
+
};
|
|
40
186
|
|
|
41
|
-
|
|
187
|
+
type MediaTrackInfo = {
|
|
188
|
+
type: string;
|
|
189
|
+
codec: string | null;
|
|
190
|
+
codecParameterString: string | null;
|
|
191
|
+
start: number;
|
|
192
|
+
end: number;
|
|
193
|
+
languageCode: string;
|
|
194
|
+
packetStats: {
|
|
195
|
+
packetCount: number;
|
|
196
|
+
averagePacketRate: number;
|
|
197
|
+
averageBitrate: number;
|
|
198
|
+
} | null;
|
|
199
|
+
} & (
|
|
200
|
+
| {
|
|
201
|
+
type: "video";
|
|
202
|
+
codedWidth: number;
|
|
203
|
+
codedHeight: number;
|
|
204
|
+
rotation: number;
|
|
205
|
+
pixelAspectRatio: { num: number; den: number };
|
|
206
|
+
displayWidth: number;
|
|
207
|
+
displayHeight: number;
|
|
208
|
+
transparency: boolean;
|
|
209
|
+
colorSpace: {
|
|
210
|
+
primaries: string | null;
|
|
211
|
+
transfer: string | null;
|
|
212
|
+
matrix: string | null;
|
|
213
|
+
fullRange: boolean | null;
|
|
214
|
+
hdr: boolean | null;
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
| {
|
|
218
|
+
type: "audio";
|
|
219
|
+
numberOfChannels: number;
|
|
220
|
+
sampleRate: number;
|
|
221
|
+
}
|
|
222
|
+
| {}
|
|
223
|
+
);
|
|
224
|
+
|
|
225
|
+
type MetadataTagsInfo = {
|
|
226
|
+
title?: string;
|
|
227
|
+
description?: string;
|
|
228
|
+
artist?: string;
|
|
229
|
+
album?: string;
|
|
230
|
+
albumArtist?: string;
|
|
231
|
+
trackNumber?: number;
|
|
232
|
+
tracksTotal?: number;
|
|
233
|
+
discNumber?: number;
|
|
234
|
+
discsTotal?: number;
|
|
235
|
+
genre?: string;
|
|
236
|
+
date?: string;
|
|
237
|
+
lyrics?: string;
|
|
238
|
+
comment?: string;
|
|
239
|
+
images?: {
|
|
240
|
+
mimeType: string;
|
|
241
|
+
data: Uint8Array;
|
|
242
|
+
size: number;
|
|
243
|
+
}[];
|
|
244
|
+
rawTagCount?: number;
|
|
245
|
+
raw?: Record<string, unknown>;
|
|
246
|
+
};
|
|
42
247
|
```
|
|
43
248
|
|
|
44
|
-
|
|
249
|
+
Some fields depend on what the file actually exposes and what options you pass.
|
|
250
|
+
For example, `metadataTags` and `location` are only read when
|
|
251
|
+
`includeMetadataTags` is `true`, and location is only returned when the video
|
|
252
|
+
contains a readable GPS tag.
|
|
45
253
|
|
|
46
|
-
|
|
254
|
+
Codec values come directly from Mediabunny. Use `track.codec` for the short
|
|
255
|
+
codec identifier, such as `avc` or `aac`, and `track.codecParameterString` for
|
|
256
|
+
the full codec string, such as `avc1.640034` or `mp4a.40.2`. The legacy
|
|
257
|
+
convenience fields `codec` and `audioCodec` mirror the primary video and audio
|
|
258
|
+
track `codec` values.
|
|
47
259
|
|
|
48
|
-
|
|
260
|
+
## Example With Expo Image Picker
|
|
49
261
|
|
|
50
262
|
```ts
|
|
51
|
-
|
|
52
|
-
|
|
263
|
+
import * as ImagePicker from "expo-image-picker";
|
|
264
|
+
import { getVideoInfoAsync } from "expo-video-metadata";
|
|
265
|
+
|
|
266
|
+
const result = await ImagePicker.launchImageLibraryAsync({
|
|
267
|
+
mediaTypes: "videos",
|
|
268
|
+
base64: false,
|
|
269
|
+
exif: true,
|
|
270
|
+
legacy: false,
|
|
271
|
+
videoQuality: ImagePicker.UIImagePickerControllerQualityType.High,
|
|
272
|
+
preferredAssetRepresentationMode:
|
|
273
|
+
ImagePicker.UIImagePickerPreferredAssetRepresentationMode.Current,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
if (!result.canceled) {
|
|
277
|
+
const asset = result.assets[0];
|
|
278
|
+
const info = await getVideoInfoAsync(asset.file ?? asset.uri, {
|
|
279
|
+
includeMetadataTags: true,
|
|
280
|
+
});
|
|
281
|
+
console.log(info);
|
|
282
|
+
}
|
|
53
283
|
```
|
|
54
284
|
|
|
55
|
-
|
|
285
|
+
`expo-image-picker` may not expose location data unless `legacy` is enabled, even when the original video contains it.
|
|
@@ -1,66 +1,94 @@
|
|
|
1
|
+
export type PacketStatsInfo = {
|
|
2
|
+
packetCount: number;
|
|
3
|
+
averagePacketRate: number;
|
|
4
|
+
averageBitrate: number;
|
|
5
|
+
};
|
|
6
|
+
export type RationalInfo = {
|
|
7
|
+
num: number;
|
|
8
|
+
den: number;
|
|
9
|
+
};
|
|
10
|
+
export type ColorSpaceInfo = {
|
|
11
|
+
primaries: string | null;
|
|
12
|
+
transfer: string | null;
|
|
13
|
+
matrix: string | null;
|
|
14
|
+
fullRange: boolean | null;
|
|
15
|
+
hdr: boolean | null;
|
|
16
|
+
};
|
|
17
|
+
export type MetadataImageInfo = {
|
|
18
|
+
mimeType: string;
|
|
19
|
+
data: Uint8Array;
|
|
20
|
+
size: number;
|
|
21
|
+
};
|
|
22
|
+
export type MetadataTagsInfo = {
|
|
23
|
+
title?: string;
|
|
24
|
+
description?: string;
|
|
25
|
+
artist?: string;
|
|
26
|
+
album?: string;
|
|
27
|
+
albumArtist?: string;
|
|
28
|
+
trackNumber?: number;
|
|
29
|
+
tracksTotal?: number;
|
|
30
|
+
discNumber?: number;
|
|
31
|
+
discsTotal?: number;
|
|
32
|
+
genre?: string;
|
|
33
|
+
date?: string;
|
|
34
|
+
lyrics?: string;
|
|
35
|
+
comment?: string;
|
|
36
|
+
images?: MetadataImageInfo[];
|
|
37
|
+
rawTagCount?: number;
|
|
38
|
+
raw?: Record<string, unknown>;
|
|
39
|
+
};
|
|
40
|
+
export type BaseTrackInfo = {
|
|
41
|
+
type: string;
|
|
42
|
+
codec: string | null;
|
|
43
|
+
codecParameterString: string | null;
|
|
44
|
+
start: number;
|
|
45
|
+
end: number;
|
|
46
|
+
languageCode: string;
|
|
47
|
+
packetStats: PacketStatsInfo | null;
|
|
48
|
+
};
|
|
49
|
+
export type VideoTrackInfo = BaseTrackInfo & {
|
|
50
|
+
type: "video";
|
|
51
|
+
codedWidth: number;
|
|
52
|
+
codedHeight: number;
|
|
53
|
+
rotation: number;
|
|
54
|
+
pixelAspectRatio: RationalInfo;
|
|
55
|
+
displayWidth: number;
|
|
56
|
+
displayHeight: number;
|
|
57
|
+
transparency: boolean;
|
|
58
|
+
colorSpace: ColorSpaceInfo;
|
|
59
|
+
};
|
|
60
|
+
export type AudioTrackInfo = BaseTrackInfo & {
|
|
61
|
+
type: "audio";
|
|
62
|
+
numberOfChannels: number;
|
|
63
|
+
sampleRate: number;
|
|
64
|
+
};
|
|
65
|
+
export type MediaTrackInfo = BaseTrackInfo | VideoTrackInfo | AudioTrackInfo;
|
|
1
66
|
export type VideoInfoResult = {
|
|
67
|
+
format: string;
|
|
68
|
+
mimeType: string | null;
|
|
69
|
+
start: number;
|
|
70
|
+
end: number;
|
|
71
|
+
tracks: MediaTrackInfo[];
|
|
72
|
+
metadataTags?: MetadataTagsInfo | null;
|
|
73
|
+
fileSize: number;
|
|
2
74
|
/**
|
|
3
|
-
*
|
|
75
|
+
* Legacy convenience fields derived from the primary video and audio tracks.
|
|
4
76
|
*/
|
|
5
77
|
duration: number;
|
|
6
|
-
/**
|
|
7
|
-
* Tells if the video has a audio track. If the video has no audio track, its considered a mute video.
|
|
8
|
-
*/
|
|
9
78
|
hasAudio: boolean;
|
|
10
|
-
/**
|
|
11
|
-
* Available only on iOS >= 14 and Android. Tells if the video is a HDR video.
|
|
12
|
-
* Will return null if it could not be determined. (e.g. on Web or on older iOS/Android versions)
|
|
13
|
-
*/
|
|
14
79
|
isHDR: boolean | null;
|
|
15
|
-
/**
|
|
16
|
-
* Width of the video in pixels.
|
|
17
|
-
*/
|
|
18
80
|
width: number;
|
|
19
|
-
/**
|
|
20
|
-
* Height of the video in pixels.
|
|
21
|
-
*/
|
|
22
81
|
height: number;
|
|
23
|
-
/**
|
|
24
|
-
* Frame rate of the video in frames per second.
|
|
25
|
-
* Works on iOS, Android and Web (except Safari).
|
|
26
|
-
*/
|
|
27
82
|
fps: number;
|
|
28
|
-
/**
|
|
29
|
-
* Bit rate of the video in bits per second.
|
|
30
|
-
* Supported on all platforms.
|
|
31
|
-
*/
|
|
32
83
|
bitRate: number;
|
|
33
|
-
/**
|
|
34
|
-
* File size of the video in bytes. Works only for local files, returns 0 for remote files.
|
|
35
|
-
* Supported on all platforms.
|
|
36
|
-
*/
|
|
37
|
-
fileSize: number;
|
|
38
|
-
/**
|
|
39
|
-
* Video codec.
|
|
40
|
-
* Supported on all platforms, but on Web it may return an empty string.
|
|
41
|
-
*/
|
|
42
84
|
codec: string;
|
|
43
|
-
/**
|
|
44
|
-
* Video orientation.
|
|
45
|
-
* Supported on all platforms, but on Web it may return an empty string.
|
|
46
|
-
*/
|
|
47
85
|
orientation: "Portrait" | "PortraitUpsideDown" | "Landscape" | "LandscapeRight" | "LandscapeLeft";
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
86
|
+
naturalOrientation: "Portrait" | "Landscape";
|
|
87
|
+
aspectRatio: number;
|
|
88
|
+
is16_9: boolean;
|
|
51
89
|
audioSampleRate: number;
|
|
52
|
-
/**
|
|
53
|
-
* Audio channel count of the video.
|
|
54
|
-
*/
|
|
55
90
|
audioChannels: number;
|
|
56
|
-
/**
|
|
57
|
-
* Audio codec of the video.
|
|
58
|
-
*/
|
|
59
91
|
audioCodec: string;
|
|
60
|
-
/**
|
|
61
|
-
* Location where the video was recorded.
|
|
62
|
-
* Supported on iOS and Android (if the video contains location metadata)
|
|
63
|
-
*/
|
|
64
92
|
location: {
|
|
65
93
|
latitude: number;
|
|
66
94
|
longitude: number;
|
|
@@ -70,8 +98,44 @@ export type VideoInfoResult = {
|
|
|
70
98
|
export type VideoSource = string | File | Blob;
|
|
71
99
|
export type VideoInfoOptions = {
|
|
72
100
|
/**
|
|
73
|
-
* In case `
|
|
101
|
+
* In case `source` is a remote URI, `headers` object is passed in network requests.
|
|
74
102
|
*/
|
|
75
103
|
headers?: Record<string, string>;
|
|
104
|
+
/**
|
|
105
|
+
* Set to `true` to compute exact durations by scanning packet timing when
|
|
106
|
+
* metadata duration is unavailable or approximate.
|
|
107
|
+
*
|
|
108
|
+
* Defaults to `false` for faster metadata resolution.
|
|
109
|
+
*/
|
|
110
|
+
exactDuration?: boolean;
|
|
111
|
+
/**
|
|
112
|
+
* Number of packets to inspect for packet statistics. Use `null` to scan the
|
|
113
|
+
* full track, matching Mediabunny's metadata extraction demo exactly.
|
|
114
|
+
*
|
|
115
|
+
* Defaults to `30`.
|
|
116
|
+
*/
|
|
117
|
+
packetStatsSampleCount?: number | null;
|
|
118
|
+
/**
|
|
119
|
+
* Include container metadata tags such as title, artist, comments, embedded
|
|
120
|
+
* images, raw tags, and GPS location.
|
|
121
|
+
*
|
|
122
|
+
* Defaults to `false` because tag parsing can require extra reads and is not
|
|
123
|
+
* needed for basic technical video metadata.
|
|
124
|
+
*/
|
|
125
|
+
includeMetadataTags?: boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Include video tracks in the returned `tracks` array and derived video
|
|
128
|
+
* convenience fields.
|
|
129
|
+
*
|
|
130
|
+
* Defaults to `true`.
|
|
131
|
+
*/
|
|
132
|
+
includeVideoTracks?: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Include audio tracks in the returned `tracks` array and derived audio
|
|
135
|
+
* convenience fields.
|
|
136
|
+
*
|
|
137
|
+
* Defaults to `true`.
|
|
138
|
+
*/
|
|
139
|
+
includeAudioTracks?: boolean;
|
|
76
140
|
};
|
|
77
141
|
//# sourceMappingURL=ExpoVideoMetadata.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoVideoMetadata.types.d.ts","sourceRoot":"","sources":["../src/ExpoVideoMetadata.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B
|
|
1
|
+
{"version":3,"file":"ExpoVideoMetadata.types.d.ts","sourceRoot":"","sources":["../src/ExpoVideoMetadata.types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GAAG;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;CACb,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAC1B,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,iBAAiB,EAAE,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,eAAe,GAAG,IAAI,CAAC;CACrC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG;IAC3C,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,gBAAgB,EAAE,YAAY,CAAC;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,OAAO,CAAC;IACtB,UAAU,EAAE,cAAc,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG;IAC3C,IAAI,EAAE,OAAO,CAAC;IACd,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,cAAc,GAAG,cAAc,CAAC;AAE7E,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,cAAc,EAAE,CAAC;IACzB,YAAY,CAAC,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACvC,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,UAAU,GAAG,oBAAoB,GAAG,WAAW,GAAG,gBAAgB,GAAG,eAAe,CAAC;IAClG,kBAAkB,EAAE,UAAU,GAAG,WAAW,CAAC;IAC7C,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,OAAO,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,IAAI,CAAC;CACV,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;AAE/C,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;;;;OAKG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;OAKG;IACH,sBAAsB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvC;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoVideoMetadata.types.js","sourceRoot":"","sources":["../src/ExpoVideoMetadata.types.ts"],"names":[],"mappings":"","sourcesContent":["export type
|
|
1
|
+
{"version":3,"file":"ExpoVideoMetadata.types.js","sourceRoot":"","sources":["../src/ExpoVideoMetadata.types.ts"],"names":[],"mappings":"","sourcesContent":["export type PacketStatsInfo = {\n packetCount: number;\n averagePacketRate: number;\n averageBitrate: number;\n};\n\nexport type RationalInfo = {\n num: number;\n den: number;\n};\n\nexport type ColorSpaceInfo = {\n primaries: string | null;\n transfer: string | null;\n matrix: string | null;\n fullRange: boolean | null;\n hdr: boolean | null;\n};\n\nexport type MetadataImageInfo = {\n mimeType: string;\n data: Uint8Array;\n size: number;\n};\n\nexport type MetadataTagsInfo = {\n title?: string;\n description?: string;\n artist?: string;\n album?: string;\n albumArtist?: string;\n trackNumber?: number;\n tracksTotal?: number;\n discNumber?: number;\n discsTotal?: number;\n genre?: string;\n date?: string;\n lyrics?: string;\n comment?: string;\n images?: MetadataImageInfo[];\n rawTagCount?: number;\n raw?: Record<string, unknown>;\n};\n\nexport type BaseTrackInfo = {\n type: string;\n codec: string | null;\n codecParameterString: string | null;\n start: number;\n end: number;\n languageCode: string;\n packetStats: PacketStatsInfo | null;\n};\n\nexport type VideoTrackInfo = BaseTrackInfo & {\n type: \"video\";\n codedWidth: number;\n codedHeight: number;\n rotation: number;\n pixelAspectRatio: RationalInfo;\n displayWidth: number;\n displayHeight: number;\n transparency: boolean;\n colorSpace: ColorSpaceInfo;\n};\n\nexport type AudioTrackInfo = BaseTrackInfo & {\n type: \"audio\";\n numberOfChannels: number;\n sampleRate: number;\n};\n\nexport type MediaTrackInfo = BaseTrackInfo | VideoTrackInfo | AudioTrackInfo;\n\nexport type VideoInfoResult = {\n format: string;\n mimeType: string | null;\n start: number;\n end: number;\n tracks: MediaTrackInfo[];\n metadataTags?: MetadataTagsInfo | null;\n fileSize: number;\n\n /**\n * Legacy convenience fields derived from the primary video and audio tracks.\n */\n duration: number;\n hasAudio: boolean;\n isHDR: boolean | null;\n width: number;\n height: number;\n fps: number;\n bitRate: number;\n codec: string;\n orientation: \"Portrait\" | \"PortraitUpsideDown\" | \"Landscape\" | \"LandscapeRight\" | \"LandscapeLeft\";\n naturalOrientation: \"Portrait\" | \"Landscape\";\n aspectRatio: number;\n is16_9: boolean;\n audioSampleRate: number;\n audioChannels: number;\n audioCodec: string;\n location: {\n latitude: number;\n longitude: number;\n altitude?: number;\n } | null;\n};\n\nexport type VideoSource = string | File | Blob;\n\nexport type VideoInfoOptions = {\n /**\n * In case `source` is a remote URI, `headers` object is passed in network requests.\n */\n headers?: Record<string, string>;\n /**\n * Set to `true` to compute exact durations by scanning packet timing when\n * metadata duration is unavailable or approximate.\n *\n * Defaults to `false` for faster metadata resolution.\n */\n exactDuration?: boolean;\n /**\n * Number of packets to inspect for packet statistics. Use `null` to scan the\n * full track, matching Mediabunny's metadata extraction demo exactly.\n *\n * Defaults to `30`.\n */\n packetStatsSampleCount?: number | null;\n /**\n * Include container metadata tags such as title, artist, comments, embedded\n * images, raw tags, and GPS location.\n *\n * Defaults to `false` because tag parsing can require extra reads and is not\n * needed for basic technical video metadata.\n */\n includeMetadataTags?: boolean;\n /**\n * Include video tracks in the returned `tracks` array and derived video\n * convenience fields.\n *\n * Defaults to `true`.\n */\n includeVideoTracks?: boolean;\n /**\n * Include audio tracks in the returned `tracks` array and derived audio\n * convenience fields.\n *\n * Defaults to `true`.\n */\n includeAudioTracks?: boolean;\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoVideoMetadataModule.d.ts","sourceRoot":"","sources":["../src/ExpoVideoMetadataModule.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpoVideoMetadataModule.d.ts","sourceRoot":"","sources":["../src/ExpoVideoMetadataModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;;;;;AAE9C,wBAIE"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default
|
|
1
|
+
import { getVideoInfo } from "./getVideoInfo";
|
|
2
|
+
export default {
|
|
3
|
+
name: "ExpoVideoMetadata",
|
|
4
|
+
getVideoInfo,
|
|
5
|
+
};
|
|
3
6
|
//# sourceMappingURL=ExpoVideoMetadataModule.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoVideoMetadataModule.js","sourceRoot":"","sources":["../src/ExpoVideoMetadataModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ExpoVideoMetadataModule.js","sourceRoot":"","sources":["../src/ExpoVideoMetadataModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,eAAe;IACb,IAAI,EAAE,mBAAmB;IAEzB,YAAY;CACb,CAAC","sourcesContent":["import { getVideoInfo } from \"./getVideoInfo\";\n\nexport default {\n name: \"ExpoVideoMetadata\",\n\n getVideoInfo,\n};\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { VideoInfoOptions, VideoSource } from "./ExpoVideoMetadata.types";
|
|
2
|
+
import { type SourceInfo } from "./sourceInfo";
|
|
3
|
+
export declare function createSourceInfo(source: VideoSource, options: VideoInfoOptions): Promise<SourceInfo>;
|
|
4
|
+
//# sourceMappingURL=createSourceInfo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSourceInfo.d.ts","sourceRoot":"","sources":["../src/createSourceInfo.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC/E,OAAO,EAA6C,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AA8B1F,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,UAAU,CAAC,CAerB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { File, FileMode } from "expo-file-system";
|
|
2
|
+
import { StreamSource } from "mediabunny";
|
|
3
|
+
import { createBlobSourceInfo, createUrlSourceInfo } from "./sourceInfo";
|
|
4
|
+
import { isLocalFileSource } from "./utils";
|
|
5
|
+
function createFileSystemSourceInfo(file) {
|
|
6
|
+
let handle = null;
|
|
7
|
+
const fileSize = file.size;
|
|
8
|
+
const getHandle = () => {
|
|
9
|
+
handle ??= file.open(FileMode.ReadOnly);
|
|
10
|
+
return handle;
|
|
11
|
+
};
|
|
12
|
+
return {
|
|
13
|
+
source: new StreamSource({
|
|
14
|
+
getSize: () => fileSize,
|
|
15
|
+
read: (start, end) => {
|
|
16
|
+
const currentHandle = getHandle();
|
|
17
|
+
currentHandle.offset = start;
|
|
18
|
+
return currentHandle.readBytes(end - start);
|
|
19
|
+
},
|
|
20
|
+
dispose: () => {
|
|
21
|
+
handle?.close();
|
|
22
|
+
handle = null;
|
|
23
|
+
},
|
|
24
|
+
prefetchProfile: "fileSystem",
|
|
25
|
+
}),
|
|
26
|
+
fileSize,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
export async function createSourceInfo(source, options) {
|
|
30
|
+
const blobSourceInfo = await createBlobSourceInfo(source);
|
|
31
|
+
if (blobSourceInfo) {
|
|
32
|
+
return blobSourceInfo;
|
|
33
|
+
}
|
|
34
|
+
if (typeof source === "string" && isLocalFileSource(source)) {
|
|
35
|
+
return createFileSystemSourceInfo(new File(source));
|
|
36
|
+
}
|
|
37
|
+
if (typeof source === "string") {
|
|
38
|
+
return await createUrlSourceInfo(source, options);
|
|
39
|
+
}
|
|
40
|
+
throw new TypeError("Unsupported video source.");
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=createSourceInfo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSourceInfo.js","sourceRoot":"","sources":["../src/createSourceInfo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAmB,MAAM,kBAAkB,CAAC;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG1C,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAmB,MAAM,cAAc,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAE5C,SAAS,0BAA0B,CAAC,IAAU;IAC5C,IAAI,MAAM,GAAsB,IAAI,CAAC;IACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC;IAE3B,MAAM,SAAS,GAAG,GAAG,EAAE;QACrB,MAAM,KAAK,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACxC,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,OAAO;QACL,MAAM,EAAE,IAAI,YAAY,CAAC;YACvB,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ;YACvB,IAAI,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;gBACnB,MAAM,aAAa,GAAG,SAAS,EAAE,CAAC;gBAClC,aAAa,CAAC,MAAM,GAAG,KAAK,CAAC;gBAC7B,OAAO,aAAa,CAAC,SAAS,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;YAC9C,CAAC;YACD,OAAO,EAAE,GAAG,EAAE;gBACZ,MAAM,EAAE,KAAK,EAAE,CAAC;gBAChB,MAAM,GAAG,IAAI,CAAC;YAChB,CAAC;YACD,eAAe,EAAE,YAAY;SAC9B,CAAC;QACF,QAAQ;KACT,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,MAAmB,EACnB,OAAyB;IAEzB,MAAM,cAAc,GAAG,MAAM,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC1D,IAAI,cAAc,EAAE,CAAC;QACnB,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,iBAAiB,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5D,OAAO,0BAA0B,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,MAAM,mBAAmB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,IAAI,SAAS,CAAC,2BAA2B,CAAC,CAAC;AACnD,CAAC","sourcesContent":["import { File, FileMode, type FileHandle } from \"expo-file-system\";\nimport { StreamSource } from \"mediabunny\";\n\nimport type { VideoInfoOptions, VideoSource } from \"./ExpoVideoMetadata.types\";\nimport { createBlobSourceInfo, createUrlSourceInfo, type SourceInfo } from \"./sourceInfo\";\nimport { isLocalFileSource } from \"./utils\";\n\nfunction createFileSystemSourceInfo(file: File): SourceInfo {\n let handle: FileHandle | null = null;\n const fileSize = file.size;\n\n const getHandle = () => {\n handle ??= file.open(FileMode.ReadOnly);\n return handle;\n };\n\n return {\n source: new StreamSource({\n getSize: () => fileSize,\n read: (start, end) => {\n const currentHandle = getHandle();\n currentHandle.offset = start;\n return currentHandle.readBytes(end - start);\n },\n dispose: () => {\n handle?.close();\n handle = null;\n },\n prefetchProfile: \"fileSystem\",\n }),\n fileSize,\n };\n}\n\nexport async function createSourceInfo(\n source: VideoSource,\n options: VideoInfoOptions\n): Promise<SourceInfo> {\n const blobSourceInfo = await createBlobSourceInfo(source);\n if (blobSourceInfo) {\n return blobSourceInfo;\n }\n\n if (typeof source === \"string\" && isLocalFileSource(source)) {\n return createFileSystemSourceInfo(new File(source));\n }\n\n if (typeof source === \"string\") {\n return await createUrlSourceInfo(source, options);\n }\n\n throw new TypeError(\"Unsupported video source.\");\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { VideoInfoOptions, VideoSource } from "./ExpoVideoMetadata.types";
|
|
2
|
+
import { type SourceInfo } from "./sourceInfo";
|
|
3
|
+
export declare function createSourceInfo(source: VideoSource, options: VideoInfoOptions): Promise<SourceInfo>;
|
|
4
|
+
//# sourceMappingURL=createSourceInfo.web.d.ts.map
|