A probe on the torch stage worker (~/dockers/torch-worker) runs beside every transcription and decides what the recording is: solo dictation returns as paragraphs exactly as before, several voices return speaker-labeled with conversation: true. Nobody declares which — the caller cannot know. Transcription and the worker each get a serial FIFO queue on their own resource, so the probe costs a solo memo nothing and multi-user traffic stays fair. The worker is optional and best-effort throughout: unreachable or failing, everything still transcribes, just never labeled. Speaker attribution is segment-granularity by maximal turn overlap — whisper.cpp's own timestamps, no alignment stage. If boundaries prove sloppy, wav2vec2 alignment returns as a worker endpoint. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
56 lines
3.0 KiB
Markdown
56 lines
3.0 KiB
Markdown
# Transcribe
|
|
|
|
Officer's speech-to-text, talking to a self-hosted whisper.cpp server.
|
|
|
|
Transcribe does not run Whisper and ships no model. You point it at a whisper.cpp `/inference` server
|
|
you already run and it forwards to it, tuned for one person talking into a phone: detect the spoken
|
|
language, then transcribe faithfully in it — never translated, never guessed at in English when the
|
|
audio is not.
|
|
|
|
## What you get
|
|
|
|
- **`POST /api/transcribe/transcribe`** — send an audio file, get back its text and the language Whisper
|
|
detected. Two-pass under the hood (detect, then transcribe in that language) so a low-confidence guess
|
|
never quietly defaults to English.
|
|
- **Conversations come back as conversations.** Nobody declares what a recording is — a probe on the
|
|
diarization worker runs alongside every transcription and finds out. Solo dictation returns as
|
|
paragraphs, exactly as before; a recording with several voices returns speaker-labeled
|
|
(`Speaker 1: …`) with `conversation: true` and a speaker count. The worker is optional: without it,
|
|
or if it fails mid-request, everything still transcribes — just never labeled. See
|
|
`~/dockers/torch-worker` for the worker itself.
|
|
- **Fair queueing for a multi-user server.** Transcription and diarization each run one job at a time
|
|
behind their own queue, in arrival order — and on different hardware, so the conversation probe costs
|
|
a solo memo nothing.
|
|
- **A file-browser task.** Right-click an `.mp3`, `.wav` or `.m4a` and transcribe it without a model
|
|
turn — the task is a plain script that calls this plugin's own route and files the result next to the
|
|
original.
|
|
- **A skill**, so an agent asked to transcribe something knows the route, the shape, and what to say when
|
|
nothing is configured, without being told.
|
|
|
|
## What you need
|
|
|
|
**A whisper.cpp server you already run**, reachable from this machine, answering `POST /inference` —
|
|
the same container the platform used to talk to directly. Nothing else. No system packages, no host
|
|
binaries; the sidecar reaches it with `fetch`.
|
|
|
|
## Setup
|
|
|
|
```
|
|
PUT /api/transcribe/config
|
|
{ "url": "http://192.168.1.50:64201" }
|
|
```
|
|
|
|
Validated against the server before it is stored — a wrong URL is a 400 with the reason, not a saved
|
|
value that fails on the first real transcription.
|
|
|
|
## What this plugin deliberately does not have
|
|
|
|
- **No dashboard route, no dock tile.** There is nothing to look at — this is reached through the file
|
|
browser's task menu and by an agent that has read the skill, not through a screen. Shipping no `web/`
|
|
is a supported shape, not an oversight.
|
|
- **No streaming.** One file in, one answer back. If you want a live microphone, that is a different
|
|
feature built on top of this one, not something this plugin does today.
|
|
- **No translation.** It transcribes in whatever language was spoken. Whisper's own translate mode is
|
|
English-only, so honouring "translate into <language>" for anything else would mean silently
|
|
handing back a rough English rendering of, say, Portuguese audio — worse than refusing.
|