fix: make !volume apply immediately during playback
stream_audio now accepts a callable for volume, re-read on each PCM frame instead of capturing a static float at track start. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -556,8 +556,8 @@ HTML stripped on receive, escaped on send. IRC-only commands are no-ops.
|
||||
!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.
|
||||
Requires: `yt-dlp`, `ffmpeg`, `libopus` on the host.
|
||||
Max 50 tracks in queue. Volume changes take effect immediately.
|
||||
Mumble-only: `!play` replies with error on other adapters, others silently no-op.
|
||||
|
||||
## Plugin Template
|
||||
|
||||
@@ -1576,7 +1576,7 @@ and voice transmission.
|
||||
```
|
||||
|
||||
- Queue holds up to 50 tracks
|
||||
- Volume applies from the next track (default: 50%)
|
||||
- Volume takes effect immediately during playback (default: 50%)
|
||||
- Title resolved via `yt-dlp --get-title` before playback
|
||||
- Audio pipeline: `yt-dlp | ffmpeg` subprocess, PCM fed to pymumble
|
||||
- Commands are Mumble-only; `!play` on other adapters replies with an error,
|
||||
|
||||
@@ -78,10 +78,11 @@ async def _play_loop(bot) -> None:
|
||||
done = asyncio.Event()
|
||||
ps["done_event"] = done
|
||||
|
||||
volume = ps["volume"] / 100.0
|
||||
try:
|
||||
await bot.stream_audio(
|
||||
track.url, volume=volume, on_done=done,
|
||||
track.url,
|
||||
volume=lambda: ps["volume"] / 100.0,
|
||||
on_done=done,
|
||||
)
|
||||
except asyncio.CancelledError:
|
||||
raise
|
||||
@@ -269,7 +270,7 @@ async def cmd_volume(bot, message):
|
||||
|
||||
Usage:
|
||||
!volume Show current volume
|
||||
!volume <0-100> Set volume (applies on next track)
|
||||
!volume <0-100> Set volume (takes effect immediately)
|
||||
"""
|
||||
if not _is_mumble(bot):
|
||||
return
|
||||
|
||||
@@ -421,7 +421,7 @@ class MumbleBot:
|
||||
self,
|
||||
url: str,
|
||||
*,
|
||||
volume: float = 0.5,
|
||||
volume=0.5,
|
||||
on_done=None,
|
||||
) -> None:
|
||||
"""Stream audio from URL through yt-dlp|ffmpeg to voice channel.
|
||||
@@ -432,12 +432,16 @@ class MumbleBot:
|
||||
|
||||
Feeds raw PCM to pymumble's sound_output which handles Opus
|
||||
encoding, packetization, and timing.
|
||||
|
||||
``volume`` may be a float (static) or a callable returning float
|
||||
(dynamic, re-read each frame).
|
||||
"""
|
||||
if self._mumble is None:
|
||||
return
|
||||
|
||||
_get_vol = volume if callable(volume) else lambda: volume
|
||||
log.info("stream_audio: starting pipeline for %s (vol=%.0f%%)",
|
||||
url, volume * 100)
|
||||
url, _get_vol() * 100)
|
||||
|
||||
proc = await asyncio.create_subprocess_exec(
|
||||
"sh", "-c",
|
||||
@@ -457,8 +461,9 @@ class MumbleBot:
|
||||
if len(pcm) < _FRAME_BYTES:
|
||||
pcm += b"\x00" * (_FRAME_BYTES - len(pcm))
|
||||
|
||||
if volume != 1.0:
|
||||
pcm = _scale_pcm(pcm, volume)
|
||||
vol = _get_vol()
|
||||
if vol != 1.0:
|
||||
pcm = _scale_pcm(pcm, vol)
|
||||
|
||||
self._mumble.sound_output.add_sound(pcm)
|
||||
frames += 1
|
||||
|
||||
Reference in New Issue
Block a user