video-fps-probe 0.2.0 → 0.3.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/CHANGELOG.md +51 -0
- package/README.md +26 -14
- package/dist/api/errors.js +1 -1
- package/dist/api/guards.d.ts +2 -0
- package/dist/api/guards.js +2 -1
- package/dist/check/index.js +12 -2
- package/dist/client/compare.js +2 -2
- package/dist/client/create.d.ts +3 -0
- package/dist/client/create.js +8 -0
- package/dist/client/fallback.js +2 -2
- package/dist/client/index.d.ts +1 -1
- package/dist/client/index.js +1 -1
- package/dist/client/inline.js +1 -1
- package/dist/client/lazy.js +1 -1
- package/dist/client/probe-client.js +4 -0
- package/dist/client/probe.js +23 -22
- package/dist/client/route.js +20 -0
- package/dist/client/split.js +9 -0
- package/dist/client/stub.js +2 -2
- package/dist/client/types.d.ts +1 -0
- package/dist/core/analyze.js +4 -78
- package/dist/core/dispatch.js +76 -0
- package/dist/core/isobmff/boxes.js +4 -7
- package/dist/core/isobmff/index.js +8 -5
- package/dist/core/isobmff/model.js +1 -1
- package/dist/core/isobmff/moov.js +12 -7
- package/dist/core/isobmff/track.js +4 -2
- package/dist/core/matroska/ebml.js +1 -1
- package/dist/core/reader.d.ts +0 -12
- package/dist/core/reader.js +10 -27
- package/dist/engines/common.js +6 -0
- package/dist/engines/mediabunny.js +17 -4
- package/dist/engines/mp4box.js +2 -1
- package/dist/plugins/own.js +5 -2
- package/dist/presets/index.d.ts +1 -0
- package/dist/presets/sources.json +8 -0
- package/dist/probe.js +2 -1
- package/dist/react/store.js +1 -1
- package/dist/standalone/own-isobmff.worker.js +1 -0
- package/dist/standalone/own-matroska.worker.js +1 -0
- package/dist/standalone/own.worker.js +1 -1
- package/dist/worker/own-isobmff.worker.js +4 -0
- package/dist/worker/own-matroska.worker.js +4 -0
- package/dist/worker/runtime.d.ts +2 -3
- package/dist/worker/runtime.js +2 -97
- package/dist/worker/serve.d.ts +3 -0
- package/dist/worker/serve.js +97 -0
- package/dist/worker/single.js +13 -0
- package/package.json +8 -2
- package/dist/client/inline.d.ts +0 -19
- package/dist/client/pool.d.ts +0 -29
- package/dist/client/probe.d.ts +0 -29
|
@@ -5,9 +5,6 @@ export class IsoBmffError extends Error {
|
|
|
5
5
|
this.name = 'IsoBmffError';
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
|
-
function printable(type) {
|
|
9
|
-
return type.replace(/[^\x20-\x7e]/g, '?');
|
|
10
|
-
}
|
|
11
8
|
export const MAX_BOX_HEADER = 32;
|
|
12
9
|
export function readBoxHeader(dv, p, parentEnd, base = 0) {
|
|
13
10
|
const avail = Math.min(dv.byteLength, parentEnd);
|
|
@@ -22,7 +19,7 @@ export function readBoxHeader(dv, p, parentEnd, base = 0) {
|
|
|
22
19
|
return null;
|
|
23
20
|
const big = dv.getBigUint64(p + 8);
|
|
24
21
|
if (big > BigInt(Number.MAX_SAFE_INTEGER))
|
|
25
|
-
throw new IsoBmffError(`corrupt file: box '${
|
|
22
|
+
throw new IsoBmffError(`corrupt file: box '${type}' at ${base + p} has a size above 2^53-1`);
|
|
26
23
|
size = Number(big);
|
|
27
24
|
headerSize = 16;
|
|
28
25
|
}
|
|
@@ -32,7 +29,7 @@ export function readBoxHeader(dv, p, parentEnd, base = 0) {
|
|
|
32
29
|
if (type === 'uuid')
|
|
33
30
|
headerSize += 16;
|
|
34
31
|
if (size < headerSize)
|
|
35
|
-
throw new IsoBmffError(`corrupt file: box '${
|
|
32
|
+
throw new IsoBmffError(`corrupt file: box '${type}' at ${base + p} is smaller than its header`);
|
|
36
33
|
const end = p + size;
|
|
37
34
|
return { type, start: p, size, headerSize, end: Math.min(end, parentEnd), truncated: end > parentEnd };
|
|
38
35
|
}
|
|
@@ -56,13 +53,13 @@ export function* childBoxes(dv, start, end, warnings) {
|
|
|
56
53
|
export function boxU64(dv, p, box, at) {
|
|
57
54
|
const v = dv.getBigUint64(p);
|
|
58
55
|
if (v > BigInt(Number.MAX_SAFE_INTEGER))
|
|
59
|
-
throw new IsoBmffError(`unsupported: box '${
|
|
56
|
+
throw new IsoBmffError(`unsupported: box '${box}' at ${at} holds a value above 2^53-1`);
|
|
60
57
|
return Number(v);
|
|
61
58
|
}
|
|
62
59
|
export function boxI64(dv, p, box, at) {
|
|
63
60
|
const v = dv.getBigInt64(p);
|
|
64
61
|
if (v > BigInt(Number.MAX_SAFE_INTEGER) || v < -BigInt(Number.MAX_SAFE_INTEGER)) {
|
|
65
|
-
throw new IsoBmffError(`unsupported: box '${
|
|
62
|
+
throw new IsoBmffError(`unsupported: box '${box}' at ${at} holds a value beyond 2^53-1`);
|
|
66
63
|
}
|
|
67
64
|
return Number(v);
|
|
68
65
|
}
|
|
@@ -16,7 +16,7 @@ const MAX_TOP_LEVEL_BOXES = 4_000_000;
|
|
|
16
16
|
const SMALL_MDAT = 64 * 1024;
|
|
17
17
|
const HEADER_PEEK = 16;
|
|
18
18
|
function isAbort(e, reader) {
|
|
19
|
-
return reader.signal?.aborted === true ||
|
|
19
|
+
return reader.signal?.aborted === true || e?.name === 'AbortError';
|
|
20
20
|
}
|
|
21
21
|
function containerOf(movie) {
|
|
22
22
|
return movie.brand === 'qt ' || (!movie.hasFtyp && movie.topLevel.length > 0) ? 'mov' : 'mp4';
|
|
@@ -66,12 +66,15 @@ async function walk(reader, opts, movie) {
|
|
|
66
66
|
break;
|
|
67
67
|
const h = { ...rel, start: pos, end: Math.min(pos + rel.size, size) };
|
|
68
68
|
const boxEnd = pos + rel.size;
|
|
69
|
+
const trailer = rel.truncated && sawMoov && h.type !== 'mdat' && h.type !== 'moof';
|
|
69
70
|
if (rel.truncated) {
|
|
70
71
|
movie.truncated = true;
|
|
71
|
-
movie.warnings.push(`'${h.type}' at ${pos} is truncated`);
|
|
72
|
+
movie.warnings.push(trailer ? `ignored trailing data at ${pos}: not a box` : `'${h.type}' at ${pos} is truncated`);
|
|
72
73
|
}
|
|
73
74
|
const top = { type: h.type, start: pos, end: h.end, sidx: null };
|
|
74
75
|
movie.topLevel.push(top);
|
|
76
|
+
if (trailer)
|
|
77
|
+
break;
|
|
75
78
|
if (h.type === 'ftyp') {
|
|
76
79
|
const fv = await reader.view(pos, Math.min(h.size, 1024));
|
|
77
80
|
const p = h.headerSize;
|
|
@@ -231,7 +234,7 @@ function buildVideoTrack(tr, movie, opts, ctx) {
|
|
|
231
234
|
w.push('avg_frame_rate of ffprobe is not reproduced: its header values are incomplete or overrun a box');
|
|
232
235
|
const r = ctx.ffprobeFails || broken ? null : ffprobeStage1Rate(tr, movie, totals.moovSamples, opts.maxExpandedSamples, w);
|
|
233
236
|
t.rFpsFfprobe = r ? toFfprobeString(r) : null;
|
|
234
|
-
const edits = editInfo(tr, movie.timescale);
|
|
237
|
+
const edits = editInfo(tr, movie.timescale, totals);
|
|
235
238
|
if (!broken) {
|
|
236
239
|
const timing = trackTiming(tr, movie, totals, edits);
|
|
237
240
|
t.durationSec = timing.durationTs / ts;
|
|
@@ -335,7 +338,7 @@ function formatDuration(movie, videoTracks) {
|
|
|
335
338
|
continue;
|
|
336
339
|
}
|
|
337
340
|
const totals = sampleTotals(tr);
|
|
338
|
-
const timing = trackTiming(tr, movie, totals, editInfo(tr, movie.timescale));
|
|
341
|
+
const timing = trackTiming(tr, movie, totals, editInfo(tr, movie.timescale, totals));
|
|
339
342
|
const d = rescaleRound(timing.durationTs, 1e6, tr.timescale);
|
|
340
343
|
if (timing.startPts !== null) {
|
|
341
344
|
const s = rescaleRound(timing.startPts, 1e6, tr.timescale);
|
|
@@ -383,7 +386,7 @@ export async function analyzeIsoBmffDetailed(reader, opts) {
|
|
|
383
386
|
if (isAbort(e, reader))
|
|
384
387
|
throw e;
|
|
385
388
|
const message = e instanceof Error ? e.message : String(e);
|
|
386
|
-
const analysis = emptyAnalysis(containerOf(movie), e instanceof IsoBmffError ? message : `corrupt file: ${message}`);
|
|
389
|
+
const analysis = emptyAnalysis(containerOf(movie), e instanceof IsoBmffError || message.startsWith(`file read failed`) ? message : `corrupt file: ${message}`);
|
|
387
390
|
analysis.brand = movie.brand;
|
|
388
391
|
analysis.warnings = movie.warnings;
|
|
389
392
|
return { analysis, movie };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export const TO_MEDIA_END = Number.MAX_SAFE_INTEGER;
|
|
1
2
|
export const IDENTITY_MATRIX = [65536, 0, 0, 0, 65536, 0, 0, 0, 1 << 30];
|
|
2
3
|
export function newMovie(fileSize) {
|
|
3
4
|
return {
|
|
@@ -13,7 +14,6 @@ export function newMovie(fileSize) {
|
|
|
13
14
|
chapterTrackIds: new Set(),
|
|
14
15
|
hasMvex: false,
|
|
15
16
|
trex: new Map(),
|
|
16
|
-
mehdDuration: null,
|
|
17
17
|
moofCount: 0,
|
|
18
18
|
topLevel: [],
|
|
19
19
|
truncated: false,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { fourcc } from "../reader.js";
|
|
2
2
|
import { boundEntries, boxI64, boxU64, childBoxes, IsoBmffError, readBoxHeader } from "./boxes.js";
|
|
3
|
-
import { newTrack } from "./model.js";
|
|
3
|
+
import { newTrack, TO_MEDIA_END } from "./model.js";
|
|
4
4
|
export const MAX_STTS_DELTA = 4294487295;
|
|
5
5
|
const UINT32_ALL_ONES = 0xffffffff;
|
|
6
6
|
function children(dv, h, ctx, skip = 0) {
|
|
@@ -105,7 +105,7 @@ export function parseCtts(dv, h, tr) {
|
|
|
105
105
|
tr.cttsOffsets = Int32Array.from(offsets);
|
|
106
106
|
tr.dtsShift = shift;
|
|
107
107
|
}
|
|
108
|
-
function parseElst(dv, h, tr, ctx) {
|
|
108
|
+
function parseElst(dv, h, tr, ctx, movie) {
|
|
109
109
|
const p = payload(h);
|
|
110
110
|
if (p + 8 > h.end)
|
|
111
111
|
return;
|
|
@@ -125,8 +125,15 @@ function parseElst(dv, h, tr, ctx) {
|
|
|
125
125
|
const at = ctx.base + h.start;
|
|
126
126
|
for (let i = 0; i < n; i++) {
|
|
127
127
|
const o = p + 8 + i * size;
|
|
128
|
-
if (v === 1)
|
|
129
|
-
|
|
128
|
+
if (v === 1) {
|
|
129
|
+
const mediaTime = boxI64(dv, o + 8, 'elst', at);
|
|
130
|
+
const unknown = dv.getBigInt64(o) === -1n;
|
|
131
|
+
if (unknown) {
|
|
132
|
+
tr.warnings.push(`unknown elst duration: ${mediaTime === -1 ? 'the empty edit is ignored' : 'the edit lasts to the end'}`);
|
|
133
|
+
movie.ffprobeReject ??= { moof: -1, reason: 'rejects this file: an elst duration of -1' };
|
|
134
|
+
}
|
|
135
|
+
tr.edits.push({ duration: !unknown ? boxU64(dv, o, 'elst', at) : mediaTime === -1 ? 0 : TO_MEDIA_END, mediaTime, rate: dv.getInt32(o + 16) / 65536 });
|
|
136
|
+
}
|
|
130
137
|
else
|
|
131
138
|
tr.edits.push({ duration: dv.getUint32(o), mediaTime: dv.getInt32(o + 4), rate: dv.getInt32(o + 8) / 65536 });
|
|
132
139
|
}
|
|
@@ -287,7 +294,7 @@ function parseTrak(dv, h, movie, ctx) {
|
|
|
287
294
|
else if (c.type === 'edts') {
|
|
288
295
|
for (const e of children(dv, c, ctx))
|
|
289
296
|
if (e.type === 'elst')
|
|
290
|
-
parseElst(dv, e, tr, ctx);
|
|
297
|
+
parseElst(dv, e, tr, ctx, movie);
|
|
291
298
|
}
|
|
292
299
|
else if (c.type === 'mdia') {
|
|
293
300
|
parseMdia(dv, c, tr, ctx);
|
|
@@ -330,8 +337,6 @@ export function parseMoov(dv, h, movie, strict, base = 0) {
|
|
|
330
337
|
const q = payload(m);
|
|
331
338
|
if (m.type === 'trex' && q + 24 <= m.end)
|
|
332
339
|
movie.trex.set(dv.getUint32(q + 4), { duration: dv.getUint32(q + 12), size: dv.getUint32(q + 16) });
|
|
333
|
-
else if (m.type === 'mehd' && q + 8 <= m.end)
|
|
334
|
-
movie.mehdDuration = dv.getUint8(q) === 1 && q + 12 <= m.end ? boxU64(dv, q + 4, 'mehd', base + m.start) : dv.getUint32(q + 4);
|
|
335
340
|
}
|
|
336
341
|
break;
|
|
337
342
|
case 'cmov':
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { INT_MAX, reduceRational, toFfprobeString } from "../rational.js";
|
|
2
|
+
import { TO_MEDIA_END } from "./model.js";
|
|
2
3
|
export function rescaleRound(a, b, c) {
|
|
3
4
|
if (!(c > 0))
|
|
4
5
|
return 0;
|
|
@@ -62,13 +63,14 @@ export function missingMandatoryAtoms(tr) {
|
|
|
62
63
|
const samples = tr.sampleCount ?? 0;
|
|
63
64
|
return (chunks > 0 && (!stts || declared(tr.stsc) === 0 || (tr.sampleSize === 0 && samples === 0))) || (samples > 0 && chunks === 0);
|
|
64
65
|
}
|
|
65
|
-
export function editInfo(tr, movieTimescale) {
|
|
66
|
+
export function editInfo(tr, movieTimescale, totals) {
|
|
66
67
|
let emptyBefore = 0;
|
|
67
68
|
let editSum = 0;
|
|
68
69
|
let mediaEdits = 0;
|
|
69
70
|
let firstMedia = null;
|
|
71
|
+
const mediaEnd = (tr.cttsOffsets?.[0] ?? 0) + totals.moovDuration;
|
|
70
72
|
for (const e of tr.edits) {
|
|
71
|
-
const d = rescaleRound(e.duration, tr.timescale, movieTimescale);
|
|
73
|
+
const d = e.duration === TO_MEDIA_END ? Math.max(0, mediaEnd - e.mediaTime) : rescaleRound(e.duration, tr.timescale, movieTimescale);
|
|
72
74
|
editSum += d;
|
|
73
75
|
if (e.mediaTime === -1) {
|
|
74
76
|
if (!firstMedia)
|
|
@@ -146,7 +146,7 @@ export function readString(b, p, n) {
|
|
|
146
146
|
let e = p;
|
|
147
147
|
while (e < p + n && b[e] !== 0)
|
|
148
148
|
e++;
|
|
149
|
-
return utf8.decode(b.subarray(p, e));
|
|
149
|
+
return utf8.decode(b.subarray(p, e)).replace(/[^\x20-\x7e\xa0-\uffff]/g, '?');
|
|
150
150
|
}
|
|
151
151
|
export function* children(b, start, end) {
|
|
152
152
|
let p = start;
|
package/dist/core/reader.d.ts
CHANGED
|
@@ -10,17 +10,9 @@ export interface BlobReaderOptions {
|
|
|
10
10
|
maxWindows?: number;
|
|
11
11
|
signal?: AbortSignal | null;
|
|
12
12
|
}
|
|
13
|
-
export interface ReaderStats {
|
|
14
|
-
reads: number;
|
|
15
|
-
bytesFetched: number;
|
|
16
|
-
bytesTransferred: number;
|
|
17
|
-
}
|
|
18
13
|
export declare const DEFAULT_HEAD_WINDOW: number;
|
|
19
14
|
export declare const DEFAULT_MAX_WINDOWS = 4;
|
|
20
15
|
export declare const MAX_SAFE_OFFSET: number;
|
|
21
|
-
export declare class EndOfFileError extends Error {
|
|
22
|
-
constructor(message: string);
|
|
23
|
-
}
|
|
24
16
|
export declare function toSafeNumber(value: bigint, what?: string): number;
|
|
25
17
|
export declare class BlobReader {
|
|
26
18
|
#private;
|
|
@@ -31,16 +23,12 @@ export declare class BlobReader {
|
|
|
31
23
|
constructor(source: BlobLike, options?: BlobReaderOptions);
|
|
32
24
|
get reads(): number;
|
|
33
25
|
get bytesFetched(): number;
|
|
34
|
-
get bytesTransferred(): number;
|
|
35
|
-
stats(): ReaderStats;
|
|
36
26
|
checkAbort(): void;
|
|
37
27
|
read(offset: number, length: number): Promise<Uint8Array>;
|
|
38
28
|
readMany(ranges: ReadonlyArray<readonly [offset: number, length: number]>, concurrency?: number): Promise<Uint8Array[]>;
|
|
39
29
|
peek(offset: number, length: number): DataView | null;
|
|
40
30
|
view(offset: number, length: number, readAhead?: number): Promise<DataView>;
|
|
41
|
-
viewExact(offset: number, length: number, readAhead?: number): Promise<DataView>;
|
|
42
31
|
bytes(offset: number, length: number, readAhead?: number): Promise<Uint8Array>;
|
|
43
|
-
clearCache(): void;
|
|
44
32
|
}
|
|
45
33
|
export declare function u8(dv: DataView, p: number): number;
|
|
46
34
|
export declare function u16(dv: DataView, p: number): number;
|
package/dist/core/reader.js
CHANGED
|
@@ -2,12 +2,6 @@ import { throwIfAborted } from "./abort.js";
|
|
|
2
2
|
export const DEFAULT_HEAD_WINDOW = 64 * 1024;
|
|
3
3
|
export const DEFAULT_MAX_WINDOWS = 4;
|
|
4
4
|
export const MAX_SAFE_OFFSET = Number.MAX_SAFE_INTEGER;
|
|
5
|
-
export class EndOfFileError extends Error {
|
|
6
|
-
constructor(message) {
|
|
7
|
-
super(message);
|
|
8
|
-
this.name = 'EndOfFileError';
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
5
|
function assertSafeCount(value, what) {
|
|
12
6
|
if (!Number.isSafeInteger(value) || value < 0)
|
|
13
7
|
throw new RangeError(`${what} must be a non-negative safe integer, got ${value}`);
|
|
@@ -27,7 +21,6 @@ export class BlobReader {
|
|
|
27
21
|
#covered = [];
|
|
28
22
|
#reads = 0;
|
|
29
23
|
#unique = 0;
|
|
30
|
-
#transferred = 0;
|
|
31
24
|
constructor(source, options = {}) {
|
|
32
25
|
assertSafeCount(source.size, 'blob size');
|
|
33
26
|
this.#source = source;
|
|
@@ -43,12 +36,6 @@ export class BlobReader {
|
|
|
43
36
|
get bytesFetched() {
|
|
44
37
|
return this.#unique;
|
|
45
38
|
}
|
|
46
|
-
get bytesTransferred() {
|
|
47
|
-
return this.#transferred;
|
|
48
|
-
}
|
|
49
|
-
stats() {
|
|
50
|
-
return { reads: this.#reads, bytesFetched: this.#unique, bytesTransferred: this.#transferred };
|
|
51
|
-
}
|
|
52
39
|
checkAbort() {
|
|
53
40
|
throwIfAborted(this.signal);
|
|
54
41
|
}
|
|
@@ -61,12 +48,18 @@ export class BlobReader {
|
|
|
61
48
|
if (end === offset)
|
|
62
49
|
return new Uint8Array(0);
|
|
63
50
|
this.checkAbort();
|
|
64
|
-
|
|
51
|
+
let ab;
|
|
52
|
+
try {
|
|
53
|
+
ab = await this.#source.slice(offset, end).arrayBuffer();
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
this.checkAbort();
|
|
57
|
+
throw e?.name === 'AbortError' ? e : Error(`file read failed: ${e}`);
|
|
58
|
+
}
|
|
65
59
|
this.checkAbort();
|
|
66
60
|
this.#reads++;
|
|
67
|
-
this.#transferred += ab.byteLength;
|
|
68
61
|
if (ab.byteLength !== end - offset) {
|
|
69
|
-
throw
|
|
62
|
+
throw Error(`file read failed: short read at ${offset}: expected ${end - offset} bytes, got ${ab.byteLength}`);
|
|
70
63
|
}
|
|
71
64
|
this.#cover(offset, end);
|
|
72
65
|
return new Uint8Array(ab);
|
|
@@ -132,20 +125,10 @@ export class BlobReader {
|
|
|
132
125
|
this.#windows.length = this.maxWindows;
|
|
133
126
|
return new DataView(buf.buffer, buf.byteOffset, end - offset);
|
|
134
127
|
}
|
|
135
|
-
async viewExact(offset, length, readAhead = this.headWindow) {
|
|
136
|
-
const dv = await this.view(offset, length, readAhead);
|
|
137
|
-
if (dv.byteLength < length) {
|
|
138
|
-
throw new EndOfFileError(`unexpected end of file: wanted ${length} bytes at ${offset}, file size ${this.size}`);
|
|
139
|
-
}
|
|
140
|
-
return dv;
|
|
141
|
-
}
|
|
142
128
|
async bytes(offset, length, readAhead = this.headWindow) {
|
|
143
129
|
const dv = await this.view(offset, length, readAhead);
|
|
144
130
|
return new Uint8Array(dv.buffer, dv.byteOffset, dv.byteLength);
|
|
145
131
|
}
|
|
146
|
-
clearCache() {
|
|
147
|
-
this.#windows = [];
|
|
148
|
-
}
|
|
149
132
|
#cover(start, end) {
|
|
150
133
|
const list = this.#covered;
|
|
151
134
|
let lo = 0;
|
|
@@ -213,5 +196,5 @@ export function ascii(dv, p, length) {
|
|
|
213
196
|
return s;
|
|
214
197
|
}
|
|
215
198
|
export function fourcc(dv, p) {
|
|
216
|
-
return ascii(dv, p, 4);
|
|
199
|
+
return ascii(dv, p, 4).replace(/[^ -~]/g, '?');
|
|
217
200
|
}
|
package/dist/engines/common.js
CHANGED
|
@@ -53,6 +53,12 @@ export function isAbort(e, signal) {
|
|
|
53
53
|
export function newResult(name, size, engine) {
|
|
54
54
|
return { name, size, ...emptyAnalysis('unknown'), io: { reads: 0, bytesRead: 0, ms: 0 }, engine };
|
|
55
55
|
}
|
|
56
|
+
const printable = (warnings) => warnings.map((w) => w.replace(/[^\x20-\x7e\xa0-\uffff]/g, '?'));
|
|
57
|
+
export function printableWarnings(result) {
|
|
58
|
+
result.warnings = printable(result.warnings);
|
|
59
|
+
for (const t of result.videoTracks)
|
|
60
|
+
t.warnings = printable(t.warnings);
|
|
61
|
+
}
|
|
56
62
|
export function ffprobeRotation(matrix) {
|
|
57
63
|
const a = matrix[0] / 65536;
|
|
58
64
|
const b = matrix[1] / 65536;
|
|
@@ -3,7 +3,7 @@ import { throwIfAborted } from "../core/abort.js";
|
|
|
3
3
|
import { resolveOptions } from "../core/options.js";
|
|
4
4
|
import { emptyTrack } from "../core/result.js";
|
|
5
5
|
import { analyzeTimeline } from "../core/stats.js";
|
|
6
|
-
import { applyStats, approxRational, codecNameFromFourcc, errorMessage, isAbort, newResult } from "./common.js";
|
|
6
|
+
import { applyStats, approxRational, codecNameFromFourcc, errorMessage, isAbort, newResult, printableWarnings } from "./common.js";
|
|
7
7
|
import { CountingBlob, elapsed, now } from "./counting.js";
|
|
8
8
|
export const MEDIABUNNY_VERSION = '1.62.1';
|
|
9
9
|
const CODEC_NAMES = {
|
|
@@ -145,7 +145,18 @@ async function probe(counted, result, opts, t0) {
|
|
|
145
145
|
];
|
|
146
146
|
const source = new CustomSource({
|
|
147
147
|
getSize: () => counted.size,
|
|
148
|
-
read: async (start, end) =>
|
|
148
|
+
read: async (start, end) => {
|
|
149
|
+
let ab;
|
|
150
|
+
try {
|
|
151
|
+
ab = await counted.slice(start, end).arrayBuffer();
|
|
152
|
+
}
|
|
153
|
+
catch (e) {
|
|
154
|
+
throw isAbort(e, signal) ? e : Error(`file read failed: ${e}`);
|
|
155
|
+
}
|
|
156
|
+
if (ab.byteLength !== end - start)
|
|
157
|
+
throw Error(`file read failed: short read at ${start}: expected ${end - start} bytes, got ${ab.byteLength}`);
|
|
158
|
+
return new Uint8Array(ab);
|
|
159
|
+
},
|
|
149
160
|
prefetchProfile: 'fileSystem',
|
|
150
161
|
handleUnhandledError: (e) => {
|
|
151
162
|
unhandled.push(errorMessage(e));
|
|
@@ -160,7 +171,8 @@ async function probe(counted, result, opts, t0) {
|
|
|
160
171
|
catch (e) {
|
|
161
172
|
if (isAbort(e, signal))
|
|
162
173
|
throw e;
|
|
163
|
-
|
|
174
|
+
const message = errorMessage(e);
|
|
175
|
+
result.error = message.startsWith('file read failed') ? message : `not a recognised container: ${message}`;
|
|
164
176
|
return;
|
|
165
177
|
}
|
|
166
178
|
result.container = containerOf(format);
|
|
@@ -176,7 +188,7 @@ async function probe(counted, result, opts, t0) {
|
|
|
176
188
|
works.push(await collectTrack(track, quantized, signal, maxPackets));
|
|
177
189
|
}
|
|
178
190
|
catch (e) {
|
|
179
|
-
if (isAbort(e, signal))
|
|
191
|
+
if (isAbort(e, signal) || errorMessage(e).startsWith('file read failed'))
|
|
180
192
|
throw e;
|
|
181
193
|
result.warnings.push(`track ${track.id}: ${errorMessage(e)}`);
|
|
182
194
|
}
|
|
@@ -235,6 +247,7 @@ export async function analyzeWithMediabunny(blob, name, opts = {}) {
|
|
|
235
247
|
}
|
|
236
248
|
if (result.mediabunny === undefined)
|
|
237
249
|
result.io = counted.io(t0);
|
|
250
|
+
printableWarnings(result);
|
|
238
251
|
return result;
|
|
239
252
|
}
|
|
240
253
|
export const containers = 'any';
|
package/dist/engines/mp4box.js
CHANGED
|
@@ -5,7 +5,7 @@ import { BlobReader, fourcc, u32, u64 } from "../core/reader.js";
|
|
|
5
5
|
import { emptyTrack } from "../core/result.js";
|
|
6
6
|
import { sniff } from "../core/sniff.js";
|
|
7
7
|
import { analyzeTimeline } from "../core/stats.js";
|
|
8
|
-
import { applyStats, codecNameFromFourcc, errorMessage, ffprobeRotation, isAbort, newResult } from "./common.js";
|
|
8
|
+
import { applyStats, codecNameFromFourcc, errorMessage, ffprobeRotation, isAbort, newResult, printableWarnings } from "./common.js";
|
|
9
9
|
import { CountingBlob, now } from "./counting.js";
|
|
10
10
|
export const MP4BOX_VERSION = '2.4.1';
|
|
11
11
|
const MAX_TOP_LEVEL_BOXES = 5_000_000;
|
|
@@ -423,6 +423,7 @@ export async function analyzeWithMp4box(blob, name, opts = {}) {
|
|
|
423
423
|
result.error = errorMessage(e);
|
|
424
424
|
}
|
|
425
425
|
result.io = counted.io(t0);
|
|
426
|
+
printableWarnings(result);
|
|
426
427
|
return result;
|
|
427
428
|
}
|
|
428
429
|
export const containers = ['isobmff'];
|
package/dist/plugins/own.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
export const ownDescriptor = {
|
|
2
2
|
id: 'own',
|
|
3
3
|
thread: 'worker',
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
createWorkers: {
|
|
5
|
+
isobmff: () => new Worker(new URL('../worker/own-isobmff.worker.js', import.meta.url), { type: 'module' }),
|
|
6
|
+
matroska: () => new Worker(new URL('../worker/own-matroska.worker.js', import.meta.url), { type: 'module' }),
|
|
7
|
+
},
|
|
8
|
+
load: () => import("../worker/runtime.js").then((m) => m.ownEngine),
|
|
6
9
|
};
|
package/dist/presets/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { CheckRules } from '../check/index.js';
|
|
|
2
2
|
export type PresetSourceKind = 'official' | 'gateway';
|
|
3
3
|
export interface ProviderPreset {
|
|
4
4
|
readonly name: string;
|
|
5
|
+
/** @deprecated Use video-fps-probe/presets/sources.json; sourceUrl will be removed in the next major. */
|
|
5
6
|
readonly sourceUrl: string;
|
|
6
7
|
readonly sourceKind: PresetSourceKind;
|
|
7
8
|
readonly verifiedAt: string;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"klingO1ReferenceVideo": "https://kling.ai/document-api/api/video/o1/video-omni.md",
|
|
3
|
+
"klingMotionControl": "https://kling.ai/document-api/api/video/motion-control.md",
|
|
4
|
+
"runwayAleph2": "https://docs.dev.runwayml.com/assets/inputs",
|
|
5
|
+
"veoExtend": "https://docs.cloud.google.com/gemini-enterprise-agent-platform/models/video/extend-a-veo-video",
|
|
6
|
+
"wan26ReferenceToVideoFal": "https://fal.ai/models/wan/v2.6/reference-to-video/api",
|
|
7
|
+
"seedance2ReferenceVideo": "https://evolink.ai/docs/en/api-manual/video-series/seedance2.0/seedance-2.0-reference-to-video"
|
|
8
|
+
}
|
package/dist/probe.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createProbeCore } from "./client/probe.js";
|
|
2
|
+
import { splitRoute } from "./client/route.js";
|
|
2
3
|
import { ownDescriptor } from "./plugins/own.js";
|
|
3
4
|
export function createProbe(options = {}) {
|
|
4
5
|
const { engines = [], worker, ...rest } = options;
|
|
5
|
-
return createProbeCore({ ...rest, engines: [ownDescriptor, ...engines], worker: worker === 'inline' ? 'inline' : undefined });
|
|
6
|
+
return createProbeCore({ ...rest, engines: [ownDescriptor, ...engines], worker: worker === 'inline' ? 'inline' : undefined, split: splitRoute });
|
|
6
7
|
}
|
package/dist/react/store.js
CHANGED
|
@@ -5,7 +5,7 @@ const IDLE = { status: 'idle', ...CLEAR, cancel: noop, retry: noop };
|
|
|
5
5
|
const hosts = new WeakMap();
|
|
6
6
|
let hostCount = 0;
|
|
7
7
|
const loadSummary = () => import("../api/summary.js");
|
|
8
|
-
const failure = (error, reason) => error
|
|
8
|
+
const failure = (error, reason) => error?.name === 'ProbeError' && typeof error.code === 'string' ? error : Object.assign(new ProbeError('worker-failed', String(error), { cause: error }), { reason });
|
|
9
9
|
const sortKeys = (_key, v) => (v && typeof v === 'object' && !Array.isArray(v) ? Object.fromEntries(Object.entries(v).sort(([a], [b]) => (a < b ? -1 : 1))) : v);
|
|
10
10
|
export function createVideoFpsStore(probe) {
|
|
11
11
|
const cache = new WeakMap();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){var e=Object.defineProperty,t=(e,t,n)=>()=>{if(n)throw n[0];try{return e&&(t=e(e=0)),t}catch(e){throw n=[e],e}},n=(t,n)=>{let r={};for(var i in t)e(r,i,{get:t[i],enumerable:!0});return n||e(r,Symbol.toStringTag,{value:`Module`}),r};function r(e,t=null){return{container:e,brand:null,formatDurationSec:null,scan:null,videoTracks:[],audioTrackCount:0,primaryTrackId:null,error:t,warnings:[]}}function i(e){return{trackId:e,fourccOrCodecId:``,codecName:``,width:0,height:0,rotation:0,timescale:0,frames:null,presentedFrames:null,durationSec:null,startSec:null,avgFps:null,avgFpsFfprobe:null,rFpsFfprobe:null,nominalFps:null,dominantFps:null,minFps:null,maxFps:null,isVfr:null,vfrRatio:0,distinctDeltas:0,duplicateTimestamps:0,timestampsQuantized:!1,isStill:!1,rateProfile:null,provenance:{},warnings:[]}}function a(e){return e<0n?-e:e}function o(e,t){for(;t!==0n;){let n=e%t;e=t,t=n}return e}function s(e,t){if(typeof e==`bigint`)return e;if(!Number.isSafeInteger(e))throw RangeError(`${t} must be a safe integer, got ${e}`);return BigInt(e)}function c(e,t,n=p){let r=s(e,`num`),i=s(t,`den`),c=s(n,`max`),l=0n,u=1n,d=1n,f=0n,m=r<0n!=i<0n,h=o(a(r),a(i));for(h!==0n&&(r=a(r)/h,i=a(i)/h),r<=c&&i<=c&&(d=r,f=i,i=0n);i!==0n;){let e=r/i,t=r-i*e,n=e*d+l,a=e*f+u;if(n>c||a>c){if(d!==0n&&(e=(c-l)/d),f!==0n){let t=(c-u)/f;t<e&&(e=t)}i*(2n*e*f+u)>r*f&&(d=e*d+l,f=e*f+u);break}l=d,u=f,d=n,f=a,r=i,i=t}let g=Number(d);return{num:m?-g:g,den:Number(f),exact:i===0n}}function l(e){return e.den===0?0:e.num/e.den}function u(e){return e?`${e.num}/${e.den}`:`0/0`}function d(e,t){return{num:e,den:t,value:l({num:e,den:t})}}function f(e,t,n=p){let r=c(e,t,n);return d(r.num,r.den)}var p,m=t((()=>{p=2147483647}));function h(e,t){let n={...e};if(!t)return n;for(let e of Object.keys(t)){let r=t[e];r!==void 0&&(n[e]=r)}return n}function g(e={}){return{signal:e.signal??null,matroskaMode:e.matroskaMode??`auto`,exactBudgetMs:e.exactBudgetMs??150,readAhead:h(_,e.readAhead),costModel:h(v,e.costModel),maxExpandedSamples:e.maxExpandedSamples??5e6,onProgress:e.onProgress??null}}var _,v,y=t((()=>{_={head:65536,fragment:1048576,matroskaScan:1048576,tail:262144},v={perReadMs:.8,bytesPerMs:5e5,perBlockMs:2e-4}})),b=n({CUSUM_ALARM_PERIODS:()=>2,FREEZE_FACTOR:()=>4,FREEZE_MIN_SEC:()=>we,MAX_ANOMALIES:()=>50,MAX_BUCKETS:()=>120,MAX_SEGMENTS:()=>50,MIN_SEGMENT_FRAMES:()=>5,MIN_SEGMENT_SEC:()=>S,UNEVEN_DOMINANT_SHARE:()=>C,rateProfile:()=>D});function x(e,t,n){e.t0=Math.min(e.t0,t.t0),e.t1=Math.max(e.t1,t.t1),e.frames+=t.frames,n?(e.n+=t.n,e.sum+=t.sum,e.ex+=t.ex):e.ex+=t.t1-t.t0}var S,C,w,T,E,D,ee=t((()=>{Ee(),S=.5,C=.8,w=1+Se,T=e=>String(+e.toPrecision(4)),E=e=>({t0:e,t1:e,n:0,sum:0,frames:0,ex:0,d:0,kind:`steady`}),D=(e,t,n,r)=>{let i=t,a=we*i,o=e=>i*e.n/e.sum,s=e=>e.n>=5&&e.t1-e.t0>=.5*i,c=[],l=e=>{let t=c[c.length-1];s(e)?c.push(e):t?.kind===`short`?x(t,e,!0):c.push({...e,kind:`short`})},u=E(0),d=E(0),f=E(0),p=0,m=0,h=0,g=0,_=0,v=!1,y=()=>{u.t1=p,v?c.push({...u,kind:`hold`}):l(u),u=E(p),v=!1,g=_=0},b=Math.min(120,Math.floor(n/2)),S=r/b,C=new Float64Array(b),D=(e,t)=>{u.n+=e,u.sum+=e*t,u.frames+=e,p+=e*t},ee=(e,t)=>{let n=e;if(t<=0)u.frames+=n,h+=n;else{for(let e=p,r=e+n*t,i=Math.floor(e/S);e<r&&i<b;i++){let n=Math.min(r,(i+1)*S);n>e&&(C[i]+=(n-e)/t),e=Math.max(e,n)}for(;n>0;){let e=u.sum/u.n;if(u.n&&t>=Math.max(a,4*e)){y(),v=!0,D(1,t),n--;continue}if(v&&Math.abs(t-e)>.075*e&&y(),v=!1,!u.n){D(n,t);return}let r=t-e,i=Ce*e,o=2*e,s=Math.abs(r)>i,c=s?1:n;if(s&&(r>0?!g||r-i>o:!_)){let e={...u,t1:p,d:t};r>0?d=e:f=e}if(g=Math.max(0,g+c*(r-i)),_=Math.max(0,_-c*(r+i)),D(c,t),n-=c,g>o||_>o){let e=g>o?d:f,t=u.n-e.n-1;t>0&&Math.abs(Math.log(e.d*e.n/e.sum))<Math.abs(Math.log(e.d*t/(u.sum-e.sum-e.d)))&&(e.t1+=e.d,e.n++,e.sum+=e.d,e.frames++),u.t0=e.t1,u.n-=e.n,u.sum-=e.sum,u.frames-=e.frames,l(e),g=_=0}}}},O=0,k=0;if(e((e,t)=>{e>0&&(m+=e,O&&t!==k&&(ee(O,k),O=0),O+=e,k=t)}),O&&ee(O,k),!(p>0))return null;u.n?y():c[c.length-1].frames+=u.frames;let A=[],te=(e,t,n,r,a=t.t1-t.t0)=>{A.push({kind:e,atSec:t.t0/i,durationSec:a/i,fromFps:n,toFps:r})},j=[],ne=(e,t)=>e?Math.abs(Math.log(o(e)/t)):1/0;c.forEach((e,t)=>{let n=j[j.length-1];if(e.kind===`short`||e.kind===`hold`){let r=o(e),i=c[t+1]?.kind===`steady`?c[t+1]:void 0,l=ne(n,r)<=ne(i,r)?n:i;if(e.kind=s(e)?`variable`:`steady`,e.kind===`steady`&&l){let t=o(l),n=e.sum>=e.n*Math.max(a,4*l.sum/l.n)?`freeze`:r*w<t?`gap`:r>t*w?`burst`:null;n&&te(n,e,t,r),x(l,e,!n);return}}let r=n?o(e)/o(n):0;n?.kind===`steady`&&e.kind===`steady`&&r<w&&r*w>1?x(n,e,!0):j.push(e)});let M=j[j.length-1],N=p+M.sum/M.n;M.frames+=n-m,M.t1=N;for(let e=1;e<j.length;e++){let t=j[e-1],n=j[e],r=o(n)/o(t);(t.kind===`steady`&&n.kind===`steady`||r>=w||r*w<=1)&&te(`rate-change`,n,o(t),o(n),0)}A.sort((e,t)=>e.atSec-t.atSec);let P=j.filter(e=>e.kind===`steady`).map(e=>[o(e),e.t1-e.t0-e.ex,e.n]).sort((e,t)=>e[0]-t[0]),F=0,I=0,L=0,re=0,R=0;for(let[e,t,n]of P){for(L+=t,re+=n;e>=P[R][0]*w;R++)L-=P[R][1],re-=P[R][2];F=Math.max(F,L),I=Math.max(I,re)}let ie=F/N,ae=ie<.8||I<.8*(m-h)||P.length>1&&P[P.length-1][0]>=P[0][0]*w,z=j.slice(0,3).map(e=>`${e.kind===`variable`?`~`:``}${T(o(e))} fps for ${T((e.t1-e.t0)/i)} s`);j.length>3&&z.push(`+${j.length-3} more`);let B=``,oe=(e,t)=>{e&&(B+=`${B?`, `:`; `}${e} ${t}${e>1?`s`:``}`)};for(let e of[`freeze`,`gap`,`burst`])oe(A.filter(t=>t.kind===e).length,e);return oe(h,`duplicate timestamp`),{segments:j.slice(0,50).map(e=>({startSec:e.t0/i,endSec:e.t1/i,frames:e.frames,fps:o(e),kind:e.kind})),moreSegments:Math.max(0,j.length-50),anomalies:A.slice(0,50),moreAnomalies:Math.max(0,A.length-50),buckets:{bucketSec:S/i,fps:Array.from(C,e=>e*i/S)},uneven:ae,dominantShare:ie,summary:`${ae?`Uneven`:B?`Mostly steady`:`Steady`}: ${z.join(`, `)}${B}`}}})),O=n({CUSUM_DRIFT:()=>Ce,FREEZE_FACTOR:()=>4,FREEZE_MIN_SEC:()=>we,MAX_REORDER_DEPTH:()=>16,RATE_CHANGE_RELATIVE:()=>Se,SNAP_RELATIVE_TOLERANCE:()=>be,VFR_RELATIVE_TOLERANCE:()=>xe,analyzeTimeline:()=>N,msGridTicks:()=>A,rateFromTicks:()=>M,rateProfileOf:()=>ce,reorderDepthFromCts:()=>j,snapToStandardRate:()=>k,vfrTolerance:()=>te});function k(e,t=be){if(!(e>0))return null;let n=null,r=1/0;for(let t of Te){let i=Math.abs(e-t.value)/t.value;i<r&&(r=i,n=t)}return r<=t?n:null}function A(e,t){if(!(e>1e3)||t.length===0)return 0;for(let n of t){let t=n*1e3;if(!Number.isSafeInteger(t)||t%e!==0)return 0}return e/1e3}function te(e,t,n){return Math.max(1,Math.round(xe*e),A(t,n))}function j(e,t,n){return!(t>e)||!(n>0)?0:Math.min(16,Math.ceil((t-e)/n))}function ne(e){if(Number.isInteger(e)||!(e>0))return null;let t=1e9/e,n=Math.round(t);return n>0&&Math.abs(t-n)<=1e-6*n?n:null}function M(e,t){let n=ne(e);return n!==null&&t>0&&Number.isSafeInteger(n*t)?f(1e9,n*t,2**53-1):I(e,t,2**53-1)}function N(e){let t=[],n=re(e.timescale,t);return`segments`in e?he(e,n,t):ye(e,n,t)}function P(e){return`counts`in e&&`deltas`in e?{n:Math.min(e.counts.length,e.deltas.length),counts:e.counts,values:e.deltas}:{n:e.length,counts:null,values:e}}function F(e){return e?`counts`in e&&`offsets`in e?{n:Math.min(e.counts.length,e.offsets.length),counts:e.counts,values:e.offsets}:{n:e.length,counts:null,values:e}:null}function I(e,t,n=p){if(!(e>0)||!(t>0))return null;if(Number.isSafeInteger(e)&&Number.isSafeInteger(t))return f(e,t,n);let r=1e6,i=Math.round(e*r),a=Math.round(t*r);return Number.isSafeInteger(i)&&Number.isSafeInteger(a)?f(i,a,n):d(e/t,1)}function L(e,t,n){if(!(t>0)||!(n>0))return null;let r=ne(e);return r!==null&&Number.isSafeInteger(t)&&Number.isSafeInteger(n)?f(BigInt(t)*1000000000n,BigInt(r)*BigInt(n),p):Number.isSafeInteger(e)&&Number.isSafeInteger(t)&&Number.isSafeInteger(n)?f(BigInt(e)*BigInt(t),n,p):I(e*t,n)}function re(e,t){return e>0&&Number.isFinite(e)?e:(t.push(`invalid timescale ${e}, using 1`),1)}function R(e){return e?{ws:e.start,we:e.end>e.start?e.end:1/0}:{ws:-1/0,we:1/0}}function ie(e,t){return{timescale:e,sampleCount:0,durationSum:0,avgFps:null,avgFpsString:`0/0`,presentedAvgFps:null,presentedFrames:null,firstPts:null,lastPts:null,deltaCount:0,excludedTailDeltas:0,reorderDepth:0,duplicateTimestamps:0,discontinuities:0,histogram:[],distinctDeltas:0,minDelta:null,maxDelta:null,medianDelta:null,meanDelta:null,tolerance:null,minFps:null,maxFps:null,isVfr:null,vfrRatio:0,nominalFps:null,dominantFps:null,timestampsQuantized:!1,profile:null,fastPath:!1,warnings:t}}function ae(e,t,n,r,i,a){let o=e.timescale,s=e.isVfr===!1&&n-t<=(e.tolerance??0)&&n<2*t;return n>t*1.075&&!s?e=>e(r,o,i,a):null}function z(e,t){let n=e.medianDelta,r=e.timescale;!n||!t||t<4*n||t<.5*r||e.warnings.push(`last frame held ${(t/r).toFixed(3)} s (${(t/n).toFixed(1)}x the median frame interval): the average is below the frame rate`)}function B(e,t){if(z(e,t),e.presentedFrames===null||e.presentedFrames<=0||e.firstPts===null||e.lastPts===null)return;let n=t>0?t:e.medianDelta??0;e.presentedAvgFps=L(e.timescale,e.presentedFrames,e.lastPts-e.firstPts+n)}function oe(e,t){let n=0;for(let[r,i]of V(e)){if(t<n+r)return i;n+=r}return 0}async function se(){try{let{rateProfile:e}=await Promise.resolve().then(()=>(ee(),b));return e}catch{return null}}async function ce(e){let t=e&&await se();return t?e(t):null}function le(e,t){return e-t>=2?e-t:e}function ue(e,t,n){let r=e.timescale,i=[...t.keys()].sort((e,t)=>e-t),a=i.map(e=>[e,t.get(e)??0]),o=0,s=0;for(let[e,t]of a)o+=t,s+=e*t;if(e.histogram=a,e.distinctDeltas=i.length,o===0)return;let c=0,l=i[0];for(let[e,t]of a)if(c+=t,c*2>=o){l=e;break}let u=i[0],d=0;for(let[e,t]of a)t>d&&(u=e,d=t);let f=A(r,i),p=Math.max(1,Math.round(xe*l),f),m=0;for(let[e,t]of a)Math.abs(e-l)>p&&(m+=t);let h=i[0],g=i[i.length-1],_=o>=2&&m>0;if(e.minDelta=h,e.maxDelta=g,e.medianDelta=l,e.meanDelta=s/o,e.tolerance=p,e.minFps=M(r,g),e.maxFps=M(r,h),e.isVfr=_,e.vfrRatio=m/o,i.length===1){let t=M(r,h);t&&(e.nominalFps={...t,kind:`exact`})}else if(_&&d*2>=o){let t=M(r,u);t&&(e.dominantFps={rate:t,share:d/o})}e.timestampsQuantized=(n||f>0)&&!_&&i.length>1}function de(e){if(e.nominalFps||e.isVfr!==!1||e.distinctDeltas<2||!e.avgFps)return;let t=k(e.meanDelta?e.timescale/e.meanDelta:e.avgFps.value);t&&(e.nominalFps={...t,kind:`snapped`})}function fe(e){let t={n:0,d:0,constantCts:!0,ctsValue:0,ctsMin:1/0,ctsMax:-1/0,firstDelta:0,negativeDurations:!1,discontinuities:0,startDts:0,ctsMismatch:0},n=!1,r=e=>{n?e!==t.ctsValue&&(t.constantCts=!1):(t.ctsValue=e,n=!0),e<t.ctsMin&&(t.ctsMin=e),e>t.ctsMax&&(t.ctsMax=e)},i=0;for(let n=0;n<e.length;n++){let a=e[n];a.baseDts!==void 0&&a.baseDts!==null&&(n===0?t.startDts=a.baseDts:a.baseDts!==i&&t.discontinuities++,i=a.baseDts);let o=P(a.durations),s=0;for(let e=0;e<o.n;e++){let n=o.counts?o.counts[e]:1;if(n<=0)continue;let r=o.values[e];s+=n,t.d+=n*r,i+=n*r,r<0&&(t.negativeDurations=!0),t.firstDelta===0&&r>0&&(t.firstDelta=r)}t.n+=s;let c=F(a.cts),l=0,u=0;if(c){for(let e=0;e<c.n;e++){let t=c.counts?c.counts[e]:1;if(t<=0)continue;u+=t;let n=Math.min(t,s-l);n<=0||(l+=n,r(c.values[e]))}u!==s&&t.ctsMismatch++}l<s&&r(0)}return n||(t.ctsMin=0,t.ctsMax=0),t}function*V(e){for(let t of e){let e=P(t.durations);for(let t=0;t<e.n;t++){let n=e.counts?e.counts[t]:1;n>0&&(yield[n,e.values[t]])}}}function pe(e,t,n,r){if(n===-1/0)return 0;if(n===1/0)return r;let i=t,a=0;for(let[t,r]of V(e)){if(r===0){if(i<n){a+=t;continue}return a}if(i+(t-1)*r<n)a+=t,i+=t*r;else return a+Math.max(0,Math.min(t,Math.ceil((n-i)/r)))}return a}function me(e,t,n){let r=t,i=0;for(let[t,a]of V(e)){if(n<i+t)return r+(n-i)*a;i+=t,r+=t*a}return r}function he(e,t,n){let r=e.segments,i=fe(r);i.ctsMismatch>0&&n.push(`composition offsets do not match the sample count in ${i.ctsMismatch} segment(s)`),i.discontinuities>0&&n.push(`decode timestamp discontinuities: ${i.discontinuities}`),i.negativeDurations&&n.push(`negative sample durations`),Number.isSafeInteger(i.d)||n.push(`duration sum exceeds 2^53-1`);let a=ie(t,n);if(a.sampleCount=i.n,a.durationSum=i.d,a.discontinuities=i.discontinuities,a.avgFps=L(t,i.n,i.d),a.avgFpsString=u(a.avgFps),i.n===0)return a.presentedFrames=0,a;let o=e.reorderDepth??j(i.ctsMin,i.ctsMax,i.firstDelta);a.reorderDepth=o;let s=1+o,{ws:c,we:l}=R(e.editWindow),d=e.tickQuantized??!1;if(!e.forceExpand&&i.constantCts&&i.discontinuities===0&&!i.negativeDurations){a.fastPath=!0;let e=i.startDts+i.ctsValue,t=pe(r,e,c,i.n),n=Math.max(t,pe(r,e,l,i.n));if(a.presentedFrames=n-t,n===t)return a;let o=me(r,e,t),u=me(r,e,n-1);a.firstPts=o,a.lastPts=u;let f=n-t-1,p=le(f,s),m=new Map,h=0,g=1/0,_=0;for(let[e,n]of V(r)){if(h>=t+f)break;let r=Math.max(h,t),i=Math.min(h+e,t+f);if(i>r){if(n===0)a.duplicateTimestamps+=i-r;else{g=Math.min(g,n),_=Math.max(_,n);let i=Math.min(h+e,t+p);i>r&&(m.set(n,(m.get(n)??0)+(i-r)),a.deltaCount+=i-r)}}h+=e}return a.excludedTailDeltas=f-p,ue(a,m,d),de(a),B(a,oe(r,n-1)),a.profile=ae(a,g,_,e=>{let n=0;for(let[i,a]of V(r)){if(n>=t+f)break;let r=Math.max(n,t),o=Math.min(n+i,t+f);o>r&&e(o-r,a),n+=i}},n-t,u-o),a}let f=e.maxExpandedSamples??5e6;if(i.n>f)return n.push(`per-sample analysis skipped: ${i.n} samples exceed the limit of ${f}`),a;let p=new Float64Array(i.n),m=0,h=0;for(let e of r){e.baseDts!==void 0&&e.baseDts!==null&&(h=e.baseDts);let t=m,n=P(e.durations);for(let e=0;e<n.n;e++){let t=n.counts?n.counts[e]:1,r=n.values[e];for(let e=0;e<t;e++)p[m++]=h,h+=r}let r=F(e.cts);if(r){let e=t;for(let t=0;t<r.n&&e<m;t++){let n=r.counts?r.counts[t]:1,i=r.values[t];for(let t=0;t<n&&e<m;t++)p[e++]+=i}}}let g=-1;for(let e=0;e<p.length;e++){let t=p[e];t>=c&&t<l&&(g<0||t>=p[g])&&(g=e)}let _=g>=0?oe(r,g):0;return _e(a,ge(p,c,l),s,d),B(a,_),de(a),a}function ge(e,t,n){let r=e.length;if(t!==-1/0||n!==1/0){r=0;for(let i=0;i<e.length;i++){let a=e[i];a>=t&&a<n&&(e[r++]=a)}}let i=e.subarray(0,r);for(let e=1;e<r;e++)if(i[e]<i[e-1]){i.sort();break}return i}function _e(e,t,n,r){let i=t.length;if(e.presentedFrames=i,i===0)return;e.firstPts=t[0],e.lastPts=t[i-1];let a=i-1,o=le(a,n),s=new Map,c=1/0,l=0;for(let n=1;n<=a;n++){let r=t[n]-t[n-1];r<=0?e.duplicateTimestamps++:(c=Math.min(c,r),l=Math.max(l,r),n<=o&&(s.set(r,(s.get(r)??0)+1),e.deltaCount++))}e.excludedTailDeltas=a-o,ue(e,s,r),e.profile=ae(e,c,l,e=>{for(let n=1;n<=a;n++)e(1,t[n]-t[n-1])},i,t[a]-t[0])}function ve(e){let t=-1/0,n=0;for(let r=0;r<e.length;r++){let i=e[r];i>t?t=i:t-i>n&&(n=t-i)}return n}function ye(e,t,n){let r=e.pts,i=r.length,a=ie(t,n);if(a.sampleCount=i,i===0)return a.presentedFrames=0,a;let o=1/0,s=-1/0;for(let e=0;e<i;e++){let t=r[e];t<o&&(o=t),t>s&&(s=t)}let{ws:c,we:l}=R(e.editWindow),d=ge(Float64Array.from(r),c,l),f=e.reorderDepth;if(f===void 0){let t=0;for(let e=1;e<d.length;e++){let n=d[e]-d[e-1];if(n>0){t=n;break}}f=e.ctsRange?j(e.ctsRange.min,e.ctsRange.max,t):j(0,ve(r),t)}a.reorderDepth=f,_e(a,d,1+f,e.tickQuantized??!1),z(a,e.lastDuration);let p=e.lastDuration??a.medianDelta??0;return a.durationSum=s-o+p,a.avgFps=L(t,i,a.durationSum),a.avgFpsString=u(a.avgFps),a.presentedAvgFps=a.avgFps,de(a),a}var be,xe,Se,Ce,we,Te,Ee=t((()=>{m(),y(),be=.001,xe=.005,Se=.15,Ce=Se/2,we=.5,Te=(()=>{let e=[];for(let t of[24,30,48,60,120,240])e.push(d(t*1e3,1001));for(let t=1;t<=240;t++)e.push(d(t,1));return e})()}));function De(e){if(e?.aborted)throw e.reason??new DOMException(`Aborted`,`AbortError`)}function H(e,t){if(!Number.isSafeInteger(e)||e<0)throw RangeError(`${t} must be a non-negative safe integer, got ${e}`)}var Oe=class{size;headWindow;maxWindows;signal;#e;#t=[];#n=[];#r=0;#i=0;constructor(e,t={}){H(e.size,`blob size`),this.#e=e,this.size=e.size,this.headWindow=t.headWindow??65536,this.maxWindows=Math.max(1,t.maxWindows??4),this.signal=t.signal??null,H(this.headWindow,`headWindow`)}get reads(){return this.#r}get bytesFetched(){return this.#i}checkAbort(){De(this.signal)}async read(e,t){if(H(e,`offset`),H(t,`length`),e>this.size)throw RangeError(`offset ${e} is beyond the end of the file (${this.size})`);let n=Math.min(this.size,e+t);if(n===e)return new Uint8Array;this.checkAbort();let r;try{r=await this.#e.slice(e,n).arrayBuffer()}catch(e){throw this.checkAbort(),e?.name===`AbortError`?e:Error(`file read failed: ${e}`)}if(this.checkAbort(),this.#r++,r.byteLength!==n-e)throw Error(`file read failed: short read at ${e}: expected ${n-e} bytes, got ${r.byteLength}`);return this.#a(e,n),new Uint8Array(r)}async readMany(e,t=4){let n=Array(e.length),r=0,i=async()=>{for(;r<e.length;){let t=r++,[i,a]=e[t],o=this.peek(i,a);n[t]=o?new Uint8Array(o.buffer,o.byteOffset,o.byteLength):await this.read(i,a)}},a=[];for(let n=0;n<Math.max(1,Math.min(t,e.length));n++)a.push(i());return await Promise.all(a),n}peek(e,t){let n=Math.min(this.size,e+t);for(let t=0;t<this.#t.length;t++){let r=this.#t[t];if(e>=r.off&&n<=r.off+r.buf.length)return t>0&&(this.#t.splice(t,1),this.#t.unshift(r)),new DataView(r.buf.buffer,r.buf.byteOffset+(e-r.off),n-e)}return null}async view(e,t,n=this.headWindow){if(H(e,`offset`),H(t,`length`),H(n,`readAhead`),e>this.size)throw RangeError(`offset ${e} is beyond the end of the file (${this.size})`);let r=Math.min(this.size,e+t);if(r===e)return new DataView(new ArrayBuffer(0));let i=this.peek(e,r-e);if(i)return i;let a=Math.min(this.size,Math.max(r,e+n)),o=this.#t.find(t=>e>=t.off&&e<t.off+t.buf.length),s;if(o){let t=o.buf.subarray(e-o.off),n=await this.read(o.off+o.buf.length,a-(o.off+o.buf.length));s=new Uint8Array(t.length+n.length),s.set(t,0),s.set(n,t.length)}else s=await this.read(e,a-e);return this.#t.unshift({off:e,buf:s}),this.#t.length>this.maxWindows&&(this.#t.length=this.maxWindows),new DataView(s.buffer,s.byteOffset,r-e)}async bytes(e,t,n=this.headWindow){let r=await this.view(e,t,n);return new Uint8Array(r.buffer,r.byteOffset,r.byteLength)}#a(e,t){let n=this.#n,r=0,i=n.length;for(;r<i;){let t=r+i>>>1;n[t].end<e?r=t+1:i=t}let a=r,o=e,s=t,c=0;for(;a<n.length&&n[a].start<=t;){let r=n[a],i=Math.min(t,r.end)-Math.max(e,r.start);i>0&&(c+=i),r.start<o&&(o=r.start),r.end>s&&(s=r.end),a++}n.splice(r,a-r,{start:o,end:s}),this.#i+=t-e-c}};function ke(e,t){return e.getUint8(t)*65536+e.getUint16(t+1)}function Ae(e,t,n){let r=``;for(let i=0;i<n;i++)r+=String.fromCharCode(e.getUint8(t+i));return r}function U(e,t){return Ae(e,t,4).replace(/[^ -~]/g,`?`)}var W=class extends Error{constructor(e){super(e),this.name=`IsoBmffError`}};function G(e,t,n,r=0){let i=Math.min(e.byteLength,n);if(t+8>i)return null;let a=e.getUint32(t),o=U(e,t+4),s=8,c=a;if(a===1){if(t+16>i)return null;let n=e.getBigUint64(t+8);if(n>BigInt(2**53-1))throw new W(`corrupt file: box '${o}' at ${r+t} has a size above 2^53-1`);c=Number(n),s=16}else a===0&&(c=n-t);if(o===`uuid`&&(s+=16),c<s)throw new W(`corrupt file: box '${o}' at ${r+t} is smaller than its header`);let l=t+c;return{type:o,start:t,size:c,headerSize:s,end:Math.min(l,n),truncated:l>n}}function*K(e,t,n,r){let i=t;for(;i+8<=n;){let t;try{t=G(e,i,n)}catch(e){r?.push(e.message.replace(/^corrupt file: /,`ignored invalid child: `));return}if(!t)return;yield t,i=t.start+t.size}}function q(e,t,n,r){let i=e.getBigUint64(t);if(i>BigInt(2**53-1))throw new W(`unsupported: box '${n}' at ${r} holds a value above 2^53-1`);return Number(i)}function je(e,t,n,r){let i=e.getBigInt64(t);if(i>BigInt(2**53-1)||i<-BigInt(2**53-1))throw new W(`unsupported: box '${n}' at ${r} holds a value beyond 2^53-1`);return Number(i)}function Me(e,t,n,r,i){let a=Math.max(0,Math.floor(t/n));return e>a?(i.push(`${r} declares ${e} entries but its box holds only ${a}`),a):e}let J=null;function Ne(){if(J)return J;J=new Map;for(let e of`rawvideo:raw yuv22vuyyuvs|v210:v210|mjpeg:jpegmjpaAVDJAVRndmb1|mpeg4:mp4vDIVXXVID3IV2|h263:h263s263H263|dvvideo:dvcpdvc dvppdv5pdv5nAVdvAVd1dvhqdvhpdvh1dvh2dvh3dvh4dvh5dvh6|qtrle:rle |cinepak:cvid|svq1:SVQ1svq1svqi|svq3:SVQ3|vvc:vvc1vvi1|hevc:hev1hvc1dvhe|h264:avc1avc2avc3avc4ai5pai5qai52ai53ai55ai56ai1pai1qai12ai13ai15ai16AVinaivxdva1dvav|evc:evc1|vp8:vp08|vp9:vp09|av1:av01|mpeg1video:m1v m1v1mpegmp1v|mpeg2video:m2v1hdv1hdv2hdv3hdv4hdv5hdv6hdv7hdv8hdv9hdvamx5nmx5pmx4nmx4pmx3nmx3pxd51xd54xd55xd59xd5axd5bxd5cxd5dxd5exd5fxdv1xdv2xdv3xdv4xdv5xdv6xdv7xdv8xdv9xdvaxdvbxdvcxdvdxdvexdvfxdhdxdh2AVmpmp2v|jpeg2000:mjp2|png:png MNG |gif:gif |tiff:tiff|vc1:vc-1|cavs:avs2|avs3:avs3|dirac:drac|dnxhd:AVdnAVdh|prores:apchapcnapcsapcoap4hap4x|prores_raw:aprnaprh|hap:Hap1Hap5HapYHapAHapM|cfhd:CFHD|lcevc:lvc1|apv:apv1`.split(`|`)){let t=e.indexOf(`:`),n=e.slice(0,t);for(let r=t+1;r+4<=e.length;r+=4)J.set(e.slice(r,r+4),n)}return J}let Pe={32:`mpeg4`,33:`h264`,35:`hevc`,51:`vvc`,96:`mpeg2video`,97:`mpeg2video`,98:`mpeg2video`,99:`mpeg2video`,100:`mpeg2video`,101:`mpeg2video`,106:`mpeg1video`,108:`mjpeg`,109:`png`,110:`jpeg2000`,163:`vc1`,164:`dirac`,177:`vp9`};function Fe(e){return Ne().has(e)}function Ie(e,t=null,n=!1){return t!==null&&Pe[t]?Pe[t]:e===`dvh1`&&n?`hevc`:Ne().get(e)??`unknown`}let Le=2**53-1,Re=[65536,0,0,0,65536,0,0,0,1<<30];function ze(e){return{fileSize:e,brand:null,compatibleBrands:[],hasFtyp:!1,hasMvhd:!1,timescale:1,duration:0,matrix:Int32Array.from(Re),tracks:[],chapterTrackIds:new Set,hasMvex:!1,trex:new Map,moofCount:0,topLevel:[],truncated:!1,ffprobeMoofLimit:1/0,ffprobeReject:null,warnings:[]}}function Be(){return{id:0,enabled:!1,handler:``,timescale:0,hasMdhd:!1,mdhdDuration:0,matrix:Int32Array.from(Re),sampleEntry:``,originalFormat:null,stsdCount:0,width:0,height:0,esdsObjectType:null,hasHvcc:!1,sttsCounts:new Uint32Array,sttsDeltas:new Uint32Array,cttsCounts:null,cttsOffsets:null,dtsShift:0,sampleCount:null,sampleSize:0,overruns:[],edits:[],fragments:[],warnings:[],dv:null,stss:null,stsz:null,stz2:null,stsc:null,stco:null,co64:null}}let Ve=`no trex: sample defaults taken from tfhd`;function He(e){let t=0;for(let n=256;n<=2048;n<<=1)e&n&&(t+=4);return t}function Ue(e,t,n,r,i,a,o=i+t-8){if(t+8>n)return null;let s=ke(e,t+1),c=e.getUint32(t+4),l=r.trex.get(c),u=t+8,d=e=>u+e<=n,f=s&131072?i:a;if(s&1){if(!d(8))return null;f=q(e,u,`tfhd`,o),u+=8}s&2&&(u+=4);let p=l?l.duration:null;if(s&8){if(!d(4))return null;p=e.getUint32(u),u+=4}let m=l?l.size:0;if(s&16){if(!d(4))return null;m=e.getUint32(u)}return{flags:s,trackId:c,baseDataOffset:f,defaultDuration:p,defaultSize:m,trexMissing:!l}}function We(e,t,n,r,i,a,o,s){let c=ke(e,t+1),l=e.getUint32(t+4),u=t+8,d=i;c&1&&(d=r.baseDataOffset+e.getInt32(u),u+=4),c&4&&(u+=4);let f=He(c),p;f>0?p=Me(l,n-u,f,`trun`,o):(p=l,p>s&&(o.push(`trun count ${l} limited to ${s}`),p=s));let m=f>0&&p<l,h=!!(c&256);if(!h&&r.defaultDuration===null&&p>0)throw new W(`corrupt file: no sample duration for track ${r.trackId}`);let g=r.defaultDuration??0,_=h?new Uint32Array(p):null,v=c&2048?new Int32Array(p):null,y=!!(c&512),b=h?0:g*p,x=d,S=0,C=0;if(f>0)for(let t=0;t<p;t++){if(h){let n=e.getUint32(u);_[t]=n,b+=n,u+=4}let n=r.defaultSize;y&&(n=e.getUint32(u),u+=4),c&1024&&(u+=4),v&&(v[t]=e.getInt32(u),u+=4),x<a&&S++,C===t&&x+n<=a&&C++,x+=n}if(!y){let e=r.defaultSize,t=Math.max(0,a-d);S=e>0?Math.min(p,Math.ceil(t/e)):Math.min(p,t),C=e>0?Math.min(p,Math.floor(t/e)):S,x=d+e*p}return{fragment:{moofIndex:0,baseDts:null,count:p,durations:_,defaultDuration:g,cts:v,durationSum:b,present:S,complete:C,trexMissing:r.trexMissing,overrun:m},dataEnd:x}}function Ge(e,t,n,r,i,a){let o=n,s=!1,c=e=>{i.ffprobeReject||={moof:r,reason:e}},l=new Map;for(let e of i.tracks)l.has(e.id)||l.set(e.id,e);for(let u of K(e,t.start+t.headerSize,t.end,i.warnings)){if(u.type!==`traf`)continue;let t=null,d,f=null,p=0;for(let m of K(e,u.start+u.headerSize,u.end,i.warnings)){let u=m.start+m.headerSize;if(m.type===`tfhd`){if(t=Ue(e,u,m.end,i,n,o,n+m.start),!t)continue;t.trackId===0?c(`rejects this file: tfhd with track_ID 0`):t.trexMissing||(s=!0),p=t.baseDataOffset,d=l.get(t.trackId),d||i.warnings.push(`fragment for unknown track ${t.trackId}`)}else if(m.type===`tfdt`&&u+8<=m.end)f=e.getUint8(u)===1&&u+12<=m.end?q(e,u+4,`tfdt`,n+m.start):e.getUint32(u+4);else if(m.type===`trun`&&u+8<=m.end){if(s?(!t||t.trexMissing)&&c(`misreads this file: a traf without trex is read as another track`):c(`rejects this file: trun without a tfhd that has a trex`),!t||!d)continue;let n=d,{fragment:l,dataEnd:h}=We(e,u,m.end,t,p,i.fileSize,n.warnings,a);l.moofIndex=r,l.baseDts=f,f=null,p=h,o=h,l.trexMissing&&!n.warnings.includes(Ve)&&n.warnings.push(Ve),n.fragments.push(l)}}}}function Ke(e,t,n){let r=t.start+t.headerSize,i=r<t.end&&e.getUint8(r)===1;if(r+(i?32:24)>t.end)throw new W(`corrupt file: box 'sidx' at ${n} is truncated`);let a=r+12,o=i?q(e,a,`sidx`,n):e.getUint32(a),s=i?q(e,a+8,`sidx`,n):e.getUint32(a+4);a+=i?16:8;let c=e.getUint16(a+2);a+=4;let l=n+(t.end-t.start),u=l+s,d=0,f=!1,p=[];for(let n=0;n<c&&a+12<=t.end;n++,a+=12){let t=e.getUint32(a);t&2147483648&&(f=!0);let n=t&2147483647;p.push([u,n]),u+=n,d+=e.getUint32(a+4)}return{start:n,end:l,referenceId:e.getUint32(r+4),timescale:e.getUint32(r+8),earliestPts:o,firstOffset:s,coverageEnd:u,durationSum:d,subsegments:p,hierarchical:f}}function Y(e,t,n,r=0){return qe(K(e,t.start+t.headerSize+r,t.end,n.warnings),n,t.type)}function*qe(e,t,n){for(let r of e){if(r.truncated){if(t.strict)throw new W(`incomplete file: moov is truncated`);t.warnings.push(`'${r.type}' overruns '${n}'`)}yield r}}function X(e){return e.start+e.headerSize}function Je(e,t){let n=new Int32Array(9);for(let r=0;r<9;r++)n[r]=e.getInt32(t+r*4);return n}function Ye(e){return e>0&&e<=2147483647?e:1}function Z(e){return{start:X(e),end:e.end}}function Xe(e,t,n){let r=X(t);if(r+8>t.end)return;let i=e.getUint32(r+4),a=Me(i,t.end-r-8,8,`stts`,n.warnings);a<i&&n.overruns.push(`stts`);let o=new Uint32Array(a),s=new Uint32Array(a),c=!1;for(let t=0;t<a;t++)o[t]=e.getUint32(r+8+t*8),s[t]=e.getUint32(r+12+t*8),s[t]>4294487295&&(c=!0);c&&Ze(o,s,n.warnings),n.sttsCounts=o,n.sttsDeltas=s}function Ze(e,t,n){let r=0n,i=0n;for(let a=0;a<e.length;a++){let o=BigInt(e[a]),s=t[a];if(s>4294487295){n.push(`stts delta ${s} clipped to 1`);let e=s|0;s=1,i+=BigInt(e<0?e:1)*o}else i+=BigInt(s)*o;if(r+=BigInt(s)*o,r>i){let e=(r-i)/(o>0n?o:1n),t=BigInt(s)>e?e:BigInt(s-1>>>0);r-=t*o,s=Number(BigInt(s)-t&4294967295n)}t[a]=s}}function Qe(e,t,n){let r=X(t);if(r+8>t.end)return;let i=e.getUint32(r+4),a=Me(i,t.end-r-8,8,`ctts`,n.warnings);if(a<i&&n.overruns.push(`ctts`),a===0)return;let o=[],s=[],c=0;for(let t=0;t<a;t++){let n=e.getInt32(r+8+t*8),a=e.getInt32(r+12+t*8);n<=0||(o.push(n),s.push(a),t+2<i&&a<0&&(c=Math.max(c,a===-2147483648?2147483647:-a)))}n.cttsCounts=Uint32Array.from(o),n.cttsOffsets=Int32Array.from(s),n.dtsShift=c}function $e(e,t,n,r,i){let a=X(t);if(a+8>t.end)return;let o=e.getUint8(a),s=o===1?20:12,c=e.getUint32(a+4),l=t.end-a-8,u=c*s===l?c:Math.floor(l/s);if(u!==c&&n.warnings.push(`elst declares ${c} entries but its box holds ${u}`),u===0)return;n.edits.length&&(n.warnings.push(`duplicated elst: the last one is used`),n.edits=[]);let d=r.base+t.start;for(let t=0;t<u;t++){let r=a+8+t*s;if(o===1){let t=je(e,r+8,`elst`,d),a=e.getBigInt64(r)===-1n;a&&(n.warnings.push(`unknown elst duration: ${t===-1?`the empty edit is ignored`:`the edit lasts to the end`}`),i.ffprobeReject??={moof:-1,reason:`rejects this file: an elst duration of -1`}),n.edits.push({duration:a?t===-1?0:Le:q(e,r,`elst`,d),mediaTime:t,rate:e.getInt32(r+16)/65536})}else n.edits.push({duration:e.getUint32(r),mediaTime:e.getInt32(r+4),rate:e.getInt32(r+8)/65536})}}function et(e,t,n){let r=t+4,i=()=>{if(r+2>n)return null;let t=e.getUint8(r++),i=0;for(let t=0;t<4&&r<n;t++){let t=e.getUint8(r++);if(i=i*128+(t&127),!(t&128))break}return[t,i]},a=i();if(a&&a[0]===3){if(r+3>n)return null;let t=e.getUint8(r+2);r+=3,t&128&&(r+=2),t&64&&r<n&&(r+=1+e.getUint8(r)),t&32&&(r+=2),a=i()}return a&&a[0]===4&&r<n?e.getUint8(r):null}function tt(e,t,n,r){let i=X(t);if(i+8>t.end||(n.stsdCount=e.getUint32(i+4),n.stsdCount===0))return;let a;try{a=G(e,i+8,t.end)}catch(e){n.warnings.push(e.message);return}if(a&&(n.sampleEntry=a.type,!(n.handler===`soun`||a.start+86>a.end))){n.width=e.getUint16(a.start+32),n.height=e.getUint16(a.start+34);for(let t of K(e,a.start+86,a.end,r.warnings))if(t.type===`esds`)n.esdsObjectType=et(e,X(t),t.end);else if(t.type===`hvcC`)n.hasHvcc=!0;else if(t.type===`sinf`)for(let i of K(e,X(t),t.end,r.warnings))i.type===`frma`&&X(i)+4<=i.end&&(n.originalFormat=U(e,X(i)))}}function nt(e,t,n,r){n.dv=e;for(let i of Y(e,t,r)){let t=X(i);switch(i.type){case`stsd`:tt(e,i,n,r);break;case`stts`:Xe(e,i,n);break;case`ctts`:Qe(e,i,n);break;case`stsz`:case`stz2`:t+12<=i.end&&(n.sampleCount=e.getUint32(t+8),n.sampleSize=i.type===`stsz`?e.getUint32(t+4):0),i.type===`stsz`?n.stsz=Z(i):n.stz2=Z(i);break;case`stss`:n.stss=Z(i),t+8<=i.end&&e.getUint32(t+4)>Math.floor((i.end-t-8)/4)&&n.overruns.push(`stss`);break;case`stsc`:n.stsc=Z(i);break;case`stco`:n.stco=Z(i);break;case`co64`:n.co64=Z(i)}}}function rt(e,t,n,r){for(let i of Y(e,t,r)){let t=X(i);if(i.type===`mdhd`&&t+24<=i.end){let r=e.getUint8(t)===1;if(r&&t+32>i.end)continue;n.hasMdhd=!0;let a=e.getUint32(t+(r?20:12));if(n.timescale=Ye(a),n.timescale!==a&&n.warnings.push(`invalid mdhd timescale ${a}, using 1`),r){let r=e.getBigUint64(t+24);n.mdhdDuration=r===18446744073709551615n?0:Number(r)}else{let r=e.getUint32(t+16);n.mdhdDuration=r===4294967295?0:r}}else if(i.type===`hdlr`&&t+12<=i.end)n.handler=U(e,t+8);else if(i.type===`minf`)for(let t of Y(e,i,r))t.type===`stbl`&&nt(e,t,n,r)}}function it(e,t,n,r){let i=Be();for(let a of Y(e,t,r)){let t=X(a);if(a.type===`tkhd`&&t+84<=a.end){let n=e.getUint8(t)===1;if(n&&t+96>a.end)continue;i.enabled=(e.getUint8(t+3)&1)==1,i.id=e.getUint32(t+(n?20:12)),i.matrix=Je(e,t+(n?52:40))}else if(a.type===`edts`)for(let t of Y(e,a,r))t.type===`elst`&&$e(e,t,i,r,n);else if(a.type===`mdia`)rt(e,a,i,r);else if(a.type===`tref`){for(let t of Y(e,a,r))if(t.type===`chap`)for(let r=X(t);r+4<=t.end;r+=4)n.chapterTrackIds.add(e.getUint32(r))}}return i}function at(e,t,n,r,i=0){let a={strict:r,warnings:n.warnings,base:i};for(let r of Y(e,t,a)){let t=X(r);switch(r.type){case`mvhd`:{if(t+24>r.end)break;let i=e.getUint8(t)===1;if(i&&t+84>r.end)break;n.hasMvhd=!0,n.timescale=Ye(e.getUint32(t+(i?20:12))),n.duration=i?Number(e.getBigUint64(t+24)):e.getUint32(t+16),t+(i?84:72)<=r.end&&(n.matrix=Je(e,t+(i?48:36)));break}case`trak`:n.tracks.push(it(e,r,n,a));break;case`mvex`:n.hasMvex=!0;for(let t of Y(e,r,a)){let r=X(t);t.type===`trex`&&r+24<=t.end&&n.trex.set(e.getUint32(r+4),{duration:e.getUint32(r+12),size:e.getUint32(r+16)})}break;case`cmov`:throw new W(`unsupported: compressed movie header (cmov)`)}}}let ot=new Set([`moof`,`styp`,`sidx`,`ssix`,`emsg`,`prft`,`free`,`skip`,`uuid`]);function st(){return{windows:[],hints:[],next:0,mfraTried:!1}}function ct(e,t,n){for(let[r,i]of e.windows)if(t>=r&&t+n<=r+i.byteLength)return new DataView(i.buffer,i.byteOffset+t-r,n);return null}async function lt(e,t,n,r){for(;t.next<t.hints.length&&t.hints[t.next]<=n;)t.next++;let i=[];for(let n=t.next;n<t.hints.length&&i.length<8;n++)t.hints[n]<e.size&&i.push([t.hints[n],Math.min(r,e.size-t.hints[n])]);if(t.next+=i.length,!i.length)return;let a=await e.readMany(i,4);t.windows=i.map(([e],t)=>[e,new DataView(a[t].buffer,a[t].byteOffset,a[t].byteLength)]),t.windows.every(([,e])=>ut(e))||(t.hints=[],t.next=0)}function ut(e){return e.byteLength>=8&&e.getUint32(0)>=8&&ot.has(U(e,4))}function dt(e,t,n,r,i=2**53-1){for(let a of K(e,t,n)){let t=a.start+a.headerSize;if(a.type!==`tfra`||t+16>a.end)continue;let n=e.getUint8(t)===1,o=e.getUint32(t+8),s=(n?16:8)+(o>>4&3)+(o>>2&3)+(o&3)+3,c=Math.min(e.getUint32(t+12),Math.floor((a.end-t-16)/s));for(let a=0;a<c;a++){let o=t+16+a*s,c=n?e.getBigUint64(o+8):BigInt(e.getUint32(o+4));c>0n&&c<BigInt(i)&&r.add(Number(c))}}}async function ft(e){try{return await pt(e)}catch(t){if(e.signal?.aborted||t?.name===`AbortError`)throw t;return[]}}async function pt(e){let t=e.size,n=Math.min(t,65536);if(n<16)return[];let r=await e.view(t-n,n,0);if(U(r,n-12)!==`mfro`)return[];let i=r.getUint32(n-4);if(i<24||i>Math.min(t,16777216))return[];let a=i<=n?new DataView(r.buffer,r.byteOffset+n-i,i):await e.view(t-i,i,0),o;try{o=G(a,0,i)}catch{return[]}if(!o||o.type!==`mfra`)return[];let s=new Set;return dt(a,o.headerSize,o.end,s,t),[...s].sort((e,t)=>e-t)}m();function Q(e,t,n){if(!(n>0))return 0;let r=BigInt(Math.abs(e))*BigInt(t),i=BigInt(n),a=Number((r+i/2n)/i);return e<0?-a:a}function mt(e){let t=0,n=0;for(let r=0;r<e.sttsCounts.length;r++)t+=e.sttsCounts[r],n+=e.sttsCounts[r]*e.sttsDeltas[r];let r=0;for(let t of e.fragments)r+=t.count;return{moovSamples:t,moovDuration:n,fragmentSamples:r}}function ht(e,t,n){let r=0n,i=0n;if(n){for(let t=0;t<e.sttsCounts.length;t++)r+=BigInt(e.sttsCounts[t]),i+=BigInt(e.sttsCounts[t])*BigInt(e.sttsDeltas[t]);i<=0n&&(r=0n,i=0n)}for(let n of e.fragments)t(n.moofIndex,n.trexMissing)&&(r+=BigInt(n.count),i+=BigInt(n.durationSum));return[r,i]}function gt(e,t,n){return t<=0n||n<=0n?null:f(BigInt(e)*t,n,p)}function _t(e,t){let n=e.timescale,r=(e,n)=>e<t.ffprobeMoofLimit&&!n,[i,a]=ht(e,()=>!0,!0),[o,s]=ht(e,r,!0),c=e.overruns.includes(`stts`)||e.fragments.some(e=>e.overrun&&r(e.moofIndex,e.trexMissing))?null:gt(n,o,s);return{avg:gt(n,i,a),ffprobe:c?u(c):null}}function vt(e){let t=e.dv,n=e=>t&&e&&e.start+8<=e.end?t.getUint32(e.start+4):0,r=n(e.co64??e.stco),i=e.sttsCounts.length>0||e.overruns.includes(`stts`),a=e.sampleCount??0;return r>0&&(!i||n(e.stsc)===0||e.sampleSize===0&&a===0)||a>0&&r===0}function yt(e,t,n){let r=0,i=0,a=0,o=null,s=(e.cttsOffsets?.[0]??0)+n.moovDuration;for(let n of e.edits){let c=n.duration===Le?Math.max(0,s-n.mediaTime):Q(n.duration,e.timescale,t);i+=c,n.mediaTime===-1?o||(r+=c):(a++,o||={mediaTime:n.mediaTime,duration:c,rate:n.rate})}return{emptyBefore:r,firstMedia:o,editSum:i,mediaEdits:a}}function bt(e,t,n,r){let i=e.mdhdDuration;n.moovDuration>0&&(i=Math.min(i,n.moovDuration));let a=e.edits.length>0&&n.moovSamples>0;a&&(i=Math.min(i,r.editSum));let o=n.moovDuration,s=null,c=St(e,t);for(let t of e.fragments)t.baseDts!==null&&(o=t.baseDts),s===null&&t.count>0&&(s=o-c+(t.cts?t.cts[0]:0)),o+=t.durationSum,o>i&&(i=o);let l=xt(e,t);l!==null&&l>i&&(i=l);let u=null;return u=a?r.emptyBefore:n.moovSamples>0?e.cttsOffsets&&e.cttsOffsets.length?e.cttsOffsets[0]:0:s,{durationTs:i,startPts:u}}function xt(e,t){if(t.ffprobeMoofLimit===1/0)return null;let n=0,r=null;for(let i of t.topLevel){if(i.type===`moof`&&++n>t.ffprobeMoofLimit)break;let a=i.sidx;a&&!a.hierarchical&&a.referenceId===e.id&&a.timescale===e.timescale&&(r=a.earliestPts+a.durationSum)}return r}function St(e,t){let n=0,r=0,i=0;return e.edits.forEach((e,t)=>{t===0&&e.mediaTime===-1?(n=e.duration,i=1):t===i&&e.mediaTime>=0&&(r=e.mediaTime)}),!n&&!r?0:r-Q(n,e.timescale,t.timescale)}function Ct(e,t,n){let r=new Float64Array(e.length+1),i=new Float64Array(e.length),a=0,o=0;for(let s=0;s<e.length&&o<n;s++)e[s]<=0||(r[a]=o,i[a]=t[s],o+=Math.min(e[s],n-o),a++);return r[a]=o,{count:a,starts:r,values:i,total:o}}function wt(e){let t=e.starts,n=0;return r=>{if(r>=t[n]&&r<t[n+1])return n;let i=0,a=e.count-1;for(;i<a;){let e=Math.ceil((i+a)/2);t[e]<=r?i=e:a=e-1}return n=i,i}}function Tt(e,t){let n=e.stss;if(!n||!e.dv)return{all:!0,list:new Float64Array};let r=e.dv,i=n.start+8<=n.end?Math.min(r.getUint32(n.start+4),Math.floor((n.end-n.start-8)/4)):0;if(i===0)return{all:!1,list:Float64Array.of(0)};let a=+(r.getUint32(n.start+8)>0),o=new Float64Array(i),s=0,c=-1;for(let e=0;e<i;e++){let i=r.getUint32(n.start+8+e*4)-a;if(i<=c||i>=t)break;o[s++]=i,c=i}return{all:!1,list:o.subarray(0,s)}}function Et(e,t,n){if(n>=t)return-1;if(e.all)return n;let r=e.list,i=0,a=r.length;for(;i<a;){let e=Math.floor((i+a)/2);r[e]<n?i=e+1:a=e}return i<r.length?r[i]:-1}function Dt(e,t){if(t<0)return-1;if(e.all)return t;let n=e.list,r=0,i=n.length;for(;r<i;){let e=Math.floor((r+i)/2);n[e]<=t?r=e+1:i=e}return r>0?n[r-1]:-1}function Ot(e,t,n){let r=n;r<=0||e.len===0&&(e.first=t,e.last=t,e.len=1,r--,r===0)||((e.len>=2&&e.last!==e.first||r>=2&&t!==e.first)&&(e.bad=!0),e.last=t,e.len+=r)}function kt(e,t,n,r,i){let a=r,o=Math.min(i,t.total-r),s=0;for(;o>0&&!e.bad;){let r=n(a),i=Math.min(t.starts[r+1]-a,o);Ot(e,t.values[r],i),a+=i,o-=i,s++}return s}function At(e,t){return e.bad||e.len===0||!(e.first>0)?null:f(t,e.first,p)}function jt(e,t,n,r,i){let a=Math.min(n,e.sampleCount??0);if(a<=0||e.sttsCounts.length===0||e.overruns.length>0)return null;let o=e.timescale,s=Ct(e.sttsCounts,e.sttsDeltas,a),c=wt(s),l={len:0,first:0,last:0,bad:!1};if(e.edits.length===0)return kt(l,s,c,0,a),At(l,o);if(!e.edits.some(e=>e.mediaTime!==-1))return null;let u=!0;for(let e=1;e<s.count&&u;e++)u=s.values[e]===s.values[0];if(u)return s.values[0]>0?f(o,s.values[0],p):null;let d=Math.min(r,2e6),m=0,h=!1,g=e=>(m+=e,m>d&&(h=!0),h),_=new Float64Array(s.count+1);for(let e=0;e<s.count;e++)_[e+1]=_[e]+(s.starts[e+1]-s.starts[e])*s.values[e];let v=e=>{let t=c(e);return _[t]+(e-s.starts[t])*s.values[t]},y=e=>s.values[c(e)],b=!!e.cttsCounts&&e.cttsCounts.length>0,x=b?Ct(e.cttsCounts,e.cttsOffsets,a):null,S=x?wt(x):null,C=e=>x&&e<x.total?x.values[S(e)]:0,w=Tt(e,a),T=e=>Et(w,a,e),E=e=>Dt(w,e),D=e.dtsShift,ee=(e,t)=>{let n=0,r=t;for(;n<r;){let t=Math.floor((n+r)/2);v(t)>=e?r=t:n=t+1}return n},O=(e,t)=>{let n=D>0?e-D:e,r=-1,i=a;for(v(a-1)-D<n&&(r=a-1);i-r>1;){let e=Math.floor((r+i)/2),t=v(e)-D;t>=n&&(i=e),t<=n&&(r=e)}let o=t?r:E(r);if(o>0){let e=ee(v(o),o);if(e<o){if(t)o=e;else{let t=T(e);t>=0&&t<o&&(o=t)}}}if(b&&o>=0){let e=E(o);for(;e>=0&&!g(1)&&v(e)-D+C(e)>n;)e=E(e-1);o=e}return o},k=0,A=!1;for(let n of e.edits){let r=n.mediaTime;if(!A&&r===-1)continue;if(A=!0,g(64))break;let i=Q(n.duration,e.timescale,t.timescale),o=O(r,!1);if(o<0&&!h&&(o=O(r,!0)),h)break;o<0&&(o=0,k=0),b&&(k=o);let u=-1;if(b){let e=!1;for(let t=T(o);t>=0&&!g(1);t=T(t+1)){let n=t+1<a?y(t):i;if(v(t)+C(t)+n>=i+r){if(e){u=t;break}e=!0}}if(h)break}else{let e=o,t=a;for(;e<t;){let n=Math.floor((e+t)/2);(n+1<a?v(n+1):v(a-1)+i)>=i+r?t=n:e=n+1}e<a&&(u=T(e))}let d=u<0?a-o:u-o+1,f=Math.min(d,a-k);if(f>0&&(g(kt(l,s,c,k,f)),k+=f),l.bad)return null;if(h)break}return h?(i?.push(`r_frame_rate not reproduced: edit list walk limit reached`),null):At(l,o)}function Mt(e,t,n){let r=[],i=[],a=n;for(let n=0;n<e.length&&a>0;n++){let o=Math.min(e[n],a);o<=0||(r.push(o),i.push(t[n]),a-=o)}return{counts:r,values:i}}function Nt(e,t){let n=[];if(t>0){let r=Mt(e.sttsCounts,e.sttsDeltas,t),i=e.cttsCounts&&e.cttsOffsets?Mt(e.cttsCounts,e.cttsOffsets,t):null;n.push({durations:{counts:r.counts,deltas:r.values},cts:i?{counts:i.counts,offsets:i.values}:null})}for(let t of e.fragments){let e=t.complete;n.push({baseDts:t.baseDts,durations:t.durations?t.durations.subarray(0,e):{counts:[e],deltas:[t.defaultDuration]},cts:t.cts?t.cts.subarray(0,e):null})}return n}function Pt(e,t,n){let r=t.firstMedia;if(!r)return e.edits.length&&n.push(`edit list has no media edit`),null;t.mediaEdits>1&&n.push(`edit list has ${t.mediaEdits} media edits, only the first is applied`),r.rate!==1&&n.push(`edit rate ${r.rate} is not applied`);let i=e.fragments.length>0||r.duration<=0?r.mediaTime:r.mediaTime+r.duration;return{start:r.mediaTime,end:i}}function Ft(e,t,n){let r=e.dv,i=e.co64??e.stco,a=e.stsz??e.stz2;if(!r||!i||!a||!e.stsc||i.start+8>i.end||e.stsc.start+8>e.stsc.end||a.start+12>a.end)return null;let o=!!e.co64,s=Math.min(r.getUint32(i.start+4),Math.floor((i.end-i.start-8)/(o?8:4))),c=Math.min(r.getUint32(e.stsc.start+4),Math.floor((e.stsc.end-e.stsc.start-8)/12)),l=e.stsz?r.getUint32(a.start+4):0,u=e.stz2?r.getUint8(a.start+7):32,d=Math.min(r.getUint32(a.start+8),n),f=a.end-a.start-12,p=e=>{if(l)return l;let t=a.start+12;if(u===32)return(e+1)*4<=f?r.getUint32(t+e*4):0;if(u===16)return(e+1)*2<=f?r.getUint16(t+e*2):0;if(u===8)return e<f?r.getUint8(t+e):0;let n=e>>1<f?r.getUint8(t+(e>>1)):0;return e&1?n&15:n>>4},m=0,h=0,g=0,_=0;for(let n=0;n<s&&g<d;n++){for(;_+1<c&&r.getUint32(e.stsc.start+8+(_+1)*12)<=n+1;)_++;let a=c?r.getUint32(e.stsc.start+12+_*12):0,s=o?Number(r.getBigUint64(i.start+8+n*8)):r.getUint32(i.start+8+n*4);for(let e=0;e<a&&g<d;e++,g++){let e=p(g);s<t&&m++,s+e<=t&&h===g&&h++,s+=e}}return{present:m,complete:h}}function It(e,t){let n=[16n,16n,30n],r=new Int32Array(9);for(let i=0;i<3;i++)for(let a=0;a<3;a++){let o=0n;for(let r=0;r<3;r++)o+=BigInt(e[i*3+r])*BigInt(t[r*3+a])>>n[r];r[i*3+a]=Number(BigInt.asIntN(32,o))}if(r[0]===65536&&r[4]===65536&&r[8]===1<<30&&!r[1]&&!r[2]&&!r[3]&&!r[5]&&!r[6]&&!r[7])return 0;let i=r[0]/65536,a=r[1]/65536,o=Math.hypot(i,r[3]/65536),s=Math.hypot(a,r[4]/65536);return o===0||s===0?0:Math.trunc(-(Math.atan2(a/s,i/o)*180/Math.PI))||0}Ee(),m();let Lt=65536;function Rt(e,t){return t.signal?.aborted===!0||e?.name===`AbortError`}function zt(e){return e.brand===`qt `||!e.hasFtyp&&e.topLevel.length>0?`mov`:`mp4`}async function Bt(e,t,n){let r=e.size,i=t.start+t.size>r;if(!i&&t.size>268435456)throw new W(`unsupported: moov larger than 256 MiB`);let a=i?Math.min(r-t.start,16777216):t.size,o=await e.view(t.start,a,0),s=G(o,0,o.byteLength);if(!s)throw new W(`incomplete file: moov is truncated`);at(o,s,n,i,t.start),i&&n.warnings.push(`moov size exceeds the file; parsed what is there`)}async function Vt(e,t,n){let r=e.size,i=0,a=t.readAhead.head,o=!1,s=0,c=!1,l=st(),u=async(t,n,r)=>ct(l,t,n)??e.view(t,n,r);for(;i+8<=r;){if(e.checkAbort(),++s>4e6){n.warnings.push(`too many top-level boxes`);break}let d=c&&!o&&r-i<=16777216?r-i:a,f=await u(i,Math.min(16,r-i),d),p;try{p=G(f,0,r-i,i)}catch(e){if(!o)throw e;n.warnings.push(`ignored trailing data at ${i}: ${e.message}`);break}if(!p)break;let m={...p,start:i,end:Math.min(i+p.size,r)},h=i+p.size,g=p.truncated&&o&&m.type!==`mdat`&&m.type!==`moof`;p.truncated&&(n.truncated=!0,n.warnings.push(g?`ignored trailing data at ${i}: not a box`:`'${m.type}' at ${i} is truncated`));let _={type:m.type,start:i,end:m.end,sidx:null};if(n.topLevel.push(_),g)break;if(m.type===`ftyp`){let t=await e.view(i,Math.min(m.size,1024)),r=m.headerSize;if(r+4<=t.byteLength){n.hasFtyp=!0,n.brand=String.fromCharCode(t.getUint8(r),t.getUint8(r+1),t.getUint8(r+2),t.getUint8(r+3));for(let e=r+8;e+4<=t.byteLength;e+=4)n.compatibleBrands.push(String.fromCharCode(t.getUint8(e),t.getUint8(e+1),t.getUint8(e+2),t.getUint8(e+3)))}}else if(m.type===`moov`)o?n.warnings.push(`ignored a second moov at ${i}`):(await Bt(e,m,n),o=!0);else if(m.type===`moof`){if(!o)throw new W(`corrupt file: movie fragment (moof) before moov`);if(m.size>67108864)throw new W(`corrupt file: moof larger than 64 MiB at ${i}`);let s=Math.min(m.size+16,r-i),c=await u(i,s,0),d=G(c,0,Math.min(m.size,c.byteLength));d&&Ge(c,d,i,n.moofCount,n,t.maxExpandedSamples),n.moofCount++;let f=0;try{let e=G(c,m.size,c.byteLength);e&&e.type===`mdat`&&(f=e.size)}catch{f=0}a=f<=Lt?t.readAhead.fragment:Math.min(65536,Math.max(1024,2*m.size+64)),f>Lt&&(!l.hints.length&&!l.mfraTried&&(r-i)/(m.size+f)>16&&(l.mfraTried=!0,l.hints=await ft(e)),l.next<l.hints.length&&!ct(l,i+m.size+f,16)&&await lt(e,l,i,a)),t.onProgress&&n.moofCount%64==0&&t.onProgress({phase:`fragments`,done:i,total:r})}else if(m.type===`sidx`&&!p.truncated){let e=await u(i,m.size,0),t=G(e,0,e.byteLength);t&&(_.sidx=Ke(e,t,i)),_.sidx&&_.sidx.subsegments.length>1&&!l.hints.length&&(l.hints=_.sidx.subsegments.map(([e])=>e))}else if(m.type===`mfra`)break;c=m.type===`mdat`,i=h}if(!o)throw new W(`incomplete file: no moov`)}async function Ht(e,t){let n=e.size,r=new Set(t.tracks.map(e=>e.id)),i=!1,a=!1,o=!1,s=null,c=0;for(let l of t.topLevel){if(l.type===`moof`)c++;else if(l.type===`moov`)i=!0;else if(l.type===`mdat`&&l.end-l.start>8)a=!0;else if(l.type===`sidx`&&i&&l.sidx&&!l.sidx.hierarchical&&r.has(l.sidx.referenceId)){let t=l.sidx.coverageEnd===n;!t&&n>=4&&(s===null&&(s=(await e.view(n-4,4,0)).getUint32(0)),t=l.sidx.coverageEnd===n-s),t&&l.sidx.firstOffset===0&&(o=!0)}if(i&&a&&(o||l.end===n)){t.ffprobeMoofLimit=c;return}}}function Ut(e,t){return t.chapterTrackIds.has(e.id)?!1:e.handler===`vide`||e.handler!==`soun`&&Fe(e.originalFormat??e.sampleEntry)}function Wt(e,t,n,r){let a=i(r.reportedId),o=a.warnings;r.reportedId!==e.id&&o.push(`duplicate track_ID ${e.id}: reported as ${r.reportedId}`),o.push(...e.warnings);let s=e.handler===`auxv`;s&&o.push(`auxiliary video track (handler 'auxv')`);let c=vt(e);c&&o.push(`missing mandatory sample tables: ffprobe ignores the samples and timing of this track`);let l=e.hasMdhd?e.timescale:t.timescale;e.hasMdhd||(o.push(`no mdhd: using the movie timescale`),e.timescale=l),a.fourccOrCodecId=e.sampleEntry,a.codecName=Ie(e.originalFormat??e.sampleEntry,e.esdsObjectType,e.hasHvcc),e.originalFormat&&o.push(`encrypted: ${e.sampleEntry} of ${e.originalFormat}`),e.stsdCount>1&&o.push(`${e.stsdCount} sample descriptions, first used`),a.width=e.width,a.height=e.height,a.rotation=It(e.matrix,t.matrix),a.timescale=l;let d=mt(e),f=t.truncated,p=0;for(let t of e.fragments)p+=t.present;let m=d.moovSamples+d.fragmentSamples,h=d.moovSamples+p;a.frames=h,a.isStill=h<=1,d.moovSamples>0&&e.fragments.length>0&&o.push(`hybrid fragmented file: moov holds ${d.moovSamples} of ${m} samples`),h<m&&o.push(`truncated: ${m-h} of ${m} samples missing`);let g=_t(e,t);a.avgFps=g.avg,a.avgFpsFfprobe=r.ffprobeFails?null:g.ffprobe,a.avgFpsFfprobe!==null&&a.avgFpsFfprobe!==u(g.avg)&&o.push(`ffprobe reads part of the fragments: avg_frame_rate ${a.avgFpsFfprobe}`),g.ffprobe===null&&!r.ffprobeFails&&m>0&&o.push(`avg_frame_rate of ffprobe is not reproduced: its header values are incomplete or overrun a box`);let _=r.ffprobeFails||c?null:jt(e,t,d.moovSamples,n.maxExpandedSamples,o);a.rFpsFfprobe=_?u(_):null;let v=yt(e,t.timescale,d);if(!c){let n=bt(e,t,d,v);a.durationSec=n.durationTs/l,a.startSec=n.startPts===null?null:n.startPts/l}let y=d.moovSamples;if(e.sampleCount!==null&&e.sampleCount<y&&(o.push(`stts describes ${y} samples but the sample size table holds ${e.sampleCount}`),y=e.sampleCount),c)return a.presentedFrames=0,Gt(a),{result:a,enabled:e.enabled,auxiliary:s};if(f&&y>0){let n=Ft(e,t.fileSize,d.moovSamples);n&&n.complete<y&&(o.push(`truncated: ${n.complete} of ${y} samples complete`),y=n.complete)}let b=Pt(e,v,o);b&&!e.cttsCounts&&!e.fragments.length&&b.start<=0&&(b.end<=b.start||b.end>=d.moovDuration)&&(b=null);let x=N({segments:Nt(e,y),timescale:l,editWindow:b,maxExpandedSamples:n.maxExpandedSamples});return o.push(...x.warnings),a.presentedFrames=x.presentedFrames,a.minFps=x.minFps,a.maxFps=x.maxFps,a.isVfr=x.isVfr,a.vfrRatio=x.vfrRatio,a.distinctDeltas=x.distinctDeltas,a.duplicateTimestamps=x.duplicateTimestamps,a.nominalFps=x.nominalFps,a.dominantFps=x.dominantFps,a.timestampsQuantized=x.timestampsQuantized,x.presentedAvgFps&&(a.avgFps=x.presentedAvgFps),a.duplicateTimestamps>0&&o.push(`${a.duplicateTimestamps} duplicate timestamps`),Gt(a),x.presentedAvgFps&&(a.provenance.avgFps=`exact`),{result:a,enabled:e.enabled,auxiliary:s,profile:x.profile}}function Gt(e){let t=e.provenance;for(let e of[`codec`,`dimensions`,`rotation`,`frames`,`avgFps`])t[e]=`header`;e.durationSec!==null&&(t.durationSec=`header`),e.startSec!==null&&(t.startSec=`header`),e.presentedFrames!==null&&(t.presentedFrames=`exact`),e.isVfr!==null&&(t.minFps=`exact`,t.maxFps=`exact`,t.isVfr=`exact`,t.duplicateTimestamps=`exact`),e.nominalFps&&(t.nominalFps=`exact`),e.dominantFps&&(t.dominantFps=`exact`)}function Kt(e){let t=null,n=e=>(e.result.frames??0)>1?e.auxiliary?.5:e.enabled?2:1:0;for(let r of e)(!t||n(r)>n(t)||n(r)===n(t)&&(r.result.frames??0)>(t.result.frames??0))&&(t=r);return t?t.result.trackId:null}function qt(e,t){let n=2**53-1,r=n,i=n,a=-n,o=-n,s=-n,c=-n;for(let n of e.tracks){if(!n.hasMdhd)continue;let l=t.has(n)||n.handler===`soun`;if(vt(n)){let e=Q(n.mdhdDuration,1e6,9e4);l?s=Math.max(s,e):c=Math.max(c,e);continue}let u=mt(n),d=bt(n,e,u,yt(n,e.timescale,u)),f=Q(d.durationTs,1e6,n.timescale);if(d.startPts!==null){let e=Q(d.startPts,1e6,n.timescale);l?(r=Math.min(r,e),a=Math.max(a,e+f)):(i=Math.min(i,e),o=Math.max(o,e+f))}l?s=Math.max(s,f):c=Math.max(c,f)}return(r===n||r>i&&r-i<1e6)&&(r=i),(a===-n||a<o&&o-a<1e6)&&(a=o),(s===-n||s<c&&c-s<1e6)&&(s=c),r!==n&&a!==-n&&a>=r&&(s=Math.max(s,a-r)),s>0?s/1e6:null}function Jt(e){let t=new Map,n=new Set,r=e.reduce((e,t)=>Math.max(e,t.id),0)+1;for(let i of e)n.has(i.id)?t.set(i,r++):(n.add(i.id),t.set(i,i.id));return t}async function Yt(e,t){let n=ze(e.size),i=t=>{if(Rt(t,e))throw t;let i=t instanceof Error?t.message:String(t),a=r(zt(n),t instanceof W||i.startsWith(`file read failed`)?i:`corrupt file: ${i}`);return a.brand=n.brand,a.warnings=n.warnings,{analysis:a,movie:n}};try{await Vt(e,t,n),await Ht(e,n);let i=r(zt(n));i.brand=n.brand,i.scan=`exact`,i.warnings=n.warnings;let a=n.ffprobeReject,o=a!==null&&a.moof<n.ffprobeMoofLimit;o&&n.warnings.push(`ffprobe 8.1.1 ${a.reason}`);let s=Jt(n.tracks);[...s].some(([e,t])=>e.id!==t)&&n.warnings.push(`duplicate track_ID values`);let c=n.tracks.filter(e=>Ut(e,n)),l=c.map(e=>Wt(e,n,t,{reportedId:s.get(e)??e.id,ffprobeFails:o}));for(let e of l)e.result.rateProfile=await ce(e.profile??null);return i.videoTracks=l.map(e=>e.result),i.audioTrackCount=n.tracks.filter(e=>e.handler===`soun`).length,i.primaryTrackId=Kt(l),i.formatDurationSec=qt(n,new Set(c)),{analysis:i,movie:n}}catch(e){return i(e)}}async function Xt(e,t){return(await Yt(e,t)).analysis}let Zt=new Set([`ftyp`,`moov`,`mdat`,`free`,`skip`,`wide`,`pnot`,`uuid`,`moof`,`styp`,`sidx`]),Qt=[26,69,223,163],$t=[{bytes:[137,80,78,71,13,10,26,10],offset:0,label:`PNG image`},{bytes:[255,216,255],offset:0,label:`JPEG image`},{bytes:[71,73,70,56],offset:0,label:`GIF image`},{bytes:[82,73,70,70],offset:0,label:`RIFF file (AVI/WAV/WebP)`},{bytes:[79,103,103,83],offset:0,label:`Ogg file`},{bytes:[70,76,86,1],offset:0,label:`FLV file`},{bytes:[0,0,1,186],offset:0,label:`MPEG program stream`},{bytes:[37,80,68,70],offset:0,label:`PDF document`},{bytes:[80,75,3,4],offset:0,label:`ZIP archive`},{bytes:[73,68,51],offset:0,label:`MP3 file`}];function en(e,t,n){if(e.length<n+t.length)return!1;for(let r=0;r<t.length;r++)if(e[n+r]!==t[r])return!1;return!0}function tn(e){for(let t=4;t<8;t++){let n=e[t];if(n<32||n>126)return!1}return!0}function nn(e){let t=Math.min(e.length,512);if(t===0)return!1;for(let n=0;n<t;n++){let t=e[n];if(t!==9&&t!==10&&t!==13&&(t<32||t===127))return!1}return!0}function rn(e){for(let t of $t)if(en(e,t.bytes,t.offset))return t.label;return e.length>=188&&e[0]===71&&e[188]===71?`MPEG transport stream`:nn(e)?`text file`:`no known signature`}function an(e){if(e.length===0)return{kind:`unknown`,reason:`empty file`};if(en(e,Qt,0))return{kind:`matroska`,reason:`EBML header 1A45DFA3`};if(e.length>=8&&tn(e)){let t=String.fromCharCode(e[4],e[5],e[6],e[7]);if(Zt.has(t)){let n=e[0]*16777216+e[1]*65536+e[2]*256+e[3];if(n===0)return{kind:`isobmff`,reason:`top-level '${t}' box running to end of file`};if(n>=8)return{kind:`isobmff`,reason:`top-level '${t}' box`};if(n===1){if(e.length<16)return{kind:`unknown`,reason:`'${t}' box with a truncated 64-bit size`};let n=0;for(let t=8;t<16;t++)n=n*256+e[t];if(n>=16)return{kind:`isobmff`,reason:`top-level '${t}' box with 64-bit size`}}return{kind:`unknown`,reason:`'${t}' box with invalid size ${n}`}}}return e.length<8?{kind:`unknown`,reason:`too small (${e.length} bytes)`}:{kind:`unknown`,reason:rn(e)}}async function on(e){let{kind:t}=an(new Uint8Array(await e.slice(0,Math.min(1024,e.size)).arrayBuffer()));return t===`unknown`?null:t}y();function sn(e,t){let{perReadMs:n,bytesPerMs:r}=t.costModel,i=t.readAhead.head;return e<Math.max(i,Math.min(i+n*r,1048576))?e:i}function cn(e){return e?.name===`AbortError`}function ln(e){return e instanceof Error?e.message||e.name:String(e)}function un(e,t){e.container=t.container,e.brand=t.brand,e.formatDurationSec=t.formatDurationSec,e.scan=t.scan,e.videoTracks=t.videoTracks,e.audioTrackCount=t.audioTrackCount,e.primaryTrackId=t.primaryTrackId,e.error=t.error,e.warnings=t.warnings}async function dn(e,t,n,i){let a=performance.now(),o=g(n);De(o.signal);let s={name:t,size:e.size,...r(`unknown`),io:{reads:0,bytesRead:0,ms:0},engine:`own`},c=null,l=0;try{if(c=new Oe(e,{headWindow:o.readAhead.head,signal:o.signal}),c.size===0)s.error=`not a recognised container: empty file`;else{let e=an(await c.bytes(0,Math.min(1024,c.size),sn(c.size,o)));if(e.kind===`unknown`)s.error=`not a recognised container: ${e.reason}`;else{s.container=e.kind===`isobmff`?`mp4`:`matroska`;let t=performance.now(),n=await i(e.kind);l=performance.now()-t,un(s,await n(c,o))}}}catch(e){if(o.signal?.aborted||cn(e))throw e;s.error=ln(e)}return c&&(s.io.reads=c.reads,s.io.bytesRead=c.bytesFetched),s.io.ms=performance.now()-a-l,s}let $=(e,t)=>Object.assign(Error(e),{code:t}),fn=e=>e===`isobmff`||e===`matroska`;function pn(e){let t=self,n=new Map,r=new Map,i=e=>t.postMessage({v:1,...e}),a=t=>{let r=n.get(t);if(!r){let i=Object.hasOwn(e,t)?e[t]:void 0;if(!i)return Promise.reject($(`unknown engine ${t}`,`unknown-engine`));r=(typeof i==`function`?Promise.all([i(),Promise.resolve().then(()=>(Ee(),O))]).then(([e])=>e):Promise.resolve(i)).catch(e=>{throw n.delete(t),e}),n.set(t,r)}return r},o=(e,t,n=!1,r=!1)=>{let a=t?.code,o=a===`unknown-engine`||a===`protocol`;i({type:`error`,id:e,message:ln(t),aborted:n||cn(t),...o?{code:a}:r&&{reason:`load`}})},s=async e=>{let t=new AbortController;r.set(e.id,t);let n=0,s=!0;try{if(!(e.file instanceof Blob))throw $(`malformed analyze request`,`protocol`);let r=await a(e.engine);if(s=!1,r.containers!==`any`){let t=await on(e.file);if(!t||!r.containers.includes(t))return i({type:`skipped`,id:e.id,reason:`unsupported-container`,family:t})}let o=await r.run(e.file,e.name,{...e.options,signal:t.signal,onProgress:t=>{let r=performance.now();r-n<50||(n=r,i({type:`progress`,id:e.id,progress:t}))}});i({type:`result`,id:e.id,result:o})}catch(n){o(e.id,n,t.signal.aborted,s)}finally{r.delete(e.id)}},c=async e=>{try{if(![e.engines,e.containers].every(Array.isArray)||!e.containers.every(fn))throw $(`malformed warm request`,`protocol`);await Promise.all(e.engines.map(async t=>(await a(t)).warm?.(e.containers))),i({type:`warmed`,id:e.id})}catch(t){o(e.id,t,!1,!0)}};t.onmessage=({data:e})=>{if(e?.v!==1)return o(e?.id??0,$(`unsupported protocol version ${e?.v}`,`protocol`));if(e.type===`cancel`)r.get(e.id)?.abort();else if(e.type===`analyze`)s(e);else if(e.type===`warm`)c(e);else{let t=e;o(t.id,$(`unknown request type ${t.type}`,`protocol`))}}}let mn={isobmff:`ISO BMFF`,matroska:`Matroska`},hn=(e,t)=>`the own ${mn[e]} worker does not read ${mn[t]}`;function gn(e,t){return{containers:`any`,run:(n,r,i)=>dn(n,r,i,n=>{if(n!==e)throw Error(hn(e,n));return t})}}pn({own:gn(`isobmff`,Xt)})})();
|