feat: audio upload + AI-assisted tempo map generation

Users can now upload any audio file to generate a CTP tempo map:

BPM detection (lib/analysis/bpm-detect.ts):
- Runs entirely client-side via Web Audio API — audio is never uploaded
- Decodes any browser-supported format (MP3, WAV, AAC, OGG, FLAC, M4A)
- Energy envelope → onset strength → autocorrelation over 55–210 BPM range
- Returns BPM, normalised confidence score, duration, and optional half-time BPM
  for songs where a double-time pulse is detected

AI CTP generation (lib/analysis/ai-ctp.ts):
- Calls Claude (claude-opus-4-6) with adaptive thinking + structured JSON output
- System prompt explains CTP rules and section layout conventions
- Claude uses knowledge of well-known songs to produce accurate section maps;
  falls back to a sensible generic structure for unknown tracks
- Only BPM + duration + optional metadata is sent to the server (no audio data)

API route (app/api/analyze/route.ts):
- POST /api/analyze accepts { bpm, duration, title?, artist?, mbid?, contributed_by? }
- Validates input, calls generateCTPWithAI, runs CTP schema validation
- Returns { ctp, warnings } — warnings are surfaced in the UI rather than 500-ing

UI (components/TempoAnalyzer.tsx, app/(web)/analyze/page.tsx):
- Drag-and-drop or browse file upload
- Shows BPM, confidence, duration after detection
- Half-time toggle when double-time is detected
- Metadata form: title, artist, MusicBrainz ID, contributor name
  (filename parsed into artist/title as a convenience default)
- AI generation with streaming-style progress states
- Sections review via TempoMapEditor
- Download .ctp.json or submit directly to the database

Also: added @anthropic-ai/sdk to package.json, ANTHROPIC_API_KEY to .env.example,
updated next.config.mjs serverComponentsExternalPackages, added Analyze nav link.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
AJ Avezzano
2026-04-01 11:43:14 -04:00
parent 331a5fbfca
commit 51f67f0aeb
10 changed files with 1023 additions and 29 deletions

View File

@@ -4,41 +4,30 @@
# ─────────────────────────────────────────────────────────────────────────────
# ── Database ─────────────────────────────────────────────────────────────────
# PostgreSQL connection string.
# When using docker compose the default works out of the box.
DATABASE_URL=postgres://clicktrack:clicktrack@localhost:5432/clicktrack
# Password used by the postgres service in docker-compose.yml.
# Change this before deploying to production.
POSTGRES_PASSWORD=clicktrack
# ── Redis ────────────────────────────────────────────────────────────────────
# Redis connection URL.
REDIS_URL=redis://localhost:6379
# ── Community registry ───────────────────────────────────────────────────────
# Public GitHub repository containing community CTP files.
# Example: https://github.com/your-org/clicktrack-registry
# Leave blank to disable registry sync.
REGISTRY_REPO=
# Branch to pull from (default: main).
REGISTRY_BRANCH=main
# Interval in seconds between registry syncs (default: 3600 = 1 hour).
REGISTRY_SYNC_INTERVAL=3600
# ── AI Tempo Analysis ────────────────────────────────────────────────────────
# Required for the /analyze feature (AI tempo map generation).
# Get a key at https://console.anthropic.com
# BPM detection is client-side and works without this key.
ANTHROPIC_API_KEY=
# ── App ──────────────────────────────────────────────────────────────────────
# Display name shown in the UI and page title.
NEXT_PUBLIC_APP_NAME=ClickTrack
# ── MusicBrainz ──────────────────────────────────────────────────────────────
# User-Agent string sent to MusicBrainz. Must identify your application and
# provide a contact URL or email per their usage policy:
# https://musicbrainz.org/doc/MusicBrainz_API/Rate_Limiting
# Must identify your instance per MB rate-limit policy.
MUSICBRAINZ_USER_AGENT=ClickTrack/0.1 (https://your-instance-url)
# ── Ports (docker-compose.yml) ───────────────────────────────────────────────
# Host ports for the nginx reverse proxy.
HTTP_PORT=80
HTTPS_PORT=443