webcodecs-utils 0.2.4 → 0.2.6

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 (54) hide show
  1. package/README.md +142 -0
  2. package/dist/audio/extract-channels.d.ts +45 -0
  3. package/dist/audio/extract-channels.d.ts.map +1 -0
  4. package/dist/audio/extract-channels.js +25 -0
  5. package/dist/audio/get-sample-rate.d.ts +19 -0
  6. package/dist/audio/get-sample-rate.d.ts.map +1 -0
  7. package/dist/audio/get-sample-rate.js +14 -0
  8. package/dist/audio/mp3.d.ts +162 -0
  9. package/dist/audio/mp3.d.ts.map +1 -0
  10. package/dist/audio/mp3.js +173 -0
  11. package/dist/demux/example-muxer.d.ts +74 -0
  12. package/dist/demux/example-muxer.d.ts.map +1 -0
  13. package/dist/demux/example-muxer.js +40 -0
  14. package/dist/demux/get-chunks.d.ts +81 -0
  15. package/dist/demux/get-chunks.d.ts.map +1 -0
  16. package/dist/demux/get-chunks.js +88 -0
  17. package/dist/demux/mp4-demuxer.d.ts +84 -0
  18. package/dist/demux/mp4-demuxer.d.ts.map +1 -0
  19. package/dist/demux/mp4-demuxer.js +215 -0
  20. package/dist/demux/simple-demuxer.d.ts +49 -0
  21. package/dist/demux/simple-demuxer.d.ts.map +1 -0
  22. package/dist/demux/simple-demuxer.js +87 -0
  23. package/dist/in-memory-storage.d.ts +30 -0
  24. package/dist/in-memory-storage.d.ts.map +1 -0
  25. package/dist/in-memory-storage.js +54 -0
  26. package/dist/index.cjs +5 -298
  27. package/dist/index.d.ts +17 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +36 -13873
  30. package/dist/mux/simple-muxer.d.ts +47 -0
  31. package/dist/mux/simple-muxer.d.ts.map +1 -0
  32. package/dist/mux/simple-muxer.js +83 -0
  33. package/dist/polyfills/media-stream-track-processor.d.ts +5 -0
  34. package/dist/polyfills/media-stream-track-processor.d.ts.map +1 -0
  35. package/dist/polyfills/media-stream-track-processor.js +109 -0
  36. package/dist/streams/video-decode-stream.d.ts +11 -0
  37. package/dist/streams/video-decode-stream.d.ts.map +1 -0
  38. package/dist/streams/video-decode-stream.js +39 -0
  39. package/dist/streams/video-encode-stream.d.ts +15 -0
  40. package/dist/streams/video-encode-stream.d.ts.map +1 -0
  41. package/dist/streams/video-encode-stream.js +40 -0
  42. package/dist/streams/video-process-stream.d.ts +22 -0
  43. package/dist/streams/video-process-stream.d.ts.map +1 -0
  44. package/dist/streams/video-process-stream.js +21 -0
  45. package/dist/video/get-bitrate.d.ts +35 -0
  46. package/dist/video/get-bitrate.d.ts.map +1 -0
  47. package/dist/video/get-bitrate.js +12 -0
  48. package/dist/video/get-codec-string.d.ts +46 -0
  49. package/dist/video/get-codec-string.d.ts.map +1 -0
  50. package/dist/video/get-codec-string.js +195 -0
  51. package/dist/video/gpu-renderer.d.ts +108 -0
  52. package/dist/video/gpu-renderer.d.ts.map +1 -0
  53. package/dist/video/gpu-renderer.js +266 -0
  54. package/package.json +1 -1
@@ -0,0 +1,40 @@
1
+ import { BufferTarget as i, Output as o, Mp4OutputFormat as r, EncodedVideoPacketSource as s, EncodedAudioPacketSource as a, EncodedPacket as u } from "mediabunny";
2
+ class c {
3
+ /**
4
+ * Create a new ExampleMuxer.
5
+ *
6
+ * @param type - Track type: 'video' (default) or 'audio'
7
+ */
8
+ constructor(t) {
9
+ this.type = t || "video", this.target = new i();
10
+ const e = new o({
11
+ format: new r(),
12
+ target: this.target
13
+ });
14
+ this.started = !1, this.output = e, this.source = this.type === "video" ? new s("avc") : new a("aac"), this.output.addVideoTrack(this.source), console.warn(
15
+ "⚠️ Demo/Learning Function: This utility is intended for demos and learning purposes only. For production use, please use a proper muxing library like MediaBunny (https://mediabunny.dev/) "
16
+ );
17
+ }
18
+ /**
19
+ * Add an encoded chunk to the MP4 file.
20
+ *
21
+ * @param chunk - EncodedVideoChunk or EncodedAudioChunk from encoder output
22
+ * @param meta - Optional metadata from encoder (for video, contains decoderConfig)
23
+ */
24
+ addChunk(t, e) {
25
+ this.started || (this.output.start(), this.started = !0), this.source.add(u.fromEncodedChunk(t), e);
26
+ }
27
+ /**
28
+ * Finalize the MP4 file and return the complete buffer.
29
+ *
30
+ * Call this after all chunks have been added.
31
+ *
32
+ * @returns Complete MP4 file as ArrayBuffer
33
+ */
34
+ async finish() {
35
+ return await this.output.finalize(), this.target.buffer;
36
+ }
37
+ }
38
+ export {
39
+ c as ExampleMuxer
40
+ };
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Extract all video chunks from a media file.
3
+ *
4
+ * **⚠️ Demo/Learning Only**: For production use, use MediaBunny or web-demuxer directly.
5
+ *
6
+ * @param file - Media file to demux
7
+ * @returns Array of EncodedVideoChunk objects
8
+ *
9
+ * @example
10
+ * ```typescript
11
+ * const chunks = await getVideoChunks(file);
12
+ * // Returns all video chunks from the file
13
+ * ```
14
+ */
15
+ export declare function getVideoChunks(file: File): Promise<EncodedVideoChunk[]>;
16
+ /**
17
+ * Extract all audio chunks and decoder config from a media file.
18
+ *
19
+ * **⚠️ Demo/Learning Only**: For production use, use MediaBunny or web-demuxer directly.
20
+ *
21
+ * @param file - Media file to demux
22
+ * @returns Object containing chunks array and AudioDecoderConfig
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const { chunks, config } = await demuxAudio(file);
27
+ *
28
+ * // Configure decoder
29
+ * decoder.configure(config);
30
+ *
31
+ * // Decode all chunks
32
+ * for (const chunk of chunks) {
33
+ * decoder.decode(chunk);
34
+ * }
35
+ * ```
36
+ */
37
+ export declare function demuxAudio(file: File): Promise<{
38
+ chunks: EncodedAudioChunk[];
39
+ config: AudioDecoderConfig;
40
+ }>;
41
+ /**
42
+ * Extract all video chunks and decoder config from a media file.
43
+ *
44
+ * **⚠️ Demo/Learning Only**: For production use, use MediaBunny or web-demuxer directly.
45
+ *
46
+ * @param file - Media file to demux
47
+ * @returns Object containing chunks array and VideoDecoderConfig
48
+ *
49
+ * @example
50
+ * ```typescript
51
+ * const { chunks, config } = await demuxVideo(file);
52
+ *
53
+ * // Configure decoder
54
+ * decoder.configure(config);
55
+ *
56
+ * // Decode all chunks
57
+ * for (const chunk of chunks) {
58
+ * decoder.decode(chunk);
59
+ * }
60
+ * ```
61
+ */
62
+ export declare function demuxVideo(file: File): Promise<{
63
+ chunks: EncodedVideoChunk[];
64
+ config: VideoDecoderConfig;
65
+ }>;
66
+ /**
67
+ * Extract all audio chunks from a media file.
68
+ *
69
+ * **⚠️ Demo/Learning Only**: For production use, use MediaBunny or web-demuxer directly.
70
+ *
71
+ * @param file - Media file to demux
72
+ * @returns Array of EncodedAudioChunk objects
73
+ *
74
+ * @example
75
+ * ```typescript
76
+ * const chunks = await getAudioChunks(file);
77
+ * // Returns all audio chunks from the file
78
+ * ```
79
+ */
80
+ export declare function getAudioChunks(file: File): Promise<EncodedAudioChunk[]>;
81
+ //# sourceMappingURL=get-chunks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-chunks.d.ts","sourceRoot":"","sources":["../../src/demux/get-chunks.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;GAaG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAyB7E;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC;IAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAC,CAAC,CAwC/G;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC;IAAC,MAAM,EAAE,iBAAiB,EAAE,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAA;CAAC,CAAC,CAyC/G;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC,CAyB7E"}
@@ -0,0 +1,88 @@
1
+ import { WebDemuxer as u } from "web-demuxer";
2
+ let f = !1;
3
+ function m() {
4
+ f || (console.warn(
5
+ "⚠️ Demo/Learning Function: This utility is intended for demos and learning purposes only. For production use, please use a proper demuxing library like MediaBunny (https://mediabunny.dev/) or web-demuxer (https://github.com/bilibili/web-demuxer) directly."
6
+ ), f = !0);
7
+ }
8
+ async function p(i) {
9
+ m();
10
+ const e = new u({
11
+ wasmFilePath: "https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/wasm-files/web-demuxer.wasm"
12
+ });
13
+ await e.load(i);
14
+ const a = e.read("video", 0).getReader(), n = [];
15
+ return new Promise(function(d) {
16
+ a.read().then(async function t(o) {
17
+ const { done: s, value: r } = o;
18
+ return r && n.push(r), s ? d(n) : a.read().then(t);
19
+ });
20
+ });
21
+ }
22
+ async function g(i) {
23
+ m();
24
+ const e = new u({
25
+ wasmFilePath: "https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/wasm-files/web-demuxer.wasm"
26
+ });
27
+ await e.load(i);
28
+ const a = e.read("audio", 0).getReader(), n = [];
29
+ await new Promise(function(s) {
30
+ a.read().then(async function r(w) {
31
+ const { done: l, value: c } = w;
32
+ return c && n.push(c), l ? s(n) : a.read().then(r);
33
+ });
34
+ });
35
+ const t = (await e.getMediaInfo()).streams.filter((s) => s.codec_type_string === "audio")[0], o = {
36
+ codec: t.codec_string,
37
+ sampleRate: t.sample_rate,
38
+ numberOfChannels: t.channels
39
+ };
40
+ return {
41
+ chunks: n,
42
+ config: o
43
+ };
44
+ }
45
+ async function x(i) {
46
+ m();
47
+ const e = new u({
48
+ wasmFilePath: "https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/wasm-files/web-demuxer.wasm"
49
+ });
50
+ await e.load(i);
51
+ const a = e.read("video", 0).getReader(), n = [];
52
+ await new Promise(function(s) {
53
+ a.read().then(async function r(w) {
54
+ const { done: l, value: c } = w;
55
+ return c && n.push(c), l ? s(n) : a.read().then(r);
56
+ });
57
+ });
58
+ const t = (await e.getMediaInfo()).streams.filter((s) => s.codec_type_string === "video")[0], o = {
59
+ codec: t.codec_string,
60
+ codedWidth: t.width,
61
+ codedHeight: t.height,
62
+ description: t.extradata
63
+ };
64
+ return {
65
+ chunks: n,
66
+ config: o
67
+ };
68
+ }
69
+ async function b(i) {
70
+ m();
71
+ const e = new u({
72
+ wasmFilePath: "https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/wasm-files/web-demuxer.wasm"
73
+ });
74
+ await e.load(i);
75
+ const a = e.read("audio", 0).getReader(), n = [];
76
+ return new Promise(function(d) {
77
+ a.read().then(async function t(o) {
78
+ const { done: s, value: r } = o;
79
+ return r && n.push(r), s ? d(n) : a.read().then(t);
80
+ });
81
+ });
82
+ }
83
+ export {
84
+ g as demuxAudio,
85
+ x as demuxVideo,
86
+ b as getAudioChunks,
87
+ p as getVideoChunks
88
+ };
@@ -0,0 +1,84 @@
1
+ import { MP4Info } from 'mp4box';
2
+ type MP4Info = any;
3
+ export interface AudioTrackData {
4
+ codec: string;
5
+ sampleRate: number;
6
+ numberOfChannels: number;
7
+ }
8
+ export interface VideoTrackData {
9
+ codec: string;
10
+ codedHeight: number;
11
+ codedWidth: number;
12
+ description: Uint8Array;
13
+ frameRate: number;
14
+ }
15
+ export interface TrackData {
16
+ duration: number;
17
+ audio?: AudioTrackData;
18
+ video?: VideoTrackData;
19
+ }
20
+ /**
21
+ * MP4 demuxer for extracting video/audio chunks from MP4 files.
22
+ * Wraps MP4Box.js with a simpler API and built-in caching.
23
+ *
24
+ * @example
25
+ * ```typescript
26
+ * const demuxer = new MP4Demuxer(file);
27
+ * await demuxer.load();
28
+ *
29
+ * const tracks = demuxer.getTracks();
30
+ * const videoChunks = await demuxer.extractSegment('video', 0, 10);
31
+ * ```
32
+ */
33
+ export declare class MP4Demuxer {
34
+ private file;
35
+ private mp4Data;
36
+ /**
37
+ * Create a new MP4Demuxer instance.
38
+ * @param file - The MP4 file to demux
39
+ * @param options - Optional configuration
40
+ */
41
+ constructor(file: File);
42
+ /**
43
+ * Load and parse the MP4 file metadata.
44
+ * Must be called before extracting segments.
45
+ */
46
+ load(onProgress?: (progress: number) => void): Promise<void>;
47
+ /**
48
+ * Get track information from the loaded MP4 file.
49
+ * @returns Track data including duration, codec info, etc.
50
+ * @throws Error if load() hasn't been called yet
51
+ */
52
+ getTracks(): TrackData;
53
+ getVideoDecoderConfig(): VideoDecoderConfig | undefined;
54
+ getAudioDecoderConfig(): AudioDecoderConfig | undefined;
55
+ /**
56
+ * Get video track information.
57
+ * @returns Video track data or undefined if no video track
58
+ * @throws Error if load() hasn't been called yet
59
+ */
60
+ getVideoTrack(): VideoTrackData | undefined;
61
+ /**
62
+ * Get audio track information.
63
+ * @returns Audio track data or undefined if no audio track
64
+ * @throws Error if load() hasn't been called yet
65
+ */
66
+ getAudioTrack(): AudioTrackData | undefined;
67
+ /**
68
+ * Extract encoded chunks from a specific time range.
69
+ * @param trackType - "audio" or "video"
70
+ * @param startTime - Start time in seconds
71
+ * @param endTime - End time in seconds
72
+ * @returns Array of EncodedVideoChunk or EncodedAudioChunk
73
+ * @throws Error if load() hasn't been called yet
74
+ */
75
+ extractSegment(trackType: "audio" | "video", startTime: number, endTime: number): Promise<EncodedVideoChunk[] | EncodedAudioChunk[]>;
76
+ /**
77
+ * Get the full MP4 info object from MP4Box.
78
+ * @returns MP4Info object with detailed track information
79
+ * @throws Error if load() hasn't been called yet
80
+ */
81
+ getInfo(): MP4Info;
82
+ }
83
+ export {};
84
+ //# sourceMappingURL=mp4-demuxer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mp4-demuxer.d.ts","sourceRoot":"","sources":["../../src/demux/mp4-demuxer.ts"],"names":[],"mappings":"AACA,OAAe,EAAU,OAAO,EAAiE,MAAM,QAAQ,CAAA;AAK/G,KAAK,OAAO,GAAG,GAAG,CAAC;AAMnB,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,UAAU,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB,KAAK,CAAC,EAAE,cAAc,CAAC;CACxB;AAqSD;;;;;;;;;;;;GAYG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,OAAO,CAAwB;IAEvC;;;;OAIG;gBACS,IAAI,EAAE,IAAI;IAItB;;;OAGG;IACG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlE;;;;OAIG;IACH,SAAS,IAAI,SAAS;IAStB,qBAAqB,IAAI,kBAAkB,GAAG,SAAS;IAIvD,qBAAqB,IAAI,kBAAkB,GAAG,SAAS;IAMvD;;;;OAIG;IACH,aAAa,IAAI,cAAc,GAAG,SAAS;IAI3C;;;;OAIG;IACH,aAAa,IAAI,cAAc,GAAG,SAAS;IAI3C;;;;;;;OAOG;IACG,cAAc,CAClB,SAAS,EAAE,OAAO,GAAG,OAAO,EAC5B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAOrD;;;;OAIG;IACH,OAAO,IAAI,OAAO;CAMnB"}
@@ -0,0 +1,215 @@
1
+ import M, { DataStream as x } from "mp4box";
2
+ const S = 100, y = 0.5, R = 0.1;
3
+ function I(s, e) {
4
+ const o = s.getTrackById(e.id);
5
+ for (const r of o.mdia.minf.stbl.stsd.entries) {
6
+ const c = r.avcC || r.hvcC || r.vpcC || r.av1C;
7
+ if (c) {
8
+ const t = new x(void 0, 0, x.BIG_ENDIAN);
9
+ return c.write(t), new Uint8Array(t.buffer, 8);
10
+ }
11
+ }
12
+ throw new Error(
13
+ "Codec description box (avcC, hvcC, vpcC, or av1C) not found"
14
+ );
15
+ }
16
+ function _(s, e) {
17
+ var r, c;
18
+ const o = {
19
+ duration: e.duration / e.timescale
20
+ };
21
+ if (e.videoTracks.length > 0) {
22
+ const t = e.videoTracks[0], a = t.samples_duration / t.timescale;
23
+ o.video = {
24
+ codec: t.codec,
25
+ codedHeight: t.video.height,
26
+ codedWidth: t.video.width,
27
+ description: I(s, t),
28
+ frameRate: t.nb_samples / a
29
+ };
30
+ }
31
+ if (e.audioTracks.length > 0) {
32
+ const t = e.audioTracks[0], a = ((r = t.audio) == null ? void 0 : r.sample_rate) ?? t.timescale, d = ((c = t.audio) == null ? void 0 : c.channel_count) ?? 2;
33
+ o.audio = {
34
+ codec: t.codec,
35
+ sampleRate: a,
36
+ numberOfChannels: d
37
+ };
38
+ }
39
+ return o;
40
+ }
41
+ function P(s, e) {
42
+ return new Promise((o, r) => {
43
+ const c = s.stream().getReader();
44
+ let t = 0;
45
+ const a = M.createFile(!1);
46
+ let d = !1;
47
+ a.onReady = (n) => {
48
+ d = !0;
49
+ const u = _(a, n);
50
+ o({ info: n, trackData: u, mp4: a });
51
+ }, a.onError = (n) => {
52
+ r(
53
+ new Error(
54
+ `MP4Box parsing error: ${n instanceof Error ? n.message : String(n)}`
55
+ )
56
+ );
57
+ };
58
+ const h = async () => {
59
+ try {
60
+ const { done: n, value: u } = await c.read();
61
+ if (n) {
62
+ if (!d)
63
+ throw new Error("Invalid MP4 file: metadata not available");
64
+ a.flush();
65
+ return;
66
+ }
67
+ if (d) {
68
+ c.releaseLock(), a.flush();
69
+ return;
70
+ }
71
+ const m = u.buffer;
72
+ if (m.fileStart = t, t += u.length, e && e(t / s.size), a.appendBuffer(m), t < s.size)
73
+ return h();
74
+ if (a.flush(), !d)
75
+ throw new Error("Invalid MP4 file: metadata not available");
76
+ } catch (n) {
77
+ r(n);
78
+ }
79
+ };
80
+ h().catch(r);
81
+ });
82
+ }
83
+ function A(s, e, o, r, c) {
84
+ const { mp4: t, info: a } = e;
85
+ return new Promise((d, h) => {
86
+ let n = 0, u = !1, m = 0;
87
+ const b = o === "audio" ? EncodedAudioChunk : EncodedVideoChunk, k = [], D = o === "audio" ? a.audioTracks[0] ?? null : a.videoTracks[0] ?? null;
88
+ if (!D) {
89
+ d([]);
90
+ return;
91
+ }
92
+ m = D.id;
93
+ const w = a.duration / a.timescale - R, E = Math.min(c || w, w);
94
+ for (const i in a.tracks) {
95
+ const p = a.tracks[i];
96
+ t.unsetExtractionOptions(p.id);
97
+ }
98
+ t.onSamples = (i, p, l) => {
99
+ for (const f of l) {
100
+ const g = f.cts / f.timescale;
101
+ g < E && k.push(
102
+ new b({
103
+ type: f.is_sync ? "key" : "delta",
104
+ timestamp: Math.round(1e6 * g),
105
+ duration: Math.round(
106
+ 1e6 * (f.duration / f.timescale)
107
+ ),
108
+ data: f.data
109
+ })
110
+ );
111
+ }
112
+ if (l.length > 0 && t.releaseUsedSamples(m, l[l.length - 1].number), k.length > 0) {
113
+ const g = k[k.length - 1].timestamp / 1e6;
114
+ (Math.abs(g - E) < y || g > E) && (u = !0, t.stop(), t.flush(), d(k));
115
+ }
116
+ }, t.onError = (i) => {
117
+ h(
118
+ new Error(
119
+ `Extraction error: ${i instanceof Error ? i.message : String(i)}`
120
+ )
121
+ );
122
+ }, t.setExtractionOptions(m, null, { nbSamples: S });
123
+ const T = t.seek(r, !0), v = s.slice(T.offset).stream().getReader();
124
+ n = T.offset;
125
+ const C = async () => {
126
+ try {
127
+ const { done: i, value: p } = await v.read();
128
+ if (i || u) {
129
+ v.releaseLock(), t.flush();
130
+ return;
131
+ }
132
+ const l = p.buffer;
133
+ return l.fileStart = n, n += p.length, t.appendBuffer(l), C();
134
+ } catch (i) {
135
+ h(i);
136
+ }
137
+ };
138
+ t.start(), C().catch(h);
139
+ });
140
+ }
141
+ class N {
142
+ /**
143
+ * Create a new MP4Demuxer instance.
144
+ * @param file - The MP4 file to demux
145
+ * @param options - Optional configuration
146
+ */
147
+ constructor(e) {
148
+ this.mp4Data = null, this.file = e;
149
+ }
150
+ /**
151
+ * Load and parse the MP4 file metadata.
152
+ * Must be called before extracting segments.
153
+ */
154
+ async load(e) {
155
+ this.mp4Data = await P(this.file, e);
156
+ }
157
+ /**
158
+ * Get track information from the loaded MP4 file.
159
+ * @returns Track data including duration, codec info, etc.
160
+ * @throws Error if load() hasn't been called yet
161
+ */
162
+ getTracks() {
163
+ if (!this.mp4Data)
164
+ throw new Error("MP4Demuxer: Must call load() before getTracks()");
165
+ return this.mp4Data.trackData;
166
+ }
167
+ getVideoDecoderConfig() {
168
+ return this.getVideoTrack();
169
+ }
170
+ getAudioDecoderConfig() {
171
+ return this.getAudioTrack();
172
+ }
173
+ /**
174
+ * Get video track information.
175
+ * @returns Video track data or undefined if no video track
176
+ * @throws Error if load() hasn't been called yet
177
+ */
178
+ getVideoTrack() {
179
+ return this.getTracks().video;
180
+ }
181
+ /**
182
+ * Get audio track information.
183
+ * @returns Audio track data or undefined if no audio track
184
+ * @throws Error if load() hasn't been called yet
185
+ */
186
+ getAudioTrack() {
187
+ return this.getTracks().audio;
188
+ }
189
+ /**
190
+ * Extract encoded chunks from a specific time range.
191
+ * @param trackType - "audio" or "video"
192
+ * @param startTime - Start time in seconds
193
+ * @param endTime - End time in seconds
194
+ * @returns Array of EncodedVideoChunk or EncodedAudioChunk
195
+ * @throws Error if load() hasn't been called yet
196
+ */
197
+ async extractSegment(e, o, r) {
198
+ if (!this.mp4Data)
199
+ throw new Error("MP4Demuxer: Must call load() before extractSegment()");
200
+ return A(this.file, this.mp4Data, e, o, r);
201
+ }
202
+ /**
203
+ * Get the full MP4 info object from MP4Box.
204
+ * @returns MP4Info object with detailed track information
205
+ * @throws Error if load() hasn't been called yet
206
+ */
207
+ getInfo() {
208
+ if (!this.mp4Data)
209
+ throw new Error("MP4Demuxer: Must call load() before getInfo()");
210
+ return this.mp4Data.info;
211
+ }
212
+ }
213
+ export {
214
+ N as MP4Demuxer
215
+ };
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Simple wrapper around web-demuxer for easier usage
3
+ * Provides streaming and batch access to encoded chunks
4
+ *
5
+ * **⚠️ Demo/Learning Only**: For production use, use web-demuxer or MediaBunny directly.
6
+ */
7
+ export declare class SimpleDemuxer {
8
+ private demuxer;
9
+ private file;
10
+ private loaded;
11
+ constructor(file: File, options?: {
12
+ wasmFilePath?: string;
13
+ });
14
+ /**
15
+ * Load and parse the media file
16
+ */
17
+ load(): Promise<void>;
18
+ /**
19
+ * Get a ReadableStream of video chunks from start time (default: 0)
20
+ * @param startTime Start time in seconds (default: 0)
21
+ */
22
+ videoStream(startTime?: number): ReadableStream<EncodedVideoChunk>;
23
+ /**
24
+ * Get a ReadableStream of audio chunks from start time (default: 0)
25
+ * @param startTime Start time in seconds (default: 0)
26
+ */
27
+ audioStream(startTime?: number): ReadableStream<EncodedAudioChunk>;
28
+ /**
29
+ * Get video decoder configuration
30
+ */
31
+ getVideoDecoderConfig(): Promise<VideoDecoderConfig>;
32
+ /**
33
+ * Get audio decoder configuration
34
+ */
35
+ getAudioDecoderConfig(): Promise<AudioDecoderConfig>;
36
+ /**
37
+ * Get a segment of encoded chunks as an array
38
+ * @param type Track type ('video' or 'audio')
39
+ * @param start Start time in seconds
40
+ * @param end End time in seconds
41
+ * @returns Array of encoded chunks
42
+ */
43
+ getSegment(type: 'video' | 'audio', start: number, end: number): Promise<EncodedVideoChunk[] | EncodedAudioChunk[]>;
44
+ /**
45
+ * Get media information (tracks, duration, etc.)
46
+ */
47
+ getMediaInfo(): Promise<import("web-demuxer").WebMediaInfo>;
48
+ }
49
+ //# sourceMappingURL=simple-demuxer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simple-demuxer.d.ts","sourceRoot":"","sources":["../../src/demux/simple-demuxer.ts"],"names":[],"mappings":"AAgBA;;;;;GAKG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,IAAI,CAAO;IACnB,OAAO,CAAC,MAAM,CAAS;gBAEX,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE;QAAE,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE;IAS3D;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAK3B;;;OAGG;IACH,WAAW,CAAC,SAAS,GAAE,MAAU,GAAG,cAAc,CAAC,iBAAiB,CAAC;IAOrE;;;OAGG;IACH,WAAW,CAAC,SAAS,GAAE,MAAU,GAAG,cAAc,CAAC,iBAAiB,CAAC;IAOrE;;OAEG;IACG,qBAAqB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAO1D;;OAEG;IACG,qBAAqB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAO1D;;;;;;OAMG;IACG,UAAU,CACd,IAAI,EAAE,OAAO,GAAG,OAAO,EACvB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,iBAAiB,EAAE,GAAG,iBAAiB,EAAE,CAAC;IAsBrD;;OAEG;IACG,YAAY;CAMnB"}
@@ -0,0 +1,87 @@
1
+ import { WebDemuxer as l } from "web-demuxer";
2
+ let a = !1;
3
+ function u() {
4
+ a || (console.warn(
5
+ "⚠️ Demo/Learning Function: SimpleDemuxer is intended for demos and learning purposes only. For production use, please use web-demuxer directly (https://github.com/bilibili/web-demuxer) or MediaBunny (https://mediabunny.dev/) for more features."
6
+ ), a = !0);
7
+ }
8
+ class h {
9
+ constructor(e, r) {
10
+ this.loaded = !1, u(), this.file = e, this.demuxer = new l({
11
+ wasmFilePath: (r == null ? void 0 : r.wasmFilePath) || "https://cdn.jsdelivr.net/npm/web-demuxer@latest/dist/wasm-files/web-demuxer.wasm"
12
+ });
13
+ }
14
+ /**
15
+ * Load and parse the media file
16
+ */
17
+ async load() {
18
+ await this.demuxer.load(this.file), this.loaded = !0;
19
+ }
20
+ /**
21
+ * Get a ReadableStream of video chunks from start time (default: 0)
22
+ * @param startTime Start time in seconds (default: 0)
23
+ */
24
+ videoStream(e = 0) {
25
+ if (!this.loaded)
26
+ throw new Error("SimpleDemuxer: Must call load() before accessing streams");
27
+ return this.demuxer.read("video", e);
28
+ }
29
+ /**
30
+ * Get a ReadableStream of audio chunks from start time (default: 0)
31
+ * @param startTime Start time in seconds (default: 0)
32
+ */
33
+ audioStream(e = 0) {
34
+ if (!this.loaded)
35
+ throw new Error("SimpleDemuxer: Must call load() before accessing streams");
36
+ return this.demuxer.read("audio", e);
37
+ }
38
+ /**
39
+ * Get video decoder configuration
40
+ */
41
+ async getVideoDecoderConfig() {
42
+ if (!this.loaded)
43
+ throw new Error("SimpleDemuxer: Must call load() before getting config");
44
+ return await this.demuxer.getDecoderConfig("video");
45
+ }
46
+ /**
47
+ * Get audio decoder configuration
48
+ */
49
+ async getAudioDecoderConfig() {
50
+ if (!this.loaded)
51
+ throw new Error("SimpleDemuxer: Must call load() before getting config");
52
+ return await this.demuxer.getDecoderConfig("audio");
53
+ }
54
+ /**
55
+ * Get a segment of encoded chunks as an array
56
+ * @param type Track type ('video' or 'audio')
57
+ * @param start Start time in seconds
58
+ * @param end End time in seconds
59
+ * @returns Array of encoded chunks
60
+ */
61
+ async getSegment(e, r, o) {
62
+ if (!this.loaded)
63
+ throw new Error("SimpleDemuxer: Must call load() before getting segments");
64
+ const d = this.demuxer.read(e, r, o), t = [], i = d.getReader();
65
+ try {
66
+ for (; ; ) {
67
+ const { done: s, value: n } = await i.read();
68
+ if (s) break;
69
+ t.push(n);
70
+ }
71
+ } finally {
72
+ i.releaseLock();
73
+ }
74
+ return t;
75
+ }
76
+ /**
77
+ * Get media information (tracks, duration, etc.)
78
+ */
79
+ async getMediaInfo() {
80
+ if (!this.loaded)
81
+ throw new Error("SimpleDemuxer: Must call load() before getting media info");
82
+ return await this.demuxer.getMediaInfo();
83
+ }
84
+ }
85
+ export {
86
+ h as SimpleDemuxer
87
+ };
@@ -0,0 +1,30 @@
1
+ /**
2
+ * In-memory storage system that stores data in fixed-size chunks
3
+ * and efficiently handles overlapping writes.
4
+ */
5
+ export declare class InMemoryStorage {
6
+ private chunks;
7
+ private _chunkSize;
8
+ private _size;
9
+ /**
10
+ * Create a new InMemoryStorage instance
11
+ * @param chunkSize Size of each chunk in bytes (default: 10MB)
12
+ */
13
+ constructor(chunkSize?: number);
14
+ /**
15
+ * Write data to storage, handling overlaps efficiently
16
+ * @param data Data to write
17
+ * @param position Position to write at
18
+ */
19
+ write(data: Uint8Array, position: number): void;
20
+ /**
21
+ * Get the total size of data written
22
+ */
23
+ get size(): number;
24
+ /**
25
+ * Convert all stored chunks to a single Blob
26
+ * @param type MIME type for the Blob
27
+ */
28
+ toBlob(type?: string): Blob;
29
+ }
30
+ //# sourceMappingURL=in-memory-storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"in-memory-storage.d.ts","sourceRoot":"","sources":["../src/in-memory-storage.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,qBAAa,eAAe;IACxB,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,KAAK,CAAK;IAElB;;;OAGG;gBACS,SAAS,GAAE,MAAyB;IAIhD;;;;OAIG;IACH,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IA2C/C;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;;OAGG;IACH,MAAM,CAAC,IAAI,GAAE,MAAmC,GAAG,IAAI;CAgC1D"}