feat: Shazam-based track identification#1
Open
MWhyte wants to merge 4 commits into
Open
Conversation
Adds an `i` keybinding that captures ~12s of audio from the playing stream, fingerprints it locally in pure Go, and queries Shazam's recognition endpoint. Results appear in a modal with title/artist/album and an `o` shortcut to open the canonical Shazam page in the default browser. Completely free, no API key required. The fingerprinting algorithm is vendored from lukechampine/barbershop (MIT, attribution preserved in pkg/identifier/shazam/LICENSE) and runs against the same `amp.shazam.com/discovery` endpoint Shazam's mobile client uses. Audio is captured via a parallel HTTP read of the stream URL, MP3-decoded with hajimehoshi/go-mp3, frame-synced to recover from mid-stream connects, downmixed to mono and resampled to 16 kHz before fingerprinting. Includes `cmd/test-shazam` for diagnosing streams from the CLI. Pipeline is MP3-only; AAC/Ogg streams short-circuit with a friendly error. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
golangci-lint v2.12.2 (latest, used by CI) tightened goconst's duplication detection and flags "command" (5 uses) and "set_property" (3 uses) in pkg/player/player.go. Local lint at v2.11.4 didn't. Extracts both into named constants alongside the rest of the mpv IPC protocol layer. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`version: latest` makes CI fail unpredictably whenever golangci-lint ships a release with stricter defaults — exactly what happened on PR #1 (v2.12.2 added new goconst occurrences). Pin to v2.12.2 (the current latest, matching local installs via brew) so version bumps are deliberate, surfaced as PRs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- README: new feature bullet, dedicated section with gif, and i/o keyboard shortcuts in the controls table - Website: new feature card and showcase entry on docs/index.html - New asset: docs/assets/identify.gif (recorded via asciinema, .cast preserved alongside the other showcase casts) Ordered after Favourites in both surfaces to match the existing showcase flow. Co-Authored-By: Claude Opus 4.7 <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
ikeybinding identifies the playing track via Shazam's reverse-engineered recognition endpoint — pure Go, no API key, no third-party service. The fingerprint algorithm is vendored from lukechampine/barbershop (MIT, attribution preserved inpkg/identifier/shazam/LICENSE).amp.shazam.com/discovery/v5→ modal renders title/artist/album/year withoto openhttps://www.shazam.com/track/<key>in the default browser.Content-Typewith a friendly "Sorry, only MP3 streams are currently supported" message instead of a confusing decoder error.cmd/test-shazamstandalone CLI included for diagnosing streams without booting the TUI — prints sample count, sample rate, capture wall time and Shazam round-trip, then the identified track.How it works
iwhile a station is playing.oopens it on shazam.com,enter/escdismisses.escmid-spinner aborts the in-flight request, MP3 decode, and rate-limiter wait cleanly viacontext.CancelFunc.Test plan
make fmt,make build,make lintall clean (0 lint issues across the strict golangci-lint v2 ruleset)go vet ./...cleango test ./...passes (fingerprint hashes match upstream)ion a playing MP3 station in./rig→ modal shows correct title/artist within ~15so→ default browser opens the Shazam track pageescmid-spinner → cancels (no zombie goroutine, no extra network use)🤖 Generated with Claude Code