import os, torch, soundfile as sf
os.environ.setdefault("PHONEMIZER_ESPEAK_LIBRARY", "/usr/lib/x86_64-linux-gnu/libespeak-ng.so.1")
from transformers import AutoModelForCausalLM, AutoTokenizer
from peft import PeftModel
from snac import SNAC
from phonemizer.backend import EspeakBackend
from phonemizer.separator import Separator
CODE_START, CODE_END, OFFSET = 128257, 128258, 128266
SNAC_MIN, SNAC_MAX = 128266, 156937
dev = "cuda"
tok = AutoTokenizer.from_pretrained("maya-research/maya1")
model = AutoModelForCausalLM.from_pretrained("maya-research/maya1", dtype=torch.bfloat16).to(dev)
model = PeftModel.from_pretrained(model, "texdata/Maya1-Slovenian-TTS").eval()
snac = SNAC.from_pretrained("hubertsiuzdak/snac_24khz").eval().to(dev)
be = EspeakBackend("sl", with_stress=True, preserve_punctuation=True)
def unpack_snac(ids):
frames = len(ids) // 7; ids = ids[:frames*7]; l1,l2,l3 = [],[],[]
for i in range(frames):
s = ids[i*7:(i+1)*7]
l1.append((s[0]-OFFSET)%4096)
l2 += [(s[1]-OFFSET)%4096, (s[4]-OFFSET)%4096]
l3 += [(s[2]-OFFSET)%4096, (s[3]-OFFSET)%4096, (s[5]-OFFSET)%4096, (s[6]-OFFSET)%4096]
return [l1,l2,l3]
def synth(text, desc="A Slovenian voice, speaker Artur-B-G0911.", temperature=0.75):
phonemes = be.phonemize([text], separator=Separator(phone="", word=" "), strip=True)[0]
content = f'<description="{desc}"> {phonemes}'
prompt = tok.apply_chat_template([{"role": "user", "content": content}],
tokenize=False, add_generation_prompt=True)
ids = tok(prompt, add_special_tokens=False, return_tensors="pt").input_ids.to(dev)
out = model.generate(ids, max_new_tokens=1800, do_sample=True, temperature=temperature,
top_p=0.9, repetition_penalty=1.1, eos_token_id=CODE_END, pad_token_id=CODE_END)
gen = out[0, ids.shape[1]:].tolist()
snac_ids = [t for t in gen if SNAC_MIN <= t <= SNAC_MAX]
codes = [torch.tensor(c, device=dev).unsqueeze(0) for c in unpack_snac(snac_ids)]
audio = snac.decoder(snac.quantizer.from_codes(codes))[0,0].detach().cpu().numpy()
return audio
sf.write("out.wav", synth("Danes je lep sončen dan in ptice pojejo."), 24000)