Loading...
Loading...
Dub a video into one or more other languages using Sonilo, translating and re-voicing the speech into a new video per language. Use when a user needs a video localized into another language, not just subtitled. Billed per language with zero free trial — confirm language count with the user before calling.
npx skill4agent add sonilo-ai/skills auto-dubbing.mp4Setup: See the setup-api-key skill.
⚠️ Cost — read before calling: this is billed per language, with zero free-trial runs — even a trial account is charged from the very first call, unlike every other Sonilo tool. Requesting four languages costs four times as much as one. Confirm the exact language list with the user before calling; do not guess a long list "to be helpful."
⏱ This call is slow. It polls for at least two hours internally regardless of any shorter— that's the backend's own ceiling for the dubbing pipeline. A call that sits for an hour or more is normal, not a hang. Do not cancel it: the job keeps running and charging either way, and cancelling just loses the easy path to the result (useTIME_OUT_SECONDS, orget_sfx_taskon the hosted server, to recover it instead).get_generation_task
dubbingsonilo accountsonilo accountsonilo whoamiapi.sonilo.com⏱ On the CLI path this call cannot be one command. The backend polls for up to two hours, while a host's shell tool is capped far below that (ten minutes in Claude Code), sorun in the foreground will be killed with the job still running and already charged. Submit it and poll separately instead:sonilo dubbingbash# --timeout is the CLI's own wait, not the job's: this returns before a host # shell can kill the process. The id comes from the "Submitted task ..." line. sonilo dubbing --video-url https://example.com/clip.mp4 --languages es,fr --timeout 300 sonilo tasks wait <task-id> # repeat until it finishesThe MCP path has no such limit and is the better transport for dubbing.
dubbing(
video_path="~/Desktop/product-demo.mp4",
languages=["es", "fr"]
)pip install sonilofrom sonilo import Sonilo
with Sonilo() as client: # reads SONILO_API_KEY
result = client.dubbing.generate(
video="product-demo.mp4",
languages=["es", "fr"],
timeout=7200, # seconds — matches the backend's own ~2h ceiling
)
for language, path in result.save_all("./dubbed").items():
print(language, path)npm install soniloimport { SoniloClient } from "sonilo";
import type { DubbingResult } from "sonilo";
const client = new SoniloClient(); // reads SONILO_API_KEY
const result = await client.dubbing.generate(
{ video: "./product-demo.mp4", languages: ["es", "fr"] },
{ timeout: 7_200_000 }, // milliseconds — matches the backend's own ~2h ceiling
);
for (const [language, url] of Object.entries((result as DubbingResult).outputs ?? {})) {
console.log(language, url);
}npm install -g sonilo-clipip install sonilo-clisonilo dubbing --video-url https://example.com/product-demo.mp4 --languages es,fr --output dubbed.mp4
# writes dubbed.es.mp4 and dubbed.fr.mp4--timeoutcurl -X POST "https://api.sonilo.com/v1/dubbing" \
-H "Authorization: Bearer $SONILO_API_KEY" \
-F "video=@product-demo.mp4" \
-F 'languages=["es","fr"]'
# -> {"task_id": "..."} poll GET /v1/tasks/{task_id} — can take up to ~2 hoursvideo_url| Tool | Description |
|---|---|
| Dub a video into each requested language; one |
| Parameter | Type | Default | Notes |
|---|---|---|---|
| string | — | |
| string | — | Must be https (not just http). Exactly one of |
| list[str] | | Target language codes. Supported: |
| string | | Absolute, or relative to the base path. |
["zh_cn", "es", "fr"]trial_exhaustedget_account_servicestask_idget_sfx_task(task_id)get_generation_task(task_id).mp4dubbing-<first 8 chars of the task id>.<language>.mp4401402413422429