mediabunny 1.0.2 → 1.0.4

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 (188) hide show
  1. package/README.md +4 -4
  2. package/dist/mediabunny.d.ts +4 -2
  3. package/dist/modules/codec-data.d.ts +95 -0
  4. package/dist/modules/codec-data.d.ts.map +1 -0
  5. package/dist/modules/codec-data.js +1103 -0
  6. package/dist/modules/codec.d.ts +250 -0
  7. package/dist/modules/codec.d.ts.map +1 -0
  8. package/dist/modules/codec.js +1100 -0
  9. package/dist/modules/conversion.d.ts +158 -0
  10. package/dist/modules/conversion.d.ts.map +1 -0
  11. package/dist/modules/conversion.js +866 -0
  12. package/dist/modules/custom-coder.d.ts +119 -0
  13. package/dist/modules/custom-coder.d.ts.map +1 -0
  14. package/dist/modules/custom-coder.js +91 -0
  15. package/dist/modules/demuxer.d.ts +17 -0
  16. package/dist/modules/demuxer.d.ts.map +1 -0
  17. package/dist/modules/demuxer.js +12 -0
  18. package/dist/modules/index.d.ts +25 -0
  19. package/dist/modules/index.d.ts.map +1 -0
  20. package/dist/modules/index.js +24 -0
  21. package/dist/modules/input-format.d.ts +121 -0
  22. package/dist/modules/input-format.d.ts.map +1 -0
  23. package/dist/modules/input-format.js +333 -0
  24. package/dist/modules/input-track.d.ts +138 -0
  25. package/dist/modules/input-track.d.ts.map +1 -0
  26. package/dist/modules/input-track.js +230 -0
  27. package/dist/modules/input.d.ts +55 -0
  28. package/dist/modules/input.d.ts.map +1 -0
  29. package/dist/modules/input.js +104 -0
  30. package/dist/modules/isobmff/isobmff-boxes.d.ts +202 -0
  31. package/dist/modules/isobmff/isobmff-boxes.d.ts.map +1 -0
  32. package/dist/modules/isobmff/isobmff-boxes.js +1111 -0
  33. package/dist/modules/isobmff/isobmff-demuxer.d.ts +163 -0
  34. package/dist/modules/isobmff/isobmff-demuxer.d.ts.map +1 -0
  35. package/dist/modules/isobmff/isobmff-demuxer.js +2080 -0
  36. package/dist/modules/isobmff/isobmff-misc.d.ts +14 -0
  37. package/dist/modules/isobmff/isobmff-misc.d.ts.map +1 -0
  38. package/dist/modules/isobmff/isobmff-misc.js +20 -0
  39. package/dist/modules/isobmff/isobmff-muxer.d.ts +142 -0
  40. package/dist/modules/isobmff/isobmff-muxer.d.ts.map +1 -0
  41. package/dist/modules/isobmff/isobmff-muxer.js +858 -0
  42. package/dist/modules/isobmff/isobmff-reader.d.ts +36 -0
  43. package/dist/modules/isobmff/isobmff-reader.d.ts.map +1 -0
  44. package/dist/modules/isobmff/isobmff-reader.js +105 -0
  45. package/dist/modules/matroska/ebml.d.ts +156 -0
  46. package/dist/modules/matroska/ebml.d.ts.map +1 -0
  47. package/dist/modules/matroska/ebml.js +529 -0
  48. package/dist/modules/matroska/matroska-demuxer.d.ts +119 -0
  49. package/dist/modules/matroska/matroska-demuxer.d.ts.map +1 -0
  50. package/dist/modules/matroska/matroska-demuxer.js +1330 -0
  51. package/dist/modules/matroska/matroska-misc.d.ts +14 -0
  52. package/dist/modules/matroska/matroska-misc.d.ts.map +1 -0
  53. package/dist/modules/matroska/matroska-misc.js +20 -0
  54. package/dist/modules/matroska/matroska-muxer.d.ts +71 -0
  55. package/dist/modules/matroska/matroska-muxer.d.ts.map +1 -0
  56. package/dist/modules/matroska/matroska-muxer.js +729 -0
  57. package/dist/modules/media-sink.d.ts +272 -0
  58. package/dist/modules/media-sink.d.ts.map +1 -0
  59. package/dist/modules/media-sink.js +1264 -0
  60. package/dist/modules/media-source.d.ts +230 -0
  61. package/dist/modules/media-source.d.ts.map +1 -0
  62. package/dist/modules/media-source.js +1095 -0
  63. package/dist/modules/misc.d.ts +127 -0
  64. package/dist/modules/misc.d.ts.map +1 -0
  65. package/dist/modules/misc.js +462 -0
  66. package/dist/modules/mp3/mp3-demuxer.d.ts +32 -0
  67. package/dist/modules/mp3/mp3-demuxer.d.ts.map +1 -0
  68. package/dist/modules/mp3/mp3-demuxer.js +160 -0
  69. package/dist/modules/mp3/mp3-misc.d.ts +37 -0
  70. package/dist/modules/mp3/mp3-misc.d.ts.map +1 -0
  71. package/dist/modules/mp3/mp3-misc.js +122 -0
  72. package/dist/modules/mp3/mp3-muxer.d.ts +27 -0
  73. package/dist/modules/mp3/mp3-muxer.d.ts.map +1 -0
  74. package/dist/modules/mp3/mp3-muxer.js +112 -0
  75. package/dist/modules/mp3/mp3-reader.d.ts +25 -0
  76. package/dist/modules/mp3/mp3-reader.d.ts.map +1 -0
  77. package/dist/modules/mp3/mp3-reader.js +73 -0
  78. package/dist/modules/mp3/mp3-writer.d.ts +30 -0
  79. package/dist/modules/mp3/mp3-writer.d.ts.map +1 -0
  80. package/dist/modules/mp3/mp3-writer.js +72 -0
  81. package/dist/modules/muxer.d.ts +32 -0
  82. package/dist/modules/muxer.d.ts.map +1 -0
  83. package/dist/modules/muxer.js +50 -0
  84. package/dist/modules/ogg/ogg-demuxer.d.ts +53 -0
  85. package/dist/modules/ogg/ogg-demuxer.d.ts.map +1 -0
  86. package/dist/modules/ogg/ogg-demuxer.js +701 -0
  87. package/dist/modules/ogg/ogg-misc.d.ts +27 -0
  88. package/dist/modules/ogg/ogg-misc.d.ts.map +1 -0
  89. package/dist/modules/ogg/ogg-misc.js +78 -0
  90. package/dist/modules/ogg/ogg-muxer.d.ts +58 -0
  91. package/dist/modules/ogg/ogg-muxer.d.ts.map +1 -0
  92. package/dist/modules/ogg/ogg-muxer.js +345 -0
  93. package/dist/modules/ogg/ogg-reader.d.ts +37 -0
  94. package/dist/modules/ogg/ogg-reader.d.ts.map +1 -0
  95. package/dist/modules/ogg/ogg-reader.js +104 -0
  96. package/dist/modules/output-format.d.ts +285 -0
  97. package/dist/modules/output-format.d.ts.map +1 -0
  98. package/dist/modules/output-format.js +385 -0
  99. package/dist/modules/output.d.ts +134 -0
  100. package/dist/modules/output.d.ts.map +1 -0
  101. package/dist/modules/output.js +269 -0
  102. package/dist/modules/packet.d.ts +86 -0
  103. package/dist/modules/packet.d.ts.map +1 -0
  104. package/dist/modules/packet.js +133 -0
  105. package/dist/modules/pcm.d.ts +12 -0
  106. package/dist/modules/pcm.d.ts.map +1 -0
  107. package/dist/modules/pcm.js +85 -0
  108. package/dist/modules/reader.d.ts +40 -0
  109. package/dist/modules/reader.d.ts.map +1 -0
  110. package/dist/modules/reader.js +153 -0
  111. package/dist/modules/sample.d.ts +186 -0
  112. package/dist/modules/sample.d.ts.map +1 -0
  113. package/dist/modules/sample.js +798 -0
  114. package/dist/modules/source.d.ts +76 -0
  115. package/dist/modules/source.d.ts.map +1 -0
  116. package/dist/modules/source.js +183 -0
  117. package/dist/modules/subtitles.d.ts +37 -0
  118. package/dist/modules/subtitles.d.ts.map +1 -0
  119. package/dist/modules/subtitles.js +89 -0
  120. package/dist/modules/target.d.ts +58 -0
  121. package/dist/modules/target.d.ts.map +1 -0
  122. package/dist/modules/target.js +63 -0
  123. package/dist/modules/wave/riff-reader.d.ts +19 -0
  124. package/dist/modules/wave/riff-reader.d.ts.map +1 -0
  125. package/dist/modules/wave/riff-reader.js +38 -0
  126. package/dist/modules/wave/riff-writer.d.ts +18 -0
  127. package/dist/modules/wave/riff-writer.d.ts.map +1 -0
  128. package/dist/modules/wave/riff-writer.js +25 -0
  129. package/dist/modules/wave/wave-demuxer.d.ts +42 -0
  130. package/dist/modules/wave/wave-demuxer.d.ts.map +1 -0
  131. package/dist/modules/wave/wave-demuxer.js +239 -0
  132. package/dist/modules/wave/wave-muxer.d.ts +27 -0
  133. package/dist/modules/wave/wave-muxer.d.ts.map +1 -0
  134. package/dist/modules/wave/wave-muxer.js +108 -0
  135. package/dist/modules/writer.d.ts +85 -0
  136. package/dist/modules/writer.d.ts.map +1 -0
  137. package/dist/modules/writer.js +347 -0
  138. package/package.json +14 -10
  139. package/src/codec-data.ts +1394 -0
  140. package/src/codec.ts +1392 -0
  141. package/src/conversion.ts +1199 -0
  142. package/src/custom-coder.ts +162 -0
  143. package/src/demuxer.ts +22 -0
  144. package/src/index.ts +148 -0
  145. package/src/input-format.ts +386 -0
  146. package/src/input-track.ts +341 -0
  147. package/src/input.ts +138 -0
  148. package/src/isobmff/isobmff-boxes.ts +1365 -0
  149. package/src/isobmff/isobmff-demuxer.ts +2646 -0
  150. package/src/isobmff/isobmff-misc.ts +29 -0
  151. package/src/isobmff/isobmff-muxer.ts +1210 -0
  152. package/src/isobmff/isobmff-reader.ts +137 -0
  153. package/src/matroska/ebml.ts +595 -0
  154. package/src/matroska/matroska-demuxer.ts +1677 -0
  155. package/src/matroska/matroska-misc.ts +29 -0
  156. package/src/matroska/matroska-muxer.ts +999 -0
  157. package/src/media-sink.ts +1577 -0
  158. package/src/media-source.ts +1406 -0
  159. package/src/misc.ts +584 -0
  160. package/src/mp3/mp3-demuxer.ts +228 -0
  161. package/src/mp3/mp3-misc.ts +154 -0
  162. package/src/mp3/mp3-muxer.ts +153 -0
  163. package/src/mp3/mp3-reader.ts +93 -0
  164. package/src/mp3/mp3-writer.ts +112 -0
  165. package/src/muxer.ts +88 -0
  166. package/src/ogg/ogg-demuxer.ts +985 -0
  167. package/src/ogg/ogg-misc.ts +116 -0
  168. package/src/ogg/ogg-muxer.ts +480 -0
  169. package/src/ogg/ogg-reader.ts +143 -0
  170. package/src/output-format.ts +689 -0
  171. package/src/output.ts +427 -0
  172. package/src/packet.ts +180 -0
  173. package/src/pcm.ts +112 -0
  174. package/src/reader.ts +205 -0
  175. package/src/sample.ts +1029 -0
  176. package/src/source.ts +279 -0
  177. package/src/subtitles.ts +131 -0
  178. package/src/target.ts +106 -0
  179. package/src/tsconfig.json +13 -0
  180. package/src/wave/riff-reader.ts +48 -0
  181. package/src/wave/riff-writer.ts +30 -0
  182. package/src/wave/wave-demuxer.ts +317 -0
  183. package/src/wave/wave-muxer.ts +145 -0
  184. package/src/writer.ts +461 -0
  185. /package/dist/{mediabunny.js → bundles/mediabunny.cjs} +0 -0
  186. /package/dist/{mediabunny.min.js → bundles/mediabunny.min.cjs} +0 -0
  187. /package/dist/{mediabunny.min.mjs → bundles/mediabunny.min.mjs} +0 -0
  188. /package/dist/{mediabunny.mjs → bundles/mediabunny.mjs} +0 -0
@@ -0,0 +1,162 @@
1
+ /*!
2
+ * Copyright (c) 2025-present, Vanilagy and contributors
3
+ *
4
+ * This Source Code Form is subject to the terms of the Mozilla Public
5
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
9
+ import { AudioCodec, VideoCodec } from './codec';
10
+ import { EncodedPacket } from './packet';
11
+ import { AudioSample, VideoSample } from './sample';
12
+
13
+ /**
14
+ * Base class for custom video decoders. To add your own custom video decoder, extend this class, implement the
15
+ * abstract methods and static `supports` method, and register the decoder using `registerDecoder`.
16
+ * @public
17
+ */
18
+ export abstract class CustomVideoDecoder {
19
+ /** The input video's codec. */
20
+ readonly codec!: VideoCodec;
21
+ /** The input video's decoder config. */
22
+ readonly config!: VideoDecoderConfig;
23
+ /** The callback to call when a decoded VideoSample is available. */
24
+ readonly onSample!: (sample: VideoSample) => unknown;
25
+
26
+ /** Returns true iff the decoder can decode the given codec configuration. */
27
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
28
+ static supports(codec: VideoCodec, config: VideoDecoderConfig): boolean {
29
+ return false;
30
+ }
31
+
32
+ /** Called after decoder creation; can be used for custom initialization logic. */
33
+ abstract init(): Promise<void> | void;
34
+ /** Decodes the provided encoded packet. */
35
+ abstract decode(packet: EncodedPacket): Promise<void> | void;
36
+ /** Decodes all remaining packets and then resolves. */
37
+ abstract flush(): Promise<void> | void;
38
+ /** Called when the decoder is no longer needed and its resources can be freed. */
39
+ abstract close(): Promise<void> | void;
40
+ }
41
+
42
+ /**
43
+ * Base class for custom audio decoders. To add your own custom audio decoder, extend this class, implement the
44
+ * abstract methods and static `supports` method, and register the decoder using `registerDecoder`.
45
+ * @public
46
+ */
47
+ export abstract class CustomAudioDecoder {
48
+ /** The input audio's codec. */
49
+ readonly codec!: AudioCodec;
50
+ /** The input audio's decoder config. */
51
+ readonly config!: AudioDecoderConfig;
52
+ /** The callback to call when a decoded AudioSample is available. */
53
+ readonly onSample!: (sample: AudioSample) => unknown;
54
+
55
+ /** Returns true iff the decoder can decode the given codec configuration. */
56
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
57
+ static supports(codec: AudioCodec, config: AudioDecoderConfig): boolean {
58
+ return false;
59
+ }
60
+
61
+ /** Called after decoder creation; can be used for custom initialization logic. */
62
+ abstract init(): Promise<void> | void;
63
+ /** Decodes the provided encoded packet. */
64
+ abstract decode(packet: EncodedPacket): Promise<void> | void;
65
+ /** Decodes all remaining packets and then resolves. */
66
+ abstract flush(): Promise<void> | void;
67
+ /** Called when the decoder is no longer needed and its resources can be freed. */
68
+ abstract close(): Promise<void> | void;
69
+ }
70
+
71
+ /**
72
+ * Base class for custom video encoders. To add your own custom video encoder, extend this class, implement the
73
+ * abstract methods and static `supports` method, and register the encoder using `registerEncoder`.
74
+ * @public
75
+ */
76
+ export abstract class CustomVideoEncoder {
77
+ /** The codec with which to encode the video. */
78
+ readonly codec!: VideoCodec;
79
+ /** Config for the encoder. */
80
+ readonly config!: VideoEncoderConfig;
81
+ /** The callback to call when an EncodedPacket is available. */
82
+ readonly onPacket!: (packet: EncodedPacket, meta?: EncodedVideoChunkMetadata) => unknown;
83
+
84
+ /** Returns true iff the encoder can encode the given codec configuration. */
85
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
86
+ static supports(codec: VideoCodec, config: VideoEncoderConfig): boolean {
87
+ return false;
88
+ }
89
+
90
+ /** Called after encoder creation; can be used for custom initialization logic. */
91
+ abstract init(): Promise<void> | void;
92
+ /** Encodes the provided video sample. */
93
+ abstract encode(videoSample: VideoSample, options: VideoEncoderEncodeOptions): Promise<void> | void;
94
+ /** Encodes all remaining video samples and then resolves. */
95
+ abstract flush(): Promise<void> | void;
96
+ /** Called when the encoder is no longer needed and its resources can be freed. */
97
+ abstract close(): Promise<void> | void;
98
+ }
99
+
100
+ /**
101
+ * Base class for custom audio encoders. To add your own custom audio encoder, extend this class, implement the
102
+ * abstract methods and static `supports` method, and register the encoder using `registerEncoder`.
103
+ * @public
104
+ */
105
+ export abstract class CustomAudioEncoder {
106
+ /** The codec with which to encode the audio. */
107
+ readonly codec!: AudioCodec;
108
+ /** Config for the encoder. */
109
+ readonly config!: AudioEncoderConfig;
110
+ /** The callback to call when an EncodedPacket is available. */
111
+ readonly onPacket!: (packet: EncodedPacket, meta?: EncodedAudioChunkMetadata) => unknown;
112
+
113
+ /** Returns true iff the encoder can encode the given codec configuration. */
114
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
115
+ static supports(codec: AudioCodec, config: AudioEncoderConfig): boolean {
116
+ return false;
117
+ }
118
+
119
+ /** Called after encoder creation; can be used for custom initialization logic. */
120
+ abstract init(): Promise<void> | void;
121
+ /** Encodes the provided audio sample. */
122
+ abstract encode(audioSample: AudioSample): Promise<void> | void;
123
+ /** Encodes all remaining audio samples and then resolves. */
124
+ abstract flush(): Promise<void> | void;
125
+ /** Called when the encoder is no longer needed and its resources can be freed. */
126
+ abstract close(): Promise<void> | void;
127
+ }
128
+
129
+ export const customVideoDecoders: typeof CustomVideoDecoder[] = [];
130
+ export const customAudioDecoders: typeof CustomAudioDecoder[] = [];
131
+ export const customVideoEncoders: typeof CustomVideoEncoder[] = [];
132
+ export const customAudioEncoders: typeof CustomAudioEncoder[] = [];
133
+
134
+ /**
135
+ * Registers a custom video or audio decoder. Registered decoders will automatically be used for decoding whenever
136
+ * possible.
137
+ * @public
138
+ */
139
+ export const registerDecoder = (decoder: typeof CustomVideoDecoder | typeof CustomAudioDecoder) => {
140
+ if (decoder.prototype instanceof CustomVideoDecoder) {
141
+ customVideoDecoders.push(decoder as typeof CustomVideoDecoder);
142
+ } else if (decoder.prototype instanceof CustomAudioDecoder) {
143
+ customAudioDecoders.push(decoder as typeof CustomAudioDecoder);
144
+ } else {
145
+ throw new TypeError('Decoder must be a CustomVideoDecoder or CustomAudioDecoder.');
146
+ }
147
+ };
148
+
149
+ /**
150
+ * Registers a custom video or audio encoder. Registered encoders will automatically be used for encoding whenever
151
+ * possible.
152
+ * @public
153
+ */
154
+ export const registerEncoder = (encoder: typeof CustomVideoEncoder | typeof CustomAudioEncoder) => {
155
+ if (encoder.prototype instanceof CustomVideoEncoder) {
156
+ customVideoEncoders.push(encoder as typeof CustomVideoEncoder);
157
+ } else if (encoder.prototype instanceof CustomAudioEncoder) {
158
+ customAudioEncoders.push(encoder as typeof CustomAudioEncoder);
159
+ } else {
160
+ throw new TypeError('Encoder must be a CustomVideoEncoder or CustomAudioEncoder.');
161
+ }
162
+ };
package/src/demuxer.ts ADDED
@@ -0,0 +1,22 @@
1
+ /*!
2
+ * Copyright (c) 2025-present, Vanilagy and contributors
3
+ *
4
+ * This Source Code Form is subject to the terms of the Mozilla Public
5
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
9
+ import { Input } from './input';
10
+ import { InputTrack } from './input-track';
11
+
12
+ export abstract class Demuxer {
13
+ input: Input;
14
+
15
+ constructor(input: Input) {
16
+ this.input = input;
17
+ }
18
+
19
+ abstract computeDuration(): Promise<number>;
20
+ abstract getTracks(): Promise<InputTrack[]>;
21
+ abstract getMimeType(): Promise<string>;
22
+ }
package/src/index.ts ADDED
@@ -0,0 +1,148 @@
1
+ /*!
2
+ * Copyright (c) 2025-present, Vanilagy and contributors
3
+ *
4
+ * This Source Code Form is subject to the terms of the Mozilla Public
5
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
9
+ /// <reference types="dom-mediacapture-transform" preserve="true" />
10
+ /// <reference types="dom-webcodecs" preserve="true" />
11
+
12
+ export {
13
+ Output,
14
+ OutputOptions,
15
+ BaseTrackMetadata,
16
+ VideoTrackMetadata,
17
+ AudioTrackMetadata,
18
+ SubtitleTrackMetadata,
19
+ TrackType,
20
+ ALL_TRACK_TYPES,
21
+ } from './output';
22
+ export {
23
+ OutputFormat,
24
+ IsobmffOutputFormat,
25
+ Mp4OutputFormat,
26
+ MovOutputFormat,
27
+ IsobmffOutputFormatOptions,
28
+ MkvOutputFormat,
29
+ MkvOutputFormatOptions,
30
+ WebMOutputFormat,
31
+ WebMOutputFormatOptions,
32
+ Mp3OutputFormat,
33
+ Mp3OutputFormatOptions,
34
+ WavOutputFormat,
35
+ WavOutputFormatOptions,
36
+ OggOutputFormat,
37
+ OggOutputFormatOptions,
38
+ TrackCountLimits,
39
+ InclusiveIntegerRange,
40
+ } from './output-format';
41
+ export {
42
+ VideoEncodingConfig,
43
+ AudioEncodingConfig,
44
+ MediaSource,
45
+ VideoSource,
46
+ EncodedVideoPacketSource,
47
+ VideoSampleSource,
48
+ CanvasSource,
49
+ MediaStreamVideoTrackSource,
50
+ AudioSource,
51
+ EncodedAudioPacketSource,
52
+ AudioSampleSource,
53
+ AudioBufferSource,
54
+ MediaStreamAudioTrackSource,
55
+ SubtitleSource,
56
+ TextSubtitleSource,
57
+ } from './media-source';
58
+ export {
59
+ VIDEO_CODECS,
60
+ VideoCodec,
61
+ PCM_AUDIO_CODECS,
62
+ NON_PCM_AUDIO_CODECS,
63
+ AUDIO_CODECS,
64
+ AudioCodec,
65
+ SUBTITLE_CODECS,
66
+ SubtitleCodec,
67
+ MediaCodec,
68
+ Quality,
69
+ QUALITY_VERY_LOW,
70
+ QUALITY_LOW,
71
+ QUALITY_MEDIUM,
72
+ QUALITY_HIGH,
73
+ QUALITY_VERY_HIGH,
74
+ canEncode,
75
+ canEncodeVideo,
76
+ canEncodeAudio,
77
+ canEncodeSubtitles,
78
+ getEncodableCodecs,
79
+ getEncodableVideoCodecs,
80
+ getEncodableAudioCodecs,
81
+ getEncodableSubtitleCodecs,
82
+ getFirstEncodableVideoCodec,
83
+ getFirstEncodableAudioCodec,
84
+ getFirstEncodableSubtitleCodec,
85
+ } from './codec';
86
+ export { Target, BufferTarget, StreamTarget, StreamTargetChunk, StreamTargetOptions } from './target';
87
+ export { Rotation, AnyIterable, SetRequired } from './misc';
88
+ export {
89
+ Source,
90
+ BufferSource,
91
+ StreamSource,
92
+ StreamSourceOptions,
93
+ BlobSource,
94
+ UrlSource,
95
+ UrlSourceOptions,
96
+ } from './source';
97
+ export {
98
+ InputFormat,
99
+ IsobmffInputFormat,
100
+ Mp4InputFormat,
101
+ QuickTimeInputFormat,
102
+ MatroskaInputFormat,
103
+ WebMInputFormat,
104
+ Mp3InputFormat,
105
+ WaveInputFormat,
106
+ OggInputFormat,
107
+ ALL_FORMATS,
108
+ MP4,
109
+ QTFF,
110
+ MATROSKA,
111
+ WEBM,
112
+ MP3,
113
+ WAVE,
114
+ OGG,
115
+ } from './input-format';
116
+ export { Input, InputOptions } from './input';
117
+ export { InputTrack, InputVideoTrack, InputAudioTrack, PacketStats } from './input-track';
118
+ export { EncodedPacket, PacketType } from './packet';
119
+ export {
120
+ VideoSample,
121
+ VideoSampleInit,
122
+ AudioSample,
123
+ AudioSampleInit,
124
+ AudioSampleCopyToOptions,
125
+ } from './sample';
126
+ export {
127
+ PacketRetrievalOptions,
128
+ EncodedPacketSink,
129
+ BaseMediaSampleSink,
130
+ VideoSampleSink,
131
+ CanvasSinkOptions,
132
+ CanvasSink,
133
+ WrappedCanvas,
134
+ AudioSampleSink,
135
+ AudioBufferSink,
136
+ WrappedAudioBuffer,
137
+ } from './media-sink';
138
+ export { ConversionOptions, Conversion } from './conversion';
139
+ export {
140
+ CustomVideoDecoder,
141
+ CustomAudioDecoder,
142
+ CustomVideoEncoder,
143
+ CustomAudioEncoder,
144
+ registerDecoder,
145
+ registerEncoder,
146
+ } from './custom-coder';
147
+
148
+ // 🐡🦔
@@ -0,0 +1,386 @@
1
+ /*!
2
+ * Copyright (c) 2025-present, Vanilagy and contributors
3
+ *
4
+ * This Source Code Form is subject to the terms of the Mozilla Public
5
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
6
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
+ */
8
+
9
+ import { Demuxer } from './demuxer';
10
+ import { Input } from './input';
11
+ import { IsobmffDemuxer } from './isobmff/isobmff-demuxer';
12
+ import { IsobmffReader } from './isobmff/isobmff-reader';
13
+ import { EBMLId, EBMLReader } from './matroska/ebml';
14
+ import { MatroskaDemuxer } from './matroska/matroska-demuxer';
15
+ import { Mp3Demuxer } from './mp3/mp3-demuxer';
16
+ import { Mp3Reader } from './mp3/mp3-reader';
17
+ import { OggDemuxer } from './ogg/ogg-demuxer';
18
+ import { OggReader } from './ogg/ogg-reader';
19
+ import { RiffReader } from './wave/riff-reader';
20
+ import { WaveDemuxer } from './wave/wave-demuxer';
21
+
22
+ /**
23
+ * Base class representing an input media file format.
24
+ * @public
25
+ */
26
+ export abstract class InputFormat {
27
+ /** @internal */
28
+ abstract _canReadInput(input: Input): Promise<boolean>;
29
+
30
+ /** @internal */
31
+ abstract _createDemuxer(input: Input): Demuxer;
32
+
33
+ /** Returns the name of the input format. */
34
+ abstract get name(): string;
35
+ /** Returns the typical base MIME type of the input format. */
36
+ abstract get mimeType(): string;
37
+ }
38
+
39
+ /**
40
+ * Format representing files compatible with the ISO base media file format (ISOBMFF), like MP4 or MOV files.
41
+ * @public
42
+ */
43
+ export abstract class IsobmffInputFormat extends InputFormat {
44
+ /** @internal */
45
+ protected async _getMajorBrand(input: Input) {
46
+ const sourceSize = await input._mainReader.source.getSize();
47
+ if (sourceSize < 12) {
48
+ return null;
49
+ }
50
+
51
+ const isobmffReader = new IsobmffReader(input._mainReader);
52
+ isobmffReader.pos = 4;
53
+ const fourCc = isobmffReader.readAscii(4);
54
+
55
+ if (fourCc !== 'ftyp') {
56
+ return null;
57
+ }
58
+
59
+ return isobmffReader.readAscii(4);
60
+ }
61
+
62
+ /** @internal */
63
+ _createDemuxer(input: Input) {
64
+ return new IsobmffDemuxer(input);
65
+ }
66
+ }
67
+
68
+ /**
69
+ * MPEG-4 Part 14 (MP4) file format.
70
+ * @public
71
+ */
72
+ export class Mp4InputFormat extends IsobmffInputFormat {
73
+ /** @internal */
74
+ async _canReadInput(input: Input) {
75
+ const majorBrand = await this._getMajorBrand(input);
76
+ return !!majorBrand && majorBrand !== 'qt ';
77
+ }
78
+
79
+ get name() {
80
+ return 'MP4';
81
+ }
82
+
83
+ get mimeType() {
84
+ return 'video/mp4';
85
+ }
86
+ }
87
+
88
+ /**
89
+ * QuickTime File Format (QTFF), often called MOV.
90
+ * @public
91
+ */
92
+ export class QuickTimeInputFormat extends IsobmffInputFormat {
93
+ /** @internal */
94
+ async _canReadInput(input: Input) {
95
+ const majorBrand = await this._getMajorBrand(input);
96
+ return majorBrand === 'qt ';
97
+ }
98
+
99
+ get name() {
100
+ return 'QuickTime File Format';
101
+ }
102
+
103
+ get mimeType() {
104
+ return 'video/quicktime';
105
+ }
106
+ }
107
+
108
+ /**
109
+ * Matroska file format.
110
+ * @public
111
+ */
112
+ export class MatroskaInputFormat extends InputFormat {
113
+ /** @internal */
114
+ protected async isSupportedEBMLOfDocType(input: Input, desiredDocType: string) {
115
+ const sourceSize = await input._mainReader.source.getSize();
116
+ if (sourceSize < 8) {
117
+ return false;
118
+ }
119
+
120
+ const ebmlReader = new EBMLReader(input._mainReader);
121
+ const varIntSize = ebmlReader.readVarIntSize();
122
+ if (varIntSize < 1 || varIntSize > 8) {
123
+ return false;
124
+ }
125
+
126
+ const id = ebmlReader.readUnsignedInt(varIntSize);
127
+ if (id !== EBMLId.EBML) {
128
+ return false;
129
+ }
130
+
131
+ const dataSize = ebmlReader.readElementSize();
132
+ if (dataSize === null) {
133
+ return false; // Miss me with that shit
134
+ }
135
+
136
+ const startPos = ebmlReader.pos;
137
+ while (ebmlReader.pos < startPos + dataSize) {
138
+ const { id, size } = ebmlReader.readElementHeader();
139
+ const dataStartPos = ebmlReader.pos;
140
+ if (size === null) return false;
141
+
142
+ switch (id) {
143
+ case EBMLId.EBMLVersion: {
144
+ const ebmlVersion = ebmlReader.readUnsignedInt(size);
145
+ if (ebmlVersion !== 1) {
146
+ return false;
147
+ }
148
+ }; break;
149
+ case EBMLId.EBMLReadVersion: {
150
+ const ebmlReadVersion = ebmlReader.readUnsignedInt(size);
151
+ if (ebmlReadVersion !== 1) {
152
+ return false;
153
+ }
154
+ }; break;
155
+ case EBMLId.DocType: {
156
+ const docType = ebmlReader.readString(size);
157
+ if (docType !== desiredDocType) {
158
+ return false;
159
+ }
160
+ }; break;
161
+ case EBMLId.DocTypeVersion: {
162
+ const docTypeVersion = ebmlReader.readUnsignedInt(size);
163
+ if (docTypeVersion > 4) { // Support up to Matroska v4
164
+ return false;
165
+ }
166
+ }; break;
167
+ }
168
+
169
+ ebmlReader.pos = dataStartPos + size;
170
+ }
171
+
172
+ return true;
173
+ }
174
+
175
+ /** @internal */
176
+ _canReadInput(input: Input) {
177
+ return this.isSupportedEBMLOfDocType(input, 'matroska');
178
+ }
179
+
180
+ /** @internal */
181
+ _createDemuxer(input: Input) {
182
+ return new MatroskaDemuxer(input);
183
+ }
184
+
185
+ get name() {
186
+ return 'Matroska';
187
+ }
188
+
189
+ get mimeType() {
190
+ return 'video/x-matroska';
191
+ }
192
+ }
193
+
194
+ /**
195
+ * WebM file format, based on Matroska.
196
+ * @public
197
+ */
198
+ export class WebMInputFormat extends MatroskaInputFormat {
199
+ /** @internal */
200
+ override _canReadInput(input: Input) {
201
+ return this.isSupportedEBMLOfDocType(input, 'webm');
202
+ }
203
+
204
+ override get name() {
205
+ return 'WebM';
206
+ }
207
+
208
+ override get mimeType() {
209
+ return 'video/webm';
210
+ }
211
+ }
212
+
213
+ /**
214
+ * MP3 file format.
215
+ * @public
216
+ */
217
+ export class Mp3InputFormat extends InputFormat {
218
+ /** @internal */
219
+ async _canReadInput(input: Input) {
220
+ const sourceSize = await input._mainReader.source.getSize();
221
+ if (sourceSize < 4) {
222
+ return false;
223
+ }
224
+
225
+ const mp3Reader = new Mp3Reader(input._mainReader);
226
+ mp3Reader.fileSize = sourceSize;
227
+
228
+ const id3Tag = mp3Reader.readId3();
229
+
230
+ if (id3Tag) {
231
+ mp3Reader.pos += id3Tag.size;
232
+ }
233
+
234
+ const framesStartPos = mp3Reader.pos;
235
+ await mp3Reader.reader.loadRange(mp3Reader.pos, mp3Reader.pos + 4096);
236
+
237
+ const firstHeader = mp3Reader.readNextFrameHeader(Math.min(framesStartPos + 4096, sourceSize));
238
+ if (!firstHeader) {
239
+ return false;
240
+ }
241
+
242
+ if (id3Tag) {
243
+ // If there was an ID3 tag at the start, we can be pretty sure this is MP3 by now
244
+ return true;
245
+ }
246
+
247
+ // Fine, we found one frame header, but we're still not entirely sure this is MP3. Let's check if we can find
248
+ // another header nearby:
249
+ mp3Reader.pos = firstHeader.startPos + firstHeader.totalSize;
250
+ const secondHeader = mp3Reader.readNextFrameHeader(Math.min(framesStartPos + 4096, sourceSize));
251
+ if (!secondHeader) {
252
+ return false;
253
+ }
254
+
255
+ // In a well-formed MP3 file, we'd expect these two frames to share some similarities:
256
+ if (firstHeader.channel !== secondHeader.channel || firstHeader.sampleRate !== secondHeader.sampleRate) {
257
+ return false;
258
+ }
259
+
260
+ // We have found two matching MP3 frames, a strong indicator that this is an MP3 file
261
+ return true;
262
+ }
263
+
264
+ /** @internal */
265
+ _createDemuxer(input: Input) {
266
+ return new Mp3Demuxer(input);
267
+ }
268
+
269
+ get name() {
270
+ return 'MP3';
271
+ }
272
+
273
+ get mimeType() {
274
+ return 'audio/mpeg';
275
+ }
276
+ }
277
+
278
+ /**
279
+ * WAVE file format, based on RIFF.
280
+ * @public
281
+ */
282
+ export class WaveInputFormat extends InputFormat {
283
+ /** @internal */
284
+ async _canReadInput(input: Input) {
285
+ const sourceSize = await input._mainReader.source.getSize();
286
+ if (sourceSize < 12) {
287
+ return false;
288
+ }
289
+
290
+ const riffReader = new RiffReader(input._mainReader);
291
+ const riffType = riffReader.readAscii(4);
292
+ if (riffType !== 'RIFF' && riffType !== 'RIFX') {
293
+ return false;
294
+ }
295
+
296
+ riffReader.pos = 8;
297
+ const format = riffReader.readAscii(4);
298
+ return format === 'WAVE';
299
+ }
300
+
301
+ /** @internal */
302
+ _createDemuxer(input: Input) {
303
+ return new WaveDemuxer(input);
304
+ }
305
+
306
+ get name() {
307
+ return 'WAVE';
308
+ }
309
+
310
+ get mimeType() {
311
+ return 'audio/wav';
312
+ }
313
+ }
314
+
315
+ /**
316
+ * Ogg file format.
317
+ * @public
318
+ */
319
+ export class OggInputFormat extends InputFormat {
320
+ /** @internal */
321
+ async _canReadInput(input: Input) {
322
+ const sourceSize = await input._mainReader.source.getSize();
323
+ if (sourceSize < 4) {
324
+ return false;
325
+ }
326
+
327
+ const oggReader = new OggReader(input._mainReader);
328
+ return oggReader.readAscii(4) === 'OggS';
329
+ }
330
+
331
+ /** @internal */
332
+ _createDemuxer(input: Input) {
333
+ return new OggDemuxer(input);
334
+ }
335
+
336
+ get name() {
337
+ return 'Ogg';
338
+ }
339
+
340
+ get mimeType() {
341
+ return 'application/ogg';
342
+ }
343
+ }
344
+
345
+ /**
346
+ * MP4 input format singleton.
347
+ * @public
348
+ */
349
+ export const MP4 = new Mp4InputFormat();
350
+ /**
351
+ * QuickTime File Format input format singleton.
352
+ * @public
353
+ */
354
+ export const QTFF = new QuickTimeInputFormat();
355
+ /**
356
+ * Matroska input format singleton.
357
+ * @public
358
+ */
359
+ export const MATROSKA = new MatroskaInputFormat();
360
+ /**
361
+ * WebM input format singleton.
362
+ * @public
363
+ */
364
+ export const WEBM = new WebMInputFormat();
365
+ /**
366
+ * MP3 input format singleton.
367
+ * @public
368
+ */
369
+ export const MP3 = new Mp3InputFormat();
370
+ /**
371
+ * WAVE input format singleton.
372
+ * @public
373
+ */
374
+ export const WAVE = new WaveInputFormat();
375
+ /**
376
+ * Ogg input format singleton.
377
+ * @public
378
+ */
379
+ export const OGG = new OggInputFormat();
380
+
381
+ /**
382
+ * List of all input format singletons. If you don't need to support all input formats, you should specify the
383
+ * formats individually for better tree shaking.
384
+ * @public
385
+ */
386
+ export const ALL_FORMATS: InputFormat[] = [MP4, QTFF, MATROSKA, WEBM, WAVE, OGG, MP3];