Video to Video (Music)
For AI agents →1 call free, no credit card required.
Generate a music-scored version of a video, muxed with the original picture and delivered as a new video file. Returns 202 Accepted with a task_id; poll GET /v1/tasks/:task_id until the task reaches a terminal status. Generated audio carries an inaudible provenance watermark.
- Default: the returned video's audio is the generated music alone; the source audio is removed entirely.
- Pass
keep_original_sound=trueto keep the whole source track instead — mixed with the music statically by default, or ducked under it withducking=true. preserve_speech=truekeeps only the isolated speech rather than the whole track, but is ignored wheneverkeep_original_soundis also set.
For a walkthrough that sends a video file or a public video URL, read the guide to generating music from a video file or URL with the REST API.
POST
/v1/video-to-video-musicmultipart/form-dataAPI URL
https://api.sonilo.com/v1/video-to-video-musicSend API requests to https://api.sonilo.com. The platform.sonilo.com/docs pages are documentation only and are not API endpoints.
curl -X POST https://api.sonilo.com/v1/video-to-video-music \
-H "Authorization: Bearer sk_your_api_key" \
-F "video_url=https://example.com/clip.mp4" \
-F "prompt=uplifting orchestral score"
# => {"task_id": "9f5f2f7e-...", "status": "processing"}
curl https://api.sonilo.com/v1/tasks/9f5f2f7e-... \
-H "Authorization: Bearer sk_your_api_key"
# poll until "status" is "succeeded" or "failed"curl -X POST https://api.sonilo.com/v1/video-to-video-music \
-H "Authorization: Bearer sk_your_api_key" \
-F "video_url=https://example.com/clip.mp4" \
-F "preserve_speech=true"{
"task_id": "9f5f2f7e-…",
"status": "processing"
}Authorization
Authenticate via Bearer token. Generate keys at the API Keys page and pass them in the Authorization header on every request. Keep keys server-side, for example in SONILO_API_KEY.
Authorization: Bearer sk_your_api_keyStore the key server-side, commonly as SONILO_API_KEY. A 401 means the key is missing, invalid, or revoked. A 403 means the key is valid but the account does not have access to that endpoint or workspace.
Body Parameters
videofileVideo file upload. Provide either
video or video_url, not both. Accepted formats: mp4, mov, m4v, or webm carrying H.264, H.265/HEVC, VP9, or AV1 video. The source picture is copied into the result without re-encoding, so animated gif and VP8 webm are not supported by this endpoint. Max file size: default 300MB. Max duration: 360 sec.video_urlstringURL to a video file. Provide either
video or video_url, not both. Must be a public http:// or https:// URL; private/internal addresses are rejected. The video is downloaded before generation starts, so the same accepted formats, 300MB size limit, and 360 sec duration limit apply.promptstringOptional text prompt describing the music to generate, up to 2000 characters. For best results, omit this and let the model infer a soundtrack from the on-screen action and visuals.
segmentsstringOptional JSON array of timed segment prompts; the music changes style at each boundary. Each item has
start (seconds; the first must be 0, starts strictly increasing and at least 5 seconds apart, the last at least 5 seconds before the end of the video), prompt (1-200 characters), and an optional label that must be exactly one of these values — any other value is rejected with a 422 error, and it defaults to none when omitted: intro, verse, pre-chorus, chorus, bridge, break, silence, outro, none. 1-30 items.preserve_speechbooleanOptional boolean, default
false. When true, the model isolates the source speech and composes the new soundtrack around it; the returned video's audio then carries the isolated vocals as the voice source — mixed statically with the music by default, or ducked under it with ducking=true — instead of being silent. Superseded by keep_original_sound: when that is also true, the whole original track is kept as the voice source instead of just the isolated speech. No additional charge.keep_original_soundbooleanOptional boolean, default
false. When true, keeps the whole source video's audio track as the voice source, instead of the isolated vocals (preserve_speech) or no voice source at all. By default (false), the returned video's audio is the generated music alone, with the source's own audio removed. Supersedes preserve_speech when both are set. No additional charge.duckingbooleanOptional boolean, default
false. Selects how the voice source combines with the generated music in the returned video's audio: by default it is a static vocal-forward mix; pass ducking=true to duck it dynamically under the music instead, so dialogue stays intelligible — free either way. The voice source is the whole original track when keep_original_sound is set, the isolated vocals when only preserve_speech is set, or nothing at all when neither is set, in which case ducking has no effect and the returned audio is the generated music alone. Best-effort: if voice isolation or the duck/mix pass fails, this silently degrades to music-only audio rather than failing the request.variants_numintegerOptional. How many distinct scored videos to generate in one request, 1-10 (default
1). Each variant scores the same source video with a different musical direction, returned as its own entry in videos. Cost scales linearly — variants_num=3 costs three times a single-variant request. Values above 1 are never covered by the free trial and are always billed.prompt_influencenumberOptional number, 0 to 1 (default
0.5). How strongly the generated music follows your prompt: lower values let the video lead, higher values follow the prompt more literally. Free of charge.Response
task_idstringThe task identifier. Poll the Get Task endpoint (GET /v1/tasks/:task_id) until the task reaches a terminal status.
statusstringAlways processing on submission — generation runs asynchronously.
curl -X POST https://api.sonilo.com/v1/video-to-video-music \
-H "Authorization: Bearer sk_your_api_key" \
-F "video_url=https://example.com/clip.mp4" \
-F "prompt=uplifting orchestral score"
# => {"task_id": "9f5f2f7e-...", "status": "processing"}
curl https://api.sonilo.com/v1/tasks/9f5f2f7e-... \
-H "Authorization: Bearer sk_your_api_key"
# poll until "status" is "succeeded" or "failed"curl -X POST https://api.sonilo.com/v1/video-to-video-music \
-H "Authorization: Bearer sk_your_api_key" \
-F "video_url=https://example.com/clip.mp4" \
-F "preserve_speech=true"{
"task_id": "9f5f2f7e-…",
"status": "processing"
}