Restructure Go source code into a dedicated `src/` directory, rename the project from "audio-listen" to "Captioneer", and update README accordingly. Add `.gitignore` entry for the built binary `captioneer`.
4.1 KiB
Captioneer
Local, live English captions for the audio playing through your default PulseAudio/PipeWire output device. It captures that output's monitor source, runs the Parakeet TDT v2 model locally, and writes captions to the terminal.
Everything runs on your machine after the one-time model download. No audio is uploaded anywhere.
Requirements
- Linux on
amd64/ x86_64 - Go 1.26.2 or newer
pactlandparecavailable onPATH(on Debian/Ubuntu:sudo apt install pulseaudio-utils)curlandtarto download the models- A working PulseAudio-compatible server, including PipeWire's PulseAudio compatibility layer
The application listens to the monitor of the current default audio sink. Check it with:
pactl get-default-sink
Setup
Clone the project, then download the required models once:
git clone <your-repository-url>
cd captioneer
./scripts/download-models.sh
The download installs the Parakeet TDT v2 int8 model and Silero VAD into models/. They are intentionally not committed to Git because they are large.
Run
Use VAD mode for normal live captions. It shows a temporary … caption while speech is active, then prints a timestamped final caption after 0.5 seconds of silence:
go run ./src --mode=vad
Use fixed mode to decode exact time slices, even through silence:
go run ./src --mode=fixed --chunk-duration=1s
Build a reusable executable instead of using go run:
go build -o captioneer ./src
./captioneer --mode=vad
Press Ctrl+C to stop. Pending audio is flushed before exit.
Options
--mode is required. All other options have defaults.
| Option | Default | Description |
|---|---|---|
--mode=vad |
— | Speech-aware captions. This is the recommended everyday mode. |
--mode=fixed |
— | Decode every fixed-duration audio chunk. |
--chunk-duration=1s |
1s |
Fixed chunk length, or VAD preview refresh interval. Go duration syntax is used, e.g. 500ms, 1s, 2s. |
--models-dir=models |
models |
Directory containing parakeet-tdt-v2/ and silero_vad_v5.onnx. |
--threads=2 |
2 |
CPU threads used by Parakeet and VAD. Increase only if your CPU has spare capacity. |
--preview-threshold-dbfs=-45 |
-45 |
RMS level that begins a provisional VAD caption. Raise it (for example, -35) if background audio starts previews; lower it (for example, -55) if quiet speech does not. |
Examples:
# Faster fixed chunks
go run ./src --mode=fixed --chunk-duration=500ms
# Fewer VAD preview redraws and four CPU threads
go run ./src --mode=vad --chunk-duration=2s --threads=4
# Store or reuse models outside this repository
go run ./src --mode=vad --models-dir=/path/to/models
There are no environment variables to configure. All supported configuration is supplied with command-line options.
Source layout
All Go code lives in src/. It remains one executable package, split into focused files:
main.gocoordinates startup and shutdown.config.godefines and validates command-line options.capture.goreads the default system-audio monitor.audio.gocontains PCM conversion and audio calculations.models.govalidates and initializes Parakeet and Silero.captions.gohandles fixed chunks, VAD segments, and terminal output.
Output and troubleshooting
Final captions go to standard output in this form:
[12.34s-15.67s] This is a completed caption.
Startup messages and overload warnings go to standard error, so you can save final captions separately:
go run ./src --mode=vad > captions.txt
- Missing model files: run
./scripts/download-models.shagain. pactlorparecnot found: installpulseaudio-utilsand start a PulseAudio-compatible audio server.- No captions while audio plays: verify the default sink with
pactl get-default-sink; the app records that sink's.monitorsource. - Overload warning: recognition is behind real time. Try
--threads=4(or another suitable value) or--chunk-duration=2s.
Verify changes
go test ./...
go build -o captioneer ./src