Dub 40 nine-minute course lessons into Spanish: up to $54.94
Dubbing 40 nine-minute lessons into Spanish costs up to $54.94 on Sume: about $1.37 a lesson, with the timeline render at $0.90 as the largest line.

Dubbing 40 nine-minute course lessons into Spanish costs up to $54.94 on Sume, about $1.37 per lesson, at list rates. The render is the biggest line at $0.90 a lesson, and Index-Translate's listed free API handles the translation.
Assumptions: 9 minutes per lesson, 850 characters per minute of speech so 7,650 characters per lesson, and one language. Speech-to-text takes up to 10 minutes of audio per request, so a nine-minute lesson is one request. Rates are from the pricing page, Audio detach docs and Timeline docs, read 2026-10-05.
One lesson, then the course
Each step is captured at its own compute and never above the reservation, so these are ceilings.
| Step | Per lesson | For 40 lessons |
|---|---|---|
| Detach the audio | $0.01 | $0.40 |
| Speech-to-text, 9 minutes | $0.09 | $3.60 |
| Sume TTS, 7,650 characters | $0.3634 | $14.54 |
| Concat speech for its length | $0.01 | $0.40 |
| Timeline render, 9 minutes | $0.90 | $36.00 |
| Total, up to | $1.373 | $54.94 |
Plan the run
Use the lesson number and language in every idempotency key, such as course-l07-es-render, so a rerun reuses finished work. Slides that change between languages may need a new video track, which this bill does not include.
- Source video must be on
media.sume.com; import it first. - Detach takes up to 1,800 seconds of source, so lessons longer than 30 minutes need splitting first.
- Keep each Spanish spine near the lesson length: a spine that speaks past 9:00 adds a billable minute.
Render one lesson
This joins the speech for one lesson for its duration and renders it under the lesson video.
import os, time, requests
API = "https://api.sume.com"
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
def run(path, body, key):
r = requests.post(API + path, headers={**H, "Idempotency-Key": key}, json=body, timeout=60)
r.raise_for_status()
job = r.json()["data"]
while not requests.get(job["status_url"], headers=H, timeout=30).json()["data"]["terminal"]:
time.sleep(2)
res = requests.get(job["result_url"], headers=H, timeout=30)
res.raise_for_status()
return res.json()["data"]["result"]
VIDEO, SPEECH = os.environ["VIDEO_URL"], os.environ["SPEECH_URL"] # both on media.sume.com
joined = run("/v1/timeline-1.0/audio", {"operation": "concat", "parts": [{"url": SPEECH}]}, "dub-0412-de-spine")
secs = joined["duration_seconds"]
body = {"audio": {"url": joined["audio_url"], "duration_seconds": secs},
"video": [{"source_url": VIDEO, "start": 0, "duration": secs}]}
out = run("/v1/timeline-1.0/render", body, "dub-0412-de-render")
print(out["video_url"])
Sources
Related posts
More in Use cases
- Dub a 3-minute explainer into 4 languages: $0.43 per language
One 3-minute explainer dubbed into four languages costs up to $1.76 on Sume: $0.04 once to transcribe, then about $0.43 per language to speak and render.
- Dub a 45-second ad into Spanish and German: which steps Sume covers
Detach, transcribe, speak, join and caption are Sume jobs worth about 70 cents for two languages. Translation is not on the pages we read; bring your own.
- Dub a 60-second promo into German: step prices, up to $0.17
A 60-second promo dubbed into German costs up to $0.17 on Sume: detach, speech-to-text, TTS for 900 characters, a concat and a one-minute timeline render.
- Dubbing a video with music: what replacing the audio track means
A dub built from STT, TTS and a timeline swaps the whole audio track. The original music goes with it unless you add a bed back. Options on Sume, step by step.
Written by Sume