---
title: "Create a music video"
method: POST
path: "/music-videos"
tags: ["Music"]
---

# Create a music video

`POST /music-videos`

Builds a music video: your song plus AI visuals, synced captions, and an optional waveform.

**Pick the song (exactly one):**
- `musicId`: a completed song from `POST /music` (see `GET /music`).
- `musicAssetId`: a track you uploaded with `POST /uploads` (purpose `music`).

**Pick the visuals with `visualMode`:**
- `ai-images`: AI generates a new image every few seconds (set `secondsPerImage`).
- `ai-video`: AI generates short video clips across the song.
- `cover-image`: a single still image for the whole song (requires `coverImageAssetId`).

Returns a `videoId` (a video). Poll `GET /videos/{id}` until `status` is `completed`, then export it with `POST /exports` and download with `GET /exports/download`, or publish it.

**Cost:** depends on the visual mode, quality, and song length (see the response `estimatedCredits`). Credits are refunded automatically if generation fails.

## Request body

- object
  - `musicId` string, uuid — A completed song from `POST /music`. Provide this OR `musicAssetId`, not both.
  - `musicAssetId` string, uuid — A track uploaded with `POST /uploads` (purpose `music`). Provide this OR `musicId`, not both.
  - `visualMode` 'ai-images' | 'ai-video' | 'cover-image', required — `ai-images` (a new AI image every few seconds), `ai-video` (short AI clips), or `cover-image` (one still for the whole song).
  - `visualDirection` string — Optional art direction for the visuals, e.g. "neon cyberpunk city at night, moody".
  - `imageStyleId` string — Image style for `ai-images`/`ai-video`. Get IDs from `GET /image-styles`.
  - `imageQuality` 'basic' | 'good' | 'premium' | 'max' — Image quality for `ai-images` (higher costs more).
  - `secondsPerImage` number — For `ai-images`: how many seconds each image is shown. Fewer seconds means more images and more credits.
  - `videoQuality` 'basic' | 'good' | 'premium' — Clip quality for `ai-video` (higher costs more).
  - `coverImageAssetId` string, uuid — For `cover-image` mode: an image uploaded with `POST /uploads` (purpose `element-image`). Required for that mode.
  - `aspectRatio` '9:16' | '16:9' | '1:1' — Video dimensions.
  - `captionsEnabled` boolean — Show word-synced lyric captions. Automatically off for instrumental tracks.
  - `captionStyleId` string — Caption style ID from `GET /caption-styles`.
  - `captionPosition` 'top' | 'center' | 'bottom' — Where captions sit on screen.
  - `showWaveform` boolean — Show an audio waveform animation.
  - `musicTrimStartSeconds` number — Start the video at this point in the song (seconds). Defaults to the start.
  - `musicTrimEndSeconds` number — End the video at this point in the song (seconds). Defaults to the full length.

## Response `200`

OK

- object
  - `videoId` string, uuid, required — Poll `GET /videos/{id}`. When completed, export with POST /exports.
  - `status` 'pending', required
  - `estimatedCredits` number, required — Credits reserved. Settled to the actual cost or refunded when generation ends.

## Other responses

- `401` — 401
- `402` — 402
- `403` — 403

---

[API](https://skmtc.net/aituber/apis/aituber-api.md) · [All operations](https://skmtc.net/aituber/apis/aituber-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/aituber/aituber-api/revisions/35448566f143/schema)
