audiotrove 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- audiotrove-0.1.0/LICENSE +21 -0
- audiotrove-0.1.0/PKG-INFO +352 -0
- audiotrove-0.1.0/README.md +280 -0
- audiotrove-0.1.0/audiotrove/__init__.py +1 -0
- audiotrove-0.1.0/audiotrove/base.py +60 -0
- audiotrove-0.1.0/audiotrove/cli/__init__.py +0 -0
- audiotrove-0.1.0/audiotrove/cli/main.py +297 -0
- audiotrove-0.1.0/audiotrove/document.py +25 -0
- audiotrove-0.1.0/audiotrove/executor/__init__.py +0 -0
- audiotrove-0.1.0/audiotrove/executor/local.py +381 -0
- audiotrove-0.1.0/audiotrove/exporters/__init__.py +5 -0
- audiotrove-0.1.0/audiotrove/exporters/tts_manifest.py +71 -0
- audiotrove-0.1.0/audiotrove/filters/__init__.py +0 -0
- audiotrove-0.1.0/audiotrove/filters/duration.py +30 -0
- audiotrove-0.1.0/audiotrove/filters/enhance.py +80 -0
- audiotrove-0.1.0/audiotrove/filters/snr.py +63 -0
- audiotrove-0.1.0/audiotrove/filters/vad.py +365 -0
- audiotrove-0.1.0/audiotrove/io/__init__.py +0 -0
- audiotrove-0.1.0/audiotrove/io/readers.py +176 -0
- audiotrove-0.1.0/audiotrove/io/writers.py +30 -0
- audiotrove-0.1.0/audiotrove/pipelines/__init__.py +5 -0
- audiotrove-0.1.0/audiotrove/pipelines/tts.py +70 -0
- audiotrove-0.1.0/audiotrove/transformers/__init__.py +5 -0
- audiotrove-0.1.0/audiotrove/transformers/silence_trim.py +76 -0
- audiotrove-0.1.0/audiotrove/utils/__init__.py +0 -0
- audiotrove-0.1.0/audiotrove/utils/hashing.py +5 -0
- audiotrove-0.1.0/audiotrove.egg-info/PKG-INFO +352 -0
- audiotrove-0.1.0/audiotrove.egg-info/SOURCES.txt +47 -0
- audiotrove-0.1.0/audiotrove.egg-info/dependency_links.txt +1 -0
- audiotrove-0.1.0/audiotrove.egg-info/entry_points.txt +2 -0
- audiotrove-0.1.0/audiotrove.egg-info/requires.txt +32 -0
- audiotrove-0.1.0/audiotrove.egg-info/top_level.txt +1 -0
- audiotrove-0.1.0/pyproject.toml +88 -0
- audiotrove-0.1.0/setup.cfg +4 -0
- audiotrove-0.1.0/tests/test_additional_coverage.py +99 -0
- audiotrove-0.1.0/tests/test_cli.py +354 -0
- audiotrove-0.1.0/tests/test_document.py +26 -0
- audiotrove-0.1.0/tests/test_enhance.py +16 -0
- audiotrove-0.1.0/tests/test_executor.py +316 -0
- audiotrove-0.1.0/tests/test_executor_and_cli.py +217 -0
- audiotrove-0.1.0/tests/test_interfaces.py +50 -0
- audiotrove-0.1.0/tests/test_parallel_executor.py +82 -0
- audiotrove-0.1.0/tests/test_readers.py +233 -0
- audiotrove-0.1.0/tests/test_snr.py +95 -0
- audiotrove-0.1.0/tests/test_tts_pipeline.py +115 -0
- audiotrove-0.1.0/tests/test_vad.py +64 -0
- audiotrove-0.1.0/tests/test_vad_segmentation.py +246 -0
- audiotrove-0.1.0/tests/test_vad_snr.py +129 -0
- audiotrove-0.1.0/tests/test_writer.py +110 -0
audiotrove-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Palak Jha
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: audiotrove
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Composable audio dataset curation pipeline: VAD, SNR, segmentation, checkpointing
|
|
5
|
+
Author-email: Palak Jha <palakjha916@gmail.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Palak Jha
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/onepizzateam/AudioTrove
|
|
29
|
+
Project-URL: Repository, https://github.com/onepizzateam/AudioTrove
|
|
30
|
+
Project-URL: Bug Tracker, https://github.com/onepizzateam/AudioTrove/issues
|
|
31
|
+
Keywords: audio,dataset,machine-learning,vad,speech-processing,data-curation
|
|
32
|
+
Classifier: Development Status :: 4 - Beta
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
37
|
+
Classifier: Intended Audience :: Developers
|
|
38
|
+
Classifier: Intended Audience :: Science/Research
|
|
39
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Analysis
|
|
40
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
41
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
42
|
+
Requires-Python: >=3.10
|
|
43
|
+
Description-Content-Type: text/markdown
|
|
44
|
+
License-File: LICENSE
|
|
45
|
+
Requires-Dist: torch>=2.0.0
|
|
46
|
+
Requires-Dist: torchaudio>=2.0.0
|
|
47
|
+
Requires-Dist: numpy>=1.24.0
|
|
48
|
+
Requires-Dist: soundfile
|
|
49
|
+
Requires-Dist: fsspec>=2023.1.0
|
|
50
|
+
Requires-Dist: click>=8.1.0
|
|
51
|
+
Requires-Dist: rich>=13.0.0
|
|
52
|
+
Requires-Dist: pyyaml>=6.0
|
|
53
|
+
Provides-Extra: enhance
|
|
54
|
+
Requires-Dist: deepfilternet; extra == "enhance"
|
|
55
|
+
Provides-Extra: s3
|
|
56
|
+
Requires-Dist: s3fs>=2023.1.0; extra == "s3"
|
|
57
|
+
Provides-Extra: gcs
|
|
58
|
+
Requires-Dist: gcsfs>=2023.1.0; extra == "gcs"
|
|
59
|
+
Provides-Extra: diarize
|
|
60
|
+
Requires-Dist: pyannote.audio>=3.1.0; extra == "diarize"
|
|
61
|
+
Provides-Extra: embed-dedup
|
|
62
|
+
Requires-Dist: faiss-cpu>=1.7.4; extra == "embed-dedup"
|
|
63
|
+
Requires-Dist: speechbrain>=1.0.0; extra == "embed-dedup"
|
|
64
|
+
Provides-Extra: dev
|
|
65
|
+
Requires-Dist: pytest; extra == "dev"
|
|
66
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
67
|
+
Requires-Dist: ruff; extra == "dev"
|
|
68
|
+
Requires-Dist: mypy; extra == "dev"
|
|
69
|
+
Requires-Dist: click[testing]; extra == "dev"
|
|
70
|
+
Requires-Dist: scipy>=1.10.0; extra == "dev"
|
|
71
|
+
Dynamic: license-file
|
|
72
|
+
|
|
73
|
+
# AudioTrove
|
|
74
|
+
|
|
75
|
+
> Reproducible audio curation for teams building speech and TTS datasets from raw recordings.
|
|
76
|
+
|
|
77
|
+
[](https://github.com/onepizzateam/AudioTrove/actions)
|
|
78
|
+
[](https://www.python.org/)
|
|
79
|
+
[](LICENSE)
|
|
80
|
+
|
|
81
|
+
## What AudioTrove is
|
|
82
|
+
|
|
83
|
+
Building a TTS corpus from raw audio is repetitive and easy to get wrong:
|
|
84
|
+
files need decoding and normalization, silence must be removed consistently,
|
|
85
|
+
speech and noise quality must be checked, rejected clips need accounting, and
|
|
86
|
+
an interrupted run must not make a team start from zero. AudioTrove packages
|
|
87
|
+
those steps into a local, resumable curation pipeline.
|
|
88
|
+
|
|
89
|
+
It discovers local audio, runs real Silero VAD, trims leading and trailing
|
|
90
|
+
silence, estimates SNR, applies post-trim duration bounds, and writes curated
|
|
91
|
+
WAVs plus LJSpeech- and F5-TTS-compatible manifests. Every processed document
|
|
92
|
+
is recorded in SQLite, giving repeated runs deterministic skip behavior rather
|
|
93
|
+
than an ad-hoc ffmpeg loop that must be manually reconciled.
|
|
94
|
+
|
|
95
|
+
AudioTrove is deliberately a curation tool, not a transcription service or a
|
|
96
|
+
model trainer. It produces inspectable training inputs and manifests that a
|
|
97
|
+
training framework can consume. The detailed component contracts live in
|
|
98
|
+
[ARCHITECTURE.md](ARCHITECTURE.md).
|
|
99
|
+
|
|
100
|
+
## Features
|
|
101
|
+
|
|
102
|
+
- Uses Silero VAD with cached local loading and a non-interactive `trust_repo=True` remote fallback.
|
|
103
|
+
- Computes VAD-aware SNR and records `snr_db` on each processed document.
|
|
104
|
+
- Trims outer silence while retaining configurable padding on both sides of speech.
|
|
105
|
+
- Applies duration bounds after trimming, with explicit short/long rejection metadata.
|
|
106
|
+
- Writes curated WAV files and LJSpeech `metadata.csv` plus F5-TTS `filelist.txt`.
|
|
107
|
+
- Stores processed document IDs in SQLite so interrupted runs can resume.
|
|
108
|
+
- Supports sequential execution and multi-worker local execution.
|
|
109
|
+
- Discovers WAV, FLAC, and other requested extensions through `fsspec` globs.
|
|
110
|
+
- Processed LibriSpeech dev-clean (5.39 h, 2,703 clips) at 6.3 RTFx with one worker.
|
|
111
|
+
- Uses Ruff in the declared development tooling.
|
|
112
|
+
|
|
113
|
+
## Requirements
|
|
114
|
+
|
|
115
|
+
AudioTrove requires Python 3.10 or later. Core dependencies declare
|
|
116
|
+
`torch>=2.0.0`, `torchaudio>=2.0.0`, `numpy>=1.24.0`, `soundfile`, `fsspec`,
|
|
117
|
+
Click, Rich, and PyYAML. Torchaudio is the preferred decoder; the reader falls
|
|
118
|
+
back to soundfile when appropriate. ffmpeg is not a direct Python dependency,
|
|
119
|
+
but may be needed by the torchaudio backend for formats it cannot decode alone.
|
|
120
|
+
|
|
121
|
+
The test suite is designed for Windows, macOS, and Linux. On Windows,
|
|
122
|
+
multi-worker execution uses a thread pool so the loaded Silero model is shared
|
|
123
|
+
safely; on other platforms it uses process workers.
|
|
124
|
+
|
|
125
|
+
## Installation
|
|
126
|
+
|
|
127
|
+
Install the source checkout:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
git clone https://github.com/onepizzateam/AudioTrove.git
|
|
131
|
+
cd AudioTrove
|
|
132
|
+
python -m pip install -e .
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Install development tooling when running tests or lint:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
python -m pip install -e ".[dev]"
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
Verify that the command is available:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
audiotrove --version
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Quickstart
|
|
148
|
+
|
|
149
|
+
### Curate a WAV directory
|
|
150
|
+
|
|
151
|
+
For ordinary WAV recordings, use the TTS pipeline’s defaults: two to fifteen
|
|
152
|
+
seconds after trimming, 20 dB SNR, 150 ms retained silence, and one worker.
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
audiotrove curate ./recordings ./curated-tts --tts
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
The CLI reports a TTS completion summary with kept and filtered counts, total
|
|
159
|
+
duration for that invocation, and manifest paths. It creates the output
|
|
160
|
+
directory before processing.
|
|
161
|
+
|
|
162
|
+
### Curate a FLAC corpus with four workers
|
|
163
|
+
|
|
164
|
+
Use explicitly requested extensions and stricter SNR when source audio is a
|
|
165
|
+
FLAC corpus:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
audiotrove curate ./speech-flac ./curated-flac --tts \
|
|
169
|
+
--extensions flac --workers 4 --tts-snr-min 25 \
|
|
170
|
+
--tts-min-duration 2 --tts-max-duration 15
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
After a successful run, the directory contains artifacts like:
|
|
174
|
+
|
|
175
|
+
```text
|
|
176
|
+
curated-flac/
|
|
177
|
+
├── checkpoint.db
|
|
178
|
+
├── metadata.csv
|
|
179
|
+
├── filelist.txt
|
|
180
|
+
├── speaker-0001.wav
|
|
181
|
+
└── speaker-0002.wav
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## Pipeline explained
|
|
185
|
+
|
|
186
|
+
A discovered file is loaded by `LocalAudioReader`, downmixed to mono, and
|
|
187
|
+
resampled to 16 kHz. The executor presents that `AudioDocument` to
|
|
188
|
+
`SileroVADFilter`, which records speech timestamps and speech ratio. A clip
|
|
189
|
+
with too little speech stops there and is counted as skipped; it does not stop
|
|
190
|
+
the run.
|
|
191
|
+
|
|
192
|
+
For a surviving clip, `SilenceTrimmingTransformer` finds the outermost speech
|
|
193
|
+
timestamps, keeps the requested padding, updates the audio array and duration,
|
|
194
|
+
and shifts timestamps to the trimmed origin. `SNRFilter` then uses the VAD
|
|
195
|
+
speech/non-speech regions to calculate an SNR estimate. Finally,
|
|
196
|
+
`DurationBucketFilter` checks the post-trim duration. A failure at any filter
|
|
197
|
+
short-circuits that file, records its original document ID in the checkpoint,
|
|
198
|
+
and lets the executor continue with later files.
|
|
199
|
+
|
|
200
|
+
```text
|
|
201
|
+
glob/file input
|
|
202
|
+
-> LocalAudioReader (decode, mono, 16 kHz)
|
|
203
|
+
-> SileroVADFilter (speech timestamps and ratio)
|
|
204
|
+
-> SilenceTrimmingTransformer (trim leading/trailing silence)
|
|
205
|
+
-> SNRFilter (speech/noise power estimate)
|
|
206
|
+
-> DurationBucketFilter (post-trim bounds)
|
|
207
|
+
-> TTSManifestExporter (WAV + manifests)
|
|
208
|
+
-> checkpoint.db
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Accepted documents are exported as WAV and appended to requested manifests.
|
|
212
|
+
The executor, not a worker, owns export and SQLite writes; this makes manifest
|
|
213
|
+
and checkpoint mutation serial and resumable.
|
|
214
|
+
|
|
215
|
+
## CLI reference
|
|
216
|
+
|
|
217
|
+
Use `audiotrove curate INPUT_PATH OUTPUT_PATH --tts`. TTS-specific options are
|
|
218
|
+
listed first. The remaining flags belong to the generic JSONL path and are
|
|
219
|
+
accepted by the same command but do not configure `tts_pipeline()`.
|
|
220
|
+
|
|
221
|
+
| Flag | Type | Default | Description |
|
|
222
|
+
|---|---|---:|---|
|
|
223
|
+
| `--tts` | flag | `False` | Run TTS curation and manifest export. |
|
|
224
|
+
| `--tts-min-duration` | float | `2.0` | Minimum TTS duration in seconds. |
|
|
225
|
+
| `--tts-max-duration` | float | `15.0` | Maximum TTS duration in seconds. |
|
|
226
|
+
| `--tts-snr-min` | float | `20.0` | Minimum TTS SNR in dB. |
|
|
227
|
+
| `--workers` | integer | `1` | Local worker count. |
|
|
228
|
+
| `--extensions` | string | `wav` | Comma-separated extensions, for example `wav,mp3,flac`. |
|
|
229
|
+
| `--vad-threshold` | float | `0.3` | Generic-path minimum speech ratio. |
|
|
230
|
+
| `--snr-min` | float | `15.0` | Generic-path minimum SNR in dB. |
|
|
231
|
+
| `--format` | choice | `jsonl` | Generic-path output format. |
|
|
232
|
+
| `--checkpoint` | string | none | Generic-path checkpoint database path. |
|
|
233
|
+
| `--segment` | flag | `False` | Generic-path VAD fan-out segmentation. |
|
|
234
|
+
| `--enhance` | flag | `False` | Generic-path DeepFilterNet2 enhancement. |
|
|
235
|
+
| `-v`, `--verbose` | flag | `False` | Enable DEBUG logging. |
|
|
236
|
+
|
|
237
|
+
The TTS pipeline itself fixes VAD minimum speech ratio at `0.1` and VAD model
|
|
238
|
+
threshold at `0.5`; `--vad-threshold` is not forwarded in TTS mode.
|
|
239
|
+
|
|
240
|
+
## Output format
|
|
241
|
+
|
|
242
|
+
The exporter writes WAV files using each source file’s stem. It then writes a
|
|
243
|
+
LJSpeech row when `ljspeech` is selected and an F5-TTS row when `f5tts` is
|
|
244
|
+
selected. The default requests both formats.
|
|
245
|
+
|
|
246
|
+
`metadata.csv` is pipe-delimited:
|
|
247
|
+
|
|
248
|
+
```text
|
|
249
|
+
1272-128104-0000.wav|speaker_00|
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Columns are `filename`, `speaker_id`, and `transcription`. The transcription
|
|
253
|
+
is an empty string unless `doc.metadata["transcription"]` is set.
|
|
254
|
+
|
|
255
|
+
`filelist.txt` is tab-delimited:
|
|
256
|
+
|
|
257
|
+
```text
|
|
258
|
+
curated-flac/1272-128104-0000.wav 5.3200
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Columns are the curated WAV path, the post-trim duration in seconds, and
|
|
262
|
+
transcription. The path points to the exported WAV, not the untrimmed source.
|
|
263
|
+
WAV names derive from source stems, so source-stem collisions must be avoided
|
|
264
|
+
within one output directory.
|
|
265
|
+
|
|
266
|
+
`checkpoint.db` has a `processed` SQLite table keyed by document ID. It is an
|
|
267
|
+
operational artifact, not a training manifest.
|
|
268
|
+
|
|
269
|
+
## Resumability
|
|
270
|
+
|
|
271
|
+
The executor initializes `checkpoint.db` with a primary-keyed `processed`
|
|
272
|
+
table. Before a document enters the pipeline, it checks that table; after an
|
|
273
|
+
accepted document is exported, or after a rejected original document is
|
|
274
|
+
handled, it inserts the relevant ID. An interrupted run can therefore be
|
|
275
|
+
restarted with the same input and output paths: already recorded IDs are
|
|
276
|
+
skipped, while unrecorded IDs continue through the pipeline.
|
|
277
|
+
|
|
278
|
+
Manifests are opened in append mode. Keep the checkpoint with its output
|
|
279
|
+
directory. Deleting the database while retaining manifests disables skip
|
|
280
|
+
deduplication and can append duplicate rows.
|
|
281
|
+
|
|
282
|
+
## Benchmark
|
|
283
|
+
|
|
284
|
+
The committed benchmark used LibriSpeech dev-clean: 2,703 FLAC clips and
|
|
285
|
+
19,396.1 seconds (5.39 h) of input. It used real cached Silero VAD, not the
|
|
286
|
+
energy fallback. Both configurations retained 2,123 clips and filtered 580.
|
|
287
|
+
|
|
288
|
+
| Workers | Corpus | Kept | Filtered | Wall time | RTFx | Clips/sec |
|
|
289
|
+
|---:|---|---:|---:|---:|---:|---:|
|
|
290
|
+
| 1 | LibriSpeech dev-clean (2703 clips) | 2123 | 580 | 3083.50 s | 6.3× | 0.88 |
|
|
291
|
+
| 4 | LibriSpeech dev-clean (2703 clips) | 2123 | 580 | 1968.61 s | 9.9× | 1.37 |
|
|
292
|
+
|
|
293
|
+
RTFx is total input audio duration divided by wall time. Four workers improve
|
|
294
|
+
throughput by about 1.57× rather than 4× because decoding and WAV/manifests
|
|
295
|
+
require I/O, exports and checkpoints stay in the main process, and Silero
|
|
296
|
+
inference is protected by a shared lock. The result JSON contains aggregate
|
|
297
|
+
kept/filtered counts, not a per-filter rejection breakdown; inspection of
|
|
298
|
+
component metadata/checkpoint data is needed for per-reason analysis.
|
|
299
|
+
|
|
300
|
+
## Integrating with training frameworks
|
|
301
|
+
|
|
302
|
+
F5-TTS-style consumers can read the default tab-separated filelist directly:
|
|
303
|
+
|
|
304
|
+
```python
|
|
305
|
+
for line in open("curated-tts/filelist.txt", encoding="utf-8"):
|
|
306
|
+
wav_path, duration, text = line.rstrip("\n").split("\t")
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
LJSpeech-style consumers can use `metadata.csv` with WAVs in the same output
|
|
310
|
+
directory:
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
for line in open("curated-tts/metadata.csv", encoding="utf-8"):
|
|
314
|
+
filename, speaker_id, text = line.rstrip("\n").split("|", 2)
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
AudioTrove intentionally leaves the transcription field empty when upstream
|
|
318
|
+
metadata has none; generate or attach transcripts before training a supervised
|
|
319
|
+
TTS model.
|
|
320
|
+
|
|
321
|
+
## Extending AudioTrove
|
|
322
|
+
|
|
323
|
+
Custom filters subclass `AudioFilter`, expose a name, and return a boolean
|
|
324
|
+
from `filter`. The executor will short-circuit a false result for that document.
|
|
325
|
+
|
|
326
|
+
```python
|
|
327
|
+
from audiotrove.base import AudioFilter
|
|
328
|
+
|
|
329
|
+
class PeakLimitFilter(AudioFilter):
|
|
330
|
+
name = "peak_limit"
|
|
331
|
+
|
|
332
|
+
def __init__(self, maximum: float = 0.99):
|
|
333
|
+
self.maximum = maximum
|
|
334
|
+
|
|
335
|
+
def filter(self, doc):
|
|
336
|
+
return float(abs(doc.audio).max()) <= self.maximum
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Add the filter to a pipeline list, add focused pass/fail tests, and add an
|
|
340
|
+
end-to-end test where its placement matters. New export formats should follow
|
|
341
|
+
the exporter’s `write(doc)` and `output_files` contract. See
|
|
342
|
+
[ARCHITECTURE.md](ARCHITECTURE.md) for the full extension guide.
|
|
343
|
+
|
|
344
|
+
## Contributing
|
|
345
|
+
|
|
346
|
+
Read [CONTRIBUTING.md](CONTRIBUTING.md) and keep changes small and tested.
|
|
347
|
+
Ruff is included in the development extras; add tests for new components and
|
|
348
|
+
run them across the supported Windows, macOS, and Linux environments.
|
|
349
|
+
|
|
350
|
+
## License
|
|
351
|
+
|
|
352
|
+
AudioTrove is released under the [MIT License](LICENSE).
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
# AudioTrove
|
|
2
|
+
|
|
3
|
+
> Reproducible audio curation for teams building speech and TTS datasets from raw recordings.
|
|
4
|
+
|
|
5
|
+
[](https://github.com/onepizzateam/AudioTrove/actions)
|
|
6
|
+
[](https://www.python.org/)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
|
|
9
|
+
## What AudioTrove is
|
|
10
|
+
|
|
11
|
+
Building a TTS corpus from raw audio is repetitive and easy to get wrong:
|
|
12
|
+
files need decoding and normalization, silence must be removed consistently,
|
|
13
|
+
speech and noise quality must be checked, rejected clips need accounting, and
|
|
14
|
+
an interrupted run must not make a team start from zero. AudioTrove packages
|
|
15
|
+
those steps into a local, resumable curation pipeline.
|
|
16
|
+
|
|
17
|
+
It discovers local audio, runs real Silero VAD, trims leading and trailing
|
|
18
|
+
silence, estimates SNR, applies post-trim duration bounds, and writes curated
|
|
19
|
+
WAVs plus LJSpeech- and F5-TTS-compatible manifests. Every processed document
|
|
20
|
+
is recorded in SQLite, giving repeated runs deterministic skip behavior rather
|
|
21
|
+
than an ad-hoc ffmpeg loop that must be manually reconciled.
|
|
22
|
+
|
|
23
|
+
AudioTrove is deliberately a curation tool, not a transcription service or a
|
|
24
|
+
model trainer. It produces inspectable training inputs and manifests that a
|
|
25
|
+
training framework can consume. The detailed component contracts live in
|
|
26
|
+
[ARCHITECTURE.md](ARCHITECTURE.md).
|
|
27
|
+
|
|
28
|
+
## Features
|
|
29
|
+
|
|
30
|
+
- Uses Silero VAD with cached local loading and a non-interactive `trust_repo=True` remote fallback.
|
|
31
|
+
- Computes VAD-aware SNR and records `snr_db` on each processed document.
|
|
32
|
+
- Trims outer silence while retaining configurable padding on both sides of speech.
|
|
33
|
+
- Applies duration bounds after trimming, with explicit short/long rejection metadata.
|
|
34
|
+
- Writes curated WAV files and LJSpeech `metadata.csv` plus F5-TTS `filelist.txt`.
|
|
35
|
+
- Stores processed document IDs in SQLite so interrupted runs can resume.
|
|
36
|
+
- Supports sequential execution and multi-worker local execution.
|
|
37
|
+
- Discovers WAV, FLAC, and other requested extensions through `fsspec` globs.
|
|
38
|
+
- Processed LibriSpeech dev-clean (5.39 h, 2,703 clips) at 6.3 RTFx with one worker.
|
|
39
|
+
- Uses Ruff in the declared development tooling.
|
|
40
|
+
|
|
41
|
+
## Requirements
|
|
42
|
+
|
|
43
|
+
AudioTrove requires Python 3.10 or later. Core dependencies declare
|
|
44
|
+
`torch>=2.0.0`, `torchaudio>=2.0.0`, `numpy>=1.24.0`, `soundfile`, `fsspec`,
|
|
45
|
+
Click, Rich, and PyYAML. Torchaudio is the preferred decoder; the reader falls
|
|
46
|
+
back to soundfile when appropriate. ffmpeg is not a direct Python dependency,
|
|
47
|
+
but may be needed by the torchaudio backend for formats it cannot decode alone.
|
|
48
|
+
|
|
49
|
+
The test suite is designed for Windows, macOS, and Linux. On Windows,
|
|
50
|
+
multi-worker execution uses a thread pool so the loaded Silero model is shared
|
|
51
|
+
safely; on other platforms it uses process workers.
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
Install the source checkout:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
git clone https://github.com/onepizzateam/AudioTrove.git
|
|
59
|
+
cd AudioTrove
|
|
60
|
+
python -m pip install -e .
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Install development tooling when running tests or lint:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
python -m pip install -e ".[dev]"
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Verify that the command is available:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
audiotrove --version
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Quickstart
|
|
76
|
+
|
|
77
|
+
### Curate a WAV directory
|
|
78
|
+
|
|
79
|
+
For ordinary WAV recordings, use the TTS pipeline’s defaults: two to fifteen
|
|
80
|
+
seconds after trimming, 20 dB SNR, 150 ms retained silence, and one worker.
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
audiotrove curate ./recordings ./curated-tts --tts
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The CLI reports a TTS completion summary with kept and filtered counts, total
|
|
87
|
+
duration for that invocation, and manifest paths. It creates the output
|
|
88
|
+
directory before processing.
|
|
89
|
+
|
|
90
|
+
### Curate a FLAC corpus with four workers
|
|
91
|
+
|
|
92
|
+
Use explicitly requested extensions and stricter SNR when source audio is a
|
|
93
|
+
FLAC corpus:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
audiotrove curate ./speech-flac ./curated-flac --tts \
|
|
97
|
+
--extensions flac --workers 4 --tts-snr-min 25 \
|
|
98
|
+
--tts-min-duration 2 --tts-max-duration 15
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
After a successful run, the directory contains artifacts like:
|
|
102
|
+
|
|
103
|
+
```text
|
|
104
|
+
curated-flac/
|
|
105
|
+
├── checkpoint.db
|
|
106
|
+
├── metadata.csv
|
|
107
|
+
├── filelist.txt
|
|
108
|
+
├── speaker-0001.wav
|
|
109
|
+
└── speaker-0002.wav
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Pipeline explained
|
|
113
|
+
|
|
114
|
+
A discovered file is loaded by `LocalAudioReader`, downmixed to mono, and
|
|
115
|
+
resampled to 16 kHz. The executor presents that `AudioDocument` to
|
|
116
|
+
`SileroVADFilter`, which records speech timestamps and speech ratio. A clip
|
|
117
|
+
with too little speech stops there and is counted as skipped; it does not stop
|
|
118
|
+
the run.
|
|
119
|
+
|
|
120
|
+
For a surviving clip, `SilenceTrimmingTransformer` finds the outermost speech
|
|
121
|
+
timestamps, keeps the requested padding, updates the audio array and duration,
|
|
122
|
+
and shifts timestamps to the trimmed origin. `SNRFilter` then uses the VAD
|
|
123
|
+
speech/non-speech regions to calculate an SNR estimate. Finally,
|
|
124
|
+
`DurationBucketFilter` checks the post-trim duration. A failure at any filter
|
|
125
|
+
short-circuits that file, records its original document ID in the checkpoint,
|
|
126
|
+
and lets the executor continue with later files.
|
|
127
|
+
|
|
128
|
+
```text
|
|
129
|
+
glob/file input
|
|
130
|
+
-> LocalAudioReader (decode, mono, 16 kHz)
|
|
131
|
+
-> SileroVADFilter (speech timestamps and ratio)
|
|
132
|
+
-> SilenceTrimmingTransformer (trim leading/trailing silence)
|
|
133
|
+
-> SNRFilter (speech/noise power estimate)
|
|
134
|
+
-> DurationBucketFilter (post-trim bounds)
|
|
135
|
+
-> TTSManifestExporter (WAV + manifests)
|
|
136
|
+
-> checkpoint.db
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Accepted documents are exported as WAV and appended to requested manifests.
|
|
140
|
+
The executor, not a worker, owns export and SQLite writes; this makes manifest
|
|
141
|
+
and checkpoint mutation serial and resumable.
|
|
142
|
+
|
|
143
|
+
## CLI reference
|
|
144
|
+
|
|
145
|
+
Use `audiotrove curate INPUT_PATH OUTPUT_PATH --tts`. TTS-specific options are
|
|
146
|
+
listed first. The remaining flags belong to the generic JSONL path and are
|
|
147
|
+
accepted by the same command but do not configure `tts_pipeline()`.
|
|
148
|
+
|
|
149
|
+
| Flag | Type | Default | Description |
|
|
150
|
+
|---|---|---:|---|
|
|
151
|
+
| `--tts` | flag | `False` | Run TTS curation and manifest export. |
|
|
152
|
+
| `--tts-min-duration` | float | `2.0` | Minimum TTS duration in seconds. |
|
|
153
|
+
| `--tts-max-duration` | float | `15.0` | Maximum TTS duration in seconds. |
|
|
154
|
+
| `--tts-snr-min` | float | `20.0` | Minimum TTS SNR in dB. |
|
|
155
|
+
| `--workers` | integer | `1` | Local worker count. |
|
|
156
|
+
| `--extensions` | string | `wav` | Comma-separated extensions, for example `wav,mp3,flac`. |
|
|
157
|
+
| `--vad-threshold` | float | `0.3` | Generic-path minimum speech ratio. |
|
|
158
|
+
| `--snr-min` | float | `15.0` | Generic-path minimum SNR in dB. |
|
|
159
|
+
| `--format` | choice | `jsonl` | Generic-path output format. |
|
|
160
|
+
| `--checkpoint` | string | none | Generic-path checkpoint database path. |
|
|
161
|
+
| `--segment` | flag | `False` | Generic-path VAD fan-out segmentation. |
|
|
162
|
+
| `--enhance` | flag | `False` | Generic-path DeepFilterNet2 enhancement. |
|
|
163
|
+
| `-v`, `--verbose` | flag | `False` | Enable DEBUG logging. |
|
|
164
|
+
|
|
165
|
+
The TTS pipeline itself fixes VAD minimum speech ratio at `0.1` and VAD model
|
|
166
|
+
threshold at `0.5`; `--vad-threshold` is not forwarded in TTS mode.
|
|
167
|
+
|
|
168
|
+
## Output format
|
|
169
|
+
|
|
170
|
+
The exporter writes WAV files using each source file’s stem. It then writes a
|
|
171
|
+
LJSpeech row when `ljspeech` is selected and an F5-TTS row when `f5tts` is
|
|
172
|
+
selected. The default requests both formats.
|
|
173
|
+
|
|
174
|
+
`metadata.csv` is pipe-delimited:
|
|
175
|
+
|
|
176
|
+
```text
|
|
177
|
+
1272-128104-0000.wav|speaker_00|
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Columns are `filename`, `speaker_id`, and `transcription`. The transcription
|
|
181
|
+
is an empty string unless `doc.metadata["transcription"]` is set.
|
|
182
|
+
|
|
183
|
+
`filelist.txt` is tab-delimited:
|
|
184
|
+
|
|
185
|
+
```text
|
|
186
|
+
curated-flac/1272-128104-0000.wav 5.3200
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Columns are the curated WAV path, the post-trim duration in seconds, and
|
|
190
|
+
transcription. The path points to the exported WAV, not the untrimmed source.
|
|
191
|
+
WAV names derive from source stems, so source-stem collisions must be avoided
|
|
192
|
+
within one output directory.
|
|
193
|
+
|
|
194
|
+
`checkpoint.db` has a `processed` SQLite table keyed by document ID. It is an
|
|
195
|
+
operational artifact, not a training manifest.
|
|
196
|
+
|
|
197
|
+
## Resumability
|
|
198
|
+
|
|
199
|
+
The executor initializes `checkpoint.db` with a primary-keyed `processed`
|
|
200
|
+
table. Before a document enters the pipeline, it checks that table; after an
|
|
201
|
+
accepted document is exported, or after a rejected original document is
|
|
202
|
+
handled, it inserts the relevant ID. An interrupted run can therefore be
|
|
203
|
+
restarted with the same input and output paths: already recorded IDs are
|
|
204
|
+
skipped, while unrecorded IDs continue through the pipeline.
|
|
205
|
+
|
|
206
|
+
Manifests are opened in append mode. Keep the checkpoint with its output
|
|
207
|
+
directory. Deleting the database while retaining manifests disables skip
|
|
208
|
+
deduplication and can append duplicate rows.
|
|
209
|
+
|
|
210
|
+
## Benchmark
|
|
211
|
+
|
|
212
|
+
The committed benchmark used LibriSpeech dev-clean: 2,703 FLAC clips and
|
|
213
|
+
19,396.1 seconds (5.39 h) of input. It used real cached Silero VAD, not the
|
|
214
|
+
energy fallback. Both configurations retained 2,123 clips and filtered 580.
|
|
215
|
+
|
|
216
|
+
| Workers | Corpus | Kept | Filtered | Wall time | RTFx | Clips/sec |
|
|
217
|
+
|---:|---|---:|---:|---:|---:|---:|
|
|
218
|
+
| 1 | LibriSpeech dev-clean (2703 clips) | 2123 | 580 | 3083.50 s | 6.3× | 0.88 |
|
|
219
|
+
| 4 | LibriSpeech dev-clean (2703 clips) | 2123 | 580 | 1968.61 s | 9.9× | 1.37 |
|
|
220
|
+
|
|
221
|
+
RTFx is total input audio duration divided by wall time. Four workers improve
|
|
222
|
+
throughput by about 1.57× rather than 4× because decoding and WAV/manifests
|
|
223
|
+
require I/O, exports and checkpoints stay in the main process, and Silero
|
|
224
|
+
inference is protected by a shared lock. The result JSON contains aggregate
|
|
225
|
+
kept/filtered counts, not a per-filter rejection breakdown; inspection of
|
|
226
|
+
component metadata/checkpoint data is needed for per-reason analysis.
|
|
227
|
+
|
|
228
|
+
## Integrating with training frameworks
|
|
229
|
+
|
|
230
|
+
F5-TTS-style consumers can read the default tab-separated filelist directly:
|
|
231
|
+
|
|
232
|
+
```python
|
|
233
|
+
for line in open("curated-tts/filelist.txt", encoding="utf-8"):
|
|
234
|
+
wav_path, duration, text = line.rstrip("\n").split("\t")
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
LJSpeech-style consumers can use `metadata.csv` with WAVs in the same output
|
|
238
|
+
directory:
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
for line in open("curated-tts/metadata.csv", encoding="utf-8"):
|
|
242
|
+
filename, speaker_id, text = line.rstrip("\n").split("|", 2)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
AudioTrove intentionally leaves the transcription field empty when upstream
|
|
246
|
+
metadata has none; generate or attach transcripts before training a supervised
|
|
247
|
+
TTS model.
|
|
248
|
+
|
|
249
|
+
## Extending AudioTrove
|
|
250
|
+
|
|
251
|
+
Custom filters subclass `AudioFilter`, expose a name, and return a boolean
|
|
252
|
+
from `filter`. The executor will short-circuit a false result for that document.
|
|
253
|
+
|
|
254
|
+
```python
|
|
255
|
+
from audiotrove.base import AudioFilter
|
|
256
|
+
|
|
257
|
+
class PeakLimitFilter(AudioFilter):
|
|
258
|
+
name = "peak_limit"
|
|
259
|
+
|
|
260
|
+
def __init__(self, maximum: float = 0.99):
|
|
261
|
+
self.maximum = maximum
|
|
262
|
+
|
|
263
|
+
def filter(self, doc):
|
|
264
|
+
return float(abs(doc.audio).max()) <= self.maximum
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
Add the filter to a pipeline list, add focused pass/fail tests, and add an
|
|
268
|
+
end-to-end test where its placement matters. New export formats should follow
|
|
269
|
+
the exporter’s `write(doc)` and `output_files` contract. See
|
|
270
|
+
[ARCHITECTURE.md](ARCHITECTURE.md) for the full extension guide.
|
|
271
|
+
|
|
272
|
+
## Contributing
|
|
273
|
+
|
|
274
|
+
Read [CONTRIBUTING.md](CONTRIBUTING.md) and keep changes small and tested.
|
|
275
|
+
Ruff is included in the development extras; add tests for new components and
|
|
276
|
+
run them across the supported Windows, macOS, and Linux environments.
|
|
277
|
+
|
|
278
|
+
## License
|
|
279
|
+
|
|
280
|
+
AudioTrove is released under the [MIT License](LICENSE).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.0"
|