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
Publish 1.9.13
9 files changed
+81−50
Cargo.toml+1−1@@ -1,6 +1,6 @@ [package] name = "adom-tts"-version = "1.9.12"+version = "1.9.13" edition = "2021" license = "AGPL-3.0-or-later" repository = "https://github.com/adom-inc/adom-tts"
VERSION+1−1@@ -1 +1 @@-1.9.12+1.9.13
bin/adom-tts⋯ 1 unchanged line ⋯
install.sh+2−2@@ -12,9 +12,9 @@ mkdir -p "$BIN_DIR" install -m 0755 "$DIR/bin/adom-tts" "$BIN_DIR/adom-tts" echo "Installed adom-tts -> $BIN_DIR/adom-tts" -# 2) Claude Code skills (main + build sibling).+# 2) Claude Code skill (user tier only — dev/publish skills stay in source). SKILL_DIR="${HOME}/.claude/skills"-for s in adom-tts adom-tts-build; do+for s in adom-tts; do if [ -f "$DIR/skills/$s/SKILL.md" ]; then mkdir -p "$SKILL_DIR/$s" install -m 0644 "$DIR/skills/$s/SKILL.md" "$SKILL_DIR/$s/SKILL.md"
package.json+1−1@@ -1,6 +1,6 @@ { "slug": "adom-tts",- "version": "1.9.12",+ "version": "1.9.13", "type": "app", "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.", "license": "MIT",
page.json+63−9@@ -4,24 +4,78 @@ "slug": "adom-tts", "title": "adom-tts — your AI's voice", "brief": "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.",- "version": "1.9.12",+ "version": "1.9.13", "license": "MIT",- "tags": ["tts", "voice", "audio", "demo", "accessibility", "open-source", "mit"],+ "tags": [+ "tts",+ "voice",+ "audio",+ "demo",+ "accessibility",+ "cli",+ "open-source",+ "mit"+ ], "hero": { "type": "image", "path": "screenshots/hero-v2.png", "thumbnail": "screenshots/hero-v2-thumb.png" }, "discovery_pitch": "Hands-free in the car? Say 'read me your last answer, I'm driving' and adom-tts speaks it aloud. Making a demo video? Feed it your script and get a perfectly-timed narration track in the house voice — no recording booth, no retakes. One shared edge-tts service with Adom pronunciation overrides and an instant source-hash cache.",- "discovery_triggers": ["adom-tts", "text to speech", "tts", "voiceover", "demo narration", "narration", "synthesize speech", "make audio from text", "read it to me", "read me your answer", "read that back", "read me the last prompt", "I'm driving", "hands-free", "drive mode", "narrate the answer", "play this audio"],+ "discovery_triggers": [+ "adom-tts",+ "text to speech",+ "tts",+ "voiceover",+ "demo narration",+ "narration",+ "synthesize speech",+ "make audio from text",+ "read it to me",+ "read me your answer",+ "read that back",+ "read me the last prompt",+ "I'm driving",+ "hands-free",+ "drive mode",+ "narrate the answer",+ "play this audio"+ ], "sample_prompts": [- { "label": "Drive mode", "prompt": "Read me your last answer, I'm driving" },- { "label": "Demo voiceover", "prompt": "Render this script as a demo voiceover track" },- { "label": "Synthesize and play", "prompt": "Synthesize a 30-second walkthrough of this design and play it for me" },- { "label": "Replay last", "prompt": "Play the last TTS clip again" },- { "label": "Add pronunciation", "prompt": "Teach the TTS service that aci is pronounced A-C-I" }+ {+ "label": "Drive mode",+ "prompt": "Read me your last answer, I'm driving"+ },+ {+ "label": "Demo voiceover",+ "prompt": "Render this script as a demo voiceover track"+ },+ {+ "label": "Synthesize and play",+ "prompt": "Synthesize a 30-second walkthrough of this design and play it for me"+ },+ {+ "label": "Replay last",+ "prompt": "Play the last TTS clip again"+ },+ {+ "label": "Add pronunciation",+ "prompt": "Teach the TTS service that aci is pronounced A-C-I"+ } ], "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,+ "org": "adom",+ "author": {+ "name": "John Lauer",+ "email": "[email protected]" }-}+}
screenshots/hero-v3-thumb.pngadded⋯ 1 unchanged line ⋯
screenshots/hero-v3.pngadded⋯ 1 unchanged line ⋯
src/main.rs+13−36@@ -558,49 +558,26 @@ fn cmd_say( Ok(()) } -const BUILD_SKILL: &str = include_str!("../BUILD-SKILL.md");+// The USER skill ships inside the binary so `adom-tts install` (the Tier B+// curl-install path, no package dir around) always writes a skill that matches+// this exact build. Dev/publish skills are source-only (dev-skills/,+// publish-skills/ on the wiki page repo) and are NEVER installed to users.+const USER_SKILL: &str = include_str!("../skills/adom-tts/SKILL.md"); fn cmd_install() -> Result<()> { let home = std::env::var("HOME").map(PathBuf::from) .map_err(|_| anyhow!("no $HOME"))?; let skill_dir = home.join(".claude/skills/adom-tts"); std::fs::create_dir_all(&skill_dir)?;-- // Deploy the sibling build skill too (adom-app-model §5).- let build_dir = home.join(".claude/skills/adom-tts-build");- std::fs::create_dir_all(&build_dir)?;- std::fs::write(build_dir.join("SKILL.md"), BUILD_SKILL)?;- eprintln!("✓ build skill → {}", build_dir.join("SKILL.md").display());-- // Fetch SKILL.md from the wiki page. Mirrors adom-cli-design rule 7.b- // (no include_str! of prose). Falls back to a brief placeholder if the- // wiki is unreachable + nothing already exists.- let wiki = "https://wiki-ufypy5dpx93o.adom.cloud/api/v1/pages";- let dst = skill_dir.join("SKILL.md");- match http_client().get(wiki).send() {- Ok(r) if r.status().is_success() => {- if let Ok(body) = r.json::<serde_json::Value>() {- let pages = body.get("pages").and_then(|p| p.as_array())- .or_else(|| body.as_array())- .cloned().unwrap_or_default();- let page = pages.iter()- .find(|p| p.get("slug").and_then(|s| s.as_str()) == Some("adom-tts")- && p.get("type").and_then(|t| t.as_str()) == Some("app"));- if let Some(p) = page {- if let Some(src) = p.get("skill_source").and_then(|s| s.as_str()).filter(|s| !s.is_empty()) {- std::fs::write(&dst, src)?;- eprintln!("✓ skill fetched from wiki → {}", dst.display());- return write_completions(&home);- }- }- }- }- _ => {}- }- if !dst.exists() {- std::fs::write(&dst, "# adom-tts\n\nSee https://wiki-ufypy5dpx93o.adom.cloud/apps/adom-tts for the full skill.\n")?;+ std::fs::write(skill_dir.join("SKILL.md"), USER_SKILL)?;+ eprintln!("✓ skill → {}", skill_dir.join("SKILL.md").display());+ // Clean up the legacy build-skill leak (shipped to users before the+ // three-tier layout; it belongs in dev-skills/ on the wiki page only).+ let legacy = home.join(".claude/skills/adom-tts-build");+ if legacy.exists() {+ let _ = std::fs::remove_dir_all(&legacy);+ eprintln!("✓ removed legacy dev-skill leak {}", legacy.display()); }- eprintln!("! wiki unreachable — kept {} (may be stale)", dst.display()); write_completions(&home) }