PeerSpeak Feature Inventory
A capability list of what PeerSpeak already does, so we don't keep
re-deriving it. This is the user-facing companion to ARCHITECTURE.md (which
covers internals). When you ship a feature, add it here.
Field-test status legend:
- ✅ Verified — confirmed working on a real call (usually desktop ↔ dopedart).
- 🧪 Tests-green — unit-tested and/or smoke-tested locally, but not yet
exercised on a real 2-machine call. Treat as unproven.
- ⚙️ Plumbing — wiring/persistence that has no separate field test of its own.
Rooms & sessions
| Feature |
Status |
Notes |
| Create a room → shareable join ticket |
✅ |
Ticket carries host addr + topic id. |
| Join a room via ticket |
✅ |
Paste ticket on the launch screen. |
| Leave a room |
✅ |
|
| Multi-peer rooms (mesh) |
✅ |
Presence over the iroh gossip plane. |
| Copy ticket to clipboard |
✅ |
Button on the room screen. |
| Remembered nickname |
✅ |
config.username pre-fills the launch field, saved on join/create. |
| In-call duration timer |
✅ |
call_started drives the header clock. |
Audio I/O & codec
| Feature |
Status |
Notes |
| PipeWire capture + playback |
✅ |
src/audio/pipewire_impl.rs. |
| Input device selection |
✅ |
|
| Output device selection |
✅ |
|
| App-internal input (mic) gain slider |
✅ |
Unity default; applied pre-gate/encode. |
| App-internal output gain slider |
✅ |
Unity default; applied on the mixed output. |
| Opus codec |
✅ |
48 kHz mono, Application::Voip, 20 ms / 960-sample frames. |
| Adaptive jitter buffer + Opus PLC |
🧪 |
src/core/jitter.rs; reorders by seq, adaptive playout delay, conceals drops. Not field-tested. |
Voice controls
| Feature |
Status |
Notes |
| Self mute |
✅ |
|
| Deafen |
✅ |
|
| Push-to-talk + rebindable hotkey |
✅ |
TogglePtt / StartSettingHotkey; gate ahead of the encoder. |
| Noise gate (hysteresis + attack/release/hangover) |
✅ |
src/audio/gate.rs. |
| Draggable gate threshold on the mic meter |
✅ |
Discord/OBS-style GateMeter canvas widget. |
| Mic level meter — in-call |
✅ |
|
| Mic level meter — off-call "Test mic" |
✅ |
SetMicMonitor / standalone capture stream. |
| Mix-bus soft limiter |
🧪 |
src/audio/limiter.rs; A/B never confirmed on a real call. |
| Echo cancellation (opt-in) |
🧪 |
src/audio/echo_cancel.rs; PipeWire module-echo-cancel (WebRTC AEC+NS+AGC) via RAII pactl guard. Needs a 2-machine call through speakers, not headphones. |
Per-peer controls
| Feature |
Status |
Notes |
| Per-peer volume |
✅ |
SetPeerVolume. |
| Per-peer local mute |
✅ |
Still decoded (levels show) but not mixed. |
| Per-peer speaking indicator |
✅ |
audio_levels per EndpointId. |
Text chat
| Feature |
Status |
Notes |
| In-room text chat |
🧪 |
Over the gossip plane; full-width bottom-dock UI. 2-machine delivery not confirmed. |
| Outgoing + incoming sanitization |
✅ |
sanitize_chat: strips control chars, collapses whitespace, caps 2000. |
| History cap |
⚙️ |
CHAT_HISTORY_MAX = 300. |
| Local echo of own messages |
✅ |
|
Recording
| Feature |
Status |
Notes |
| Local call recording (mic + incoming mix → WAV) |
🧪 |
src/audio/recorder.rs; writes to ~/peerspeak-recordings/. Solo + 2-machine recording not confirmed. Header REC timer present. |
Notifications & sounds
| Feature |
Status |
Notes |
| Desktop notifications toggle |
✅ |
notifications_enabled. |
| Event chimes |
✅ |
8 events: self-join, peer-join, peer-leave, reconnect-attempt, reconnected, self-leave, mic-toggle, reconnect-failed. |
| Per-event custom sound override |
✅ |
custom_sound_* paths in config. |
Networking & privacy
| Feature |
Status |
Notes |
| iroh QUIC transport |
✅ |
|
| Network mode picker |
✅ |
RelayNoDiscovery (default), N0Full, DirectOnly. Takes effect next join. |
| Retained-address reconnect |
✅ |
Dials last-known full addr before falling back to bare id. |
| Reconnect + eviction model |
✅ |
Incl. two-outage reconnect-eviction fix + regression test. |
| Self-hosted relay |
❌ |
Decided against — rely on n0 relays, RelayNoDiscovery default. |
UI & layout
| Feature |
Status |
Notes |
| Selectable room layouts |
✅ |
3-Column, Bottom Dock (default), Drawer. |
| Layout picker popup w/ canvas thumbnails |
✅ |
LayoutThumb, no image dependency. |
| Draggable + persisted panel dividers |
✅ |
Per-layout, clamped to window; saved on drag-release. |
| Chat drawer toggle (drawer layout) |
🧪 |
Toggle + restart-persistence not explicitly confirmed. |
| Responsive full-window Settings screen |
✅ |
|
Persistence
| Feature |
Status |
Notes |
| Config file |
✅ |
~/.config/peerspeak/config.json. |
| Backward-compatible loading |
✅ |
serde defaults fill missing fields; unknown fields tolerated. |
Known field-test debt (the 🧪 rows above, collected)
Re-run on a real desktop ↔ dopedart call before calling these done:
- Echo cancellation — 2-machine call through speakers (the only path that
actually exercises AEC).
- Mix-bus soft limiter — A/B a hot signal.
- Local call recording — solo + 2-machine, verify the WAV.
- In-room text chat — 2-machine delivery.
- Adaptive jitter buffer — behaviour under real packet loss/jitter.
- Chat drawer — toggle + persistence across restart.
Not built (candidate features)
Things that came up but do not exist yet:
- Soundboard (play short clips into the call mix).
- Video / screen share.
- Invite links beyond the raw ticket / room persistence.