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.
Files changed (63) hide show
  1. package/.oxfmtrc.json +5 -0
  2. package/.oxlintrc.json +6 -0
  3. package/.yarnrc.yml +5 -1
  4. package/README.md +258 -28
  5. package/build/ExpoVideoMetadata.types.d.ts +113 -49
  6. package/build/ExpoVideoMetadata.types.d.ts.map +1 -1
  7. package/build/ExpoVideoMetadata.types.js.map +1 -1
  8. package/build/ExpoVideoMetadataModule.d.ts +5 -1
  9. package/build/ExpoVideoMetadataModule.d.ts.map +1 -1
  10. package/build/ExpoVideoMetadataModule.js +5 -2
  11. package/build/ExpoVideoMetadataModule.js.map +1 -1
  12. package/build/createSourceInfo.d.ts +4 -0
  13. package/build/createSourceInfo.d.ts.map +1 -0
  14. package/build/createSourceInfo.js +42 -0
  15. package/build/createSourceInfo.js.map +1 -0
  16. package/build/createSourceInfo.web.d.ts +4 -0
  17. package/build/createSourceInfo.web.d.ts.map +1 -0
  18. package/build/createSourceInfo.web.js +12 -0
  19. package/build/createSourceInfo.web.js.map +1 -0
  20. package/build/getVideoInfo.d.ts +3 -0
  21. package/build/getVideoInfo.d.ts.map +1 -0
  22. package/build/getVideoInfo.js +304 -0
  23. package/build/getVideoInfo.js.map +1 -0
  24. package/build/index.d.ts +7 -4
  25. package/build/index.d.ts.map +1 -1
  26. package/build/index.js +5 -4
  27. package/build/index.js.map +1 -1
  28. package/build/sourceInfo.d.ts +9 -0
  29. package/build/sourceInfo.d.ts.map +1 -0
  30. package/build/sourceInfo.js +35 -0
  31. package/build/sourceInfo.js.map +1 -0
  32. package/build/utils.d.ts +4 -0
  33. package/build/utils.d.ts.map +1 -0
  34. package/build/utils.js +15 -0
  35. package/build/utils.js.map +1 -0
  36. package/expo-module.config.json +1 -7
  37. package/package.json +36 -23
  38. package/src/ExpoVideoMetadata.types.ts +124 -55
  39. package/src/ExpoVideoMetadataModule.ts +7 -2
  40. package/src/createSourceInfo.ts +53 -0
  41. package/src/createSourceInfo.web.ts +18 -0
  42. package/src/getVideoInfo.ts +417 -0
  43. package/src/index.ts +18 -9
  44. package/src/sourceInfo.ts +51 -0
  45. package/src/utils.ts +15 -0
  46. package/tsconfig.json +2 -1
  47. package/.eslintrc.js +0 -8
  48. package/.prettierrc.json +0 -3
  49. package/android/build.gradle +0 -89
  50. package/android/src/main/AndroidManifest.xml +0 -2
  51. package/android/src/main/java/expo/modules/videometadata/Exceptions.kt +0 -9
  52. package/android/src/main/java/expo/modules/videometadata/ExpoVideoMetadataModule.kt +0 -253
  53. package/android/src/main/java/expo/modules/videometadata/VideoMetadataOptions.kt +0 -9
  54. package/build/ExpoVideoMetadataModule.web.d.ts +0 -34
  55. package/build/ExpoVideoMetadataModule.web.d.ts.map +0 -1
  56. package/build/ExpoVideoMetadataModule.web.js +0 -130
  57. package/build/ExpoVideoMetadataModule.web.js.map +0 -1
  58. package/ios/ExpoVideoMetadata.podspec +0 -27
  59. package/ios/ExpoVideoMetadataExceptions.swift +0 -7
  60. package/ios/ExpoVideoMetadataModule.swift +0 -159
  61. package/ios/ExpoVideoMetadataOptions.swift +0 -5
  62. package/src/ExpoVideoMetadataModule.web.ts +0 -188
  63. package/tea.yaml +0 -6
package/.oxfmtrc.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "$schema": "./node_modules/oxfmt/configuration_schema.json",
3
+ "trailingComma": "es5",
4
+ "ignorePatterns": ["build/**", "ios/**", "android/**", "example/ios/**", "example/android/**"]
5
+ }
package/.oxlintrc.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "./node_modules/oxlint/configuration_schema.json",
3
+ "env": {
4
+ "builtin": true
5
+ }
6
+ }
package/.yarnrc.yml CHANGED
@@ -1,3 +1,7 @@
1
+ enableScripts: true
2
+
1
3
  nodeLinker: node-modules
2
4
 
3
- yarnPath: .yarn/releases/yarn-4.5.1.cjs
5
+ npmMinimalAgeGate: 2d
6
+
7
+ yarnPath: .yarn/releases/yarn-4.15.0.cjs
package/README.md CHANGED
@@ -1,55 +1,285 @@
1
1
  # expo-video-metadata
2
2
 
3
- This React Native (Expo) library provides a versatile function designed to extract a wide range of metadata from video files, including duration, width, height, frame rate, codec, audio availability, orientation, audio channels, audio codec, and audio sample rate. For comprehensive details, please refer to the listed exported types. Although the library is equipped with web support, its performance is reliant on specific platform APIs, leading to potential variability in its effectiveness across different browsers.
3
+ Video metadata for Expo apps, powered by [Mediabunny](https://mediabunny.dev) on iOS, Android, and web.
4
4
 
5
- <img src="https://raw.githubusercontent.com/hirbod/expo-video-metadata/assets/preview.png" width="500" />
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
- # Installation in bare React Native projects
11
+ It is currently maintained against **Expo SDK 57**.
8
12
 
9
- This package needs **Expo SDK 50** or **higher**, as it uses FileSystem APIs that were added in that version. This package adds native code to your project and does not work with Expo Go. Please use a custom dev client or build a standalone app. Works with Fabric. Needs RN 0.73+ (Java JDK 17)
13
+ <img src="https://raw.githubusercontent.com/hirbod/expo-video-metadata/assets/preview_2026_mediabunny.png" width="800" />
10
14
 
11
- For bare React Native projects, you must ensure that you have [installed and configured the `expo` package](https://docs.expo.dev/bare/installing-expo-modules/) before continuing (SDK 50+). This just adds ~150KB to your final app size and is the easiest way to get started and it works with and without Expo projects.
15
+ ## Install
12
16
 
13
- ### Add the package to your npm dependencies
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
- npx expo install expo-video-metadata
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
- ### Configure for iOS
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
- Run `npx pod-install` after installing the npm package.
140
+ To match Mediabunny's metadata extraction demo more closely, use:
22
141
 
23
- ### Configure for Android
142
+ ```ts
143
+ const info = await getVideoInfoAsync(source, {
144
+ exactDuration: true,
145
+ includeMetadataTags: true,
146
+ packetStatsSampleCount: null,
147
+ });
148
+ ```
24
149
 
25
- No additional set up necessary.
150
+ Those settings can scan much more of the file.
26
151
 
27
- # API
152
+ ## Result
28
153
 
29
154
  ```ts
30
- import { getVideoInfoAsync } from 'expo-video-metadata';
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
- * Retrieves video metadata.
34
- *
35
- * @param sourceFilename An URI of the video, local or remote. On web, it can be a File or Blob object, too. base64 URIs are supported but not recommended, as they can be very large and cause performance issues.
36
- * @param options Pass `headers` object in case `sourceFilename` is a remote URI, e.g { headers: "Authorization": "Bearer some-token" } etc.
37
- *
38
- * @return Returns a promise which fulfils with [`VideoInfoResult`](#Videoinforesult).
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
- const result = await getVideoInfoAsync(sourceFilename: string | File | Blob, options: VideoInfoOptions = {}): Promise<VideoInfoResult>
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
- See [VideoInfoResult](https://github.com/hirbod/expo-video-metadata/blob/main/src/ExpoVideoMetadata.types.ts#L1) type for more information.
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
- ## Hints
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
- If you're using libraries like expo-image-picker, make sure to use [preferredAssetRepresentationMode](https://docs.expo.dev/versions/latest/sdk/imagepicker/#imagepickeroptions) option like this:
260
+ ## Example With Expo Image Picker
49
261
 
50
262
  ```ts
51
- preferredAssetRepresentationMode: ImagePicker
52
- .UIImagePickerPreferredAssetRepresentationMode.Current;
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
- when picking a video. This will avoid the need to copy or transcode the video file and thus be a lot faster on iOS. If you use a different library, make sure to use the equivalent option. Location data is not supported with expo-image-picker, unless you set `legacy` to `true`.
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
- * Duration of the video in seconds (float).
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
- * Audio sample rate of the video in samples per second.
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 `sourceFilename` is a remote URI, `headers` object is passed in a network request.
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;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IACtB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,WAAW,EACP,UAAU,GACV,oBAAoB,GACpB,WAAW,GACX,gBAAgB,GAChB,eAAe,CAAC;IACpB;;OAEG;IACH,eAAe,EAAE,MAAM,CAAC;IACxB;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,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;CAClC,CAAC"}
1
+ {"version":3,"file":"ExpoVideoMetadata.types.d.ts","sourceRoot":"","sources":["../src/ExpoVideoMetadata.types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoVideoMetadata.types.js","sourceRoot":"","sources":["../src/ExpoVideoMetadata.types.ts"],"names":[],"mappings":"","sourcesContent":["export type VideoInfoResult = {\n /**\n * Duration of the video in seconds (float).\n */\n duration: number;\n /**\n * Tells if the video has a audio track. If the video has no audio track, its considered a mute video.\n */\n hasAudio: boolean;\n /**\n * Available only on iOS >= 14 and Android. Tells if the video is a HDR video.\n * Will return null if it could not be determined. (e.g. on Web or on older iOS/Android versions)\n */\n isHDR: boolean | null;\n /**\n * Width of the video in pixels.\n */\n width: number;\n /**\n * Height of the video in pixels.\n */\n height: number;\n /**\n * Frame rate of the video in frames per second.\n * Works on iOS, Android and Web (except Safari).\n */\n fps: number;\n /**\n * Bit rate of the video in bits per second.\n * Supported on all platforms.\n */\n bitRate: number;\n /**\n * File size of the video in bytes. Works only for local files, returns 0 for remote files.\n * Supported on all platforms.\n */\n fileSize: number;\n /**\n * Video codec.\n * Supported on all platforms, but on Web it may return an empty string.\n */\n codec: string;\n /**\n * Video orientation.\n * Supported on all platforms, but on Web it may return an empty string.\n */\n orientation:\n | \"Portrait\"\n | \"PortraitUpsideDown\"\n | \"Landscape\"\n | \"LandscapeRight\"\n | \"LandscapeLeft\";\n /**\n * Audio sample rate of the video in samples per second.\n */\n audioSampleRate: number;\n /**\n * Audio channel count of the video.\n */\n audioChannels: number;\n /**\n * Audio codec of the video.\n */\n audioCodec: string;\n /**\n * Location where the video was recorded.\n * Supported on iOS and Android (if the video contains location metadata)\n */\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 `sourceFilename` is a remote URI, `headers` object is passed in a network request.\n */\n headers?: Record<string, string>;\n};\n"]}
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,3 +1,7 @@
1
- declare const _default: any;
1
+ import { getVideoInfo } from "./getVideoInfo";
2
+ declare const _default: {
3
+ name: string;
4
+ getVideoInfo: typeof getVideoInfo;
5
+ };
2
6
  export default _default;
3
7
  //# sourceMappingURL=ExpoVideoMetadataModule.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoVideoMetadataModule.d.ts","sourceRoot":"","sources":["../src/ExpoVideoMetadataModule.ts"],"names":[],"mappings":";AACA,wBAAwD"}
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 { requireNativeModule } from "expo";
2
- export default requireNativeModule("ExpoVideoMetadata");
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,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAC3C,eAAe,mBAAmB,CAAC,mBAAmB,CAAC,CAAC","sourcesContent":["import { requireNativeModule } from \"expo\";\nexport default requireNativeModule(\"ExpoVideoMetadata\");\n"]}
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