lyric-align-ts 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +19 -173
- package/THIRD_PARTY_NOTICES.md +115 -107
- package/dist/assets/manifest.json +3 -3
- package/dist/assets/parity.js +1 -1
- package/dist/assets/parity.wasm +0 -0
- package/dist/binding.js +1 -1
- package/dist/binding.js.map +1 -1
- package/dist/build-proof.json +14 -12
- package/dist/core/cue-score.d.mts +9 -0
- package/dist/core/refine.d.mts +32 -0
- package/dist/core/timeline-cues.d.mts +1 -0
- package/dist/index.js +135 -22
- package/dist/index.js.map +4 -4
- package/dist/types.d.ts +3 -0
- package/dist/worker.js +325 -150
- package/dist/worker.js.map +4 -4
- package/package.json +15 -46
package/dist/index.js
CHANGED
|
@@ -120,20 +120,26 @@ function scoreCues(run, reference) {
|
|
|
120
120
|
}
|
|
121
121
|
});
|
|
122
122
|
const n = expected.length, m = actual.length, width = m + 1;
|
|
123
|
-
const dp = new Uint32Array((n + 1) * width);
|
|
124
|
-
for (let i2 = 0; i2 <= n; i2++) dp[i2 * width] = i2;
|
|
125
|
-
for (let j2 = 0; j2 <= m; j2++) dp[j2] = j2;
|
|
126
|
-
for (let i2 = 1; i2 <= n; i2++) for (let j2 = 1; j2 <= m; j2++) dp[i2 * width + j2] = Math.min(dp[(i2 - 1) * width + j2] + 1, dp[i2 * width + j2 - 1] + 1, dp[(i2 - 1) * width + j2 - 1] + (expected[i2 - 1] === actual[j2 - 1] ? 0 : 1));
|
|
127
123
|
const mapping = new Int32Array(n).fill(-1);
|
|
128
|
-
let
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
124
|
+
let distance = 0;
|
|
125
|
+
if (n === m && expected.every((c, i) => c === actual[i])) {
|
|
126
|
+
for (let i = 0; i < n; i++) mapping[i] = i;
|
|
127
|
+
} else {
|
|
128
|
+
const dp = new Uint32Array((n + 1) * width);
|
|
129
|
+
for (let i2 = 0; i2 <= n; i2++) dp[i2 * width] = i2;
|
|
130
|
+
for (let j2 = 0; j2 <= m; j2++) dp[j2] = j2;
|
|
131
|
+
for (let i2 = 1; i2 <= n; i2++) for (let j2 = 1; j2 <= m; j2++) dp[i2 * width + j2] = Math.min(dp[(i2 - 1) * width + j2] + 1, dp[i2 * width + j2 - 1] + 1, dp[(i2 - 1) * width + j2 - 1] + (expected[i2 - 1] === actual[j2 - 1] ? 0 : 1));
|
|
132
|
+
let i = n, j = m;
|
|
133
|
+
while (i || j) {
|
|
134
|
+
const cost = dp[i * width + j];
|
|
135
|
+
if (i && j && cost === dp[(i - 1) * width + j - 1] + (expected[i - 1] === actual[j - 1] ? 0 : 1)) {
|
|
136
|
+
if (expected[i - 1] === actual[j - 1]) mapping[i - 1] = j - 1;
|
|
137
|
+
i--;
|
|
138
|
+
j--;
|
|
139
|
+
} else if (i && cost === dp[(i - 1) * width + j] + 1) i--;
|
|
140
|
+
else j--;
|
|
141
|
+
}
|
|
142
|
+
distance = dp[n * width + m];
|
|
137
143
|
}
|
|
138
144
|
let offset = 0;
|
|
139
145
|
const rows = reference.map((cue, index) => {
|
|
@@ -143,15 +149,15 @@ function scoreCues(run, reference) {
|
|
|
143
149
|
const complete = indices.length > 0 && indices.every((v, k) => v >= 0 && (!k || v === indices[k - 1] + 1));
|
|
144
150
|
const wordIds = [...new Set(indices.filter((x) => x >= 0).map((x) => owners[x]))];
|
|
145
151
|
const group = wordIds.map((x) => run.timeline[x]);
|
|
146
|
-
const
|
|
147
|
-
return { line: index + 1, text: cue.text, referenceStart: cue.start, start: group[0]?.startTime ?? null, end: group.at(-1)?.endTime ?? null, usable:
|
|
152
|
+
const valid2 = complete && group.every((w) => !hasMissingText(w) && Number.isFinite(w.startTime) && w.startTime >= 0 && w.startTime <= run.audioSeconds) && group.every((w, k) => !k || w.startTime >= group[k - 1].startTime);
|
|
153
|
+
return { line: index + 1, text: cue.text, referenceStart: cue.start, start: group[0]?.startTime ?? null, end: group.at(-1)?.endTime ?? null, usable: valid2, textComplete: complete, error: valid2 ? group[0].startTime - cue.start : null };
|
|
148
154
|
});
|
|
149
155
|
const errors = rows.filter((r) => r.usable).map((r) => Math.abs(r.error));
|
|
150
|
-
return { total: rows.length, matched: errors.length, withinOne: errors.filter((e) => e <= 1 + 1e-9).length, max: errors.length ? Math.max(...errors) : null, mean: errors.length ? errors.reduce((a, b) => a + b) / errors.length : null, characterEditDistance:
|
|
156
|
+
return { total: rows.length, matched: errors.length, withinOne: errors.filter((e) => e <= 1 + 1e-9).length, max: errors.length ? Math.max(...errors) : null, mean: errors.length ? errors.reduce((a, b) => a + b) / errors.length : null, characterEditDistance: distance, rows };
|
|
151
157
|
}
|
|
152
158
|
|
|
153
|
-
// src/cues.
|
|
154
|
-
function
|
|
159
|
+
// src/core/timeline-cues.mjs
|
|
160
|
+
function mapTimelineToCues(lyrics, words, audioSeconds) {
|
|
155
161
|
const rows = scoreCues({ timeline: words, audioSeconds }, lyrics.map((text) => ({ text, start: 0 }))).rows;
|
|
156
162
|
return rows.map((row) => {
|
|
157
163
|
const issues = [];
|
|
@@ -165,6 +171,11 @@ function timelineToCues(lyrics, words, audioSeconds) {
|
|
|
165
171
|
return { id: row.line, text: row.text, start: row.start, end: row.end, matched: row.usable, issues };
|
|
166
172
|
});
|
|
167
173
|
}
|
|
174
|
+
|
|
175
|
+
// src/cues.ts
|
|
176
|
+
function timelineToCues(lyrics, words, audioSeconds) {
|
|
177
|
+
return mapTimelineToCues(lyrics, words, audioSeconds);
|
|
178
|
+
}
|
|
168
179
|
function timestamp(seconds) {
|
|
169
180
|
const total = Math.round(seconds * 1e3);
|
|
170
181
|
const pad = (n, width = 2) => String(n).padStart(width, "0");
|
|
@@ -177,6 +188,79 @@ ${c.text}
|
|
|
177
188
|
`).join("\n");
|
|
178
189
|
}
|
|
179
190
|
|
|
191
|
+
// src/core/refine.mjs
|
|
192
|
+
var REFINE = { meanTokenSeconds: 0.1, longestTokenSeconds: 3, rateDeviation: 1, maxFlaggedFraction: 0.25, runGap: 1, maxExpansion: 1, anchorTolerance: 0.5, clipMargin: 0.3, minClipSeconds: 1 };
|
|
193
|
+
var valid = (cue) => cue.matched && Number.isFinite(cue.start) && Number.isFinite(cue.end);
|
|
194
|
+
var tokensOf = (words) => words.flatMap((w) => w.timeline?.length ? w.timeline : [w]).sort((a, b) => a.startTime - b.startTime);
|
|
195
|
+
var median = (values) => {
|
|
196
|
+
const s = [...values].sort((x, y) => x - y);
|
|
197
|
+
return s[s.length >> 1];
|
|
198
|
+
};
|
|
199
|
+
function suspectLines(cues, words) {
|
|
200
|
+
const tokens = tokensOf(words), rate = (cue) => (cue.end - cue.start) / Math.max(1, Array.from(cue.text.replace(/\s/g, "")).length);
|
|
201
|
+
const typical = median(cues.filter(valid).map(rate));
|
|
202
|
+
return cues.map((cue) => {
|
|
203
|
+
if (!valid(cue)) return false;
|
|
204
|
+
const durations = tokens.filter((t) => t.startTime >= cue.start - 1e-6 && t.startTime < cue.end - 1e-6).map((t) => t.endTime - t.startTime);
|
|
205
|
+
const mean = durations.length ? durations.reduce((a, b) => a + b, 0) / durations.length : 0, longest = durations.length ? Math.max(...durations) : 0;
|
|
206
|
+
return mean < REFINE.meanTokenSeconds || longest > REFINE.longestTokenSeconds || Math.abs(Math.log(rate(cue) / typical)) > REFINE.rateDeviation;
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
function suspectRuns(flags) {
|
|
210
|
+
const runs = [], n = flags.length;
|
|
211
|
+
let i = 0;
|
|
212
|
+
while (i < n) {
|
|
213
|
+
if (!flags[i]) {
|
|
214
|
+
i++;
|
|
215
|
+
continue;
|
|
216
|
+
}
|
|
217
|
+
let j = i;
|
|
218
|
+
while (j + REFINE.runGap < n && (flags[j + 1] || flags[j + 2])) j = flags[j + 1] ? j + 1 : j + 2;
|
|
219
|
+
runs.push([i, j]);
|
|
220
|
+
i = j + 1;
|
|
221
|
+
}
|
|
222
|
+
return runs;
|
|
223
|
+
}
|
|
224
|
+
var matchedCount = (cues) => cues.filter(valid).length;
|
|
225
|
+
async function refineTimeline({ lines, words, audioSeconds, alignClip, onStep }) {
|
|
226
|
+
let current = words, cues = mapTimelineToCues(lines, words, audioSeconds);
|
|
227
|
+
const flags = suspectLines(cues, words), flagged = flags.filter(Boolean).length;
|
|
228
|
+
const summary = { flaggedLines: flagged, attempts: 0, refinedLines: 0 };
|
|
229
|
+
if (!flagged || flagged > cues.length * REFINE.maxFlaggedFraction) return { words, cues, ...summary };
|
|
230
|
+
const runs = suspectRuns(flags);
|
|
231
|
+
let step = 0;
|
|
232
|
+
for (const [first, last] of runs) {
|
|
233
|
+
onStep?.(step++, runs.length);
|
|
234
|
+
for (let expand = 0; expand <= REFINE.maxExpansion; expand++) {
|
|
235
|
+
const a = Math.max(0, first - expand), b = Math.min(cues.length - 1, last + expand), left = a > 0, right = b + 1 < cues.length;
|
|
236
|
+
const fi = left ? a - 1 : 0, lj = right ? b + 1 : cues.length - 1;
|
|
237
|
+
if (left && !valid(cues[fi]) || right && !valid(cues[lj])) continue;
|
|
238
|
+
const from = left ? Math.max(0, cues[fi].start - REFINE.clipMargin) : 0, to = right ? Math.min(audioSeconds, cues[lj].end + REFINE.clipMargin) : audioSeconds;
|
|
239
|
+
if (to - from < REFINE.minClipSeconds) continue;
|
|
240
|
+
const clipLines = lines.slice(left ? fi : a, right ? lj + 1 : b + 1);
|
|
241
|
+
summary.attempts++;
|
|
242
|
+
const clip = await alignClip(from, to, clipLines);
|
|
243
|
+
if (!clip) continue;
|
|
244
|
+
const found = mapTimelineToCues(clipLines, clip, to - from), lead = left ? 1 : 0, inner = found.slice(lead, lead + (b - a + 1));
|
|
245
|
+
if (left && (!valid(found[0]) || Math.abs(found[0].start + from - cues[fi].start) > REFINE.anchorTolerance)) continue;
|
|
246
|
+
if (right && (!valid(found.at(-1)) || Math.abs(found.at(-1).end + from - cues[lj].end) > REFINE.anchorTolerance)) continue;
|
|
247
|
+
if (!inner.every(valid)) continue;
|
|
248
|
+
const oldFrom = left ? cues[fi].end : 0, oldTo = right ? cues[lj].start : audioSeconds, newFrom = left ? found[0].end : 0, newTo = right ? found.at(-1).start : to - from;
|
|
249
|
+
const merged = [...current.filter((w) => w.startTime < oldFrom - 1e-6 || w.startTime >= oldTo - 1e-6), ...shift(clip.filter((w) => w.startTime >= newFrom - 1e-6 && w.startTime < newTo - 1e-6), from)].sort((x, y) => x.startTime - y.startTime);
|
|
250
|
+
const remapped = mapTimelineToCues(lines, merged, audioSeconds);
|
|
251
|
+
if (matchedCount(remapped) < matchedCount(cues)) continue;
|
|
252
|
+
current = merged;
|
|
253
|
+
cues = remapped;
|
|
254
|
+
summary.refinedLines += b - a + 1;
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
return { words: current, cues, ...summary };
|
|
259
|
+
}
|
|
260
|
+
function shift(entries, seconds) {
|
|
261
|
+
return entries.map((entry) => ({ ...entry, startTime: entry.startTime + seconds, endTime: entry.endTime + seconds, ...entry.timeline ? { timeline: shift(entry.timeline, seconds) } : {} }));
|
|
262
|
+
}
|
|
263
|
+
|
|
180
264
|
// src/subtitles.ts
|
|
181
265
|
function parseTimestamp(value) {
|
|
182
266
|
const match = /^(\d{2,}):(\d{2}):(\d{2})[,.](\d{3})$/.exec(value);
|
|
@@ -215,7 +299,7 @@ function normalizeError(value, fallback) {
|
|
|
215
299
|
}
|
|
216
300
|
var capabilities = Object.freeze({
|
|
217
301
|
contractVersion: 1,
|
|
218
|
-
libraryVersion: "1.0.
|
|
302
|
+
libraryVersion: "1.0.2",
|
|
219
303
|
supportedLanguages: Object.freeze(["en", "ja", "zh"]),
|
|
220
304
|
model: Object.freeze({ id: "ggerganov/whisper.cpp/ggml-tiny-q5_1.bin", revision: "5359861c739e955e79d9a303bcbc70fb988958b1", device: "wasm", dtype: "q5_1" }),
|
|
221
305
|
alignmentOptions: Object.freeze(["threshold", "karaoke"]),
|
|
@@ -444,13 +528,42 @@ async function createAligner(options = {}) {
|
|
|
444
528
|
const audioPreparationSeconds = (performance.now() - operationStart) / 1e3;
|
|
445
529
|
if (disposed || input.signal?.aborted) throw abortError();
|
|
446
530
|
const audioSeconds = samples.length / 16e3;
|
|
531
|
+
const original = input.language === "ja" || input.language === "en" ? samples.slice() : void 0;
|
|
447
532
|
const result = await request({ type: "align", audio: samples, lyrics: lines.join("\n"), language: input.language }, input.onProgress, [samples.buffer]);
|
|
448
533
|
const cueStart = performance.now();
|
|
449
|
-
|
|
534
|
+
let words = result.words, cues = result.cues ?? timelineToCues(lines, words, audioSeconds);
|
|
535
|
+
let refinementSeconds = 0, refinedLines = 0;
|
|
536
|
+
if (original) {
|
|
537
|
+
const refineStart = performance.now();
|
|
538
|
+
const refined = await refineTimeline({
|
|
539
|
+
lines,
|
|
540
|
+
words,
|
|
541
|
+
audioSeconds,
|
|
542
|
+
onStep: (completed, total) => {
|
|
543
|
+
try {
|
|
544
|
+
input.onProgress?.({ stage: "refine", completed, total });
|
|
545
|
+
} catch {
|
|
546
|
+
}
|
|
547
|
+
},
|
|
548
|
+
alignClip: async (from, to, clipLines) => {
|
|
549
|
+
const clip = original.slice(Math.floor(from * 16e3), Math.ceil(to * 16e3));
|
|
550
|
+
try {
|
|
551
|
+
return (await request({ type: "align", audio: clip, lyrics: clipLines.join("\n"), language: input.language }, void 0, [clip.buffer])).words;
|
|
552
|
+
} catch (error) {
|
|
553
|
+
if (disposed || input.signal?.aborted) throw error;
|
|
554
|
+
return void 0;
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
words = refined.words;
|
|
559
|
+
cues = refined.cues;
|
|
560
|
+
refinedLines = refined.refinedLines;
|
|
561
|
+
refinementSeconds = (performance.now() - refineStart) / 1e3;
|
|
562
|
+
}
|
|
450
563
|
const srt = toSrt(cues);
|
|
451
|
-
const cueMappingSeconds = (performance.now() - cueStart) / 1e3;
|
|
564
|
+
const cueMappingSeconds = (performance.now() - cueStart) / 1e3 - refinementSeconds;
|
|
452
565
|
const operationSeconds = (performance.now() - operationStart) / 1e3;
|
|
453
|
-
return { ...result, cues, srt, audioSeconds, metrics: { ...result.metrics, engineTotalSeconds: result.metrics.totalSeconds, initializationSeconds, audioPreparationSeconds, cueMappingSeconds, operationSeconds, totalSeconds: initializationSeconds + operationSeconds } };
|
|
566
|
+
return { ...result, words, cues, srt, audioSeconds, metrics: { ...result.metrics, engineTotalSeconds: result.metrics.totalSeconds, initializationSeconds, audioPreparationSeconds, cueMappingSeconds, refinementSeconds, refinedLines, operationSeconds, totalSeconds: initializationSeconds + operationSeconds } };
|
|
454
567
|
} finally {
|
|
455
568
|
busy = false;
|
|
456
569
|
input.signal?.removeEventListener("abort", onAbort);
|
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/audio.ts", "../src/core/score.mjs", "../src/core/cue-score.mjs", "../src/cues.ts", "../src/subtitles.ts", "../src/model.ts", "../src/binding.ts", "../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["import type { AudioInput } from './types.ts';\r\n\r\nasync function abortable<T>(operation: Promise<T>, signal?: AbortSignal): Promise<T> {\r\n if (!signal) return operation;\r\n signal.throwIfAborted();\r\n return new Promise<T>((resolve, reject) => {\r\n const abort = () => { cleanup(); reject(signal.reason); };\r\n const cleanup = () => signal.removeEventListener('abort', abort);\r\n signal.addEventListener('abort', abort, { once: true });\r\n operation.then(value => { cleanup(); resolve(value); }, error => { cleanup(); reject(error); });\r\n });\r\n}\r\n\r\nfunction validate(samples: Float32Array): Float32Array {\r\n if (!samples.length) throw new TypeError('Audio must contain at least one sample');\r\n for (const sample of samples) if (!Number.isFinite(sample)) throw new TypeError('Audio samples must be finite');\r\n return samples.slice();\r\n}\r\nasync function fromBuffer(buffer: AudioBuffer, signal?: AbortSignal): Promise<Float32Array> {\r\n if (!buffer.numberOfChannels || !buffer.length) throw new TypeError('Audio must not be empty');\r\n const mono = new Float32Array(buffer.length);\r\n for (let ch = 0; ch < buffer.numberOfChannels; ch++) {\r\n const samples = buffer.getChannelData(ch);\r\n for (let i = 0; i < mono.length; i++) mono[i] += samples[i] / buffer.numberOfChannels;\r\n }\r\n if (buffer.sampleRate === 16000) return validate(mono);\r\n if (typeof OfflineAudioContext === 'undefined') throw new Error('Resampling requires Web Audio OfflineAudioContext');\r\n const context = new OfflineAudioContext(1, Math.ceil(buffer.length * 16000 / buffer.sampleRate), 16000);\r\n const source = context.createBufferSource();\r\n const input = context.createBuffer(1, mono.length, buffer.sampleRate);\r\n input.copyToChannel(mono, 0);\r\n source.buffer = input;\r\n source.connect(context.destination);\r\n source.start();\r\n const rendered = await abortable(context.startRendering(), signal);\r\n return validate(rendered.getChannelData(0));\r\n}\r\nfunction pcmWav16000(bytes: ArrayBuffer): Float32Array | undefined {\r\n if(bytes.byteLength<12)return;\r\n const v=new DataView(bytes),tag=(at:number,s:string)=>[...s].every((c,i)=>v.getUint8(at+i)===c.charCodeAt(0));\r\n if(!tag(0,'RIFF')||!tag(8,'WAVE'))return;\r\n const end=v.getUint32(4,true)+8;if(end>bytes.byteLength||end<12)return;\r\n let format=false,data=-1,length=0;\r\n for(let at=12;at<end;){\r\n if(at+8>end)return;\r\n const size=v.getUint32(at+4,true),start=at+8,next=start+size+(size%2);\r\n if(next>end)return;\r\n if(tag(at,'fmt ')){\r\n if(size<16)return;\r\n format=v.getUint16(start,true)===1&&v.getUint16(start+2,true)===1&&v.getUint32(start+4,true)===16000&&v.getUint32(start+8,true)===32000&&v.getUint16(start+12,true)===2&&v.getUint16(start+14,true)===16;\r\n if(!format)return;\r\n }else if(tag(at,'data')){if(data>=0)return;data=start;length=size;}\r\n at=next;\r\n }\r\n if(!format||data<0||!length||length%2)return;\r\n const pcm=new Float32Array(length/2);\r\n // Match the browser's asymmetric signed-PCM normalization, including both full-scale endpoints.\r\n const positiveScale=Math.fround(1/32767);\r\n for(let i=0;i<pcm.length;i++){const sample=v.getInt16(data+i*2,true);pcm[i]=sample*(sample<0?1/32768:positiveScale);}\r\n return pcm;\r\n}\r\n/** Known PCM WAV is decoded directly; other files use browser codecs. Caller PCM is copied. */\r\nexport async function prepareAudio(audio: AudioInput, signal?: AbortSignal): Promise<Float32Array> {\r\n signal?.throwIfAborted();\r\n if (audio && typeof audio === 'object' && 'samples' in audio) {\r\n if (!(audio.samples instanceof Float32Array) || audio.sampleRate !== 16000) throw new TypeError('PCM requires Float32Array samples at sampleRate: 16000');\r\n return validate(audio.samples);\r\n }\r\n if (audio && typeof audio === 'object' && 'getChannelData' in audio) return fromBuffer(audio as AudioBuffer, signal);\r\n if (typeof Blob !== 'undefined' && audio instanceof Blob) {\r\n const bytes = await abortable(audio.arrayBuffer(), signal);\r\n signal?.throwIfAborted();\r\n const pcm=pcmWav16000(bytes);if(pcm)return pcm;\r\n if (typeof AudioContext === 'undefined') throw new Error('Decoding files requires Web Audio AudioContext');\r\n const context = new AudioContext({ sampleRate: 16000 });\r\n let closing: Promise<void> | undefined;\r\n const close = () => closing ??= context.close().catch(() => {});\r\n const abort = () => { void close(); };\r\n signal?.addEventListener('abort', abort, { once: true });\r\n try {\r\n const buffer = await abortable(context.decodeAudioData(bytes), signal);\r\n return await fromBuffer(buffer, signal);\r\n } finally { signal?.removeEventListener('abort', abort); await close(); }\r\n }\r\n throw new TypeError('audio must be a File/Blob, AudioBuffer, or 16000 Hz PCM input');\r\n}\r\n", "// Shared text normalization for monotonic lyric matching and evaluation.\r\nexport const normalize=text=>text.normalize('NFKC').toLowerCase().replace(/[^\\p{L}\\p{N}]/gu,'');\r\n", "import {normalize} from './score.mjs';\r\nconst hasMissingText=w=>w.confidence===0||(w.timeline??[]).some(hasMissingText);\r\n// Monotonic character alignment handles omitted text without shifting every later cue.\r\n// Reference timestamps never participate in matching.\r\nexport function scoreCues(run,reference){\r\n const expected=Array.from(reference.map(x=>normalize(x.text)).join(''));\r\n const actual=[],owners=[];\r\n run.timeline.forEach((w,index)=>{for(const c of normalize(w.text)){actual.push(c);owners.push(index);}});\r\n const n=expected.length,m=actual.length,width=m+1;\r\n const dp=new Uint32Array((n+1)*width);\r\n for(let i=0;i<=n;i++)dp[i*width]=i;for(let j=0;j<=m;j++)dp[j]=j;\r\n for(let i=1;i<=n;i++)for(let j=1;j<=m;j++)dp[i*width+j]=Math.min(dp[(i-1)*width+j]+1,dp[i*width+j-1]+1,dp[(i-1)*width+j-1]+(expected[i-1]===actual[j-1]?0:1));\r\n const mapping=new Int32Array(n).fill(-1);let i=n,j=m;\r\n while(i||j){const cost=dp[i*width+j];if(i&&j&&cost===dp[(i-1)*width+j-1]+(expected[i-1]===actual[j-1]?0:1)){if(expected[i-1]===actual[j-1])mapping[i-1]=j-1;i--;j--;}else if(i&&cost===dp[(i-1)*width+j]+1)i--;else j--;}\r\n let offset=0;\r\n const rows=reference.map((cue,index)=>{const a=offset;offset+=Array.from(normalize(cue.text)).length;const indices=Array.from(mapping.slice(a,offset));\r\n const complete=indices.length>0&&indices.every((v,k)=>v>=0&&(!k||v===indices[k-1]+1));\r\n const wordIds=[...new Set(indices.filter(x=>x>=0).map(x=>owners[x]))];const group=wordIds.map(x=>run.timeline[x]);\r\n const valid=complete&&group.every(w=>!hasMissingText(w)&&Number.isFinite(w.startTime)&&w.startTime>=0&&w.startTime<=run.audioSeconds)&&group.every((w,k)=>!k||w.startTime>=group[k-1].startTime);\r\n return {line:index+1,text:cue.text,referenceStart:cue.start,start:group[0]?.startTime??null,end:group.at(-1)?.endTime??null,usable:valid,textComplete:complete,error:valid?group[0].startTime-cue.start:null};});\r\n const errors=rows.filter(r=>r.usable).map(r=>Math.abs(r.error));\r\n return {total:rows.length,matched:errors.length,withinOne:errors.filter(e=>e<=1+1e-9).length,max:errors.length?Math.max(...errors):null,mean:errors.length?errors.reduce((a,b)=>a+b)/errors.length:null,characterEditDistance:dp[n*width+m],rows};\r\n}\r\n", "import { scoreCues } from './core/cue-score.mjs';\r\nimport type { Cue, TimelineEntry } from './types.ts';\r\n\r\n/** Map supplied lyric lines without consulting any reference timestamps. */\r\nexport function timelineToCues(lyrics: string[], words: TimelineEntry[], audioSeconds: number): Cue[] {\r\n const rows = scoreCues({ timeline: words, audioSeconds }, lyrics.map(text => ({ text, start: 0 }))).rows;\r\n return rows.map((row: { line: number; text: string; start: number | null; end: number | null; usable: boolean }) => {\r\n const issues: string[] = [];\r\n if (!row.usable) issues.push('unmatched-text');\r\n if (row.start === null || row.end === null || !Number.isFinite(row.start) || !Number.isFinite(row.end)) issues.push('invalid-time');\r\n else {\r\n if (row.end === row.start) issues.push('zero-duration');\r\n if (row.end < row.start) issues.push('negative-duration');\r\n if (row.start < 0 || row.end > audioSeconds + 1e-8) issues.push('out-of-bounds');\r\n }\r\n return { id: row.line, text: row.text, start: row.start, end: row.end, matched: row.usable, issues };\r\n });\r\n}\r\nfunction timestamp(seconds: number): string {\r\n const total = Math.round(seconds * 1000);\r\n const pad = (n: number, width = 2) => String(n).padStart(width, '0');\r\n return `${pad(Math.floor(total / 3600000))}:${pad(Math.floor(total / 60000) % 60)}:${pad(Math.floor(total / 1000) % 60)},${pad(total % 1000, 3)}`;\r\n}\r\n/** Export valid intervals only; no guessed offsets or artificial duration padding. */\r\nexport function toSrt(cues: readonly Cue[]): string {\r\n return cues.filter(c => c.matched && c.issues.length === 0 && c.start !== null && c.end !== null && Number.isFinite(c.start) && Number.isFinite(c.end) && c.start >= 0 && Math.round(c.end * 1000) > Math.round(c.start * 1000))\r\n .map((c, i) => `${i + 1}\\n${timestamp(c.start!)} --> ${timestamp(c.end!)}\\n${c.text}\\n`).join('\\n');\r\n}\r\n", "export interface SourceCue { id: number; start: number; end: number; text: string }\r\nfunction parseTimestamp(value: string): number {\r\n const match = /^(\\d{2,}):(\\d{2}):(\\d{2})[,.](\\d{3})$/.exec(value);\r\n if (!match || Number(match[2]) > 59 || Number(match[3]) > 59) throw new TypeError(`Invalid SRT timestamp: ${value}`);\r\n const seconds = Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3]) + Number(match[4]) / 1000;\r\n if (!Number.isFinite(seconds)) throw new TypeError('SRT timestamp must be finite');\r\n return seconds;\r\n}\r\n/** Parse SRT; to align these lyrics, pass only .map(cue => cue.text) to align(). */\r\nexport function parseSrt(text: string): SourceCue[] {\r\n const normalized = text.replace(/^\\uFEFF/, '').replaceAll('\\r\\n', '\\n').trim();\r\n if (!normalized) return [];\r\n return normalized.split(/\\n\\s*\\n/).map(block => {\r\n const lines = block.split('\\n'), id = Number(lines.shift());\r\n const range = /^(\\S+)\\s+-->\\s+(\\S+)(?:\\s+.*)?$/.exec(lines.shift() ?? '');\r\n if (!Number.isInteger(id) || !range || !lines.length) throw new TypeError('Invalid SRT cue');\r\n const start = parseTimestamp(range[1]), end = parseTimestamp(range[2]);\r\n if (end <= start) throw new TypeError(`Invalid SRT range in cue ${id}`);\r\n return { id, start, end, text: lines.map(line => line.trim()).join(' ') };\r\n });\r\n}\r\n", "export const DEFAULT_MODEL_URL = 'https://huggingface.co/ggerganov/whisper.cpp/resolve/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny-q5_1.bin';\r\nexport const DEFAULT_MODEL_SHA256 = '818710568da3ca15689e31a743197b520007872ff9576237bda97bd1b469c3d7';\r\n", "import { DEFAULT_MODEL_URL, DEFAULT_MODEL_SHA256 } from './model.ts';\r\nimport type { Capabilities, ErrorCode, LyricAlignBinding, LyricAlignSession, OperationContext, Progress } from './contract.ts';\r\nexport type * from './contract.ts';\r\n\r\nexport interface BindingOptions {\r\n workerUrl?: string | URL;\r\n assetBaseUrl?: string | URL;\r\n /** Relocate the pinned model; its SHA256 is always verified. */\r\n modelUrl?: string | URL;\r\n threads?: 1 | 2 | 4 | 6 | 8 | 12;\r\n}\r\n\r\nexport function libraryError(code: ErrorCode, message: string): Error & { code: ErrorCode } {\r\n return Object.assign(new Error(message), { code });\r\n}\r\nconst codes: readonly string[] = ['UNSUPPORTED_LANGUAGE','UNSUPPORTED_DEVICE','UNSUPPORTED_OPTION','MODEL_LOAD_FAILED','INVALID_INPUT','OUT_OF_MEMORY','TRANSCRIPTION_FAILED','ALIGNMENT_FAILED','ABORTED'];\r\nfunction normalizeError(value: unknown, fallback: ErrorCode) {\r\n const error = value as { code?: string; message?: string } | null;\r\n const message = typeof error?.message === 'string' ? error.message : String(value);\r\n const code = codes.includes(error?.code ?? '') ? error!.code as ErrorCode\r\n : /out of memory|cannot allocate memory|allocation failed|memory access out of bounds/i.test(message) ? 'OUT_OF_MEMORY' : fallback;\r\n return libraryError(code, message);\r\n}\r\nconst capabilities: Capabilities = Object.freeze({\r\n contractVersion: 1, libraryVersion: '1.0.0',\r\n supportedLanguages: Object.freeze(['en', 'ja', 'zh']),\r\n model: Object.freeze({ id: 'ggerganov/whisper.cpp/ggml-tiny-q5_1.bin', revision: '5359861c739e955e79d9a303bcbc70fb988958b1', device: 'wasm' as const, dtype: 'q5_1' }),\r\n alignmentOptions: Object.freeze(['threshold', 'karaoke'] as const), lyricsContext: false,\r\n});\r\nfunction language(value: unknown, fallback: string): string {\r\n if (value === undefined) return fallback;\r\n if (typeof value !== 'string' || !capabilities.supportedLanguages.includes(value)) throw libraryError('UNSUPPORTED_LANGUAGE', `Unsupported language: ${String(value)}`);\r\n return value;\r\n}\r\nfunction optionsOnly(options: object, keys: readonly string[]) {\r\n if (!options || typeof options !== 'object' || Array.isArray(options)) throw libraryError('INVALID_INPUT', 'Options must be an object');\r\n for (const key of Object.keys(options)) if (!keys.includes(key)) throw libraryError('UNSUPPORTED_OPTION', `Unsupported option: ${key}`);\r\n}\r\n\r\n/** No model, Worker, fetch or device access occurs until prepare(). */\r\nexport function createBinding(options: BindingOptions = {}): LyricAlignBinding {\r\n optionsOnly(options, ['workerUrl', 'assetBaseUrl', 'modelUrl', 'threads']);\r\n const config = { ...options };\r\n if (![1,2,4,6,8,12].includes(config.threads ?? 8)) throw libraryError('UNSUPPORTED_OPTION', 'Unsupported thread count');\r\n return Object.freeze({ capabilities, async createSession(): Promise<LyricAlignSession> {\r\n let worker: Worker | undefined, disposed = false, ready = false, busy = false, preparedLanguage = 'en', requestId = 0;\r\n let active: { id: number; reject: (error: unknown) => void; resolve: (value: any) => void; progress: (data: any) => void; code: ErrorCode } | undefined;\r\n function stop(error = libraryError('ABORTED', 'Session disposed')) {\r\n disposed = true; ready = false;\r\n worker?.terminate(); worker = undefined;\r\n const current = active; active = undefined; current?.reject(error);\r\n }\r\n function request(message: Record<string, unknown>, code: ErrorCode, progress: (data: any) => void, transfer: Transferable[] = []) {\r\n return new Promise<any>((resolve, reject) => {\r\n const id = ++requestId;\r\n active = { id, resolve, reject, progress, code };\r\n try { worker!.postMessage({ ...message, id }, transfer); }\r\n catch (error) { active = undefined; reject(normalizeError(error, code)); }\r\n });\r\n }\r\n async function operation<T>(phase: Progress['phase'], context: OperationContext, work: (emit: (data?: any) => void) => Promise<T>): Promise<T> {\r\n if (!context?.signal || typeof context.signal.addEventListener !== 'function') throw libraryError('INVALID_INPUT', 'An AbortSignal is required');\r\n if (context.signal.aborted) throw libraryError('ABORTED', 'Operation aborted');\r\n if (disposed || busy) throw libraryError('INVALID_INPUT', disposed ? 'Session is disposed' : 'Session is busy');\r\n busy = true;\r\n let sequence = 0;\r\n const emit = (data?: any) => {\r\n if (disposed || context.signal.aborted) return;\r\n const base = { phase, sequence: ++sequence, ...(typeof data?.stage === 'string' ? { detail: data.stage } : {}) };\r\n // Only explicitly typed native measurements can be forwarded. Legacy\r\n // sample counters and untyped model totals are deliberately indeterminate.\r\n const measured = data?.kind === 'measured' && Number.isFinite(data.completed) && Number.isFinite(data.total)\r\n && data.total > 0 && data.completed >= 0 && data.completed <= data.total\r\n && ['bytes','seconds','items'].includes(data.unit) && typeof data.scope === 'string' && data.scope.length > 0;\r\n const event: Progress = measured ? { ...base, kind: 'measured', completed: data.completed, total: data.total, unit: data.unit, scope: data.scope } : { ...base, kind: 'indeterminate' };\r\n try { context.onProgress?.(event); } catch { /* Observers cannot break computation. */ }\r\n };\r\n const abort = () => stop(libraryError('ABORTED', 'Operation aborted'));\r\n context.signal.addEventListener('abort', abort, { once: true });\r\n try {\r\n emit();\r\n if (disposed || context.signal.aborted) throw libraryError('ABORTED', 'Operation aborted');\r\n const result = await work(emit);\r\n if (disposed || context.signal.aborted) throw libraryError('ABORTED', 'Operation aborted');\r\n return result;\r\n }\r\n catch (error) { throw normalizeError(error, phase === 'preparing-model' ? 'MODEL_LOAD_FAILED' : phase === 'transcribing' ? 'TRANSCRIPTION_FAILED' : 'ALIGNMENT_FAILED'); }\r\n finally { busy = false; context.signal.removeEventListener('abort', abort); }\r\n }\r\n return {\r\n prepare(opts, context) {\r\n return operation('preparing-model', context, async emit => {\r\n optionsOnly(opts, ['language']); const selected = language(opts.language, preparedLanguage);\r\n if (ready) { preparedLanguage = selected; return; }\r\n if (typeof Worker === 'undefined' || typeof WebAssembly === 'undefined' || typeof SharedArrayBuffer === 'undefined' || !globalThis.crossOriginIsolated || !globalThis.isSecureContext) throw libraryError('UNSUPPORTED_DEVICE', 'tiny/WASM requires a secure cross-origin-isolated browser with Worker and SharedArrayBuffer');\r\n try {\r\n worker = new Worker(new URL(String(config.workerUrl ?? './worker.js'), import.meta.url));\r\n worker.addEventListener('message', ({ data }) => {\r\n const current = active; if (!current || data?.id !== current.id) return;\r\n if (data.type === 'progress') current.progress(data);\r\n else if (data.type === 'result') { active = undefined; current.resolve(data.result); }\r\n else if (data.type === 'error') { active = undefined; current.reject(normalizeError(data.error, current.code)); }\r\n });\r\n const crash = (message: string) => stop(libraryError(active?.code ?? 'MODEL_LOAD_FAILED', message));\r\n worker.addEventListener('error', event => crash(event.message || 'Worker crashed'));\r\n worker.addEventListener('messageerror', () => crash('Could not deserialize Worker response'));\r\n const base = new URL(String(config.assetBaseUrl ?? './assets/'), import.meta.url); if (!base.pathname.endsWith('/')) base.pathname += '/';\r\n await request({ type: 'initialize', options: { modelUrl: String(config.modelUrl ?? DEFAULT_MODEL_URL), modelSha256: DEFAULT_MODEL_SHA256, assetBaseUrl: base.href, threads: config.threads ?? 8 } }, 'MODEL_LOAD_FAILED', emit);\r\n ready = true; preparedLanguage = selected;\r\n } catch (error) { const normalized = normalizeError(error, 'MODEL_LOAD_FAILED'); stop(normalized); throw normalized; }\r\n });\r\n },\r\n transcribe(audio, opts, context) {\r\n return operation('transcribing', context, async emit => {\r\n if (!ready) throw libraryError('INVALID_INPUT', 'Call prepare before transcribe');\r\n optionsOnly(opts, ['language']); const selected = language(opts.language, preparedLanguage);\r\n if (!audio || audio.sampleRate !== 16000 || !(audio.pcm instanceof Float32Array) || !audio.pcm.length) throw libraryError('INVALID_INPUT', 'Expected nonempty mono Float32Array PCM at 16000 Hz');\r\n for (const sample of audio.pcm) if (!Number.isFinite(sample)) throw libraryError('INVALID_INPUT', 'PCM samples must be finite');\r\n const copy = audio.pcm.slice();\r\n return request({ type: 'transcribe', audio: copy, language: selected }, 'TRANSCRIPTION_FAILED', emit, [copy.buffer]);\r\n });\r\n },\r\n align(segments, lyrics, opts, context) {\r\n return operation('aligning', context, async emit => {\r\n if (!ready) throw libraryError('INVALID_INPUT', 'Call prepare before align');\r\n optionsOnly(opts, ['threshold','karaoke']);\r\n if (opts.karaoke !== undefined && opts.karaoke !== false) throw libraryError('UNSUPPORTED_OPTION', 'Only karaoke=false is supported');\r\n if (opts.threshold !== undefined && (!Number.isFinite(opts.threshold) || opts.threshold < 0 || opts.threshold > 1)) throw libraryError('INVALID_INPUT', 'threshold must be between 0 and 1');\r\n return request({ type: 'align-segments', segments, lyrics, options: opts }, 'ALIGNMENT_FAILED', emit);\r\n });\r\n },\r\n async dispose() { stop(); },\r\n };\r\n } });\r\n}\r\nexport const binding = createBinding();\r\n", "import { prepareAudio } from './audio.ts';\r\nimport { timelineToCues, toSrt } from './cues.ts';\r\nimport type { Aligner, AlignerOptions, AlignmentMetrics, AlignmentResult, Progress, TimelineEntry } from './types.ts';\r\nexport { timelineToCues, toSrt } from './cues.ts';\r\nexport { parseSrt } from './subtitles.ts';\r\nexport type { SourceCue } from './subtitles.ts';\r\nexport type * from './types.ts';\r\n\r\nimport { DEFAULT_MODEL_URL, DEFAULT_MODEL_SHA256 } from './model.ts';\r\nexport { DEFAULT_MODEL_URL, DEFAULT_MODEL_SHA256 } from './model.ts';\r\nexport { binding, createBinding } from './binding.ts';\r\nexport type { BindingOptions } from './binding.ts';\r\nexport type { LyricAlignBinding, LyricAlignSession, Capabilities, OperationContext, PrepareOptions, TranscribeOptions, AlignOptions, Segment, Word, AlignedLine, ErrorCode, LibraryError, AudioInput as ContractAudioInput, Progress as ContractProgress } from './contract.ts';\r\ntype Pending = { resolve: (value: any) => void; reject: (error: Error) => void; progress?: (p: Progress) => void };\r\nconst abortError = () => new DOMException('Alignment was aborted; create a new aligner to continue', 'AbortError');\r\n\r\nexport async function createAligner(options: AlignerOptions = {}): Promise<Aligner> {\r\n const initializeStart = performance.now();\r\n if (typeof Worker === 'undefined' || typeof WebAssembly === 'undefined' || typeof SharedArrayBuffer === 'undefined') throw new Error('This runtime requires browser Worker, WebAssembly and SharedArrayBuffer');\r\n if (!globalThis.crossOriginIsolated) throw new Error('Cross-origin isolation required: serve COOP: same-origin and COEP: require-corp headers');\r\n if (!globalThis.isSecureContext) throw new Error('A secure context (HTTPS or localhost) is required');\r\n const threads = options.threads ?? 8;\r\n if (![1, 2, 4, 6, 8, 12].includes(threads)) throw new TypeError('threads must be 1, 2, 4, 6, 8 or 12');\r\n const modelSha256 = options.modelSha256 ?? DEFAULT_MODEL_SHA256;\r\n if (!/^[a-f0-9]{64}$/i.test(modelSha256)) throw new TypeError('modelSha256 must be a 64-character SHA256 hash');\r\n options.signal?.throwIfAborted();\r\n const assetBaseUrl = new URL(String(options.assetBaseUrl ?? './assets/'), import.meta.url);\r\n if (!assetBaseUrl.pathname.endsWith('/')) assetBaseUrl.pathname += '/';\r\n const worker = new Worker(new URL(String(options.workerUrl ?? './worker.js'), import.meta.url));\r\n const pending = new Map<number, Pending>();\r\n const lifetime = new AbortController();\r\n let sequence = 0, disposed = false, busy = false;\r\n const stop = (error = new Error('Aligner is disposed')) => {\r\n if (disposed) return;\r\n disposed = true;\r\n lifetime.abort(error);\r\n worker.terminate();\r\n for (const request of pending.values()) request.reject(error);\r\n pending.clear();\r\n };\r\n worker.addEventListener('message', ({ data }) => {\r\n const request = pending.get(data?.id);\r\n if (!request) return;\r\n if (data.type === 'progress') {\r\n try { request.progress?.({ stage: data.stage, completed: data.completed, total: data.total }); } catch { /* Observer failures cannot corrupt inference. */ }\r\n } else if (data.type === 'result') { pending.delete(data.id); request.resolve(data.result); }\r\n else if (data.type === 'error') { pending.delete(data.id); const error = new Error(data.error?.message ?? 'Worker failed'); error.name = data.error?.name ?? 'Error'; request.reject(error); }\r\n });\r\n worker.addEventListener('error', event => stop(new Error(event.message || 'Alignment Worker failed')));\r\n worker.addEventListener('messageerror', () => stop(new Error('Could not deserialize Worker response')));\r\n const request = <T>(message: Record<string, unknown>, progress?: (p: Progress) => void, transfer: Transferable[] = []) => new Promise<T>((resolve, reject) => {\r\n if (disposed) { reject(new Error('Aligner is disposed')); return; }\r\n const id = ++sequence;\r\n pending.set(id, { resolve, reject, progress });\r\n try { worker.postMessage({ ...message, id }, transfer); } catch (error) { pending.delete(id); reject(error); }\r\n });\r\n const initializeAbort = () => stop(abortError());\r\n options.signal?.addEventListener('abort', initializeAbort, { once: true });\r\n try {\r\n await request({ type: 'initialize', options: { modelUrl: String(options.modelUrl ?? DEFAULT_MODEL_URL), modelSha256: modelSha256.toLowerCase(), assetBaseUrl: assetBaseUrl.href, threads } }, options.onProgress);\r\n } catch (error) { stop(); throw error; }\r\n finally { options.signal?.removeEventListener('abort', initializeAbort); }\r\n const initializationSeconds = (performance.now() - initializeStart) / 1000;\r\n return {\r\n async align(input): Promise<AlignmentResult> {\r\n if (disposed) throw new Error('Aligner is disposed');\r\n if (busy) throw new Error('An alignment is already in progress (instance is busy)');\r\n input.signal?.throwIfAborted();\r\n const lines = (typeof input.lyrics === 'string' ? input.lyrics.split(/\\r?\\n/) : input.lyrics).map(line => line.trim()).filter(Boolean);\r\n if (!lines.length || !lines.some(line => /[\\p{L}\\p{N}]/u.test(line))) throw new TypeError('lyrics must include spoken text');\r\n if (typeof input.language !== 'string' || !/^[a-z]{2,3}$/.test(input.language)) throw new TypeError('language must be an explicit ISO language code, e.g. en or ja');\r\n busy = true;\r\n const operationStart = performance.now();\r\n const onAbort = () => stop(abortError());\r\n input.signal?.addEventListener('abort', onAbort, { once: true });\r\n try {\r\n const samples = await prepareAudio(input.audio, lifetime.signal);\r\n const audioPreparationSeconds = (performance.now() - operationStart) / 1000;\r\n if (disposed || input.signal?.aborted) throw abortError();\r\n const audioSeconds = samples.length / 16000;\r\n const result = await request<{ words: TimelineEntry[]; metrics: AlignmentMetrics }>({ type: 'align', audio: samples, lyrics: lines.join('\\n'), language: input.language }, input.onProgress, [samples.buffer]);\r\n const cueStart = performance.now();\r\n const cues = timelineToCues(lines, result.words, audioSeconds);\r\n const srt = toSrt(cues);\r\n const cueMappingSeconds = (performance.now() - cueStart) / 1000;\r\n const operationSeconds = (performance.now() - operationStart) / 1000;\r\n return { ...result, cues, srt, audioSeconds, metrics: { ...result.metrics, engineTotalSeconds: result.metrics.totalSeconds, initializationSeconds, audioPreparationSeconds, cueMappingSeconds, operationSeconds, totalSeconds: initializationSeconds + operationSeconds } };\r\n } finally { busy = false; input.signal?.removeEventListener('abort', onAbort); }\r\n },\r\n dispose() { stop(); },\r\n };\r\n}\r\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["i", "j", "request"]
|
|
3
|
+
"sources": ["../src/audio.ts", "../src/core/score.mjs", "../src/core/cue-score.mjs", "../src/core/timeline-cues.mjs", "../src/cues.ts", "../src/core/refine.mjs", "../src/subtitles.ts", "../src/model.ts", "../src/binding.ts", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AudioInput } from './types.ts';\n\nasync function abortable<T>(operation: Promise<T>, signal?: AbortSignal): Promise<T> {\n if (!signal) return operation;\n signal.throwIfAborted();\n return new Promise<T>((resolve, reject) => {\n const abort = () => { cleanup(); reject(signal.reason); };\n const cleanup = () => signal.removeEventListener('abort', abort);\n signal.addEventListener('abort', abort, { once: true });\n operation.then(value => { cleanup(); resolve(value); }, error => { cleanup(); reject(error); });\n });\n}\n\nfunction validate(samples: Float32Array): Float32Array {\n if (!samples.length) throw new TypeError('Audio must contain at least one sample');\n for (const sample of samples) if (!Number.isFinite(sample)) throw new TypeError('Audio samples must be finite');\n return samples.slice();\n}\nasync function fromBuffer(buffer: AudioBuffer, signal?: AbortSignal): Promise<Float32Array> {\n if (!buffer.numberOfChannels || !buffer.length) throw new TypeError('Audio must not be empty');\n const mono = new Float32Array(buffer.length);\n for (let ch = 0; ch < buffer.numberOfChannels; ch++) {\n const samples = buffer.getChannelData(ch);\n for (let i = 0; i < mono.length; i++) mono[i] += samples[i] / buffer.numberOfChannels;\n }\n if (buffer.sampleRate === 16000) return validate(mono);\n if (typeof OfflineAudioContext === 'undefined') throw new Error('Resampling requires Web Audio OfflineAudioContext');\n const context = new OfflineAudioContext(1, Math.ceil(buffer.length * 16000 / buffer.sampleRate), 16000);\n const source = context.createBufferSource();\n const input = context.createBuffer(1, mono.length, buffer.sampleRate);\n input.copyToChannel(mono, 0);\n source.buffer = input;\n source.connect(context.destination);\n source.start();\n const rendered = await abortable(context.startRendering(), signal);\n return validate(rendered.getChannelData(0));\n}\nfunction pcmWav16000(bytes: ArrayBuffer): Float32Array | undefined {\n if(bytes.byteLength<12)return;\n const v=new DataView(bytes),tag=(at:number,s:string)=>[...s].every((c,i)=>v.getUint8(at+i)===c.charCodeAt(0));\n if(!tag(0,'RIFF')||!tag(8,'WAVE'))return;\n const end=v.getUint32(4,true)+8;if(end>bytes.byteLength||end<12)return;\n let format=false,data=-1,length=0;\n for(let at=12;at<end;){\n if(at+8>end)return;\n const size=v.getUint32(at+4,true),start=at+8,next=start+size+(size%2);\n if(next>end)return;\n if(tag(at,'fmt ')){\n if(size<16)return;\n format=v.getUint16(start,true)===1&&v.getUint16(start+2,true)===1&&v.getUint32(start+4,true)===16000&&v.getUint32(start+8,true)===32000&&v.getUint16(start+12,true)===2&&v.getUint16(start+14,true)===16;\n if(!format)return;\n }else if(tag(at,'data')){if(data>=0)return;data=start;length=size;}\n at=next;\n }\n if(!format||data<0||!length||length%2)return;\n const pcm=new Float32Array(length/2);\n // Match the browser's asymmetric signed-PCM normalization, including both full-scale endpoints.\n const positiveScale=Math.fround(1/32767);\n for(let i=0;i<pcm.length;i++){const sample=v.getInt16(data+i*2,true);pcm[i]=sample*(sample<0?1/32768:positiveScale);}\n return pcm;\n}\n/** Known PCM WAV is decoded directly; other files use browser codecs. Caller PCM is copied. */\nexport async function prepareAudio(audio: AudioInput, signal?: AbortSignal): Promise<Float32Array> {\n signal?.throwIfAborted();\n if (audio && typeof audio === 'object' && 'samples' in audio) {\n if (!(audio.samples instanceof Float32Array) || audio.sampleRate !== 16000) throw new TypeError('PCM requires Float32Array samples at sampleRate: 16000');\n return validate(audio.samples);\n }\n if (audio && typeof audio === 'object' && 'getChannelData' in audio) return fromBuffer(audio as AudioBuffer, signal);\n if (typeof Blob !== 'undefined' && audio instanceof Blob) {\n const bytes = await abortable(audio.arrayBuffer(), signal);\n signal?.throwIfAborted();\n const pcm=pcmWav16000(bytes);if(pcm)return pcm;\n if (typeof AudioContext === 'undefined') throw new Error('Decoding files requires Web Audio AudioContext');\n const context = new AudioContext({ sampleRate: 16000 });\n let closing: Promise<void> | undefined;\n const close = () => closing ??= context.close().catch(() => {});\n const abort = () => { void close(); };\n signal?.addEventListener('abort', abort, { once: true });\n try {\n const buffer = await abortable(context.decodeAudioData(bytes), signal);\n return await fromBuffer(buffer, signal);\n } finally { signal?.removeEventListener('abort', abort); await close(); }\n }\n throw new TypeError('audio must be a File/Blob, AudioBuffer, or 16000 Hz PCM input');\n}\n", "// Shared text normalization for monotonic lyric matching and evaluation.\nexport const normalize=text=>text.normalize('NFKC').toLowerCase().replace(/[^\\p{L}\\p{N}]/gu,'');\n", "import {normalize} from './score.mjs';\nconst hasMissingText=w=>w.confidence===0||(w.timeline??[]).some(hasMissingText);\n// Sentence acceptance evaluates the public cues/SRT source, not uncorrected\n// token-level diagnostics. Unmatched public cues remain unmatched in scoring.\nexport function scorePublicCues(result,reference){\n return scoreCues({audioSeconds:result.audioSeconds,timeline:result.cues.map(c=>({text:c.text,startTime:c.start,endTime:c.end,confidence:c.matched?1:0}))},reference);\n}\n// Monotonic character alignment handles omitted text without shifting every later cue.\n// Reference timestamps never participate in matching.\nexport function scoreCues(run,reference){\n const expected=Array.from(reference.map(x=>normalize(x.text)).join(''));\n const actual=[],owners=[];\n run.timeline.forEach((w,index)=>{for(const c of normalize(w.text)){actual.push(c);owners.push(index);}});\n const n=expected.length,m=actual.length,width=m+1;\n const mapping=new Int32Array(n).fill(-1);let distance=0;\n if(n===m&&expected.every((c,i)=>c===actual[i])){\n // Exact normalized equality has one zero-edit monotonic mapping. Avoid the\n // quadratic matrix without changing the fallback's tie-breaking behavior.\n for(let i=0;i<n;i++)mapping[i]=i;\n }else{\n const dp=new Uint32Array((n+1)*width);\n for(let i=0;i<=n;i++)dp[i*width]=i;for(let j=0;j<=m;j++)dp[j]=j;\n for(let i=1;i<=n;i++)for(let j=1;j<=m;j++)dp[i*width+j]=Math.min(dp[(i-1)*width+j]+1,dp[i*width+j-1]+1,dp[(i-1)*width+j-1]+(expected[i-1]===actual[j-1]?0:1));\n let i=n,j=m;\n while(i||j){const cost=dp[i*width+j];if(i&&j&&cost===dp[(i-1)*width+j-1]+(expected[i-1]===actual[j-1]?0:1)){if(expected[i-1]===actual[j-1])mapping[i-1]=j-1;i--;j--;}else if(i&&cost===dp[(i-1)*width+j]+1)i--;else j--;}\n distance=dp[n*width+m];\n }\n let offset=0;\n const rows=reference.map((cue,index)=>{const a=offset;offset+=Array.from(normalize(cue.text)).length;const indices=Array.from(mapping.slice(a,offset));\n const complete=indices.length>0&&indices.every((v,k)=>v>=0&&(!k||v===indices[k-1]+1));\n const wordIds=[...new Set(indices.filter(x=>x>=0).map(x=>owners[x]))];const group=wordIds.map(x=>run.timeline[x]);\n const valid=complete&&group.every(w=>!hasMissingText(w)&&Number.isFinite(w.startTime)&&w.startTime>=0&&w.startTime<=run.audioSeconds)&&group.every((w,k)=>!k||w.startTime>=group[k-1].startTime);\n return {line:index+1,text:cue.text,referenceStart:cue.start,start:group[0]?.startTime??null,end:group.at(-1)?.endTime??null,usable:valid,textComplete:complete,error:valid?group[0].startTime-cue.start:null};});\n const errors=rows.filter(r=>r.usable).map(r=>Math.abs(r.error));\n return {total:rows.length,matched:errors.length,withinOne:errors.filter(e=>e<=1+1e-9).length,max:errors.length?Math.max(...errors):null,mean:errors.length?errors.reduce((a,b)=>a+b)/errors.length:null,characterEditDistance:distance,rows};\n}\n", "import {scoreCues} from './cue-score.mjs';\n// Shared by the public API and optional worker-side boundary estimation.\nexport function mapTimelineToCues(lyrics,words,audioSeconds){\n const rows=scoreCues({timeline:words,audioSeconds},lyrics.map(text=>({text,start:0}))).rows;\n return rows.map(row=>{\n const issues=[];\n if(!row.usable)issues.push('unmatched-text');\n if(row.start===null||row.end===null||!Number.isFinite(row.start)||!Number.isFinite(row.end))issues.push('invalid-time');\n else{\n if(row.end===row.start)issues.push('zero-duration');\n if(row.end<row.start)issues.push('negative-duration');\n if(row.start<0||row.end>audioSeconds+1e-8)issues.push('out-of-bounds');\n }\n return {id:row.line,text:row.text,start:row.start,end:row.end,matched:row.usable,issues};\n });\n}\n", "import { mapTimelineToCues } from './core/timeline-cues.mjs';\nimport type { Cue, TimelineEntry } from './types.ts';\n\n/** Map supplied lyric lines without consulting any reference timestamps. */\nexport function timelineToCues(lyrics: string[], words: TimelineEntry[], audioSeconds: number): Cue[] {\n return mapTimelineToCues(lyrics, words, audioSeconds);\n}\nfunction timestamp(seconds: number): string {\n const total = Math.round(seconds * 1000);\n const pad = (n: number, width = 2) => String(n).padStart(width, '0');\n return `${pad(Math.floor(total / 3600000))}:${pad(Math.floor(total / 60000) % 60)}:${pad(Math.floor(total / 1000) % 60)},${pad(total % 1000, 3)}`;\n}\n/** Export valid intervals only; no guessed offsets or artificial duration padding. */\nexport function toSrt(cues: readonly Cue[]): string {\n return cues.filter(c => c.matched && c.issues.length === 0 && c.start !== null && c.end !== null && Number.isFinite(c.start) && Number.isFinite(c.end) && c.start >= 0 && Math.round(c.end * 1000) > Math.round(c.start * 1000))\n .map((c, i) => `${i + 1}\\n${timestamp(c.start!)} --> ${timestamp(c.end!)}\\n${c.text}\\n`).join('\\n');\n}\n", "import {mapTimelineToCues as timelineToCues} from './timeline-cues.mjs';\n// Constants come from the cross-validated simulation on 17 Japanese songs plus\n// the held-out \u6625\u6CE5\u68D2 and SUNEO-ISM (strict feature detector, one-line expansion).\nexport const REFINE={meanTokenSeconds:.1,longestTokenSeconds:3,rateDeviation:1,maxFlaggedFraction:.25,runGap:1,maxExpansion:1,anchorTolerance:.5,clipMargin:.3,minClipSeconds:1};\nconst valid=cue=>cue.matched&&Number.isFinite(cue.start)&&Number.isFinite(cue.end);\nconst tokensOf=words=>words.flatMap(w=>w.timeline?.length?w.timeline:[w]).sort((a,b)=>a.startTime-b.startTime);\nconst median=values=>{const s=[...values].sort((x,y)=>x-y);return s[s.length>>1]};\n// A burst of shifted lines shows up as squeezed or stretched lines: tokens\n// stuck at the minimum step, one token held for seconds, or a speaking rate far\n// from the song's own median. Reference timestamps are never consulted.\nexport function suspectLines(cues,words){\n const tokens=tokensOf(words),rate=cue=>(cue.end-cue.start)/Math.max(1,Array.from(cue.text.replace(/\\s/g,'')).length);\n const typical=median(cues.filter(valid).map(rate));\n return cues.map(cue=>{\n if(!valid(cue))return false;\n const durations=tokens.filter(t=>t.startTime>=cue.start-1e-6&&t.startTime<cue.end-1e-6).map(t=>t.endTime-t.startTime);\n const mean=durations.length?durations.reduce((a,b)=>a+b,0)/durations.length:0,longest=durations.length?Math.max(...durations):0;\n return mean<REFINE.meanTokenSeconds||longest>REFINE.longestTokenSeconds||Math.abs(Math.log(rate(cue)/typical))>REFINE.rateDeviation;\n });\n}\n// Merge flagged lines separated by at most one unflagged line.\nexport function suspectRuns(flags){\n const runs=[],n=flags.length;let i=0;\n while(i<n){\n if(!flags[i]){i++;continue}\n let j=i;\n while(j+REFINE.runGap<n&&(flags[j+1]||flags[j+2]))j=flags[j+1]?j+1:j+2;\n runs.push([i,j]);i=j+1;\n }\n return runs;\n}\nconst matchedCount=cues=>cues.filter(valid).length;\n/**\n * Re-aligns each suspect run between the two lines on either side of it. A\n * result replaces the run only if both neighbours land where they already were.\n * `alignClip(start,end,lines)` returns a timeline relative to the clip, or\n * undefined when the clip could not be aligned.\n */\nexport async function refineTimeline({lines,words,audioSeconds,alignClip,onStep}){\n let current=words,cues=timelineToCues(lines,words,audioSeconds);\n const flags=suspectLines(cues,words),flagged=flags.filter(Boolean).length;\n const summary={flaggedLines:flagged,attempts:0,refinedLines:0};\n if(!flagged||flagged>cues.length*REFINE.maxFlaggedFraction)return{words,cues,...summary};\n const runs=suspectRuns(flags);let step=0;\n for(const [first,last] of runs){\n onStep?.(step++,runs.length);\n for(let expand=0;expand<=REFINE.maxExpansion;expand++){\n const a=Math.max(0,first-expand),b=Math.min(cues.length-1,last+expand),left=a>0,right=b+1<cues.length;\n const fi=left?a-1:0,lj=right?b+1:cues.length-1;\n if((left&&!valid(cues[fi]))||(right&&!valid(cues[lj])))continue;\n const from=left?Math.max(0,cues[fi].start-REFINE.clipMargin):0,to=right?Math.min(audioSeconds,cues[lj].end+REFINE.clipMargin):audioSeconds;\n if(to-from<REFINE.minClipSeconds)continue;\n const clipLines=lines.slice(left?fi:a,right?lj+1:b+1);\n summary.attempts++;\n const clip=await alignClip(from,to,clipLines);\n if(!clip)continue;\n const found=timelineToCues(clipLines,clip,to-from),lead=left?1:0,inner=found.slice(lead,lead+(b-a+1));\n if(left&&(!valid(found[0])||Math.abs(found[0].start+from-cues[fi].start)>REFINE.anchorTolerance))continue;\n if(right&&(!valid(found.at(-1))||Math.abs(found.at(-1).end+from-cues[lj].end)>REFINE.anchorTolerance))continue;\n if(!inner.every(valid))continue;\n const oldFrom=left?cues[fi].end:0,oldTo=right?cues[lj].start:audioSeconds,newFrom=left?found[0].end:0,newTo=right?found.at(-1).start:to-from;\n const merged=[...current.filter(w=>w.startTime<oldFrom-1e-6||w.startTime>=oldTo-1e-6),...shift(clip.filter(w=>w.startTime>=newFrom-1e-6&&w.startTime<newTo-1e-6),from)].sort((x,y)=>x.startTime-y.startTime);\n const remapped=timelineToCues(lines,merged,audioSeconds);\n if(matchedCount(remapped)<matchedCount(cues))continue;\n current=merged;cues=remapped;summary.refinedLines+=b-a+1;break;\n }\n }\n return{words:current,cues,...summary};\n}\nfunction shift(entries,seconds){\n return entries.map(entry=>({...entry,startTime:entry.startTime+seconds,endTime:entry.endTime+seconds,...(entry.timeline?{timeline:shift(entry.timeline,seconds)}:{})}));\n}\n", "export interface SourceCue { id: number; start: number; end: number; text: string }\nfunction parseTimestamp(value: string): number {\n const match = /^(\\d{2,}):(\\d{2}):(\\d{2})[,.](\\d{3})$/.exec(value);\n if (!match || Number(match[2]) > 59 || Number(match[3]) > 59) throw new TypeError(`Invalid SRT timestamp: ${value}`);\n const seconds = Number(match[1]) * 3600 + Number(match[2]) * 60 + Number(match[3]) + Number(match[4]) / 1000;\n if (!Number.isFinite(seconds)) throw new TypeError('SRT timestamp must be finite');\n return seconds;\n}\n/** Parse SRT; to align these lyrics, pass only .map(cue => cue.text) to align(). */\nexport function parseSrt(text: string): SourceCue[] {\n const normalized = text.replace(/^\\uFEFF/, '').replaceAll('\\r\\n', '\\n').trim();\n if (!normalized) return [];\n return normalized.split(/\\n\\s*\\n/).map(block => {\n const lines = block.split('\\n'), id = Number(lines.shift());\n const range = /^(\\S+)\\s+-->\\s+(\\S+)(?:\\s+.*)?$/.exec(lines.shift() ?? '');\n if (!Number.isInteger(id) || !range || !lines.length) throw new TypeError('Invalid SRT cue');\n const start = parseTimestamp(range[1]), end = parseTimestamp(range[2]);\n if (end <= start) throw new TypeError(`Invalid SRT range in cue ${id}`);\n return { id, start, end, text: lines.map(line => line.trim()).join(' ') };\n });\n}\n", "export const DEFAULT_MODEL_URL = 'https://huggingface.co/ggerganov/whisper.cpp/resolve/5359861c739e955e79d9a303bcbc70fb988958b1/ggml-tiny-q5_1.bin';\nexport const DEFAULT_MODEL_SHA256 = '818710568da3ca15689e31a743197b520007872ff9576237bda97bd1b469c3d7';\n", "import { DEFAULT_MODEL_URL, DEFAULT_MODEL_SHA256 } from './model.ts';\nimport type { Capabilities, ErrorCode, LyricAlignBinding, LyricAlignSession, OperationContext, Progress } from './contract.ts';\nexport type * from './contract.ts';\n\nexport interface BindingOptions {\n workerUrl?: string | URL;\n assetBaseUrl?: string | URL;\n /** Relocate the pinned model; its SHA256 is always verified. */\n modelUrl?: string | URL;\n threads?: 1 | 2 | 4 | 6 | 8 | 12;\n}\n\nexport function libraryError(code: ErrorCode, message: string): Error & { code: ErrorCode } {\n return Object.assign(new Error(message), { code });\n}\nconst codes: readonly string[] = ['UNSUPPORTED_LANGUAGE','UNSUPPORTED_DEVICE','UNSUPPORTED_OPTION','MODEL_LOAD_FAILED','INVALID_INPUT','OUT_OF_MEMORY','TRANSCRIPTION_FAILED','ALIGNMENT_FAILED','ABORTED'];\nfunction normalizeError(value: unknown, fallback: ErrorCode) {\n const error = value as { code?: string; message?: string } | null;\n const message = typeof error?.message === 'string' ? error.message : String(value);\n const code = codes.includes(error?.code ?? '') ? error!.code as ErrorCode\n : /out of memory|cannot allocate memory|allocation failed|memory access out of bounds/i.test(message) ? 'OUT_OF_MEMORY' : fallback;\n return libraryError(code, message);\n}\nconst capabilities: Capabilities = Object.freeze({\n contractVersion: 1, libraryVersion: '1.0.2',\n supportedLanguages: Object.freeze(['en', 'ja', 'zh']),\n model: Object.freeze({ id: 'ggerganov/whisper.cpp/ggml-tiny-q5_1.bin', revision: '5359861c739e955e79d9a303bcbc70fb988958b1', device: 'wasm' as const, dtype: 'q5_1' }),\n alignmentOptions: Object.freeze(['threshold', 'karaoke'] as const), lyricsContext: false,\n});\nfunction language(value: unknown, fallback: string): string {\n if (value === undefined) return fallback;\n if (typeof value !== 'string' || !capabilities.supportedLanguages.includes(value)) throw libraryError('UNSUPPORTED_LANGUAGE', `Unsupported language: ${String(value)}`);\n return value;\n}\nfunction optionsOnly(options: object, keys: readonly string[]) {\n if (!options || typeof options !== 'object' || Array.isArray(options)) throw libraryError('INVALID_INPUT', 'Options must be an object');\n for (const key of Object.keys(options)) if (!keys.includes(key)) throw libraryError('UNSUPPORTED_OPTION', `Unsupported option: ${key}`);\n}\n\n/** No model, Worker, fetch or device access occurs until prepare(). */\nexport function createBinding(options: BindingOptions = {}): LyricAlignBinding {\n optionsOnly(options, ['workerUrl', 'assetBaseUrl', 'modelUrl', 'threads']);\n const config = { ...options };\n if (![1,2,4,6,8,12].includes(config.threads ?? 8)) throw libraryError('UNSUPPORTED_OPTION', 'Unsupported thread count');\n return Object.freeze({ capabilities, async createSession(): Promise<LyricAlignSession> {\n let worker: Worker | undefined, disposed = false, ready = false, busy = false, preparedLanguage = 'en', requestId = 0;\n let active: { id: number; reject: (error: unknown) => void; resolve: (value: any) => void; progress: (data: any) => void; code: ErrorCode } | undefined;\n function stop(error = libraryError('ABORTED', 'Session disposed')) {\n disposed = true; ready = false;\n worker?.terminate(); worker = undefined;\n const current = active; active = undefined; current?.reject(error);\n }\n function request(message: Record<string, unknown>, code: ErrorCode, progress: (data: any) => void, transfer: Transferable[] = []) {\n return new Promise<any>((resolve, reject) => {\n const id = ++requestId;\n active = { id, resolve, reject, progress, code };\n try { worker!.postMessage({ ...message, id }, transfer); }\n catch (error) { active = undefined; reject(normalizeError(error, code)); }\n });\n }\n async function operation<T>(phase: Progress['phase'], context: OperationContext, work: (emit: (data?: any) => void) => Promise<T>): Promise<T> {\n if (!context?.signal || typeof context.signal.addEventListener !== 'function') throw libraryError('INVALID_INPUT', 'An AbortSignal is required');\n if (context.signal.aborted) throw libraryError('ABORTED', 'Operation aborted');\n if (disposed || busy) throw libraryError('INVALID_INPUT', disposed ? 'Session is disposed' : 'Session is busy');\n busy = true;\n let sequence = 0;\n const emit = (data?: any) => {\n if (disposed || context.signal.aborted) return;\n const base = { phase, sequence: ++sequence, ...(typeof data?.stage === 'string' ? { detail: data.stage } : {}) };\n // Only explicitly typed native measurements can be forwarded. Legacy\n // sample counters and untyped model totals are deliberately indeterminate.\n const measured = data?.kind === 'measured' && Number.isFinite(data.completed) && Number.isFinite(data.total)\n && data.total > 0 && data.completed >= 0 && data.completed <= data.total\n && ['bytes','seconds','items'].includes(data.unit) && typeof data.scope === 'string' && data.scope.length > 0;\n const event: Progress = measured ? { ...base, kind: 'measured', completed: data.completed, total: data.total, unit: data.unit, scope: data.scope } : { ...base, kind: 'indeterminate' };\n try { context.onProgress?.(event); } catch { /* Observers cannot break computation. */ }\n };\n const abort = () => stop(libraryError('ABORTED', 'Operation aborted'));\n context.signal.addEventListener('abort', abort, { once: true });\n try {\n emit();\n if (disposed || context.signal.aborted) throw libraryError('ABORTED', 'Operation aborted');\n const result = await work(emit);\n if (disposed || context.signal.aborted) throw libraryError('ABORTED', 'Operation aborted');\n return result;\n }\n catch (error) { throw normalizeError(error, phase === 'preparing-model' ? 'MODEL_LOAD_FAILED' : phase === 'transcribing' ? 'TRANSCRIPTION_FAILED' : 'ALIGNMENT_FAILED'); }\n finally { busy = false; context.signal.removeEventListener('abort', abort); }\n }\n return {\n prepare(opts, context) {\n return operation('preparing-model', context, async emit => {\n optionsOnly(opts, ['language']); const selected = language(opts.language, preparedLanguage);\n if (ready) { preparedLanguage = selected; return; }\n if (typeof Worker === 'undefined' || typeof WebAssembly === 'undefined' || typeof SharedArrayBuffer === 'undefined' || !globalThis.crossOriginIsolated || !globalThis.isSecureContext) throw libraryError('UNSUPPORTED_DEVICE', 'tiny/WASM requires a secure cross-origin-isolated browser with Worker and SharedArrayBuffer');\n try {\n worker = new Worker(new URL(String(config.workerUrl ?? './worker.js'), import.meta.url));\n worker.addEventListener('message', ({ data }) => {\n const current = active; if (!current || data?.id !== current.id) return;\n if (data.type === 'progress') current.progress(data);\n else if (data.type === 'result') { active = undefined; current.resolve(data.result); }\n else if (data.type === 'error') { active = undefined; current.reject(normalizeError(data.error, current.code)); }\n });\n const crash = (message: string) => stop(libraryError(active?.code ?? 'MODEL_LOAD_FAILED', message));\n worker.addEventListener('error', event => crash(event.message || 'Worker crashed'));\n worker.addEventListener('messageerror', () => crash('Could not deserialize Worker response'));\n const base = new URL(String(config.assetBaseUrl ?? './assets/'), import.meta.url); if (!base.pathname.endsWith('/')) base.pathname += '/';\n await request({ type: 'initialize', options: { modelUrl: String(config.modelUrl ?? DEFAULT_MODEL_URL), modelSha256: DEFAULT_MODEL_SHA256, assetBaseUrl: base.href, threads: config.threads ?? 8 } }, 'MODEL_LOAD_FAILED', emit);\n ready = true; preparedLanguage = selected;\n } catch (error) { const normalized = normalizeError(error, 'MODEL_LOAD_FAILED'); stop(normalized); throw normalized; }\n });\n },\n transcribe(audio, opts, context) {\n return operation('transcribing', context, async emit => {\n if (!ready) throw libraryError('INVALID_INPUT', 'Call prepare before transcribe');\n optionsOnly(opts, ['language']); const selected = language(opts.language, preparedLanguage);\n if (!audio || audio.sampleRate !== 16000 || !(audio.pcm instanceof Float32Array) || !audio.pcm.length) throw libraryError('INVALID_INPUT', 'Expected nonempty mono Float32Array PCM at 16000 Hz');\n for (const sample of audio.pcm) if (!Number.isFinite(sample)) throw libraryError('INVALID_INPUT', 'PCM samples must be finite');\n const copy = audio.pcm.slice();\n return request({ type: 'transcribe', audio: copy, language: selected }, 'TRANSCRIPTION_FAILED', emit, [copy.buffer]);\n });\n },\n align(segments, lyrics, opts, context) {\n return operation('aligning', context, async emit => {\n if (!ready) throw libraryError('INVALID_INPUT', 'Call prepare before align');\n optionsOnly(opts, ['threshold','karaoke']);\n if (opts.karaoke !== undefined && opts.karaoke !== false) throw libraryError('UNSUPPORTED_OPTION', 'Only karaoke=false is supported');\n if (opts.threshold !== undefined && (!Number.isFinite(opts.threshold) || opts.threshold < 0 || opts.threshold > 1)) throw libraryError('INVALID_INPUT', 'threshold must be between 0 and 1');\n return request({ type: 'align-segments', segments, lyrics, options: opts }, 'ALIGNMENT_FAILED', emit);\n });\n },\n async dispose() { stop(); },\n };\n } });\n}\nexport const binding = createBinding();\n", "import { prepareAudio } from './audio.ts';\nimport { timelineToCues, toSrt } from './cues.ts';\nimport { refineTimeline } from './core/refine.mjs';\nimport type { Aligner, AlignerOptions, AlignmentMetrics, AlignmentResult, Progress, TimelineEntry, Cue } from './types.ts';\nexport { timelineToCues, toSrt } from './cues.ts';\nexport { parseSrt } from './subtitles.ts';\nexport type { SourceCue } from './subtitles.ts';\nexport type * from './types.ts';\n\nimport { DEFAULT_MODEL_URL, DEFAULT_MODEL_SHA256 } from './model.ts';\nexport { DEFAULT_MODEL_URL, DEFAULT_MODEL_SHA256 } from './model.ts';\nexport { binding, createBinding } from './binding.ts';\nexport type { BindingOptions } from './binding.ts';\nexport type { LyricAlignBinding, LyricAlignSession, Capabilities, OperationContext, PrepareOptions, TranscribeOptions, AlignOptions, Segment, Word, AlignedLine, ErrorCode, LibraryError, AudioInput as ContractAudioInput, Progress as ContractProgress } from './contract.ts';\ntype Pending = { resolve: (value: any) => void; reject: (error: Error) => void; progress?: (p: Progress) => void };\nconst abortError = () => new DOMException('Alignment was aborted; create a new aligner to continue', 'AbortError');\n\nexport async function createAligner(options: AlignerOptions = {}): Promise<Aligner> {\n const initializeStart = performance.now();\n if (typeof Worker === 'undefined' || typeof WebAssembly === 'undefined' || typeof SharedArrayBuffer === 'undefined') throw new Error('This runtime requires browser Worker, WebAssembly and SharedArrayBuffer');\n if (!globalThis.crossOriginIsolated) throw new Error('Cross-origin isolation required: serve COOP: same-origin and COEP: require-corp headers');\n if (!globalThis.isSecureContext) throw new Error('A secure context (HTTPS or localhost) is required');\n const threads = options.threads ?? 8;\n if (![1, 2, 4, 6, 8, 12].includes(threads)) throw new TypeError('threads must be 1, 2, 4, 6, 8 or 12');\n const modelSha256 = options.modelSha256 ?? DEFAULT_MODEL_SHA256;\n if (!/^[a-f0-9]{64}$/i.test(modelSha256)) throw new TypeError('modelSha256 must be a 64-character SHA256 hash');\n options.signal?.throwIfAborted();\n const assetBaseUrl = new URL(String(options.assetBaseUrl ?? './assets/'), import.meta.url);\n if (!assetBaseUrl.pathname.endsWith('/')) assetBaseUrl.pathname += '/';\n const worker = new Worker(new URL(String(options.workerUrl ?? './worker.js'), import.meta.url));\n const pending = new Map<number, Pending>();\n const lifetime = new AbortController();\n let sequence = 0, disposed = false, busy = false;\n const stop = (error = new Error('Aligner is disposed')) => {\n if (disposed) return;\n disposed = true;\n lifetime.abort(error);\n worker.terminate();\n for (const request of pending.values()) request.reject(error);\n pending.clear();\n };\n worker.addEventListener('message', ({ data }) => {\n const request = pending.get(data?.id);\n if (!request) return;\n if (data.type === 'progress') {\n try { request.progress?.({ stage: data.stage, completed: data.completed, total: data.total }); } catch { /* Observer failures cannot corrupt inference. */ }\n } else if (data.type === 'result') { pending.delete(data.id); request.resolve(data.result); }\n else if (data.type === 'error') { pending.delete(data.id); const error = new Error(data.error?.message ?? 'Worker failed'); error.name = data.error?.name ?? 'Error'; request.reject(error); }\n });\n worker.addEventListener('error', event => stop(new Error(event.message || 'Alignment Worker failed')));\n worker.addEventListener('messageerror', () => stop(new Error('Could not deserialize Worker response')));\n const request = <T>(message: Record<string, unknown>, progress?: (p: Progress) => void, transfer: Transferable[] = []) => new Promise<T>((resolve, reject) => {\n if (disposed) { reject(new Error('Aligner is disposed')); return; }\n const id = ++sequence;\n pending.set(id, { resolve, reject, progress });\n try { worker.postMessage({ ...message, id }, transfer); } catch (error) { pending.delete(id); reject(error); }\n });\n const initializeAbort = () => stop(abortError());\n options.signal?.addEventListener('abort', initializeAbort, { once: true });\n try {\n await request({ type: 'initialize', options: { modelUrl: String(options.modelUrl ?? DEFAULT_MODEL_URL), modelSha256: modelSha256.toLowerCase(), assetBaseUrl: assetBaseUrl.href, threads } }, options.onProgress);\n } catch (error) { stop(); throw error; }\n finally { options.signal?.removeEventListener('abort', initializeAbort); }\n const initializationSeconds = (performance.now() - initializeStart) / 1000;\n return {\n async align(input): Promise<AlignmentResult> {\n if (disposed) throw new Error('Aligner is disposed');\n if (busy) throw new Error('An alignment is already in progress (instance is busy)');\n input.signal?.throwIfAborted();\n const lines = (typeof input.lyrics === 'string' ? input.lyrics.split(/\\r?\\n/) : input.lyrics).map(line => line.trim()).filter(Boolean);\n if (!lines.length || !lines.some(line => /[\\p{L}\\p{N}]/u.test(line))) throw new TypeError('lyrics must include spoken text');\n if (typeof input.language !== 'string' || !/^[a-z]{2,3}$/.test(input.language)) throw new TypeError('language must be an explicit ISO language code, e.g. en or ja');\n busy = true;\n const operationStart = performance.now();\n const onAbort = () => stop(abortError());\n input.signal?.addEventListener('abort', onAbort, { once: true });\n try {\n const samples = await prepareAudio(input.audio, lifetime.signal);\n const audioPreparationSeconds = (performance.now() - operationStart) / 1000;\n if (disposed || input.signal?.aborted) throw abortError();\n const audioSeconds = samples.length / 16000;\n // The first pass transfers `samples` to the Worker; refinement re-aligns slices of this copy.\n const original = input.language === 'ja' || input.language === 'en' ? samples.slice() : undefined;\n const result = await request<{ words: TimelineEntry[]; metrics: AlignmentMetrics; cues?: Cue[] }>({ type: 'align', audio: samples, lyrics: lines.join('\\n'), language: input.language }, input.onProgress, [samples.buffer]);\n const cueStart = performance.now();\n let words = result.words, cues = result.cues ?? timelineToCues(lines, words, audioSeconds);\n let refinementSeconds = 0, refinedLines = 0;\n if (original) {\n // Calibrated on Japanese and checked on English; other languages keep the single pass.\n const refineStart = performance.now();\n const refined = await refineTimeline({\n lines, words, audioSeconds,\n onStep: (completed: number, total: number) => { try { input.onProgress?.({ stage: 'refine', completed, total }); } catch { /* Observer failures cannot corrupt inference. */ } },\n alignClip: async (from: number, to: number, clipLines: string[]) => {\n const clip = original.slice(Math.floor(from * 16000), Math.ceil(to * 16000));\n try { return (await request<{ words: TimelineEntry[] }>({ type: 'align', audio: clip, lyrics: clipLines.join('\\n'), language: input.language }, undefined, [clip.buffer])).words; }\n catch (error) { if (disposed || input.signal?.aborted) throw error; return undefined; }\n },\n });\n words = refined.words; cues = refined.cues; refinedLines = refined.refinedLines;\n refinementSeconds = (performance.now() - refineStart) / 1000;\n }\n const srt = toSrt(cues);\n const cueMappingSeconds = (performance.now() - cueStart) / 1000 - refinementSeconds;\n const operationSeconds = (performance.now() - operationStart) / 1000;\n return { ...result, words, cues, srt, audioSeconds, metrics: { ...result.metrics, engineTotalSeconds: result.metrics.totalSeconds, initializationSeconds, audioPreparationSeconds, cueMappingSeconds, refinementSeconds, refinedLines, operationSeconds, totalSeconds: initializationSeconds + operationSeconds } };\n } finally { busy = false; input.signal?.removeEventListener('abort', onAbort); }\n },\n dispose() { stop(); },\n };\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["i", "j", "valid", "request"]
|
|
7
7
|
}
|
package/dist/types.d.ts
CHANGED
|
@@ -48,6 +48,9 @@ export interface AlignmentMetrics {
|
|
|
48
48
|
audioPreparationSeconds: number;
|
|
49
49
|
alignmentSeconds: number;
|
|
50
50
|
cueMappingSeconds: number;
|
|
51
|
+
/** Time spent re-aligning suspect lines (Japanese and English only); 0 when nothing was flagged. */
|
|
52
|
+
refinementSeconds: number;
|
|
53
|
+
refinedLines: number;
|
|
51
54
|
operationSeconds: number;
|
|
52
55
|
engineTotalSeconds: number;
|
|
53
56
|
totalSeconds: number;
|