feat(processed-audio-sources): phase 7 - testing and polish
Fix test_list_filters test (filter_id field name mismatch). Add tests for audio filters, template store, and source store. All 678 tests pass, ruff clean, tsc clean, esbuild clean. No dead code remaining from old source types.
This commit is contained in:
@@ -134,8 +134,8 @@ async def update_audio_processing_template(
|
||||
try:
|
||||
pm = get_processor_manager()
|
||||
pm.refresh_audio_filter_pipelines(template_id)
|
||||
except Exception:
|
||||
pass # Non-critical: streams will pick up changes on next restart
|
||||
except Exception as exc:
|
||||
logger.warning("Hot-update of audio filter pipelines failed: %s", exc)
|
||||
return _apt_to_response(template)
|
||||
except EntityNotFoundError as e:
|
||||
raise HTTPException(status_code=404, detail=str(e))
|
||||
@@ -158,15 +158,14 @@ async def delete_audio_processing_template(
|
||||
):
|
||||
"""Delete an audio processing template."""
|
||||
try:
|
||||
# TODO: Phase 3 will add reference checks against ProcessedAudioSource
|
||||
store.delete_template(template_id)
|
||||
fire_entity_event("audio_processing_template", "deleted", template_id)
|
||||
# Hot-update: rebuild filter pipelines for running streams that used this template
|
||||
try:
|
||||
pm = get_processor_manager()
|
||||
pm.refresh_audio_filter_pipelines(template_id)
|
||||
except Exception:
|
||||
pass # Non-critical
|
||||
except Exception as exc:
|
||||
logger.warning("Hot-update of audio filter pipelines after delete failed: %s", exc)
|
||||
except HTTPException:
|
||||
raise
|
||||
except EntityNotFoundError as e:
|
||||
|
||||
@@ -324,10 +324,12 @@ class AudioColorStripStream(ColorStripStream):
|
||||
buf = _buf_a if _use_a else _buf_b
|
||||
_use_a = not _use_a
|
||||
|
||||
# Get latest audio analysis
|
||||
# Get latest audio analysis and apply filter pipeline once per frame
|
||||
analysis = None
|
||||
if self._audio_stream is not None:
|
||||
analysis = self._audio_stream.get_latest_analysis()
|
||||
if analysis is not None and self._filter_pipeline is not None:
|
||||
analysis = self._filter_pipeline.process(analysis)
|
||||
|
||||
render_fn = renderers.get(self._visualization_mode, self._render_spectrum)
|
||||
t_render = time.perf_counter()
|
||||
@@ -361,15 +363,8 @@ class AudioColorStripStream(ColorStripStream):
|
||||
|
||||
# ── Filter pipeline + channel selection ──────────────────────────
|
||||
|
||||
def _apply_filters(self, analysis):
|
||||
"""Apply audio filter pipeline (if any) and return (spectrum, rms).
|
||||
|
||||
The filter pipeline handles channel extraction, band extraction,
|
||||
gain, noise gate, etc. as configured by the ProcessedAudioSource
|
||||
template chain.
|
||||
"""
|
||||
if self._filter_pipeline is not None:
|
||||
analysis = self._filter_pipeline.process(analysis)
|
||||
def _extract_spectrum_rms(self, analysis):
|
||||
"""Return (spectrum, rms) from an already-filtered analysis."""
|
||||
return analysis.spectrum, analysis.rms
|
||||
|
||||
# ── Spectrum Analyzer ──────────────────────────────────────────
|
||||
@@ -379,7 +374,7 @@ class AudioColorStripStream(ColorStripStream):
|
||||
buf[:] = 0
|
||||
return
|
||||
|
||||
spectrum, _ = self._apply_filters(analysis)
|
||||
spectrum, _ = self._extract_spectrum_rms(analysis)
|
||||
sensitivity = self.resolve("sensitivity", self._sensitivity)
|
||||
smoothing = self.resolve("smoothing", self._smoothing)
|
||||
lut = self._palette_lut
|
||||
@@ -430,7 +425,7 @@ class AudioColorStripStream(ColorStripStream):
|
||||
buf[:] = 0
|
||||
return
|
||||
|
||||
_, ch_rms = self._apply_filters(analysis)
|
||||
_, ch_rms = self._extract_spectrum_rms(analysis)
|
||||
sensitivity = self.resolve("sensitivity", self._sensitivity)
|
||||
smoothing = self.resolve("smoothing", self._smoothing)
|
||||
rms = ch_rms * sensitivity
|
||||
|
||||
@@ -605,10 +605,3 @@ function _renderAudioSpectrum() {
|
||||
}
|
||||
}
|
||||
|
||||
// ── Removed types ─────────────────────────────────────────────
|
||||
// MonoAudioSource and BandExtractAudioSource have been removed.
|
||||
// Channel selection is now handled by the channel_extract audio filter.
|
||||
// Band filtering is now handled by the band_extract audio filter.
|
||||
// These are applied via ProcessedAudioSource referencing an AudioProcessingTemplate.
|
||||
// Exported stubs for backward compatibility (no-op):
|
||||
export function onBandPresetChange() { /* removed */ }
|
||||
|
||||
@@ -1258,8 +1258,7 @@ export async function saveStream() {
|
||||
|
||||
if (!name) { showToast(t('streams.error.required'), 'error'); return; }
|
||||
|
||||
const payload: any = { name, description: description || null, tags: _streamTagsInput ? _streamTagsInput.getValue() : [] };
|
||||
if (!streamId) payload.stream_type = streamType;
|
||||
const payload: any = { name, stream_type: streamType, description: description || null, tags: _streamTagsInput ? _streamTagsInput.getValue() : [] };
|
||||
|
||||
if (streamType === 'raw') {
|
||||
payload.display_index = parseInt((document.getElementById('stream-display-index') as HTMLInputElement).value) || 0;
|
||||
|
||||
@@ -58,6 +58,7 @@ _ENTITY_TABLES = [
|
||||
"home_assistant_sources",
|
||||
"mqtt_sources",
|
||||
"game_integrations",
|
||||
"audio_processing_templates",
|
||||
]
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user