Orpheus Australian-English TTS
A finetune of canopylabs/orpheus-tts-0.1-pretrained
(Llama-3.2-3B backbone + SNAC 24 kHz neural codec) that speaks
Australian-accented English in 8 named voices. Trained on public-domain Australian LibriVox audiobooks
and dramatic readings, with mild DeepFilterNet denoising.
Voices
Pass one of these names as the speaker. (Names are random pseudonyms; the underlying public-domain readers are not identified.)
| voice | gender |
|---|---|
flynn | male |
angus | male |
mason | male |
cooper | male |
delta | female |
ruby | female |
sienna | female |
matilda | female |
Samples
Generated with this model at temperature=0.6. Nothing was hand-picked by ear: each clip was
transcribed back with Whisper large-v3-turbo and kept only if it matched the target sentence
(31 of 32 first takes passed; one was re-rolled). Browse or download them in
samples/, or open the demo Space.
“Good morning! It's a lovely day for a walk down by the harbour, isn't it?”
| voice | voice | ||
|---|---|---|---|
flynn (male) | angus (male) | ||
mason (male) | cooper (male) | ||
delta (female) | ruby (female) | ||
sienna (female) | matilda (female) |
“The dance class starts at half past three, so we'd rather take the car than walk in this weather.”
| voice | voice | ||
|---|---|---|---|
flynn (male) | angus (male) | ||
mason (male) | cooper (male) | ||
delta (female) | ruby (female) | ||
sienna (female) | matilda (female) |
“No worries, mate. I'll grab a coffee on the way and meet you at the station this afternoon.”
| voice | voice | ||
|---|---|---|---|
flynn (male) | angus (male) | ||
mason (male) | cooper (male) | ||
delta (female) | ruby (female) | ||
sienna (female) | matilda (female) |
“It was a warm afternoon in the bush, and the road stretched on for miles ahead of us, past the grey gum trees and the dry creek bed.”
| voice | voice | ||
|---|---|---|---|
flynn (male) | angus (male) | ||
mason (male) | cooper (male) | ||
delta (female) | ruby (female) | ||
sienna (female) | matilda (female) |
Install
pip install torch transformers soundfile
pip install snac # neural audio codec used by Orpheus
If transformers fails to import with a Keras-3 error, run with USE_TF=0 USE_FLAX=0.
Quick start / deployment
A single self-contained inference function. Works on a CUDA GPU (bf16 ~7 GB VRAM); for CPU drop .to("cuda") and use float32.
import torch, soundfile as sf
from transformers import AutoModelForCausalLM, AutoTokenizer
from snac import SNAC
REPO = "ablmontazer/orpheus-australian-en-tts"
DEV = "cuda"
# Orpheus control tokens (fixed)
SOH, EOT, EOH, SOAI, SOS, EOS, EOAI, PAD, BASE_A = 128259,128009,128260,128261,128257,128258,128262,128263,128266
tok = AutoTokenizer.from_pretrained(REPO)
model = AutoModelForCausalLM.from_pretrained(REPO, torch_dtype=torch.bfloat16).to(DEV).eval()
snac = SNAC.from_pretrained("hubertsiuzdak/snac_24khz").to(DEV).eval()
@torch.inference_mode()
def tts(voice: str, text: str, out_path: str = "out.wav", temperature: float = 0.6):
# prompt format is "<voice>: <text>"
ids = [SOH] + tok.encode(f"{voice}: {text}", add_special_tokens=False) + [EOT, EOH, SOAI, SOS]
gen = model.generate(torch.tensor([ids]).to(DEV), max_new_tokens=1400, do_sample=True,
temperature=temperature, top_p=0.95, eos_token_id=EOAI, pad_token_id=PAD)[0].tolist()
audio = [t for t in gen[len(ids):] if BASE_A <= t < BASE_A + 7*4096]
a = [t - BASE_A for t in audio]; n = len(a)//7
c0, c1, c2 = [], [], []
for i in range(n): # de-interleave 7 tokens/frame -> 3 SNAC codebooks
f = a[i*7:i*7+7]
c0.append(f[0]%4096)
c1.append(f[1]%4096); c1.append(f[4]%4096)
c2.append(f[2]%4096); c2.append(f[3]%4096); c2.append(f[5]%4096); c2.append(f[6]%4096)
codes = [torch.tensor(c0)[None].to(DEV), torch.tensor(c1)[None].to(DEV), torch.tensor(c2)[None].to(DEV)]
y = snac.decode(codes)[0, 0].cpu().numpy()
sf.write(out_path, y, 24000)
return out_path
# examples
tts("delta", "Good morning! It's a lovely day for a walk down by the harbour.")
tts("flynn", "No worries mate, I'll give you a hand with that.")
Available voices: flynn, angus, mason, cooper, delta, ruby, sienna, matilda.
Minimal HTTP server (optional)
from fastapi import FastAPI
from fastapi.responses import FileResponse
app = FastAPI()
@app.get("/tts")
def synth(voice: str, text: str):
return FileResponse(tts(voice, text, "/tmp/tts.wav"), media_type="audio/wav")
# uvicorn app:app --host 0.0.0.0 --port 8000
Notes
- Sampling:
temperature0.5-0.7 is a good range; lower = steadier, higher = more expressive. - Output is 24 kHz mono.
- One voice (the smallest) has less training data and is slightly less stable.
Training
- ~22 h total across the 8 voices (capped ~4 h/voice), 24 kHz, mild DeepFilterNet denoise.
- Sequence:
[SOH] + text_ids("voice: text") + [EOT,EOH,SOAI,SOS] + snac_audio + [EOS,EOAI]. - Eval + early stopping (best checkpoint kept), cosine LR 5e-5, bf16, ~1 epoch effective.
Data & license
Source audio is public domain (LibriVox). Base model and code under Apache-2.0. Speaker identities are anonymised (pseudonymous voice names).