music-video-1-0
Music Video 1.0 — turn a song into a music video. Pass an audio track and 1-7 reference images; the API returns a video synced to the song. Five aspect ratios, up to 1080P, optional burned-in subtitles, billed per second of the song.
Music Video 1.0 turns a song into a music video. Pass an audio track plus 1-7 reference images (the visual style/model) and the API returns a video synced to the song. One async endpoint, five aspect ratios, up to 1080P, optional burned-in subtitles. Billing is per second of the song's server-probed length. See current pricing on the model page.
Quick example
curl https://reapi.ai/api/v1/videos/generations \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "music-video-1-0",
"reference_image_urls": ["https://your-cdn.com/style.png"],
"audio_url": "https://your-cdn.com/song.mp3",
"aspect_ratio": "16:9",
"resolution": "540P"
}'import requests
resp = requests.post(
"https://reapi.ai/api/v1/videos/generations",
headers={
"Authorization": "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
json={
"model": "music-video-1-0",
"reference_image_urls": ["https://your-cdn.com/style.png"],
"audio_url": "https://your-cdn.com/song.mp3",
"aspect_ratio": "16:9",
"resolution": "540P",
},
timeout=30,
)
print(resp.json())const r = await fetch("https://reapi.ai/api/v1/videos/generations", {
method: "POST",
headers: {
Authorization: "Bearer YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "music-video-1-0",
reference_image_urls: ["https://your-cdn.com/style.png"],
audio_url: "https://your-cdn.com/song.mp3",
aspect_ratio: "16:9",
resolution: "540P",
}),
});
console.log(await r.json());package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
body, _ := json.Marshal(map[string]any{
"model": "music-video-1-0",
"reference_image_urls": []string{"https://your-cdn.com/style.png"},
"audio_url": "https://your-cdn.com/song.mp3",
"aspect_ratio": "16:9",
"resolution": "540P",
})
req, _ := http.NewRequest("POST",
"https://reapi.ai/api/v1/videos/generations", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}Submit response
{
"id": "task_018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e",
"model": "music-video-1-0",
"status": "processing",
"created_at": 1735000000
}Poll GET /api/v1/tasks/{id} (see the Tasks reference) until
status === "completed". The completed payload's output.video_urls holds the
generated MP4 URL.
Authentication
Every call needs a Bearer token. Generate keys at reapi.ai/settings/apikeys.
Authorization: Bearer YOUR_API_KEYEndpoint
POST /api/v1/videos/generations
GET /api/v1/tasks/{id}Submission is async. The POST returns immediately with a task_id; the task
endpoint returns the same envelope until completion. Polling does not consume
credits.
Request body
model — required
string. Must be "music-video-1-0".
reference_image_urls — required
string[]. 1 to 7 public HTTP(S) image URLs (JPEG / PNG / WebP). These are
the style / model references that fix the visual identity of the music video.
No data: URIs. reApi rejects base64 inputs platform-wide. Upload to public
storage (your own CDN, S3, R2…) and pass the URL.
audio_url — required
string. Public HTTP(S) URL of the song (MP3). The audio must be 10 to
300 seconds (up to 5 minutes). The output music video length tracks the song,
and the billable second count is the song's server-probed duration, not a
client estimate.
aspect_ratio — string, default "16:9"
Output frame shape.
| Value | Orientation |
|---|---|
"1:1" | Square |
"16:9" | Landscape (default) |
"9:16" | Portrait |
"4:3" | Landscape |
"3:4" | Portrait |
resolution — string, default "540P"
Output clarity. Higher resolutions take longer to render.
| Value | Notes |
|---|---|
"540P" | Fastest (default) |
"720P" | Balanced |
"1080P" | Highest clarity |
name — string, optional
A label for the track. Shown on subtitles when add_subtitle is enabled.
prompt — string, optional
Up to 3000 characters. Steers the visual style, mood, and scene direction of the music video.
add_subtitle — boolean, default false
Burn lyric subtitles into the music video. With add_subtitle: true and no
srt_url, subtitles are generated from the song.
subtitle_color — string, default "#FFFFFF"
Hex color for burned-in subtitles (e.g. "#FF0000").
srt_url — string, optional
Public HTTP(S) URL of a .srt subtitle file. Overrides auto-generated
subtitles when add_subtitle is on.
Response envelope
Submit and poll share the same shape — only status and output fill in over
time.
{
"id": "task_018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e",
"model": "music-video-1-0",
"status": "completed",
"created_at": 1735000000,
"output": {
"video_urls": ["https://cdn.reapi.ai/media/tasks/018f5a3a1b6e7d9f8c2b4d6e8f0a2c4e/0.mp4"]
},
"error": null
}| Field | Type | Notes |
|---|---|---|
id | string | Task identifier — keep it for polling and audit |
model | string | Echo of the submitted model |
status | string | processing / completed / failed |
created_at | integer | Submission unix timestamp |
output | object | null | null until completion. output.video_urls holds the MP4 |
error | object | null | Populated on failed — { code, message } |
Pricing
Flat per second of the song. The billable second count is the audio's server-probed length — reApi measures the uploaded track server-side rather than trusting a client value.
Bill formula (1 credit = $0.001):
billable_seconds = min(ceil(server_probed_song_seconds), 300)
bill_usd = per_second_usd × billable_seconds
credits = ceil(bill_usd × 1000)See the current per-second rate on the
model page. Failed jobs refund
automatically. A probe failure returns 400 PRICING_UNAVAILABLE (code 30002)
with no charge.
The playground's draft estimate may show a default before the upload finishes — the authoritative number is computed at submit, after the server probes the song.
Validation errors
All cases below return HTTP 400. Pattern-match on code, not message —
message strings carry request-specific context and are not a stable contract.
| Trigger | Code | Message (illustrative) |
|---|---|---|
reference_image_urls missing / empty | 20002 | reference_image_urls is required |
| More than 7 reference images | 20003 | reference_image_urls accepts at most 7 items |
audio_url missing | 20002 | audio_url is required |
aspect_ratio / resolution invalid | 20003 | invalid aspect_ratio (allowed: 1:1 / 16:9 / 9:16 / 4:3 / 3:4) |
subtitle_color not a hex color | 20003 | subtitle_color must be a hex color like #FFFFFF |
Any media field carrying a data: URI | 20003 | audio_url must be a public http(s) URL |
| Song probe fails (network / format) | 30002 | Could not determine source audio duration for billing: … |
| Song length outside the 10-300s window | 80007 | Provider rejected the request as invalid |
The full envelope is { "error": { "code", "message", "request_id" } } — see
Errors catalog for the wire format and request_id
correlation tips.
Recipes
Minimum request
{
"model": "music-video-1-0",
"reference_image_urls": ["https://your-cdn.com/style.png"],
"audio_url": "https://your-cdn.com/song.mp3",
"aspect_ratio": "16:9",
"resolution": "540P"
}Portrait lyric video, 1080P, with subtitles
{
"model": "music-video-1-0",
"reference_image_urls": [
"https://your-cdn.com/style-1.png",
"https://your-cdn.com/style-2.png"
],
"audio_url": "https://your-cdn.com/song.mp3",
"aspect_ratio": "9:16",
"resolution": "1080P",
"prompt": "Dreamy pastel anime style, soft lighting, visuals shift with each chorus",
"add_subtitle": true,
"subtitle_color": "#FFE0F0"
}Bring your own subtitle file
{
"model": "music-video-1-0",
"reference_image_urls": ["https://your-cdn.com/style.png"],
"audio_url": "https://your-cdn.com/song.mp3",
"aspect_ratio": "16:9",
"resolution": "720P",
"add_subtitle": true,
"srt_url": "https://your-cdn.com/lyrics.srt"
}Tips
- Cost tracks the song. A 90-second track bills ~90 seconds; trim the audio to control spend. Songs must be 10 to 300 seconds.
- Use reference images to lock the look. Pass 1-7 style/model images; reuse the same set across tracks for a consistent channel aesthetic.
- Prompt the mood, not just the scene. Phrasing the energy ("dynamic lights pulsing on the downbeat") sharpens the result.
- Subtitles, three ways. Leave
add_subtitleoff for a clean cut, on for auto-generated lyrics, or supply your ownsrt_urlfor exact timing. - Start at 540P. Validate the look on the fastest tier, then re-run at 720P / 1080P for the final take.