mirror of
https://github.com/JezzWTF/vibepod.git
synced 2026-06-13 03:58:07 +00:00
feat(phase-1): persistent generation library
- Save every completed generation to SQLite (generation_store.py) with WAV and waveform peaks written to data/generations/<id>/ - Deferred DB write until success — cancelled/errored generations never touch the DB and never appear in the library - Fixed cancel+regenerate IndexError: _reset_scheduler_caches() now directly zeros scheduler._step_index and running state in addition to clearing VibePod cache dicts; same explicit resets added in the fresh path of prepare_noise_scheduler as belt-and-suspenders - Added /library page with GenerationCard, WaveformPreview, waveform fetch, play/pause, download, delete, pagination, empty + error states - Added generation API routes (list, single, audio stream, waveform, delete) proxying to Python server - Added Library nav link to Header with active state - Persist script/speaker/CFG to localStorage so generate page state survives navigation - Updated build plan: Phase 0+1 ticked off, better-sqlite3 moved to Phase 2, architectural note on Python owning all persistence
This commit is contained in:
+23
-23
@@ -137,7 +137,7 @@ Build inside the existing stack. New packages require a written reason in this d
|
||||
|---|---|---|
|
||||
| `zustand` | Studio editor state | Phase 2 |
|
||||
| `@dnd-kit/core` + `@dnd-kit/utilities` | Clip drag-and-drop in timeline | Phase 2 |
|
||||
| `better-sqlite3` | SQLite for job and project persistence | Phase 1 |
|
||||
| `better-sqlite3` | SQLite for project/studio persistence (Next.js layer) | Phase 2 |
|
||||
|
||||
**Conditionally approved (evaluate at phase start):**
|
||||
|
||||
@@ -712,11 +712,11 @@ Render runs in a background thread. The client polls `GET /api/projects/:id/rend
|
||||
**Goal:** Clean foundation. No new features.
|
||||
|
||||
Tasks:
|
||||
- [ ] Extract WAV assembly from `useStreamingGeneration.ts` into `web/lib/audio/wav.ts`
|
||||
- [ ] Extract waveform peak generation into `server/waveform.py`
|
||||
- [ ] Confirm generation cancellation works cleanly (stream abort + server cancel_event)
|
||||
- [ ] Add `nanoid` to backend for stable generation IDs
|
||||
- [ ] Add `data/` directory to `.gitignore`
|
||||
- [x] Extract WAV assembly from `useStreamingGeneration.ts` into `web/lib/audio/wav.ts`
|
||||
- [x] Extract waveform peak generation into `server/waveform.py`
|
||||
- [x] Confirm generation cancellation works cleanly (stream abort + server cancel_event)
|
||||
- [x] Add stable generation IDs to backend (`server/ids.py` via `secrets.token_urlsafe`)
|
||||
- [x] Add `data/` directory to `.gitignore`
|
||||
|
||||
**Acceptance:** WAV assembly is a pure function with unit tests. Generation IDs are stable.
|
||||
|
||||
@@ -727,25 +727,23 @@ Tasks:
|
||||
**Goal:** Every generation is saved. Users can browse, play, and download past generations.
|
||||
|
||||
**Backend tasks:**
|
||||
- [ ] Add SQLite setup (`data/db/vibepod.db`, schema migration 001)
|
||||
- [ ] `generations` table: `id, created_at, status, script, speaker, cfg_scale, inference_steps, duration_secs, sample_rate, audio_path, waveform_path, error_message`
|
||||
- [ ] On generation complete: save WAV to `data/generations/<id>/audio.wav`
|
||||
- [ ] On generation complete: compute and save waveform peaks to `data/generations/<id>/waveform.json`
|
||||
- [ ] Implement `GET /api/generations` (list, paginated)
|
||||
- [ ] Implement `GET /api/generations/:id` (single)
|
||||
- [ ] Implement `GET /api/generations/:id/audio` (stream file)
|
||||
- [ ] Implement `GET /api/generations/:id/waveform` (peaks JSON)
|
||||
- [ ] Implement `DELETE /api/generations/:id` (delete row + files)
|
||||
- [x] Add SQLite setup (`data/db/vibepod.db`)
|
||||
- [x] `generations` table: `id, created_at, status, script, speaker, cfg_scale, inference_steps, duration_secs, sample_rate, audio_path, waveform_path, error_message`
|
||||
- [x] On generation complete: save WAV to `data/generations/<id>/audio.wav`
|
||||
- [x] On generation complete: compute and save waveform peaks to `data/generations/<id>/waveform.json`
|
||||
- [x] Implement `GET /api/generations` (list, paginated)
|
||||
- [x] Implement `GET /api/generations/:id` (single)
|
||||
- [x] Implement `GET /api/generations/:id/audio` (stream file)
|
||||
- [x] Implement `GET /api/generations/:id/waveform` (peaks JSON)
|
||||
- [x] Implement `DELETE /api/generations/:id` (delete row + files)
|
||||
|
||||
**Frontend tasks:**
|
||||
- [ ] Install `better-sqlite3` + types
|
||||
- [ ] Create `web/lib/db/` — schema, migration runner, query helpers
|
||||
- [ ] Create `/library` route and `LibraryPage` component
|
||||
- [ ] `GenerationCard` component: waveform preview canvas, metadata, play/download/delete actions
|
||||
- [ ] `WaveformPreview` component: draws peaks on canvas (static, no playback)
|
||||
- [ ] Mini audio player for library card playback (reuse `useAudioPlayer` hook)
|
||||
- [ ] Link "Open in Studio" button (navigates to `/studio/new?fromGeneration=<id>`)
|
||||
- [ ] Add "Library" link to `Header`
|
||||
- [x] Create `/library` route and `LibraryPage` component
|
||||
- [x] `GenerationCard` component: waveform preview canvas, metadata, play/download/delete actions
|
||||
- [x] `WaveformPreview` component: draws peaks on canvas (static, no playback)
|
||||
- [x] Mini audio player for library card playback
|
||||
- [ ] Link "Open in Studio" button (navigates to `/studio/new?fromGeneration=<id>`) — deferred to Phase 2
|
||||
- [x] Add "Library" link to `Header`
|
||||
|
||||
**Acceptance:**
|
||||
- Generate audio → close browser → reopen → generation appears in library with waveform
|
||||
@@ -771,6 +769,8 @@ Tasks:
|
||||
- [ ] Implement basic render endpoint (single voice track, WAV out only)
|
||||
|
||||
**Frontend tasks:**
|
||||
- [ ] Install `better-sqlite3` + types
|
||||
- [ ] Create `web/lib/db/` — schema, migration runner, query helpers
|
||||
- [ ] Install `zustand`, `@dnd-kit/core`, `@dnd-kit/utilities`
|
||||
- [ ] Create Studio Zustand store (`web/stores/studioStore.ts`)
|
||||
- Project state, selected clip, playhead time, zoom, isPlaying, undo stack
|
||||
|
||||
Reference in New Issue
Block a user