Drop any audio or video: ffmpeg decodes, live segments, ETA.
Closes to the tray — the queue and voice API keep running.
The first ~10 seconds detect the language — and the best model for it is picked automatically.
decode → detect → route → transcribe → save. Walk away.
Downloaded an episode or lecture? Drop it in — get searchable text.
Load a video, get a timestamped transcript — read, search, translate.
Send voice messages from your phone or the desktop app — transcribed locally into the same session.
Download the app, let it pull the models once — after that h2voice simply lives in your system tray.
Grab the desktop build for your OS — Linux, macOS or Windows — and install it like any other app.
On first launch the app pulls the STT models once. From then on they live on your disk — nothing is fetched again.
Close the window — the app keeps running in the system tray. The queue and voice API stay up; dictation is one hotkey away.
h2voice serves a small HTTP/1.1 API on a local Unix domain socket — ~/.h2voice/voice.sock (chmod 0600, override with H2VOICE_VOICE_SOCKET). JSON in, JSON out; recording streams progress over Server-Sent Events. Audio and models never leave your machine.
# 200 OK
{"status": "ok", "version": "0.2.1"}
# 200 OK
{
"recording": false,
"device": "default",
"stt_engine": "auto",
"stt_ready": true,
"language": "auto",
"sample_rate": 16000
}
Request body (all fields optional): {"language": "auto", "stt_engine": "auto"}. The response is an SSE stream; the final transcript arrives as the result event.
# 200 OK — text/event-stream
data: {"type": "started", "sample_rate": 16000, "channels": 1, "device": "default"}
data: {"type": "level", "rms": 0.062}
data: {"type": "level", "rms": 0.118}
data: {"type": "stopped", "duration_ms": 2130}
data: {"type": "transcribing", "engine": "gigaam", "language": "ru"}
data: {"type": "result", "text": "добавь тесты на retry-логику", "duration_ms": 2130, "language": "ru", "engine": "gigaam"}
# 200 OK
{"status": "stopped", "duration_ms": 2130}
Request: {"path": "/home/u/notes.m4a", "engine": "auto", "language": null} — file up to 25 MB by default, from ~/.h2code/voice or the temp dir.
# 200 OK
{"text": "расшифрованный текст", "duration_sec": 12.4, "engine": "gigaam", "language": "ru"}
# liveness + protocol version curl --unix-socket ~/.h2voice/voice.sock http://localhost/health # → {"status": "ok", "version": "0.2.1"} # transcribe a local file (engine & language are optional, "auto" by default) curl --unix-socket ~/.h2voice/voice.sock http://localhost/v1/transcribe/file \ -d '{"path": "/home/u/notes.m4a", "engine": "auto", "language": null}' # → {"text": "…", "duration_sec": 12.4, "engine": "gigaam", "language": "ru"}
Engine auto-selection: Russian goes to GigaAM when ready, everything else to Whisper. A headless h2voice-server serves the same protocol and socket for running without the GUI.