Generated banner for Music
Generated logo for Music

Music

ElevenLabsOfficialPublished by ElevenLabs

  • Skill
  • Tool integration
  • Automation and integrations
  • MIT
  • Medium risk

From the author

Generate music using ElevenLabs Music API. Use when creating instrumental tracks, songs with lyrics, background music, jingles, or any AI-generated music composition. Supports prompt-based generation, composition plans for granular control, and detailed output with metadata.
— the description by ElevenLabs

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

This skill provides an interface to the ElevenLabs Music API, enabling the generation of instrumental tracks, songs with lyrics, and background music. It supports prompt-based generation, structured composition plans for granular control, and advanced features like inpainting, video-to-music conversion, and custom finetuning.

What it does

  • Generates music from text prompts or structured composition plans.
  • Converts video files into synchronized background music scores.
  • Supports inpainting to edit or extend existing audio tracks.
  • Enables training and management of custom music finetunes.
  • Provides streaming capabilities for audio generation.
  • Allows detailed output with metadata and word-level timestamps.

When to use it

  • When you need to generate original background music or songs for creative projects.
  • When you require precise control over musical structure, lyrics, or instrumentation.
  • When you need to score video content with AI-generated music.
  • When you want to edit or extend previously generated audio using inpainting.

Advantages

  • Offers granular control via composition plans for specific sections and styles.
  • Supports both simple prompt-based generation and complex multi-step workflows.
  • Provides tools for managing and reusing custom music finetunes.
  • Enables integration with video workflows for automated scoring.

Usage examples

“Generate a 30-second chill lo-fi hip hop beat.”
The agent uses the music.compose method to generate an MP3 file based on the provided prompt and duration.
“Create a background score for this video file.”
The agent uses the music.video_to_music method to analyze the video and generate a matching musical score.
“Create a composition plan for an orchestral piece.”
The agent generates a structured JSON plan that can be edited before final audio synthesis.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/elevenlabs/music/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip music.zip -d .agents/skills

Documentation by ElevenLabs

ElevenLabs Music Generation

Generate music from text prompts - supports instrumental tracks, songs with lyrics, and fine-grained control via composition plans.

Setup, before writing any code: if ELEVENLABS_API_KEY isn't set for this project, run npx -y @elevenlabs/cli@latest onboard init from the app's folder first and follow what it prints: it signs the user in and stores a key for the project, so nobody copies one by hand. Otherwise see the Installation Guide. For JavaScript, use @elevenlabs/* packages only.

All examples below use music_v2_5, the most advanced generation model. Pass music_v2 or music_v1 only when an older model is explicitly requested.

Quick Start

Python
from elevenlabs import ElevenLabs

client = ElevenLabs()

audio = client.music.compose(
    prompt="A chill lo-fi hip hop beat with jazzy piano chords",
    music_length_ms=30000,
    model_id="music_v2_5",
)

with open("output.mp3", "wb") as f:
    for chunk in audio:
        f.write(chunk)
TypeScript
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import { createWriteStream } from "fs";

const client = new ElevenLabsClient();
const audio = await client.music.compose({
  prompt: "A chill lo-fi hip hop beat with jazzy piano chords",
  musicLengthMs: 30000,
  modelId: "music_v2_5",
});
audio.pipe(createWriteStream("output.mp3"));
CLI
elevenlabs music compose \
  --prompt "A chill lo-fi beat" \
  --music-length-ms 30000 \
  --model-id music_v2_5 \
  --output output.mp3

Methods

MethodDescription
music.composeGenerate audio from a prompt or composition plan
music.streamStream audio chunks as they are generated (paid plans)
music.composition_plan.createGenerate a structured plan for fine-grained control
music.compose_detailedGenerate audio + composition plan + metadata; pass store_for_inpainting=True to enable inpainting
music.compose_detailed_streamStream audio plus composition plan, metadata, and optional word timestamps as Server-Sent Events
music.video_to_musicGenerate background music from one or more uploaded video files
music.uploadUpload an audio file for later inpainting workflows, optionally extracting its composition plan or word-level timestamps
music.finetunes.listList accessible music finetunes
music.finetunes.createTrain a music finetune from uploaded audio
music.finetunes.getRetrieve finetune status and metadata
music.finetunes.updateUpdate finetune metadata or visibility
music.finetunes.deleteDelete a music finetune

See API Reference for full parameter details.

music.upload is available to enterprise clients with access to the inpainting feature.

Music Finetunes

Create a finetune from training audio with POST /v1/music/finetunes, then poll the get endpoint until its status is completed. Pass the returned id as finetune_id when composing music.

Use the list, update, and delete endpoints to manage accessible finetunes.

Video to Music

Generate background music from uploaded video clips via POST /v1/music/video-to-music (client.music.video_to_music). This is separate from prompt-based music.compose (POST /v1/music).

The API combines videos in order, accepts an optional natural-language description, and lets you steer style with up to 10 tags such as upbeat or cinematic. This endpoint still defaults to music_v1; pass model_id="music_v2_5" to use the most advanced model.

Three optional flags shape the result: use_audio_as_reference takes genre, BPM, instrumentation, and mood from the video's own audio, add_sfx adds sound effects that match the video, and separate_tracks returns a ZIP with the music and sound effects as separate files for mixing.

Python
from elevenlabs import ElevenLabs

client = ElevenLabs()

audio = client.music.video_to_music(
    videos=["trailer.mp4"],
    description="Build suspense, then resolve with a warm cinematic finish.",
    tags=["cinematic", "suspenseful", "uplifting"],
    model_id="music_v2_5",
)

with open("video-score.mp3", "wb") as f:
    for chunk in audio:
        f.write(chunk)
TypeScript
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
import { createReadStream, createWriteStream } from "fs";

const client = new ElevenLabsClient();

const audio = await client.music.videoToMusic({
  videos: [createReadStream("trailer.mp4")],
  description: "Build suspense, then resolve with a warm cinematic finish.",
  tags: ["cinematic", "suspenseful", "uplifting"],
  modelId: "music_v2_5",
});

audio.pipe(createWriteStream("video-score.mp3"));
CLI
elevenlabs music video_to_music \
  --videos trailer.mp4 \
  --description "Build suspense, then resolve with a warm cinematic finish." \
  --tags cinematic \
  --model-id music_v2_5 \
  --output video-score.mp3

The CLI currently accepts one --videos file and one --tags value per request; use the Python or TypeScript SDK to send multiple videos or tags.

Constraints from the current API schema:

  • Upload 1-10 video files per request

  • Keep total combined upload size at or below 200 MB

  • Keep total combined video duration at or below 600 seconds

  • Use description for high-level musical direction and tags for concise style cues

Composition Plans

music_v2_5 composition plans are an ordered list of chunks. Each chunk specifies its own text (section label, lyrics, inline cues), duration_ms, positive_styles, negative_styles, and context_adherence (low, medium, or high, default high). Up to 30 chunks per plan, each 3,000–120,000 ms, total length 3 s to 10 minutes. Each chunk's text supports up to 6,132 characters, with up to 30 lines of 200 characters each.

Generate a plan first, edit it, then compose:

plan = client.music.composition_plan.create(
    prompt="An epic orchestral piece building to a climax",
    music_length_ms=60000,
    model_id="music_v2_5",
)

# Edit chunks in place
plan["chunks"][0]["text"] = "[Intro]\nQuiet strings rising"

audio = client.music.compose(
    composition_plan=plan,
    model_id="music_v2_5",
)
const plan = await client.music.compositionPlan.create({
  prompt: "An epic orchestral piece building to a climax",
  musicLengthMs: 60000,
  modelId: "music_v2_5",
});

plan.chunks[0].text = "[Intro]\nQuiet strings rising";

const audio = await client.music.compose({
  compositionPlan: plan,
  modelId: "music_v2_5",
});

Or hand-build a plan to control lyrics and style per section:

composition_plan = {
    "chunks": [
        {
            "text": "[Verse]\nWalking down an empty street",
            "duration_ms": 15000,
            "positive_styles": ["pop", "upbeat", "female vocals", "acoustic guitar"],
            "negative_styles": ["dark", "slow"],
            "context_adherence": "high",
        },
        {
            "text": "[Chorus]\nThis is my moment",
            "duration_ms": 15000,
            "positive_styles": ["powerful vocals", "full band"],
            "negative_styles": [],
            "context_adherence": "high",
        },
    ]
}

audio = client.music.compose(composition_plan=composition_plan, model_id="music_v2_5")
const compositionPlan = {
  chunks: [
    {
      text: "[Verse]\nWalking down an empty street",
      durationMs: 15000,
      positiveStyles: ["pop", "upbeat", "female vocals", "acoustic guitar"],
      negativeStyles: ["dark", "slow"],
      contextAdherence: "high",
    },
    {
      text: "[Chorus]\nThis is my moment",
      durationMs: 15000,
      positiveStyles: ["powerful vocals", "full band"],
      negativeStyles: [],
      contextAdherence: "high",
    },
  ],
};

const audio = await client.music.compose({
  compositionPlan,
  modelId: "music_v2_5",
});

Put broader characteristics (genre, instrumentation, vocal style) in positive_styles, not in text. The first chunk's styles set the overall tone — include 6–7 styles there.

Output Formats

Use the output_format query parameter on compose, detailed compose, or stream requests to select the generated audio format. auto chooses a model-appropriate MP3 format; for music_v2 and music_v2_5, it selects mp3_48000_192. Higher-bitrate MP3 options include mp3_48000_240 and mp3_48000_320.

Streaming

For paid plans, stream audio chunks as they are generated instead of waiting for the full file:

from io import BytesIO

stream = client.music.stream(
    prompt="A driving synthwave track with arpeggiated leads",
    music_length_ms=30000,
    model_id="music_v2_5",
)

buffer = BytesIO()
for chunk in stream:
    if chunk:
        buffer.write(chunk)
const stream = await client.music.stream({
  prompt: "A driving synthwave track with arpeggiated leads",
  musicLengthMs: 30000,
  modelId: "music_v2_5",
});

const chunks: Buffer[] = [];
for await (const chunk of stream) {
  chunks.push(chunk);
}
Detailed streaming

Use detailed streaming when the application needs generated music metadata while audio is still arriving. POST /v1/music/detailed/stream accepts the same prompt or composition-plan body as detailed compose, streams text/event-stream, and can include word timestamps with with_timestamps.

elevenlabs music compose_detailed_stream \
  --prompt "A bright indie pop hook with warm guitars" \
  --music-length-ms 30000 \
  --model-id music_v2_5 \
  --with-timestamps true \
  --output-format auto

Inpainting

Inpainting edits or extends a stored song by mixing audio reference chunks (unchanged slices of a stored song) with new generation chunks in a single composition plan.

Step 1 — get a song_id, either by storing a fresh generation or uploading existing audio:

# Option A: keep a generation for later editing
result = client.music.compose_detailed(
    prompt="An upbeat pop song with verse and chorus",
    music_length_ms=60000,
    model_id="music_v2_5",
    store_for_inpainting=True,
)
song_id = result.song_id

# Option B: upload an existing track and extract its plan
uploaded = client.music.upload(
    file=open("my-song.mp3", "rb"),
    extract_composition_plan="music_v2_5",
)
song_id = uploaded.song_id
composition_plan = uploaded.composition_plan
import { createReadStream } from "fs";

// Option A: keep a generation for later editing
const result = await client.music.composeDetailed({
  prompt: "An upbeat pop song with verse and chorus",
  musicLengthMs: 60000,
  modelId: "music_v2_5",
  storeForInpainting: true,
});
let songId = result.songId;

// Option B: upload an existing track and extract its plan
const uploaded = await client.music.upload({
  file: createReadStream("my-song.mp3"),
  extractCompositionPlan: "music_v2_5",
});
songId = uploaded.songId;
const compositionPlan = uploaded.compositionPlan;

Step 2 — compose a plan that references the stored audio and regenerates the part you want to change:

plan = {
    "chunks": [
        {"song_id": song_id, "range": {"start_ms": 0, "end_ms": 30000}},
        {
            "text": "[Chorus]\nWe're rising up tonight",
            "duration_ms": 30000,
            "positive_styles": ["bigger drums", "layered vocals", "anthemic"],
            "negative_styles": ["sparse"],
            "context_adherence": "high",
        },
    ]
}

audio = client.music.compose(composition_plan=plan, model_id="music_v2_5")
const plan = {
  chunks: [
    { songId, range: { startMs: 0, endMs: 30000 } },
    {
      text: "[Chorus]\nWe're rising up tonight",
      durationMs: 30000,
      positiveStyles: ["bigger drums", "layered vocals", "anthemic"],
      negativeStyles: ["sparse"],
      contextAdherence: "high",
    },
  ],
};

const audio = await client.music.compose({
  compositionPlan: plan,
  modelId: "music_v2_5",
});

To match the feel of a stored slice without copying it, attach a conditioning_ref (up to 30,000 ms) plus a condition_strength of low, medium, high, or xhigh to a generation chunk. Conditioning placed on the first chunk influences every later chunk.

See API Reference for the full inpainting parameter list.

Content Restrictions

  • Cannot reference specific artists, bands, or copyrighted lyrics

  • bad_prompt errors include a prompt_suggestion with alternative phrasing

  • bad_composition_plan errors include a composition_plan_suggestion

Error Handling

try:
    audio = client.music.compose(prompt="...", music_length_ms=30000)
except Exception as e:
    print(f"API error: {e}")
try {
  const audio = await client.music.compose({
    prompt: "...",
    musicLengthMs: 30000,
  });
} catch (err) {
  console.error("API error:", err);
}

Common errors: 401 (invalid key), 422 (invalid params), 429 (rate limit).

References

Files

references/api_reference.md

Music API Reference

All endpoints below default to music_v1 unless noted for backwards compatibility. Pass music_v2_5 unless the caller explicitly needs an older model.

Table of Contents

  • compose

  • stream

  • composition_plan.create

  • compose_detailed

  • compose_detailed_stream

  • upload

  • video_to_music

  • Inpainting

  • Error Handling

compose

Generate music from a text prompt or composition plan. Returns an audio stream.

Parameters
ParameterTypeRequiredDescription
promptstringYes*Description of desired music
composition_planobjectYes*Pre-defined composition plan (alternative to prompt)
music_length_msintegerNoDuration in milliseconds (3,000–600,000) when using prompt; if omitted, the model chooses. Returns an error if a composition plan is also provided.
model_idstringNoMusic model: music_v1, music_v2, or music_v2_5. Defaults to music_v1.
force_instrumentalbooleanNoGuarantee an instrumental output (prompt mode only)
finetune_idstringNoID of the music finetune to use for generation.
respect_sections_durationsbooleanNoEnforce exact duration_ms for each composition plan chunk. Ignored for music_v2 and music_v2_5.
output_formatstringNoQuery parameter for output codec/sample-rate/bitrate. auto selects mp3_44100_128 for music_v1 and mp3_48000_192 for v2 models; high-bitrate MP3 options include mp3_48000_240 and mp3_48000_320.

*Provide either prompt or composition_plan, not both.

Python
audio = client.music.compose(
    prompt="An upbeat electronic track with synth leads",
    music_length_ms=30000,
    model_id="music_v2_5",
)

with open("output.mp3", "wb") as f:
    for chunk in audio:
        f.write(chunk)
TypeScript
const audio = await client.music.compose({
  prompt: "An upbeat electronic track with synth leads",
  musicLengthMs: 30000,
  modelId: "music_v2_5",
});

const writeStream = createWriteStream("output.mp3");
audio.pipe(writeStream);
With Composition Plan
plan = client.music.composition_plan.create(
    prompt="A jazz ballad with piano and saxophone",
    music_length_ms=60000,
    model_id="music_v2_5",
)

# Modify the plan as needed
audio = client.music.compose(
    composition_plan=plan,
    model_id="music_v2_5",
)
const plan = await client.music.compositionPlan.create({
  prompt: "A jazz ballad with piano and saxophone",
  musicLengthMs: 60000,
  modelId: "music_v2_5",
});

// Modify the plan as needed
const audio = await client.music.compose({
  compositionPlan: plan,
  modelId: "music_v2_5",
});

stream

Stream audio chunks as they are generated. Same parameters as compose; returns an iterable/async-iterable of audio bytes instead of a single response. Available on paid plans only.

Python
from io import BytesIO

stream = client.music.stream(
    prompt="A driving synthwave track with arpeggiated leads",
    music_length_ms=30000,
    model_id="music_v2_5",
)

buffer = BytesIO()
for chunk in stream:
    if chunk:
        buffer.write(chunk)
TypeScript
const stream = await client.music.stream({
  prompt: "A driving synthwave track with arpeggiated leads",
  musicLengthMs: 30000,
  modelId: "music_v2_5",
});

const chunks: Buffer[] = [];
for await (const chunk of stream) {
  chunks.push(chunk);
}

composition_plan.create

Generate a structured composition plan from a prompt for granular control before generating audio.

Parameters
ParameterTypeRequiredDescription
promptstringYesMusic description
music_length_msintegerYesTotal duration in milliseconds (3,000–600,000)
model_idstringNoSupports music_v1, music_v2, and music_v2_5. Defaults to music_v1. Plan structure differs between model generations.
Plan Structure (music_v2 and music_v2_5)

A plan is an ordered list of chunks. Each chunk is either a generation chunk or an audio reference chunk (see Inpainting).

FieldTypeDescription
chunksarrayUp to 30 chunks; 3 s to 10 min total
chunks[].textstringSection labels ([Verse 1]), lyrics, inline cues like {guitar solo}. Up to 6,132 characters, 30 lines, and 200 characters per line.
chunks[].duration_msinteger3,000–120,000 ms
chunks[].positive_stylesarray<string>Up to 50 desired qualities (genre, instrumentation, vocal style). Must be English.
chunks[].negative_stylesarray<string>Up to 50 qualities to avoid
chunks[].context_adherencestringlow, medium, or high (default). Higher = stays consistent with surrounding chunks.
Python
plan = client.music.composition_plan.create(
    prompt="A peaceful ambient track with nature sounds",
    music_length_ms=60000,
    model_id="music_v2_5",
)

# Inspect or edit the plan in place
print(plan["chunks"][0]["positive_styles"])
plan["chunks"][0]["text"] = "[Intro]\nSoft pad with rain"

audio = client.music.compose(composition_plan=plan, model_id="music_v2_5")
TypeScript
const plan = await client.music.compositionPlan.create({
  prompt: "A peaceful ambient track with nature sounds",
  musicLengthMs: 60000,
  modelId: "music_v2_5",
});

plan.chunks[0].text = "[Intro]\nSoft pad with rain";
const audio = await client.music.compose({ compositionPlan: plan, modelId: "music_v2_5" });

compose_detailed

Generate music while returning both the composition plan and metadata alongside the audio.

Parameters
ParameterTypeRequiredDescription
promptstringYes*Description of desired music
composition_planobjectYes*Pre-defined composition plan (alternative to prompt)
music_length_msintegerNoTotal duration in milliseconds when using prompt
model_idstringNoSupports music_v1, music_v2, and music_v2_5. Defaults to music_v1.
store_for_inpaintingbooleanNoIf true, retains the generated audio under a song_id so it can be referenced by later inpainting plans
force_instrumentalbooleanNoGuarantee an instrumental output (prompt mode only)
with_waveform_visualbooleanNoInclude a low-resolution waveform preview; defaults to false
output_formatstringNoQuery parameter for output codec/sample-rate/bitrate. auto selects mp3_44100_128 for music_v1 and mp3_48000_192 for v2 models; high-bitrate MP3 options include mp3_48000_240 and mp3_48000_320.

*Provide either prompt or composition_plan, not both.

Returns
FieldDescription
jsonComposition plan + song metadata (includes lyrics if applicable)
filenameOutput file identifier
audioAudio bytes
song_idIdentifier for the stored song (only when store_for_inpainting=True)
json.waveform_visualOptional integer array sampled four times per second, with values from -1000 to 1000
Python
result = client.music.compose_detailed(
    prompt="A pop song about summer adventures",
    music_length_ms=120000,
    model_id="music_v2_5",
    store_for_inpainting=True,
)

print(result.json)        # composition plan + metadata
print(result.song_id)     # reusable identifier for inpainting

with open(result.filename, "wb") as f:
    f.write(result.audio)
TypeScript
import { writeFileSync } from "fs";

const result = await client.music.composeDetailed({
  prompt: "A pop song about summer adventures",
  musicLengthMs: 120000,
  modelId: "music_v2_5",
  storeForInpainting: true,
});

console.log(result.json);    // composition plan + metadata
console.log(result.songId);  // reusable identifier for inpainting

writeFileSync(result.filename, result.audio);

compose_detailed_stream

Stream music generation details as Server-Sent Events from POST /v1/music/detailed/stream. Use this when a client should receive the composition plan, song metadata, audio chunks, optional word timestamps, and completion signal incrementally.

Parameters
ParameterTypeRequiredDescription
promptstringYes*Description of desired music
composition_planobjectYes*Pre-defined composition plan (alternative to prompt)
music_length_msintegerNoDuration in milliseconds when using prompt
model_idstringNoDefaults to music_v1; pass music_v2_5 for the most advanced model
seedintegerNoRandom seed for more consistent generation; cannot be used with prompt
force_instrumentalbooleanNoGuarantee an instrumental output (prompt mode only)
store_for_inpaintingbooleanNoStore the generated song so it can be referenced by later inpainting plans
with_timestampsbooleanNoInclude word timestamps in the streamed events
with_waveform_visualbooleanNoInclude a low-resolution waveform preview in the streamed events
output_formatstringNoQuery parameter for output codec/sample-rate/bitrate. auto selects mp3_44100_128 for music_v1 and mp3_48000_192 for v2 models.

*Provide either prompt or composition_plan, not both.

CLI
elevenlabs music compose_detailed_stream \
  --prompt "A bright indie pop hook with warm guitars" \
  --music-length-ms 30000 \
  --model-id music_v2_5 \
  --with-timestamps true \
  --output-format auto

upload

Upload a music file for later inpainting workflows. This endpoint is available to enterprise clients with access to the inpainting feature.

Parameters
ParameterTypeRequiredDescription
filefileYesThe audio file to upload
extract_composition_planboolean | stringNoIf true (or a model ID such as "music_v2_5"), the response includes an extracted composition plan; passing a model ID chooses the extraction model. The request may take longer to return.
with_timestampsbooleanNoTranscribe the uploaded song and include word-level timestamps in the response. The request may take longer to return.
with_waveform_visualbooleanNoInclude a low-resolution waveform preview in the response
Returns
FieldDescription
song_idUnique identifier for the uploaded song
composition_planExtracted composition plan, or null when extract_composition_plan is not enabled
words_timestampsWord-level timestamps when with_timestamps is enabled
waveform_visualInteger array sampled four times per second, with values from -1000 to 1000, when with_waveform_visual is enabled
Python
response = client.music.upload(
    file=open("my-song.mp3", "rb"),
    extract_composition_plan="music_v2_5",
)
song_id = response.song_id
composition_plan = response.composition_plan
TypeScript
import { createReadStream } from "fs";

const response = await client.music.upload({
  file: createReadStream("my-song.mp3"),
  extractCompositionPlan: "music_v2_5",
});
const songId = response.songId;
const compositionPlan = response.compositionPlan;
CLI
elevenlabs music upload \
  --file my-song.mp3 \
  --extract-composition-plan music_v2_5

video_to_music

Generate background music from uploaded video clips. This is a separate endpoint from compose (POST /v1/music/video-to-music, not POST /v1/music). See the Video to music API reference.

Videos are combined in order before music generation.

Parameters
ParameterTypeRequiredDescription
videosarray of filesYesOne or more video files. Up to 10 files, 200MB combined size, and 600 seconds total duration.
descriptionstringNoOptional text prompt describing the desired music (up to 1000 characters).
tagsarray of stringsNoOptional style tags such as upbeat or cinematic (up to 10 tags).
model_idstringNoMusic model to use. Defaults to music_v1 on this endpoint; pass music_v2_5 for the most advanced model.
use_audio_as_referencebooleanNoUse the genres, BPM, instrumentation, mood, and arc of the video's own audio track as reference. Defaults to false.
add_sfxbooleanNoAdd sound effects that match the video. Defaults to false.
separate_tracksbooleanNoReturn a ZIP with separate music and sound effects tracks instead of a single mixed file. Defaults to false.
sign_with_c2pabooleanNoSign generated MP3 output with C2PA metadata. Defaults to false.
output_formatstringNoOutput codec/sample-rate/bitrate, such as mp3_44100_128, pcm_44100, or opus_48000_96.
Python
audio = client.music.video_to_music(
    videos=[open("scene-1.mp4", "rb"), open("scene-2.mp4", "rb")],
    description="Cinematic ambient score with a gentle build",
    tags=["cinematic", "ambient"],
    model_id="music_v2_5",
)

with open("video-score.mp3", "wb") as f:
    for chunk in audio:
        f.write(chunk)
TypeScript
import { createReadStream, createWriteStream } from "fs";

const audio = await client.music.videoToMusic({
  videos: [createReadStream("scene-1.mp4"), createReadStream("scene-2.mp4")],
  description: "Cinematic ambient score with a gentle build",
  tags: ["cinematic", "ambient"],
  modelId: "music_v2_5",
});

audio.pipe(createWriteStream("video-score.mp3"));
CLI
elevenlabs music video_to_music \
  --videos scene-1.mp4 \
  --description "Cinematic ambient score with a gentle build" \
  --tags cinematic \
  --output-format mp3_44100_128 \
  --output video-score.mp3

The CLI currently accepts one --videos file and one --tags value per request; use the Python or TypeScript SDK to send multiple videos or tags.

Inpainting

Inpainting edits or extends a stored song by combining audio reference chunks (unchanged slices of stored audio) with generation chunks in a single music_v2 or music_v2_5 composition plan. Available to enterprise clients.

Getting a song_id
  • Call compose_detailed or compose with store_for_inpainting=True to keep a generation for later editing.

  • Call upload with extract_composition_plan="music_v2_5" to import an existing track and recover its plan.

Chunk Types

Audio reference chunk — replay a slice of a stored song unchanged:

FieldTypeDescription
song_idstringStored song identifier
range.start_msintegerStart offset (minimum 50 ms range)
range.end_msintegerEnd offset

Generation chunk — same fields as a normal v2 model plan chunk (text, duration_ms, positive_styles, negative_styles, context_adherence), with two optional fields for matching the feel of an existing slice:

FieldTypeDescription
conditioning_ref.song_idstringSong to condition on
conditioning_ref.rangeobjectstart_ms/end_ms; up to 30,000 ms
condition_strengthstringlow, medium (default), high, or xhigh

conditioning_ref on the first chunk influences every subsequent chunk in the plan.

Constraints
ConstraintLimit
Chunks per plan30
Chunk duration3,000–120,000 ms
Conditioning reference durationup to 30,000 ms
Minimum time range50 ms
Python
plan = {
    "chunks": [
        {"song_id": song_id, "range": {"start_ms": 0, "end_ms": 30000}},
        {
            "text": "[Chorus]\nWe're rising up tonight",
            "duration_ms": 30000,
            "positive_styles": ["bigger drums", "layered vocals", "anthemic"],
            "negative_styles": ["sparse"],
            "context_adherence": "high",
            "conditioning_ref": {
                "song_id": song_id,
                "range": {"start_ms": 30000, "end_ms": 45000},
            },
            "condition_strength": "high",
        },
    ]
}

audio = client.music.compose(composition_plan=plan, model_id="music_v2_5")
TypeScript
const plan = {
  chunks: [
    { songId, range: { startMs: 0, endMs: 30000 } },
    {
      text: "[Chorus]\nWe're rising up tonight",
      durationMs: 30000,
      positiveStyles: ["bigger drums", "layered vocals", "anthemic"],
      negativeStyles: ["sparse"],
      contextAdherence: "high",
      conditioningRef: { songId, range: { startMs: 30000, endMs: 45000 } },
      conditionStrength: "high",
    },
  ],
};

const audio = await client.music.compose({ compositionPlan: plan, modelId: "music_v2_5" });

Error Handling

bad_prompt

Occurs when the prompt references copyrighted material (specific artists, bands, or copyrighted lyrics). The error response includes a prompt_suggestion with alternative phrasing.

try:
    audio = client.music.compose(
        prompt="A song like Beatles",
        music_length_ms=30000
    )
except Exception as e:
    print(f"Request failed: {e}")
try {
  const audio = await client.music.compose({
    prompt: "A song like Beatles",
    musicLengthMs: 30000,
  });
} catch (err) {
  console.error("Request failed:", err);
}
bad_composition_plan

Returned when a composition plan contains copyrighted styles. The error includes a composition_plan_suggestion with corrected styles. No suggestion is provided for harmful content.

Common HTTP Errors
CodeMeaning
401Invalid API key
422Invalid parameters
429Rate limit exceeded

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs an API key, Needs Python, Needs Node.js

The author says: Requires internet access and an ElevenLabs API key (ELEVENLABS_API_KEY).

Security

What our scanner noticed· Medium risk

  • Instructions that use the network
  • Downloads piped into a shell

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
ElevenLabs
Publisher
ElevenLabs (Official)
Source
elevenlabs/skills · music · commit 9763c39
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by ElevenLabs or ElevenLabs.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download music.zip