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.
|