fix: harden arabic terminal rtl rendering

This commit is contained in:
Adolfo Reyna
2026-03-06 19:25:12 -05:00
parent e3cd538dca
commit 57366543ec
2 changed files with 35 additions and 3 deletions
+8
View File
@@ -152,3 +152,11 @@ The project now features a high-performance, Apple Silicon-optimized pipeline th
- Implemented comment/blank-line support and invalid-line skipping with line-level warnings. - Implemented comment/blank-line support and invalid-line skipping with line-level warnings.
- Merged file-based glossary entries with repeatable `--glossary-pair` CLI entries for runtime overrides. - Merged file-based glossary entries with repeatable `--glossary-pair` CLI entries for runtime overrides.
- **Outcome:** English caption correction can now use a maintained glossary file automatically, while preserving ad-hoc CLI term fixes. - **Outcome:** English caption correction can now use a maintained glossary file automatically, while preserving ad-hoc CLI term fixes.
## Phase 19: Arabic Terminal Rendering Hardening
- **Goal:** Improve readability of Arabic captions in terminal environments with mixed LTR/RTL output.
- **Approach:**
- Switched Arabic output to a strict two-line format (`[AR]:` label line + dedicated RTL content line).
- Wrapped Arabic caption content in explicit RTL embedding marks for better bidirectional layout stability.
- Added punctuation normalization for Arabic display (`،`, `؛`, `؟`) to reduce LTR punctuation artifacts.
- **Outcome:** Arabic captions render more consistently in terminal output, especially when adjacent to English/French/Spanish caption lines.
+27 -3
View File
@@ -229,6 +229,30 @@ def maybe_merge_recent_caption(recent_en_lines, current_text, now_ts, window_sec
previous["ts"] = now_ts previous["ts"] = now_ts
return old, merged return old, merged
def normalize_arabic_punctuation(text):
"""Convert common Latin punctuation to Arabic-friendly equivalents."""
updated = text.replace(",", "،").replace(";", "؛")
# Convert question mark only when there are Arabic letters present.
if re.search(r"[\u0600-\u06FF]", updated):
updated = updated.replace("?", "؟")
return updated
def format_caption_lines(lang_key, text):
"""Format caption output lines for terminal display."""
key = lang_key.lower()
if key == "ar":
cleaned = normalize_arabic_punctuation(text)
# Put label on separate line and force RTL embedding for the content line.
return ["[AR]:", f"\u202B{cleaned}\u202C"]
return [f"[{lang_key.upper()}]: {text}"]
def print_caption(lang_key, text, leading_newline=False):
lines = format_caption_lines(lang_key, text)
if leading_newline and lines:
lines[0] = "\n" + lines[0]
for line in lines:
print(line)
def is_hallucination(text): def is_hallucination(text):
"""Detect common Whisper hallucinations or high repetition.""" """Detect common Whisper hallucinations or high repetition."""
if not text: return False if not text: return False
@@ -517,7 +541,7 @@ def main():
recent_en_lines.clear() recent_en_lines.clear()
if original_text: if original_text:
print(f"\n[{detected_lang.upper()}]: {original_text}") print_caption(detected_lang, original_text, leading_newline=True)
last_change_time = time.time() # Successfully transcribed full segment last_change_time = time.time() # Successfully transcribed full segment
# Prepare payload # Prepare payload
@@ -588,7 +612,7 @@ def main():
# Skip if we already filled this (e.g. detected lang was 'es') # Skip if we already filled this (e.g. detected lang was 'es')
if lang_key in payload: if lang_key in payload:
if lang_key != detected_lang: # Already printed original if lang_key != detected_lang: # Already printed original
print(f"[{lang_key.upper()}]: {payload[lang_key]}") print_caption(lang_key, payload[lang_key])
continue continue
translated_parts = [] translated_parts = []
@@ -608,7 +632,7 @@ def main():
translated_text = " ".join(part for part in translated_parts if part).strip() translated_text = " ".join(part for part in translated_parts if part).strip()
payload[lang_key] = translated_text payload[lang_key] = translated_text
print(f"[{lang_key.upper()}]: {translated_text}") print_caption(lang_key, translated_text)
# Queue for background ingestion if enabled # Queue for background ingestion if enabled
if args.ingest: if args.ingest: