Ming-3.0-tts clones a voice in about 3 GB of GPU memory, but speaks slower than real time
inclusionAI's MIT speech model on a 16 GB card: 2.9 GB peak, 17 of 19 lines word for word, clones that held, about 0.65x real time.
We wanted to know whether a 3 GB speech model really runs on a small graphics card. Ming-3.0-tts-0.5B is an MIT-licensed model from inclusionAI, Ant Group's AI lab, and its authors only list tests on data-center cards with 80 GB and 96 GB of memory. On a 16 GB RTX 2000 Ada it needed 2.9 GB at its peak, and made the exact same audio when allowed only 3 GB, as on a small card. We typed a laugh and a sigh into a line of text: every word came out right, and the waveform shows bursts where the laugh tag sat. If you run your own GPUs, that means one small card can clone a voice, invent a new one from a sentence and speak Spanish as well as English. The catch is speed: about 1.5 seconds of work for every second of speech. So it suits recorded narration, not a live voice agent. Our SDK example deploys it on your own GPU in about a minute.
![Two waveforms of the same cloned voice saying the same line on one RTX 2000 Ada 16 GB. Top, no tags: 5.3 s of audio in 8.1 s of GPU time, 0.66x real time. Bottom, with [Laughter], [Sigh] and [Uhm] in the text: 7.0 s of audio in 11.0 s, 0.63x. Amber boxes mark each tag: laughter bursts before 'Okay', only a faint breath at the sigh, and the 'Um' that Whisper heard](/assets/research/ming-tts-voice-design-small-gpu/key-comparison.jpg)
Same voice, same line, same card. The three tags in brackets added 1.7 seconds of sound. The words came out right both times.
- Without tags (5.3 s)
- With [Laughter], [Sigh] and [Uhm] (7.0 s)

What the model page promises: five ways to shape a voice in a 3 GB download
The model page lists five ways to shape a voice. It clones a voice from a short clip. It builds a new voice from a written description ("voice design"). It follows free-form directions on how to say a line. It ships built-in English and Chinese voices. And it takes 14 inline tags, words in square brackets such as [Laughter], [Sigh], [Cough] or [Uhm], that turn into sounds in the middle of a sentence.
The page lists Chinese, English, German, Spanish, French, Korean and Japanese, plus two Chinese dialects.
The credit for the model belongs to the inclusionAI team at Ant Group. They released the weights and the code under MIT, which allows commercial use, with their own benchmarks and an honest limitations section. On their tests, Ming gets about 1.6 English words in 100 wrong, between two rival open models (1.45 and 1.83). In Spanish it is about 1.1 in 100. At matching a written voice description in Chinese, it scores 72.3% against Qwen3-TTS's 77.1%. We did not rerun any of these.
We spotted it in the AI Search news video of 25 October. The presenter said the small model is "only around three gigabytes, so you should be able to run it on many consumer GPUs."
The model page says something narrower: "Tested on NVIDIA H800-80GB and H20-96G with CUDA 12.4." Those are data-center cards, and the authors give no memory figure and no smaller GPU. Our part was the rest: packaging their code, running it on a smaller card, and checking the output.
The test: one 16 GB card, 19 lines in three languages, checked by machine
We ran the authors' own code, unchanged, on one RTX 2000 Ada with 16 GB. It is a small workstation card with a 70-watt power limit. We sent 19 test lines in English, Spanish and Chinese, plus three controls: two lines without their tags and one with the numbers written as words. They covered cloning, voice design, free-form direction, built-in voices and tags, plus numbers and paragraphs of up to 21 seconds. Then we repeated five of them on an RTX 4090 to see whether a faster card speeds it up.
For cloning, we needed a voice nobody owns. So the reference was a synthetic 5.2-second support-desk line from a stock voice of Pocket TTS, a small speech model by Kyutai that we also run. That follows the authors' own rule: do not impersonate anyone without consent, and label synthetic speech as synthetic.
- Reference voice: synthetic (5.2 s)
The checks were done by machine. Whisper, OpenAI's speech-to-text model, transcribed every clip. A speaker-recognition model scored how close each clone sounds to the reference, from 0 (unrelated) to 1 (identical). Nobody on our side listened to the clips, so we can tell you the words were right and the voice matched, not how natural it sounds. The reference was also the easy case: a clean synthetic clip, not a real voice from a laptop mic or a phone line. Each line ran only once.
Results: 17 of 19 lines word for word, and clones that keep the voice in Spanish
The text was almost always exact. Of 19 lines, 17 came back word for word in English, Spanish and Chinese, including paragraphs of 18 to 21 seconds. Both misses were numbers, covered in the next section.
The clones held, even across languages: from an English reference, the Spanish clone kept the voice as well as the English one.
| Clip | Same voice as the reference? (0 to 1) |
|---|---|
| English clone | 0.87 |
| English clone with tags | 0.85 |
| Spanish clone, from the English reference | 0.84 |
| Built-in voice US_Emma (not a clone) | 0.54 |
| Designed narrator voice (not a clone) | 0.32 |
One caveat: our scoring model is the one Ming itself uses to learn a voice, so it leans in Ming's favour. A second, independent checker agreed, but it is lenient: it also rated a different female voice close to our female reference.
- Clone in English (4.6 s)
- The same clone in Spanish (7.0 s)
The tags made real sounds, but only some can be checked. Tagged clips were 1.3 to 1.7 seconds longer than the same lines without tags. Whisper wrote "Um" where [Uhm] sat and "Huh?" for [Question-huh]. Laughs have no words, but the waveform shows them. The sigh barely shows. We tested tags in English only. The authors document them for English and Chinese text, so tags inside Spanish are untested.
Voice design got every word right. We asked for "a gravelly old sea captain in his seventies, amused and a little hoarse", among others, and every designed line came back word for word. The designed voices are clearly different from our reference (0.25 to 0.32). Whether each voice fits its description, we did not measure.
- Designed voice: an old sea captain (6.4 s)
Where it breaks: numbers, and speech that comes out slower than it plays
Numbers are unreliable, and the model is slower than real time on every card we tried.
Numbers. The two misses came from the step that turns written text into words to say. In English, 4521 was read as "four thousand five hundred twenty, one", with a pause. A phone number, 555-0142, was read as "five hundred fifty-five minus one hundred forty-two". Spanish skips that step entirely. So "1.249,99 euros, un 12,5 %" came out garbled. Writing the numbers as words did not fix the English case. If a price or an order number matters, check the audio.
- Numbers misread (16.1 s)
Speed. "Real time" means one second of audio made in one second. On the RTX 2000 Ada, a 20.7-second English paragraph took 31 to 32 seconds to make, and every line but one Chinese outlier ran at that pace. The RTX 4090, a far faster card, made a 20.9-second paragraph in 27 seconds. That is about 17% faster, and part of it may come from the 4090 machine's different processor.
The card was not the bottleneck. The small card was busy less than a third of the time, the 4090 a fifth at most. Ming writes audio in slices of 80 milliseconds, one after another. Between slices, a loop written in Python does its bookkeeping and hands the next slice to the card. In the time 12.5 slices play, it makes about 8.5: two thirds of the pace. Think of a session guitarist who waits for the bandleader to call every chord: hire a faster guitarist and the song still runs at the bandleader's pace.
The authors' roadmap marks support for a faster serving engine, vLLM-Omni, as done. We did not try that route, so whether it fixes the speed is open.
One request was much slower: the authors' own Chinese voice-design example took 50 seconds for 5 seconds of audio, because the model never decided one piece of text was finished. We did not see it in English or Spanish.
Which GPU: capped at 3 GB, the audio was identical
The smallest setup that worked: our 16 GB card with the model allowed only 3 GB of its memory, with default settings. The audio was byte-for-byte identical to the uncapped run, at the same speed.
The driver needs about 0.4 GB on top, so we estimate a 4 GB card is enough, untested.
No real card under 16 GB ran. We tried a 12 GB RTX 3080 Ti twice, and both machines came up without the remote access our setup needs, so neither ever ran the model. 8 GB cards were out of stock. A smaller chip could also be slower than ours, and we have no number for it.
On InferenceKey: ready in 60 seconds, with the authors' own code behind an API
On your own GPU you can run the authors' code as it is, without waiting for someone to package it, and ours was serving in 60.3 seconds. InferenceKey has no ready-made support for Ming, and the authors ship it as Python code, so we put that code behind an API. Our custom backend is a short Python file that InferenceKey installs and runs on your GPU machine. It fetches the authors' code at a fixed version, downloads the weights and loads the model once. Your app then calls it the way it calls OpenAI's chat API, and gets back the WAV inside the reply.
From a clean machine, about half of that time was installing the Python libraries. The 3 GB of weights took 7 seconds to download and under 3 seconds to load. With everything already on disk, a restart took about 13 seconds. The backend answers one request at a time, and we did not test several at once.
One rough edge you will hit too:
- Apps built for OpenAI ask for speech at a separate address, and that address cannot return a custom backend's audio yet. So the example uses the chat address and reads the audio out of the reply's text. Status: open, tracked as IK-531.
Should you use it? Yes for recorded narration on a small card, no for live voice
- If you make voice-overs, audiobook samples or narrated demos, it is worth running. One small card gives you cloning, designed voices and tags, and the license allows commercial use. The words and the voice match held up on machine checks. Listen to the samples above before you commit.
- If you need a voice agent that answers in real time, look elsewhere for now. It makes speech slower than it plays, and a bigger card barely helps.
- If your text has prices, phone numbers or dates, check every one in the audio.
- If you need Spanish, it is usable for cloned narration, with numbers checked by hand. Our earlier Spanish Pocket TTS voice ran faster than real time on a desktop CPU (1.05x), Ming at 0.61 to 0.77x on a GPU. We have not compared their quality.
- If your card is small, we estimate about 4 GB is enough for memory, untested (see the GPU section).
To hear four lines on your own NVIDIA GPU, publish the backend with python publish.py and run python main.py from the SDK example. You get a built-in voice, a designed voice, a clone with a laugh and a sigh, and the same clone in Spanish. You need an InferenceKey project with an SDK token and an API key. Your GPU machine needs an up-to-date NVIDIA driver (CUDA 12.4 or newer) and about 3 GB of free GPU memory.
For engineers
Model and files
Model card, GitHub (inclusionAI/Ming-3.0-tts), authors' benchmarks. Repo inclusionAI/Ming-3.0-tts-0.5B, created 2026-09-22, lastModified 2026-10-27T12:07:15Z, sha 7247f4c94a5b2e987404ed28a5cfec41b1a4ca61, license MIT, not gated, pipeline text-to-speech, 5,546 downloads and 156 likes on 2026-10-28.
model.safetensors: 2,959,055,504 B. Safetensors metadata: 1,479,454,868 parameters (1,479,454,804 BF16 plus 64 F32).campplus.onnx(speaker encoder): 28,303,423 B. Full repo about 3.0 GB, including a 390,569 B PDF (Ming-3.0-tts-0.5B-TDS2026.pdf) and figures.- Card table: dense, Qwen2.5-0.5B backbone, 0.5B parameters. The weights file stores about 1.48 billion in all; the authors do not break down where the rest sits. Also on the card: languages zh, en, de, es, fr, ko, ja, dialects Sichuanese and Cantonese, Python API
ming_tts.MingTTS, CLIinfer.py, 44.1 kHz. - The 14 tags:
[Breathing],[Cough],[Sigh],[Laughter],[Surprise-ah],[Surprise-oh],[Dissatisfaction-hnn],[Uhm],[Confirmation-en],[Question-ei],[Question-ah],[Question-en],[Question-oh],[Question-huh]. Documented for Chinese or English text, case-sensitive, routed around text normalization (cookbooks/instruction_en.md,frontend/toolkit.py). - Tasks:
TTS,FREEFORM,VOICE_DESIGN,MULTILINGUAL,BASIC,EMOTION,DIALECT,IP. - Hardware statement: "Tested on NVIDIA H800-80GB and H20-96G with CUDA 12.4. flash-attn is optional; inference falls back to PyTorch SDPA." No smaller GPU and no VRAM figure.
- Code at commit
9332fb9443325d4726ce02cefd4ec1c211df4079(2026-10-27, "docs: align recommended voices, catalogs and examples"), the commit our backend pins. Earlier:028c1eac(2026-10-21, long-text splitting fix),e999c39f(2026-10-19, "mark vLLM-Omni support").requirements.txtpins torch 2.6.0, torchaudio 2.6.0, transformers 4.46.3, accelerate 1.3.0, x_transformers 2.9.2, diffusers 0.33.0, soundfile 0.12.1, plus onnxruntime, inflect, einops. pynini 2.1.6 (text normalization) and flash_attn 2.7.4.post1 are optional. A Docker image is offered (torch 2.6, CUDA 12.4, transformers 4.46.3). MingTTSloads intorch.bfloat16(hardcoded) oncuda:0.synthesize()defaults:cfg=2.0,sigma=0.25,temperature=0.0,max_length=24(fragment split),max_decode_steps=1000. Non-zh/enlanguage_idtext bypasses the FST normalizer ("Non-zh/en text is passed through unchanged").- Decode loop (
modeling_bailingmm.py): one LLM forward plus a flow-matching head (FlowLoss.sample, 10 steps by default, with CFG) per step, until a stop head fires. The 512-position static KV cache caps the budget at 512 minus the prompt length. The audio VAE uses hop 882 at 44,100 Hz with patch_size 4, so one step is 80 ms of audio and real time needs 12.5 steps/s. We measured about 8.3 to 8.9 steps/s. - The sibling model, Ming-3.0-tts-tiny, is an MoE on Ling V3 (7.9B total, 1.3B active), needs its own environment (Python 3.10.15, torch 2.7.1+cu118), recommends an H800, and is the only one with multi-speaker podcast dialogue. We did not run it.
- Leaderboards claimed in the GitHub README (Artificial Analysis, October 2026): 1st among open weights on Controlled Voice (Elo 1069, 13th overall), 1st overall on Pronunciation Robustness (93.2%), 3rd among open weights on Provider Voice (Elo 1188, 17th overall). The README does not say whether these are for 0.5b or tiny. We did not check artificialanalysis.ai.
Authors' benchmarks (not reproduced by us)

| Test | Ming-3.0-tts-0.5B | Others in the authors' table |
|---|---|---|
| Seed-TTS EN WER (lower is better) | 1.584% (SIM 0.691) | Qwen3-TTS-12Hz-1.7B 1.24, CosyVoice3-1.5B 1.45, F5-TTS 1.83, CosyVoice3-0.5B 2.02 |
| Seed-TTS ZH WER | 0.800% | |
| MiniMax multilingual WER | German 0.365%, Spanish 1.099% (SIM 0.763), French 4.264% (SIM 0.675) | |
| InstructTTSEval-ZH voice design average | 72.29% | Qwen3-TTS 77.13, Ming tiny 75.37, Mimo-Audio-7B-Instruct 70.50, VoiceSculptor 67.30 |
| NVBench English single CER | 7.60 | Ming tiny 5.86, CosyVoice3 7.87 |
Authors' limitations: speaker similarity is weaker than content accuracy (French SIM is the clearest gap). NVBench Multi trails Single, so stability with several tags per sentence is still improving. Emotion is harder when the words carry no emotional signal. Pitch is less accurate, and open-ended voice design does not yet match the strongest evaluated system. The usage disclaimer forbids impersonating a real person without consent and asks that synthetic speech be labelled as synthetic.
Setup
- One RTX 2000 Ada 16 GB on our cloud (driver 595.91.07, compute capability 8.9, 70 W limit, AMD EPYC 7352 host with 6 vCPUs), registered as a worker with a local InferenceKey manager. Production was never touched. An RTX A4000 and an RTX 4000 Ada were out of stock.
- Speed check: one RTX 4090 24 GB (450 W, AMD EPYC 75F3 host), 5 cases.
- Custom backend
ming-3-tts-05b0.1.0 (7,215-byte package).setup()fetches the Ming source tarball at the pinned commit (skipsming_tiny, figures, docker, cookbooks), runssnapshot_downloadof the pinned revision (no PDF or figures), buildsMingTTS(model_dir, device, text_normalization=True)with the pynini 2.1.6.post1 wheel, applies an optionalMING_VRAM_LIMIT_GIBthroughtorch.cuda.set_per_process_memory_fraction, and warms up with the built-in voice US_Emma. bf16, SDPA, authors' defaults, seed 1895. - Reference voice: synthetic 5.22 s English clip from our local Pocket TTS stock voice "anna": "Thanks for calling the support line. I can help you reset your password in just a minute." Spanish clone line: "Gracias por llamar. Su nueva contraseña ya está lista; por favor, vuelva a iniciar sesión en todos sus dispositivos."
- Checks on the pod:
openai/whisper-large-v3-turbowith the language forced per case, CAM++ (campplus.onnx, the encoder Ming conditions on) andmicrosoft/wavlm-base-plus-sv(independent).
Time to ready
| Phase | Time |
|---|---|
ensure() to ready, empty caches, RTX 2000 Ada | 60.3 s |
| of which: worker builds the backend venv | about 32 s |
| of which: backend setup | 26.4 s (source 0.9 s, weights 7.1 s, load 2.7 s, warm-up 3.7 s) |
| Warm restarts (venv and weights cached) | 13.1, 12.9, 12.7, 13.2 s |
ensure() to ready, empty caches, RTX 4090 | 47.3 s |
Per request, RTX 2000 Ada
Non-streaming POST /endpoint/<project>/ming-tts/v1/chat/completions. GPU s is the backend's synchronised time around synthesize(). Round trip measured on the client, through a tunnel.
| Case | Task | Audio s | GPU s | x real time | Peak alloc MiB | Round trip s | Whisper heard |
|---|---|---|---|---|---|---|---|
| en-ip-george | IP UK_George | 5.3 | 8.39 | 0.63 | 2,919 | 8.52 | exact |
| en-ip-emma | IP US_Emma | 8.2 | 12.95 | 0.63 | 2,924 | 13.18 | exact ("I am" for "I'm") |
| en-freeform-coach | FREEFORM | 4.9 | 7.79 | 0.63 | 2,890 | 8.01 | exact |
| en-freeform-whisper | FREEFORM ("Whisper, tense and frightened") | 2.9 | 4.79 | 0.61 | 2,888 | 4.96 | exact |
| en-design-narrator | VOICE_DESIGN | 4.2 | 6.71 | 0.63 | 2,926 | 6.91 | exact |
| en-design-captain | VOICE_DESIGN | 6.4 | 10.03 | 0.64 | 2,927 | 10.24 | exact |
| en-design-girl | VOICE_DESIGN | 3.5 | 5.66 | 0.62 | 2,922 | 5.84 | exact |
| en-clone | TTS + reference | 4.5 | 7.07 | 0.64 | 2,916 | 7.53 | exact |
| en-clone-tags | TTS + reference, [Laughter] [Sigh] [Uhm] | 7.0 | 11.02 | 0.63 | 2,922 | 11.49 | exact + "Um," |
| en-clone-notags (control) | same text, no tags | 5.3 | 8.05 | 0.66 | 2,917 | 8.62 | exact |
| en-ip-tags | IP, [Breathing] [Cough] [Question-huh] | 5.5 | 8.71 | 0.63 | 2,924 | 8.92 | text + "Huh?" |
| en-ip-notags (control) | same text, no tags | 4.2 | 6.40 | 0.66 | 2,920 | 6.58 | exact |
| en-numbers | IP US_Emma | 16.1 | 25.04 | 0.64 | 2,936 | 25.32 | numbers wrong |
| en-numbers-words (control) | numbers spelled as words | 5.9 | 8.92 | 0.66 | 2,920 | 9.12 | "Order Number 40, 520, 1 ... 2020, 6." |
| en-long | IP UK_George, 61 words | 20.7 | 32.41 | 0.64 | 2,923 | 32.96 | exact |
| es-clone | MULTILINGUAL es + English reference | 6.9 | 10.48 | 0.66 | 2,920 | 10.85 | exact |
| es-ip-emma | IP US_Emma + language_id es | 7.6 | 11.60 | 0.66 | 2,927 | 11.79 | exact |
| es-design | VOICE_DESIGN + es | 4.9 | 7.64 | 0.64 | 2,930 | 7.82 | exact |
| es-freeform | FREEFORM + es | 5.7 | 8.62 | 0.66 | 2,894 | 8.83 | exact |
| es-long | MULTILINGUAL es, 52 words | 18.5 | 28.01 | 0.66 | 2,922 | 28.61 | exact |
| es-numbers | MULTILINGUAL es | 11.4 | 17.08 | 0.67 | 2,927 | 17.99 | numbers wrong |
| zh-design-authors | VOICE_DESIGN, the authors' Chinese example | 5.0 | 49.84 | 0.10 | 2,988 | 50.00 | exact |
- Round trip minus GPU time: 0.13 to 0.9 s (base64 WAV through the tunnel and the message bus, a 20 s clip is about 1.8 MB raw). Across runs, the 20.7 s paragraph took 31.0 to 32.4 s of GPU time.
zh-design-authors: the text was split in two fragments and the first ran the whole decode budget (343 steps, 41 s, stop head never fired) before the trailing silence was trimmed.- GPU memory: 2,846 MiB allocated after load, 2,888 to 2,936 MiB peak allocated per request (2,988 MiB on the Chinese outlier). nvidia-smi card peak 3,336 MiB, including the CUDA context. GPU utilisation 23 to 31%, about 24 W of 70 W.
- The backend serves one request at a time (a lock plus workload concurrency 1). No parallel test.
- With the same seed, outputs are deterministic per card but differ slightly across cards (5.2 vs 5.3 s for en-ip-george, 7.0 vs 6.4 s for the captain).
RTX 4090 speed check
| Case | Audio s | GPU s | x real time | Round trip s |
|---|---|---|---|---|
| en-ip-george | 5.2 | 6.85 | 0.76 | 8.44 |
| en-design-captain | 7.0 | 9.05 | 0.77 | 9.62 |
| en-clone-tags | 6.9 | 8.94 | 0.77 | 9.80 |
| en-long | 20.9 | 27.11 / 27.79 | 0.77 / 0.75 | 27.94 / 28.49 |
| es-clone | 6.9 | 9.23 | 0.75 | 9.93 |
nvidia-smi during en-long: 3,562 MiB, 14 to 20% utilisation, about 81 W of 450 W. The step loop is launch and CPU bound. We did not separate how much of the roughly 17% gain comes from the faster host CPU.

VRAM ladder
The narrative rounds these caps to GB; the exact values are GiB. Caps set with MING_VRAM_LIMIT_GIB (torch.cuda.set_per_process_memory_fraction) on the RTX 2000 Ada, each a fresh ensure() with warm caches. WAVs of en-clone-tags, en-ip-george, en-long and es-clone compared by md5 against the uncapped run.
| Rung | Config | Peak alloc | Speed | Output | Real or emulated |
|---|---|---|---|---|---|
| RTX 4090 24 GB | bf16, SDPA, default | 2,923 MiB (3,562 MiB card) | 0.75 to 0.77x | text exact on the subset | real |
| RTX 2000 Ada 16 GB | bf16, SDPA, default (main run) | 2,936 MiB (3,336 MiB card) | 0.61 to 0.68x | reference | real |
| 8 GiB cap | MING_VRAM_LIMIT_GIB=8 | 2,923 MiB | 0.66 to 0.67x | byte-identical | emulated |
| 4 GiB cap | MING_VRAM_LIMIT_GIB=4 | 2,923 MiB | 0.64 to 0.66x | byte-identical | emulated |
| 3 GiB cap | MING_VRAM_LIMIT_GIB=3 | 2,923 MiB | 0.65 to 0.68x | byte-identical | emulated |
| 2.75 GiB cap | MING_VRAM_LIMIT_GIB=2.75 | setup() failed: CUDA out of memory. Tried to allocate 20.00 MiB ... this process has 2.83 GiB memory in use. 2.75 GiB allowed | emulated | ||
| RTX 3080 Ti 12 GB | two attempts | the machine came up without direct SSH (no port 22 mapping) and the manager terminated it after 180 s, twice | real, never ran |
Not tried: any real card under 16 GB, fp16 on pre-Ampere cards, flash-attn, vLLM-Omni, CPU.
Quality details
- Words: 17 of 19 bench clips word for word. Ladder and 4090 subsets gave identical text.
- English numbers. The normalizer output in the backend log was
Order number four thousand, five hundred twenty,one ships on March three , two thousand twenty,six and costs one thousand, two hundred forty,nine point nine nine dollars , about twelve point five percent less than last year. Call five hundred fifty,five minus one hundred forty,two .The hyphen becomes a full-width comma (a pause), and the phone number 555-0142 is read as a subtraction. Whisper heard "Order number 4520. One ships ... costs $1,240, $9.99 ... Call 550-5-142". Spelling the numbers as words did not avoid it ("forty-five twenty-one" became "40, 520, 1"). - Spanish numbers skip the normalizer: "1.249,99 euros, un 12,5 %" was heard as "1.1249.99 euros, un 2,5%".
- Speaker similarity, CAM++ cosine against the reference: en-clone 0.865, en-clone-tags 0.849, es-clone 0.838, es-long 0.853, es-numbers 0.836. Non-clones 0.162 (Chinese) to 0.540 (US_Emma). Designed voices 0.25 to 0.32. WavLM-SV: clones 0.924 to 0.970, but built-in US_Emma (a female voice like the reference) also 0.84 to 0.86, so WavLM separates less. Cross-lingual cloning (English reference, Spanish output) kept the voice as well as same-language cloning by both measures.
- Tags: 7.0 vs 5.3 s (clone,
[Laughter][Sigh][Uhm]) and 5.5 vs 4.2 s (built-in voice,[Breathing][Cough][Question-huh]). Tag boxes in the key image come from Whisper word timings and are approximate. No human listening test. - Voice design and free-form direction in English and Spanish gave exact text. Prompts included "A gravelly old sea captain in his seventies, amused and a little hoarse..." and "Whisper, tense and frightened, very quietly and slowly." Whether the voice matches the description was not measured.
- No crash, NaN or empty output in about 60 requests.
- No head-to-head Spanish comparison with our earlier Pocket TTS Spanish fine-tune: no same text, no shared checker, no listening. The only contrast is speed, on different hardware: that fine-tune ran at 1.05x real time on a desktop CPU, Ming at 0.61 to 0.77x on GPU.

Step by step with the SDK example
The SDK example is commit b038dd7529651076b5055604584c1fd1b51f517c on inferencekey-sdk main: backend.py, publish.py, main.py, requirements.txt, README.md, .env.example, .gitignore.
You need an SDK token (ik_sdk_), an API key (ik_live_), a project slug and a registered NVIDIA worker (IK_WORKER_ID) with a driver for CUDA 12.4 or newer and about 3 GB of free VRAM. INFERENCEKEY_TENANT_ID and INFERENCEKEY_USER_TOKEN are optional. Without them, upload dist/*.tar.gz from Dashboard, Custom backends, and turn on Chat in the workload's endpoint settings by hand.
cp .env.example .env # fill in real values
python -m venv .venv && . .venv/bin/activate
pip install maturin requests
( cd ../../bindings/python && maturin develop --release )
python publish.py # once: packages backend.py and uploads it
python main.py # ensure -> wait until ready -> 4 WAV files in ./outputs
main.py deploys the workload (ensure(), policy fixed, one replica), turns on the chat route, waits until ready, writes four WAVs and deletes the workload on exit (IK_KEEP_ALIVE=1 keeps it). Our run with IK_KEEP_ALIVE=1:
| Output | Audio | GPU time | x real time |
|---|---|---|---|
| 1-built-in-voice (UK_George) | 5.3 s | 7.899 s | 0.67 |
| 2-voice-design (narrator) | 4.2 s | 6.12 s | 0.69 |
3-clone-with-tags ([Laughter], [Sigh]) | 6.0 s | 9.124 s | 0.66 |
| 4-clone-spanish | 4.3 s | 7.201 s | 0.60 |
Peak VRAM 2,912 to 2,926 MiB. Ready after 60.3 s.
Request shape. The text is the last user message, a reference goes as an input_audio part, and options go in extra_body (task, language_id, style, instruction, voice, prompt_text, seed, cfg, sigma). The reply's message content is a JSON string with audio_b64 (16-bit WAV, 44.1 kHz), seconds, task and timings (gpu_s, total_s, realtime_factor, peak_vram_mib). Limits: 600 characters of text and 30 s of reference per request.
import base64, json, os, requests
base = os.environ.get("INFERENCEKEY_BASE_URL", "https://cloud.inferencekey.com").rstrip("/")
project = os.environ["INFERENCEKEY_PROJECT"]
api_key = os.environ["INFERENCEKEY_API_KEY"]
slug = os.environ.get("MING_WORKLOAD_SLUG", "ming-tts")
ref_b64 = base64.b64encode(open("reference.wav", "rb").read()).decode()
REFERENCE_TRANSCRIPT = "Thanks for calling the support line. I can help you reset your password in just a minute."
body = {
"model": "default",
"messages": [{"role": "user", "content": [
{"type": "text", "text": "[Laughter] I did not expect that at all. [Sigh] Well, let's try one more time."},
{"type": "input_audio", "input_audio": {"data": ref_b64, "format": "wav"}},
]}],
"extra_body": {"task": "TTS", "prompt_text": REFERENCE_TRANSCRIPT, "language_id": "en", "seed": 1895},
}
r = requests.post(f"{base}/endpoint/{project}/{slug}/v1/chat/completions",
headers={"Authorization": f"Bearer {api_key}"}, json=body, timeout=600)
out = json.loads(r.json()["choices"][0]["message"]["content"]) # IK-531 workaround
open("clone.wav", "wb").write(base64.b64decode(out["audio_b64"]))
For Spanish, German, French, Korean or Japanese use "task": "MULTILINGUAL" with "language_id": "es" (and so on). For a designed voice use "task": "VOICE_DESIGN" with "style". For a built-in voice use "task": "IP" with "voice": "UK_George".
Problems
- Slower than real time on both cards (0.61 to 0.77x), with the GPU 14 to 31% busy. The authors' Python step loop sets the pace. vLLM-Omni support is marked done in their roadmap. We did not try that route.
- Numbers: English hyphenated number words get a pause and phone numbers become subtractions. Spanish numbers skip the normalizer and come out garbled. Status: upstream behaviour, open. Check numbers in the output.
- Chinese voice-design example hit the decode limit once: 49.8 s for 5 s of audio. Not seen in English or Spanish.
/v1/audio/speechcannot carry a custom backend's output: the example uses the chat route andjson.loadsof the message content. Open, IK-531.- Backend upload refused on our dev machine (
XMinioStorageFull, disk about 99% full). Fixed for the run by freeing our own files. A test-environment issue, not one you will see. - RTX 3080 Ti machines without direct SSH (twice): the worker could not be installed and the manager terminated each after 180 s.
- Cosmetic: the panel showed an Access "No access" badge while a wildcard key worked.
- Upstream load warnings, with correct output:
You are using a model of type dense to instantiate a model of type bailingmm,Sliding Window Attention is enabled but not implemented for sdpa, and a transformerspast_key_valuesdeprecation.
Remaining samples
- Spanish paragraph, cloned voice, 52 words (18.6 s)
- Built-in voice UK_George (5.3 s)
- Designed voice: a young girl (3.5 s)
- Designed voice: a calm narrator (4.2 s)
- Free-form direction: "Whisper, tense and frightened" (3.0 s)
Demo video
A 191-second walkthrough: the authors' own demo clips (credited to inclusionAI, Ant Group), their benchmarks, our test as questions and answers, and which GPU. English subtitles.
Sources
- Model card: https://huggingface.co/inclusionAI/Ming-3.0-tts-0.5B (HF API fetched 2026-10-28)
- Code: https://github.com/inclusionAI/Ming-3.0-tts at commit
9332fb94, includingrequirements.txt,ming_tts.py,modeling_bailingmm.py,fm/flowloss.py,cookbooks/instruction_en.md - Authors' benchmarks and leaderboard claims: https://github.com/inclusionAI/Ming-3.0-tts#performance
- Where we spotted it: AI Search news video of 2026-10-25, chapter at 13:33, https://www.youtube.com/watch?v=EfyQOAJjx1A
- Our SDK example: https://github.com/inferencekey/inferencekey-sdk/tree/main/examples/ming-3-tts-05b-speech-custom-backend-private-nvidia
- Our measurements: deploy test of 2026-10-28 (bench, ladder and 4090 logs, per-case summaries, Whisper and speaker-similarity results, nvidia-smi samples)
