aboutsummaryrefslogtreecommitdiffstats
path: root/CONTEXT.md
blob: 5a992ec343fa70705cd118aef4ed304f0f9a8bbc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# CONTEXT

Glossary of terms used in this codebase. This file is a glossary only — it
holds no implementation decisions or specs (those live in `docs/adr/`).

## Voice

- **Voice activity** — per-user join / leave / AFK *timing metadata*, persisted
  in the `voice_activity` table and updated by `events::handle_voice_state_update`.
  Despite the name, it contains **no audio** — only timestamps and durations.
- **Recording** — capturing the *audio* of a voice channel into a rolling
  in-memory buffer while the bot is connected. Distinct from *voice activity*
  (metadata). Recording is opt-in via `RECORDING_ENABLED` (default false); when
  enabled a bot records continuously while in a VC and "flushes" on `/record`.
- **Window** — the retention horizon of the recording buffer: how many seconds
  of the recent past are kept. Older audio is discarded as new audio arrives.
  Configured via `RECORDING_WINDOW_SECONDS` (default 900 = 15 minutes).
- **Flush** — the `/record` action: snapshot the current recording buffer to an
  mp3 and upload it to Copyparty. Non-destructive — the buffer keeps recording
  after a flush, so successive calls may overlap.

## Stats & Leaderboard

- **User stats** — cumulative per-user counters (message count, total voice
  active time, total voice AFK time) stored in the `user_stats` table. Persists
  across restarts. Distinct from *voice activity* which is session-scoped.
- **Voice activity** (session) — per-session timing metadata (join time, current
  active/AFK durations, is_afk flag). Resets when user joins VC. Used for
  real-time status, not leaderboard rankings.
- **Leaderboard** — `/leaderboard` command group showing ranked user stats.
  Metrics: `messages`, `active` (voice), `afk` (voice), `total` (voice active +
  afk). Paged at 10 entries, descending by default.
- **Tracked guild** — the guild containing `status_channel_id`. Message counts
  are only tracked in this guild.

## TTS

- **Synthesize** — convert text to audio via local Piper TTS (ONNX model
  loaded in-process via `piper-rs`). No external fallback. Output is f32 PCM
  at the model's native sample rate (typically 22050 Hz mono), resampled to
  48 kHz stereo via inline linear interpolation before playback. Songbird does
  not resample — playing un-resampled audio results in wrong playback speed.
- **TtsState** — struct held in poise `Data`: `OnceLock<Arc<std::sync::Mutex<Piper>>>`
  for the model instance, `DashMap<String, (Vec<u8>, Instant)>` for the
  text→audio cache. Piper is loaded lazily on first TTS call, off the async
  runtime. Cache is keyed by the full phrase, bounded by entries/bytes, and
  evicted by TTL. No external TTS fallback.
- **Pre-generation** — on first voice event for a user, synthesize all 6 event
  phrases (join/leave/deafen/undeafen/mute/unmute) with their display name and
  cache them. ~120ms first time, instant after. Lazy — no startup cost.

## Music Playback

- **Queue** — per-guild, in-memory list of tracks waiting to play. Lost on
  restart. `/music queue` shows the current track first, then the pending
  items in play order.
- **Position** — where `/music grajcuj` inserts a track: `now` interrupts the
  current track, `next` inserts after it, `last` appends (default). When
  nothing is playing, every position starts playback immediately.
- **Skip** — stop the current track and play the next queued one. With an
  empty queue, playback stops but the bot stays in the voice channel.
- **Auto-advance** — when a track ends (or errors), the next queued track is
  started automatically and announced in the channel.
- **Compressed playback** — `/music grajcuj ... compressed`: downloads audio, runs
  through the /compress pipeline (Opus 500bps, 12 kHz, mono → OGG), then
  decodes the compressed file via symphonia for playback. Produces properly
  destroyed audio via Opus codec, not just raw low-sample-rate PCM.