app
Adom TTS: Text to Speech
Public Made by Adomby adom
Adom's shared voice service. Reads your AI's answers back to you while you drive, and renders perfectly-timed voiceover tracks for your demo videos, so you never record your own voice.
← Commit history
v1.9.46 — issue #4 (a): both enqueue paths (say --play and play) warn at SEND time when the player is paused and name 'adom-tts control play'; previously only offline audiences warned, and only on say
5 files changed
+16−24
Cargo.lock+1−1@@ -4,7 +4,7 @@ version = 4 [[package]] name = "adom-tts"-version = "1.9.45"+version = "1.9.46" dependencies = [ "anyhow", "base64",
Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "adom-tts"-version = "1.9.45"+version = "1.9.46" edition = "2021" license = "AGPL-3.0-or-later" repository = "https://github.com/adom-inc/adom-tts"
VERSION+1−1@@ -1 +1 @@-1.9.45+1.9.46
page.json−21@@ -12,7 +12,6 @@ "audio", "demo", "accessibility",- "cli", "open-source", "mit" ],@@ -65,25 +64,5 @@ ], "install": { "binary_name": "adom-tts"- },- "description": "Adom's shared text-to-speech CLI + Playground. Reads your AI answers back to you while driving, and renders perfectly-timed voiceover tracks for demo videos.",- "dependencies": {},- "scripts": {- "install": "./install.sh",- "uninstall": "./uninstall.sh"- },- "needs_sudo": false,- "files": [- "package.json",- "install.sh",- "uninstall.sh",- "bin/adom-tts",- "skills/**",- "completions/**"- ],- "org": "adom",- "author": {- "name": "John Lauer",- "email": "[email protected]" } }
src/play.rs+13@@ -91,6 +91,9 @@ fn adopt_surface_env() { } pub fn run(target: &str, surface_cli: Option<Surface>, _wait: bool, allow_repeat: bool) -> Result<()> {+ // Same send-time honesty as `say --play` (issue #4): a replay into a paused+ // or offline player must say so NOW, not surface it via a later timeout.+ warn_if_no_audience(); let path = resolve_target(target)?; let cfg = config::load(); let surface = config::resolve_surface(surface_cli, &cfg.play);@@ -2026,6 +2029,16 @@ pub fn warn_if_no_audience() { .timeout(Duration::from_millis(700)).send() else { return }; let Ok(v) = r.json::<serde_json::Value>() else { return }; let age = v.get("poll_age_ms").and_then(|x| x.as_u64()).unwrap_or(0);+ // PAUSED is a different failure from OFFLINE and needs a different action.+ // Field report (issue #4, live demo narration): a thread's clip sat behind+ // a human pause with no warning at send time. Say so NOW, at enqueue, and+ // name the command; do not make the caller discover it via a 226s timeout.+ if v.get("paused").and_then(|p| p.as_bool()).unwrap_or(false) {+ eprintln!("⏸ PLAYER IS PAUSED: your clip is queued but NOTHING will play until the player resumes.");+ eprintln!(" YOU can resume it yourself, no human needed: `adom-tts control play`");+ eprintln!(" (If a human paused it on purpose, leave it: your clip plays, in order, when they resume.)");+ return;+ } if age > 4000 { eprintln!("⚠ AUDIENCE OFFLINE: no player page has polled for {}s — the listener's device is likely", age / 1000); eprintln!(" locked/disconnected. Your clip is BUFFERED (up to 10 min, 3 retries) and will play on");