Summary
Changing an audio effect mid-song restarts that song from 0:00. If you are four minutes into a track and type !bassboost, you lose your place.
Why it happens
An FFmpeg filter chain is fixed for the lifetime of the process, so changing it requires respawning FFmpeg. MusicPlayer.apply_effect() handles that by setting _replay = True and calling vc.stop(), and the player loop then re-spawns the stream with the new -af value — from the start of the track.
MusicPlayer._start_ts already records when the current track began (monotonic clock) and is currently only used for the sub-2-second "failed to load" heuristic. The elapsed position is therefore already available; it is just not used to seek.
Proposal
On a _replay, seek the new FFmpeg process to the elapsed position with -ss, so the effect appears to apply in place.
Points to settle during implementation:
-ss must go in FFmpeg's input options (before_options), not options, to seek cheaply.
- Elapsed time must account for any time spent paused, which
_start_ts does not currently track.
- Live streams (no duration) must not be seeked.
- Seeking a piped stdin stream is not free — verify how it behaves versus letting yt-dlp do the seeking.
Acceptance
!bassboost four minutes into a track resumes within ~1s of 4:00, not at 0:00.
!reset behaves the same way.
- Live streams still work and are not seeked.
- Rapid effect toggling stays throttled by the existing 3s per-guild cooldown.
Affected code
utils/player.py — apply_effect(), _player_loop(), _advance(), _start_ts
services/media.py — spawn_stream(), make_pipe_source()
Summary
Changing an audio effect mid-song restarts that song from 0:00. If you are four minutes into a track and type
!bassboost, you lose your place.Why it happens
An FFmpeg filter chain is fixed for the lifetime of the process, so changing it requires respawning FFmpeg.
MusicPlayer.apply_effect()handles that by setting_replay = Trueand callingvc.stop(), and the player loop then re-spawns the stream with the new-afvalue — from the start of the track.MusicPlayer._start_tsalready records when the current track began (monotonic clock) and is currently only used for the sub-2-second "failed to load" heuristic. The elapsed position is therefore already available; it is just not used to seek.Proposal
On a
_replay, seek the new FFmpeg process to the elapsed position with-ss, so the effect appears to apply in place.Points to settle during implementation:
-ssmust go in FFmpeg's input options (before_options), notoptions, to seek cheaply._start_tsdoes not currently track.Acceptance
!bassboostfour minutes into a track resumes within ~1s of 4:00, not at 0:00.!resetbehaves the same way.Affected code
utils/player.py—apply_effect(),_player_loop(),_advance(),_start_tsservices/media.py—spawn_stream(),make_pipe_source()