Text-to-Speech
ONNX
GGUF
Chinese
English
onnxruntime
tts
on-device
jetson
telephony
vits
mb-istft-vits
multi-speaker
mandarin
taiwanese-mandarin
imatrix
conversational
Instructions to use Luigi/PrimeTTS with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use Luigi/PrimeTTS with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf Luigi/PrimeTTS:F32 # Run inference directly in the terminal: llama cli -hf Luigi/PrimeTTS:F32
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf Luigi/PrimeTTS:F32 # Run inference directly in the terminal: llama cli -hf Luigi/PrimeTTS:F32
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf Luigi/PrimeTTS:F32 # Run inference directly in the terminal: ./llama-cli -hf Luigi/PrimeTTS:F32
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf Luigi/PrimeTTS:F32 # Run inference directly in the terminal: ./build/bin/llama-cli -hf Luigi/PrimeTTS:F32
Use Docker
docker model run hf.co/Luigi/PrimeTTS:F32
- LM Studio
- Jan
- Ollama
How to use Luigi/PrimeTTS with Ollama:
ollama run hf.co/Luigi/PrimeTTS:F32
- Unsloth Studio
How to use Luigi/PrimeTTS with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for Luigi/PrimeTTS to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for Luigi/PrimeTTS to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for Luigi/PrimeTTS to start chatting
- Atomic Chat new
- Docker Model Runner
How to use Luigi/PrimeTTS with Docker Model Runner:
docker model run hf.co/Luigi/PrimeTTS:F32
- Lemonade
How to use Luigi/PrimeTTS with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull Luigi/PrimeTTS:F32
Run and chat with the model
lemonade run user.PrimeTTS-F32
List all available models
lemonade list
one-click rebuild_voice.sh + generators + text pools
Browse files- scripts/rebuild_voice.sh +85 -0
scripts/rebuild_voice.sh
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
#!/usr/bin/env bash
|
| 2 |
+
# ============================================================================
|
| 3 |
+
# ONE-CLICK: build a full zh-TW + English 8 kHz PrimeTTS model in YOUR voice.
|
| 4 |
+
# The reference voice is the ONLY input you change; the text pools, ASR gate,
|
| 5 |
+
# alignment and training recipe are fixed. Both vocoder and acoustic are
|
| 6 |
+
# retrained (both are voice-specific).
|
| 7 |
+
#
|
| 8 |
+
# RUN FROM THE REPO ROOT:
|
| 9 |
+
# PY=/path/to/venv/bin/python ./scripts/rebuild_voice.sh ref.wav ref.txt mytag
|
| 10 |
+
#
|
| 11 |
+
# ref.wav ~6-12 s clean clip of your target voice (mono; zh-TW that also reads
|
| 12 |
+
# a little English is ideal). ref.txt its exact transcript.
|
| 13 |
+
# No recording? synth a reference with Edge-TTS (pip install edge-tts):
|
| 14 |
+
# edge-tts --voice zh-TW-HsiaoYuNeural --text "您好,歡迎來電。Thank you for calling." --write-media ref.mp3
|
| 15 |
+
# ffmpeg -y -i ref.mp3 -ar 24000 -ac 1 ref.wav ; printf '%s' "您好,歡迎來電。Thank you for calling." > ref.txt
|
| 16 |
+
#
|
| 17 |
+
# PREREQS (one venv, on PYTHONPATH=repo root):
|
| 18 |
+
# pip install torch torchaudio transformers onnxruntime soundfile librosa \
|
| 19 |
+
# g2pw g2p_en cn2an opencc inflect faster-whisper edge-tts voxcpm nltk
|
| 20 |
+
# python -c "import nltk; nltk.download('names')"
|
| 21 |
+
# # base warm-start ckpt: download inflect_nano_v1_acoustic.pt from owensong/Inflect-Nano-v1
|
| 22 |
+
# Result corpus: ~12k clips (≈27% zh / 50% mix / 23% en), entity clips ×2 at train time.
|
| 23 |
+
# ============================================================================
|
| 24 |
+
set -e
|
| 25 |
+
REF=${1:?need ref.wav}; REFTXT=${2:?need ref.txt}; TAG=${3:-myvoice}
|
| 26 |
+
PY=${PY:-python} # a venv with all deps above
|
| 27 |
+
GPUS=${GPUS:-0,1}; G0=${GPUS%,*}; G1=${GPUS#*,}
|
| 28 |
+
INIT=${INIT:-inflect_nano_v1_acoustic.pt} # base acoustic (owensong/Inflect-Nano-v1)
|
| 29 |
+
export PYTHONPATH=${PYTHONPATH:-$PWD}
|
| 30 |
+
S=scripts; C=corpus_${TAG}; mkdir -p $C/wav
|
| 31 |
+
|
| 32 |
+
echo "### 1. Text pools (committed in the repo; regenerated only if absent) ###"
|
| 33 |
+
[ -f voxcpm_texts.jsonl ] || { echo "need voxcpm_texts.jsonl (base 2500 zh / 2000 en / 2800 mix)"; exit 1; }
|
| 34 |
+
[ -f codemix_v2.txt ] || $PY $S/gen_codemix_v2.py --n 3000 --exclude codemix_corpus.txt --out codemix_v2.txt
|
| 35 |
+
[ -f entity_texts.jsonl ] || $PY $S/gen_entity_texts.py --n 2600 --out entity_texts.jsonl
|
| 36 |
+
$PY - <<PY
|
| 37 |
+
import json
|
| 38 |
+
with open("$C/all_texts.jsonl","w",encoding="utf-8") as o:
|
| 39 |
+
for l in open("voxcpm_texts.jsonl"): o.write(l)
|
| 40 |
+
for i,t in enumerate(x.strip() for x in open("codemix_v2.txt") if x.strip()):
|
| 41 |
+
o.write(json.dumps({"id":f"mz{i:05d}","text":t,"lang":"mix"},ensure_ascii=False)+"\n")
|
| 42 |
+
for l in open("entity_texts.jsonl"): o.write(l)
|
| 43 |
+
print("assembled", "$C/all_texts.jsonl")
|
| 44 |
+
PY
|
| 45 |
+
|
| 46 |
+
echo "### 2. Clone YOUR voice for every line (VoxCPM2), dual-GPU ###"
|
| 47 |
+
$PY -c "ls=[l for l in open('$C/all_texts.jsonl') if l.strip()];open('$C/t0.jsonl','w').writelines(ls[0::2]);open('$C/t1.jsonl','w').writelines(ls[1::2])"
|
| 48 |
+
CUDA_VISIBLE_DEVICES=$G0 $PY $S/gen_voxcpm_corpus.py --texts $C/t0.jsonl --ref "$REF" --ref-text "$REFTXT" --out-dir $C/wav --manifest $C/m0.jsonl &
|
| 49 |
+
CUDA_VISIBLE_DEVICES=$G1 $PY $S/gen_voxcpm_corpus.py --texts $C/t1.jsonl --ref "$REF" --ref-text "$REFTXT" --out-dir $C/wav --manifest $C/m1.jsonl &
|
| 50 |
+
wait; cat $C/m0.jsonl $C/m1.jsonl > $C/manifest.jsonl
|
| 51 |
+
|
| 52 |
+
echo "### 3. ASR-gate generic clips; trust entity (et*) clips as-is ###"
|
| 53 |
+
$PY -c "
|
| 54 |
+
import json
|
| 55 |
+
g=open('$C/to_gate.jsonl','w'); e=open('$C/entity.jsonl','w')
|
| 56 |
+
for l in open('$C/manifest.jsonl'): (e if json.loads(l)['id'].startswith('et') else g).write(l)"
|
| 57 |
+
CUDA_VISIBLE_DEVICES=$G0 $PY $S/asr_filter.py --manifest $C/to_gate.jsonl --out $C/to_gate --device cuda
|
| 58 |
+
cat $C/to_gate.clean.jsonl $C/entity.jsonl > $C/clean.jsonl
|
| 59 |
+
|
| 60 |
+
echo "### 4. Normalize entities + phone-level align + entity-upsample 2x ###"
|
| 61 |
+
$PY $S/build_corpus_v3.py --out $C/norm.jsonl $C/clean.jsonl
|
| 62 |
+
CUDA_VISIBLE_DEVICES=$G0 $PY $S/align_durations_v4.py --manifest $C/norm.jsonl --out $C/align.jsonl --device cuda
|
| 63 |
+
$PY -c "import json;r=[l for l in open('$C/align.jsonl') if l.strip()];e=[l for l in r if json.loads(l).get('id','').startswith('et')];open('$C/align.up.jsonl','w').writelines(r+e);print('train rows',len(r)+len(e))"
|
| 64 |
+
|
| 65 |
+
echo "### 5. Train 8 kHz vocoder on your voice ###"
|
| 66 |
+
$PY -c "import json;o=open('$C/voc_rows.jsonl','w');[o.write(json.dumps({'target_audio':json.loads(l)['target_audio'],'target_text':json.loads(l)['text']},ensure_ascii=False)+'\n') for l in open('$C/norm.jsonl')]"
|
| 67 |
+
CUDA_VISIBLE_DEVICES=$G1 $PY -m inflect_nano.vocoder --train-jsonl $C/voc_rows.jsonl --out-dir $C/vocoder_8k \
|
| 68 |
+
--variant snake_8k --steps 40000 --batch-size 16 --segment-size 16384 --stft-weight 2.0 --save-interval 5000 --device cuda
|
| 69 |
+
|
| 70 |
+
echo "### 6. Train acoustic: warm-start v1 + 2D mel-GAN + en-upsample 2 ###"
|
| 71 |
+
CUDA_VISIBLE_DEVICES=$G0 $PY -m inflect_nano.acoustic --durations-jsonl $C/align.up.jsonl --out-dir $C/acoustic_8k \
|
| 72 |
+
--vocoder-variant snake_8k --sample-rate 8000 --vocoder-checkpoint $C/vocoder_8k/hifigan-snake_8k-final.pt \
|
| 73 |
+
--vocoder-mel-weight 1.0 --init-checkpoint "$INIT" \
|
| 74 |
+
--mel-gan-weight 0.1 --gan-2d --gan-fm-auto --gan-r1-gamma 1.0 --gan-crop 128 --gan-warmup-steps 25000 \
|
| 75 |
+
--steps 60000 --batch-size 16 --lr 2e-4 --max-frames 1000 --en-upsample 2 --save-interval 5000 --device cuda
|
| 76 |
+
|
| 77 |
+
echo "### 7. Export + assess (sweep ckpts; ~35k is usually the held-out sweet spot) ###"
|
| 78 |
+
for K in 30000 35000 40000; do
|
| 79 |
+
$PY $S/export_8k.py --acoustic-ckpt $C/acoustic_8k/inflect-micro-fastspeech-$K.pt \
|
| 80 |
+
--vocoder-ckpt $C/vocoder_8k/hifigan-snake_8k-final.pt --out-dir $C/onnx_$K
|
| 81 |
+
$PY $S/synth_from_text.py --onnx-dir $C/onnx_$K --out-dir $C/eval_$K --texts eval_big.jsonl
|
| 82 |
+
$PY $S/synth_from_text.py --onnx-dir $C/onnx_$K --out-dir $C/entity_$K --texts eval_entity.jsonl
|
| 83 |
+
CUDA_VISIBLE_DEVICES='' $PY $S/assess_quality.py --synth-dir $C/eval_$K --tag ${TAG}_$K || true
|
| 84 |
+
done
|
| 85 |
+
echo "DONE -> pick best $C/onnx_<K>/ ; ship its *.onnx + meta.json to your model repo."
|