""" Supertonic TTS Gradio Demo — concurrent chunk streaming with playback sync Splits text into statements, synthesizes in a background thread, streams audio chunk-by-chunk. A JS timeupdate listener tracks audio.currentTime to bold exactly the chunk currently playing in the browser. Usage: python app.py """ import json import logging import queue import re import threading from pathlib import Path import gradio as gr import numpy as np from supertonic import TTS, AVAILABLE_LANGUAGES logger = logging.getLogger(__name__) CLONED_VOICE_JSON = Path(__file__).resolve().parent / "recorded_voice_supertonic-3.json" CLONED_VOICE_LABEL = "Custom (recorded_voice_supertonic-3.json)" print("Loading Supertonic TTS model...") tts = TTS(auto_download=True) builtin_voices = tts.voice_style_names # M1-M5, F1-F5 all_voices = ([CLONED_VOICE_LABEL] + builtin_voices) if CLONED_VOICE_JSON.exists() else builtin_voices _SENTENCE_SPLIT_RE = re.compile(r'(?<=[.!?;])\s+') _SENTINEL = object() # JavaScript injected once at page load. # Watches for changes to the hidden timing component, then attaches a # timeupdate listener that bolds whichever .chunk-text span is currently # playing based on audio.currentTime. _SYNC_JS = """ () => { function attachAudioSync(chunks) { // Find the streaming audio element — Gradio wraps it inside a // data-testid="audio" block; fall back to first