By Hakim Team6 min read

Clicks, creeping loudness and cut-off endings: cleaning up realtime Arabic speech

What made long realtime TTS sessions sound wrong, how we measured it on real sessions, and the fixes now live for every voice.

EngineeringModels

A voice that sounds great in a ten-second demo can still sound wrong forty turns into a customer call. Over the last few months we traced what teams running Hakim in production told us to four problems, measured each one on real sessions, and fixed them. This post walks through what we found.

Measure sessions, not samples

The first lesson was about method. Single-utterance tests looked clean. The problems only appeared across a session: dozens of short utterances generated back to back, often from text arriving in chunks from a language model.

So we started recording the delivered level of every realtime utterance (average level, peak, and clipped samples) and the shape of its last few hundred milliseconds. That gave us numbers to check every fix against, instead of relying on listening tests alone.

1. Clicks between chunks

Streamed audio is produced in pieces. When each piece was resampled on its own, the edges did not line up exactly, and listeners heard a faint click every few hundred milliseconds.

The fix was to carry the resampling state across the whole stream, so pieces join without a seam. We also found isolated single-sample ticks inside pauses, and those are now removed. While we were there, MP3 output started choosing its bitrate from the sample rate you request instead of one fixed value.

2. Loudness that creeps up

In a long session each utterance continues from the one before it, which keeps a voice consistent. Left unchecked, small errors compound, and late in a call the level can climb until it clips.

We now cut that chain short as soon as the level starts running hot, and never continue from a hot utterance. A second cause was the reference audio: a voice's output loudness tends to follow the loudness of the clip it was registered from, so hot reference clips are now levelled at registration.

For clients that send many small chunks, the chunk_chain: false session option generates every utterance from the voice's own reference. It trades a little continuity for steadier delivery over very long sessions.

3. Endings that sound cut off

Listeners are very sensitive to the last syllable. Some utterances stopped while the voice was still at full level, which sounds like a dropped connection.

Two changes fixed most of it. Text now always ends on sentence punctuation, so the voice closes the phrase naturally. And the final fade adapts to how loud the voice still is, with enough audio held back to finish it smoothly. We deliberately do not fade in the middle of speech: that only swaps one artifact for another.

4. Gaps between chunks

When text arrives sentence by sentence, the default 100 ms of silence after each utterance adds up to audible gaps. The trailing_silence_ms session option now takes any value from 0 to 500. Set 0 and chunks join without a pause.

What it adds up to

The fixes are live for every voice, preset and cloned, with no change needed on your side. The two session options are opt-in and documented in the streaming guide. If something still sounds off to you, send a sample to support@tryhakim.ai and we will check it against the same numbers.

Read next