Skip to content

feat(audio-tagging): output control + in-memory handoff + agent-ready contracts - #2339

Open
shubhamNvidia wants to merge 1 commit into
NVIDIA-NeMo:mainfrom
shubhamNvidia:agent/tagging
Open

feat(audio-tagging): output control + in-memory handoff + agent-ready contracts#2339
shubhamNvidia wants to merge 1 commit into
NVIDIA-NeMo:mainfrom
shubhamNvidia:agent/tagging

Conversation

@shubhamNvidia

Copy link
Copy Markdown
Contributor

Contracts: describe() + *_key params across the tagging stages (ASR-align, merge-alignment-diarization, prepare-module-segments, resample, split, and the Chinese-conversion / inverse-text-normalization text stages). Includes the SplitASRAlignJoinStage composite contract, so the planner can see through the composite to the sub-stages it expands into rather than treating it as an opaque box.

New functionality

  • In-memory handoff on resample (keep_waveform_in_task, write_to_disk) — a resample feeding an ASR stage no longer has to land on disk first.

  • Stable output naming on resample (fixes duplicate and stale files). The output was named after the input path. That broke in three ways, all now covered by tests:

    • A row fed from an in-memory waveform has only a scratch path, which differs every run — so every run wrote a fresh set of files. Measured on one corpus: 129 files on disk for 65 manifest rows.
    • Two recordings sharing a basename (same filename in different folders) wrote to the same output and silently overwrote each other.
    • Re-running at a different target rate produced the same filename, so the pipeline served the old conversion.

    The output is now named from a digest of the audio content plus the settings being applied (target_sample_rate, target_nchannels, target_format). Rows that already carry a real input path keep the name they have always had — the digest only stands in where the path cannot.

  • update_audio_filepath on resample — choose whether downstream stages see the resampled file or the original path, instead of that being decided for you.

  • Configurable outputsoutput_dir on split (where the chunks go) and output_suffix on the text stages (_ITN, _simplified), so a pipeline can direct these without editing code.

Depends on the agent-ready foundation, #2332 — that must merge first (this branch imports nemo_curator/stages/audio/_agent/, so CI here stays red until it lands).

Adds describe() contracts to the tagging stages (ASR-align, merge-alignment-diarization, prepare-module-segments, resample, split, and the text normalizers) so a planner can tell what each reads and writes before running it.

Depends on the agent-ready foundation (nemo_curator/stages/audio/_agent/), which must merge first.

Signed-off-by: Shubham Bhawsar <shbhawsar@nvidia.com>
@copy-pr-bot

copy-pr-bot Bot commented Aug 25, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@shubhamNvidia
shubhamNvidia marked this pull request as ready for review August 25, 2026 11:19
@shubhamNvidia
shubhamNvidia requested a review from a team as a code owner August 25, 2026 11:19
@shubhamNvidia
shubhamNvidia requested review from sarahyurick and removed request for a team August 25, 2026 11:19
@greptile-apps

greptile-apps Bot commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds agent-readable contracts and configurable metadata keys across audio-tagging stages, plus in-memory resampling, stable resample naming, configurable split destinations, and configurable text-output suffixes.

  • Adds file-or-waveform residency handling and independent disk/waveform output controls to resampling.
  • Makes resample output naming collision-resistant and validates existing conversions before reuse.
  • Adds configurable split destinations and propagates segment-key configuration through the split/ASR/join composite.
  • Adds StageContract descriptions to ASR, merge, segment-preparation, split/join, and text-normalization stages.

Confidence Score: 4/5

The PR should not merge until output_dir either correctly writes through the selected remote filesystem or explicitly rejects non-local destinations.

A remote split destination can advertise cloud chunk URLs without placing audio at those URLs, breaking the downstream split-and-align flow; the in-memory resample path also leaks a temporary file when waveform loading fails.

Files Needing Attention: nemo_curator/stages/audio/tagging/split.py, nemo_curator/stages/audio/tagging/resample_audio.py

Important Files Changed

Filename Overview
nemo_curator/stages/audio/tagging/resample_audio.py Adds residency-aware resampling, stable output identity, atomic replacement, and configurable outputs; failure cleanup misses the temporary in-memory output.
nemo_curator/stages/audio/tagging/split.py Adds configurable chunk destinations and composite contracts, but remote output directories produce mismatched write and advertised paths.
nemo_curator/stages/audio/tagging/inference/nemo_asr_align.py Parameterizes ASR metadata keys and publishes an agent-readable stage contract.
nemo_curator/stages/audio/tagging/prepare_module_segments.py Parameterizes segment, duration, and metrics keys while declaring deterministic per-row behavior.
nemo_curator/stages/audio/tagging/text/chinese_conversion.py Adds configurable segment keys and converted-text suffixes with matching contract metadata.
nemo_curator/stages/audio/tagging/text/itn.py Adds configurable segment keys and ITN output suffixes with matching contract metadata.
tests/stages/audio/tagging/test_resample_audio.py Covers stable naming, rate changes, fan-out collisions, and memory-only conversion, but not temporary cleanup after load failures.
tests/stages/audio/tagging/test_split.py Covers local split destinations and basename collisions but does not exercise remote output_dir behavior.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Input[File or in-memory waveform] --> Resample[ResampleAudioStage]
  Resample -->|write_to_disk| ResampledFile[Resampled file]
  Resample -->|keep_waveform_in_task| Waveform[Waveform and sample rate]
  ResampledFile --> Split[SplitLongAudioStage]
  Split --> Chunks[Split chunk files and metadata]
  Chunks --> ASR[NeMoASRAlignerStage]
  ASR --> Join[JoinSplitAudioMetadataStage]
  Join --> Output[Joined text and alignment]
Loading

Reviews (1): Last reviewed commit: "feat(audio-tagging): make tagging stages..." | Re-trigger Greptile

if self.output_dir is None:
split_filepath = f"{parent_url}/{split_name}" if parent_url else split_name
split_resolved = f"{resolved_parent}/{split_name}" if resolved_parent else split_name
return split_filepath, split_resolved

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Remote split writes diverge

If output_dir is a remote URL, _split_paths advertises that URL but passes its protocol-stripped path to torchaudio.save, causing chunks to be written locally or fail while downstream ASR reads nonexistent remote objects.

Knowledge Base Used: Audio curation stages

Comment on lines +286 to +295
if self.keep_waveform_in_task:
waveform, sample_rate = load_audio_file(output_audio_path, mono=False)
data_entry[self.waveform_key] = waveform
data_entry[self.sample_rate_key] = sample_rate
duration = get_audio_duration(output_audio_path)
data_entry[self.duration_key] = duration
if not self.write_to_disk:
try: # noqa: SIM105
os.remove(output_audio_path)
except OSError:

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Temporary output leaks on failure

With write_to_disk=False, an exception from load_audio_file occurs before output_audio_path is removed, leaving one converted temporary file behind for every failed in-memory handoff.

Knowledge Base Used: Audio curation stages

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant