Instructions to use AlicanKiraz0/Kizagan-TTS-v1.0 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- VoxCPM
How to use AlicanKiraz0/Kizagan-TTS-v1.0 with VoxCPM:
import soundfile as sf from voxcpm import VoxCPM model = VoxCPM.from_pretrained("AlicanKiraz0/Kizagan-TTS-v1.0") wav = model.generate( text="VoxCPM is an innovative end-to-end TTS model from ModelBest, designed to generate highly expressive speech.", prompt_wav_path=None, # optional: path to a prompt speech for voice cloning prompt_text=None, # optional: reference text cfg_value=2.0, # LM guidance on LocDiT, higher for better adherence to the prompt, but maybe worse inference_timesteps=10, # LocDiT inference timesteps, higher for better result, lower for fast speed normalize=True, # enable external TN tool denoise=True, # enable external Denoise tool retry_badcase=True, # enable retrying mode for some bad cases (unstoppable) retry_badcase_max_times=3, # maximum retrying times retry_badcase_ratio_threshold=6.0, # maximum length restriction for bad case detection (simple but effective), it could be adjusted for slow pace speech ) sf.write("output.wav", wav, 16000) print("saved: output.wav") - Notebooks
- Google Colab
- Kaggle
Kizagan-TTS-v1.0
Kızagan is a Turkish text-to-speech adaptation of OpenBMB's VoxCPM2, released by Alican Kiraz. It produces mono 48 kHz speech and includes a reference-conditioned inference script for explicit sentence-by-sentence generation.
v1.0 packages the already evaluated, merged Step 1500 checkpoint. No additional fine-tuning or weight changes were performed for this release. The release adds a documented inference recipe, runnable commands, and source-derived evaluation results.
Model and training provenance
| Item | Value |
|---|---|
| Base model | openbmb/VoxCPM2 |
| Fine-tuned checkpoint | AlicanKiraz0/Kizagan-TTS-step_1500, revision 458112a0fc3d850de38951796290e48ef710bc26 |
| Dataset | AlicanKiraz0/TR-Voice-TTS, private Turkish single-speaker corpus |
| Adaptation | LoRA, rank 64, alpha 64, LM + DiT attention projections |
| Checkpoint step | 1500 |
| Release format | Full merged weights; load directly without applying the old adapter again |
| Inference dtype / output | BF16 / mono 48 kHz |
The original merge manifest records the base snapshot and merge settings. The original training input manifest and optimizer state were not recovered during this evaluation, so this card does not claim an independently reproduced training run. Dataset recordings and raw listener response files are not redistributed in this model repository.
Install and download
The supplied command targets Linux with an NVIDIA CUDA GPU and Python 3.12. Install a CUDA-enabled PyTorch/torchaudio pair appropriate for your driver; the following uses the official CUDA 13.0 wheel index. VoxCPM is pinned to the source revision used in our evaluations.
python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install torch torchaudio --index-url https://download.pytorch.org/whl/cu130
python -m pip install "voxcpm @ git+https://github.com/OpenBMB/VoxCPM.git@f772e498a45fbb5fb8e13fbf9b9c48be9fe33e69" "huggingface_hub==1.30.0"
# Authenticate with an account that can access the repository if it is private.
hf auth login
hf download AlicanKiraz0/Kizagan-TTS-v1.0 --local-dir ./Kizagan-TTS-v1.0
The benchmark software versions below describe the existing measured environment; these installation commands do not freeze every transitive dependency. Timing and output can vary across hardware, drivers and package versions. The packaged inference command is validated separately on the recorded CUDA environment.
Inference
Supply a clean, mono reference WAV for the intended voice. Each non-empty line in a sentences file is one complete utterance; prepare the boundaries yourself. The script preserves the line order and uses the same reference afresh for every line.
# Two short utterances. Replace speaker.wav with your reference recording.
python ./Kizagan-TTS-v1.0/inference.py \
--model ./Kizagan-TTS-v1.0 \
--reference ./speaker.wav \
--sentences-file ./Kizagan-TTS-v1.0/examples/quickstart.sentences.txt \
--output-dir ./Kizagan-quickstart
# A single short utterance.
python ./Kizagan-TTS-v1.0/inference.py \
--model ./Kizagan-TTS-v1.0 \
--reference ./speaker.wav \
--text "Merhaba, bugün sana nasıl yardımcı olabilirim?" \
--output-dir ./Kizagan-single
The packaged command passed a two-utterance CUDA smoke check on 7 September 2026: 3.36 seconds of 48 kHz audio, no length-cap failure. Listen to that generated sample or inspect the validation record. This verifies the command; it is separate from the older development benchmark below.
Each command writes audio.wav, individual sentence_*.wav files and metrics.json. Use a new output directory for each run. The script fixes CFG 2.0, 16 diffusion steps and seed 42, disables compilation/denoising/automatic retries, and concatenates the generated PCM without adding silence, trimming, crossfading or changing speed. It loads the model once and builds a fresh reference cache for each utterance.
--text is one call: it does not automatically split a paragraph. For long answers, use a sentences file. The script does not automatically resolve Turkish abbreviations, numbers or ambiguous sentence boundaries. Spell out numbers as they should be spoken and keep each line a natural utterance.
Voice cloning guide
Yes: Kızagan accepts a voice reference and generates new text conditioned on that recording. This happens during inference; supplying a new recording does not train another adapter or change the model weights. A transcript is optional: the packaged inference.py uses reference audio alone.
Kızagan was fine-tuned on a Turkish single-speaker corpus. Its recorded listening evaluation used that speaker, so it does not establish cloning similarity for unfamiliar speakers, accents or languages. The API can accept another speaker's recording, but speaker similarity, style adherence and intelligibility need listening checks with that recording.
| Capability | How to use it | Evidence for this release |
|---|---|---|
| Reference-only voice cloning | inference.py --reference or Python reference_wav_path |
Packaged command tested; limited same-speaker listening results below |
| Long text with the same reference | --sentences-file, one utterance per line |
Preferred in the two recorded long-text listening trials |
| Reference plus its transcript | Python reference_wav_path + prompt_wav_path + prompt_text |
Inherited VoxCPM2 API; separate functional examples below |
| Emotion/pace guidance with a reference | A parenthesized instruction at the start of Python text |
Inherited control format; style accuracy not evaluated |
| Voice design without a reference | A voice description at the start of Python text |
Inherited control format; designed-voice quality not evaluated |
| TTS without a reference | Python generate(text=...) |
Inherited API; default-voice quality not evaluated |
| Stream audio chunks | Python generate_streaming(...) |
Python yields chunks; packaged CLI saves completed WAV files |
1. Prepare a reference recording
Use your own voice or a recording you have permission to use. Choose one speaker, a quiet room, clear pronunciation and a natural speaking style. Avoid background music, overlapping speakers, clipped peaks and long stretches of silence. Cut at word boundaries and keep the beginning and end of the spoken phrase intact.
Start with a short, representative utterance. Our measured reference was 6.175 seconds; this is an evaluated example length, not a minimum or maximum accepted by the API. A longer recording is not automatically a better reference and consumes more model context. The style in the recording can influence the result as well as the voice identity.
The packaged CLI requires non-empty, finite, mono audio. A mono WAV is the simplest input. VoxCPM2 internally resamples the input to 16 kHz; the output is 48 kHz. The measured 24 kHz reference therefore did not require manual conversion to 48 kHz.
If FFmpeg is installed, this optional conversion turns a phone recording into a mono 16 kHz PCM WAV:
ffmpeg -i ./my-recording.m4a -ac 1 -ar 16000 -c:a pcm_s16le ./speaker.wav
Conversion does not remove noise or repair clipping. Listen to the converted file before using it. Neither the supplied CLI nor the Python examples below enable denoising.
2. Clone the voice without a transcript
Run this after the installation and model download above:
python ./Kizagan-TTS-v1.0/inference.py \
--model ./Kizagan-TTS-v1.0 \
--reference ./speaker.wav \
--text "Merhaba, yeni bir metni referans sesle okuyorum." \
--output-dir ./Kizagan-voice-clone
Listen to ./Kizagan-voice-clone/audio.wav. The reference may contain different words from --text: it supplies voice conditioning, while --text supplies the new words to synthesize. No speaker.txt, speaker ID, speaker embedding export or additional fine-tuning is required for this mode.
To try another voice, pass its recording to --reference and choose a new output directory. Compare the outputs using the same short text before moving to a longer passage. This is voice-conditioned TTS, not a speech-to-speech converter: it generates speech from the supplied text rather than replacing the voice in an existing recording.
3. Keep the reference consistent across a long text
Create a UTF-8 file with one complete utterance on each line:
cat > ./my-sentences.txt <<'TXT'
Merhaba, bugün birlikte kısa bir yolculuğa çıkacağız.
Önce planımızı gözden geçirelim.
Ardından her adımı sakin ve anlaşılır biçimde anlatalım.
TXT
python ./Kizagan-TTS-v1.0/inference.py \
--model ./Kizagan-TTS-v1.0 \
--reference ./speaker.wav \
--sentences-file ./my-sentences.txt \
--output-dir ./Kizagan-long-clone
Every line starts with a fresh cache from the same original reference. Generated sentences are not fed back as the next sentence's voice prompt. This is the evaluated long-text recipe. It can still produce imperfect sentence joins; the script adds no pauses or crossfades. Listen to transitions as well as individual sentences.
Advanced Python examples
These use the pinned VoxCPM Python API, with Kızagan's merged weights. They do not require reapplying the old LoRA. Parameters such as reference_wav_path and prompt_text are Python arguments, not additional flags accepted by the packaged inference.py.
Run this setup once, then run the examples you want in the same Python session or script, from the directory containing Kizagan-TTS-v1.0 and your reference files. Use a new output folder when starting another run.
from pathlib import Path
import soundfile as sf
from voxcpm import VoxCPM
out = Path("Kizagan-python-examples")
out.mkdir(exist_ok=False)
model = VoxCPM.from_pretrained(
"./Kizagan-TTS-v1.0",
device="cuda",
load_denoiser=False,
optimize=False,
)
sample_rate = model.tts_model.sample_rate
settings = dict(
cfg_value=2.0,
inference_timesteps=16,
seed=42,
min_len=2,
max_len=1024,
normalize=False,
denoise=False,
retry_badcase=False,
)
The examples keep the release's CFG, diffusion-step count and seed. The high-level API examples are separate from the packaged command's measured streaming recipe: matching these settings does not imply identical PCM or timing. Keep targets short for initial checks. The Python API returns waveforms; it does not create the wrapper's metrics.json or provide its length-cap error report.
Reference-only cloning in Python
wav = model.generate(
text="Merhaba, yeni bir metni referans sesle okuyorum.",
reference_wav_path="./speaker.wav",
**settings,
)
sf.write(out / "reference-clone.wav", wav, sample_rate, subtype="FLOAT")
Cloning with the reference's exact transcript
Create speaker.txt in UTF-8 containing the words actually spoken in speaker.wav, in their original order. This is the reference transcript, not the new target sentence. Do not paste example words unless they match your recording.
reference_transcript = " ".join(
Path("speaker.txt").read_text(encoding="utf-8").split()
)
if not reference_transcript:
raise ValueError("speaker.txt must contain the reference recording's transcript")
wav = model.generate(
text="Şimdi yeni bir cümleyle devam ediyorum.",
reference_wav_path="./speaker.wav",
prompt_wav_path="./speaker.wav",
prompt_text=reference_transcript + " ",
**settings,
)
sf.write(out / "transcript-clone.wav", wav, sample_rate, subtype="FLOAT")
This combines a voice reference with audio/text continuation conditioning. The upstream documentation calls this Ultimate Cloning. Both audio arguments deliberately point to the same recording. prompt_wav_path and prompt_text must always be supplied together; the generated WAV contains the new output, not a file concatenation of the reference recording and the output.
The trailing space after reference_transcript preserves the boundary before the new target text: the pinned implementation concatenates prompt text and target text directly.
The API also accepts the audio/transcript pair without reference_wav_path for continuation-only conditioning. That variation is not part of our example validation. Transcript-conditioned generation is a different mode from the evaluated long-text reset recipe; higher similarity is not guaranteed for Kızagan. Keep style instructions out of the reference transcript and do not combine the transcript mode with the style-control recipe below.
Guide emotion or pace while keeping a reference
wav = model.generate(
text="(Calm, warm tone, speaking slowly)Merhaba, birlikte sakin bir başlangıç yapalım.",
reference_wav_path="./speaker.wav",
**settings,
)
sf.write(out / "controlled-clone.wav", wav, sample_rate, subtype="FLOAT")
The parenthesized prefix is the upstream format for a natural-language style instruction. It is not a speed multiplier or a guaranteed emotion label. Here the instruction is in English and the target speech is Turkish. Whether the requested pace and emotion are expressed correctly must be checked by listening; Kızagan has not been separately evaluated for instruction adherence.
Design a voice without reference audio
wav = model.generate(
text="(An adult man with a warm, gentle voice)Merhaba, bugün sana nasıl yardımcı olabilirim?",
**settings,
)
sf.write(out / "voice-design.wav", wav, sample_rate, subtype="FLOAT")
This requests a voice through a description. It does not clone a particular person. Single-speaker fine-tuning may constrain the variety retained from the base model, so this example is an API usage demonstration rather than evidence of broad voice-design quality.
For ordinary TTS without a reference or voice description:
wav = model.generate(
text="Merhaba, bugün sana nasıl yardımcı olabilirim?",
**settings,
)
sf.write(out / "no-reference.wav", wav, sample_rate, subtype="FLOAT")
Consume streaming audio chunks
import numpy as np
chunks = []
stream = model.generate_streaming(
text="Merhaba, bu ses küçük parçalar halinde üretiliyor.",
reference_wav_path="./speaker.wav",
**settings,
)
try:
for chunk in stream:
# A mono float32 NumPy array on CPU, at sample_rate Hz.
# An application can send each chunk to its audio playback queue here.
chunks.append(chunk)
finally:
stream.close()
if not chunks:
raise RuntimeError("The model returned no audio chunks")
sf.write(out / "streaming-clone.wav", np.concatenate(chunks), sample_rate, subtype="FLOAT")
This example collects chunks into a WAV. It demonstrates the generator interface; it does not implement a live player, HTTP endpoint or streaming server. The packaged inference.py also streams internally, but its user-facing outputs are files.
Troubleshooting and validation boundaries
| Symptom | Check |
|---|---|
--reference must contain finite, non-empty mono audio |
Convert stereo to mono; check that the file contains readable samples. |
--output-dir already exists |
Use a new directory; the packaged command preserves existing outputs. |
prompt_wav_path and prompt_text must both be provided |
Supply both the recording and its transcript, or use reference-only mode. |
| Voice differs from the intended speaker | Check reference quality and compare short targets first; unfamiliar-speaker similarity has not been established for this fine-tune. |
| Output drifts toward the end of a paragraph | Use explicit sentence lines with the same original reference for every line. |
| A style instruction is ineffective or spoken aloud | Remove the prefix and compare reference-only generation; instruction adherence is unmeasured. |
| Transcript-conditioned output repeats or omits words | Check the reference transcript and phrase boundary; compare against reference-only mode. |
| A generation is cut short | Inspect the packaged command's metrics.json and shorten the utterance/reference context. API examples do not implement that cap check. |
On 7 September 2026, all six generation examples above produced finite, non-empty, mono 48 kHz audio on the recorded RTX PRO 6000 environment, using Kızagan weights from release commit 90d34bee01d7ffaf3d7cffce3fbabdb8f3329dde. For this functional check, the published synthetic quickstart audio and its source text supplied the reference and transcript. The revised transcript example also passed with a transcript lacking terminal punctuation, verifying the explicit word boundary. The streaming example yielded multiple chunks whose concatenation matched the saved waveform. These are execution checks, not listening tests of the advanced modes.
API availability, successful waveform generation and perceived cloning quality are different checks. The recorded human ratings below apply to the original same-speaker reference recipe, not to new voices, transcript conditioning, voice design, style control or other languages. The published quickstart WAV is generated speech, not a replacement for a clean recording of the voice you want to use.
Measured inference examples
Measurements below come from the fixed 5 September 2026 development run on an NVIDIA RTX PRO 6000 Blackwell Workstation Edition, 96 GB, CUDA BF16, CFG 2.0, 16 diffusion steps, seed 42 and the same reference clip. They are observations from two texts, not a throughput SLA.
| Example | Sentences | Generated audio | Sum of call times | Aggregate RTF | Peak PyTorch reserved |
|---|---|---|---|---|---|
| Library, 151 words | 12 | 68.16 s | 24.521 s | 0.360 | 6,114 MiB |
| Train platform, 149 words | 13 | 66.72 s | 24.042 s | 0.360 | 6,114 MiB |
Aggregate RTF = sum(call elapsed seconds) / sum(audio seconds). Calls include reference-cache preparation and generation; these totals exclude model loading, file I/O, gaps between calls and final assembly. Peak reserved memory is a PyTorch allocator measurement, not total GPU process memory. First-chunk measurements and whole-paragraph comparisons are in evaluation/README.md; the first whole-paragraph call was cold relative to later calls, so their first-chunk timings are not an equal-warmup comparison.
Run the same texts and record your own measurements:
python ./Kizagan-TTS-v1.0/inference.py \
--model ./Kizagan-TTS-v1.0 \
--reference ./speaker.wav \
--sentences-file ./Kizagan-TTS-v1.0/examples/library.sentences.txt \
--output-dir ./Kizagan-library
python ./Kizagan-TTS-v1.0/inference.py \
--model ./Kizagan-TTS-v1.0 \
--reference ./speaker.wav \
--sentences-file ./Kizagan-TTS-v1.0/examples/platform.sentences.txt \
--output-dir ./Kizagan-platform
In the new script, call_elapsed_s and call_rtf include fresh reference-cache preparation through generator completion; generation_elapsed_s and rtf cover generation only. Download/path resolution and model load are reported separately. These are generation measurements, not network-serving latency.
The measured reference was r2, a 6.175 s, mono 24 kHz validation recording, SHA-256 5f36097c430ae461dc55d76ebe4ef897442e5a34f19c48cfdb9e909afd85c18d. It is not included because it belongs to the private dataset. Using your own speaker.wav reproduces the procedure, not the exact benchmark conditions or voice. Audio durations and results may differ.
| Recorded environment | Version |
|---|---|
| Python | 3.12.13 |
| PyTorch | 2.14.0+cu130 |
| torchaudio | 2.11.0+cu130 |
| transformers | 5.16.1 |
| VoxCPM source | f772e498a45fbb5fb8e13fbf9b9c48be9fe33e69 |
| NumPy / SoundFile | 2.5.2 / 0.14.0 |
Detailed measurements, error counts and source hashes are in evaluation/metrics.json.
Listening results and limits
One Turkish listener compared sentence-by-sentence and whole-paragraph generation on two new development texts, with balanced A/B positions and matched listening loudness:
| Example | Sentence-by-sentence naturalness / similarity | Whole-paragraph naturalness / similarity | Preference |
|---|---|---|---|
| Library | 5/5 and 5/5 | 1/5 and 1/5 | Sentence-by-sentence |
| Train platform | 4/5 and 5/5 | 1/5 and 1/5 | Sentence-by-sentence |
The listener reported deterioration toward the end of both whole-paragraph outputs. The second sentence-by-sentence artifact checkbox was unanswered, so it is not labelled artifact-free. A separate earlier development paragraph also favored sentence-by-sentence generation; it is not pooled into these two trials. These observations support the supplied recipe for development use, not population MOS, an isolated causal explanation or guaranteed quality on arbitrary text.
Fixed ASR word-error counts for whole-paragraph / sentence-by-sentence audio were 1/151 / 0/151 on the library text and 2/149 / 2/149 on the platform text. ASR differences include orthographic and recognition ambiguity; they are not substitutes for listening or confirmed pronunciation mistakes. This release does not establish Step 1500 as universally better than Step 2000, nor does it claim that an earlier final-evaluation gate was passed by the new sentence-based method. Evaluate your own text, reference and serving environment before depending on its behavior.
Acknowledgments and attribution
A heartfelt thank you to the OpenBMB team and the VoxCPM contributors for making VoxCPM2, its weights, training tools and implementation available. Kızagan builds directly on their work; this Turkish adaptation and its evaluation would not have been possible without that foundation. OpenBMB ekibine ve VoxCPM2'ye emek veren tüm araştırmacılara çok teşekkür ederiz.
- Base model: openbmb/VoxCPM2
- Upstream implementation: OpenBMB/VoxCPM
- Technical report: Zhou et al., VoxCPM2 Technical Report (2026)
- Earlier work: VoxCPM (2025)
This is an independent community adaptation; OpenBMB authorship applies to the foundation model and upstream implementation. See LICENSE and NOTICE for preserved licensing and attribution.
- Downloads last month
- 410