Spaces:
Running on Zero
Running on Zero
Remove the LLM compose step (Inference Providers cost)
Browse filesLyrics + structured caption are now editable reference nodes wired
directly into generate_song, with the official-guide defaults. Drops the
openai dep, the MiniMax-M3 prompts, OAuth token plumbing, and the
inference-api scope.
- README.md +5 -11
- app.py +5 -67
- requirements.txt +0 -1
- workflow.json +108 -95
README.md
CHANGED
|
@@ -9,25 +9,19 @@ app_file: app.py
|
|
| 9 |
pinned: true
|
| 10 |
suggested_hardware: zero-a10g
|
| 11 |
hf_oauth: true
|
| 12 |
-
hf_oauth_scopes:
|
| 13 |
-
- inference-api
|
| 14 |
---
|
| 15 |
|
| 16 |
# MiniMax Music 3 — diffusers demo as a `gr.Workflow`
|
| 17 |
|
| 18 |
-
Generates full songs from a
|
| 19 |
-
visual, node-based `gr.Workflow` canvas (`workflow.json`):
|
| 20 |
|
| 21 |
-
**
|
| 22 |
prompting guide) → `generate_song` (`@spaces.GPU` ZeroGPU worker: AR frames → windowed DiT decode → vocoder →
|
| 23 |
wav) → Output Song / Seed Used / Stats → `make_video` (CPU ffmpeg visualizer) → Share Video.**
|
| 24 |
|
| 25 |
-
|
| 26 |
-
nodes. `hf_oauth: true` lets the owner edit the canvas; visitors
|
| 27 |
-
`compose_song` LLM step uses the visitor's own OAuth token (`inference-api` scope), so inference bills the
|
| 28 |
-
visitor directly. For logged-out visitors the LLM step is skipped (it's an add-on) and the pipeline
|
| 29 |
-
generates from the built-in demo lyrics + structured caption; set an `HF_TOKEN` secret to let anonymous
|
| 30 |
-
runs use the owner's token instead. The original Blocks app
|
| 31 |
(with the live-streaming PCM player) is preserved as `app_blocks.py` — workflow fn nodes are plain callables,
|
| 32 |
so chunk-by-chunk streaming is replaced by a final audio subject.
|
| 33 |
|
|
|
|
| 9 |
pinned: true
|
| 10 |
suggested_hardware: zero-a10g
|
| 11 |
hf_oauth: true
|
|
|
|
|
|
|
| 12 |
---
|
| 13 |
|
| 14 |
# MiniMax Music 3 — diffusers demo as a `gr.Workflow`
|
| 15 |
|
| 16 |
+
Generates full songs from tagged lyrics + a structured caption using the `MiniMaxMusic3Pipeline` diffusers
|
| 17 |
+
port, presented as a visual, node-based `gr.Workflow` canvas (`workflow.json`):
|
| 18 |
|
| 19 |
+
**Lyrics + Global Metadata + Vocal Details + Arrangement (editable reference nodes, defaults per the official
|
| 20 |
prompting guide) → `generate_song` (`@spaces.GPU` ZeroGPU worker: AR frames → windowed DiT decode → vocoder →
|
| 21 |
wav) → Output Song / Seed Used / Stats → `make_video` (CPU ffmpeg visualizer) → Share Video.**
|
| 22 |
|
| 23 |
+
Duration, seed, randomize-seed, flow-matching steps, guidance scale, and video title are also editable
|
| 24 |
+
reference nodes. `hf_oauth: true` lets the owner edit the canvas; visitors can run the pipeline. The original Blocks app
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
(with the live-streaming PCM player) is preserved as `app_blocks.py` — workflow fn nodes are plain callables,
|
| 26 |
so chunk-by-chunk streaming is replaced by a final audio subject.
|
| 27 |
|
app.py
CHANGED
|
@@ -470,66 +470,6 @@ DEFAULT_ARRANGEMENT = (
|
|
| 470 |
"long, starlit reverb wash."
|
| 471 |
)
|
| 472 |
|
| 473 |
-
_CAPTION_CONTRACT = """The three caption fields follow the exact labeled style the model was trained on. Be concrete and musical; describe an energy arc and instrument lifecycles, never a static equipment list or decorative adjectives. Never contradict an explicit user constraint: instrumental stays instrumental; never reverse a required vocal gender, tempo limit, required instrument, or exclusion. Do not quote or paraphrase lyric lines inside the caption. Total caption length roughly 250-400 words.
|
| 474 |
-
|
| 475 |
-
global_metadata: one paragraph, in order: "Basic Attributes: bpm is <number>. key is <letter>, and scale is <major|minor>. <Genre / Subgenre>." then "Global Emotional Progression: <how the emotion evolves from the opening through the final section>." then "Application Scenarios & Imagery: <two or three vivid listening scenarios>." then "Sonics & Production Profile: <soundstage, frequency balance, dynamics, production character>."
|
| 476 |
-
|
| 477 |
-
vocal_details: one paragraph: "Vocal Gender & Timbre: Singer A (<Male|Female>), <timbre and register>." then "Vocal Style: <delivery, and how it shifts per section>." then "Harmony/Backing Vocals: <where harmonies or doubles appear and their character>." then "Vocal FX: <restrained treatment: reverb, delay, light compression>." For instrumental pieces write "Instrumental, no vocals." and name the instrument or texture carrying the lead melodic role.
|
| 478 |
-
|
| 479 |
-
arrangement: one paragraph: "Instrument Lifecycle Description (Primary/Secondary Layering): Primary: <core instruments present start to finish and their role>. Secondary: <instruments that enter, exit or intensify, and in which sections>." then "Groove & Foundation Progression: <how drums, bass and groove develop across sections>." then "Embellishments, Textures & Spatial FX: <fills, textures, transitional gestures, stereo and space treatment where relevant>." State what enters, exits, changes or intensifies for every section of the song, aligned with the lyric section tags."""
|
| 480 |
-
|
| 481 |
-
_LYRICS_RULES = """lyrics: singable lyrics using ONLY these section tags, each ALWAYS ALONE on its own line: [intro] [verse] [pre-chorus] [chorus] [post-chorus] [bridge] [instrumental] [solo] [outro]. Never put words on the same line as a tag. Size the structure to the duration: <=30s: one verse + one chorus; ~60s: verse/pre-chorus/chorus/verse/chorus; >=120s: full structure with bridge and outro. Roughly 12-16 sung words per 10 seconds. Musical instructions (tempo, instruments, dynamics) never belong in the lyrics. If the song is instrumental, use [instrumental] sections with no words."""
|
| 482 |
-
|
| 483 |
-
_COMPOSER_SYSTEM = f"""You write inputs for MiniMax Music 3, a lyrics+description music generation model.
|
| 484 |
-
Given a song description and a target duration, produce:
|
| 485 |
-
1. {_LYRICS_RULES}
|
| 486 |
-
2-4. global_metadata, vocal_details, arrangement — a structured caption. {_CAPTION_CONTRACT}
|
| 487 |
-
Answer with ONLY a JSON object with keys: lyrics, global_metadata, vocal_details, arrangement."""
|
| 488 |
-
|
| 489 |
-
_LYRICS_SYSTEM = f"""You write lyrics for MiniMax Music 3, a lyrics+description music generation model.
|
| 490 |
-
Given a lyrics instruction, the current structured prompt (global metadata, vocal details, arrangement) and a target duration, write lyrics coherent with that structured prompt.
|
| 491 |
-
{_LYRICS_RULES}
|
| 492 |
-
Answer with ONLY a JSON object with key: lyrics."""
|
| 493 |
-
|
| 494 |
-
_PROMPT_SYSTEM = f"""You write the structured caption for MiniMax Music 3, a lyrics+description music generation model.
|
| 495 |
-
Given a sound instruction and/or lyrics, produce global_metadata, vocal_details and arrangement. Build the arrangement timeline around the lyric section tags when lyrics are provided. {_CAPTION_CONTRACT}
|
| 496 |
-
Answer with ONLY a JSON object with keys: global_metadata, vocal_details, arrangement."""
|
| 497 |
-
|
| 498 |
-
|
| 499 |
-
def _llm_json(system, user, token=None):
|
| 500 |
-
import json as _json
|
| 501 |
-
|
| 502 |
-
from openai import OpenAI
|
| 503 |
-
|
| 504 |
-
# Prefer the visitor's OAuth token (hf_oauth + inference-api scope bills the visitor
|
| 505 |
-
# directly); fall back to the Space owner's HF_TOKEN secret for local/anonymous runs.
|
| 506 |
-
api_key = getattr(token, "token", None) or os.environ.get("HF_TOKEN")
|
| 507 |
-
if not api_key:
|
| 508 |
-
return None # logged-out visitor, no owner secret: caller skips the LLM step
|
| 509 |
-
client = OpenAI(base_url="https://router.huggingface.co/v1", api_key=api_key)
|
| 510 |
-
completion = client.chat.completions.create(
|
| 511 |
-
model="MiniMaxAI/MiniMax-M3:fastest",
|
| 512 |
-
messages=[{"role": "system", "content": system}, {"role": "user", "content": user}],
|
| 513 |
-
)
|
| 514 |
-
text = completion.choices[0].message.content.strip()
|
| 515 |
-
if text.startswith("```"):
|
| 516 |
-
text = text.split("```")[1].removeprefix("json").strip()
|
| 517 |
-
return _json.loads(text)
|
| 518 |
-
|
| 519 |
-
|
| 520 |
-
def compose_song(description, duration, token: gr.OAuthToken = None):
|
| 521 |
-
# `token` is injected by gr.Workflow (OAuthToken params are excluded from the canvas
|
| 522 |
-
# ports and filled with the signed-in visitor's OAuth token at run time).
|
| 523 |
-
if not description.strip():
|
| 524 |
-
raise gr.Error("Describe the song you want first.")
|
| 525 |
-
data = _llm_json(_COMPOSER_SYSTEM, f"Song description: {description}\nTarget duration: {int(duration)} seconds.", token)
|
| 526 |
-
if data is None:
|
| 527 |
-
# No OAuth token (logged out) and no HF_TOKEN secret: the LLM compose step is an
|
| 528 |
-
# add-on — skip it and generate from the built-in demo lyrics + structured caption.
|
| 529 |
-
return DEFAULT_LYRICS, DEFAULT_GLOBAL, DEFAULT_VOCALS, DEFAULT_ARRANGEMENT
|
| 530 |
-
return data["lyrics"], data["global_metadata"], data["vocal_details"], data["arrangement"]
|
| 531 |
-
|
| 532 |
-
|
| 533 |
def render_video(wav_path, title):
|
| 534 |
# Social share visualizer: warm citrus bars on a dark gradient, rendered via numpy -> ffmpeg pipe (CPU).
|
| 535 |
if not wav_path:
|
|
@@ -637,13 +577,12 @@ def render_video(wav_path, title):
|
|
| 637 |
|
| 638 |
|
| 639 |
# ---------------------------------------------------------------------------
|
| 640 |
-
# gr.Workflow app. The canvas (workflow.json) wires
|
| 641 |
-
# compose_song — MiniMax-M3 LLM writes lyrics + structured caption from a one-line idea
|
| 642 |
# generate_song — @spaces.GPU ZeroGPU worker: AR frames -> windowed DiT decode -> vocoder -> wav
|
| 643 |
# make_video — CPU ffmpeg visualizer for the share video
|
| 644 |
-
#
|
| 645 |
-
#
|
| 646 |
-
#
|
| 647 |
# ---------------------------------------------------------------------------
|
| 648 |
|
| 649 |
import tempfile
|
|
@@ -677,7 +616,7 @@ def _friendly_gpu_error(err):
|
|
| 677 |
def _generate_song_gpu(lyrics, global_meta, vocal_details, arrangement, duration, seed, randomize_seed, steps, guidance):
|
| 678 |
caption = "\n".join(s.strip() for s in (global_meta, vocal_details, arrangement) if s and s.strip())
|
| 679 |
if not caption:
|
| 680 |
-
raise gr.Error("Fill in the structured prompt (
|
| 681 |
if not lyrics or not lyrics.strip():
|
| 682 |
raise gr.Error("Lyrics are required (section tags like [verse] must be on their own line).")
|
| 683 |
if randomize_seed:
|
|
@@ -751,7 +690,6 @@ def make_video(audio, title: str):
|
|
| 751 |
demo = gr.Workflow(
|
| 752 |
graph="workflow.json",
|
| 753 |
bind={
|
| 754 |
-
"compose_song": compose_song,
|
| 755 |
"generate_song": generate_song,
|
| 756 |
"make_video": make_video,
|
| 757 |
},
|
|
|
|
| 470 |
"long, starlit reverb wash."
|
| 471 |
)
|
| 472 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 473 |
def render_video(wav_path, title):
|
| 474 |
# Social share visualizer: warm citrus bars on a dark gradient, rendered via numpy -> ffmpeg pipe (CPU).
|
| 475 |
if not wav_path:
|
|
|
|
| 577 |
|
| 578 |
|
| 579 |
# ---------------------------------------------------------------------------
|
| 580 |
+
# gr.Workflow app. The canvas (workflow.json) wires two fn operators:
|
|
|
|
| 581 |
# generate_song — @spaces.GPU ZeroGPU worker: AR frames -> windowed DiT decode -> vocoder -> wav
|
| 582 |
# make_video — CPU ffmpeg visualizer for the share video
|
| 583 |
+
# Lyrics + structured caption are editable reference nodes (defaults from the official
|
| 584 |
+
# prompting guide). Workflow fn nodes are plain callables (no streaming), so the live PCM
|
| 585 |
+
# player of the Blocks version becomes a final audio subject.
|
| 586 |
# ---------------------------------------------------------------------------
|
| 587 |
|
| 588 |
import tempfile
|
|
|
|
| 616 |
def _generate_song_gpu(lyrics, global_meta, vocal_details, arrangement, duration, seed, randomize_seed, steps, guidance):
|
| 617 |
caption = "\n".join(s.strip() for s in (global_meta, vocal_details, arrangement) if s and s.strip())
|
| 618 |
if not caption:
|
| 619 |
+
raise gr.Error("Fill in the structured prompt (Global metadata / Vocal details / Arrangement) first.")
|
| 620 |
if not lyrics or not lyrics.strip():
|
| 621 |
raise gr.Error("Lyrics are required (section tags like [verse] must be on their own line).")
|
| 622 |
if randomize_seed:
|
|
|
|
| 690 |
demo = gr.Workflow(
|
| 691 |
graph="workflow.json",
|
| 692 |
bind={
|
|
|
|
| 693 |
"generate_song": generate_song,
|
| 694 |
"make_video": make_video,
|
| 695 |
},
|
requirements.txt
CHANGED
|
@@ -3,4 +3,3 @@ transformers
|
|
| 3 |
accelerate
|
| 4 |
scipy
|
| 5 |
spaces
|
| 6 |
-
openai
|
|
|
|
| 3 |
accelerate
|
| 4 |
scipy
|
| 5 |
spaces
|
|
|
workflow.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
| 1 |
{
|
| 2 |
"schema_version": "2",
|
| 3 |
"name": "MiniMax Music 3",
|
| 4 |
-
"description": "Full-song generation with MiniMax Music 3 on ZeroGPU:
|
| 5 |
"runtime": {
|
| 6 |
"default": "client"
|
| 7 |
},
|
|
@@ -10,30 +10,111 @@
|
|
| 10 |
},
|
| 11 |
"references": [
|
| 12 |
{
|
| 13 |
-
"id": "
|
| 14 |
-
"label": "
|
| 15 |
"role": "reference",
|
| 16 |
"asset_type": "text",
|
| 17 |
"inputs": [
|
| 18 |
{
|
| 19 |
"id": "in",
|
| 20 |
-
"label": "
|
| 21 |
"type": "text"
|
| 22 |
}
|
| 23 |
],
|
| 24 |
"outputs": [
|
| 25 |
{
|
| 26 |
"id": "out",
|
| 27 |
-
"label": "
|
| 28 |
"type": "text"
|
| 29 |
}
|
| 30 |
],
|
| 31 |
"x": 40,
|
| 32 |
-
"y":
|
| 33 |
-
"width":
|
| 34 |
-
"height":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
"data": {
|
| 36 |
-
"out": "a
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 37 |
}
|
| 38 |
},
|
| 39 |
{
|
|
@@ -56,7 +137,7 @@
|
|
| 56 |
}
|
| 57 |
],
|
| 58 |
"x": 40,
|
| 59 |
-
"y":
|
| 60 |
"width": 200,
|
| 61 |
"height": 90,
|
| 62 |
"data": {
|
|
@@ -82,8 +163,8 @@
|
|
| 82 |
"type": "number"
|
| 83 |
}
|
| 84 |
],
|
| 85 |
-
"x":
|
| 86 |
-
"y":
|
| 87 |
"width": 200,
|
| 88 |
"height": 90,
|
| 89 |
"data": {
|
|
@@ -110,7 +191,7 @@
|
|
| 110 |
}
|
| 111 |
],
|
| 112 |
"x": 40,
|
| 113 |
-
"y":
|
| 114 |
"width": 200,
|
| 115 |
"height": 90,
|
| 116 |
"data": {
|
|
@@ -136,8 +217,8 @@
|
|
| 136 |
"type": "number"
|
| 137 |
}
|
| 138 |
],
|
| 139 |
-
"x":
|
| 140 |
-
"y":
|
| 141 |
"width": 200,
|
| 142 |
"height": 90,
|
| 143 |
"data": {
|
|
@@ -164,7 +245,7 @@
|
|
| 164 |
}
|
| 165 |
],
|
| 166 |
"x": 40,
|
| 167 |
-
"y":
|
| 168 |
"width": 200,
|
| 169 |
"height": 90,
|
| 170 |
"data": {
|
|
@@ -200,58 +281,6 @@
|
|
| 200 |
}
|
| 201 |
],
|
| 202 |
"operators": [
|
| 203 |
-
{
|
| 204 |
-
"id": "op_compose",
|
| 205 |
-
"label": "compose_song",
|
| 206 |
-
"role": "operator",
|
| 207 |
-
"kind": "fn",
|
| 208 |
-
"source": "fn",
|
| 209 |
-
"fn": "compose_song",
|
| 210 |
-
"inputs": [
|
| 211 |
-
{
|
| 212 |
-
"id": "in_0",
|
| 213 |
-
"label": "description",
|
| 214 |
-
"type": "text",
|
| 215 |
-
"required": true
|
| 216 |
-
},
|
| 217 |
-
{
|
| 218 |
-
"id": "in_1",
|
| 219 |
-
"label": "duration",
|
| 220 |
-
"type": "number"
|
| 221 |
-
}
|
| 222 |
-
],
|
| 223 |
-
"outputs": [
|
| 224 |
-
{
|
| 225 |
-
"id": "out_0",
|
| 226 |
-
"label": "lyrics",
|
| 227 |
-
"type": "text",
|
| 228 |
-
"output_index": 0
|
| 229 |
-
},
|
| 230 |
-
{
|
| 231 |
-
"id": "out_1",
|
| 232 |
-
"label": "global_metadata",
|
| 233 |
-
"type": "text",
|
| 234 |
-
"output_index": 1
|
| 235 |
-
},
|
| 236 |
-
{
|
| 237 |
-
"id": "out_2",
|
| 238 |
-
"label": "vocal_details",
|
| 239 |
-
"type": "text",
|
| 240 |
-
"output_index": 2
|
| 241 |
-
},
|
| 242 |
-
{
|
| 243 |
-
"id": "out_3",
|
| 244 |
-
"label": "arrangement",
|
| 245 |
-
"type": "text",
|
| 246 |
-
"output_index": 3
|
| 247 |
-
}
|
| 248 |
-
],
|
| 249 |
-
"x": 380,
|
| 250 |
-
"y": 150,
|
| 251 |
-
"width": 260,
|
| 252 |
-
"height": 180,
|
| 253 |
-
"data": {}
|
| 254 |
-
},
|
| 255 |
{
|
| 256 |
"id": "op_generate",
|
| 257 |
"label": "generate_song",
|
|
@@ -327,8 +356,8 @@
|
|
| 327 |
"output_index": 2
|
| 328 |
}
|
| 329 |
],
|
| 330 |
-
"x":
|
| 331 |
-
"y":
|
| 332 |
"width": 280,
|
| 333 |
"height": 300,
|
| 334 |
"data": {}
|
|
@@ -471,56 +500,40 @@
|
|
| 471 |
}
|
| 472 |
],
|
| 473 |
"edges": [
|
| 474 |
-
{
|
| 475 |
-
"id": "e_desc",
|
| 476 |
-
"from_node_id": "ref_description",
|
| 477 |
-
"from_port_id": "out",
|
| 478 |
-
"to_node_id": "op_compose",
|
| 479 |
-
"to_port_id": "in_0",
|
| 480 |
-
"type": "text"
|
| 481 |
-
},
|
| 482 |
-
{
|
| 483 |
-
"id": "e_dur_c",
|
| 484 |
-
"from_node_id": "ref_duration",
|
| 485 |
-
"from_port_id": "out",
|
| 486 |
-
"to_node_id": "op_compose",
|
| 487 |
-
"to_port_id": "in_1",
|
| 488 |
-
"type": "number"
|
| 489 |
-
},
|
| 490 |
{
|
| 491 |
"id": "e_lyr",
|
| 492 |
-
"from_node_id": "
|
| 493 |
-
"from_port_id": "
|
| 494 |
"to_node_id": "op_generate",
|
| 495 |
"to_port_id": "in_0",
|
| 496 |
"type": "text"
|
| 497 |
},
|
| 498 |
{
|
| 499 |
"id": "e_gm",
|
| 500 |
-
"from_node_id": "
|
| 501 |
-
"from_port_id": "
|
| 502 |
"to_node_id": "op_generate",
|
| 503 |
"to_port_id": "in_1",
|
| 504 |
"type": "text"
|
| 505 |
},
|
| 506 |
{
|
| 507 |
"id": "e_vd",
|
| 508 |
-
"from_node_id": "
|
| 509 |
-
"from_port_id": "
|
| 510 |
"to_node_id": "op_generate",
|
| 511 |
"to_port_id": "in_2",
|
| 512 |
"type": "text"
|
| 513 |
},
|
| 514 |
{
|
| 515 |
"id": "e_arr",
|
| 516 |
-
"from_node_id": "
|
| 517 |
-
"from_port_id": "
|
| 518 |
"to_node_id": "op_generate",
|
| 519 |
"to_port_id": "in_3",
|
| 520 |
"type": "text"
|
| 521 |
},
|
| 522 |
{
|
| 523 |
-
"id": "
|
| 524 |
"from_node_id": "ref_duration",
|
| 525 |
"from_port_id": "out",
|
| 526 |
"to_node_id": "op_generate",
|
|
|
|
| 1 |
{
|
| 2 |
"schema_version": "2",
|
| 3 |
"name": "MiniMax Music 3",
|
| 4 |
+
"description": "Full-song generation with MiniMax Music 3 on ZeroGPU: tagged lyrics + a structured caption (Global metadata / Vocal details / Arrangement, per the official prompting guide) feed the diffusers pipeline (AR frames -> windowed DiT decode -> vocoder), plus an ffmpeg share-video visualizer. Edit the Lyrics and caption reference nodes to shape the song.",
|
| 5 |
"runtime": {
|
| 6 |
"default": "client"
|
| 7 |
},
|
|
|
|
| 10 |
},
|
| 11 |
"references": [
|
| 12 |
{
|
| 13 |
+
"id": "ref_lyrics",
|
| 14 |
+
"label": "Lyrics",
|
| 15 |
"role": "reference",
|
| 16 |
"asset_type": "text",
|
| 17 |
"inputs": [
|
| 18 |
{
|
| 19 |
"id": "in",
|
| 20 |
+
"label": "Lyrics",
|
| 21 |
"type": "text"
|
| 22 |
}
|
| 23 |
],
|
| 24 |
"outputs": [
|
| 25 |
{
|
| 26 |
"id": "out",
|
| 27 |
+
"label": "Lyrics",
|
| 28 |
"type": "text"
|
| 29 |
}
|
| 30 |
],
|
| 31 |
"x": 40,
|
| 32 |
+
"y": 80,
|
| 33 |
+
"width": 300,
|
| 34 |
+
"height": 200,
|
| 35 |
+
"data": {
|
| 36 |
+
"out": "[intro]\n\n[verse]\nRiding on a beam of light tonight\nEvery little star is burning bright\n[pre-chorus]\nHold your breath, the sky is opening\n[chorus]\nWe are made of sound and time\nEvery heartbeat keeps the rhyme\n[outro]"
|
| 37 |
+
}
|
| 38 |
+
},
|
| 39 |
+
{
|
| 40 |
+
"id": "ref_global",
|
| 41 |
+
"label": "Global Metadata",
|
| 42 |
+
"role": "reference",
|
| 43 |
+
"asset_type": "text",
|
| 44 |
+
"inputs": [
|
| 45 |
+
{
|
| 46 |
+
"id": "in",
|
| 47 |
+
"label": "Global Metadata",
|
| 48 |
+
"type": "text"
|
| 49 |
+
}
|
| 50 |
+
],
|
| 51 |
+
"outputs": [
|
| 52 |
+
{
|
| 53 |
+
"id": "out",
|
| 54 |
+
"label": "Global Metadata",
|
| 55 |
+
"type": "text"
|
| 56 |
+
}
|
| 57 |
+
],
|
| 58 |
+
"x": 40,
|
| 59 |
+
"y": 310,
|
| 60 |
+
"width": 300,
|
| 61 |
+
"height": 160,
|
| 62 |
+
"data": {
|
| 63 |
+
"out": "Basic Attributes: bpm is 120. key is C, and scale is major. Synth-Pop / Electropop. Global Emotional Progression: The track opens in shimmering anticipation, a filtered pulse like city lights coming on at dusk. The verse glides forward with hopeful momentum, the pre-chorus holds its breath as the arrangement tightens and rises, and the chorus bursts open into wide-screen euphoria \u2014 bright, weightless, celebratory. The outro drifts back down into a starry afterglow, ending on air and quiet wonder. Application Scenarios & Imagery: a night drive under neon overpasses with the windows down; a planetarium dome igniting as the lights dim; a rooftop countdown at midnight. Sonics & Production Profile: a polished, modern pop mix with a wide stereo image \u2014 airy sparkling highs, present mid-range vocals, and a tight, punchy low end; side-chained compression gives the chorus a gentle pumping lift, and the outro dissolves into long reverb tails."
|
| 64 |
+
}
|
| 65 |
+
},
|
| 66 |
+
{
|
| 67 |
+
"id": "ref_vocals",
|
| 68 |
+
"label": "Vocal Details",
|
| 69 |
+
"role": "reference",
|
| 70 |
+
"asset_type": "text",
|
| 71 |
+
"inputs": [
|
| 72 |
+
{
|
| 73 |
+
"id": "in",
|
| 74 |
+
"label": "Vocal Details",
|
| 75 |
+
"type": "text"
|
| 76 |
+
}
|
| 77 |
+
],
|
| 78 |
+
"outputs": [
|
| 79 |
+
{
|
| 80 |
+
"id": "out",
|
| 81 |
+
"label": "Vocal Details",
|
| 82 |
+
"type": "text"
|
| 83 |
+
}
|
| 84 |
+
],
|
| 85 |
+
"x": 40,
|
| 86 |
+
"y": 500,
|
| 87 |
+
"width": 300,
|
| 88 |
+
"height": 140,
|
| 89 |
"data": {
|
| 90 |
+
"out": "Vocal Gender & Timbre: Singer A (Female), a warm mezzo-soprano with an intimate, breathy texture in her low register and a clear, ringing brightness when she lifts. Vocal Style: soft and close-miked through the verse, phrasing like a secret; the pre-chorus rises with held, urgent notes, and the chorus opens into a confident, soaring belt with sustained tones riding the beat; over the outro she dissolves into wordless, airy ad-libs echoing the chorus melody. Harmony/Backing Vocals: a single ghost double shadows the pre-chorus; stacked parallel harmonies in thirds widen the chorus into a glowing wall; the verse stays solo and intimate. Vocal FX: light plate reverb throughout, tempo-synced delay throws on chorus line endings, subtle saturation for chorus presence, and a longer, washier reverb on the outro ad-libs."
|
| 91 |
+
}
|
| 92 |
+
},
|
| 93 |
+
{
|
| 94 |
+
"id": "ref_arrangement",
|
| 95 |
+
"label": "Arrangement",
|
| 96 |
+
"role": "reference",
|
| 97 |
+
"asset_type": "text",
|
| 98 |
+
"inputs": [
|
| 99 |
+
{
|
| 100 |
+
"id": "in",
|
| 101 |
+
"label": "Arrangement",
|
| 102 |
+
"type": "text"
|
| 103 |
+
}
|
| 104 |
+
],
|
| 105 |
+
"outputs": [
|
| 106 |
+
{
|
| 107 |
+
"id": "out",
|
| 108 |
+
"label": "Arrangement",
|
| 109 |
+
"type": "text"
|
| 110 |
+
}
|
| 111 |
+
],
|
| 112 |
+
"x": 40,
|
| 113 |
+
"y": 670,
|
| 114 |
+
"width": 300,
|
| 115 |
+
"height": 160,
|
| 116 |
+
"data": {
|
| 117 |
+
"out": "Instrument Lifecycle Description (Primary/Secondary Layering): Primary: a round, side-chained analog-style synth bass anchors the harmony from the first verse through the chorus, under a soft pad bed that opens the intro and never fully leaves. Secondary: a shimmering arpeggio enters at the pre-chorus and runs through the chorus; wide analog pads and a bright synth counter-melody appear only in the chorus to lift it; a sparse felt piano takes over the outro as the synths fall away. Groove & Foundation Progression: the intro pulses on a filtered four-on-the-floor kick; the verse keeps drums minimal \u2014 kick, soft clap, ticking closed hat; the pre-chorus adds open hats and a rising snare build, and the chorus lands with the full kit: punchy kick on every beat, layered claps, driving crash accents. After the chorus the drums drop out entirely, leaving piano, pad, and air for the outro. Embellishments, Textures & Spatial FX: a white-noise riser and reverse swell launch the chorus; glittering bell accents answer the vocal there; and the final piano chord rings into a long, starlit reverb wash."
|
| 118 |
}
|
| 119 |
},
|
| 120 |
{
|
|
|
|
| 137 |
}
|
| 138 |
],
|
| 139 |
"x": 40,
|
| 140 |
+
"y": 860,
|
| 141 |
"width": 200,
|
| 142 |
"height": 90,
|
| 143 |
"data": {
|
|
|
|
| 163 |
"type": "number"
|
| 164 |
}
|
| 165 |
],
|
| 166 |
+
"x": 260,
|
| 167 |
+
"y": 860,
|
| 168 |
"width": 200,
|
| 169 |
"height": 90,
|
| 170 |
"data": {
|
|
|
|
| 191 |
}
|
| 192 |
],
|
| 193 |
"x": 40,
|
| 194 |
+
"y": 980,
|
| 195 |
"width": 200,
|
| 196 |
"height": 90,
|
| 197 |
"data": {
|
|
|
|
| 217 |
"type": "number"
|
| 218 |
}
|
| 219 |
],
|
| 220 |
+
"x": 260,
|
| 221 |
+
"y": 980,
|
| 222 |
"width": 200,
|
| 223 |
"height": 90,
|
| 224 |
"data": {
|
|
|
|
| 245 |
}
|
| 246 |
],
|
| 247 |
"x": 40,
|
| 248 |
+
"y": 1100,
|
| 249 |
"width": 200,
|
| 250 |
"height": 90,
|
| 251 |
"data": {
|
|
|
|
| 281 |
}
|
| 282 |
],
|
| 283 |
"operators": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 284 |
{
|
| 285 |
"id": "op_generate",
|
| 286 |
"label": "generate_song",
|
|
|
|
| 356 |
"output_index": 2
|
| 357 |
}
|
| 358 |
],
|
| 359 |
+
"x": 560,
|
| 360 |
+
"y": 400,
|
| 361 |
"width": 280,
|
| 362 |
"height": 300,
|
| 363 |
"data": {}
|
|
|
|
| 500 |
}
|
| 501 |
],
|
| 502 |
"edges": [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 503 |
{
|
| 504 |
"id": "e_lyr",
|
| 505 |
+
"from_node_id": "ref_lyrics",
|
| 506 |
+
"from_port_id": "out",
|
| 507 |
"to_node_id": "op_generate",
|
| 508 |
"to_port_id": "in_0",
|
| 509 |
"type": "text"
|
| 510 |
},
|
| 511 |
{
|
| 512 |
"id": "e_gm",
|
| 513 |
+
"from_node_id": "ref_global",
|
| 514 |
+
"from_port_id": "out",
|
| 515 |
"to_node_id": "op_generate",
|
| 516 |
"to_port_id": "in_1",
|
| 517 |
"type": "text"
|
| 518 |
},
|
| 519 |
{
|
| 520 |
"id": "e_vd",
|
| 521 |
+
"from_node_id": "ref_vocals",
|
| 522 |
+
"from_port_id": "out",
|
| 523 |
"to_node_id": "op_generate",
|
| 524 |
"to_port_id": "in_2",
|
| 525 |
"type": "text"
|
| 526 |
},
|
| 527 |
{
|
| 528 |
"id": "e_arr",
|
| 529 |
+
"from_node_id": "ref_arrangement",
|
| 530 |
+
"from_port_id": "out",
|
| 531 |
"to_node_id": "op_generate",
|
| 532 |
"to_port_id": "in_3",
|
| 533 |
"type": "text"
|
| 534 |
},
|
| 535 |
{
|
| 536 |
+
"id": "e_dur",
|
| 537 |
"from_node_id": "ref_duration",
|
| 538 |
"from_port_id": "out",
|
| 539 |
"to_node_id": "op_generate",
|