I cloned my voice so my blog could read itself
Four voices, every post, zero dollars a month. Why a lifelong text to speech user finally built narration into his own site, and the voice clone that almost fooled me.

Most things I read, I also listen to. I select the text and have macOS read it while my eyes follow along. I used to pay for Speechify. I dropped it when the built in Mac voices got good enough that I stopped noticing them.
Reading and listening at the same time puts me in a focus state that reading alone does not. Two channels, one text. It keeps me inside the sentence instead of three tabs away.
But my own blog could not do that for you. You would have to know the macOS trick exists, and most people have never heard of it. So now there is a listen button on this page. Press it and this post reads itself to you in four voices, and the one it starts with is mine. Every post here has audio, and so does every case study, once you have the password. It all renders on my own machine and costs zero dollars a month. This is the build log: what I picked, what surprised me, and the one part I refused to hand over.

The bake-off ran blind
I had my agents research text to speech models I could run locally for free, then put every candidate on a plain HTML page. One row per model, a shared player, a speed control, and a toggle that hides the model names so the pick could not be biased by reputation.

Two rules made the test honest. Every candidate read a long multi paragraph script, never a demo sentence, because one model kept turning into a different narrator a few seconds in and a one line sample would have hidden it completely. And before choosing anything I sat through a full seven minute post, start to finish, because a voice that charms you for two minutes can wear badly by minute six.
Three stock voices survived: Bella, Puck and Heart. All from the same small model, which I did not know until I unhid the names: Kokoro-82M. 82 million parameters, open weights, free.
The clone that almost fooled me
The fourth voice is mine. The reference is 39 seconds of me reading at my desk. It took two takes, because take one pronounced things I never would.
Here is the part that genuinely shocked me. One of the clone generations, from Qwen3-TTS, was so close to my real voice that if I had heard it cold, I would have been fully convinced it was a recording of me. Not impressed. Convinced.
I did not ship that one. I shipped a slightly less identical clone from Chatterbox, because it reads with more expression, and a voice can be a perfect copy and still a flat read. Realism is not the finish line. Maybe I overshot and the shipped voice is a touch too lively. I would rather err on the side of a narrator who sounds interested.
I specced the player like a human was going to build it
The player took longer than the voices, and most of that time was mine.
I first generated five complete design directions and picked one. Then I asked for revisions, got exactly what I asked for, and liked the result less with every round. The UI was getting heavy. Each revision was correct on its own and the sum was worse than the start.
So I opened Figma and drew it myself. A floating listen button that follows you down the page, opening into a single glass row.

Then I specced the frame the way I would for a human engineer: exact sizes, exact colors, red notes for behavior, both placements drawn out.

I handed all of it to Claude Code. And to keep the implementation honest, it built me a small comparison dashboard: the Figma frame on one side, the live build on the other, overlaid with a slider I can drag to see exactly where they disagree. We looped until they did not.

This is the same handoff I spent 17 years giving people, except the builder answers in minutes and never gets tired of my nitpicks. Figma stayed the design surface. The code became the print.
The detail nobody will notice
The four voices read at different speeds. The same post is seven minutes in one voice and not in another.
So the player stores your position as a fraction of the text, not as a timestamp. Switch voices halfway through a paragraph and you land on the same sentence, not the same second. Closing the bar does not stop the audio, because closing a bar is not a request for silence. Come back three days later and it remembers your place, and it does not start playing on its own. Nothing plays unless you pressed something.
Same spirit in the scrubber: the click target around the seek head is a good deal larger than the seek head you can see. Grabbing a four pixel line should not require aim.

If all of that works, you will never once think about it. That is the job.
Where this falls short
The audio goes stale the moment I edit a post. A command lists what has drifted, and it exists because I know I will forget.
Password protected posts get no audio at all, on purpose. Their narration would be an unauthenticated copy of a private text on a guessable URL.
And the clone is good, not me. It never stumbles, never speeds up when it likes its own sentence. It is a decent way to hear my writing when your eyes are busy. It is not me reading to you.
Sound on
I have wanted this feature for years, back when building it would have meant a vendor, a bill and a compromise on every one of these details. Instead I got the voices for free, drew the player myself, and had the implementation checked against my Figma frame pixel by pixel.
I have written before that the production moved to the machine and the design moved back to me. This feature is that sentence with the sound on. And I honestly cannot remember a version of this job that was more fun.
Get new posts by email
I write when there is something worth saying. One email per post, nothing else.
- ai
- design
- build
- narration
