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.
Pass one of these names as the speaker. (Names are random pseudonyms; the underlying public-domain readers are not identified.)
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.
1pip install torch transformers soundfile
2pip install snac # neural audio codec used by Orpheus
A single self-contained inference function. Works on a CUDA GPU (bf16 ~7 GB VRAM); for CPU drop .to("cuda") and use float32.
1import torch, soundfile as sf
2from transformers import AutoModelForCausalLM, AutoTokenizer
3from snac import SNAC
4
5REPO = "ablmontazer/orpheus-australian-en-tts"
6DEV = "cuda"
7# Orpheus control tokens (fixed)
8SOH, EOT, EOH, SOAI, SOS, EOS, EOAI, PAD, BASE_A = 128259,128009,128260,128261,128257,128258,128262,128263,128266
9
10tok = AutoTokenizer.from_pretrained(REPO)
11model = AutoModelForCausalLM.from_pretrained(REPO, torch_dtype=torch.bfloat16).to(DEV).eval()
12snac = SNAC.from_pretrained("hubertsiuzdak/snac_24khz").to(DEV).eval()
13
14@torch.inference_mode()
15def tts(voice: str, text: str, out_path: str = "out.wav", temperature: float = 0.6):
16 # prompt format is "<voice>: <text>"
17 ids = [SOH] + tok.encode(f"{voice}: {text}", add_special_tokens=False) + [EOT, EOH, SOAI, SOS]
18 gen = model.generate(torch.tensor([ids]).to(DEV), max_new_tokens=1400, do_sample=True,
19 temperature=temperature, top_p=0.95, eos_token_id=EOAI, pad_token_id=PAD)[0].tolist()
20 audio = [t for t in gen[len(ids):] if BASE_A <= t < BASE_A + 7*4096]
21 a = [t - BASE_A for t in audio]; n = len(a)//7
22 c0, c1, c2 = [], [], []
23 for i in range(n): # de-interleave 7 tokens/frame -> 3 SNAC codebooks
24 f = a[i*7:i*7+7]
25 c0.append(f[0]%4096)
26 c1.append(f[1]%4096); c1.append(f[4]%4096)
27 c2.append(f[2]%4096); c2.append(f[3]%4096); c2.append(f[5]%4096); c2.append(f[6]%4096)
28 codes = [torch.tensor(c0)[None].to(DEV), torch.tensor(c1)[None].to(DEV), torch.tensor(c2)[None].to(DEV)]
29 y = snac.decode(codes)[0, 0].cpu().numpy()
30 sf.write(out_path, y, 24000)
31 return out_path
32
33# examples
34tts("delta", "Good morning! It's a lovely day for a walk down by the harbour.")
35tts("flynn", "No worries mate, I'll give you a hand with that.")
1from fastapi import FastAPI
2from fastapi.responses import FileResponse
3app = FastAPI()
4
5@app.get("/tts")
6def synth(voice: str, text: str):
7 return FileResponse(tts(voice, text, "/tmp/tts.wav"), media_type="audio/wav")
8# uvicorn app:app --host 0.0.0.0 --port 8000