Files
Captioneer/README.md
T

120 lines
4.1 KiB
Markdown
Raw Normal View History

# 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
- `pactl` and `parec` available on `PATH` (on Debian/Ubuntu: `sudo apt install pulseaudio-utils`)
- `curl` and `tar` to 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:
```bash
pactl get-default-sink
```
## Setup
Clone the project, then download the required models once:
```bash
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:
```bash
go run ./src/cmd/captioneer --mode=vad
```
Use fixed mode to decode exact time slices, even through silence:
```bash
go run ./src/cmd/captioneer --mode=fixed --chunk-duration=1s
```
Build a reusable executable instead of using `go run`:
```bash
go build -o captioneer ./src/cmd/captioneer
./captioneer --mode=vad
```
Press <kbd>Ctrl</kbd>+<kbd>C</kbd> 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:
```bash
# Faster fixed chunks
go run ./src/cmd/captioneer --mode=fixed --chunk-duration=500ms
# Fewer VAD preview redraws and four CPU threads
go run ./src/cmd/captioneer --mode=vad --chunk-duration=2s --threads=4
# Store or reuse models outside this repository
go run ./src/cmd/captioneer --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/` as focused packages:
- `cmd/captioneer` is the executable entrypoint.
- `config` defines command-line options.
- `audio` contains PCM conversion and audio calculations.
- `capture` reads the default system-audio monitor.
- `models` owns Parakeet and Silero model resources.
- `captions` handles fixed chunks, VAD segments, and terminal output.
## Output and troubleshooting
Final captions go to standard output in this form:
```text
[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:
```bash
go run ./src/cmd/captioneer --mode=vad > captions.txt
```
- **Missing model files:** run `./scripts/download-models.sh` again.
- **`pactl` or `parec` not found:** install `pulseaudio-utils` and 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 `.monitor` source.
- **Overload warning:** recognition is behind real time. Try `--threads=4` (or another suitable value) or `--chunk-duration=2s`.
## Verify changes
```bash
go test ./...
go build -o captioneer ./src/cmd/captioneer
```