feat(processed-audio-sources): phase 3 - processed audio source model
Replace MultichannelAudioSource with CaptureAudioSource, add ProcessedAudioSource (audio_source_id + audio_processing_template_id), remove MonoAudioSource and BandExtractAudioSource entirely. Update store resolution to walk processed chains collecting template IDs. Update all API schemas, routes, and frontend references.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Phase 3: Processed Audio Source Model
|
||||
|
||||
**Status:** ⬜ Not Started
|
||||
**Status:** ✅ Done
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** backend
|
||||
|
||||
@@ -9,57 +9,69 @@ Add the `ProcessedAudioSource` type, rename `MultichannelAudioSource` to `Captur
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Task 1: Rename `MultichannelAudioSource` → `CaptureAudioSource` in `storage/audio_source.py`
|
||||
- [x] Task 1: Rename `MultichannelAudioSource` → `CaptureAudioSource` in `storage/audio_source.py`
|
||||
- Change class name, update `source_type` default to `"capture"`
|
||||
- Same fields: `device_index`, `is_loopback`, `audio_template_id`
|
||||
- [ ] Task 2: Add `ProcessedAudioSource` dataclass in `storage/audio_source.py`
|
||||
- [x] Task 2: Add `ProcessedAudioSource` dataclass in `storage/audio_source.py`
|
||||
- Fields: `audio_source_id: str` (input source), `audio_processing_template_id: str`
|
||||
- `source_type` = `"processed"`
|
||||
- Inherits standard base fields (id, name, description, tags, created_at, updated_at)
|
||||
- [ ] Task 3: Remove `MonoAudioSource` class entirely
|
||||
- [ ] Task 4: Remove `BandExtractAudioSource` class entirely
|
||||
- [ ] Task 5: Update `create_audio_source()` factory function to handle new types
|
||||
- [ ] Task 6: Update `AudioSourceStore` resolution logic:
|
||||
- [x] Task 3: Remove `MonoAudioSource` class entirely
|
||||
- [x] Task 4: Remove `BandExtractAudioSource` class entirely
|
||||
- [x] Task 5: Update `create_audio_source()` factory function to handle new types
|
||||
- [x] Task 6: Update `AudioSourceStore` resolution logic:
|
||||
- `resolve_audio_source()` now returns: device info (from CaptureAudioSource at chain end) + ordered list of filter chains (from AudioProcessingTemplates along the chain)
|
||||
- Walk chain: ProcessedAudioSource → ... → CaptureAudioSource
|
||||
- Collect all audio_processing_template_ids in order
|
||||
- Cycle detection for ProcessedAudioSource chains
|
||||
- [ ] Task 7: Update `ResolvedAudioSource` dataclass:
|
||||
- [x] Task 7: Update `ResolvedAudioSource` dataclass:
|
||||
- Remove `channel` and `freq_low`/`freq_high` fields (handled by filters now)
|
||||
- Add `filter_instances: List[FilterInstance]` — flattened, ordered list of all filters to apply
|
||||
- Or add `template_ids: List[str]` and resolve at runtime
|
||||
- [ ] Task 8: Update reference validation in store:
|
||||
- Add `audio_processing_template_ids: List[str]` — ordered list of template IDs along the chain
|
||||
- [x] Task 8: Update reference validation in store:
|
||||
- `ProcessedAudioSource.audio_source_id` must reference an existing audio source
|
||||
- `ProcessedAudioSource.audio_processing_template_id` must reference an existing template
|
||||
- Delete checks: can't delete a source referenced by another ProcessedAudioSource
|
||||
- Delete checks: can't delete a template referenced by a ProcessedAudioSource
|
||||
- [ ] Task 9: Update API schemas in `api/schemas/audio_sources.py`
|
||||
- Added `get_sources_referencing_template()` helper for template delete checks
|
||||
- [x] Task 9: Update API schemas in `api/schemas/audio_sources.py`
|
||||
- Remove `MonoAudioSourceCreate/Update/Response` schemas
|
||||
- Remove `BandExtractAudioSourceCreate/Update/Response` schemas
|
||||
- Add `CaptureAudioSourceCreate/Update/Response` (rename from Multichannel)
|
||||
- Add `ProcessedAudioSourceCreate/Update/Response`
|
||||
- Update discriminated union to use new type literals
|
||||
- [ ] Task 10: Update API routes in `api/routes/audio_sources.py`
|
||||
- [x] Task 10: Update API routes in `api/routes/audio_sources.py`
|
||||
- Handle new source types in create/update endpoints
|
||||
- Remove handling of old types
|
||||
- Update WebSocket test endpoint to work with ProcessedAudioSource
|
||||
- [ ] Task 11: Update any imports/references across the codebase that reference the old types
|
||||
- Update WebSocket test endpoint to work with new resolution (no channel/band)
|
||||
- [x] Task 11: Update any imports/references across the codebase that reference the old types
|
||||
|
||||
## Files to Modify/Create
|
||||
- `storage/audio_source.py` — **modify** — rename, add, remove dataclasses
|
||||
- `storage/audio_source_store.py` — **modify** — new resolution logic, validation
|
||||
- `storage/audio_template_store.py` — **modify** — CaptureAudioSource import
|
||||
- `api/schemas/audio_sources.py` — **modify** — new schemas
|
||||
- `api/routes/audio_sources.py` — **modify** — handle new types
|
||||
- Any files importing `MultichannelAudioSource`, `MonoAudioSource`, `BandExtractAudioSource` — **modify**
|
||||
- `core/processing/audio_stream.py` — **modify** — remove channel/band logic
|
||||
- `core/processing/value_stream.py` — **modify** — remove channel logic
|
||||
- `core/demo_seed.py` — **modify** — update demo data to new types
|
||||
- `storage/color_strip_source.py` — **modify** — update comment
|
||||
- `storage/value_source.py` — **modify** — update comment
|
||||
- `static/js/types.ts` — **modify** — new TS interfaces
|
||||
- `static/js/core/icons.ts` — **modify** — new icon mapping
|
||||
- `static/js/core/graph-nodes.ts` — **modify** — new icon mapping
|
||||
- `static/js/features/audio-sources.ts` — **modify** — new source types
|
||||
- `static/js/features/streams.ts` — **modify** — new card sections
|
||||
- `static/js/features/value-sources.ts` — **modify** — badge text
|
||||
- `static/js/features/color-strips.ts` — **modify** — badge text, navigation
|
||||
- `static/js/core/command-palette.ts` — **modify** — navigation mapping
|
||||
|
||||
## Acceptance Criteria
|
||||
- `CaptureAudioSource` replaces `MultichannelAudioSource` (same behavior, new name/type)
|
||||
- `ProcessedAudioSource` can be created referencing a source + template
|
||||
- `MonoAudioSource` and `BandExtractAudioSource` are fully removed
|
||||
- Chain resolution walks ProcessedAudioSource → ... → CaptureAudioSource correctly
|
||||
- Cycle detection prevents circular source references
|
||||
- Reference validation prevents dangling references
|
||||
- API accepts/returns new type discriminators
|
||||
- [x] `CaptureAudioSource` replaces `MultichannelAudioSource` (same behavior, new name/type)
|
||||
- [x] `ProcessedAudioSource` can be created referencing a source + template
|
||||
- [x] `MonoAudioSource` and `BandExtractAudioSource` are fully removed
|
||||
- [x] Chain resolution walks ProcessedAudioSource → ... → CaptureAudioSource correctly
|
||||
- [x] Cycle detection prevents circular source references
|
||||
- [x] Reference validation prevents dangling references
|
||||
- [x] API accepts/returns new type discriminators
|
||||
|
||||
## Notes
|
||||
- Clean-slate: no migration of existing data. Old source type records will be lost.
|
||||
@@ -68,11 +80,37 @@ Add the `ProcessedAudioSource` type, rename `MultichannelAudioSource` to `Captur
|
||||
- Template reference checks in the store need coordination with `AudioProcessingTemplateStore` — may need to pass it as a dependency.
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [x] All tasks completed
|
||||
- [x] Code follows project conventions
|
||||
- [x] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- Filled in by the implementation agent after completing this phase. -->
|
||||
|
||||
### What was built
|
||||
- `CaptureAudioSource` replaces `MultichannelAudioSource` (class + source_type "capture")
|
||||
- `ProcessedAudioSource` added with `audio_source_id` + `audio_processing_template_id` fields
|
||||
- `MonoAudioSource` and `BandExtractAudioSource` fully removed from model, store, schemas, routes, and all frontend references
|
||||
- `ResolvedAudioSource` now returns `audio_processing_template_ids: List[str]` instead of `channel`/`freq_low`/`freq_high`
|
||||
- Chain resolution walks ProcessedAudioSource → ... → CaptureAudioSource, collecting template IDs in order (outermost first)
|
||||
- Cycle detection for both create and update operations
|
||||
- `get_sources_referencing_template()` helper added for template delete checks
|
||||
- All frontend TS files updated: types, icons, card sections, navigation, command palette
|
||||
|
||||
### What Phase 4 needs to know
|
||||
- `ResolvedAudioSource` now has `audio_processing_template_ids` field — Phase 4 must resolve these to `FilterInstance` lists and instantiate/apply them in the stream runtime
|
||||
- `AudioColorStripStream._pick_channel()` currently returns raw `analysis.spectrum, analysis.rms` — Phase 4 must wire filter processing here
|
||||
- `AudioValueStream._pick_rms()` and `_pick_peak()` currently return raw analysis values — Phase 4 must apply filter chain
|
||||
- Both streams store `self._audio_processing_template_ids` for use by Phase 4
|
||||
- The WebSocket test endpoint also needs filter application wired in Phase 4
|
||||
|
||||
### Temporary breakages (resolved in Phase 4)
|
||||
- Channel selection removed from `AudioColorStripStream._pick_channel()` — always uses mono mix
|
||||
- Channel selection removed from `AudioValueStream._pick_rms()` and `_pick_peak()` — always uses mono
|
||||
- These were previously handled by MonoAudioSource/BandExtractAudioSource; now handled by channel_extract/band_extract filters in ProcessedAudioSource chains
|
||||
|
||||
### Known deviations from plan
|
||||
- Task 7: Used `audio_processing_template_ids: List[str]` (template IDs) rather than `filter_instances: List[FilterInstance]` — runtime resolution deferred to Phase 4
|
||||
- Task 8: Template reference validation at create time not implemented (would require injecting AudioProcessingTemplateStore as dependency) — deferred to Phase 4 or Phase 7
|
||||
- Frontend was also updated comprehensively (not just backend) to avoid broken UI
|
||||
|
||||
Reference in New Issue
Block a user