Home/Writing/Build note

Dubbing Arabic without drifting off the speaker

The obvious way to dub a lecture is to translate it, voice it and join the clips. In Arabic, that slowly pulls the voice away from the face.

Saad Al-TamariFrom the work: Dubljly · 20262 min read
Arabic AISpeechProduct

Dubljly turns an English lecture, from a YouTube link or an upload, into Arabic: a synced voice-over, Arabic and English subtitles, a study pack, and a tutor that knows the lecture. I built it solo, as one FastAPI service with a React front end and no extra infrastructure.

Fetchyt-dlp
TranscribeWhisper
Segmenttimed chunks
Study packshown first
TranslateArabic
Voiceone clip per segment
Mixover the original
The seven-step pipeline, run by a single background worker

Why joining clips drifts

Arabic often takes longer to say than the English it translates. Join the voiced clips end to end and every sentence that runs a little long pushes the next one later. A few minutes in, the narrator is describing a slide that has already gone.

English original
1234
Joined end to end
1234 late
Placed at each start
1234
0:000:100:200:300:40
Joined clips drift later with every sentence; placed clips start with the speaker. Clip 3 ran long and was fitted to its slot

Place every clip on the original timeline

Each transcript segment keeps its original start time. Its Arabic clip is placed at that start, never after the previous clip. When a clip is longer than its slot, a fit ladder shortens or speeds it up until it fits, so the voice stays with the speaker for the whole lecture.

Learning starts before the dub finishes

The study pack (summary, key terms and their Arabic meanings) is built before anything is translated or voiced. The target is a study pack in about 30 to 40 seconds and a full dub in about 2 to 3 minutes for a 10-minute lecture. Those are spec targets, not measured figures.

Swappable providers, validated output

Speech-to-text, language models and voice each sit behind an adapter, so the pipeline never imports a vendor SDK. Structured calls ask for JSON and validate it with Pydantic: invalid output gets one retry with the error attached, then the router moves to the next provider.

The hard part of Arabic dubbing isn’t translation. It is time.

Read the full Dubljly case study.

Read next · Field guideRAG past the tutorial: where retrieval quietly breaks
Contact

Let's build

Building something like this, or want me to write about your problem next? One email is enough to start.