Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,21 @@ Validated audio pipeline · Multi-backend matching · Flask web UI · Terminal o
***
<div align="center">
<h1 style="margin:0;padding:0">Audio Recognition</h1>
<p style="margin:4px 0 8px;color:#1E90FF">Identify songs from your microphone or an audio file with validated multi-backend matching</p>
<p style="margin:4px 0 8px;color:#e35c43">Identify songs from your microphone or an audio file with validated multi-backend matching</p>
</div>

## Overview
DIY Shazam captures audio from the CLI microphone/file path or the Flask browser UI, normalizes it through one bounded audio pipeline, and identifies tracks using RapidAPI/Shazam, AcoustID, AudD, or local spectrogram peaks and constellation hash pairs. FFT output is a diagnostic visualization only; it is not the recognition algorithm. Flask serves the complete browser UI and JSON API from one origin.

The supported web experience is a focused, local-first showcase MVP: a microphone-first recognition flow, a supported upload path, readable runtime diagnostics, recovery-oriented result states, and optional session-only history. Authentication, persistent history, a public deployment, and real-world accuracy claims remain explicit follow-on work rather than implied features.

## Implemented

- Flask is the supported browser application; `web/app.py` serves the UI and JSON API from one origin.
- CLI and web inputs use the documented bounded normalization pipeline. The CLI accepts WAV/PCM; the web path converts the documented browser upload formats through FFmpeg.
- Provider dispatch uses RapidAPI/Shazam, AcoustID, AudD, and the local constellation-hash backend with stable public statuses and safe diagnostics.
- Production configuration includes Gunicorn, `/healthz`, `/readyz`, bounded uploads and FFmpeg work, atomic Supabase quota operations, trusted-proxy controls, and debug-off defaults outside explicit development mode.
- The browser surface uses an accessible microphone-first CTA, expandable runtime details, structured match/error cards, safe external links, theme persistence, and focus-aware song details.
- The current checkout has 193 passing Python tests. CI also defines Ruff, coverage, dependency-audit, and secret-scanning gates.

## Known limitations
Expand All @@ -43,7 +46,7 @@ Supabase authentication, persistent user history, RLS-backed history, account de

- Reproducible benchmark entry points are documented in [`evaluation/README.md`](evaluation/README.md), but no complete result is present in this checkout.
- The committed FFT image at [`docs/screenshots/fft-output.png`](docs/screenshots/fft-output.png) is diagnostic output from `shazam_project.fft_analyze.analyze_audio`; the original capture command was not preserved in Git. Recreate it through the CLI's `python main.py` path after choosing `mic` or `file`.
- The current browser smoke check was run against `python web/app.py` on a local development port with debug disabled. It verified page load, status rendering, and the unsupported-upload error state; it did not use provider credentials or record microphone audio.
- The current browser smoke check was run against `python web/app.py` on a local development port with debug disabled. It verified page load, status rendering, the runtime-details disclosure, empty-upload recovery, theme switching, and the responsive visual hierarchy at 1280x900 and 390x844; it did not use provider credentials or record microphone audio.

## Performance

Expand Down Expand Up @@ -75,10 +78,10 @@ flowchart LR
F -->|Local hashes| J[Peak/hash index]
G & H & I & J --> K[Normalized Result]
K --> L[Display (CLI) / JSON (Web)]
classDef blue fill:#ffffff,stroke:#1E90FF,stroke-width:2px,color:#1E90FF;
class A,B,C,D,E,F,G,H,I,J,K,L blue;
classDef accent fill:#fbfaf7,stroke:#e35c43,stroke-width:2px,color:#171817;
class A,B,C,D,E,F,G,H,I,J,K,L accent;
```
Theme: black / white / blue — white nodes with a professional DodgerBlue accent (#1E90FF). The browser UI is served directly by Flask; there is no separate browser bundle.
Theme: warm paper / graphite / coral, with an optional dark mode. The browser UI is served directly by Flask; there is no separate browser bundle.

## Quickstart
### Windows PowerShell
Expand Down Expand Up @@ -181,7 +184,9 @@ Entrypoints remain:
Supported env vars (see `shazam_project.config.load_config()`): `AUDD_API_TOKEN`, `ACOUSTID_API_KEY`, `FP_CALC_PATH`, `RAPIDAPI_KEY`, and optional `LOCAL_FINGERPRINT_INDEX` (with `FINGERPRINT_INDEX_PATH` accepted as a legacy alias). The shared audio contract is controlled by `INTERNAL_SAMPLE_RATE`, `MIN_AUDIO_SECONDS`, `MAX_AUDIO_SECONDS`, `MAX_UPLOAD_BYTES`, and `FFMPEG_TIMEOUT_SECONDS`; provider WAVs are always fixed 16-bit PCM. Matcher order is RapidAPI → AcoustID → AudD → local fingerprint index.

## Web UI
`python web/app.py` serves `/`, `/static/*`, `/api/match`, and `/api/status` from the same origin. CLI file mode accepts WAV/PCM files. Web uploads support WAV, MP3, M4A, AAC, OGG, FLAC, and WEBM; non-WAV web uploads require FFmpeg on `PATH` and are converted before decoding. The browser also supports microphone recording, manual stop, waveform visualization, loading/error/no-match states, light/dark theme persistence, and session-only recognition history.
`python web/app.py` serves `/`, `/static/*`, `/api/match`, and `/api/status` from the same origin. CLI file mode accepts WAV/PCM files. Web uploads support WAV, MP3, M4A, AAC, OGG, FLAC, and WEBM; non-WAV web uploads require FFmpeg on `PATH` and are converted before decoding. The browser also supports a microphone-first recording flow, manual stop, waveform visualization, expandable capability details, structured loading/error/no-match/match states, light/dark theme persistence, focus-aware song details, and session-only recognition history.

The current showcase presentation uses Space Grotesk for display headings, Manrope for body and interface copy, and IBM Plex Mono for runtime metadata. Responsive `clamp()` sizing, a small shared type scale, and a consistent label-to-heading-to-copy rhythm keep the editorial layout coherent from the 1280x900 desktop view to the 390x844 mobile view. The warm paper, graphite, and coral palette is implemented in `web/static/style.css`, with the typography refinements isolated in [`web/static/typography.css`](web/static/typography.css).

The durations are intentionally different by path: CLI microphone mode defaults to 8 seconds and accepts an interactive override; the RapidAPI/Shazam adapter sends at most the first 5 seconds of the normalized clip; browser recording auto-stops after 10 seconds but can be stopped manually; and the reproducible benchmark uses separate 4-second, 8-second, and 15-second microphone clips.

Expand Down
16 changes: 9 additions & 7 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ missing lawful corpus, credentials, or real benchmark execution.
- [x] Mark unsupported Supabase/auth/history/RLS/account/settings claims as planned or remove them.
- [x] Reconcile README content with the actual Flask source tree.
- [x] Reconcile documented 8-second CLI, 5-second RapidAPI trim, and 10-second browser-recording behavior.
- [ ] Document the exact source and command for each screenshot, and add failure-state screenshots where useful.
- [ ] Document the exact source and command for each committed screenshot, and add failure-state screenshots where useful; the current 1280x900 and 390x844 visual review remains local-only.
- [x] Remove unsupported platform claims and document API statuses, backend order, environment variables, and security boundaries.
- [ ] Tick Main task 7 only after documentation describes shipped behavior rather than aspiration.

Expand Down Expand Up @@ -181,7 +181,7 @@ missing lawful corpus, credentials, or real benchmark execution.
- [x] Add RapidAPI configuration to `/api/status`; report the actual active backend order.
- [x] Standardize response fields and statuses across all providers and the CLI/browser consumers, including local `no_match` responses.
- [x] Correct the CLI missing-configuration message so it identifies missing recognition configuration generically rather than naming AudD only.
- [ ] Add a health/startup check that clearly reports missing provider, Supabase, FFmpeg, and `fpcalc` configuration.
- [x] Add a health/startup check that clearly reports missing provider, Supabase, FFmpeg, and `fpcalc` configuration.

### Rate limiting and production safety

Expand All @@ -197,7 +197,7 @@ missing lawful corpus, credentials, or real benchmark execution.
- [x] Add `Retry-After` headers to rate-limit responses.
- [x] Disable `debug=True` outside an explicitly local development mode.
- [ ] Add a production WSGI/server configuration and document deployment assumptions.
- [ ] Add tests for unauthorized requests, daily limits, monthly limits, cooldowns, concurrent requests, and Supabase failures.
- [x] Add tests for unauthorized requests, daily limits, monthly limits, cooldowns, concurrent requests, and Supabase failures.

## P1 — engineering quality and verification

Expand Down Expand Up @@ -231,13 +231,13 @@ missing lawful corpus, credentials, or real benchmark execution.

## P1 — documentation reconciliation

- [ ] Split documentation into “Implemented”, “Known limitations”, “Planned”, and “Evaluation evidence”.
- [ ] Mark Supabase authentication, persistent user history, RLS-backed history, account deletion, settings, and protected routes as planned unless implemented.
- [x] Split documentation into “Implemented”, “Known limitations”, “Planned”, and “Evaluation evidence”.
- [x] Mark Supabase authentication, persistent user history, RLS-backed history, account deletion, settings, and protected routes as planned unless implemented.
- [x] Reconcile the README with the actual Flask source tree.
- [ ] Reconcile the documented 8-second CLI behavior, 5-second RapidAPI trim, and 10-second browser recording behavior.
- [x] Reconcile the documented 8-second CLI behavior, 5-second RapidAPI trim, and 10-second browser recording behavior.
- [x] Document that the current FFT is diagnostic and not used for matching.
- [x] Replace the stale README “Add CI” roadmap entry with the implemented pytest, coverage, lint, and build gates.
- [ ] Document the exact source and command used to generate each screenshot.
- [ ] Document the exact source and command used to generate each committed screenshot; the current 1280x900 and 390x844 visual review remains local-only.
- [ ] Add screenshots or recordings for no-match, provider error, permission denial, rate limiting, and upload failure states.
- [x] Add a concise README Limitations section covering noise, catalog coverage, language/region differences, and live/cover/remix versions.
- [x] Remove unsupported “platforms tested” claims and state that cross-platform support is not independently verified.
Expand Down Expand Up @@ -273,6 +273,8 @@ Record evidence here as work lands:

| Date | Task/check | Evidence | Result |
|---|---|---|---|
| 2026-09-14 | Typography consistency and visual review | Feature branch `codex/showcase-ready-20260913`; local Flask browser review at 1280x900 and 390x844; verified Space Grotesk / Manrope / IBM Plex Mono roles, shared responsive type tokens, aligned spacing, runtime details, empty-upload recovery, theme toggle, no overflow, and no console warnings/errors. | Showcase documentation synced to the current interface. Local visual captures were reviewed but no binary screenshot assets were committed; provider credentials, real recording, benchmark corpus, and live deployment remain open. |
| 2026-09-13 | Showcase-ready browser polish | Feature branch `codex/showcase-ready-20260913`; local Flask browser smoke verified first viewport, theme toggle, runtime-details disclosure, empty-upload recovery, no horizontal overflow at 390px/320px, and no current console errors. | Microphone-first CTA, structured result/error cards, focus-aware details modal, safe external links, and current/roadmap documentation boundary added. Provider credentials, real recording, benchmark corpus, and live deployment remain open. |
| 2026-08-17 | Current checkout audit and documentation reconciliation | Dedicated branch `codex/audio-recognition-p0-audit`; supported `.venv-pipeline` ran 193 tests; FFmpeg and fpcalc were available; local browser smoke checked page load, status rendering, and unsupported-upload handling; `/readyz`/quota/WSGI behavior is covered by repository tests. | Production/configuration and documentation checkboxes updated. No provider values, source catalog, microphone clips, benchmark results, or credentialed smoke evidence are present locally, so the real benchmark and release gates remain open. |
| 2026-08-01 | Production rate limits | Added `production_rate_limits` migration through the Supabase CLI; private row-locked quota RPC, RLS with no public policies, server-only service-role access, HMAC client identifiers, fail-closed 503 handling, development fallback, trusted-proxy configuration, direct API-secret authentication, and Retry-After responses. | 93 tests passed; 68% total branch coverage; compileall and diff checks passed. Local/linked SQL execution remains unavailable: Docker is not running and the linked `shazam-project` is inactive; linked advisors returned no lints and migration listing timed out. |
| 2026-08-01 | Prompt 3 cleanup and review fixes | Flask status display restored RapidAPI and Supabase fields; local `no_match` uses the shared `result: null` shape; all providers receive normalized mono float32 audio; provider diagnostics are safe; rate limits run before upload processing; fixed 16-bit provider WAV encoding is documented; README/TODO record the validated contract and Prompt 4 production blockers. | 73 tests passed; 66% total branch coverage; compileall and diff checks passed locally; CI and `coverage.xml` artifact are pending this push; Codecov upload previously reported `Repository not found` and remains deferred |
Expand Down
14 changes: 14 additions & 0 deletions docs/01-product-requirements.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Product Requirements Document (PRD)

> Status: This document records the intended product direction. The current showcase slice is a guest, local-first Flask MVP. Authentication, persistent history, account deletion, and hosted user settings are not implemented and must not be inferred from this document.

**Project:** Shazam Clone — Music Recognition Web App
**Author:** Shaurya Saria
**Version:** 1.0
Expand All @@ -12,6 +14,18 @@

A full-stack web application that replicates core Shazam functionality — identifying songs from audio input via microphone or file upload, displaying song metadata (title, artist, album, artwork), and maintaining a personal history of identified tracks. The app targets music listeners who want quick, browser-native song identification without needing a native app.

## Current implementation boundary

| Capability | Current state |
|---|---|
| Song recognition | Implemented through the supported Flask UI, CLI, configured provider backends, and optional local fingerprint index. |
| Guest history | Implemented as optional session-only browser history with removal and detail actions. |
| Song detail view | Implemented for returned matches, including available metadata and a safe Spotify search fallback. |
| Authentication and persistent history | Planned; no protected user routes or Supabase Auth flow is shipped. |
| Account settings and deletion | Planned; the current privacy control only governs session-history storage. |

The showcase and README should describe the current implementation boundary above. The remaining requirements below are retained as the product roadmap, not as claims about the current runtime.

---

## Problem Statement
Expand Down
10 changes: 5 additions & 5 deletions docs/02-technical-requirements.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Technical Requirements Document

**Project:** Audio Recognition
**Status:** Current Flask implementation
**Status:** Current Flask implementation; authentication and persistent-history features remain roadmap items.

## Architecture

Expand All @@ -21,31 +21,31 @@ CLI at main.py -> shared shazam_project modules -> matcher backends
| Layer | Implementation |
|---|---|
| Browser UI | Flask templates, vanilla JavaScript, and CSS |
| Web server | Flask development server for local use; WSGI deployment is planned |
| Web server | Flask development server for local use; Gunicorn WSGI configuration for deployment |
| Audio capture | Browser MediaRecorder and Web Audio API visualization |
| Audio decoding | WAV loader; optional FFmpeg conversion for browser uploads |
| Recognition | RapidAPI/Shazam, AcoustID, AudD, then local fingerprint index |
| Usage limits | Optional Supabase-backed counters plus process-local cooldown |

## Browser behavior

The page at `/` supports file upload, microphone capture with manual stop and a ten-second limit, waveform visualization, loading and error states, matched and no-match results, light/dark theme persistence, and session-only history. History is stored in the browser session and is not an authenticated database feature.
The page at `/` supports a microphone-first recording flow, file upload, manual stop and a ten-second limit, waveform visualization, expandable runtime details, structured loading/error states, matched and no-match results, light/dark theme persistence, focus-aware song details, and session-only history. History is stored in the browser session and is not an authenticated database feature.

## API contract

`POST /api/match` accepts a multipart field named `file` and returns JSON with one of these statuses:

- `matched`: includes normalized `title`, `artist`, `album`, and optional `image` fields.
- `no_match`: no configured backend identified the audio.
- `no_token`: no recognition backend is configured.
- `not_configured`: no recognition backend is configured.
- `rate_limited`: the request exceeded a configured limit.
- `error`: the upload, conversion, provider, or runtime path failed.

`GET /api/status` reports configured providers, optional `fpcalc` and FFmpeg availability, usage counters, cooldown, and upload/audio limits.

## Configuration and security

Provider keys and server configuration are loaded from the root `.env` file. The browser receives no provider keys or server secrets. Same-origin browser requests are accepted when `INTERNAL_API_SECRET` is enabled; optional external API clients must be explicitly listed in `CORS_ORIGINS`.
Provider keys and server configuration are loaded from the root `.env` file. The browser receives no provider keys or server secrets. When `INTERNAL_API_SECRET` is enabled, requests must present the secret directly; same-origin headers never bypass it. Optional external API clients must be explicitly listed in `CORS_ORIGINS`.

Uploads are bounded by `MAX_UPLOAD_BYTES` and `MAX_AUDIO_SECONDS`. Temporary files are removed after processing, and provider calls have bounded timeouts.

Expand Down
Loading
Loading