audio-snip 0.1.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/dist/cjs/core.js +149 -0
- package/dist/cjs/core.js.map +1 -0
- package/dist/cjs/index.js +11 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/plugins/mp3.js +357 -0
- package/dist/cjs/plugins/mp3.js.map +1 -0
- package/dist/cjs/plugins/mp4.js +276 -0
- package/dist/cjs/plugins/mp4.js.map +1 -0
- package/dist/esm/core.js +141 -0
- package/dist/esm/core.js.map +1 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/{plugins → esm/plugins}/mp3.js +31 -44
- package/dist/esm/plugins/mp3.js.map +1 -0
- package/dist/{plugins → esm/plugins}/mp4.js +84 -47
- package/dist/esm/plugins/mp4.js.map +1 -0
- package/dist/{core.d.ts → types/core.d.ts} +21 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/{plugins → types/plugins}/mp4.d.ts +0 -1
- package/package.json +16 -10
- package/dist/core.js +0 -73
- package/dist/core.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- package/dist/index.js.map +0 -1
- package/dist/plugins/mp3.js.map +0 -1
- package/dist/plugins/mp4.js.map +0 -1
- /package/dist/{plugins → types/plugins}/mp3.d.ts +0 -0
package/dist/cjs/core.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ─── Types ───────────────────────────────────────────────────────────────────
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.audioSnip = exports.RemoteFile = exports.BasePlugin = void 0;
|
|
5
|
+
exports.fetchRange = fetchRange;
|
|
6
|
+
exports.fetchContentLength = fetchContentLength;
|
|
7
|
+
exports.trimBySamples = trimBySamples;
|
|
8
|
+
class BasePlugin {
|
|
9
|
+
}
|
|
10
|
+
exports.BasePlugin = BasePlugin;
|
|
11
|
+
// ─── Shared utilities ────────────────────────────────────────────────────────
|
|
12
|
+
async function fetchRange(url, start, end) {
|
|
13
|
+
const resp = await fetch(url, {
|
|
14
|
+
headers: { Range: `bytes=${start}-${end}` },
|
|
15
|
+
});
|
|
16
|
+
if (!resp.ok && resp.status !== 206) {
|
|
17
|
+
throw new Error(`HTTP ${resp.status} fetching range ${start}-${end}`);
|
|
18
|
+
}
|
|
19
|
+
const data = new Uint8Array(await resp.arrayBuffer());
|
|
20
|
+
// If server ignored Range and returned full file, slice to requested range
|
|
21
|
+
if (resp.status === 200 && data.length > end - start + 1) {
|
|
22
|
+
return data.slice(start, end + 1);
|
|
23
|
+
}
|
|
24
|
+
return data;
|
|
25
|
+
}
|
|
26
|
+
async function fetchContentLength(url) {
|
|
27
|
+
const headResp = await fetch(url, { method: 'HEAD' });
|
|
28
|
+
const cl = headResp.headers.get('content-length');
|
|
29
|
+
if (cl)
|
|
30
|
+
return parseInt(cl, 10);
|
|
31
|
+
// Fallback: Range 0-0, parse Content-Range or Content-Length
|
|
32
|
+
const rangeResp = await fetch(url, {
|
|
33
|
+
headers: { Range: 'bytes=0-0' },
|
|
34
|
+
});
|
|
35
|
+
const cr = rangeResp.headers.get('content-range');
|
|
36
|
+
const cl2 = rangeResp.headers.get('content-length');
|
|
37
|
+
await rangeResp.arrayBuffer(); // consume body
|
|
38
|
+
if (cr) {
|
|
39
|
+
const match = cr.match(/\/(\d+)/);
|
|
40
|
+
if (match)
|
|
41
|
+
return parseInt(match[1], 10);
|
|
42
|
+
}
|
|
43
|
+
if (cl2)
|
|
44
|
+
return parseInt(cl2, 10);
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
// ─── RemoteFile — per-operation file handle ──────────────────────────────────
|
|
48
|
+
/**
|
|
49
|
+
* Wraps a URL for efficient byte access. On the first getRange() call it probes
|
|
50
|
+
* whether the server supports HTTP Range requests. If the server returns 200
|
|
51
|
+
* (full file), the data is kept in memory and all subsequent getRange() calls
|
|
52
|
+
* are served locally — the file is never re-downloaded.
|
|
53
|
+
*
|
|
54
|
+
* Create one RemoteFile per decode() call, let it go when done.
|
|
55
|
+
*/
|
|
56
|
+
class RemoteFile {
|
|
57
|
+
constructor(url) {
|
|
58
|
+
this.fullData = null;
|
|
59
|
+
this._size = null;
|
|
60
|
+
this._rangeSupported = null;
|
|
61
|
+
this.url = url;
|
|
62
|
+
}
|
|
63
|
+
get rangeSupported() {
|
|
64
|
+
return this._rangeSupported;
|
|
65
|
+
}
|
|
66
|
+
get size() {
|
|
67
|
+
return this._size;
|
|
68
|
+
}
|
|
69
|
+
/** Fetch content length via HEAD (does not download body). */
|
|
70
|
+
async fetchSize() {
|
|
71
|
+
if (this._size !== null)
|
|
72
|
+
return this._size;
|
|
73
|
+
if (this.fullData) {
|
|
74
|
+
this._size = this.fullData.length;
|
|
75
|
+
return this._size;
|
|
76
|
+
}
|
|
77
|
+
this._size = await fetchContentLength(this.url);
|
|
78
|
+
return this._size;
|
|
79
|
+
}
|
|
80
|
+
/** Read a byte range. Detects Range support on first call. */
|
|
81
|
+
async getRange(start, end) {
|
|
82
|
+
// Already have the whole file in memory — just slice
|
|
83
|
+
if (this.fullData) {
|
|
84
|
+
return this.fullData.slice(start, end + 1);
|
|
85
|
+
}
|
|
86
|
+
const resp = await fetch(this.url, {
|
|
87
|
+
headers: { Range: `bytes=${start}-${end}` },
|
|
88
|
+
});
|
|
89
|
+
if (!resp.ok && resp.status !== 206) {
|
|
90
|
+
throw new Error(`HTTP ${resp.status} fetching range ${start}-${end} from ${this.url}`);
|
|
91
|
+
}
|
|
92
|
+
const data = new Uint8Array(await resp.arrayBuffer());
|
|
93
|
+
if (resp.status === 206) {
|
|
94
|
+
this._rangeSupported = true;
|
|
95
|
+
// Pick up total size from Content-Range if we don't have it yet
|
|
96
|
+
if (this._size === null) {
|
|
97
|
+
const cr = resp.headers.get('content-range');
|
|
98
|
+
if (cr) {
|
|
99
|
+
const m = cr.match(/\/(\d+)/);
|
|
100
|
+
if (m)
|
|
101
|
+
this._size = parseInt(m[1], 10);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return data;
|
|
105
|
+
}
|
|
106
|
+
// Server returned 200 (full file) — keep it, never re-download
|
|
107
|
+
this._rangeSupported = false;
|
|
108
|
+
this.fullData = data;
|
|
109
|
+
this._size = data.length;
|
|
110
|
+
return data.slice(start, end + 1);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.RemoteFile = RemoteFile;
|
|
114
|
+
function trimBySamples(ctx, buffer, startSample, endSample) {
|
|
115
|
+
const start = Math.max(0, Math.round(startSample));
|
|
116
|
+
const end = Math.min(buffer.length, Math.round(endSample));
|
|
117
|
+
const length = end - start;
|
|
118
|
+
if (length <= 0) {
|
|
119
|
+
throw new Error(`Invalid trim range: startSample=${startSample}, endSample=${endSample}, bufferLength=${buffer.length}`);
|
|
120
|
+
}
|
|
121
|
+
const trimmed = ctx.createBuffer(buffer.numberOfChannels, length, buffer.sampleRate);
|
|
122
|
+
for (let ch = 0; ch < buffer.numberOfChannels; ch++) {
|
|
123
|
+
const src = buffer.getChannelData(ch);
|
|
124
|
+
trimmed.copyToChannel(src.subarray(start, end), ch);
|
|
125
|
+
}
|
|
126
|
+
return trimmed;
|
|
127
|
+
}
|
|
128
|
+
// ─── Plugin registry / singleton ─────────────────────────────────────────────
|
|
129
|
+
class AudioSnip {
|
|
130
|
+
constructor() {
|
|
131
|
+
this.plugins = [];
|
|
132
|
+
}
|
|
133
|
+
register(plugin) {
|
|
134
|
+
this.plugins.push(plugin);
|
|
135
|
+
}
|
|
136
|
+
resolve(url) {
|
|
137
|
+
for (const p of this.plugins) {
|
|
138
|
+
if (p.canHandle(url))
|
|
139
|
+
return p;
|
|
140
|
+
}
|
|
141
|
+
throw new Error(`No plugin registered for URL: ${url}`);
|
|
142
|
+
}
|
|
143
|
+
async decodeAudioDataSegment(ctx, url, startTime, endTime) {
|
|
144
|
+
const plugin = this.resolve(url);
|
|
145
|
+
return plugin.decode(ctx, url, startTime, endTime);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
exports.audioSnip = new AudioSnip();
|
|
149
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../src/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.trimBySamples = exports.fetchContentLength = exports.fetchRange = exports.RemoteFile = exports.BasePlugin = exports.audioSnip = void 0;
|
|
4
|
+
var core_js_1 = require("./core.js");
|
|
5
|
+
Object.defineProperty(exports, "audioSnip", { enumerable: true, get: function () { return core_js_1.audioSnip; } });
|
|
6
|
+
Object.defineProperty(exports, "BasePlugin", { enumerable: true, get: function () { return core_js_1.BasePlugin; } });
|
|
7
|
+
Object.defineProperty(exports, "RemoteFile", { enumerable: true, get: function () { return core_js_1.RemoteFile; } });
|
|
8
|
+
Object.defineProperty(exports, "fetchRange", { enumerable: true, get: function () { return core_js_1.fetchRange; } });
|
|
9
|
+
Object.defineProperty(exports, "fetchContentLength", { enumerable: true, get: function () { return core_js_1.fetchContentLength; } });
|
|
10
|
+
Object.defineProperty(exports, "trimBySamples", { enumerable: true, get: function () { return core_js_1.trimBySamples; } });
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;AAAA,qCAOmB;AANjB,oGAAA,SAAS,OAAA;AACT,qGAAA,UAAU,OAAA;AACV,qGAAA,UAAU,OAAA;AACV,qGAAA,UAAU,OAAA;AACV,6GAAA,kBAAkB,OAAA;AAClB,wGAAA,aAAa,OAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Mp3Plugin = void 0;
|
|
4
|
+
const core_js_1 = require("../core.js");
|
|
5
|
+
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
6
|
+
const HEAD_SIZE = 128 * 1024; // 128 KB initial fetch
|
|
7
|
+
// MPEG bitrate tables [version][layer][index]
|
|
8
|
+
const BITRATE_TABLE = {
|
|
9
|
+
'V1L1': [0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0],
|
|
10
|
+
'V1L2': [0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0],
|
|
11
|
+
'V1L3': [0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0],
|
|
12
|
+
'V2L1': [0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0],
|
|
13
|
+
'V2L2': [0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0],
|
|
14
|
+
'V2L3': [0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0],
|
|
15
|
+
};
|
|
16
|
+
const SAMPLE_RATE_TABLE = [
|
|
17
|
+
[44100, 48000, 32000, 0], // MPEG1
|
|
18
|
+
[22050, 24000, 16000, 0], // MPEG2
|
|
19
|
+
[11025, 12000, 8000, 0], // MPEG2.5
|
|
20
|
+
];
|
|
21
|
+
const SAMPLES_PER_FRAME = {
|
|
22
|
+
'V1L1': 384,
|
|
23
|
+
'V1L2': 1152,
|
|
24
|
+
'V1L3': 1152,
|
|
25
|
+
'V2L1': 384,
|
|
26
|
+
'V2L2': 1152,
|
|
27
|
+
'V2L3': 576,
|
|
28
|
+
};
|
|
29
|
+
function parseFrameHeader(data, offset) {
|
|
30
|
+
if (offset + 4 > data.length)
|
|
31
|
+
return null;
|
|
32
|
+
const b0 = data[offset];
|
|
33
|
+
const b1 = data[offset + 1];
|
|
34
|
+
const b2 = data[offset + 2];
|
|
35
|
+
const b3 = data[offset + 3];
|
|
36
|
+
// Sync: 11 bits set
|
|
37
|
+
if (b0 !== 0xFF || (b1 & 0xE0) !== 0xE0)
|
|
38
|
+
return null;
|
|
39
|
+
const versionBits = (b1 >> 3) & 0x03;
|
|
40
|
+
const layerBits = (b1 >> 1) & 0x03;
|
|
41
|
+
const bitrateIdx = (b2 >> 4) & 0x0F;
|
|
42
|
+
const srIdx = (b2 >> 2) & 0x03;
|
|
43
|
+
const padding = ((b2 >> 1) & 0x01) === 1;
|
|
44
|
+
const channelMode = (b3 >> 6) & 0x03;
|
|
45
|
+
// Reject reserved values
|
|
46
|
+
if (versionBits === 1 || layerBits === 0 || bitrateIdx === 0 || bitrateIdx === 15 || srIdx === 3) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
const mpegVersion = versionBits === 3 ? 1 : versionBits === 2 ? 2 : 2.5;
|
|
50
|
+
const layer = layerBits === 3 ? 1 : layerBits === 2 ? 2 : 3;
|
|
51
|
+
const vKey = mpegVersion === 1 ? 'V1' : 'V2';
|
|
52
|
+
const lKey = `L${layer}`;
|
|
53
|
+
const key = `${vKey}${lKey}`;
|
|
54
|
+
const bitrate = BITRATE_TABLE[key]?.[bitrateIdx];
|
|
55
|
+
if (!bitrate)
|
|
56
|
+
return null;
|
|
57
|
+
const srTableIdx = mpegVersion === 1 ? 0 : mpegVersion === 2 ? 1 : 2;
|
|
58
|
+
const sampleRate = SAMPLE_RATE_TABLE[srTableIdx][srIdx];
|
|
59
|
+
if (!sampleRate)
|
|
60
|
+
return null;
|
|
61
|
+
const samplesPerFrame = SAMPLES_PER_FRAME[key];
|
|
62
|
+
const channels = channelMode === 3 ? 1 : 2;
|
|
63
|
+
let frameSize;
|
|
64
|
+
if (layer === 1) {
|
|
65
|
+
frameSize = Math.floor((12 * bitrate * 1000) / sampleRate + (padding ? 1 : 0)) * 4;
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
frameSize = Math.floor((samplesPerFrame * (bitrate * 1000) / 8) / sampleRate) + (padding ? 1 : 0);
|
|
69
|
+
}
|
|
70
|
+
// Side information size for Layer 3
|
|
71
|
+
let sideInfoSize = 0;
|
|
72
|
+
if (layer === 3) {
|
|
73
|
+
if (mpegVersion === 1) {
|
|
74
|
+
sideInfoSize = channels === 1 ? 17 : 32;
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
sideInfoSize = channels === 1 ? 9 : 17;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
mpegVersion,
|
|
82
|
+
layer,
|
|
83
|
+
bitrate,
|
|
84
|
+
sampleRate,
|
|
85
|
+
channels,
|
|
86
|
+
padding,
|
|
87
|
+
samplesPerFrame,
|
|
88
|
+
frameSize,
|
|
89
|
+
sideInfoSize,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// ─── ID3v2 tag size ──────────────────────────────────────────────────────────
|
|
93
|
+
function id3v2Size(data) {
|
|
94
|
+
if (data.length < 10)
|
|
95
|
+
return 0;
|
|
96
|
+
if (data[0] !== 0x49 || data[1] !== 0x44 || data[2] !== 0x33)
|
|
97
|
+
return 0; // "ID3"
|
|
98
|
+
// Syncsafe integer at bytes 6-9
|
|
99
|
+
const size = ((data[6] & 0x7F) << 21) |
|
|
100
|
+
((data[7] & 0x7F) << 14) |
|
|
101
|
+
((data[8] & 0x7F) << 7) |
|
|
102
|
+
(data[9] & 0x7F);
|
|
103
|
+
const flags = data[5];
|
|
104
|
+
const hasFooter = (flags & 0x10) !== 0;
|
|
105
|
+
return size + 10 + (hasFooter ? 10 : 0); // 10-byte header + optional 10-byte footer
|
|
106
|
+
}
|
|
107
|
+
// ─── Find first frame sync after given offset ───────────────────────────────
|
|
108
|
+
function findFrameSync(data, start) {
|
|
109
|
+
for (let i = start; i < data.length - 4; i++) {
|
|
110
|
+
if (data[i] === 0xFF && (data[i + 1] & 0xE0) === 0xE0) {
|
|
111
|
+
const hdr = parseFrameHeader(data, i);
|
|
112
|
+
if (hdr && hdr.frameSize > 0) {
|
|
113
|
+
// Validate next frame exists
|
|
114
|
+
const next = i + hdr.frameSize;
|
|
115
|
+
if (next + 2 <= data.length) {
|
|
116
|
+
if (data[next] === 0xFF && (data[next + 1] & 0xE0) === 0xE0) {
|
|
117
|
+
return i;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
// Near end of data, trust single sync
|
|
122
|
+
return i;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return -1;
|
|
128
|
+
}
|
|
129
|
+
function parseXingVbri(data, frameOffset, header) {
|
|
130
|
+
// Xing/Info header is after frame header (4 bytes) + side info
|
|
131
|
+
const xingOffset = frameOffset + 4 + header.sideInfoSize;
|
|
132
|
+
if (xingOffset + 4 > data.length)
|
|
133
|
+
return null;
|
|
134
|
+
const tag = String.fromCharCode(data[xingOffset], data[xingOffset + 1], data[xingOffset + 2], data[xingOffset + 3]);
|
|
135
|
+
if (tag === 'Xing' || tag === 'Info') {
|
|
136
|
+
const flags = readU32BE(data, xingOffset + 4);
|
|
137
|
+
let pos = xingOffset + 8;
|
|
138
|
+
let totalFrames = null;
|
|
139
|
+
let totalBytes = null;
|
|
140
|
+
let toc = null;
|
|
141
|
+
if (flags & 1) {
|
|
142
|
+
totalFrames = readU32BE(data, pos);
|
|
143
|
+
pos += 4;
|
|
144
|
+
}
|
|
145
|
+
if (flags & 2) {
|
|
146
|
+
totalBytes = readU32BE(data, pos);
|
|
147
|
+
pos += 4;
|
|
148
|
+
}
|
|
149
|
+
if (flags & 4) {
|
|
150
|
+
toc = data.slice(pos, pos + 100);
|
|
151
|
+
pos += 100;
|
|
152
|
+
}
|
|
153
|
+
// flags & 8 → quality indicator, skip
|
|
154
|
+
if (flags & 8) {
|
|
155
|
+
pos += 4;
|
|
156
|
+
}
|
|
157
|
+
// LAME tag: encoder string at Xing+120, delay/padding at Xing+141
|
|
158
|
+
let encoderDelay = 0;
|
|
159
|
+
let encoderPadding = 0;
|
|
160
|
+
const lameOffset = xingOffset + 141;
|
|
161
|
+
if (lameOffset + 3 <= data.length) {
|
|
162
|
+
// Verify LAME tag exists (9 char encoder string at xingOffset+120)
|
|
163
|
+
const lameTag = String.fromCharCode(data[xingOffset + 120], data[xingOffset + 121], data[xingOffset + 122], data[xingOffset + 123]);
|
|
164
|
+
if (lameTag === 'LAME' || lameTag === 'Lavf' || lameTag === 'Lavc') {
|
|
165
|
+
// Encoder delay: 12 bits at byte 141, encoder padding: 12 bits at byte 142-143
|
|
166
|
+
const delayByte1 = data[xingOffset + 141];
|
|
167
|
+
const delayByte2 = data[xingOffset + 142];
|
|
168
|
+
const delayByte3 = data[xingOffset + 143];
|
|
169
|
+
encoderDelay = (delayByte1 << 4) | (delayByte2 >> 4);
|
|
170
|
+
encoderPadding = ((delayByte2 & 0x0F) << 8) | delayByte3;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
isVbr: tag === 'Xing',
|
|
175
|
+
totalFrames,
|
|
176
|
+
totalBytes,
|
|
177
|
+
toc,
|
|
178
|
+
encoderDelay,
|
|
179
|
+
encoderPadding,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
// Try VBRI (Fraunhofer) — always at offset 36 from frame start
|
|
183
|
+
const vbriOffset = frameOffset + 36;
|
|
184
|
+
if (vbriOffset + 4 <= data.length) {
|
|
185
|
+
const vbriTag = String.fromCharCode(data[vbriOffset], data[vbriOffset + 1], data[vbriOffset + 2], data[vbriOffset + 3]);
|
|
186
|
+
if (vbriTag === 'VBRI') {
|
|
187
|
+
const totalBytes = readU32BE(data, vbriOffset + 10);
|
|
188
|
+
const totalFrames = readU32BE(data, vbriOffset + 14);
|
|
189
|
+
return {
|
|
190
|
+
isVbr: true,
|
|
191
|
+
totalFrames,
|
|
192
|
+
totalBytes,
|
|
193
|
+
toc: null,
|
|
194
|
+
encoderDelay: 0,
|
|
195
|
+
encoderPadding: 0,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
function readU32BE(data, offset) {
|
|
202
|
+
return (((data[offset] << 24) >>> 0) +
|
|
203
|
+
(data[offset + 1] << 16) +
|
|
204
|
+
(data[offset + 2] << 8) +
|
|
205
|
+
data[offset + 3]);
|
|
206
|
+
}
|
|
207
|
+
// ─── TOC-based byte interpolation for VBR ────────────────────────────────────
|
|
208
|
+
function tocInterpolate(toc, fraction, totalBytes) {
|
|
209
|
+
// fraction is 0..1 representing position in file
|
|
210
|
+
const scaledPos = fraction * 100;
|
|
211
|
+
const idx = Math.min(99, Math.floor(scaledPos));
|
|
212
|
+
const idxFrac = scaledPos - idx;
|
|
213
|
+
const lower = toc[idx];
|
|
214
|
+
const upper = idx < 99 ? toc[idx + 1] : 256;
|
|
215
|
+
const interpolated = lower + idxFrac * (upper - lower);
|
|
216
|
+
return Math.floor((interpolated / 256) * totalBytes);
|
|
217
|
+
}
|
|
218
|
+
class Mp3Plugin extends core_js_1.BasePlugin {
|
|
219
|
+
constructor(options = {}) {
|
|
220
|
+
super();
|
|
221
|
+
this.paddingFrames = options.paddingFrames ?? 8;
|
|
222
|
+
}
|
|
223
|
+
canHandle(url) {
|
|
224
|
+
const path = url.split('?')[0].split('#')[0].toLowerCase();
|
|
225
|
+
return path.endsWith('.mp3');
|
|
226
|
+
}
|
|
227
|
+
async getInfo(url) {
|
|
228
|
+
const file = new core_js_1.RemoteFile(url);
|
|
229
|
+
const { header, vbrInfo, fileSize, audioStart } = await this.fetchHeader(file);
|
|
230
|
+
const duration = this.computeDuration(header, vbrInfo, fileSize, audioStart, vbrInfo?.encoderDelay ?? 0, vbrInfo?.encoderPadding ?? 0);
|
|
231
|
+
return {
|
|
232
|
+
duration,
|
|
233
|
+
sampleRate: header.sampleRate,
|
|
234
|
+
channels: header.channels,
|
|
235
|
+
bitrate: header.bitrate,
|
|
236
|
+
codec: `MPEG${header.mpegVersion} Layer ${header.layer}`,
|
|
237
|
+
isVbr: vbrInfo?.isVbr ?? false,
|
|
238
|
+
encoderDelay: vbrInfo?.encoderDelay ?? 0,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
async decode(ctx, url, startTime, endTime) {
|
|
242
|
+
const file = new core_js_1.RemoteFile(url);
|
|
243
|
+
const { header, vbrInfo, audioStart, xingFrameStart, fileSize } = await this.fetchHeader(file);
|
|
244
|
+
const sampleRate = header.sampleRate;
|
|
245
|
+
const encoderDelay = vbrInfo?.encoderDelay ?? 0;
|
|
246
|
+
const encoderPadding = vbrInfo?.encoderPadding ?? 0;
|
|
247
|
+
const isVbr = vbrInfo?.isVbr ?? false;
|
|
248
|
+
const duration = this.computeDuration(header, vbrInfo, fileSize, audioStart, encoderDelay, encoderPadding);
|
|
249
|
+
// Compute byte range for the requested time segment
|
|
250
|
+
let startByte;
|
|
251
|
+
let endByte;
|
|
252
|
+
// For VBR+TOC, map time to byte position via TOC
|
|
253
|
+
if (isVbr && vbrInfo?.toc && vbrInfo.totalBytes && duration) {
|
|
254
|
+
const startFrac = Math.max(0, startTime / duration);
|
|
255
|
+
const endFrac = Math.min(1, endTime / duration);
|
|
256
|
+
startByte = xingFrameStart + tocInterpolate(vbrInfo.toc, startFrac, vbrInfo.totalBytes);
|
|
257
|
+
endByte = xingFrameStart + tocInterpolate(vbrInfo.toc, endFrac, vbrInfo.totalBytes);
|
|
258
|
+
}
|
|
259
|
+
else {
|
|
260
|
+
// CBR or VBR-without-TOC: linear byte estimate
|
|
261
|
+
const bytesPerSecond = (header.bitrate * 1000) / 8;
|
|
262
|
+
startByte = audioStart + Math.floor(startTime * bytesPerSecond);
|
|
263
|
+
endByte = audioStart + Math.ceil(endTime * bytesPerSecond);
|
|
264
|
+
}
|
|
265
|
+
// Snap to frame boundaries and add padding
|
|
266
|
+
const paddingBytes = this.paddingFrames * header.frameSize;
|
|
267
|
+
const fetchStart = Math.max(audioStart, startByte - paddingBytes);
|
|
268
|
+
// Add extra frames at end for safety
|
|
269
|
+
const fetchEnd = Math.min((fileSize ?? endByte + paddingBytes * 2) - 1, endByte + paddingBytes * 2);
|
|
270
|
+
// Fetch the segment
|
|
271
|
+
const chunk = await file.getRange(fetchStart, fetchEnd);
|
|
272
|
+
// Find first valid frame in fetched chunk
|
|
273
|
+
const firstSync = findFrameSync(chunk, 0);
|
|
274
|
+
if (firstSync === -1) {
|
|
275
|
+
throw new Error('No valid MP3 frame found in fetched range');
|
|
276
|
+
}
|
|
277
|
+
// Walk frames to count samples up to the actual startByte offset
|
|
278
|
+
// This gives us exact sample count for trimming, even for VBR
|
|
279
|
+
const offsetInChunk = startByte - fetchStart;
|
|
280
|
+
let samplesBefore = 0;
|
|
281
|
+
let pos = firstSync;
|
|
282
|
+
while (pos < chunk.length - 4) {
|
|
283
|
+
const fh = parseFrameHeader(chunk, pos);
|
|
284
|
+
if (!fh || fh.frameSize <= 0)
|
|
285
|
+
break;
|
|
286
|
+
if (pos >= offsetInChunk)
|
|
287
|
+
break;
|
|
288
|
+
samplesBefore += fh.samplesPerFrame;
|
|
289
|
+
pos += fh.frameSize;
|
|
290
|
+
}
|
|
291
|
+
// Decode the entire fetched chunk
|
|
292
|
+
const audioData = new Uint8Array(chunk.subarray(firstSync)).buffer;
|
|
293
|
+
const decoded = await ctx.decodeAudioData(audioData.slice(0));
|
|
294
|
+
// Use decoded buffer's sampleRate — AudioContext may resample (e.g. 44100→48000)
|
|
295
|
+
const decodedRate = decoded.sampleRate;
|
|
296
|
+
const resampleRatio = decodedRate / sampleRate;
|
|
297
|
+
// Scale samplesBefore and encoderDelay to decoded rate
|
|
298
|
+
const trimStartSamples = Math.round((samplesBefore - encoderDelay) * resampleRatio);
|
|
299
|
+
const wantedSamples = Math.round((endTime - startTime) * decodedRate);
|
|
300
|
+
const startSample = Math.max(0, trimStartSamples);
|
|
301
|
+
let endSample = startSample + wantedSamples;
|
|
302
|
+
// If endTime >= duration, also trim encoder padding from end
|
|
303
|
+
if (duration && endTime >= duration - 0.01 && encoderPadding > 0) {
|
|
304
|
+
const scaledPadding = Math.round(encoderPadding * resampleRatio);
|
|
305
|
+
endSample = Math.min(endSample, decoded.length - scaledPadding);
|
|
306
|
+
}
|
|
307
|
+
endSample = Math.min(endSample, decoded.length);
|
|
308
|
+
return (0, core_js_1.trimBySamples)(ctx, decoded, startSample, endSample);
|
|
309
|
+
}
|
|
310
|
+
// ─── Internal helpers ────────────────────────────────────────────────────
|
|
311
|
+
async fetchHeader(file) {
|
|
312
|
+
const fileSize = await file.fetchSize();
|
|
313
|
+
let headData = await file.getRange(0, HEAD_SIZE - 1);
|
|
314
|
+
// Skip ID3v2 tag
|
|
315
|
+
let audioStart = 0;
|
|
316
|
+
const id3Size = id3v2Size(headData);
|
|
317
|
+
if (id3Size > 0) {
|
|
318
|
+
audioStart = id3Size;
|
|
319
|
+
if (id3Size >= HEAD_SIZE) {
|
|
320
|
+
headData = await file.getRange(id3Size, id3Size + HEAD_SIZE - 1);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
// Find first frame sync (search from 0 if we re-fetched past ID3, else from audioStart)
|
|
324
|
+
const searchStart = id3Size >= HEAD_SIZE ? 0 : audioStart;
|
|
325
|
+
const syncOffset = findFrameSync(headData, searchStart);
|
|
326
|
+
if (syncOffset === -1) {
|
|
327
|
+
throw new Error('No valid MP3 frame sync found');
|
|
328
|
+
}
|
|
329
|
+
const header = parseFrameHeader(headData, syncOffset);
|
|
330
|
+
const absoluteFrameOffset = id3Size >= HEAD_SIZE ? id3Size + syncOffset : syncOffset;
|
|
331
|
+
const vbrInfo = parseXingVbri(headData, syncOffset, header);
|
|
332
|
+
// Audio starts after the Xing/Info frame (if present), or at the first frame
|
|
333
|
+
const audioDataStart = vbrInfo
|
|
334
|
+
? absoluteFrameOffset + header.frameSize
|
|
335
|
+
: absoluteFrameOffset;
|
|
336
|
+
return {
|
|
337
|
+
header,
|
|
338
|
+
vbrInfo,
|
|
339
|
+
audioStart: audioDataStart,
|
|
340
|
+
xingFrameStart: absoluteFrameOffset,
|
|
341
|
+
fileSize,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
computeDuration(header, vbrInfo, fileSize, audioStart, encoderDelay = 0, encoderPadding = 0) {
|
|
345
|
+
if (vbrInfo?.totalFrames) {
|
|
346
|
+
const totalSamples = vbrInfo.totalFrames * header.samplesPerFrame - encoderDelay - encoderPadding;
|
|
347
|
+
return totalSamples / header.sampleRate;
|
|
348
|
+
}
|
|
349
|
+
if (fileSize) {
|
|
350
|
+
const audioBytes = fileSize - audioStart;
|
|
351
|
+
return audioBytes / ((header.bitrate * 1000) / 8);
|
|
352
|
+
}
|
|
353
|
+
return null;
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
exports.Mp3Plugin = Mp3Plugin;
|
|
357
|
+
//# sourceMappingURL=mp3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mp3.js","sourceRoot":"","sources":["../../../src/plugins/mp3.ts"],"names":[],"mappings":";;;AAAA,wCAKoB;AAEpB,gFAAgF;AAEhF,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC,uBAAuB;AAErD,8CAA8C;AAC9C,MAAM,aAAa,GAA6B;IAC9C,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IACjF,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IAC9E,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IAC7E,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IAC9E,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IACzE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;CAC1E,CAAC;AAEF,MAAM,iBAAiB,GAAe;IACpC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,QAAQ;IAClC,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,QAAQ;IAClC,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAG,UAAU;CACrC,CAAC;AAEF,MAAM,iBAAiB,GAA2B;IAChD,MAAM,EAAE,GAAG;IACX,MAAM,EAAE,IAAI;IACZ,MAAM,EAAE,IAAI;IACZ,MAAM,EAAE,GAAG;IACX,MAAM,EAAE,IAAI;IACZ,MAAM,EAAE,GAAG;CACZ,CAAC;AAgBF,SAAS,gBAAgB,CAAC,IAAgB,EAAE,MAAc;IACxD,IAAI,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAE1C,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IACxB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC5B,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC5B,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAE5B,oBAAoB;IACpB,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,EAAE,GAAG,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAErD,MAAM,WAAW,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IACrC,MAAM,SAAS,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IACnC,MAAM,UAAU,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IACpC,MAAM,KAAK,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IAC/B,MAAM,OAAO,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,IAAI,CAAC;IAErC,yBAAyB;IACzB,IAAI,WAAW,KAAK,CAAC,IAAI,SAAS,KAAK,CAAC,IAAI,UAAU,KAAK,CAAC,IAAI,UAAU,KAAK,EAAE,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QACjG,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,WAAW,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACxE,MAAM,KAAK,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,KAAK,EAAE,CAAC;IACzB,MAAM,GAAG,GAAG,GAAG,IAAI,GAAG,IAAI,EAAE,CAAC;IAE7B,MAAM,OAAO,GAAG,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IACjD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAE1B,MAAM,UAAU,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,UAAU,GAAG,iBAAiB,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC;IACxD,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAE7B,MAAM,eAAe,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,WAAW,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3C,IAAI,SAAiB,CAAC;IACtB,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,OAAO,GAAG,IAAI,CAAC,GAAG,UAAU,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACrF,CAAC;SAAM,CAAC;QACN,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,eAAe,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACpG,CAAC;IAED,oCAAoC;IACpC,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;QAChB,IAAI,WAAW,KAAK,CAAC,EAAE,CAAC;YACtB,YAAY,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1C,CAAC;aAAM,CAAC;YACN,YAAY,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;IAED,OAAO;QACL,WAAW;QACX,KAAK;QACL,OAAO;QACP,UAAU;QACV,QAAQ;QACR,OAAO;QACP,eAAe;QACf,SAAS;QACT,YAAY;KACb,CAAC;AACJ,CAAC;AAED,gFAAgF;AAEhF,SAAS,SAAS,CAAC,IAAgB;IACjC,IAAI,IAAI,CAAC,MAAM,GAAG,EAAE;QAAE,OAAO,CAAC,CAAC;IAC/B,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,CAAC,CAAC,CAAC,QAAQ;IAChF,gCAAgC;IAChC,MAAM,IAAI,GACR,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACxB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACxB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACnB,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IACtB,MAAM,SAAS,GAAG,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;IACvC,OAAO,IAAI,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,2CAA2C;AACtF,CAAC;AAED,+EAA+E;AAE/E,SAAS,aAAa,CAAC,IAAgB,EAAE,KAAa;IACpD,KAAK,IAAI,CAAC,GAAG,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;YACtD,MAAM,GAAG,GAAG,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACtC,IAAI,GAAG,IAAI,GAAG,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC;gBAC7B,6BAA6B;gBAC7B,MAAM,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC,SAAS,CAAC;gBAC/B,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;oBAC5B,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;wBAC5D,OAAO,CAAC,CAAC;oBACX,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,sCAAsC;oBACtC,OAAO,CAAC,CAAC;gBACX,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC,CAAC;AACZ,CAAC;AAaD,SAAS,aAAa,CACpB,IAAgB,EAChB,WAAmB,EACnB,MAAmB;IAEnB,+DAA+D;IAC/D,MAAM,UAAU,GAAG,WAAW,GAAG,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC;IAEzD,IAAI,UAAU,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAE9C,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAC7B,IAAI,CAAC,UAAU,CAAC,EAChB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,EACpB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,EACpB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CACrB,CAAC;IAEF,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC;QAC9C,IAAI,GAAG,GAAG,UAAU,GAAG,CAAC,CAAC;QAEzB,IAAI,WAAW,GAAkB,IAAI,CAAC;QACtC,IAAI,UAAU,GAAkB,IAAI,CAAC;QACrC,IAAI,GAAG,GAAsB,IAAI,CAAC;QAElC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,WAAW,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YACnC,GAAG,IAAI,CAAC,CAAC;QACX,CAAC;QACD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,UAAU,GAAG,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAClC,GAAG,IAAI,CAAC,CAAC;QACX,CAAC;QACD,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,CAAC,CAAC;YACjC,GAAG,IAAI,GAAG,CAAC;QACb,CAAC;QACD,sCAAsC;QACtC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACd,GAAG,IAAI,CAAC,CAAC;QACX,CAAC;QAED,kEAAkE;QAClE,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,IAAI,cAAc,GAAG,CAAC,CAAC;QAEvB,MAAM,UAAU,GAAG,UAAU,GAAG,GAAG,CAAC;QACpC,IAAI,UAAU,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAClC,mEAAmE;YACnE,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CACjC,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,EACtB,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,EACtB,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,EACtB,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,CACvB,CAAC;YACF,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;gBACnE,+EAA+E;gBAC/E,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC;gBAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC;gBAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC,CAAC;gBAC1C,YAAY,GAAG,CAAC,UAAU,IAAI,CAAC,CAAC,GAAG,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC;gBACrD,cAAc,GAAG,CAAC,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,UAAU,CAAC;YAC3D,CAAC;QACH,CAAC;QAED,OAAO;YACL,KAAK,EAAE,GAAG,KAAK,MAAM;YACrB,WAAW;YACX,UAAU;YACV,GAAG;YACH,YAAY;YACZ,cAAc;SACf,CAAC;IACJ,CAAC;IAED,+DAA+D;IAC/D,MAAM,UAAU,GAAG,WAAW,GAAG,EAAE,CAAC;IACpC,IAAI,UAAU,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,MAAM,CAAC,YAAY,CACjC,IAAI,CAAC,UAAU,CAAC,EAChB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,EACpB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,EACpB,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,CACrB,CAAC;QACF,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;YACvB,MAAM,UAAU,GAAG,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,EAAE,CAAC,CAAC;YACpD,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,EAAE,CAAC,CAAC;YACrD,OAAO;gBACL,KAAK,EAAE,IAAI;gBACX,WAAW;gBACX,UAAU;gBACV,GAAG,EAAE,IAAI;gBACT,YAAY,EAAE,CAAC;gBACf,cAAc,EAAE,CAAC;aAClB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,SAAS,CAAC,IAAgB,EAAE,MAAc;IACjD,OAAO,CACL,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC;QAC5B,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QACxB,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CACjB,CAAC;AACJ,CAAC;AAED,gFAAgF;AAEhF,SAAS,cAAc,CACrB,GAAe,EACf,QAAgB,EAChB,UAAkB;IAElB,iDAAiD;IACjD,MAAM,SAAS,GAAG,QAAQ,GAAG,GAAG,CAAC;IACjC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,SAAS,GAAG,GAAG,CAAC;IAEhC,MAAM,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,MAAM,KAAK,GAAG,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IAC5C,MAAM,YAAY,GAAG,KAAK,GAAG,OAAO,GAAG,CAAC,KAAK,GAAG,KAAK,CAAC,CAAC;IAEvD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,YAAY,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC;AACvD,CAAC;AAQD,MAAa,SAAU,SAAQ,oBAAU;IAGvC,YAAY,UAA4B,EAAE;QACxC,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,CAAC,CAAC;IAClD,CAAC;IAED,SAAS,CAAC,GAAW;QACnB,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QAC3D,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAW;QACvB,MAAM,IAAI,GAAG,IAAI,oBAAU,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC/E,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,IAAI,CAAC,EAAE,OAAO,EAAE,cAAc,IAAI,CAAC,CAAC,CAAC;QAEvI,OAAO;YACL,QAAQ;YACR,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,OAAO,EAAE,MAAM,CAAC,OAAO;YACvB,KAAK,EAAE,OAAO,MAAM,CAAC,WAAW,UAAU,MAAM,CAAC,KAAK,EAAE;YACxD,KAAK,EAAE,OAAO,EAAE,KAAK,IAAI,KAAK;YAC9B,YAAY,EAAE,OAAO,EAAE,YAAY,IAAI,CAAC;SACzC,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,MAAM,CACV,GAAqB,EACrB,GAAW,EACX,SAAiB,EACjB,OAAe;QAEf,MAAM,IAAI,GAAG,IAAI,oBAAU,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAE/F,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACrC,MAAM,YAAY,GAAG,OAAO,EAAE,YAAY,IAAI,CAAC,CAAC;QAChD,MAAM,cAAc,GAAG,OAAO,EAAE,cAAc,IAAI,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,OAAO,EAAE,KAAK,IAAI,KAAK,CAAC;QACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,eAAe,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,YAAY,EAAE,cAAc,CAAC,CAAC;QAE3G,oDAAoD;QACpD,IAAI,SAAiB,CAAC;QACtB,IAAI,OAAe,CAAC;QAEpB,iDAAiD;QACjD,IAAI,KAAK,IAAI,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,UAAU,IAAI,QAAQ,EAAE,CAAC;YAC5D,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC,CAAC;YACpD,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC,CAAC;YAChD,SAAS,GAAG,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;YACxF,OAAO,GAAG,cAAc,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;QACtF,CAAC;aAAM,CAAC;YACN,+CAA+C;YAC/C,MAAM,cAAc,GAAG,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC;YACnD,SAAS,GAAG,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,cAAc,CAAC,CAAC;YAChE,OAAO,GAAG,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,cAAc,CAAC,CAAC;QAC7D,CAAC;QAED,2CAA2C;QAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,SAAS,CAAC;QAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,EAAE,SAAS,GAAG,YAAY,CAAC,CAAC;QAClE,qCAAqC;QACrC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CACvB,CAAC,QAAQ,IAAI,OAAO,GAAG,YAAY,GAAG,CAAC,CAAC,GAAG,CAAC,EAC5C,OAAO,GAAG,YAAY,GAAG,CAAC,CAC3B,CAAC;QAEF,oBAAoB;QACpB,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAExD,0CAA0C;QAC1C,MAAM,SAAS,GAAG,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC1C,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/D,CAAC;QAED,iEAAiE;QACjE,8DAA8D;QAC9D,MAAM,aAAa,GAAG,SAAS,GAAG,UAAU,CAAC;QAC7C,IAAI,aAAa,GAAG,CAAC,CAAC;QACtB,IAAI,GAAG,GAAG,SAAS,CAAC;QACpB,OAAO,GAAG,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,MAAM,EAAE,GAAG,gBAAgB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;YACxC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,SAAS,IAAI,CAAC;gBAAE,MAAM;YACpC,IAAI,GAAG,IAAI,aAAa;gBAAE,MAAM;YAChC,aAAa,IAAI,EAAE,CAAC,eAAe,CAAC;YACpC,GAAG,IAAI,EAAE,CAAC,SAAS,CAAC;QACtB,CAAC;QAED,kCAAkC;QAClC,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;QACnE,MAAM,OAAO,GAAG,MAAM,GAAG,CAAC,eAAe,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAgB,CAAC,CAAC;QAE7E,iFAAiF;QACjF,MAAM,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;QACvC,MAAM,aAAa,GAAG,WAAW,GAAG,UAAU,CAAC;QAE/C,uDAAuD;QACvD,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,aAAa,GAAG,YAAY,CAAC,GAAG,aAAa,CAAC,CAAC;QACpF,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,SAAS,CAAC,GAAG,WAAW,CAAC,CAAC;QAEtE,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,gBAAgB,CAAC,CAAC;QAClD,IAAI,SAAS,GAAG,WAAW,GAAG,aAAa,CAAC;QAE5C,6DAA6D;QAC7D,IAAI,QAAQ,IAAI,OAAO,IAAI,QAAQ,GAAG,IAAI,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;YACjE,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,GAAG,aAAa,CAAC,CAAC;YACjE,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,GAAG,aAAa,CAAC,CAAC;QAClE,CAAC;QAED,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAEhD,OAAO,IAAA,uBAAa,EAAC,GAAG,EAAE,OAAO,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;IAC7D,CAAC;IAED,4EAA4E;IAEpE,KAAK,CAAC,WAAW,CAAC,IAAgB;QAOxC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,SAAS,EAAE,CAAC;QAExC,IAAI,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,SAAS,GAAG,CAAC,CAAC,CAAC;QAErD,iBAAiB;QACjB,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;QACpC,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;YAChB,UAAU,GAAG,OAAO,CAAC;YACrB,IAAI,OAAO,IAAI,SAAS,EAAE,CAAC;gBACzB,QAAQ,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,SAAS,GAAG,CAAC,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;QAED,wFAAwF;QACxF,MAAM,WAAW,GAAG,OAAO,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;QAC1D,MAAM,UAAU,GAAG,aAAa,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;QACxD,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;QACnD,CAAC;QAED,MAAM,MAAM,GAAG,gBAAgB,CAAC,QAAQ,EAAE,UAAU,CAAE,CAAC;QACvD,MAAM,mBAAmB,GAAG,OAAO,IAAI,SAAS,CAAC,CAAC,CAAC,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;QAErF,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;QAE5D,6EAA6E;QAC7E,MAAM,cAAc,GAAG,OAAO;YAC5B,CAAC,CAAC,mBAAmB,GAAG,MAAM,CAAC,SAAS;YACxC,CAAC,CAAC,mBAAmB,CAAC;QAExB,OAAO;YACL,MAAM;YACN,OAAO;YACP,UAAU,EAAE,cAAc;YAC1B,cAAc,EAAE,mBAAmB;YACnC,QAAQ;SACT,CAAC;IACJ,CAAC;IAEO,eAAe,CACrB,MAAmB,EACnB,OAAuB,EACvB,QAAuB,EACvB,UAAkB,EAClB,eAAuB,CAAC,EACxB,iBAAyB,CAAC;QAE1B,IAAI,OAAO,EAAE,WAAW,EAAE,CAAC;YACzB,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,GAAG,MAAM,CAAC,eAAe,GAAG,YAAY,GAAG,cAAc,CAAC;YAClG,OAAO,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC;QAC1C,CAAC;QACD,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;YACzC,OAAO,UAAU,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAzLD,8BAyLC"}
|