Files
meetrec/README.md
T
fegger a1df9d4037 Add whisper-server engine: transcribe on a remote whisper.cpp server
- WhisperServerEngine posts multipart/form-data to POST /inference
  (verbose_json) with the same transcribe() contract as the other
  engines, so live and final passes work unchanged; stdlib-only
  multipart builder; HTTP and connection errors surface clean messages
- CLI: --engine whisper-server + --server-url (or MEETREC_SERVER_URL)
- GUI: engine dropdown gains whisper-server; model/device/compute grey
  out (the server owns the model), new Server URL field
- model lives server-side, beam size is a server-start setting in
  whisper.cpp v1.9.3 (documented); verbose_json reports language names
  (german) rather than ISO codes
- validated against the live R9700 server over Tailscale: array input,
  native-rate file input (server-side resample), full final_transcribe
  pipeline, and unreachable-server handling
2026-09-07 12:59:14 +02:00

160 lines
8.4 KiB
Markdown

# MeetRec
Record an in-person meeting and transcribe it with [Whisper](https://github.com/SYSTRAN/faster-whisper).
Meetrec captures audio from any input (microphone, USB conference mic, USB audio interface, or a Pulse/PipeWire sink *monitor*) and produces transcripts in `txt`, `srt`, and `json`. It runs fully locally — no audio ever leaves your machine.
Two desktop interfaces plus an Android app:
- **`meetrec.py`** — CLI: record, optionally show a live rolling transcript, and on `Ctrl+C` run a final higher-quality pass.
- **`meetrec_gui.py`** — Qt (PySide6) GUI: device/model/language selection, level meter, live transcript, and one-click *Stop & transcribe*.
- **`android/`** — native Kotlin app with the same on-device functionality, built on whisper.cpp via JNI (see `android/README.md`).
## Output files
With output stem `-o meeting`:
| File | Contents |
| ------------------ | ----------------------------------------------- |
| `meeting.wav` | raw recording (mono WAV at the input's native rate) |
| `meeting.live.srt` | live rolling transcript (only with `--live > 0`) |
| `meeting.txt` | final transcript |
| `meeting.srt` | final transcript with timestamps |
| `meeting.json` | final transcript, structured (language, segments) |
Recording always uses the input device's native sample rate; audio is resampled to Whisper's 16 kHz automatically (both for the live window and the final pass).
## Requirements
- Linux with an audio backend: **PipeWire** (or PulseAudio/ALSA). On Arch: `sudo pacman -S pipewire pipewire-pulse`
- **Python 3.10+**
- Python packages (installed for you by the install script): `numpy`, `sounddevice`, `faster-whisper`, `pyside6` (GUI only)
- A GPU (CUDA) is optional — transcription falls back to CPU.
## Installation
### Quick install
```sh
./install.sh
```
This:
1. copies the app to `~/.local/share/meetrec`,
2. creates a venv and installs all dependencies,
3. installs the `meetrec` (GUI) and `meetrec-cli` launchers into `~/.local/bin`,
4. installs the XDG desktop entry and icon (app menu shows **MeetRec** with its own red mic icon),
5. pre-downloads the `small` Whisper model (first run is otherwise slow).
Options:
```sh
./install.sh --model base # pre-download a different model (tiny/base/small/medium/large-v3)
./install.sh --whisper-cpp # also build whisper.cpp with its Vulkan GPU backend
./install.sh --no-model # skip the model pre-download
./install.sh --uninstall # remove everything the installer created
PREFIX=/opt/meetrec ./install.sh # install into a different prefix
```
On an **AMD GPU** (e.g. Ryzen AI 300 laptops with a Radeon iGPU), use `--whisper-cpp` and select the `whisper-cpp` engine — see [Engines](#engines) below. The build needs `git`, `cmake`, `g++`, and Vulkan headers (`sudo pacman -S vulkan-headers` on Arch).
### Manual install (venv)
```sh
sudo pacman -S python pipewire pipewire-pulse
python3 -m venv .venv && source .venv/bin/activate
pip install numpy sounddevice faster-whisper pyside6
```
## Usage
### GUI
```sh
meetrec # after ./install.sh
# or from a checkout:
python meetrec_gui.py
```
Pick a microphone (or type a name substring), model, language, and compute device/precision (switching model, device, or precision between recordings reloads the model automatically), press **Record**, watch the live transcript, then press **Stop & transcribe**.
### CLI
```sh
meetrec-cli --list-sources # find your input devices
meetrec-cli -s "Conference Mic" --model small --live 8 -o meeting
meetrec-cli -s monitor --model base --language en # record system audio
meetrec-cli --engine whisper-cpp -o meeting # transcribe on the GPU (Vulkan)
MEETREC_SERVER_URL=http://100.103.83.12:8085 \
meetrec-cli --engine whisper-server -o meeting # transcribe on a remote server
python meetrec.py --help # all options
```
Key options:
| Option | Meaning |
| --------------- | ---------------------------------------------------------------- |
| `--engine` | transcription backend: `faster-whisper` (default), `whisper-cpp`, or `whisper-server` |
| `--server-url` | whisper-server base URL, e.g. `http://100.103.83.12:8085` (or `MEETREC_SERVER_URL`) |
| `-s, --source` | `default` or a substring of a device name (`--list-sources`) |
| `-m, --model` | `tiny` / `base` / `small` / `medium` / `large-v3` (default `small`) |
| `-o, --output` | output file stem (default `meeting`) |
| `--live SEC` | live-transcription interval in seconds; `0` disables (default 8) |
| `--language` | force a language code, e.g. `en`, `de` (default: autodetect) |
| `--device` | `auto` / `cpu` / `cuda` (default `auto`); faster-whisper only |
| `--compute-type`| `int8` / `int8_float16` / `float16` / `float32` (default `int8`); faster-whisper only |
`Ctrl+C` stops recording and runs the final transcription.
### Tips
- **Record system audio**: sink monitors appear as `<sink name>.monitor`; use `-s monitor` (or a matching substring).
- **Model size vs. speed/accuracy**: `tiny`/`base` are fast and rough, `small` is a good default, `medium`/`large-v3` are most accurate but much slower on CPU.
- Models are cached in `~/.cache/huggingface` (faster-whisper) and `~/.cache/meetrec/whisper-cpp` (whisper.cpp) and shared between the CLI and the GUI.
## Engines
Meetrec supports two interchangeable transcription backends — `--engine` on the CLI, the **Engine** dropdown in the GUI:
| Engine | Backend | GPU support |
| ------ | ------- | ----------- |
| `faster-whisper` (default) | CTranslate2 | NVIDIA CUDA (`--device cuda`); otherwise CPU |
| `whisper-cpp` | [whisper.cpp](https://github.com/ggml-org/whisper.cpp) | **AMD / Intel / NVIDIA via Vulkan**; falls back to CPU |
| `whisper-server` | remote whisper.cpp HTTP server | whatever the server has — see [server/whisper-server/](server/whisper-server/) (Docker Compose, Vulkan GPU, Tailscale) |
On AMD hardware (e.g. the Radeon iGPU in Ryzen AI 300 laptops) the `faster-whisper` path is CPU-only — use the `whisper-cpp` engine there, which runs on the GPU when whisper.cpp is built with `-DWHISPER_VULKAN=ON` (`./install.sh --whisper-cpp` does this for you). The `whisper-server` engine moves the work to a server entirely (ideal for slow clients such as phones) and can run `large-v3` on a GPU.
Notes on `whisper-cpp`:
- The `whisper-cli` binary is looked up in `WHISPER_CPP_BIN`, then `PATH`, then `~/.local/share/meetrec/whisper-cpp/bin/whisper-cli` (where `install.sh --whisper-cpp` puts it).
- GGML models (`ggml-*.bin`) download automatically to `~/.cache/meetrec/whisper-cpp` on first use.
- VAD works like on faster-whisper: whisper.cpp's Silero VAD model (~1 MB) downloads automatically and is used for both live and final passes.
- Live mode spawns `whisper-cli` for every rolling-window pass, so the GGML model is reloaded on each live tick — slightly heavier than faster-whisper, which loads once per recording.
Notes on `whisper-server`:
- The model lives on the server — `--model`, `--device`, `--compute-type` do not apply; beam size is a server-start setting in whisper.cpp v1.9.3 (no per-request override).
- Run your own with the Docker Compose stack in `server/whisper-server/` — Vulkan GPU (AMD/NVIDIA/Intel), model auto-download, Tailscale-only binding.
- The server has no authentication: keep it on Tailscale or behind a VPN/firewall.
- `verbose_json` reports language names ("german") rather than ISO codes.
- `--device` / `--compute-type` do not apply (GPU vs. CPU is decided by the whisper.cpp build).
## Project layout
```
meetrec.py CLI: recording + live & final transcription
meetrec_gui.py PySide6 GUI (reuses meetrec.py's logic)
requirements.txt Python dependencies
install.sh install / uninstall into a local prefix
bin/meetrec GUI launcher (installed into ~/.local/bin)
bin/meetrec-cli CLI launcher (installed into ~/.local/bin)
share/applications/meetrec.desktop XDG desktop entry
share/icons/hicolor/ app icon (SVG + PNG fallbacks)
android/ native Android app (Kotlin + whisper.cpp JNI)
```
## Privacy
Everything runs locally. The only network access is the one-time Whisper model download from Hugging Face.