From 54e4c33c9452edaa16c692a195c68cc3916e3e59 Mon Sep 17 00:00:00 2001 From: Fahad Date: Thu, 9 Jul 2026 18:50:27 +0530 Subject: [PATCH 1/2] Fix flicker from overlapping whisper timestamps in build_ass.py When Whisper produces overlapping word timestamps (word B starts before word A ends), the old fallback of seg_start + 0.05s created a visible flash. Now uses the word's own whisper-reported end time, with a 0.3s minimum floor. Non-overlapping words are unaffected. --- scripts/build_ass.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/build_ass.py b/scripts/build_ass.py index a6a7ee9..e0db32d 100644 --- a/scripts/build_ass.py +++ b/scripts/build_ass.py @@ -54,7 +54,7 @@ def fmt_time(t): for i, w in enumerate(chunk): seg_start = w["start"] seg_end = chunk[i+1]["start"] if i+1 < len(chunk) else chunk_end - if seg_end <= seg_start: seg_end = seg_start + 0.05 + if seg_end <= seg_start: seg_end = max(w["end"], seg_start + 0.3) if P["highlight"]: parts = [] for j, ww in enumerate(chunk): From b656c176a76df0235b922e64c2cd33520485bafc Mon Sep 17 00:00:00 2001 From: Fahad Date: Thu, 27 Aug 2026 18:46:08 +0530 Subject: [PATCH 2/2] Normalize word timestamps to fix subtitle flicker When Whisper produces overlapping word timestamps (word B starts before word A ends), the fallback on line 62 created a visible flash. Instead of patching the fallback, sanitize the word list right after it is built so starts are monotonic with a minimum 0.15s word duration. - Only glitched words get shifted; normal timestamps are unaffected - Fallback kept as belt-and-braces (nearly unreachable now) - Fixes the stacking artifact from the previous approach --- scripts/build_ass.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/scripts/build_ass.py b/scripts/build_ass.py index e0db32d..9807689 100644 --- a/scripts/build_ass.py +++ b/scripts/build_ass.py @@ -31,6 +31,11 @@ def fmt_time(t): for w in seg.get("words", []): words.append({"start": w["start"], "end": w["end"], "text": w["word"].strip()}) +MIN_WORD = 0.15 +for k in range(1, len(words)): + if words[k]["start"] < words[k-1]["start"] + MIN_WORD: + words[k]["start"] = words[k-1]["start"] + MIN_WORD + chunks = [words[i:i+P["chunk"]] for i in range(0, len(words), P["chunk"])] header = f"""[Script Info] @@ -54,7 +59,7 @@ def fmt_time(t): for i, w in enumerate(chunk): seg_start = w["start"] seg_end = chunk[i+1]["start"] if i+1 < len(chunk) else chunk_end - if seg_end <= seg_start: seg_end = max(w["end"], seg_start + 0.3) + if seg_end <= seg_start: seg_end = seg_start + 0.05 if P["highlight"]: parts = [] for j, ww in enumerate(chunk):