cy_en_GB-bu_tts-bangor — Welsh/English Bilingual Neural TTS
A bilingual Welsh (Cymraeg) + English neural text-to-speech model (VITS / Piper architecture) with three studio voices.
It pronounces English natively (not Welsh-accented) and handles code-switched cy/en text within a sentence, because it is phonemized with the permissive Bangor Welsh G2P rather than eSpeak.
Developed by: Uned Technolegau Iaith (Language Technologies Unit), Bangor University Model type: Multi-speaker neural TTS (VITS), 3 voices · Languages: Welsh (cy) + English (en) · Format: ONNX
Model details
- Architecture: Piper VITS, medium quality
- Speakers: 3 (speaker ids
0,1,2) - Sample rate: 22,050 Hz · Symbols: 256 · Size: ~77 MB (ONNX)
- Phonemizer: permissive Bangor Welsh G2P —
backend: bangor,english_mode: native,data_version: b1edc63e35bb7a6f - Punctuation-aware pauses for natural phrasing; no eSpeak/GPL at inference.
⚠️ Important: phonemization
This model was trained with the Bangor G2P, so it will not produce correct pronunciation through the default eSpeak-based piper command. You must phonemize with the matching front-end:
- Python reference: piper-cy-local
core/phonemize—BangorG2P(english_mode="native") - C runtime: libcy_phonemize (same repo)
Both emit the exact phoneme-id sequence the model expects; the runtime asserts data_version == b1edc63e35bb7a6f.
Usage (Python + ONNX Runtime + Bangor G2P)
import numpy as np, onnxruntime as ort, wave, sys
sys.path.insert(0, "piper-cy-local/core/phonemize")
from bangor_g2p import BangorG2P
g2p = BangorG2P(english_mode="native")
sess = ort.InferenceSession("cy_en_GB-bu_tts-bangor-medium.onnx")
scales = np.array([0.667, 1.0, 0.8], dtype=np.float32) # noise, length, noise_w
def synth(text, sid=0, path="out.wav"):
ids = g2p.text_to_ids(text)
audio = sess.run(None, {
"input": np.array([ids], dtype=np.int64),
"input_lengths": np.array([len(ids)], dtype=np.int64),
"scales": scales,
"sid": np.array([sid], dtype=np.int64),
})[0].squeeze()
audio = (audio * (32767 / max(0.01, np.max(np.abs(audio))))).astype("<i2") # peak-normalize
with wave.open(path, "wb") as w:
w.setnchannels(1); w.setsampwidth(2); w.setframerate(22050); w.writeframes(audio.tobytes())
synth("Bore da. Sut wyt ti'n teimlo heddiw?", sid=0) # Welsh
synth("Good morning. How are you feeling today?", sid=1) # English
synth("Nes i fwcio'r tickets ar-lein, so we're all set.", 2) # code-switched
Model files
cy_en_GB-bu_tts-bangor-medium.onnx— the TTS model (ONNX)cy_en_GB-bu_tts-bangor-medium.onnx.json— config (phoneme id-map, speaker map,phonemizerblock)cy_en_GB-bu_tts-bangor-medium.safetensors— pickle-free share of the training checkpoint
Intended use & limitations
Screen readers and assistive technology, Welsh/bilingual language-learning apps, and local/offline TTS. Best on general conversational Welsh, English, and mixed cy/en text. Medium quality (assistive-grade, not studio mastering); OOV/technical terms, rare place names and unusual spellings may mispronounce; neutral tone with limited emotional range.
Licence
Released under CC0-1.0 (public domain) — free to use, modify, and distribute for any purpose without restriction. Model-code (Piper/VITS) is MIT. Built on Piper / the Rhasspy community; the acoustic model is warm-started from the VCTK Piper checkpoint (en_GB-vctk-medium), VCTK corpus © University of Edinburgh, CC BY 4.0.