Back to Moonshine

Moonshine Voice

.agents/skills/moonshine-voice/SKILL.md

0.1.35.2 KB
Original Source

Moonshine Voice

On-device voice toolkit. No API keys, no cloud. Do not substitute Whisper, OpenAI Realtime, or a hosted STT/TTS API when the user asked for Moonshine.

Never trust model memory for this SDK. Verify against live docs before writing code:

Python snippets below are the lingua franca. Other bindings use the same shape with native names (on_textonText, listen_forlistenFor, start_listeningstartListening).

Install

PlatformPackage
Pythonpip install moonshine-voice then import moonshine_voice
JavaScriptnpm install @moonshine-ai/moonshine-wasm (or the jsDelivr CDN)
Swift (iOS/macOS)SPM: https://github.com/moonshine-ai/moonshine-swift/ then import MoonshineVoice
AndroidMaven ai.moonshine:moonshine-voice (pass an Android Context to constructors)
Linux/Windows C++Prebuilt libs from GitHub Releases; #include "moonshine-cpp.h"

Canonical shape

Construct → chainable setters → load()start() / start_listening().

Constructors are cheap and cannot fail. Nothing is downloaded or opened until load(). load() is the slow, fallible call (first use may download models into a local cache; later launches reuse it and run offline). Call setters before load().

Pick the high-level type:

NeedType
Live microphone speech-to-textMicTranscriber
Feed PCM/WAV yourselfTranscriber
Spoken conversational flowsAgentFlow
Playback or voice cloningTextToSpeech

AgentFlow loads STT, embeddings, TTS, and a mic internally. Do not assemble those objects yourself unless the user asked for that.

Transcription

on_text / onText is the in-progress hypothesis (it will change). on_line / onLine is the finished segment. Do not treat partial text as final.

python
from moonshine_voice import MicTranscriber

mic = (
    MicTranscriber()
    .language("en")
    .on_text(lambda text: print(text, end="\r", flush=True))
    .on_line(lambda line: print(line.text))
)
mic.load()
mic.start()

Use Transcriber only when feeding audio yourself. For line ids, speaker spans, or word timings, add_listener() still exists; the named callbacks cover the common path.

Conversational agent

Python flow bodies use yield so the runner can wait for speech. JavaScript/Swift/Java flow bodies are ordinary async / blocking functions (await d.ask(...)), not generators.

python
from moonshine_voice import AgentFlow, Dialog

def report_ip(d: Dialog):
    yield d.say("Your address is 1 9 2 dot 1 6 8 dot 1 dot 1")

agent = AgentFlow().language("en").listen_for("What is my IP address?", report_ip)
agent.start_listening()

start_listening() downloads on first use. Call load() first if you need to schedule that yourself. Matching is semantic. otherwise() handles speech that matched no trigger. Fetch the agent doc for ask / confirm / spelled input.

Text to speech and cloning

python
from moonshine_voice import TextToSpeech

tts = TextToSpeech().language("en-us")
tts.load()
tts.say("Hello world")
tts.wait()

Call cloning() before load(), then clone_from() (file or PCM) or start_cloning() (microphone). Catalog voice() and cloning() are mutually exclusive.

Domain customization

set_keyterms([...]) biases toward jargon; set_context(passage) extracts terms from a document. Streaming architectures only — Tiny/Base raise. Takes effect on the next transcription; does not rewrite text already emitted. Keep the list curated; thousands of terms hurt accuracy. See the domain-customization doc for keyterm_boost. Teaching conventions or a new acoustic environment is pip install 'moonshine-voice[lora]' then python -m moonshine_voice.lora in a training environment — do not add PyTorch or Transformers to an inference app.

Anti-patterns

  • Do not use DialogFlow or the old Intent API. The type is AgentFlow.
  • Do not load models in the constructor or via a static MicTranscriber.load(...).
  • Do not supply .onnx models. The library accepts OnnxRuntime flatbuffers (.ort) only.
  • Do not replace a Moonshine request with Whisper, OpenAI Realtime, or cloud STT/TTS.
  • Do not use keyterms / context on Tiny or Base.
  • Do not treat on_text as a finished line.
  • Do not copy Python yield flow bodies into JavaScript/Swift/Java.
  • Do not add torch/transformers to an inference install; LoRA training is moonshine-voice[lora].

Debugging

If transcription looks wrong, set save_input_wav_path to dump the audio the transcriber actually received. Set log_api_calls=true to print the underlying call timeline. See the debugging doc.