Svrooij.PodcastToPiper 0.1.0

dotnet tool install --global Svrooij.PodcastToPiper --version 0.1.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local Svrooij.PodcastToPiper --version 0.1.0
                    
This package contains a .NET tool you can call from the shell/command line.
#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

  1. Convert — input MP3/WAV is converted to 16 kHz mono PCM for Whisper.
  2. Transcribe — Whisper produces timestamped text segments (GPU-accelerated via Vulkan on supported hardware).
  3. Diarize — 80-dim log Mel-filterbank features are fed to a WeSpeaker ResNet34 ONNX model to produce speaker embeddings; agglomerative clustering assigns a SPEAKER_N label to each segment (GPU-accelerated via DirectML).
  4. Select — you choose (or pre-specify) which speaker's clips to extract.
  5. Filter — phrases outside the duration window are dropped.
  6. Slice — each phrase is cut from the audio with a short silence pad and resampled to the Piper target sample rate.
  7. Exportwavs/XXXX.wav clips and metadata.csv in LJSpeech format, ready for piper_train.

License

MIT © 2026 Stephan van Rooij

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
0.1.0 119 7/26/2026