mkvpeek 0.1.0
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/LICENSE +21 -0
- package/README.md +120 -0
- package/dist/browser.d.ts +12 -0
- package/dist/browser.js +3 -0
- package/dist/ebml.d.ts +168 -0
- package/dist/ebml.js +224 -0
- package/dist/entry/browser.d.ts +44 -0
- package/dist/entry/browser.js +9 -0
- package/dist/entry/node.d.ts +37 -0
- package/dist/entry/node.js +38 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +3 -0
- package/dist/io/file.d.ts +2 -0
- package/dist/io/file.js +47 -0
- package/dist/io/lanes.d.ts +17 -0
- package/dist/io/lanes.js +124 -0
- package/dist/io/memory.d.ts +2 -0
- package/dist/io/memory.js +16 -0
- package/dist/io/range.d.ts +22 -0
- package/dist/io/range.js +190 -0
- package/dist/io/source.d.ts +102 -0
- package/dist/io/source.js +31 -0
- package/dist/io/url-node.d.ts +10 -0
- package/dist/io/url-node.js +99 -0
- package/dist/io/url.d.ts +21 -0
- package/dist/io/url.js +80 -0
- package/dist/io/windows.d.ts +37 -0
- package/dist/io/windows.js +105 -0
- package/dist/matroska/block.d.ts +47 -0
- package/dist/matroska/block.js +114 -0
- package/dist/matroska/chain.d.ts +55 -0
- package/dist/matroska/chain.js +47 -0
- package/dist/matroska/clusters.d.ts +4 -0
- package/dist/matroska/clusters.js +232 -0
- package/dist/matroska/cues.d.ts +23 -0
- package/dist/matroska/cues.js +93 -0
- package/dist/matroska/header.d.ts +52 -0
- package/dist/matroska/header.js +531 -0
- package/dist/peek/contract.d.ts +57 -0
- package/dist/peek/contract.js +24 -0
- package/dist/peek/engine.d.ts +19 -0
- package/dist/peek/engine.js +32 -0
- package/dist/peek/target.d.ts +11 -0
- package/dist/peek/target.js +56 -0
- package/dist/subtitle/assemble.d.ts +21 -0
- package/dist/subtitle/assemble.js +114 -0
- package/dist/subtitle/conclude.d.ts +20 -0
- package/dist/subtitle/conclude.js +57 -0
- package/dist/subtitle/indexed.d.ts +5 -0
- package/dist/subtitle/indexed.js +172 -0
- package/dist/subtitle/options.d.ts +76 -0
- package/dist/subtitle/options.js +1 -0
- package/dist/subtitle/peek.d.ts +5 -0
- package/dist/subtitle/peek.js +107 -0
- package/dist/subtitle/tuning.d.ts +4 -0
- package/dist/subtitle/tuning.js +76 -0
- package/dist/subtitle/walked.d.ts +5 -0
- package/dist/subtitle/walked.js +28 -0
- package/dist/tracks/core.d.ts +25 -0
- package/dist/tracks/core.js +24 -0
- package/dist/tracks/list.d.ts +8 -0
- package/dist/tracks/list.js +6 -0
- package/dist/tracks/subtitle.d.ts +45 -0
- package/dist/tracks/subtitle.js +38 -0
- package/dist/vocabulary.d.ts +88 -0
- package/dist/vocabulary.js +10 -0
- package/package.json +68 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import * as E from "../ebml.js";
|
|
2
|
+
import { HaltableQueue, joinOrAbort } from "../io/lanes.js";
|
|
3
|
+
import { available, stopIfAborted, } from "../io/source.js";
|
|
4
|
+
import { windowAt, windowPool } from "../io/windows.js";
|
|
5
|
+
import { BLOCK_HEAD_BYTES, BLOCK_REFUSAL, frameIn, } from "./block.js";
|
|
6
|
+
import { CLUSTER_PROBE_BYTES, FRAME_IDS, hopTopLevel, readClusterTime, } from "./chain.js";
|
|
7
|
+
export async function walkFrames(pass, tracks, knobs, { onProgress, signal }) {
|
|
8
|
+
const fileSize = pass.head.fileSize;
|
|
9
|
+
onProgress(0, fileSize);
|
|
10
|
+
const slotBytes = Math.min(knobs.blockAheadBytes, fileSize);
|
|
11
|
+
const pool = windowPool(slotBytes, knobs.concurrency + 4);
|
|
12
|
+
const sized = { source: pass.source, fileSize };
|
|
13
|
+
const walk = { sized, tracks, knobs, head: pass.head };
|
|
14
|
+
let done = 0;
|
|
15
|
+
let refused = false;
|
|
16
|
+
const walked = new Map();
|
|
17
|
+
const record = (index, span, outcome) => {
|
|
18
|
+
if (typeof outcome === "string") {
|
|
19
|
+
refused = true;
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
walked.set(index, outcome.frames);
|
|
23
|
+
done += outcome.end - span.at;
|
|
24
|
+
onProgress(done, fileSize);
|
|
25
|
+
return true;
|
|
26
|
+
};
|
|
27
|
+
const queue = new HaltableQueue();
|
|
28
|
+
let count = 0;
|
|
29
|
+
const feed = async () => {
|
|
30
|
+
let seed;
|
|
31
|
+
try {
|
|
32
|
+
let pos = pass.segment.body;
|
|
33
|
+
while (!queue.halted) {
|
|
34
|
+
let openCluster = null;
|
|
35
|
+
for await (const { at, el, window } of hopTopLevel(pass, pos)) {
|
|
36
|
+
if (queue.halted)
|
|
37
|
+
return;
|
|
38
|
+
if (!TOP_LEVEL_IDS.has(el.id)) {
|
|
39
|
+
refused = true;
|
|
40
|
+
queue.halt();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (el.id !== E.ID.segment.CLUSTER)
|
|
44
|
+
continue;
|
|
45
|
+
if ("open" in el) {
|
|
46
|
+
openCluster = { index: count++, span: { at, el, end: pass.segment.end }, window };
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
const queued = { index: count++, span: { at, el, end: el.next }, window };
|
|
50
|
+
queue.push(queued);
|
|
51
|
+
}
|
|
52
|
+
if (openCluster === null)
|
|
53
|
+
break;
|
|
54
|
+
const outcome = await walkCluster(walk, openCluster.span, pool, seed ?? openCluster.window);
|
|
55
|
+
if (!record(openCluster.index, openCluster.span, outcome)) {
|
|
56
|
+
queue.halt();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (seed !== undefined && outcome.carried !== seed)
|
|
60
|
+
seed.release?.();
|
|
61
|
+
seed = outcome.carried;
|
|
62
|
+
pos = outcome.end;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
queue.halt();
|
|
67
|
+
if (!E.isGrammarError(error))
|
|
68
|
+
throw error;
|
|
69
|
+
refused = true;
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
queue.close();
|
|
73
|
+
seed?.release?.();
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
const eachCluster = async (item) => {
|
|
77
|
+
const outcome = await walkCluster(walk, item.span, pool, item.window);
|
|
78
|
+
const kept = record(item.index, item.span, outcome);
|
|
79
|
+
if (kept)
|
|
80
|
+
outcome.carried.release?.();
|
|
81
|
+
return kept;
|
|
82
|
+
};
|
|
83
|
+
const feeding = feed();
|
|
84
|
+
if (knobs.concurrency < 2) {
|
|
85
|
+
await feeding.then(() => { }, () => { });
|
|
86
|
+
}
|
|
87
|
+
const laneCount = Math.max(1, knobs.concurrency - 1);
|
|
88
|
+
const draining = queue.drain(laneCount, eachCluster, signal);
|
|
89
|
+
await joinOrAbort([feeding, draining], signal);
|
|
90
|
+
stopIfAborted(signal);
|
|
91
|
+
if (refused || count === 0)
|
|
92
|
+
return null;
|
|
93
|
+
onProgress(fileSize, fileSize);
|
|
94
|
+
return merged(walked);
|
|
95
|
+
}
|
|
96
|
+
const CLUSTER_CHILD_IDS = new Set([
|
|
97
|
+
...Object.values(E.ID.cluster),
|
|
98
|
+
...Object.values(E.ID.global),
|
|
99
|
+
]);
|
|
100
|
+
const CLUSTER_END_IDS = new Set(Object.values(E.ID.segment));
|
|
101
|
+
const TOP_LEVEL_IDS = new Set([...CLUSTER_END_IDS, ...Object.values(E.ID.global)]);
|
|
102
|
+
const STRAY_IDS = new Set(Object.values(E.ID.blockGroup));
|
|
103
|
+
async function walkCluster(walk, span, pool, seed) {
|
|
104
|
+
const ledger = new Set();
|
|
105
|
+
let outcome;
|
|
106
|
+
try {
|
|
107
|
+
const loans = { pool, ledger };
|
|
108
|
+
outcome = await walkSpan(walk, span, loans, seed);
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
releaseAll(ledger, true);
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
if (typeof outcome !== "string")
|
|
115
|
+
ledger.delete(outcome.carried);
|
|
116
|
+
releaseAll(ledger, false);
|
|
117
|
+
return outcome;
|
|
118
|
+
}
|
|
119
|
+
function releaseAll(ledger, swallow) {
|
|
120
|
+
let first = null;
|
|
121
|
+
for (const window of ledger) {
|
|
122
|
+
try {
|
|
123
|
+
window.release?.();
|
|
124
|
+
}
|
|
125
|
+
catch (error) {
|
|
126
|
+
first ??= error;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
if (first !== null && !swallow)
|
|
130
|
+
throw first;
|
|
131
|
+
}
|
|
132
|
+
async function walkSpan({ sized, tracks, knobs, head }, span, { pool, ledger }, seed) {
|
|
133
|
+
const widthFor = (at, need) => {
|
|
134
|
+
if (knobs.blockAheadBytes === 0)
|
|
135
|
+
return need;
|
|
136
|
+
const bound = Math.min(knobs.blockAheadBytes, span.end - at);
|
|
137
|
+
return Math.max(need, bound);
|
|
138
|
+
};
|
|
139
|
+
const first = widthFor(span.at, CLUSTER_PROBE_BYTES);
|
|
140
|
+
const fetchWindow = async (at, width) => {
|
|
141
|
+
const bounded = available(at, width, sized.fileSize);
|
|
142
|
+
if (E.covers(head, at, bounded))
|
|
143
|
+
return head;
|
|
144
|
+
const lease = pool.borrow(width);
|
|
145
|
+
if (lease === null)
|
|
146
|
+
return windowAt(sized, at, width);
|
|
147
|
+
let window;
|
|
148
|
+
try {
|
|
149
|
+
window = await windowAt(sized, at, width, lease.bytes);
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
lease.release();
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
if (window.bytes.buffer !== lease.bytes.buffer) {
|
|
156
|
+
lease.release();
|
|
157
|
+
return window;
|
|
158
|
+
}
|
|
159
|
+
const owned = { ...window, release: lease.release };
|
|
160
|
+
ledger.add(owned);
|
|
161
|
+
return owned;
|
|
162
|
+
};
|
|
163
|
+
const seeded = available(span.at, first, sized.fileSize);
|
|
164
|
+
const adopted = seed !== undefined && E.covers(seed, span.at, seeded) ? seed : null;
|
|
165
|
+
let carried = adopted ?? (await fetchWindow(span.at, first));
|
|
166
|
+
const clusterTime = readClusterTime(carried, span.el);
|
|
167
|
+
if (clusterTime === null)
|
|
168
|
+
return BLOCK_REFUSAL.noClusterTime;
|
|
169
|
+
const frames = new Map();
|
|
170
|
+
let pos = span.el.body;
|
|
171
|
+
const supply = async (at, need) => {
|
|
172
|
+
if (E.covers(carried, at, need))
|
|
173
|
+
return carried;
|
|
174
|
+
const width = widthFor(at, need);
|
|
175
|
+
const window = await fetchWindow(at, width);
|
|
176
|
+
if (E.reachOf(window) > E.reachOf(carried)) {
|
|
177
|
+
carried = window;
|
|
178
|
+
}
|
|
179
|
+
return window;
|
|
180
|
+
};
|
|
181
|
+
const claim = (track) => tracks.get(track) ?? null;
|
|
182
|
+
while (pos < span.end) {
|
|
183
|
+
const need = Math.min(BLOCK_HEAD_BYTES, span.end - pos);
|
|
184
|
+
const window = await supply(pos, need);
|
|
185
|
+
const el = E.readElement(window, pos);
|
|
186
|
+
if (typeof el === "string")
|
|
187
|
+
return BLOCK_REFUSAL.notAnElement;
|
|
188
|
+
if ("open" in el) {
|
|
189
|
+
if ("open" in span.el)
|
|
190
|
+
return { frames, end: pos, carried };
|
|
191
|
+
return BLOCK_REFUSAL.runsPastCluster;
|
|
192
|
+
}
|
|
193
|
+
if (STRAY_IDS.has(el.id))
|
|
194
|
+
return BLOCK_REFUSAL.strayBlock;
|
|
195
|
+
if (!CLUSTER_CHILD_IDS.has(el.id)) {
|
|
196
|
+
if ("open" in span.el && CLUSTER_END_IDS.has(el.id))
|
|
197
|
+
return { frames, end: pos, carried };
|
|
198
|
+
return BLOCK_REFUSAL.stranger;
|
|
199
|
+
}
|
|
200
|
+
if (el.next > span.end)
|
|
201
|
+
return BLOCK_REFUSAL.runsPastCluster;
|
|
202
|
+
if (FRAME_IDS.has(el.id)) {
|
|
203
|
+
const attributed = await frameIn(el, clusterTime, window, claim, supply);
|
|
204
|
+
if (typeof attributed === "string")
|
|
205
|
+
return attributed;
|
|
206
|
+
if (attributed !== null) {
|
|
207
|
+
const list = frames.get(attributed.track);
|
|
208
|
+
if (list === undefined)
|
|
209
|
+
frames.set(attributed.track, [attributed.frame]);
|
|
210
|
+
else
|
|
211
|
+
list.push(attributed.frame);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
pos = el.next;
|
|
215
|
+
}
|
|
216
|
+
return { frames, end: span.end, carried };
|
|
217
|
+
}
|
|
218
|
+
function merged(walked) {
|
|
219
|
+
const chunks = new Map();
|
|
220
|
+
const sorted = [...walked.entries()].sort(([a], [b]) => a - b);
|
|
221
|
+
for (const [, found] of sorted) {
|
|
222
|
+
for (const [track, frames] of found) {
|
|
223
|
+
const list = chunks.get(track);
|
|
224
|
+
if (list === undefined)
|
|
225
|
+
chunks.set(track, [frames]);
|
|
226
|
+
else
|
|
227
|
+
list.push(frames);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
const flattened = [...chunks].map(([track, lists]) => [track, lists.flat()]);
|
|
231
|
+
return new Map(flattened);
|
|
232
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Element, Window } from "../ebml.js";
|
|
2
|
+
import type { Range } from "../io/source.js";
|
|
3
|
+
import type { WindowIndex } from "../io/windows.js";
|
|
4
|
+
import { type BlockClause, type Frame } from "./block.js";
|
|
5
|
+
import type { CuePosition } from "./header.js";
|
|
6
|
+
/**
|
|
7
|
+
* The cluster the previous point named.
|
|
8
|
+
*
|
|
9
|
+
* Points naming the same cluster in a row share its element, its time and the last window.
|
|
10
|
+
*/
|
|
11
|
+
export interface ClusterMemo {
|
|
12
|
+
last: LastCluster | null;
|
|
13
|
+
}
|
|
14
|
+
interface LastCluster {
|
|
15
|
+
clusterPos: number;
|
|
16
|
+
cluster: Element;
|
|
17
|
+
clusterTime: number | null;
|
|
18
|
+
window: Window;
|
|
19
|
+
}
|
|
20
|
+
export declare function planRanges(points: readonly CuePosition[], cueAheadBytes: number): Range[];
|
|
21
|
+
export declare function planShortfall(windows: WindowIndex, points: readonly CuePosition[]): Range[];
|
|
22
|
+
export declare function readFrame(windows: WindowIndex, point: CuePosition, trackNumber: number, numbered: boolean, memo?: ClusterMemo): Promise<Frame | BlockClause>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import * as E from "../ebml.js";
|
|
2
|
+
import { BLOCK_REFUSAL, frameIn, } from "./block.js";
|
|
3
|
+
import { CLUSTER_PROBE_BYTES, ELEMENT_HEADER_BYTES, FRAME_IDS, headerNeed, readClusterTime, } from "./chain.js";
|
|
4
|
+
export function planRanges(points, cueAheadBytes) {
|
|
5
|
+
const ranges = [];
|
|
6
|
+
const clusters = new Set();
|
|
7
|
+
for (const { clusterPos, relPos } of points) {
|
|
8
|
+
if (!clusters.has(clusterPos)) {
|
|
9
|
+
clusters.add(clusterPos);
|
|
10
|
+
ranges.push({ at: clusterPos, length: CLUSTER_PROBE_BYTES });
|
|
11
|
+
}
|
|
12
|
+
ranges.push({
|
|
13
|
+
at: clusterPos + relPos,
|
|
14
|
+
length: MAX_CLUSTER_HEADER_BYTES + cueAheadBytes,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
return ranges;
|
|
18
|
+
}
|
|
19
|
+
export function planShortfall(windows, points) {
|
|
20
|
+
const ranges = [];
|
|
21
|
+
const memo = { last: null };
|
|
22
|
+
for (const point of points) {
|
|
23
|
+
const pointed = locateBlock(windows, point, memo);
|
|
24
|
+
if (typeof pointed === "string")
|
|
25
|
+
continue;
|
|
26
|
+
const { window, blockAt, outer } = pointed;
|
|
27
|
+
const covered = E.reachOf(window);
|
|
28
|
+
if (outer.next > covered) {
|
|
29
|
+
ranges.push({ at: blockAt, length: outer.next - blockAt });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return ranges;
|
|
33
|
+
}
|
|
34
|
+
export async function readFrame(windows, point, trackNumber, numbered, memo = { last: null }) {
|
|
35
|
+
const pointed = locateBlock(windows, point, memo);
|
|
36
|
+
if (typeof pointed === "string")
|
|
37
|
+
return pointed;
|
|
38
|
+
const { clusterTime, window, outer } = pointed;
|
|
39
|
+
if (clusterTime === null)
|
|
40
|
+
return BLOCK_REFUSAL.noClusterTime;
|
|
41
|
+
const claim = (track) => (track === trackNumber ? numbered : null);
|
|
42
|
+
const supply = (at, need) => {
|
|
43
|
+
const window = windows.find(at, need);
|
|
44
|
+
if (window === null)
|
|
45
|
+
throw new E.GrammarError();
|
|
46
|
+
return Promise.resolve(window);
|
|
47
|
+
};
|
|
48
|
+
try {
|
|
49
|
+
const claimed = await frameIn(outer, clusterTime, window, claim, supply);
|
|
50
|
+
if (claimed === null)
|
|
51
|
+
return BLOCK_REFUSAL.notThisTrack;
|
|
52
|
+
return typeof claimed === "string" ? claimed : claimed.frame;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (!E.isGrammarError(error))
|
|
56
|
+
throw error;
|
|
57
|
+
return BLOCK_REFUSAL.notFetched;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const MAX_CLUSTER_HEADER_BYTES = 4 + E.MAX_VINT_BYTES;
|
|
61
|
+
function locateBlock(windows, { clusterPos, relPos }, memo) {
|
|
62
|
+
let last = memo.last;
|
|
63
|
+
if (last === null || last.clusterPos !== clusterPos) {
|
|
64
|
+
const head = windows.find(clusterPos, ELEMENT_HEADER_BYTES);
|
|
65
|
+
if (head === null)
|
|
66
|
+
return BLOCK_REFUSAL.notFetched;
|
|
67
|
+
const cluster = E.readElement(head, clusterPos);
|
|
68
|
+
if (typeof cluster === "string" || cluster.id !== E.ID.segment.CLUSTER) {
|
|
69
|
+
return BLOCK_REFUSAL.notACluster;
|
|
70
|
+
}
|
|
71
|
+
if ("open" in cluster)
|
|
72
|
+
return BLOCK_REFUSAL.openCluster;
|
|
73
|
+
const clusterTime = readClusterTime(head, cluster);
|
|
74
|
+
last = { clusterPos, cluster, clusterTime, window: head };
|
|
75
|
+
memo.last = last;
|
|
76
|
+
}
|
|
77
|
+
const { cluster, clusterTime } = last;
|
|
78
|
+
if (relPos >= cluster.size)
|
|
79
|
+
return BLOCK_REFUSAL.pastTheCluster;
|
|
80
|
+
const blockAt = cluster.body + relPos;
|
|
81
|
+
const bound = headerNeed(blockAt, cluster.next);
|
|
82
|
+
const held = last.window;
|
|
83
|
+
const window = E.covers(held, blockAt, bound) ? held : windows.find(blockAt, bound);
|
|
84
|
+
if (window === null)
|
|
85
|
+
return BLOCK_REFUSAL.notFetched;
|
|
86
|
+
last.window = window;
|
|
87
|
+
const outer = E.readElement(window, blockAt);
|
|
88
|
+
if (!E.fits(outer, cluster.next))
|
|
89
|
+
return BLOCK_REFUSAL.runsPastCluster;
|
|
90
|
+
if (!FRAME_IDS.has(outer.id))
|
|
91
|
+
return BLOCK_REFUSAL.notABlock;
|
|
92
|
+
return { clusterTime, window, blockAt, outer };
|
|
93
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { Window } from "../ebml.js";
|
|
2
|
+
import { type Source } from "../io/source.js";
|
|
3
|
+
import type { Attachment, ContainerInfo, RefusalCode, TrackFlags, TrackTag, Wants } from "../vocabulary.js";
|
|
4
|
+
import { type Segment } from "./chain.js";
|
|
5
|
+
export interface TrackEntry {
|
|
6
|
+
streamIndex: number;
|
|
7
|
+
number: number;
|
|
8
|
+
uid: string | null;
|
|
9
|
+
codecId: string;
|
|
10
|
+
codecPrivate: string;
|
|
11
|
+
codecDelayNs: number;
|
|
12
|
+
type: number;
|
|
13
|
+
language: string | null;
|
|
14
|
+
languageIetf: string | null;
|
|
15
|
+
name: string | null;
|
|
16
|
+
flags: TrackFlags;
|
|
17
|
+
encoded: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface CuePosition {
|
|
20
|
+
clusterPos: number;
|
|
21
|
+
relPos: number;
|
|
22
|
+
}
|
|
23
|
+
/** @see {@linkcode readContainer|readContainer(source, "tracks")} */
|
|
24
|
+
export interface TracksHeader {
|
|
25
|
+
segment: Segment;
|
|
26
|
+
trackEntries: TrackEntry[];
|
|
27
|
+
fileSize: number;
|
|
28
|
+
trackTags: Map<string, TrackTag[]>;
|
|
29
|
+
info: ContainerInfo;
|
|
30
|
+
attachments: Attachment[];
|
|
31
|
+
}
|
|
32
|
+
/** @see {@linkcode readContainer|readContainer(source, "timed")} */
|
|
33
|
+
export interface TimedHeader extends TracksHeader {
|
|
34
|
+
head: Window;
|
|
35
|
+
firstClusterTicks: number | null;
|
|
36
|
+
}
|
|
37
|
+
/** @see {@linkcode readContainer|readContainer(source, "indexed")} */
|
|
38
|
+
export interface IndexedHeader extends TimedHeader {
|
|
39
|
+
cues: Map<number, CuePosition[]>;
|
|
40
|
+
}
|
|
41
|
+
interface ContainerReadOptions extends Wants {
|
|
42
|
+
concurrency?: number | undefined;
|
|
43
|
+
signal?: AbortSignal | undefined;
|
|
44
|
+
}
|
|
45
|
+
export declare function readContainer(source: Source, depth: "tracks", options: ContainerReadOptions): Promise<TracksHeader | RefusalCode>;
|
|
46
|
+
export declare function readContainer(source: Source, depth: "timed", options: ContainerReadOptions & {
|
|
47
|
+
concurrency: number;
|
|
48
|
+
}): Promise<TimedHeader | RefusalCode>;
|
|
49
|
+
export declare function readContainer(source: Source, depth: "indexed", options: ContainerReadOptions & {
|
|
50
|
+
concurrency: number;
|
|
51
|
+
}): Promise<IndexedHeader | RefusalCode>;
|
|
52
|
+
export {};
|