a1df9d4037
- 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
160 lines
8.4 KiB
Markdown
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.
|