nc://openrouter-voice

v0.1.0Pinned
ThomSharktools/nodecode-openrouter-voice: Transcribes audio files and speaks text aloud through OpenRouter's voice endpoints. - a rewrite of esketids/hermes-openrouter-voice (MIT), credited to esketidsd0ba631· 9 Nov1 commit
test1 filecell.lisp32.7 KB

nodecode-openrouter-voice

OpenRouter voice: transcribe an audio file to text, and speak text as an mp3. A Nodecode rewrite of esketids/hermes-openrouter-voice by esketids.

The model gets two tools. transcribe_audio posts an audio file to OpenRouter's /audio/transcriptions and answers the words; speak_text posts text to /audio/speech and writes the mp3 where you asked for it. Both bill the same OpenRouter key your chat already uses, so there is no second account.

Get it

Tell the agent "add the openrouter-voice cell", or run

nodecode add nc://openrouter-voice

Set it up

One key, from https://openrouter.ai/keys. Either put it in the environment as OPENROUTER_API_KEY, or name it in the section:

{
  "openrouter-voice": {
    "api_key_env": "OPENROUTER_API_KEY"   // or "api_key": "sk-or-..." inline
  }
}

Everything else has a default that works: stt_model openai/whisper-large-v3, tts_model deepgram/aura-2, voice aura-2-thalia-en. /settings and the Settings tab both edit it, and a start with no key refuses by name rather than failing on the first call.

Use it

Ask for it in words — "transcribe this recording", "read this out loud" — and the model calls the tool. By hand:

/voice                       where it points, and what it uses
/voice ~/notes/call.wav      transcribe a file, answered in the shell
/voice say good morning      speech into output_dir, answered with the path
/voice voices                the default model's voice ids

A .wav that is not 16 kHz mono is rewritten to that shape in Lisp before it is sent, because one of the catalog's transcription models answers 400 otherwise; other containers (the desktop's webm/opus, mp3) go through ffmpeg when it is installed, and are sent as they are when it is not. A voice belongs to a model — aura-2-* for the default, af_heart for kokoro — and the fish-audio models publish none, so they are sent without one. Speed is 0.25 to 4.0: whatever a model accepts natively is sent, the rest is time-stretched locally with ffmpeg.

Test

.github/test-cell.sh tools/nodecode-openrouter-voice

Offline: every request is a stubbed nlk:http, and ffmpeg is stubbed absent.

Gaps

The original is a pair of Hermes voice providers, so Hermes' desktop Voice tab could select OpenRouter for dictation and for spoken replies. Nodecode has no seam a cell adds a voice provider to, so here the two directions are two tools the model calls, plus /voice; a shell that wants to play the mp3 itself still does that step. Audio is posted whole, as the original does: no streaming transcription, and a long file is one long request.

Add nc://openrouter-voice

  1. 1

    Install Nodecode

    Once per machine.

    $ curl -fsSL https://nodecode.ai/install.sh | sh
  2. 2

    Add the cell

    Pinned at d0ba631.

    $ nodecode add nc://openrouter-voice

    Or tell the agent add the openrouter voice cell.