The alignment algorithm in js/word-alignment.js (the "align previously transcribed content" feature, #259) uses Levenshtein edit-distance to map a human-corrected transcript onto the machine transcript's word timings. It works, but has several concrete weaknesses worth addressing:
1. Inserted-word timing is borrowed wholesale from one neighbour.
generateAlignedJSON gives every inserted word the next matched word's start/end verbatim (falling back to the previous). A run of several inserted words therefore collapses to identical timestamps — producing zero-duration and overlapping cues. Timing should be distributed/interpolated across the gap between the two surrounding anchored words, so inserted words get monotonic, non-overlapping spans.
2. Punctuation-aware matching is documented but not applied.
normalizeWord/stripPunctuation exist, but alignWords compares raw .toLowerCase() (lines 504 & 540). So "hello," vs "hello" scores as a substitution, not a match, inflating edit distance and worsening alignment. Numbers ("20" vs "twenty"), contractions, and hyphenation cause the same spurious substitutions. The DP comparison should normalise (and ideally handle number-word and contraction equivalence).
3. Full O(m×n) DP table over the whole transcript.
Memory/time grows with the product of both lengths — a long transcript (tens of thousands of words) builds an enormous table. Consider anchored / banded alignment (split on high-confidence match anchors and align segments) to bound cost.
4. Leftover debug output.
alignTranscripts has several console.log calls (lines 792–799) that should be removed.
Suggested acceptance criteria / tests:
- Insert-run timings are strictly monotonic with no zero/negative durations or overlaps.
- Normalised matches (trailing punctuation, case) count as matches, not substitutions.
- A performance guard for large inputs.
The module is already self-contained, so this can be reworked and unit-tested in isolation.
The alignment algorithm in
js/word-alignment.js(the "align previously transcribed content" feature, #259) uses Levenshtein edit-distance to map a human-corrected transcript onto the machine transcript's word timings. It works, but has several concrete weaknesses worth addressing:1. Inserted-word timing is borrowed wholesale from one neighbour.
generateAlignedJSONgives every inserted word the next matched word'sstart/endverbatim (falling back to the previous). A run of several inserted words therefore collapses to identical timestamps — producing zero-duration and overlapping cues. Timing should be distributed/interpolated across the gap between the two surrounding anchored words, so inserted words get monotonic, non-overlapping spans.2. Punctuation-aware matching is documented but not applied.
normalizeWord/stripPunctuationexist, butalignWordscompares raw.toLowerCase()(lines 504 & 540). So"hello,"vs"hello"scores as a substitution, not a match, inflating edit distance and worsening alignment. Numbers ("20"vs"twenty"), contractions, and hyphenation cause the same spurious substitutions. The DP comparison should normalise (and ideally handle number-word and contraction equivalence).3. Full O(m×n) DP table over the whole transcript.
Memory/time grows with the product of both lengths — a long transcript (tens of thousands of words) builds an enormous table. Consider anchored / banded alignment (split on high-confidence match anchors and align segments) to bound cost.
4. Leftover debug output.
alignTranscriptshas severalconsole.logcalls (lines 792–799) that should be removed.Suggested acceptance criteria / tests:
The module is already self-contained, so this can be reworked and unit-tested in isolation.