Downloads · 30 days
0
nakash1987/subly-ru-tts
subly-ru-tts is a text-to-speech model from nakash1987. Use it when you need text read aloud. It is set up for coreml. The card lists the license as cc-by-4.0.
A fully on-device Russian text-to-speech voice for Apple platforms (iOS/macOS), plus everything needed to turn raw Russian text into the phoneme stream the model expects. The acoustic model is a StyleTTS2 fine-tune ex…
Downloads · 30 days
0
Access
Public
Updated Jun 18, 2026
Repo size
707 MB
Likes
1
Public
Click a slice to open those files.
.bin1.9 GB · 100%
From the Hugging Face model README
A fully on-device Russian text-to-speech voice for Apple platforms (iOS/macOS),
plus everything needed to turn raw Russian text into the phoneme stream the model
expects. The acoustic model is a StyleTTS2
fine-tune exported to Core ML, designed to run through the
FluidAudio StyleTTS2 runtime.
No server, no network at inference time, no Python.
Built for the Subly app, released openly so anyone can use it. 24 kHz, female voice, neutral narration style.
| Path | What it is | Size |
|---|---|---|
models/*.mlmodelc | 14 StyleTTS2 stages compiled to Core ML (FLOAT32): text_encoder, bert (+t64/t128/t256 token buckets), ref_encoder, fused_diffusion_sampler (+buckets), duration_predictor, fused_f0n_har_source, decoder_pre, decoder_upsample | ~867 MB |
ru_stress.bin | Word→stress dictionary, 3.19 M entries (mmap, binary-searchable) | 87 MB |
ru_accent_oov_fp32.mlmodelc | Char-level RoFormer that predicts stress for out-of-dictionary words | 2.2 MB |
ru_yo.bin | ё-restoration dictionary, 85.5 K words (е→ё) | 2.5 MB |
ru_natasha_ref.wav | Reference clip — StyleTTS2 timbre is zero-shot from this audio (24 kHz mono) | 156 KB |
ru_g2p.py | Reference grapheme→IPA phonemizer (rule-based Russian phonology) | — |
manifest.json | Flat list of every file + size (for on-demand downloaders) | — |
Russian text becomes audio in four steps. The first three are CPU-cheap; only the last touches the neural models.
raw text
→ ё-restoration (ru_yo.bin) "елка" → "ёлка"
→ stress marking (ru_stress.bin, "ёлка" → "+ёлка" (+ before the stressed vowel)
OOV model for misses)
→ grapheme→IPA (ru_g2p.py) "+ёлка" → "jˈolkə"
→ StyleTTS2 synthesis (models/, ref clip) IPA → 24 kHz waveform
This mirrors the training pipeline (RUAccent stress + a rule-based G2P), so the IPA fed at inference matches what the model was trained on.
| Param | Value | Note |
|---|---|---|
alpha | 0.5 | reference/diffusion style blend |
beta | 0.9 | more diffusion-driven prosody = livelier |
noiseSeed | 1 | a pleasant default; only changes the per-utterance sample |
| compute units | CPU-only | the diffusion stage is FP32 (can't run on ANE); under MPS the ref-encoder mixes FP16/FP32 and crashes — run on CPU |
import FluidAudio
// Point the manager at the `models/` directory from this repo.
let manager = StyleTTS2Manager(directory: modelsDir, computeUnits: .cpuOnly)
try await manager.initialize()
let ipa = "prʲɪvʲˈɛt ! ˈɛtə tʲˈɛst rˈusskəvə dʲˈiktərə ." // from the pipeline above
let samples = try await manager.synthesize(
ipa: ipa,
referenceAudioURL: refClipURL, // ru_natasha_ref.wav
alpha: 0.5, beta: 0.9, noiseSeed: 1
) // -> [Float] PCM @ 24 kHz
The IPA is tokenized by FluidAudio's StyleTTS2TextCleaner (the StyleTTS2 178-symbol
set); any symbol outside that set is dropped, so feed clean IPA.
So you can read these from any language, not just Swift.
ru_stress.bin and ru_yo.binLittle-endian, sorted by UTF-8 byte order (so a byte-wise binary search works):
ru_stress.bin: ["RUS1"][u32 count][offsets: count × u32][records]
record = [u8 keyLen][key UTF-8][u8 pos]
pos = char index of the stressed vowel (where '+' is inserted); 255 = unstressed.
ru_yo.bin: ["RUYO"][u32 count][offsets: count × u32][records]
record = [u8 keyLen][key UTF-8][u8 posCount][posCount × u8 charIndex]
charIndex = positions in the (lowercased) word where 'е' should become 'ё'.
offsets[i] is the byte offset of record i relative to the start of the records
section (= 8 + count*4). Binary-search by reading offsets[mid], then the key.
ru_accent_oov_fp32.mlmodelc (OOV stress model)Char-level token classifier (converted from RUAccent's nn_accent).
input_ids: [1, 48] int32 — [bos]=2, then chars by the vocab below, [eos]=3, padded with [pad]=0.logits: [1, 48, 3] — labels 0=NO, 1=STRESS_PRIMARY, 2=STRESS_SECONDARY.+ before char i-1 when position i is argmax PRIMARY with probability ≥ 0.55.Vocab (id → token): 0 [pad], 1 [unk], 2 [bos], 3 [eos], 4 ', 5 -, 6 .,
7 ?, 8 `, 9 c, 10 e, 11 ́ (U+0301), then Cyrillic 12 а … 43 я, 44 ё.
57/64/128/256.123 won't be voiced).This repository is released under CC BY 4.0 — use it commercially or non-commercially, just keep the attributions below.
Please credit "SOVA TTS Natasha (CC BY 4.0, Virtual Assistant LLC)" and this repo when you use the voice.