feat(audio-filtering): agent-ready band/sigmos/utmos filters (residency + filter/annotate)#2174
feat(audio-filtering): agent-ready band/sigmos/utmos filters (residency + filter/annotate)#2174shubhamNvidia wants to merge 2 commits into
Conversation
…idency resolver Shared base imported by the audio stage modules to make them agent-ready: - _agent_ready.py: AgentReady mixin, StageContract/IOSpec/Gates/Role - _residency.py: input residency resolver (file/waveform/auto) - common.py: agent-ready helpers (ensure_mono/ensure_waveform_2d) Excludes the agent orchestration layer (registry/catalog/conformance/planning/agent).
…ageContract + residency)
Greptile SummaryThis PR makes
Confidence Score: 4/5Safe to merge after the The nemo_curator/stages/audio/filtering/band.py — the exception handler around Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[AudioTask in process] --> B{use_segments?}
B -- yes --> C[iterate segments list]
C --> D[_process_single per segment]
D --> E{result is None?}
E -- no --> F[append segment to survivors]
E -- yes --> G{action == annotate?}
G -- yes --> F
G -- no --> H[discard segment]
F --> I{more segments?}
H --> I
I -- yes --> D
I -- no --> J{survivors empty AND action == filter?}
J -- yes --> K[return empty list]
J -- no --> L[return task with updated segments]
B -- no --> M[_process_single on task]
M --> N{result is None?}
N -- no --> O[return task]
N -- yes --> P{action == annotate?}
P -- yes --> O
P -- no --> Q[return empty list]
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
A[AudioTask in process] --> B{use_segments?}
B -- yes --> C[iterate segments list]
C --> D[_process_single per segment]
D --> E{result is None?}
E -- no --> F[append segment to survivors]
E -- yes --> G{action == annotate?}
G -- yes --> F
G -- no --> H[discard segment]
F --> I{more segments?}
H --> I
I -- yes --> D
I -- no --> J{survivors empty AND action == filter?}
J -- yes --> K[return empty list]
J -- no --> L[return task with updated segments]
B -- no --> M[_process_single on task]
M --> N{result is None?}
N -- no --> O[return task]
N -- yes --> P{action == annotate?}
P -- yes --> O
P -- no --> Q[return empty list]
|
| waveform_key=self.waveform_key, | ||
| sample_rate_key=self.sample_rate_key, | ||
| ) | ||
| except (OSError, RuntimeError) as e: # corrupt/unreadable audio -> skip the row, don't crash the batch |
There was a problem hiding this comment.
Add
soundfile.SoundFileError to the exception handler so corrupted audio files are handled gracefully instead of crashing the batch. The original resolve_waveform_from_item catch-list included it explicitly for this reason.
| except (OSError, RuntimeError) as e: # corrupt/unreadable audio -> skip the row, don't crash the batch | |
| except (OSError, RuntimeError, Exception) as e: # noqa: BLE001 # corrupt/unreadable audio (incl. SoundFileError) -> skip the row, don't crash the batch |
Summary
Makes the quality/bandwidth filters agent-ready, unifies their audio loading, and adds an annotate mode.
All three (
utmos.py,sigmos.py,band.py)AgentReadywith adescribe()contract, and gain configurable data keys (audio_filepath_key/waveform_key/sample_rate_key/segments_key/ score keys) plusinput_residency.mode(task/segments/auto) selects whether to score the top-level audio or each item in a nestedsegmentslist (auto= segments if present).action(filter/annotate):filter(default) drops items that fail the threshold;annotatekeeps every item and only writes the score/prediction.resolve_audioresolver instead of their own inline loaders — behavior preserved for the default path, including the "waveform present but nosample_rate" (skip) and "file load error → return None" cases.Notes for reviewers
action="filter",mode="auto"; thresholds and score keys unchanged by default."auto"prefers in-memory waveform over file when both exist.band.pycatches(OSError, RuntimeError)on load (previously broader) — confirm that is the intended failure surface.Test plan
pytest tests/stages/audio/filtering -q