Repository navigation
feat(player): add volume control and shortcuts - #31
Merged
Merged
Conversation
Add a speaker button and a volume slider to the player's transport, with ↑/↓ to change the volume by 10% and M to mute. The volume and mute are kept in settings.json and carry over from film to film. ffplay runs without its window and takes its volume only at start, so a new volume restarts the sound at the playhead once the volume has rested for 250 ms, instead of cutting it at every key repeat or slider step.
houko
force-pushed
the
feat/player-volume
branch
from
November 9, 2026 05:58
6e27b89 to
b3b0b10
Compare
- Restart the sound where it has played on to when the app is back from the background, not where the frozen picture stands. - Make the sound for a film that finished opening at the current volume instead of starting it and restarting it at once. - End the sound process while muted instead of playing silence, and start it again on unmute. - Give no sound when afplay, the fallback without ffplay, is asked to start partway, since it can only play from the start; before, a seek or a volume change played the film's start under a later picture. - Keep a volume changed just before quitting, which the 250 ms settle never saved. - Prefix the player-only volume helpers with player, as AGENTS.md asks.
houko
added a commit
that referenced
this pull request
Nov 9, 2026
Resolve the conflict with the volume control (#31). A picture taking over from the background keeps the sound and the volume keep had, and soundAt reads the sound clock through a returning field from the moment the app comes back until the picture takes over or fails, since backgroundAt is cleared then. backgroundResumeAt becomes soundClock. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
↑/↓change the volume by 10%,Mmutes. Each shows an OSD message on the picture (音量 70%,静音). They work as soon as a film is open, and are listed in the cheat sheet and the menu bar.settings.json(volume,mutedinsavedPlayer) and carry over from film to film.How it works
The sound plays through
ffplay -nodisp, which takes its volume only at start (-volume N; theafplayfallback gets-v). A change therefore restarts the sound at the playhead. Changes are debounced by 250 ms, so holding an arrow key or dragging the slider restarts it once when it rests instead of cutting the sound at every step. A held (paused) film drops its prepared sound and starts it at the new volume on play. A film still opening picks up a volume changed meanwhile.Muted with ↑/↓ unmutes from the kept volume;
Mon a volume of 0 brings it back to 50% so it can be heard.While muted (or at 0) there is no sound process at all; unmuting starts one at the playhead. Back from the background, a volume change restarts the sound where it has played on to, not where the paused picture stands. A change made within 250 ms of quitting is still saved.
Behavior change in the fallback: without ffplay the sound plays through
afplay, which cannot start partway into a file. It used to play the film's start under a later picture after any seek; now it gives no sound when asked to start partway (it still plays from 0:00). Homebrew's ffmpeg ships ffplay, so this only affects standalone ffmpeg builds.Screenshots
Playing, controls shown:
Muted with
M(new sceneplayer-muted):Cheat sheet:
Test plan
go vet ./...andgo test ./apps/kando/...pass locally (macOS, with ffmpeg/ffplay)GOOS=windows go vet ./apps/kando(theaudio_stub.gobuild)TestVolumeKeys,TestMuteButtonMutes,TestVolumeSettingsRoundTrip,TestAudioCommandSetsTheVolume,TestHeldFilmStartsAtTheNewVolume,TestAfplayPlaysOnlyFromTheStart,TestMutedFilmHasNoSound,TestQuittingKeepsTheVolume,TestSoundRestartsWhereItPlayedOn