2026-11-02 · 4 min read
Captions for Translated and Dubbed Videos
Dubbing a video into a new language is only half the job. Viewers watching muted, hard of hearing viewers, and viewers in noisy places all rely on captions even when the audio is in their language. If your localization pipeline stops at the dub, the last accessibility step is still missing.
Because the caption.sh API works from the rendered video itself, it slots in after your dubbing step: dub the video, host the result, then submit the dubbed file for captioning like any other clip.
Submit a dubbed video
curl -X POST https://api.caption.sh/v1/videos \
-H "Authorization: Bearer $CAPTION_API_KEY" \
-H "Content-Type: application/json" \
-d '{"source_url": "https://example.com/interview-es.mp4", "options": {"font": "inter"}}'
# response
# {"job_id": "job_8f3k..."}Poll for the finished render
Rendering is asynchronous, so the submit response is a job id. Poll the job endpoint until it reports done or error, with your own timeout as the third exit.
curl https://api.caption.sh/v1/jobs/job_8f3k... \
-H "Authorization: Bearer $CAPTION_API_KEY"
# poll every few seconds until status is done or error
# {"job_id": "job_8f3k...", "status": "done", ...}What to know before you batch
- Submissions are rate limited per API key. A 429 response means wait a moment and retry, it does not mean the job failed.
- Rendering is prepaid at $0.10 per minute of video. A 402 response means the balance is empty, so top up before retrying.
- Every render needs a bounded poll loop with three exits: done, error, and your own timeout. Do not poll forever.
- The API documents no webhook surface, so polling is the intended way to learn a job finished.
Run a small batch first and check the caption timing on your longest dub. Once the output looks right, the same two calls scale to every language version you produce.