AGPL-3.0-or-later · forever.

the standard library

nika:tts_generate

Synthesize speech audio (local compat servers · openai gpt-4o-mini-tts · elevenlabs · mock for offline runs) — saves ONE audio file under output_dir and returns path + format + sha256 + duration (+ a provenance manifest); audio bytes never ride outputs. One of 28 builtins in the closed nika: namespace.

the media familyimages, audio, charts: assets, not blobs

  • mediafamily4 tools
  • 11argsdeclared contract
  • 2requiredcheck teaches a miss
  • craftedusage filecheck-green below

the contract

11 args · 2 required

A missing required arg is a nika check finding before anything runs; the vocabulary below comes from the binary itself (nika catalog --tools --json), not from prose.

provider
stringlocal | openai | elevenlabs | mock (inferred from model: when omitted · local is never inferred)
model
stringprovider model id · defaults: tts-1 (local · LocalAI convention) · gpt-4o-mini-tts · eleven_multilingual_v2 · mock-tts-1
text*
stringthe text to speak · ≤4096 chars (fan long scripts out with for_each)
voice
stringprovider voice · defaults: alloy (openai/local) · Rachel's id (elevenlabs) · sine (mock)
format
stringmp3 | wav | auto (default · provider-native · the saved extension follows the bytes)
speed
number0.25..=4.0 (openai/local · warned-dropped elsewhere)
output_dir*
stringdirectory the audio lands in (created if missing · fs-permit gated)
filename_prefix
stringfilename stem (default: metadata.page_slug, else `speech`)
manifest
booleanwrite the sidecar provenance manifest (default true)
metadata
objectfree-form provenance echoed into output + manifest
timeout_ms
integerper-request cap · default 120000 (local 300000) · max 600000

in a real file

a complete workflow
tts_generate.nika.yaml
nika: v1workflow:  id: say-the-verdict  description: "one audio file under output_dir — mock provider runs offline"permits:  fs:    write: ["./audio/**"]  exec: false  tools: ["nika:log", "nika:tts_generate"]tasks:  line:    infer:      model: ollama/qwen3.5:4b      prompt: "One warm sentence announcing a green run. Nothing else."      temperature: 0.9    retry:      max_attempts: 3      backoff_ms: 500      backoff_max_ms: 4000  speak:    with:      line: ${{ tasks.line.output }}    invoke:      tool: "nika:tts_generate"      args:        provider: mock        text: "${{ with.line }}"        output_dir: "./audio"    on_finally:      - invoke:          tool: "nika:log"          args: { message: "audio pass done — anything staged is under ./audio" }outputs:  audio: ${{ tasks.speak.output }}

a complete file, nika check green; the drift gate re-validates this copy against the schema on every test run. open it in the playground →

cross-references

ships in skeletons

no skeleton ships it; the crafted file above is the reference.

the check gates

the media family

4 tools

images, audio, charts: assets, not blobs.

Machines read the same vocabulary at /tools/catalog.json; the contract lives in spec 06 · stdlib. Install and ask the binary itself: nika catalog --tools. Read the spec →