Skip to content

Local voice mode

Local voice mode keeps voice transcription private and local. Bestie receives an audio attachment from any channel or runtime surface that wires into the voice pipeline, converts it to WAV when needed, runs whisper.cpp, sends only the bounded transcript and metadata to the agent, then deletes raw voice/audio files when configured.

.bestie/tools/whisper-bin/whisper-cli
.bestie/tools/local-whisper-transcribe.sh
.bestie/models/ggml-small.bin

The wrapper accepts model path and audio path, converts with ffmpeg, and prints transcript text to stdout.

If the local files exist, configure shared local voice mode with:

Terminal window
bestie voice setup-local

List models and the current configured model:

Terminal window
bestie voice models

Preview a model download:

Terminal window
bestie voice download-model small

Download and switch to the model:

Terminal window
bestie voice download-model small --confirm --use
bestie voice download-model small --confirm --force --use

Supported names are tiny, small, medium, and large-v3-turbo. Existing files are not overwritten unless --force is provided.

Use ElevenLabs when you want hosted speech-to-text and speech replies instead of local whisper.cpp:

Terminal window
bestie voice setup-elevenlabs
bestie doctor --telegram-speech-test

Setup asks for an ElevenLabs API key, voice id, TTS model id, STT model id, and output format. Bestie stores the key in .bestie/.env as ELEVENLABS_API_KEY, writes transcription and speech config, and enables Telegram voice/audio attachment transcription plus voice replies for voice inputs. The default speech reply policy is voice-input-only, with an 800-character reply cap and a 30-second cooldown unless existing Telegram config overrides those values.

Bestie also exposes a local Voicebox setup flow:

Terminal window
bestie voice setup-voicebox

Run the command and follow its prompts to configure the local Voicebox integration. Use bestie doctor after setup to check the configured local voice dependencies.

{
"transcription": {
"provider": "local-whisper",
"command": ".bestie/tools/local-whisper-transcribe.sh",
"args": ["{modelPath}", "{audioPath}", "-l", "vi"],
"modelPath": ".bestie/models/ggml-small.bin",
"timeoutMs": 120000
},
"channels": {
"telegram": {
"attachments": {
"downloadPolicy": "allow",
"transcriptionPolicy": "allow",
"transcriptionMaxBytes": 10485760,
"deleteAfterProcessingKinds": ["voice", "audio"]
}
}
}
}

For Vietnamese, ggml-small.bin is the practical local baseline. ggml-tiny.bin is faster but commonly too inaccurate for Vietnamese voice chat.

Run Doctor:

Terminal window
bestie doctor
bestie doctor --telegram-speech-test

Expected checks include local transcription command, model, ffmpeg, and model quality warnings.

For a real Telegram adapter smoke transcript, run Telegram separately after shared voice is configured:

Terminal window
bestie channels telegram --once --transcript .bestie/logs/telegram-local-voice-smoke.jsonl

The transcript file must not contain raw message text, transcript text, file ids, file paths, owner ids, chat ids, bot tokens, or provider secrets.

Preview retained old voice/audio files:

Terminal window
bestie tools attachments cleanup --older-than 7d --kinds voice,audio

Delete matched files:

Terminal window
bestie tools attachments cleanup --older-than 7d --kinds voice,audio --confirm

Voice is now a separate capability instead of being coupled to Telegram. A Bestie can use voice features from any supported channel or runtime surface that wires audio input/output into the agent.

This means Telegram can still support voice workflows by passing Telegram voice/audio attachments into the shared pipeline, but Telegram is no longer the owner of the voice feature. Keep voice configuration and voice behavior documented as a standalone capability, then connect it to Telegram, CLI, web, or future adapters as needed.