feat: download audio before playback, add !keep and !kept commands

Audio is now downloaded to data/music/ before playback begins,
eliminating CDN hiccups mid-stream. Falls back to streaming on
download failure. Files are deleted after playback unless marked
with !keep. stream_audio detects local files and uses a direct
ffmpeg pipeline (no yt-dlp).
This commit is contained in:
user
2026-02-22 02:52:51 +01:00
parent ab924444de
commit df20c154ca
4 changed files with 316 additions and 6 deletions

View File

@@ -1574,6 +1574,8 @@ and voice transmission.
!queue <url> Add to queue (alias for !play)
!np Now playing
!volume [0-100] Get/set volume
!keep Keep current track's audio file after playback
!kept [clear] List kept files or clear all
!testtone Play 3-second 440Hz test tone
```
@@ -1585,7 +1587,11 @@ and voice transmission.
- Volume changes ramp smoothly over ~1s (no abrupt jumps)
- Default volume: 50%
- Titles resolved via `yt-dlp --flat-playlist` before playback
- Audio pipeline: `yt-dlp | ffmpeg` subprocess, PCM fed to pymumble
- Audio is downloaded before playback (`data/music/`); files are deleted
after playback unless `!keep` is used. Falls back to streaming on
download failure.
- Audio pipeline: `ffmpeg` subprocess for local files, `yt-dlp | ffmpeg`
for streaming fallback, PCM fed to pymumble
- 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
@@ -1657,3 +1663,17 @@ duck_floor = 1 # Floor volume % during ducking (default: 1)
duck_silence = 15 # Seconds of silence before restoring (default: 15)
duck_restore = 30 # Seconds for smooth volume restore (default: 30)
```
### Download-First Playback
Audio is downloaded to `data/music/` before playback begins. This
eliminates CDN hiccups mid-stream and enables instant seeking. Files
are identified by a hash of the URL so the same URL reuses the same
file (natural dedup).
- If download fails, playback falls back to streaming (`yt-dlp | ffmpeg`)
- After a track finishes, the local file is automatically deleted
- Use `!keep` during playback to preserve the file
- Use `!kept` to list preserved files and their sizes
- Use `!kept clear` to delete all preserved files
- On cancel/error, files are not deleted (needed for `!resume`)