Giving Writing A Voice

Cloning your own voice with Qwen3-TTS

Fifty minutes of narration in my own voice, running entirely offline. The model behaved. My microphone did not, and the reference recording needed to be twenty times shorter than I assumed.

September 2026 / Part two of three
In Plain English

Why bother with your own voice

A synthetic narration is fine. I shipped one, and most listeners would not object to it. So the honest question is what you get for the extra work.

You get a narrator who is a person. For a course or a personal essay, where part of what you are shipping is that a particular human thought this through, that is not a cosmetic difference. A synthetic voice quietly reframes the piece as content. Your own voice keeps it as something you said.

Whether that is worth an afternoon and three recording takes depends entirely on the piece. For documentation, no. For anything with your name on it as the reason to listen, probably.

What you read matters

Do not read random text. The clone learns the prosody you give it, so the passage should cover the shapes it will have to reproduce.

Mine covers long subordinate clauses, a semicolon's mid-sentence lift, a colon setting up a list, two very short declaratives for the falling cadence, digits spoken in sequence, and one real question. That last one is not decoration. Miss the question mark and every question you ever narrate comes out flat.

from the passage I read
A protocol is just an agreement about how two programs talk.

The model does not run the tool. It cannot.

Zero, one, two, three, four, five, six, seven, eight, nine.

Is it going to rain tomorrow?

About 160 words, or ninety seconds at teaching pace. Two rules for the reading itself, both of which I got wrong before I got them right.

Read at your normal speed. The clone copies your rhythm, so a carefully-slow take gives you a carefully-slow narrator for every article you ever render. And do not restart on a stumble. A fluffed word costs nothing. Three increasingly stiff takes cost you the voice, because what you end up cloning is the sound of someone concentrating on not making mistakes.

Your microphone is lying to you

I needed three sessions to get ninety usable seconds, and none of the failures were about machine learning.

Take one was on Bluetooth earbuds. When a Bluetooth device is used as a microphone the link drops to the hands-free profile, which caps the mic at 16 kHz sampling. That is an 8 kHz audio ceiling. Windows then upsamples to 48 kHz to fill the file header, so everything about the recording looks correct.

the file claims one thing, the spectrum says another
# metadata: flawless
samplerate: 48000 Hz   channels: 2   subtype: PCM_16

# actual energy by band:
   4000-8000  Hz : 26.71%
   8000-12000 Hz : 0.04%     <- nothing lives up here
  12000-16000 Hz : 0.02%

Above 8 kHz is where sibilance and consonant air live. The s, the t, the sh. A clone conditioned on band-limited audio reproduces that limitation, and you get fifty minutes of narration that sounds like a phone call.

So I switched to the laptop's built-in array microphone. Take two was worse. Same 8 kHz ceiling, because the voice DSP runs a 16 kHz capture pipeline you cannot switch off from the recorder app, and now I had also given up 23 dB of signal-to-noise and four fifths of the presence band by sitting thirty centimetres away.

Record on your phone

Any modern phone voice-memo app captures genuinely full-band audio and bypasses your laptop's audio stack entirely. Hold it a hand's width from your mouth, slightly off-axis so plosives do not hit the capsule head on. It beats both your headset and your built-in mic, and it costs nothing.

Measure the take before you trust it

Twenty lines that would have saved me two recording sessions. The last check is the one that matters, and it is the one nobody tells you to run.

where does the audio actually stop
S = np.abs(np.fft.rfft(d * np.hanning(len(d))))
f = np.fft.rfftfreq(len(d), 1/sr)
c = np.cumsum(S) / S.sum()
print(f"99.9% of energy below {f[np.searchsorted(c, 0.999)]:.0f} Hz")

You want that reading 15,000 or higher. Mine read 7,943, twice, from two different microphones, before I understood what I was looking at.

Alongside it: peak below 0.99 with zero clipped samples, and a signal-to-noise ratio above roughly 25 dB. That last one is about your room rather than your microphone. A quiet room with a phone beats a treated room with a Bluetooth headset, because one of those problems is fixable in software and the other is not.

Then throw most of it away

I recorded 85 seconds with a matching transcript, which felt like a generous conditioning signal. The model advertises cloning from three seconds, so more seemed obviously better.

It was not. It was substantially worse.

Reference length Speed Outcome
85.1 seconds 9.7x real time stalled partway through a four-second line
4.52 seconds 4.6x real time stable, and no worse to my ear

The reason is that the reference does not get consumed once and discarded. It stays in the model's working context for the whole generation. Eighty-five seconds of audio becomes roughly a thousand tokens that every subsequent word has to be computed against, before a single word of output exists.

So pick one clean, complete sentence. Cut it on silence at both ends. Save the exact transcript beside it. Four to ten seconds is the whole reference, and the quality difference against ninety seconds was not something I could hear on an A/B.

It needs the words, not just the audio

Qwen3-TTS clones in-context, so it refuses to run without a transcript of the reference. There is a mode that skips it, documented as lower quality. I take the refusal as a good sign. It is genuinely aligning text against audio rather than pulling a speaker embedding and hoping.

It speaks at a human pace

My 45.5-minute synthetic track came out at 50.3 minutes cloned. File by file, between 6% and 20% longer. Nothing was truncated. It simply speaks the way a person does, because it learned that from a person.

That is worth knowing in advance for two reasons. If your player uses a duration manifest, it needs regenerating. And if you have been tuning paragraph gaps against the synthetic version, they will feel slightly different here, because the speech around them changed length while the silence did not.

I also checked the other direction. On a single sentence the clone ran 3.84 seconds against my own 4.52, so it is not uniformly slower. It redistributes time the way I do, which is the thing you actually wanted.

Is it worth it

Honestly, only if the voice being yours is the point.

The synthetic path costs no recording and no traps worth writing about. This one cost me three recording sessions, an afternoon of debugging, and roughly twenty times the compute per render. On a modest GPU that is about three hours for a fifty-minute track.

What you get back is that it is your voice, it runs on hardware you already own, nothing is uploaded anywhere, and the weights are Apache 2.0. For a course or a personal blog, that is a different product rather than a cheaper version of the same one.

I kept both tracks in separate directories. The synthetic one still ships. Having both is the reason I get to not decide yet.