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/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 i = n, j = m;
129
- while (i || j) {
130
- const cost = dp[i * width + j];
131
- if (i && j && cost === dp[(i - 1) * width + j - 1] + (expected[i - 1] === actual[j - 1] ? 0 : 1)) {
132
- if (expected[i - 1] === actual[j - 1]) mapping[i - 1] = j - 1;
133
- i--;
134
- j--;
135
- } else if (i && cost === dp[(i - 1) * width + j] + 1) i--;
136
- else j--;
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 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);
147
- 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 };
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: dp[n * width + m], rows };
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.ts
154
- function timelineToCues(lyrics, words, audioSeconds) {
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.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
- const cues = timelineToCues(lines, result.words, audioSeconds);
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;