Model reference · open weights
plapre-nano is an open-weight audio or speech model from syvai. AxForge deploys and operates it for you on dedicated EU-owned hardware — with the licence handled where one is required.
Available as managed deployment — configured and operated for you on dedicated EU hardware, quoted per deployment.
What it is
| Released by | syvai |
|---|---|
| Type | Audio & music |
| Task | Text→speech |
| Parameters (lead) | 335M |
| Runs with | transformers |
| Released | 2026-02-14 |
| Popularity | 2k downloads / month |
| Licence | Open weights |
About
Danish multi-task text-to-speech. A 335M LlamaForCausalLM that autoregressively
predicts Kanade 25 Hz
audio tokens from Danish BPE text and decodes them to 24 kHz speech. A 128-d
speaker embedding — extracted from any reference clip with the Kanade encoder —
is projected and prepended to the sequence, so every generation is voiced.
Two tasks:
| task | in → out |
|---|---|
| generate | text → speech in a chosen voice |
| edit | an existing recording + new text → the same recording with words substituted, inserted or deleted; only the masked span is regenerated, the surrounding audio is untouched |
Four controls that stack onto generate:
| control | effect |
|---|---|
| voice-reference (cloning) | speak in the voice of a reference clip (audio + its transcript) |
| context | condition on the previous utterance (text + audio) so tone, energy and tempo continue naturally across turns |
| pace | per-word duration targets (40 ms frames) — set the speaking rate, or ramp it within a sentence |
| pronunciation | up to 10 (word, reference-audio) pairs that pin how names, loanwords or acronyms are pronounced |
Controls are composable — any subset stacks in one prompt, in this block order:
[SPK] [pronunciation] [voice-reference] [context] BPE [pace] …
| combination | what you get |
|---|---|
| clone + pace | a cloned voice at a pace you set |
| clone + pronunciation | a cloned voice that says a name correctly |
| clone + context | a cloned voice continuing a conversation |
| context + pace | a conversational reply at a controlled tempo |
| clone + context + pace + pronunciation | all four at once |
| edit + pronunciation | regenerate a span so the corrected word is pronounced right |
Voice-reference is the only control that swaps the speaker embedding (to the reference clip's); the others keep the target voice. Edit composes with pronunciation only. All combinations are trained, not emergent.
The easiest path is the plapre library, which wraps every task and combination:
from plapre import Plapre
tts = Plapre("syvai/plapre-nano-v2")
# plain TTS
tts.speak("Hej, hvordan har du det?", output="out.wav", split_sentences=True)
# clone a voice from any clip
tts.clone("Denne sætning har stemmen aldrig sagt.", reference_wav="voice.wav")
# cloned voice + set pace + pinned pronunciation, in one call
tts.clone(
"Mette Frederiksen mødte Volodymyr Zelenskyj i København.",
reference_wav="voice.wav",
durations=[14, 22, 12, 24, 4, 18], # one frame count per word
pronunciations=[("Zelenskyj", "zelenskyj_ref.wav")],
)
# continue a conversation with matching prosody
tts.continue_context("Og det er derfor, vi handler nu.",
prev_text="Situationen har ændret sig markant.",
prev_wav="previous_line.wav", speaker_wav="voice.wav")
# edit a recording: replace words in place
tts.edit("… ny formulering her …", mask_start=40, mask_end=55,
original_wav="clip.wav")
import numpy as np, torch
from transformers import AutoModelForCausalLM, AutoTokenizer
from huggingface_hub import hf_hub_download
CKPT = "syvai/plapre-nano-v2"
tok = AutoTokenizer.from_pretrained(CKPT)
m = AutoModelForCausalLM.from_pretrained(CKPT, torch_dtype=torch.float32).eval()
spj = torch.nn.Linear(128, m.config.hidden_size)
spj.load_state_dict(torch.load(hf_hub_download(CKPT, "speaker_proj.pt"), map_location="cpu"))
spj.eval()
g = tok.convert_tokens_to_ids
STOPS = [g(""), tok.eos_token_id] # stop on BOTH terminators
pre = [g("")] + tok.encode(text, add_special_tokens=False) + [g("")]
pe = m.get_input_embeddings()(torch.tensor(pre))
spk = spj(torch.tensor(np.asarray(speaker_embedding), dtype=torch.float32)).unsqueeze(0)
inp = torch.cat([spk, pe], 0).unsqueeze(0)
out = m.generate(inputs_embeds=inp,
attention_mask=torch.ones(inp.shape[:2], dtype=torch.long),
max_new_tokens=500, do_sample=True, temperature=0.7,
top_p=0.95, top_k=50, eos_token_id=STOPS,
pad_token_id=tok.eos_token_id)[0].tolist()
audio_base = g("")
content = []
for t in out:
if audio_base <= t < audio_base + 12800:
content.append(t - audio_base)
elif content:
break
# decode `content` with kanade_tokenizer (frothywater/kanade-25hz-clean) -> 24 kHz wav
Control-block prompt formats (reference audio caps, `` ids, edit
masking/splicing) are implemented in
plapre/tasks.py
— pure token-layout builders you can read or reuse directly.
then —
pass both ids as stop tokens (the library does this for you).vllm>=0.15,<0.16 with enable_prompt_embeds=True
— newer stacks measurably degrade generation quality on identical weights.num2words, lang="da") before encoding.| Architecture | 335M LlamaForCausalLM (SmolLM2 layout, hidden 960, 32 layers) + 128→960 speaker projection (speaker_proj.pt) |
| Audio codec | frothywater/kanade-25hz-clean — 25 Hz content code |
From the published model card. Full card on the HuggingFace links in the sidebar.
How it works
Using it via the API
Once AxForge deploys plapre-nano for you, it answers on the OpenAI-compatible API — the same base URL and keys as every other model. (plapre-nano below is illustrative; you get the exact model name on deployment.)
$ curl -sS https://api.axforge.ai/v1/audio/transcriptions \ -H "Authorization: Bearer $AXFORGE_API_KEY" \ -F model="plapre-nano" -F file=@audio.mp3
Create an account — your API key is available in the console. 3M free tokens every 30 days with every new account.