fix: harden arabic terminal rtl rendering
This commit is contained in:
@@ -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
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user