Files
led2/.planning/phases/04-timeline-editor/04-CONTEXT.md
Claude 9d9cd935b6 docs(phase-04): capture context for timeline editor phase
Inspector panel below timeline (above transport) confirmed.
Block data model, canvas tech, and undo/redo architecture left to Claude's discretion with recommendations noted.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-06 22:14:06 +00:00

6.9 KiB

Phase 4: Timeline Editor - Context

Gathered: 2026-04-06 Status: Ready for planning

## Phase Boundary

The main area becomes a live DAW timeline — per-device horizontal tracks on a time axis, animation blocks that can be placed, moved, resized, and deleted, a real-time playback cursor, undo/redo stack (min 20 steps), beat detection overlay from librosa, snap-to-beat, beat calibration offset, and a block editor for per-block color/param editing. No live UDP firing (Phase 5), no AI sync (Phase 6).

## Implementation Decisions

Block editor placement

  • D-01: Fixed inspector panel between the timeline and the transport bar — always visible when a block is selected, hidden/collapsed when nothing is selected
  • D-02: Inspector shows block label (animation type), color picker, and animation params (speed, direction, length, etc.) in a single horizontal row — compact strip style matching the terminal aesthetic
  • D-03: Layout from top to bottom: TIMELINE → BLOCK INSPECTOR (conditional) → TRANSPORT BAR

Claude's Discretion

  • Block data model: Add duration: float = 4.0 to existing CueModel — backward-compatible, timestamp stays as start time. Schema_version stays at 1 (duration defaults gracefully for old files). Renaming timestamp to start_time would be cleaner but requires migration — defer to v2.
  • Timeline canvas technology: Choose based on what's best for the interaction model. HTML5 Canvas is recommended (custom hit-testing, DAW-like perf, consistent with waveform rendering approach). DOM divs are acceptable if the planner has strong reasons. Mixed (canvas background + DOM blocks) is also valid.
  • State ownership for undo/redo: Frontend-owned state recommended — all timeline mutations live in a JS command history stack, backend updated on explicit save or after each mutation via async API call. This matches how the audio clock already lives in the browser. The command pattern must support at least 20 undo steps.
  • Beat detection UI placement: Beat marks overlaid directly on the timeline (same horizontal axis as blocks). Calibration offset control can live in a settings/toolbar area or inline near the beat mark display — planner decides.
  • Waveform canvas: Phase 2 backend (/api/audio/waveform, lightsync/audio/waveform.py) and frontend beat analysis are implemented, but there's currently no <canvas> element in index.html. Phase 4 must add the waveform canvas to the timeline panel and wire it up.
## Specific Ideas
  • Terminal aesthetic carries forward from Phase 1: flat, sharp edges, cyan/teal on near-black, monospace. No rounded corners, no drop shadows, no gradients. The inspector panel should look like a terminal status bar, not a floating dialog.
  • The full app layout from Phase 1 (DEVICES sidebar | main area | transport bar) is the permanent shell. Phase 4 fills main-area with the actual timeline. The inspector sits between the timeline canvas and the existing .transport-bar footer.

<canonical_refs>

Canonical References

Downstream agents MUST read these before planning or implementing.

Requirements

  • .planning/REQUIREMENTS.md — TL-01 through TL-08, SYNC-01, SYNC-02 (this phase's acceptance criteria)
  • .planning/ROADMAP.md §Phase 4 — Success criteria (6 items), plan breakdown (04-01 through 04-04)

Data models and protocol

  • lightsync/models/show.py — CueModel, TrackModel, ShowModel (add duration field here; all blocks live in tracks.cues)
  • lightsync/models/device.py — DeviceConfig (track labels come from device name/strip_type)

Audio and beat analysis (Phase 2 output — Phase 4 consumes)

  • lightsync/audio/beats.py — Beat detection logic (librosa beat_track + plp + onset_detect)
  • lightsync/api/audio.py — GET /api/audio/beats endpoint, GET /api/audio/waveform endpoint
  • lightsync/audio/waveform.py — extract_peaks() function for waveform canvas data

Animation library (Phase 3 output — Phase 4 library panel)

  • lightsync/animations/ — All 7 animation types (chase, pulse, rainbow, strobe, color_wipe, fire, solid)

Existing frontend

  • lightsync/frontend/index.html — Current layout (sidebar, main-area, transport-bar); Phase 4 replaces the animation tile grid in main-area with the actual timeline canvas
  • lightsync/frontend/app.js — Existing WebSocket client, audio tick loop, device CRUD — new timeline code integrates here
  • lightsync/frontend/style.css — CSS variables (--accent cyan, dark theme conventions from Phase 1 D-11 through D-15)

Prior context

  • .planning/phases/01-foundation/01-CONTEXT.md — Visual aesthetic decisions (D-11 through D-15): flat, sharp, cyan/teal, monospace, uppercase headers

</canonical_refs>

<code_context>

Existing Code Insights

Reusable Assets

  • lightsync/audio/waveform.py — extract_peaks() returns amplitude samples for canvas rendering
  • lightsync/api/audio.py — GET /api/audio/beats?path= returns {beat_times, onset_times, tempo_bpm}; cached after first analysis
  • lightsync/animations/ — Animation registry with all 7 types; factory function create_animation(name, params)
  • lightsync/frontend/app.js — LightSyncClient WebSocket class, 10Hz tick loop (audio.currentTime → server), apiPost/apiDelete helpers
  • lightsync/api/ — Router structure (devices.py, shows.py, audio.py, ws.py) — add timeline/block REST endpoints here

Established Patterns

  • Frontend is ES module (type="module") — import/export pattern required for new JS files
  • Transport state is browser-driven: HTML5 <audio> element is the master clock, position ticks sent via WebSocket to server at timeupdate
  • All REST calls use apiPost/apiDelete helpers from app.js
  • CSS uses --accent (cyan), --bg (near-black), --border (dimmed cyan) variables; panel borders are 1px solid var(--border)
  • Panel headers are uppercase with class panel-header or section-header

Integration Points

  • lightsync/models/show.py TrackModel.cues → where timeline blocks are stored (add duration to CueModel)
  • lightsync/api/shows.py → REST endpoints for show save/load; new block CRUD endpoints go here or in a new timeline.py router
  • WebSocket ws.py → already receives tick and seek events from browser; Phase 4 can add block_select or beat_update events if needed
  • index.html main-area div → currently holds animation tile grid; Phase 4 replaces this with timeline canvas + track headers

</code_context>

## Deferred Ideas
  • Live UDP firing while timeline plays — Phase 5
  • AI-assisted block placement — Phase 6
  • Structural segmentation overlay (verse/chorus/bridge regions) — Phase 6 / v2
  • Keyboard shortcuts for all primary operations — Phase 5 (UI-03)
  • Show save/load persistence across sessions — Phase 5

Phase: 04-timeline-editor Context gathered: 2026-04-06