audiogear
Annotate speech/TTS datasets with per-clip quality metrics (MOS, SNR, STOI, pitch, bandwidth, speaking rate, WER/CER, gender/emotion), multi-ASR consensus transcription and speaker labeling using the audiogear pipeline; then filter clips by quality and build listenable HTML QA reports. Use when asked to compute audio dataset metrics, build extended_metadata.csv, transcribe unlabeled audio, select clean TTS training data, or QA a speech dataset.
含まれるファイル(109)
- SKILL.md9.7 KB
- .env.example360 B
- .gitignore872 B
- configs/annotate.yaml3.0 KB
- configs/config.yaml693 B
- configs/executor/local.yaml730 B
- configs/metric/bandwidth.yaml192 B
- configs/metric/brouhaha_snr_reverb.yaml217 B
- configs/metric/distillmos.yaml136 B
- configs/metric/emotion.yaml153 B
- configs/metric/gender.yaml124 B
- configs/metric/gigaam_multilingual.yaml743 B
- configs/metric/gigaam_v3.yaml844 B
- configs/metric/pitch.yaml631 B
- configs/metric/speaker.yaml256 B
- configs/metric/speaking_rate.yaml177 B
- configs/metric/squim.yaml134 B
- configs/metric/style.yaml129 B
- configs/metric/wada_snr.yaml108 B
- configs/metric/wer.yaml201 B
- configs/reader/csv.yaml376 B
- configs/reader/folder.yaml256 B
- configs/reader/ru.yaml440 B
- configs/resd.yaml2.8 KB
- configs/writer/csv.yaml123 B
- configs/writer/jsonl.yaml120 B
- docs/multi-node.md3.6 KB
- docs/README.md641 B
- docs/storage.md4.1 KB
- docs/testing.md5.3 KB
- eval/sanity_distillmos.py3.0 KB
- examples/filter_clean.py4.4 KB
- examples/gen_configs.py6.1 KB
- examples/qa_report.py12.9 KB
- examples/README.md2.3 KB
- examples/run_batch.py4.4 KB
- LICENSE1.1 KB
- process.py931 B
- pyproject.toml4.3 KB
- README.md28.5 KB
- src/audiogear/__init__.py847 B
- src/audiogear/audio.py3.7 KB
- src/audiogear/build.py4.6 KB
- src/audiogear/data.py1.2 KB
- src/audiogear/executer/__init__.py0 B
- src/audiogear/executer/base.py5.7 KB
- src/audiogear/executer/local.py6.3 KB
- src/audiogear/io.py9.2 KB
- src/audiogear/pipeline/__init__.py0 B
- src/audiogear/pipeline/base.py2.2 KB
- src/audiogear/pipeline/checkpoint.py3.2 KB
- src/audiogear/pipeline/metrics/__init__.py0 B
- src/audiogear/pipeline/metrics/accent.py1.6 KB
- src/audiogear/pipeline/metrics/bandwidth.py2.3 KB
- src/audiogear/pipeline/metrics/base.py25.9 KB
- src/audiogear/pipeline/metrics/brouhaha_snr_reverb.py2.3 KB
- src/audiogear/pipeline/metrics/distillmos.py2.1 KB
- src/audiogear/pipeline/metrics/emotion.py1.3 KB
- src/audiogear/pipeline/metrics/gender.py1.3 KB
- src/audiogear/pipeline/metrics/gigaam_v3.py6.9 KB
- src/audiogear/pipeline/metrics/hf.py7.9 KB
- src/audiogear/pipeline/metrics/models/__init__.py0 B
- src/audiogear/pipeline/metrics/models/brouhaha_vad.py12.1 KB
- src/audiogear/pipeline/metrics/models/nisqa/__init__.py0 B
- src/audiogear/pipeline/metrics/pitch.py6.0 KB
- src/audiogear/pipeline/metrics/punctuation.py5.9 KB
- src/audiogear/pipeline/metrics/speaker.py11.6 KB
- src/audiogear/pipeline/metrics/speaking_rate.py4.6 KB
- src/audiogear/pipeline/metrics/squim.py2.5 KB
- src/audiogear/pipeline/metrics/style.py2.1 KB
- src/audiogear/pipeline/metrics/wada_snr.py4.0 KB
- src/audiogear/pipeline/metrics/wav2vec_mos.py1.3 KB
- src/audiogear/pipeline/metrics/wer.py3.5 KB
- src/audiogear/pipeline/parallel.py5.2 KB
- src/audiogear/pipeline/readers/__init__.py27 B
- src/audiogear/pipeline/readers/base.py6.1 KB
- src/audiogear/pipeline/readers/csv.py3.3 KB
- src/audiogear/pipeline/readers/folder.py3.9 KB
- src/audiogear/pipeline/readers/huggingface.py2.8 KB
- src/audiogear/pipeline/readers/jsonl.py1.9 KB
- src/audiogear/pipeline/segmenters/__init__.py0 B
- src/audiogear/pipeline/segmenters/base.py3.7 KB
- src/audiogear/pipeline/segmenters/whisper.py5.5 KB
- src/audiogear/pipeline/transcribers/__init__.py415 B
- src/audiogear/pipeline/transcribers/backends.py4.9 KB
- src/audiogear/pipeline/transcribers/base.py1.6 KB
- src/audiogear/pipeline/transcribers/consensus.py6.9 KB
- src/audiogear/pipeline/writers/__init__.py0 B
- src/audiogear/pipeline/writers/base_disk.py3.5 KB
- src/audiogear/pipeline/writers/csv.py4.3 KB
- src/audiogear/pipeline/writers/jsonl.py708 B
- src/audiogear/utils/__init__.py0 B
- src/audiogear/utils/import_utils.py479 B
- src/audiogear/utils/logging.py1.6 KB
- src/audiogear/utils/progress.py1.3 KB
- src/audiogear/utils/runtime.py6.5 KB
- tests/conftest.py831 B
- tests/test_checkpoint_resume.py4.7 KB
- tests/test_csv_roundtrip.py1.4 KB
- tests/test_csv_writer.py5.5 KB
- tests/test_merge_dedup.py1.9 KB
- tests/test_metric_columns.py912 B
- tests/test_metric_guard.py6.0 KB
- tests/test_metric_scheduling.py2.7 KB
- tests/test_progress.py1.3 KB
- tests/test_punct_transfer.py4.1 KB
- tests/test_reader_adapter.py1.6 KB
- tests/test_runtime.py3.2 KB
- tests/test_wer_normalize.py748 B
SKILL.md(原文)
インストールする前に、エージェントに与えられる指示の中身を確認できます。
audiogear — speech-dataset annotation pipeline
audiogear (https://github.com/lIkesimba9/audiogear) computes per-clip features over a speech dataset: reader → metric blocks → CSV writer, configured with Hydra, sharded across GPUs/nodes. This skill drives it from any project.
Copy this file into the consuming project as
.claude/skills/audiogear/SKILL.md. SetAUDIOGEAR_HOMEbelow to wherever the audiogear checkout lives.
Setup (once per machine)
export AUDIOGEAR_HOME=~/audiogear # adjust; add to the project env
git clone https://github.com/lIkesimba9/audiogear.git "$AUDIOGEAR_HOME" || true
cd "$AUDIOGEAR_HOME"
uv sync --extra ru-pipeline # or à-la-carte: --extra mos --extra asr --extra pitch
sudo apt-get install -y espeak-ng # needed only for SpeakingRateMetric
cp -n .env.example .env # put HF_TOKEN= in .env for gated models (pyannote)
Python 3.10–3.12. GigaAM pins torch <2.6 — do not "upgrade" torch inside this venv.
Input contract
One directory per dataset with a |-delimited metadata.csv:
<data_root>/<dataset>/
metadata.csv # one row per clip
audio/... # referenced by audio_path, relative to the dataset dir
Required columns: id (unique), audio_path, text (may be empty).
All other columns pass through untouched; computed metric columns are appended.
If the source data has a different shape, first write a converter that produces
this layout (see build_betterset-style scripts) — do NOT teach audiogear the
foreign schema.
Core workflow
1. Write a dataset config
Create $AUDIOGEAR_HOME/configs/feat_<ds>.yaml. Proven template (mirrors the
generated feat_* configs) with CPU∥GPU lanes so DSP metrics hide under GPU
time:
defaults:
- reader: ru # CsvReader preset: delimiter "|", audio_key=audio_path, id_key=id
- writer: csv
- executor: local
- _self_
hydra:
job: {chdir: false}
run: {dir: .}
output_subdir: null
device: cuda
reader:
data_folder: /path/to/data_root/<ds>
glob_pattern: metadata.csv
limit: -1 # set to 10 for a dry run
writer:
output_folder: outputs/<ds>
output_filename: ext_$rank.csv
sep: "|"
executor:
tasks: 8 # shards; rows are split round-robin
workers: 2 # concurrent processes; each pins ONE GPU (rank % gpus)
skip_completed: true
logging_dir: logs/<ds>
metrics:
- _target_: audiogear.pipeline.parallel.ParallelLanes
lanes:
cpu:
- _target_: audiogear.pipeline.metrics.bandwidth.BandwidthMetric
- _target_: audiogear.pipeline.metrics.wada_snr.SnrMetric
- _target_: audiogear.pipeline.metrics.speaking_rate.SpeakingRateMetric
language: ru
gpu:
- _target_: audiogear.pipeline.metrics.distillmos.DistillMosMetric
device: ${device}
- _target_: audiogear.pipeline.metrics.squim.SquimMetrics
device: ${device}
- _target_: audiogear.pipeline.metrics.pitch.CrepePitchMetric
device: ${device}
crepe_model: tiny
- _target_: audiogear.pipeline.metrics.style.StyleMetric # after pitch (reuses pitch_*)
- _target_: audiogear.pipeline.metrics.gender.GenderMetric
device: ${device}
Add WhisperWer to the gpu lane only when text is human-authored.
Lane rules (violating them corrupts data silently):
- lanes must write disjoint columns;
- a metric that consumes another's output (
StyleMetric←pitch_mean,WhisperWer/SpeakingRateMetric←text) goes in the SAME lane, after its producer; a producer needed by both lanes (e.g.ConsensusTranscriber) runs as an ordinary step BEFORE the lanes block.
2. Dry run, then full run
cd "$AUDIOGEAR_HOME"
uv run python process.py --config-name feat_<ds> reader.limit=10 # smoke test, downloads models
uv run python process.py --config-name feat_<ds> # full run
Multi-GPU: executor.workers=<n_gpus>. executor.gpus is an int (count),
never a list. Never set CUDA_VISIBLE_DEVICES yourself — the executor pins it.
Multi-node: launch the same command once per node under SLURM, or set
AUDIOGEAR_NODE_RANK/AUDIOGEAR_NUM_NODES; put executor.logging_dir on
shared storage.
3. Merge shards → extended_metadata.csv
Each shard writes outputs/<ds>/ext_<rank>.csv. Merge with id-dedup (duplicates
appear if executor.tasks changed between an interrupted run and its rerun):
export AUDIOGEAR_DATA_DIR=/path/to/data_root
uv run python examples/run_batch.py <ds> # run + merge + .FEAT_DONE marker per dataset
For many datasets, examples/gen_configs.py generates the per-dataset configs
and examples/run_batch.py sweeps them smallest-first with resume.
4. Filter + QA
uv run python examples/filter_clean.py <ds> # extended_metadata.csv -> clean_metadata.csv + drop reasons
uv run python examples/qa_report.py <ds> # -> <data_root>/<ds>/qa_report.html
qa_report.html is self-contained: metric histograms with the filter thresholds
drawn in, and playable audio just below/just above each threshold. To calibrate
thresholds: listen to both sides — rejected clips sounding fine ⇒ threshold too
strict; accepted clips sounding bad ⇒ too loose. Edit TH in
examples/filter_clean.py (single source of truth for filter and report) and
regenerate. Set HUMAN_TEXT/ASR_TEXT there: the CER filter is only valid
where text was written by humans, not by an ASR model.
Metric catalogue
Class (audiogear.pipeline.metrics.*) | Columns | Notes |
|---|---|---|
distillmos.DistillMosMetric | distillmos | no-ref MOS, GPU |
squim.SquimMetrics | pyt_stoi, pyt_pesq, pyt_si_sdr | GPU, never batched (padding skews scores) |
wada_snr.SnrMetric | wada_snr | blind SNR, CPU |
bandwidth.BandwidthMetric | bandwidth_hz, is_upsampled_est | detects upsampled audio; container sample_rate lies |
pitch.CrepePitchMetric / pitch.PitchMetric | pitch_mean, pitch_std | GPU torchcrepe / CPU pyin |
style.StyleMetric | energy_db, energy_dynamics, expressiveness | CPU; reuses pitch_* if present |
speaking_rate.SpeakingRateMetric | speaking_rate, phonemes_per_word, char_rate | espeak-ng; NOT thread-safe — leave it serial |
wer.WhisperWer | whisper_wer, whisper_cer | vs text; -1 when no reference. Skip for ASR-derived text (CER≈0, meaningless, expensive) |
gigaam_v3.GigaAMv3 | gigaam3_text, gigaam3_cer, text_punctuated, opt-in words JSON | punctuated-from-audio RU transcript + punctuation transferred onto reference words; model_name: multilingual_ctc for ru/en/kk/ky/uz (no punctuation — set punct_column: null); words_column adds word timestamps |
gender.GenderMetric / emotion.EmotionMetric | gender_pred / emotion_pred, emotion_score | _pred suffix — never overwrite curated columns |
hf.HFAudioModelMetric | configurable | any 🤗 audio classification/regression model, config-only |
brouhaha_snr_reverb.SnrReverbMetrics | snr, c50 | pyannote, gated (HF_TOKEN) |
speaker.SpeakerLabeler | speaker, speaker_conf, speaker_margin | dataset-level clustering — run with executor.tasks=1 |
transcribers.consensus.ConsensusTranscriber | text, asr_text_*, asr_agreement | multi-ASR medoid; for datasets without transcripts |
Reliability semantics (what to expect downstream)
- Sentinels, not crashes. A corrupt/unscorable clip never kills a run: the
per-clip guard writes NaN (or
-1for WER/CER/SQUIM) and continues. Always treat NaN and negative metric values as "no value" when filtering. A long unbroken failure streak (default 50) aborts the shard — that means a systematic problem (model/config), not bad data. - Resume is two-level. Completed shards are skipped via markers in
logging_dir; inside an unfinished shard, per-metric JSONL checkpoints in<output_folder>/checkpoints/resume from the last computed clip. Rerunning the same command after any crash is always safe. Checkpoints are keyed by clip id only — after changing a metric's model/parameters, delete<output_folder>/checkpoints/(or the run reuses stale values). Disable withresume: falsein the config.
Pitfalls checklist
executor.gpus: 1(int) —gpus: [0]breaks.- Whisper
compute_type: int8_float16when 2 workers share a GPU (halves VRAM). - Clips >25 s are truncated by GigaAMv3; SQUIM needs ≥1024 samples (else -1).
- Audio must be locally readable (torchaudio); CSVs/outputs/logs may be
s3://…(fsspec), audio may not — FUSE-mount buckets instead. - Models load lazily per worker process — first clips are slow, that's normal.
- Adding a metric: subclass
BaseMetric, implementcompute_metric(segment), setmetric=to the column name(s). Do NOT add try/except around it — the base class guards every path already. Load models lazily viaaudiogear.utils.runtime.cached_model.
Programmatic use (no CLI)
from omegaconf import OmegaConf
from audiogear.build import build_pipeline
cfg = OmegaConf.create({...}) # same shape as a yaml config
data = None
for step in build_pipeline(cfg): # reader -> metrics -> writer
data = step(data, 0, 1) # (data, rank, world_size)
# data: list[AudioSegment]; computed values in segment.metadata
レビュー
まだレビューはありません。使ってみた感想をお寄せください。