Svrooij.PodcastToPiper
0.1.0
dotnet tool install --global Svrooij.PodcastToPiper --version 0.1.0
dotnet new tool-manifest
dotnet tool install --local Svrooij.PodcastToPiper --version 0.1.0
#tool dotnet:?package=Svrooij.PodcastToPiper&version=0.1.0
nuke :add-package Svrooij.PodcastToPiper --version 0.1.0
podcast-to-piper
A .NET global tool that splits podcast episodes into per-speaker phrases for Piper TTS voice training data (LJSpeech format).
It transcribes audio with Whisper.net, performs speaker diarization via ONNX speaker embeddings, lets you interactively pick the target speaker (with audio preview), and exports ready-to-use wavs/ clips and metadata.csv.
Requirements
- .NET 10 SDK or Runtime
- Windows (DirectML GPU acceleration for diarization; Vulkan for Whisper on Snapdragon/Adreno)
Installation
dotnet tool install -g Svrooij.PodcastToPiper
Quick start
# Download models ahead of time (optional but recommended before first run)
podcast-to-piper download --model small
# Process one or more podcast files
podcast-to-piper episode1.mp3 episode2.mp3 --output ./dataset --language nl
Commands
podcast-to-piper — main pipeline
Transcribes each audio file, assigns speaker labels, lets you choose the target speaker, and exports LJSpeech-format clips.
podcast-to-piper [options] <files>...
Arguments
| Argument | Description |
|---|---|
<files> |
One or more local audio files to process (MP3 or WAV). At least one is required. |
Options
| Option | Default | Description |
|---|---|---|
--output <dir> |
./output |
Output directory for the generated dataset. Created if it does not exist. |
--language <code> |
auto |
Language code for transcription, e.g. nl, en, de. Use auto to detect automatically. |
--model <size> |
small |
Whisper model size: tiny, base, small, medium, large. Larger models are more accurate but slower. |
--models-dir <dir> |
~/.podcast-to-piper/models |
Directory where downloaded Whisper and diarization models are cached. |
--speaker <id> |
(interactive) | Speaker ID to extract, e.g. SPEAKER_0. Skips interactive selection. |
--quality <level> |
Medium |
Target Piper voice quality — sets output sample rate. Low = 16 kHz, Medium/High = 22 050 Hz. |
--min-duration <sec> |
1.0 |
Minimum phrase duration in seconds. Shorter phrases are discarded. |
--max-duration <sec> |
15.0 |
Maximum phrase duration in seconds. Longer phrases are discarded. |
--max-speakers <n> |
(auto) | Expected number of speakers (e.g. 2 for a two-person podcast). Forces cluster merging down to this count. Helps avoid over-segmentation. |
--no-download |
false |
Fail immediately if a required model is not already cached locally. Useful for offline/CI scenarios. |
Output layout
<output>/
wavs/
0000.wav
0001.wav
...
metadata.csv # LJSpeech format: wavs/XXXX.wav|text|text
quality.txt # e.g. "medium"
dataset_info.json # summary: clip count, total duration, source files, …
.cache/ # intermediate results (transcripts, diarization) for resume
Checkpoint / resume
Results are cached in <output>/.cache/ after each pipeline stage. If a run is interrupted (Ctrl+C) the tool resumes from where it left off on the next invocation with the same options. The partial transcript is also preserved so transcription can resume without re-processing audio from the beginning.
Interactive speaker selection
When --speaker is not provided, the tool prints available speakers and their segment counts and prompts you to choose:
SPEAKER_0 (142 segments)
SPEAKER_1 ( 38 segments)
Enter speaker ID ('p SPEAKER_X' to preview), or Enter to skip 'episode1.mp3': p SPEAKER_0
Type p SPEAKER_X to play a short audio preview of that speaker before deciding.
Examples
# Two-person Dutch podcast, force exactly 2 speakers, use small Whisper model
podcast-to-piper interview.mp3 --language nl --max-speakers 2 --output ./dataset
# Batch several episodes, skip interactive prompt
podcast-to-piper ep1.mp3 ep2.mp3 ep3.mp3 --speaker SPEAKER_0 --output ./dataset
# High-quality output, only keep phrases between 2 and 10 seconds
podcast-to-piper talk.wav --quality High --min-duration 2 --max-duration 10 --output ./dataset
# Offline run — fail if models are not already downloaded
podcast-to-piper episode.mp3 --no-download --output ./dataset
podcast-to-piper download — pre-download models
Downloads the Whisper model and the speaker-embedding ONNX model to the local cache. Useful to avoid download delays at processing time or to prepare an offline environment.
podcast-to-piper download [options]
| Option | Default | Description |
|---|---|---|
--model <size> |
small |
Whisper model to download: tiny, base, small, medium, large. |
--models-dir <dir> |
~/.podcast-to-piper/models |
Directory to store downloaded models. |
Example
# Pre-download the medium Whisper model and the embedding model
podcast-to-piper download --model medium
podcast-to-piper clear-cache — delete intermediate results
Deletes all cached transcription and diarization JSON files stored under <output>/.cache/. Useful when you want to force a full re-run (e.g. after changing the model or language).
podcast-to-piper clear-cache [options]
| Option | Default | Description |
|---|---|---|
--output <dir> |
./output |
Output directory whose .cache folder should be cleared. |
Example
# Clear the cache for a specific output directory
podcast-to-piper clear-cache --output ./dataset
How it works
- Convert — input MP3/WAV is converted to 16 kHz mono PCM for Whisper.
- Transcribe — Whisper produces timestamped text segments (GPU-accelerated via Vulkan on supported hardware).
- Diarize — 80-dim log Mel-filterbank features are fed to a WeSpeaker ResNet34 ONNX model to produce speaker embeddings; agglomerative clustering assigns a
SPEAKER_Nlabel to each segment (GPU-accelerated via DirectML). - Select — you choose (or pre-specify) which speaker's clips to extract.
- Filter — phrases outside the duration window are dropped.
- Slice — each phrase is cut from the audio with a short silence pad and resampled to the Piper target sample rate.
- Export —
wavs/XXXX.wavclips andmetadata.csvin LJSpeech format, ready forpiper_train.
License
MIT © 2026 Stephan van Rooij
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
This package has no dependencies.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.1.0 | 119 | 7/26/2026 |