Skip to content

Duck Spotify volume while speaking instead of talking over it - #10

Merged
malpern merged 1 commit into
mainfrom
spotify-ducking
Jul 25, 2026
Merged

Duck Spotify volume while speaking instead of talking over it#10
malpern merged 1 commit into
mainfrom
spotify-ducking

Conversation

@malpern

@malpern malpern commented Jul 25, 2026

Copy link
Copy Markdown
Owner

What

The extension already paused YouTube while VoxClaw spoke, but Spotify web playback was left at full volume, so speech competed with the music. This fades playing open.spotify.com tabs down to 20% for the duration of the speech, then restores each tab's original volume (300ms down, 500ms up). YouTube's pause/resume behavior is unchanged.

Notes

  • Restore is held 1.5s (RESTORE_HOLD_MS). /status reports reading:false during the speech queue's 1s inter-item gap, so without the hold the volume yo-yos between queued utterances.
  • Volume is also restored if the VoxClaw listener disappears mid-speech or polling is toggled off, so a tab is never left stuck quiet.
  • Each tab's original volume is preserved per-tab; tabs already at or below the duck level are left alone.
  • Ducking moves Spotify's own volume slider, since that slider reads element.volume — the dip is visible in the UI, not just audible.
  • Tunables are the four constants at the top of service_worker.js.

Verification

  • Fade math simulated against a stepped requestAnimationFrame clock: ducks to exactly 0.2, restores to the original 0.85, and skips elements already quieter than the duck level.
  • Probed Spotify's real DOM via an instrumented build: the player is a media element in the main document (shallow=1, deep=1, readyState=4), so querySelectorAll("video, audio") reaches it with no shadow-DOM traversal.
  • Installed unpacked in Dia (Chromium 150) and confirmed the service worker polls /status at a steady 1Hz against a running VoxClaw.
  • Not exercised: the !media.paused gate, i.e. ducking during actual playback.

🤖 Generated with Claude Code

The extension already paused YouTube while VoxClaw spoke, but Spotify web
playback was left at full volume, so speech competed with music. Fade
playing open.spotify.com tabs down to 20% for the duration of the speech
and restore each tab's original volume afterward.

Restore is held 1.5s because /status reports reading:false during the
speech queue's 1s inter-item gap; without the hold, volume yo-yos between
queued utterances. Volume is also restored if the listener disappears or
polling is turned off, so tabs are never left stuck quiet.

Verified on Spotify's real DOM: the player is a media element in the main
document (readyState 4), so querySelectorAll reaches it without shadow-DOM
traversal.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@malpern
malpern merged commit a68c262 into main Jul 25, 2026
2 checks passed
@malpern
malpern deleted the spotify-ducking branch July 25, 2026 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant