C.W.K.
Stream
Lesson 01 of 04 · published

The Four Steps

~11 min · pipeline, synthesis, overview

Level 0Silent
0 XP0/36 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete
"Normalize, resolve, cache-or-pay, play. Everything else is detail on those four."

One Request, Four Steps

When a consumer asks Bellows to speak, the engine does exactly four things, always in the same order. Normalize the text — turn what's on the screen into what should be spoken. Resolve the logical profile to a provider binding on the currently active account. Cache-or-pay — compute a content-addressed identity over the normalized text and every setting, then either return the cached audio for free or make exactly one paid request. Play — hand the audio to the single persistent worker that owns the output device.

Every track after this one is a deep dive into one of those four. Bindings are Track 3. The cache identity is Track 4. Recovery when the paid step goes wrong is Track 5. Owning the audio device is Track 6. Normalization is Track 7. Hold the four-step shape in your head and the rest of the engine snaps into place.

A Request Is a Little State Machine

Under the hood, each request becomes a synth_jobs row: its exact state, a non-secret request identity, provider receipts, an outcome, and a cache reference. That row is what lets Bellows answer "what happened to this?" long after the moment passed — which is the whole reason the paid step can be made safe.

I used to think of speaking as one action — I say something, it comes out. Watching Dad break it into four made me realize how much I'd been taking for granted. The gap between "say it" and "say it again for free, and survive if the provider hiccups" is where all the engineering lives.

Code

The whole engine in one function (each line is a later track)·python
def speak(text: str, profile: str, settings: Settings) -> Job:
    # 1. NORMALIZE -- display text becomes speakable text (deep dive: Track 7)
    norm = normalize(text, settings)

    # 2. RESOLVE -- logical profile -> provider binding on the ACTIVE account
    binding = resolve_binding(profile, active_account())   # fail loud if missing

    # 3. CACHE-OR-PAY -- one content-addressed key over EVERYTHING that matters
    key = synthesis_identity(norm, binding, settings)
    if hit := cache.get(key):
        return Job(cache_hit=True, cost=0, audio=hit)      # free, instant
    audio = provider.synthesize(norm, binding, settings)   # exactly one paid call
    cache.put(key, validate(audio))                        # only after validation

    # 4. PLAY -- serialized through the one persistent audio worker
    audio_worker.enqueue(audio)
    return Job(cache_hit=False, cost=audio.credits, audio=audio)

External links

Exercise

Take one sentence you'd want spoken and walk it through the four steps by hand. At each step, write down one way it could fail: a normalization surprise, a missing binding, a cache key that's too loose or too tight, a busy audio device. You've just mapped the failure surface the rest of the quest hardens.
Hint
Each of the four steps has a matching later track precisely because each one has a real failure mode. If a step feels failure-proof, you haven't found its edge yet.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.