92 lines
4.5 KiB
Markdown
92 lines
4.5 KiB
Markdown
# Nat20 Notes
|
|
|
|
Turn a recorded tabletop RPG session (audio or video) into two documents:
|
|
a full GM/DM session log, and a spoiler-free player recap — using local
|
|
transcription (WhisperX) and either a local LLM (Ollama) or any
|
|
OpenAI-compatible hosted API for summarization.
|
|
|
|
## Requirements
|
|
|
|
- Docker + Docker Compose
|
|
- An NVIDIA GPU with drivers + [NVIDIA Container Toolkit](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html) installed on the host (for transcription; CPU-only works but is much slower)
|
|
- A free [HuggingFace token](https://huggingface.co/settings/tokens) — needed for speaker diarization. You'll also need to accept the terms on the gated pyannote model page it links you to on first run.
|
|
- Either: [Ollama](https://ollama.com) running somewhere reachable from this app (local or LAN), **or** an API key for a hosted LLM (OpenAI, or any OpenAI-compatible provider)
|
|
|
|
## Quick start
|
|
|
|
```bash
|
|
git clone <this-repo>
|
|
cd nat20-notes
|
|
# Review docker-compose.yml — see Configuration below for env vars
|
|
docker compose up -d --build
|
|
```
|
|
|
|
Then open `http://<your-server>:8020` (yes, that port's a nod to the d20) and follow the setup wizard:
|
|
|
|
1. Choose a Whisper model size based on your GPU's available VRAM (guidance shown in-app)
|
|
2. Choose local Ollama or a hosted API for summarization, and paste your HF token
|
|
3. Optionally paste campaign/world context (NPC names, places) so summaries recognize them correctly
|
|
|
|
A reference compose file using named volumes only (no host paths) is at
|
|
[`docker-compose.example.yml`](./docker-compose.example.yml).
|
|
|
|
## Using it
|
|
|
|
1. **Upload** a recording (audio or video — video is auto-converted, audio-only files skip that step and are much faster). Files over **90 MB** are auto-chunked with 3-way concurrent uploads.
|
|
2. **Transcribe** — runs in the background. On completion you're **automatically taken** to the speaker-naming screen.
|
|
3. **Name your speakers** — a waveform-style "session reel" shows each detected speaker's segments; click any point to jump the audio there and hear who's talking, then type in their name. Use the checkboxes to **merge** speakers (e.g. when diarization over-splits one person into `SPEAKER_00`, `SPEAKER_05`, etc.).
|
|
4. **Generate notes** — click "Done naming" and confirm; notes generation starts automatically and you're taken to the job progress screen. When finished, navigate to the notes viewer.
|
|
5. **Review & tweak** — regenerate notes, rename speakers, or delete jobs/sessions from the session detail page.
|
|
|
|
## Data layout
|
|
|
|
The app stores everything under `/data` (inside the container), which by default
|
|
is a [bind mount](./docker-compose.yml) to a host path of your choice:
|
|
|
|
| Directory / File | Contents |
|
|
|---|---|
|
|
| `audio/` | Uploaded recordings and extracted audio |
|
|
| `transcriptions/` | Per-session transcript JSON files |
|
|
| `notes/` | Generated notes (GM log + player recap) |
|
|
| `app.db` | SQLite database (sessions, speakers, settings, jobs) |
|
|
|
|
## Configuration
|
|
|
|
### Prefilling the setup wizard
|
|
|
|
Set `NAT20_*` environment variables under the `backend` service in
|
|
`docker-compose.yml` — the wizard will pick them up as defaults:
|
|
|
|
```yaml
|
|
environment:
|
|
NAT20_HF_TOKEN: "hf_..."
|
|
NAT20_WHISPER_MODEL: medium
|
|
NAT20_OLLAMA_HOST: http://localhost:11434
|
|
NAT20_WORLD_CONTEXT_PATH: /data/campaign-context.txt
|
|
```
|
|
|
|
See the `environment:` block in `docker-compose.yml` for the full list.
|
|
|
|
### Campaign context
|
|
|
|
You can paste context directly in the Settings page, or point to a file
|
|
inside the container using the `world_context_path` setting (or the
|
|
`NAT20_WORLD_CONTEXT_PATH` env var). The file path version is useful for
|
|
large campaign bibles that you update independently.
|
|
|
|
## Notes on hardware
|
|
|
|
Transcription is GPU-bound and by far the slowest step for long sessions.
|
|
Summarization is comparatively light — a 7-8B parameter local model is
|
|
sufficient for most groups; only step up in size if you have the VRAM
|
|
headroom after Whisper's footprint (they don't run at the same time, so
|
|
you only need enough VRAM for whichever is currently running, plus normal
|
|
system overhead from other GPU-using services).
|
|
|
|
## Architecture
|
|
|
|
- `backend/` — FastAPI, SQLite (no external DB needed), WhisperX as a library (no nested Docker), in-process `ThreadPoolExecutor` background jobs (no Redis/Celery)
|
|
- `frontend/` — React 18 + Vite + Tailwind, served via nginx (listens on port **8020**) which proxies `/api` to the backend
|
|
|
|
Both run as standard Docker Compose services — no special orchestration needed beyond GPU passthrough for the backend.
|