Music and OpenAI-compatible audio APIs
The studio, native jobs and both audio endpoints share port 8087 and one FIFO compute worker. Requests never execute GPU inference in parallel. All models and generated audio stay on the machine running the container.
Open the local API guide or download
http://localhost:8087/openapi.json for the OpenAPI 3.1 contract. The guide is
packaged in the image and works without a CDN.
For agents, connect to /mcp. Its four tools require reading the
songwriting guide first, expose basic musical controls and return HTTP
download links valid for one hour after completion.
Generate music
POST /v1/audio/music is our music extension. It returns one complete audio file:
curl http://localhost:8087/v1/audio/music \
-H 'Content-Type: application/json' \
--data '{"model":"yue2","lyrics":"[Verse]\nMorning light across the floor\nA little song outside the door","style":"English acoustic pop, warm female singing, gentle guitar","duration":30,"steps":8,"response_format":"flac"}' \
--output song.flac
Use lyrics and style, or their compatibility equivalents input and
instructions. Lyrics are passed verbatim. If both input and lyrics are
provided, they must match. instructions supplements style when both exist.
An empty lyric string with instrumental direction is supported. Omitted model
selection resolves to YuE2; harmless unrelated fields are ignored.
/v1/audio/music is a local extension, not an official OpenAI endpoint. Existing
OpenAI SDKs use the speech adapter below rather than an audio.music resource.
OpenAI clients
POST /v1/audio/speech accepts the same requests and returns the same audio.
It generates songs, including when the input is ordinary text. This service
does not provide spoken narration or OpenAI voice identities.
from openai import OpenAI
client = OpenAI(base_url="http://localhost:8087/v1", api_key="local")
with client.audio.speech.with_streaming_response.create(
model="yue2",
input="[Verse]\nMorning light across the floor\nA little song outside the door",
instructions="English acoustic pop, warm female singing, gentle guitar",
voice="auto",
response_format="flac",
extra_body={"duration": 30, "steps": 8},
) as response:
response.stream_to_file("song.flac")
import OpenAI from "openai";
import { writeFile } from "node:fs/promises";
const client = new OpenAI({ baseURL: "http://localhost:8087/v1", apiKey: "local" });
const response = await client.audio.speech.create({
model: "yue2",
input: "Morning light across the floor. A little song outside the door.",
instructions: "English acoustic pop, warm female singing, gentle guitar",
voice: "auto",
response_format: "opus",
duration: 30,
steps: 8,
});
await writeFile("song.opus", Buffer.from(await response.arrayBuffer()));
The JavaScript example is plain JavaScript; typed clients can pass music-only
fields through their SDK’s extra-body mechanism or call the music endpoint.
The complete song is generated before response delivery. Streaming-response
helpers can download the completed file, but this is not live music generation.
stream_format="audio" works; speech SSE events and stream=true are rejected.
Models and voices
GET /v1/models lists the actual local yue2 model with its capabilities.
GET /v1/models/{id} also resolves yue2-3b, tts-1, tts-1-hd and
gpt-4o-mini-tts. These aliases all use local YuE2; no provider model or cloud
account is involved. Unknown models return 404.
Acoustic variations
Studio and fresh native /synth requests default to two acoustic renditions
of each composition. synth_batch_size accepts integers 1–3; larger counts
and other value types are rejected before queue admission. /props advertises
the default and limits.synth_batch_size_max. Explicit one-track requests remain
available. Per-track replay exports specify one; older replay requests containing
semantic_tokens without a count also retain one.
The two-minute scaling benchmark found a 67% throughput gain from one to two, another 25% from two to three, and only 11% from three to four. The fourth saved about 1.1 seconds per rendition while adding 624 MiB to the sampled device peak. This product caps the choice at three. These are RTX 5070 Ti observations with resident models and include desktop memory; they do not establish capacity for every song length or prompt.
The OpenAI compatibility routes and MCP still return one track per call; their single-file contracts do not inherit the native two-variation default.
voice defaults to auto, which adds no vocal hint. default behaves the same.
These hints supplement musical direction; they do not identify fixed singers:
| Values | Hint added to the musical direction |
|---|---|
female, nova, shimmer, coral |
Clear female lead vocals |
male, echo, onyx, cedar |
Clear male lead vocals |
alloy, ash, sage, marin |
Warm clear lead vocals |
ballad, fable, verse |
Expressive storytelling lead vocals |
Describe other vocal delivery in style/instructions. Custom voice objects,
unknown voice IDs and voice cloning are not supported by this adapter.
Audio quality and controls
Normal exports retain 48 kHz stereo. response_format accepts mp3 (default),
opus, aac, flac, wav, pcm, plus ogg, m4a, wav16, wav24, wav32.
wav maps to wav16. output_format is accepted as an equivalent field; if
both format fields are supplied they must agree. See encoding profiles.
Choose FLAC or WAV for lossless exports. wav32 retains the raw floating-point
output without normalization. Only explicit pcm export converts to the
compatibility layout: 24 kHz, mono, signed 16-bit little-endian samples without
a header. It does not change normal exports or the model’s output rate.
speed accepts 0.25–4.0, default 1. It changes the output tempo through
pitch-preserving FFmpeg processing after generation. It is separate from
inference speed and the musical BPM in your prompt. The duration ceiling applies
before this output adjustment.
Native settings such as duration, steps, seeds, CFG, sampling controls,
adapters, explicit ABC scores and replay/continuation tokens are supported.
Normal calls generate a fresh score and random seeds unless conditioning or
fixed seeds are explicitly supplied. Both audio endpoints return exactly one
track: n, lm_batch_size and synth_batch_size must be 1 when provided.
Responses contain the audio directly with the correct MIME type and extension,
plus X-Request-ID, X-YuE2-Job-ID, X-Audio-Sample-Rate and X-Audio-Channels.
Use /synth for asynchronous work, native batches, replay JSON and latents.
Native and compatibility requests also accept plan_retries (integer 0–8,
default 2): extra attempts for malformed model-generated scores before the music
stages. Zero disables retries but retains the early check. It does not retry
finished audio, change supplied scores or guarantee an ending/lyric accuracy.
Greedy score sampling is not retried. MCP agents use the engine default without
access to this advanced setting. See the planning behavior.
The existing native API reference remains available.
Authentication, errors and cancellation
Set YUE2_API_KEY to require Authorization: Bearer YOUR_LOCAL_KEY on /v1
and /mcp routes. SDK examples use a dummy local key because the SDK requires a key
argument; replace it with your configured key when authentication is enabled.
The key is local configuration, not an OpenAI account key.
For Docker, pass --env YUE2_API_KEY with the variable set in your shell. Local
Task commands also forward it from their environment/ignored .env without
printing its value, and preserve existing access settings across image updates.
An explicitly empty host value clears a previously configured key.
This authentication covers /v1 and /mcp. Studio, native jobs, logs and System keep
their existing local access policy. The normal Docker binding remains localhost;
whole-service remote access requires its own access configuration.
YUE2_API_TIMEOUT_SECONDS defaults to 600 and includes time waiting in the queue.
The synchronous request cancels its own job on timeout or client disconnect.
Queued cancelled work is skipped before model loading; active work cancels at
the engine’s existing checkpoints. Other jobs are unaffected. Native /synth
remains asynchronous. A failed connection after delivery starts cannot be changed
into a JSON error response.
V1 errors use {"error":{"message":"…","type":"invalid_request_error","param":"…","code":"…"}}.
Malformed/unsupported settings return 400, invalid keys 401, unknown models 404,
cancelled generation 409, generation failures 500 and the local deadline 504.
Schema and local guide routes are public. Unknown optional native model routes
remain unavailable; this change does not load transcription/tokenization models.
All compute routes share a configurable eight-job limit, including the active
job. Excess native/compatibility requests return 429 with Retry-After: 5;
compatibility errors retain the OpenAI envelope. Back off with jitter before
retrying refused submissions. Accepted jobs must be polled rather than submitted
again. An already-full native result store returns 507 before generation.
GET /health, /status and /system/queue report queue counts/capacity and
volume usage without exposing other callers’ job handles or lyrics. Completed
native/API results are streamed from /output/jobs, survive restarts, and expire
after 24 hours by default. The browser library remains separate. See
queue limits, persistence and load testing for configuration and limits.
The compatibility reference is OpenAI’s speech endpoint. Music routes, native controls and extended formats are local capabilities.
Validation
task test:api checks discovery, schema availability and rejected requests
without generating songs. task check:cpu tests native request translation,
error shapes, PCM layout and pitch-preserving speed limits without weights.
tests/clients/python_client.py and tests/clients/javascript_client.cjs are
explicit live SDK checks using a supplied native request JSON fixture and local
output paths. They generate audio; use a quiet local service and fixed seeds
when checking output against a reference.