Create a music video from a song
November 10, 2026
Table of contents
Use a pixverse.ai account to turn a song into a finished music video, the same as PixVerse’s One-Click MV. Upload the song (10 seconds to 6 minutes), optionally add a character photo, pick a mode and a visual style, and PixVerse plans the shots, generates them and cuts them to the beat. In performance mode the character lip-syncs the vocals. With subtitles: true it also burns the lyrics in as captions.
Generation is asynchronous. The call returns a video_id right away, then poll GET music-video/video_id until status is succeeded or failed, or pass a replyUrl to get the result by callback. A 30-second song took about 5 minutes in our tests, a 2½-minute song at 1080p about 16 minutes.
Step-by-step example with a full song: How to Make an AI Music Video from a Song with the PixVerse API.
The music video is an ordinary PixVerse video as well: the same video_id works with GET videos/video_id, shows up in GET videos and is deleted with DEL videos/video_id.
Modes
| Mode | What you get |
|---|---|
performance (default) | the character sings the song with lip-sync, made for singer and dancer performance videos |
expressive | emotional, atmospheric shots of the character |
storytelling | a storyline that follows your prompt, with one or two characters, made by PixVerse’s partner engine |
Prices
One minute of song costs (PixVerse bills every second, rounded to the nearest second):
| Mode and quality | Official API | Premium $60/mo 15,000 cr/mo | Pro $30/mo 6,000 cr/mo | Ultra $199/mo 25,000 cr/mo |
|---|---|---|---|---|
performance or expressive, 720p | $4.00 15 cr/s | $2.40 10 cr/s | $3.00 10 cr/s | $4.78 10 cr/s |
performance or expressive, 1080p | $6.00 22.5 cr/s | $3.60 15 cr/s | $4.50 15 cr/s | $7.16 15 cr/s |
storytelling, 720p | not sold | $4.80 20 cr/s | $6.00 20 cr/s | $9.55 20 cr/s |
storytelling, 1080p | not sold | $9.60 40 cr/s | $12.00 40 cr/s | $19.10 40 cr/s |
The first music video on every PixVerse account is free, at any length and in 1080p, even on a free Basic plan. Prices as of November 2026.
While an account’s free music video is unused, the quote shows cost_credits: 0 and free: true.
https://api.useapi.net/v2/pixverse/music-video/create
Request Headers
Authorization: Bearer {API token}
Content-Type: application/json
# Alternatively you can use multipart/form-data
# Content-Type: multipart/form-data
API tokenis required, see Setup useapi.net for details.
Request Body
{
"email": "Optional PixVerse API account email",
"audio_path": "upload/8aa34c5f-7f33-4fdc-af40-7357909102cb.mp3",
"mode": "performance",
"style": "auto",
"image_path": "upload/66952750-badc-473b-b2a2-721197e96e7d.jpeg",
"music_genre": "hip_hop",
"subtitles": true,
"lyrics": "That bassline hits me hard right now\nWe turn it up and show them how",
"aspect_ratio": "16:9",
"quality": "1080p",
"quote": false,
"replyUrl": "Place your call back URL here",
"replyRef": "Place your reference id here",
"maxJobs": 3
}
Parameters
-
emailis optional, if not specified API will randomly select account from available accounts. -
audio_pathis required, the song: apathreturned by POST files for an MP3 upload, or a song from GET music-video/library. 10 seconds to 6 minutes. PixVerse refused an M4A file in our tests, so convert to MP3 first. -
modeis optional,performance(default),expressiveorstorytelling. See Modes and Prices. styleis optional, the look of the video. The values depend on the mode:performanceandexpressive:auto(default, PixVerse picks),custom(your own style image, see below),cinematic,underground,lo_fi,dreamscape,woolen_felt,candy,golden_age,voxel,retro_game,claymation,woodland_tale,impressionism,decadence,futuristic,chromatic_clash,holiday.storytelling:photorealistic(default),anime,2d_modern_animation,cyberpunk,high_energy,digital_art,pixel_art,city_pop,y2k_collage,illustration,sketch,rock_haze,bubble_gum_punk,claymation,metal_noir,ghibli,midnight_blue_soul,lego_blocks.
-
style_image_pathis optional, only withstyle: custom. An image whose look the whole video copies, apathfrom POST files or a style from the library. Without it,customusesimage_pathas the style.style: customneedsstyle_image_pathorimage_path. -
image_pathis optional, the character who performs: a photo uploaded via POST files or a character from the library. A clear, full-body photo with the face visible works best. Without it, PixVerse invents a performer. -
image_path_2is optional, a second character,storytellingonly. Needsimage_path. -
music_genreis optional, helps PixVerse read the song:pop,rock,hip_hop,rnb,jazz,reggae,country,folk,electronic,classical,soul,funk,metal,ambient,others. Refused bystorytelling. -
subtitlesis optional, defaultfalse.trueburns lyric captions into the video, timed to the vocals. Every video also comes with a copy without captions, see GET music-video/video_id. Refused bystorytelling. -
lyricsis optional, only withsubtitles: true. The song’s lyrics, one line per caption, so the captions spell the words right. Without it, PixVerse uses the lyrics it detects in the vocals. Refused bystorytelling. Maximum length 5,000 characters. -
promptis required forstorytellingand refused by the other modes, the story to tell. Maximum length 2,000 characters. -
aspect_ratiois optional,16:9(default),9:16,1:1,4:3or3:4. -
qualityis optional,720p(default) or1080p. -
quoteis optional, defaultfalse.truereturns the price for this exact request and creates nothing. Quoting is free. -
replyUrlis optional, place here your callback URL. This is the preferred and most optimal way to receive results quickly — the API polls every 10 seconds and will call the providedreplyUrlonce the music video is completed or failed. We recommend using sites like webhook.site to test callback URL functionality. Maximum length 1024 characters. Callback body has the same JSON shape as GET videos/video_idresponse. -
replyRefis optional, place here your reference id which will be stored and returned along with this video response / result. Maximum length 1024 characters. maxJobsis optional, if not specified value from selected accounts/email will be used. It should not exceed the number of concurrent generations supported by your account subscription plan. Valid range: 1…8
Every request gets a free quote first. If the account cannot afford the video, the API answers 412 before anything is created.
Responses
-
Use the returned
video_idwith GET music-video/video_iduntilstatusissucceededorfailed.cost_creditsis what this video costs,list_cost_creditsthe price without the free music video.{ "video_id": "user:<userid>-pixverse:<email>-video:642767619916505", "project_id": 192080023076656, "mode": "performance", "quality": "1080p", "aspect_ratio": "16:9", "bill_seconds": 152, "credits_per_second": 15, "list_cost_credits": 2280, "cost_credits": 0, "free": true }With
quote: truenothing is created:{ "quote": true, "mode": "performance", "quality": "720p", "bill_seconds": 30, "credits_per_second": 10, "list_cost_credits": 300, "cost_credits": 300, "free": false, "has_enough_credits": true } -
A parameter is invalid, for example a
stylethat the mode doesn’t have,promptoutsidestorytelling,lyricswithoutsubtitles, or an audio format PixVerse refuses.{ "error": "Parameter style (anime) is not available for mode performance. Valid values: auto,custom,cinematic,…", "code": 400 } -
{ "error": "Unauthorized" } -
The account does not have enough credits for this video. Nothing was created.
{ "error": "Not enough credits: this music video costs 1800 credits", "code": 412 } -
Wait in a loop for at least 10..30 seconds and retry again.
The API query is full and can not accept new requests. Size of the query is defined by the
maxJobsoptional parameter.{ "error": "Account <email> is busy executing <maxJobs> tasks." "All configured accounts are running at maximum capacity." } -
596 Pending mod message
The account has a pending error, and the API does not use it until you add it again with POST accounts/email. You receive an email when this happens. There are three causes.
PixVerse could not sign the account in, most often because its password was changed. Add the account again with the current password.
{ "error": "Your PixVerse account has pending error. Please address this issue at https://useapi.net/docs/api-pixverse-v2/post-pixverse-accounts-email before making any new API calls.", "code": 596 }Or PixVerse suspended the account. PixVerse suspends accounts that break its content rules and does not say which generation caused it. The first response carries PixVerse’s own details in
account_moderation, and later calls return the sameerror. Add the account again afterreinstatement_at. To ask PixVerse to lift the suspension earlier, write to thesupport_emailit gives.{ "error": "PixVerse suspended account [email protected] for 30 days, from 2026-10-16 09:26 UTC until 2026-11-15 09:26 UTC. PixVerse suspends accounts that break its content rules and does not say which generation caused it. Add the account again at https://useapi.net/docs/api-pixverse-v2/post-pixverse-accounts-email after 2026-11-15 09:26 UTC. To ask PixVerse to lift it earlier, write to [email protected].", "code": 596, "account_moderation": { "ban_level": "suspend_30d", "action": "temporary_suspend", "duration_days": 30, "suspended_at": "2026-10-16 09:26:25 (UTC)", "reinstatement_at": "2026-11-15 09:26:25 (UTC)", "support_email": "[email protected]" } }Or PixVerse banned the account for violating its community guidelines. A ban is permanent unless PixVerse accepts an appeal, and the
errorquotes PixVerse’s own message, which says how to appeal. Remove the account with DELETE accounts/email, or add it again only if PixVerse lifts the ban.{ "error": "PixVerse banned account [email protected] for violating its community guidelines (400024). A ban is permanent unless PixVerse accepts an appeal. PixVerse says: \"Your account has been banned for violating community guidelines. If you wish to appeal, please contact us via ...\" Remove it with DELETE /v2/pixverse/accounts/[email protected], or add it again (https://useapi.net/docs/api-pixverse-v2/post-pixverse-accounts-email) only if PixVerse lifts the ban.", "code": 596 }If every account you have is in this state, a request without
emailreturns 596 as well.
Model
{ // TypeScript, all fields are optional
video_id: string
project_id: number
mode: 'performance' | 'expressive' | 'storytelling'
quality: '720p' | '1080p'
aspect_ratio: string
bill_seconds: number
credits_per_second: number
list_cost_credits: number
cost_credits: number
free: boolean
error: string
code: number
// quote: true only
quote: boolean
has_enough_credits: boolean
}
Examples
-
curl -H "Accept: application/json" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer …" \ -X POST "https://api.useapi.net/v2/pixverse/music-video/create" \ -d '{"audio_path": "upload/<song>.mp3", "image_path": "upload/<singer>.jpeg", "aspect_ratio": "9:16"}' -
const apiUrl = `https://api.useapi.net/v2/pixverse/music-video/create`; const token = "API token"; const data = { method: 'POST', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' } }; data.body = JSON.stringify({ audio_path: "upload/<song>.mp3", image_path: "upload/<singer>.jpeg", aspect_ratio: "9:16" }); const response = await fetch(apiUrl, data); const result = await response.json(); console.log("response", {response, result}); -
import requests apiUrl = f"https://api.useapi.net/v2/pixverse/music-video/create" token = "API token" headers = { "Content-Type": "application/json", "Authorization" : f"Bearer {token}" } body = { "audio_path": "upload/<song>.mp3", "image_path": "upload/<singer>.jpeg", "aspect_ratio": "9:16" } response = requests.post(apiUrl, headers=headers, json=body) print(response, response.json())