diff --git a/TASKS.md b/TASKS.md index 9528ff3..17e8f9c 100644 --- a/TASKS.md +++ b/TASKS.md @@ -1,6 +1,16 @@ # derp - Tasks -## Current Sprint -- v2.2.0 Configurable Proxy (2026-02-21) +## Current Sprint -- v2.3.0 Mumble Music Playback (2026-02-21) + +| Pri | Status | Task | +|-----|--------|------| +| P0 | [x] | `src/derp/opus.py` -- ctypes libopus encoder (zero Python deps) | +| P0 | [x] | `src/derp/mumble.py` -- voice varint, voice packet, PCM scaling, stream_audio | +| P0 | [x] | `plugins/music.py` -- play/stop/skip/queue/np/volume commands | +| P1 | [x] | Tests: `test_opus.py`, `test_mumble.py` voice additions, `test_music.py` | +| P2 | [x] | Documentation update (USAGE.md, CHEATSHEET.md) | + +## Previous Sprint -- v2.2.0 Configurable Proxy (2026-02-21) | Pri | Status | Task | |-----|--------|------| diff --git a/docs/CHEATSHEET.md b/docs/CHEATSHEET.md index 52be18a..9dad945 100644 --- a/docs/CHEATSHEET.md +++ b/docs/CHEATSHEET.md @@ -540,10 +540,27 @@ operators = [] trusted = [] ``` -TCP/TLS via SOCKS5 proxy by default (`proxy = true`). Text chat only (no voice). Minimal protobuf +TCP/TLS via SOCKS5 proxy by default (`proxy = true`). Minimal protobuf codec (no external dep). HTML stripped on receive, escaped on send. IRC-only commands are no-ops. ~90% of plugins work. +## Music (Mumble only) + +``` +!play # Play audio (YouTube, SoundCloud, etc.) +!stop # Stop playback, clear queue +!skip # Skip current track +!queue # Show queue +!queue # Add to queue (alias for !play) +!np # Now playing +!volume # Show current volume +!volume 75 # Set volume (0-100, default 50) +``` + +Requires: `yt-dlp`, `ffmpeg`, `libopus.so.0` on the host. +Max 50 tracks in queue. Volume applies on next track. +Mumble-only: `!play` replies with error on other adapters, others silently no-op. + ## Plugin Template ```python diff --git a/docs/USAGE.md b/docs/USAGE.md index 4479631..03846bf 100644 --- a/docs/USAGE.md +++ b/docs/USAGE.md @@ -1553,6 +1553,36 @@ Mumble uses HTML for text messages. On receive, the bot strips tags and unescapes entities. On send, text is HTML-escaped. Action messages use `` tags for italic formatting. +### Music Playback + +Stream audio from YouTube, SoundCloud, and other yt-dlp-supported sites +into the Mumble voice channel. Audio is decoded to PCM, encoded to Opus +via system libopus, and transmitted as voice packets over the TCP tunnel. + +**System dependencies** (must be installed on the host): +- `yt-dlp` -- audio stream extraction +- `ffmpeg` -- decode to 48kHz mono s16le PCM +- `libopus.so.0` -- Opus codec (ctypes, no Python binding) + +``` +!play Play audio or add to queue +!stop Stop playback, clear queue +!skip Skip current track +!queue Show queue +!queue Add to queue (alias for !play) +!np Now playing +!volume [0-100] Get/set volume +``` + +- Queue holds up to 50 tracks +- Volume applies from the next track (default: 50%) +- Title resolved via `yt-dlp --get-title` before playback +- Audio pipeline: `yt-dlp | ffmpeg` subprocess, 20ms Opus frames +- Commands are Mumble-only; `!play` on other adapters replies with an error, + other music commands silently no-op +- Playback runs as an asyncio background task; the bot remains responsive + to text commands during streaming + ### Transport TCP connections route through the SOCKS5 proxy at `127.0.0.1:1080`