Ahsoka Tano Voice (Piper TTS)
A fine-tuned Piper TTS model that clones the voice of Ahsoka Tano from Star Wars: The Clone Wars.
Files
| File | Description |
|---|---|
ahsoka-final.onnx |
ONNX model for inference |
ahsoka-final.json |
Model config (sample rate, phoneme map, inference params) |
ahsoka-final.ckpt |
PyTorch Lightning checkpoint (for continued training) |
dataset.jsonl |
Training dataset (1019 samples) |
dataset.jsonl.gz |
Compressed dataset |
Quick Start (Piper CLI)
Install Piper
# Clone and build from source
git clone https://github.com/rhasspy/piper.git
cd piper
./build.sh
Or use a pre-built binary from Piper Releases.
Download Model
mkdir -p ~/.local/share/piper-voices/ahsoka
cd ~/.local/share/piper-voices/ahsoka
# Download from HuggingFace
wget https://huggingface.co/crazygiscool/ahsoka-piper-voice/resolve/main/ahsoka-final.onnx
wget https://huggingface.co/crazygiscool/ahsoka-piper-voice/resolve/main/ahsoka-final.json
Synthesize Speech
# Pipe text in
echo "Hello, I am Ahsoka Tano" | piper --model ~/.local/share/piper-voices/ahsoka/ahsoka-final.onnx --output_file output.wav
# Or specify text directly
piper --model ~/.local/share/piper-voices/ahsoka/ahsoka-final.onnx --text "The force is strong with this one" --output_file output.wav
Python Usage
Install Dependencies
pip install piper-tts piper-phonemize torch soundfile
Synthesize with ONNX Model
import soundfile as sf
import piper_phonemize
import onnxruntime as ort
import numpy as np
# Load model
session = ort.InferenceSession("ahsoka-final.onnx")
# Phonemize text
text = "I am Ahsoka Tano"
phonemes = piper_phonemize.phonemize_espeak(text, "en-us")
phoneme_ids = piper_phonemize.phoneme_ids_espeak([p for seq in phonemes for p in seq])
# Add padding (required format: [BOS, 0, phoneme, 0, phoneme, ..., EOS])
ids = [0] + [p for pid in phoneme_ids for p in [0, pid]] + [0]
# Inference
x = np.array([ids], dtype=np.int64)
x_len = np.array([len(ids)], dtype=np.int64)
scales = np.array([0.667, 1.0, 0.8], dtype=np.float32)
audio = session.run(None, {
"input": x,
"input_lengths": x_len,
"noise_scale": scales[:1],
"length_scale": scales[1:2],
"noise_w": scales[2:],
})[0]
# Save
sf.write("output.wav", audio[0, 0], 22050)
Synthesize with PyTorch Checkpoint (for development)
import torch
from piper_train.vits.lightning import VitsModel
model = VitsModel.load_from_checkpoint("ahsoka-final.ckpt", dataset=None)
model_g = model.model_g
model_g.eval()
with torch.no_grad():
model_g.dec.remove_weight_norm()
# (same phonemize + inference code as above)
Inference Parameters
| Parameter | Default | Range | Description |
|---|---|---|---|
noise_scale |
0.667 | 0.0 - 1.0 | Phoneme noise (variation) |
length_scale |
1.0 | 0.5 - 2.0 | Speaking speed (lower = faster) |
noise_w |
0.8 | 0.0 - 1.0 | Phoneme width noise |
Training Details
- Base model: Piper English (en-us)
- Training data: 1019 audio samples (22050 Hz, mono, 16-bit PCM WAV)
- Fine-tuning LR: 1e-5 (20x lower than default for gentle adaptation)
- Epochs trained: ~7000
- Hardware: CPU only
Dataset Format
Each line in dataset.jsonl contains:
{"text": "Transcription text", "audio_filename": "relative/path/to/audio.wav"}
All audio must be: 22050 Hz, mono, 16-bit PCM WAV.
License
Apache 2.0