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.
Files changed (49) hide show
  1. audiotrove-0.1.0/LICENSE +21 -0
  2. audiotrove-0.1.0/PKG-INFO +352 -0
  3. audiotrove-0.1.0/README.md +280 -0
  4. audiotrove-0.1.0/audiotrove/__init__.py +1 -0
  5. audiotrove-0.1.0/audiotrove/base.py +60 -0
  6. audiotrove-0.1.0/audiotrove/cli/__init__.py +0 -0
  7. audiotrove-0.1.0/audiotrove/cli/main.py +297 -0
  8. audiotrove-0.1.0/audiotrove/document.py +25 -0
  9. audiotrove-0.1.0/audiotrove/executor/__init__.py +0 -0
  10. audiotrove-0.1.0/audiotrove/executor/local.py +381 -0
  11. audiotrove-0.1.0/audiotrove/exporters/__init__.py +5 -0
  12. audiotrove-0.1.0/audiotrove/exporters/tts_manifest.py +71 -0
  13. audiotrove-0.1.0/audiotrove/filters/__init__.py +0 -0
  14. audiotrove-0.1.0/audiotrove/filters/duration.py +30 -0
  15. audiotrove-0.1.0/audiotrove/filters/enhance.py +80 -0
  16. audiotrove-0.1.0/audiotrove/filters/snr.py +63 -0
  17. audiotrove-0.1.0/audiotrove/filters/vad.py +365 -0
  18. audiotrove-0.1.0/audiotrove/io/__init__.py +0 -0
  19. audiotrove-0.1.0/audiotrove/io/readers.py +176 -0
  20. audiotrove-0.1.0/audiotrove/io/writers.py +30 -0
  21. audiotrove-0.1.0/audiotrove/pipelines/__init__.py +5 -0
  22. audiotrove-0.1.0/audiotrove/pipelines/tts.py +70 -0
  23. audiotrove-0.1.0/audiotrove/transformers/__init__.py +5 -0
  24. audiotrove-0.1.0/audiotrove/transformers/silence_trim.py +76 -0
  25. audiotrove-0.1.0/audiotrove/utils/__init__.py +0 -0
  26. audiotrove-0.1.0/audiotrove/utils/hashing.py +5 -0
  27. audiotrove-0.1.0/audiotrove.egg-info/PKG-INFO +352 -0
  28. audiotrove-0.1.0/audiotrove.egg-info/SOURCES.txt +47 -0
  29. audiotrove-0.1.0/audiotrove.egg-info/dependency_links.txt +1 -0
  30. audiotrove-0.1.0/audiotrove.egg-info/entry_points.txt +2 -0
  31. audiotrove-0.1.0/audiotrove.egg-info/requires.txt +32 -0
  32. audiotrove-0.1.0/audiotrove.egg-info/top_level.txt +1 -0
  33. audiotrove-0.1.0/pyproject.toml +88 -0
  34. audiotrove-0.1.0/setup.cfg +4 -0
  35. audiotrove-0.1.0/tests/test_additional_coverage.py +99 -0
  36. audiotrove-0.1.0/tests/test_cli.py +354 -0
  37. audiotrove-0.1.0/tests/test_document.py +26 -0
  38. audiotrove-0.1.0/tests/test_enhance.py +16 -0
  39. audiotrove-0.1.0/tests/test_executor.py +316 -0
  40. audiotrove-0.1.0/tests/test_executor_and_cli.py +217 -0
  41. audiotrove-0.1.0/tests/test_interfaces.py +50 -0
  42. audiotrove-0.1.0/tests/test_parallel_executor.py +82 -0
  43. audiotrove-0.1.0/tests/test_readers.py +233 -0
  44. audiotrove-0.1.0/tests/test_snr.py +95 -0
  45. audiotrove-0.1.0/tests/test_tts_pipeline.py +115 -0
  46. audiotrove-0.1.0/tests/test_vad.py +64 -0
  47. audiotrove-0.1.0/tests/test_vad_segmentation.py +246 -0
  48. audiotrove-0.1.0/tests/test_vad_snr.py +129 -0
  49. audiotrove-0.1.0/tests/test_writer.py +110 -0
@@ -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
+ [![CI](https://img.shields.io/github/actions/workflow/status/onepizzateam/AudioTrove/ci.yml?branch=main&label=CI)](https://github.com/onepizzateam/AudioTrove/actions)
78
+ [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/)
79
+ [![License](https://img.shields.io/github/license/onepizzateam/AudioTrove)](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
+ [![CI](https://img.shields.io/github/actions/workflow/status/onepizzateam/AudioTrove/ci.yml?branch=main&label=CI)](https://github.com/onepizzateam/AudioTrove/actions)
6
+ [![Python](https://img.shields.io/badge/python-3.10%2B-blue)](https://www.python.org/)
7
+ [![License](https://img.shields.io/github/license/onepizzateam/AudioTrove)](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"