expo-video-metadata 1.2.0 → 1.2.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/README.md CHANGED
@@ -32,13 +32,13 @@ import { getVideoInfoAsync } from 'expo-video-metadata';
32
32
  /**
33
33
  * Retrieves video metadata.
34
34
  *
35
- * @param sourceFilename An URI of the video, local or remote.
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
36
  * @param options Pass `headers` object in case `sourceFilename` is a remote URI, e.g { headers: "Authorization": "Bearer some-token" } etc.
37
37
  *
38
38
  * @return Returns a promise which fulfils with [`VideoInfoResult`](#Videoinforesult).
39
39
  */
40
40
 
41
- const result = await getVideoInfoAsync(sourceFilename: string, options: VideoInfoOptions = {}): Promise<VideoInfoResult>
41
+ const result = await getVideoInfoAsync(sourceFilename: string | File | Blob, options: VideoInfoOptions = {}): Promise<VideoInfoResult>
42
42
  ```
43
43
 
44
- See [VideoInfoResult](https://github.com/hirbod/expo-video-metadata/blob/b9239224eed46f455b2fb9f1b29e69ac49da6683/src/ExpoVideoMetadata.types.ts#L1) type for more information.
44
+ See [VideoInfoResult](https://github.com/hirbod/expo-video-metadata/blob/main/src/ExpoVideoMetadata.types.ts#L1) type for more information.
@@ -58,6 +58,7 @@ export type VideoInfoResult = {
58
58
  */
59
59
  audioCodec: string;
60
60
  };
61
+ export type VideoSource = string | File | Blob;
61
62
  export type VideoInfoOptions = {
62
63
  /**
63
64
  * In case `sourceFilename` is a remote URI, `headers` object is passed in a network request.
@@ -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;CACpB,CAAC;AAEF,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":"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;CACpB,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 +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\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 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\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,4 +1,4 @@
1
- import type { VideoInfoOptions, VideoInfoResult } from "./ExpoVideoMetadata.types";
1
+ import type { VideoInfoOptions, VideoInfoResult, VideoSource } from "./ExpoVideoMetadata.types";
2
2
  interface Track {
3
3
  id: string;
4
4
  kind: string;
@@ -28,7 +28,7 @@ declare const _default: {
28
28
  }>;
29
29
  getBase64FileSize(base64String: string): number;
30
30
  getFileSize(url: string, options?: RequestInit): Promise<number>;
31
- getVideoInfo(sourceFilename: string | File | Blob, options?: VideoInfoOptions): Promise<VideoInfoResult>;
31
+ getVideoInfo(source: VideoSource, options?: VideoInfoOptions): Promise<VideoInfoResult>;
32
32
  };
33
33
  export default _default;
34
34
  //# sourceMappingURL=ExpoVideoMetadataModule.web.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoVideoMetadataModule.web.d.ts","sourceRoot":"","sources":["../src/ExpoVideoMetadataModule.web.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EAChB,MAAM,2BAA2B,CAAC;AAEnC,UAAU,KAAK;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,UAAW,SAAQ,KAAK;IAChC,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,UAAW,SAAQ,KAAK;IAChC,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;AAExB,UAAU,0BAA2B,SAAQ,gBAAgB;IAC3D,WAAW,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,aAAa,CAAC,IAAI,WAAW,CAAC;CAC/B;;;oCAKiC,0BAA0B;6BAkB9C,MAAM,YACP,WAAW,GACnB,QAAQ;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,CAAC;oCAyB5B,MAAM,GAAG,MAAM;qBAKxB,MAAM,YAAW,WAAW,GAAQ,QAAQ,MAAM,CAAC;iCAgBxD,MAAM,GAAG,IAAI,GAAG,IAAI,YAC3B,gBAAgB,GACxB,QAAQ,eAAe,CAAC;;AAvE7B,wBAyJE"}
1
+ {"version":3,"file":"ExpoVideoMetadataModule.web.d.ts","sourceRoot":"","sources":["../src/ExpoVideoMetadataModule.web.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,WAAW,EACZ,MAAM,2BAA2B,CAAC;AAEnC,UAAU,KAAK;IACb,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,UAAW,SAAQ,KAAK;IAChC,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,UAAU,UAAW,SAAQ,KAAK;IAChC,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,KAAK,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;AAExB,UAAU,0BAA2B,SAAQ,gBAAgB;IAC3D,WAAW,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IACpC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,aAAa,CAAC,IAAI,WAAW,CAAC;CAC/B;;;oCAKiC,0BAA0B;6BAkB9C,MAAM,YACP,WAAW,GACnB,QAAQ;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,gBAAgB,EAAE,MAAM,CAAA;KAAE,CAAC;oCAyB5B,MAAM,GAAG,MAAM;qBAKxB,MAAM,YAAW,WAAW,GAAQ,QAAQ,MAAM,CAAC;yBAgBhE,WAAW,YACV,gBAAgB,GACxB,QAAQ,eAAe,CAAC;;AAvE7B,wBAuJE"}
@@ -48,15 +48,14 @@ export default {
48
48
  return 0;
49
49
  }
50
50
  },
51
- async getVideoInfo(sourceFilename, options = {}) {
51
+ async getVideoInfo(source, options = {}) {
52
52
  const video = document.createElement("video");
53
53
  let videoUrl = "";
54
- if (typeof sourceFilename === "string") {
55
- videoUrl = sourceFilename;
54
+ if (typeof source === "string") {
55
+ videoUrl = source;
56
56
  }
57
- else if (sourceFilename instanceof File ||
58
- sourceFilename instanceof Blob) {
59
- videoUrl = URL.createObjectURL(sourceFilename);
57
+ else if (source instanceof File || source instanceof Blob) {
58
+ videoUrl = URL.createObjectURL(source);
60
59
  }
61
60
  Object.assign(video, {
62
61
  crossOrigin: "anonymous",
@@ -69,6 +68,10 @@ export default {
69
68
  video.removeAttribute("src");
70
69
  video.load();
71
70
  video.remove();
71
+ // Revoke the object URL if it was created
72
+ if (source instanceof File || source instanceof Blob) {
73
+ URL.revokeObjectURL(videoUrl);
74
+ }
72
75
  };
73
76
  try {
74
77
  await new Promise((resolve, reject) => {
@@ -85,8 +88,8 @@ export default {
85
88
  const hasAudio = Boolean(video.audioTracks?.length) ||
86
89
  video.mozHasAudio ||
87
90
  Boolean(video.webkitAudioDecodedByteCount);
88
- const fileSize = sourceFilename instanceof File || sourceFilename instanceof Blob
89
- ? sourceFilename.size
91
+ const fileSize = source instanceof File || source instanceof Blob
92
+ ? source.size
90
93
  : await this.getFileSize(videoUrl, options);
91
94
  const bitRate = fileSize && duration ? Math.floor(fileSize / duration) : 0;
92
95
  const { numberOfChannels: audioChannels, sampleRate: audioSampleRate } = await this.getAudioBuffer(videoUrl);
@@ -109,9 +112,6 @@ export default {
109
112
  }
110
113
  finally {
111
114
  resetVideo();
112
- if (sourceFilename instanceof File || sourceFilename instanceof Blob) {
113
- URL.revokeObjectURL(videoUrl);
114
- }
115
115
  }
116
116
  },
117
117
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ExpoVideoMetadataModule.web.js","sourceRoot":"","sources":["../src/ExpoVideoMetadataModule.web.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n VideoInfoOptions,\n VideoInfoResult,\n} from \"./ExpoVideoMetadata.types\";\n\ninterface Track {\n id: string;\n kind: string;\n label: string;\n language: string;\n}\n\ninterface AudioTrack extends Track {\n enabled: boolean;\n}\n\ninterface VideoTrack extends Track {\n selected: boolean;\n}\n\ntype TrackList<T> = T[];\n\ninterface HTMLVideoElementWithTracks extends HTMLVideoElement {\n videoTracks?: TrackList<VideoTrack>;\n audioTracks?: TrackList<AudioTrack>;\n mozHasAudio?: boolean;\n webkitAudioDecodedByteCount?: number;\n captureStream?(): MediaStream;\n}\n\nexport default {\n name: \"ExpoVideoMetadata\",\n\n getVideoFrameRate(videoElement: HTMLVideoElementWithTracks) {\n if (!videoElement.captureStream) {\n console.info(\"captureStream method not supported\");\n return 0;\n }\n\n const stream = videoElement.captureStream();\n const [videoTrack] = stream.getVideoTracks();\n\n if (!videoTrack) {\n console.info(\"No video track found\");\n return 0;\n }\n\n return videoTrack.getSettings().frameRate ?? 0;\n },\n\n async getAudioBuffer(\n audioUrl: string,\n options: RequestInit = {}\n ): Promise<{ sampleRate: number; numberOfChannels: number }> {\n const audioContext = new (window.AudioContext ||\n (window as any).webkitAudioContext)();\n\n try {\n const response = await fetch(audioUrl, options);\n const arrayBuffer = await response.arrayBuffer();\n\n return new Promise((resolve, reject) => {\n audioContext.decodeAudioData(\n arrayBuffer,\n ({ sampleRate, numberOfChannels }) =>\n resolve({ sampleRate, numberOfChannels }),\n reject\n );\n });\n } catch (error) {\n throw new Error(\n `Error fetching or decoding audio file: ${error.message}`\n );\n } finally {\n await audioContext.close();\n }\n },\n\n getBase64FileSize(base64String: string): number {\n const base64Data = base64String.replace(/^data:.+;base64,/, \"\");\n return atob(base64Data).length;\n },\n\n async getFileSize(url: string, options: RequestInit = {}): Promise<number> {\n if (url.startsWith(\"data:\")) {\n return this.getBase64FileSize(url);\n }\n\n try {\n const response = await fetch(url, { method: \"HEAD\", ...options });\n const contentLength = response.headers.get(\"Content-Length\");\n return contentLength ? parseInt(contentLength, 10) : 0;\n } catch (error) {\n console.error(\"Error fetching file size for URL:\", url, error);\n return 0;\n }\n },\n\n async getVideoInfo(\n sourceFilename: string | File | Blob,\n options: VideoInfoOptions = {}\n ): Promise<VideoInfoResult> {\n const video = document.createElement(\"video\") as HTMLVideoElementWithTracks;\n let videoUrl = \"\";\n\n if (typeof sourceFilename === \"string\") {\n videoUrl = sourceFilename;\n } else if (\n sourceFilename instanceof File ||\n sourceFilename instanceof Blob\n ) {\n videoUrl = URL.createObjectURL(sourceFilename);\n }\n\n Object.assign(video, {\n crossOrigin: \"anonymous\",\n autoplay: true,\n muted: true,\n playsInline: true,\n });\n\n const resetVideo = () => {\n video.pause();\n video.removeAttribute(\"src\");\n video.load();\n video.remove();\n };\n\n try {\n await new Promise<void>((resolve, reject) => {\n // Can't use `loadedmetadata` event because it does not contain videoTracks, audioTracks and other metadata\n video.onloadeddata = () => resolve();\n video.onerror = () =>\n reject(new Error(\"Failed to load video metadata\"));\n video.src = videoUrl;\n video.load();\n video.pause();\n });\n\n const { duration, videoWidth: width, videoHeight: height } = video;\n const videoTrack = video.videoTracks?.[0];\n const audioTrack = video.audioTracks?.[0];\n\n const hasAudio =\n Boolean(video.audioTracks?.length) ||\n video.mozHasAudio ||\n Boolean(video.webkitAudioDecodedByteCount);\n\n const fileSize =\n sourceFilename instanceof File || sourceFilename instanceof Blob\n ? sourceFilename.size\n : await this.getFileSize(videoUrl, options);\n\n const bitRate =\n fileSize && duration ? Math.floor(fileSize / duration) : 0;\n\n const { numberOfChannels: audioChannels, sampleRate: audioSampleRate } =\n await this.getAudioBuffer(videoUrl);\n\n const fps = this.getVideoFrameRate(video);\n\n return {\n duration,\n width,\n height,\n bitRate,\n fileSize,\n hasAudio,\n audioSampleRate,\n isHDR: null,\n audioCodec: audioTrack?.label ?? \"\",\n codec: videoTrack?.label ?? \"\",\n audioChannels,\n fps,\n orientation: width >= height ? \"Landscape\" : \"Portrait\",\n };\n } finally {\n resetVideo();\n if (sourceFilename instanceof File || sourceFilename instanceof Blob) {\n URL.revokeObjectURL(videoUrl);\n }\n }\n },\n};\n"]}
1
+ {"version":3,"file":"ExpoVideoMetadataModule.web.js","sourceRoot":"","sources":["../src/ExpoVideoMetadataModule.web.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n VideoInfoOptions,\n VideoInfoResult,\n VideoSource,\n} from \"./ExpoVideoMetadata.types\";\n\ninterface Track {\n id: string;\n kind: string;\n label: string;\n language: string;\n}\n\ninterface AudioTrack extends Track {\n enabled: boolean;\n}\n\ninterface VideoTrack extends Track {\n selected: boolean;\n}\n\ntype TrackList<T> = T[];\n\ninterface HTMLVideoElementWithTracks extends HTMLVideoElement {\n videoTracks?: TrackList<VideoTrack>;\n audioTracks?: TrackList<AudioTrack>;\n mozHasAudio?: boolean;\n webkitAudioDecodedByteCount?: number;\n captureStream?(): MediaStream;\n}\n\nexport default {\n name: \"ExpoVideoMetadata\",\n\n getVideoFrameRate(videoElement: HTMLVideoElementWithTracks) {\n if (!videoElement.captureStream) {\n console.info(\"captureStream method not supported\");\n return 0;\n }\n\n const stream = videoElement.captureStream();\n const [videoTrack] = stream.getVideoTracks();\n\n if (!videoTrack) {\n console.info(\"No video track found\");\n return 0;\n }\n\n return videoTrack.getSettings().frameRate ?? 0;\n },\n\n async getAudioBuffer(\n audioUrl: string,\n options: RequestInit = {}\n ): Promise<{ sampleRate: number; numberOfChannels: number }> {\n const audioContext = new (window.AudioContext ||\n (window as any).webkitAudioContext)();\n\n try {\n const response = await fetch(audioUrl, options);\n const arrayBuffer = await response.arrayBuffer();\n\n return new Promise((resolve, reject) => {\n audioContext.decodeAudioData(\n arrayBuffer,\n ({ sampleRate, numberOfChannels }) =>\n resolve({ sampleRate, numberOfChannels }),\n reject\n );\n });\n } catch (error) {\n throw new Error(\n `Error fetching or decoding audio file: ${error.message}`\n );\n } finally {\n await audioContext.close();\n }\n },\n\n getBase64FileSize(base64String: string): number {\n const base64Data = base64String.replace(/^data:.+;base64,/, \"\");\n return atob(base64Data).length;\n },\n\n async getFileSize(url: string, options: RequestInit = {}): Promise<number> {\n if (url.startsWith(\"data:\")) {\n return this.getBase64FileSize(url);\n }\n\n try {\n const response = await fetch(url, { method: \"HEAD\", ...options });\n const contentLength = response.headers.get(\"Content-Length\");\n return contentLength ? parseInt(contentLength, 10) : 0;\n } catch (error) {\n console.error(\"Error fetching file size for URL:\", url, error);\n return 0;\n }\n },\n\n async getVideoInfo(\n source: VideoSource,\n options: VideoInfoOptions = {}\n ): Promise<VideoInfoResult> {\n const video = document.createElement(\"video\") as HTMLVideoElementWithTracks;\n let videoUrl = \"\";\n\n if (typeof source === \"string\") {\n videoUrl = source;\n } else if (source instanceof File || source instanceof Blob) {\n videoUrl = URL.createObjectURL(source);\n }\n\n Object.assign(video, {\n crossOrigin: \"anonymous\",\n autoplay: true,\n muted: true,\n playsInline: true,\n });\n\n const resetVideo = () => {\n video.pause();\n video.removeAttribute(\"src\");\n video.load();\n video.remove();\n // Revoke the object URL if it was created\n if (source instanceof File || source instanceof Blob) {\n URL.revokeObjectURL(videoUrl);\n }\n };\n\n try {\n await new Promise<void>((resolve, reject) => {\n // Can't use `loadedmetadata` event because it does not contain videoTracks, audioTracks and other metadata\n video.onloadeddata = () => resolve();\n video.onerror = () =>\n reject(new Error(\"Failed to load video metadata\"));\n video.src = videoUrl;\n video.load();\n video.pause();\n });\n\n const { duration, videoWidth: width, videoHeight: height } = video;\n const videoTrack = video.videoTracks?.[0];\n const audioTrack = video.audioTracks?.[0];\n\n const hasAudio =\n Boolean(video.audioTracks?.length) ||\n video.mozHasAudio ||\n Boolean(video.webkitAudioDecodedByteCount);\n\n const fileSize =\n source instanceof File || source instanceof Blob\n ? source.size\n : await this.getFileSize(videoUrl, options);\n\n const bitRate =\n fileSize && duration ? Math.floor(fileSize / duration) : 0;\n\n const { numberOfChannels: audioChannels, sampleRate: audioSampleRate } =\n await this.getAudioBuffer(videoUrl);\n\n const fps = this.getVideoFrameRate(video);\n\n return {\n duration,\n width,\n height,\n bitRate,\n fileSize,\n hasAudio,\n audioSampleRate,\n isHDR: null,\n audioCodec: audioTrack?.label ?? \"\",\n codec: videoTrack?.label ?? \"\",\n audioChannels,\n fps,\n orientation: width >= height ? \"Landscape\" : \"Portrait\",\n };\n } finally {\n resetVideo();\n }\n },\n};\n"]}
package/build/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- import { VideoInfoOptions, VideoInfoResult } from "./ExpoVideoMetadata.types";
1
+ import { VideoInfoOptions, VideoInfoResult, VideoSource } from "./ExpoVideoMetadata.types";
2
2
  export { VideoInfoOptions, VideoInfoResult };
3
3
  /**
4
4
  * Retrieves video metadata.
5
5
  *
6
- * @param sourceFilename An URI of the video, local or remote.
6
+ * @param source An URI (string) 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.
7
7
  * @param options Pass `headers` object in case `sourceFilename` is a remote URI, e.g { headers: "Authorization": "Bearer some-token" } etc.
8
8
  *
9
9
  * @return Returns a promise which fulfils with [`VideoInfoResult`](#Videoinforesult).
10
10
  */
11
- export declare function getVideoInfoAsync(sourceFilename: string | File | Blob, options?: VideoInfoOptions): Promise<VideoInfoResult>;
11
+ export declare function getVideoInfoAsync(source: VideoSource, options?: VideoInfoOptions): Promise<VideoInfoResult>;
12
12
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAG9E,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,CAAC;AAK7C;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,EACpC,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAE1B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,WAAW,EACZ,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,CAAC;AAK7C;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,WAAW,EACnB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAE1B"}
package/build/index.js CHANGED
@@ -4,12 +4,12 @@ import ExpoVideoMetadataModule from "./ExpoVideoMetadataModule";
4
4
  /**
5
5
  * Retrieves video metadata.
6
6
  *
7
- * @param sourceFilename An URI of the video, local or remote.
7
+ * @param source An URI (string) 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.
8
8
  * @param options Pass `headers` object in case `sourceFilename` is a remote URI, e.g { headers: "Authorization": "Bearer some-token" } etc.
9
9
  *
10
10
  * @return Returns a promise which fulfils with [`VideoInfoResult`](#Videoinforesult).
11
11
  */
12
- export async function getVideoInfoAsync(sourceFilename, options = {}) {
13
- return await ExpoVideoMetadataModule.getVideoInfo(sourceFilename, options);
12
+ export async function getVideoInfoAsync(source, options = {}) {
13
+ return await ExpoVideoMetadataModule.getVideoInfo(source, options);
14
14
  }
15
15
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,uBAAuB,MAAM,2BAA2B,CAAC;AAIhE,oFAAoF;AACpF,kDAAkD;AAElD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,cAAoC,EACpC,UAA4B,EAAE;IAE9B,OAAO,MAAM,uBAAuB,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;AAC7E,CAAC","sourcesContent":["import { VideoInfoOptions, VideoInfoResult } from \"./ExpoVideoMetadata.types\";\nimport ExpoVideoMetadataModule from \"./ExpoVideoMetadataModule\";\n\nexport { VideoInfoOptions, VideoInfoResult };\n\n// Import the native module. On web, it will be resolved to ExpoVideoMetadata.web.ts\n// and on native platforms to ExpoVideoMetadata.ts\n\n/**\n * Retrieves video metadata.\n *\n * @param sourceFilename An URI of the video, local or remote.\n * @param options Pass `headers` object in case `sourceFilename` is a remote URI, e.g { headers: \"Authorization\": \"Bearer some-token\" } etc.\n *\n * @return Returns a promise which fulfils with [`VideoInfoResult`](#Videoinforesult).\n */\nexport async function getVideoInfoAsync(\n sourceFilename: string | File | Blob,\n options: VideoInfoOptions = {}\n): Promise<VideoInfoResult> {\n return await ExpoVideoMetadataModule.getVideoInfo(sourceFilename, options);\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,uBAAuB,MAAM,2BAA2B,CAAC;AAIhE,oFAAoF;AACpF,kDAAkD;AAElD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAmB,EACnB,UAA4B,EAAE;IAE9B,OAAO,MAAM,uBAAuB,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACrE,CAAC","sourcesContent":["import {\n VideoInfoOptions,\n VideoInfoResult,\n VideoSource,\n} from \"./ExpoVideoMetadata.types\";\nimport ExpoVideoMetadataModule from \"./ExpoVideoMetadataModule\";\n\nexport { VideoInfoOptions, VideoInfoResult };\n\n// Import the native module. On web, it will be resolved to ExpoVideoMetadata.web.ts\n// and on native platforms to ExpoVideoMetadata.ts\n\n/**\n * Retrieves video metadata.\n *\n * @param source An URI (string) 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.\n * @param options Pass `headers` object in case `sourceFilename` is a remote URI, e.g { headers: \"Authorization\": \"Bearer some-token\" } etc.\n *\n * @return Returns a promise which fulfils with [`VideoInfoResult`](#Videoinforesult).\n */\nexport async function getVideoInfoAsync(\n source: VideoSource,\n options: VideoInfoOptions = {}\n): Promise<VideoInfoResult> {\n return await ExpoVideoMetadataModule.getVideoInfo(source, options);\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-video-metadata",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "Module to retrieve metadata from a video with Web, Expo and React Native",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -64,6 +64,8 @@ export type VideoInfoResult = {
64
64
  audioCodec: string;
65
65
  };
66
66
 
67
+ export type VideoSource = string | File | Blob;
68
+
67
69
  export type VideoInfoOptions = {
68
70
  /**
69
71
  * In case `sourceFilename` is a remote URI, `headers` object is passed in a network request.
@@ -1,6 +1,7 @@
1
1
  import type {
2
2
  VideoInfoOptions,
3
3
  VideoInfoResult,
4
+ VideoSource,
4
5
  } from "./ExpoVideoMetadata.types";
5
6
 
6
7
  interface Track {
@@ -97,19 +98,16 @@ export default {
97
98
  },
98
99
 
99
100
  async getVideoInfo(
100
- sourceFilename: string | File | Blob,
101
+ source: VideoSource,
101
102
  options: VideoInfoOptions = {}
102
103
  ): Promise<VideoInfoResult> {
103
104
  const video = document.createElement("video") as HTMLVideoElementWithTracks;
104
105
  let videoUrl = "";
105
106
 
106
- if (typeof sourceFilename === "string") {
107
- videoUrl = sourceFilename;
108
- } else if (
109
- sourceFilename instanceof File ||
110
- sourceFilename instanceof Blob
111
- ) {
112
- videoUrl = URL.createObjectURL(sourceFilename);
107
+ if (typeof source === "string") {
108
+ videoUrl = source;
109
+ } else if (source instanceof File || source instanceof Blob) {
110
+ videoUrl = URL.createObjectURL(source);
113
111
  }
114
112
 
115
113
  Object.assign(video, {
@@ -124,6 +122,10 @@ export default {
124
122
  video.removeAttribute("src");
125
123
  video.load();
126
124
  video.remove();
125
+ // Revoke the object URL if it was created
126
+ if (source instanceof File || source instanceof Blob) {
127
+ URL.revokeObjectURL(videoUrl);
128
+ }
127
129
  };
128
130
 
129
131
  try {
@@ -147,8 +149,8 @@ export default {
147
149
  Boolean(video.webkitAudioDecodedByteCount);
148
150
 
149
151
  const fileSize =
150
- sourceFilename instanceof File || sourceFilename instanceof Blob
151
- ? sourceFilename.size
152
+ source instanceof File || source instanceof Blob
153
+ ? source.size
152
154
  : await this.getFileSize(videoUrl, options);
153
155
 
154
156
  const bitRate =
@@ -176,9 +178,6 @@ export default {
176
178
  };
177
179
  } finally {
178
180
  resetVideo();
179
- if (sourceFilename instanceof File || sourceFilename instanceof Blob) {
180
- URL.revokeObjectURL(videoUrl);
181
- }
182
181
  }
183
182
  },
184
183
  };
package/src/index.ts CHANGED
@@ -1,4 +1,8 @@
1
- import { VideoInfoOptions, VideoInfoResult } from "./ExpoVideoMetadata.types";
1
+ import {
2
+ VideoInfoOptions,
3
+ VideoInfoResult,
4
+ VideoSource,
5
+ } from "./ExpoVideoMetadata.types";
2
6
  import ExpoVideoMetadataModule from "./ExpoVideoMetadataModule";
3
7
 
4
8
  export { VideoInfoOptions, VideoInfoResult };
@@ -9,14 +13,14 @@ export { VideoInfoOptions, VideoInfoResult };
9
13
  /**
10
14
  * Retrieves video metadata.
11
15
  *
12
- * @param sourceFilename An URI of the video, local or remote.
16
+ * @param source An URI (string) 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.
13
17
  * @param options Pass `headers` object in case `sourceFilename` is a remote URI, e.g { headers: "Authorization": "Bearer some-token" } etc.
14
18
  *
15
19
  * @return Returns a promise which fulfils with [`VideoInfoResult`](#Videoinforesult).
16
20
  */
17
21
  export async function getVideoInfoAsync(
18
- sourceFilename: string | File | Blob,
22
+ source: VideoSource,
19
23
  options: VideoInfoOptions = {}
20
24
  ): Promise<VideoInfoResult> {
21
- return await ExpoVideoMetadataModule.getVideoInfo(sourceFilename, options);
25
+ return await ExpoVideoMetadataModule.getVideoInfo(source, options);
22
26
  }