- 02-03-SUMMARY.md: full redesign summary, decisions, deviations documented - STATE.md: decisions updated, session recorded, progress at 100% (7/7 plans) - ROADMAP.md: Phase 2 confirmed Complete (3/3 plans)
8.4 KiB
8.4 KiB
phase, plan, subsystem, tags, requires, provides, affects, tech-stack, key-files, key-decisions, duration, completed
| phase | plan | subsystem | tags | requires | provides | affects | tech-stack | key-files | key-decisions | duration | completed | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 02-audio-engine | 03 | audio |
|
|
|
|
|
|
|
~4 min | 2026-04-06 |
Phase 02 Plan 03: Browser Audio + Librosa Beat Detection (Architecture Redesign)
Browser plays audio via HTML5 element; server does beat analysis via librosa; WebSocket carries position ticks (browser) and beat notifications (server)
Performance
- Duration: ~4 min
- Started: 2026-04-06T15:35:26Z
- Completed: 2026-04-06T15:39:29Z
- Tasks: 9 auto commits (architecture redesign, no checkpoints)
- Files modified: 8 (1 created, 1 deleted)
Accomplishments
- Removed python-mpv from pyproject.toml and mpv-libs from Dockerfile entirely
- Created
lightsync/audio/beats.py—analyze(path)using librosa.beat.beat_track, returns{tempo, beats}as timestamps in seconds - Redesigned
lightsync/api/audio.py— POST /upload runs beat analysis and caches; GET /beats returns cached or on-demand; GET /waveform now takes path query param; removed engine-dependent endpoints - Redesigned
lightsync/api/ws.py— removed server broadcast_loop; browser sends tick messages; server does 50ms beat proximity check and fires beat events back; bisect-based O(log n) lookup - Updated
lightsync/main.py— removed MPVEngine lifespan; addedapp.state.beats = {}cache; added/showsStaticFiles mount for browser audio loading - Deleted
lightsync/audio/engine.py— fully replaced by browser audio + librosa - Frontend
index.html— added hidden<audio id="player">, beat indicator dot in header, animation selector panel - Frontend
app.js— wires audio element events, 10Hz setInterval tick loop, beat flash on WS beat events, beat marker lines drawn on waveform canvas, loadSelectedFile sets audio.src - Frontend
style.css— beat-indicator with beat-flash animation, animation-select-input styles
Task Commits
5d93294— chore: replace python-mpv with librosa in pyproject.tomlcce76a2— chore: remove mpv-libs from Dockerfile92cc09e— feat: add beats.py librosa beat detection module636160e— feat: redesign audio.py — browser-audio architecture, beat endpoint2c9ca0d— feat: redesign WebSocket protocol — browser tick-driven beat detection6366d84— feat: remove MPVEngine from main.py, add beats cache and shows route1f1ff92— chore: delete engine.pyf1941a9— feat: redesign frontend — browser audio element, beat markers, animation selector0963ad4— fix: upload file selection path consistency
Files Created/Modified
lightsync/audio/beats.py— analyze(), analyze_async(), librosa beat_track wrapperlightsync/audio/engine.py— DELETED (MPV engine removed)lightsync/api/audio.py— upload+beats cache, GET /beats endpoint, waveform takes path paramlightsync/api/ws.py— tick/beat protocol, bisect beat lookup, per-connection statelightsync/main.py— no engine, app.state.beats, /shows StaticFileslightsync/frontend/index.html— audio element, beat indicator, animation selectorlightsync/frontend/app.js— audio wiring, 10Hz ticks, beat flash, beat markerslightsync/frontend/style.css— beat-indicator, animation-select-inputpyproject.toml— python-mpv removed, librosa addedDockerfile— mpv-libs removed
Decisions Made
- Browser handles audio playback — no server-side audio process or Docker audio dependency
- librosa.beat.beat_track provides both tempo and beat grid in one call, sufficient for Phase 2
- Beat cache in app.state.beats survives WebSocket reconnects and multiple client connections
- 50ms window balances precision vs. tick rate jitter (100ms tick interval)
- Static /shows mount allows browser to load audio files with a simple URL path
Deviations from Plan
This plan was a complete architecture redesign replacing the original 02-03 implementation. The original 02-03 built on MPV; this revision removes MPV entirely.
Changes vs Original 02-03-PLAN.md
Removed from plan:
- MPV waveform-based transport UI (seek bar, time display driven by WS tick from server)
- Server-side broadcast_loop polling MPV position
Added vs original plan (per user redesign spec):
- librosa beat detection module
- Browser audio element as playback source
- 10Hz client tick loop
- Beat proximity detection in WebSocket server
- Beat flash visual indicator
- Beat marker lines on waveform canvas
- Animation selector panel
- /shows StaticFiles mount
Auto-fixed Issues
[Rule 1 - Bug] Fixed upload path pre-selection inconsistency
- Found during: Upload handler review
- Issue: refreshFileList options used
/app/shows/filenamevalues but upload called it with/shows/filename, preventing auto-selection of uploaded file - Fix: Pass full abs path from upload response directly to refreshFileList
- Files modified: lightsync/frontend/app.js
- Commit:
0963ad4
Known Stubs
- Animation selector (
<select id="animation-select">) has placeholder options — no animation logic connected yet (Phase 3+ will wire UDP commands) - WebSocket play/pause/seek messages from browser are logged only — no UDP trigger yet (deferred to Phase 3+ cue scheduler)
Next Phase Readiness
- Beat timestamps available via app.state.beats for any Phase 3+ cue scheduler
- /api/audio/beats endpoint provides analysis data for Phase 4 timeline editor beat-snap
- WebSocket protocol extended cleanly — Phase 3 can add beat → UDP animation dispatch
- Browser audio element is the master clock — Phase 5 live execution reads audio.currentTime
Phase: 02-audio-engine Completed: 2026-04-06