Text-to-Audio
Diffusers
Safetensors
PyTorch
minimax_music3
music-generation
text-to-music
sglang-omni
Instructions to use MiniMaxAI/MiniMax-Music3 with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Diffusers
How to use MiniMaxAI/MiniMax-Music3 with Diffusers:
pip install -U diffusers transformers accelerate
import torch from diffusers import DiffusionPipeline # switch to "mps" for apple devices pipe = DiffusionPipeline.from_pretrained("MiniMaxAI/MiniMax-Music3", dtype=torch.bfloat16, device_map="cuda") prompt = "Astronaut in a jungle, cold color palette, muted colors, detailed, 8k" image = pipe(prompt).images[0] - Notebooks
- Google Colab
- Kaggle
Upload scripts/end_to_end/minimax_ttm_test.py with huggingface_hub
Browse files
scripts/end_to_end/minimax_ttm_test.py
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SPDX-License-Identifier: Apache-2.0
|
| 2 |
+
"""Generate a MiniMax Music 3 WAV through the SGLang-Omni HTTP API."""
|
| 3 |
+
|
| 4 |
+
from __future__ import annotations
|
| 5 |
+
|
| 6 |
+
import argparse
|
| 7 |
+
import json
|
| 8 |
+
import urllib.error
|
| 9 |
+
import urllib.request
|
| 10 |
+
from pathlib import Path
|
| 11 |
+
|
| 12 |
+
CAPTION = """Global Metadata
|
| 13 |
+
Basic Attributes: bpm is 92. key is E, and scale is minor. Electric Blues / Blues Rock.
|
| 14 |
+
Global Emotional Progression: The track establishes a confident, gritty swagger from the outset, maintaining a driving, mid-tempo groove throughout. The emotional intensity fluctuates dynamically between the restrained, storytelling verses and the explosive, high-energy instrumental breaks where the lead guitar takes center stage. The song builds tension through call-and-response interactions before releasing it in extended, virtuosic solos, culminating in a frenetic and improvisational outro that fades on a sustained note of raw energy.
|
| 15 |
+
Application Scenarios & Imagery: A smoky, dimly lit blues club late at night, a road trip down a dusty highway in a classic muscle car, or a scene depicting a charismatic character making a bold entrance in a film.
|
| 16 |
+
Sonics & Production Profile: The production favors a live, organic feel with a moderately wide soundstage that places the lead guitar slightly off-center for prominence. The frequency response is warm and mid-range heavy, emphasizing the grit of the guitar tubes and the body of the vocals, while the low end remains tight but not overpowering. The dynamic aesthetic is relatively uncompressed, preserving the natural attack of the drums and the nuances of the guitar playing, giving the mix a "roomy" and authentic atmosphere.
|
| 17 |
+
Vocal Details
|
| 18 |
+
Vocal Gender & Timbre: Singer A (Male). The vocalist possesses a deep, gravelly baritone with a raspy, textured quality that conveys age, experience, and authority.
|
| 19 |
+
Vocal Style: The delivery is conversational and storytelling-oriented, often bordering on spoken-word phrasing in the verses to emphasize the narrative. This shifts into a more melodic, soulful singing style during the refrains, punctuated by energetic ad-libs, shouts, and exclamations that heighten the excitement during instrumental peaks.
|
| 20 |
+
Harmony/Backing Vocals: There are no distinct backing vocalists; however, the lead singer occasionally layers his own voice or utilizes call-and-response phrasing with his guitar to create a dialogue effect, particularly during the bridge and solo sections.
|
| 21 |
+
Vocal FX: The vocal track is treated with a moderate amount of plate reverb to add depth and space, along with a subtle slapback delay that enhances the vintage blues aesthetic without obscuring the lyrical clarity.
|
| 22 |
+
Arrangement
|
| 23 |
+
Instrument Lifecycle Description (Primary/Secondary Layering):
|
| 24 |
+
Primary: A clean-to-slightly-overdriven electric guitar serves as the primary melodic and harmonic driver, present from the Intro to the Outro. It alternates between rhythmic chordal comping and searing, expressive lead lines that dominate the instrumental sections.
|
| 25 |
+
Secondary: A walking electric bass line provides a solid, melodic foundation throughout the entire track, locking tightly with the drums. A Hammond-style organ enters subtly in the background during the verses, swelling in volume during the choruses and solos to add harmonic thickness and warmth.
|
| 26 |
+
Groove & Foundation Progression: A standard acoustic drum kit drives the rhythm with a steady shuffle beat, characterized by a crisp snare on beats 2 and 4 and a swinging hi-hat pattern. The groove remains consistent in tempo but increases in perceived intensity during the solos as the drummer adds more fills and dynamic accents on the crash cymbals.
|
| 27 |
+
Embellishments, Textures & Spatial FX: Occasional guitar slides and string squeals act as transitional flourishes between lyrical phrases. The arrangement features significant use of "space," allowing the instruments to breathe during the verses, which contrasts with the dense, layered texture of the extended guitar solos where the organ and rhythm section push forward to support the lead."""
|
| 28 |
+
|
| 29 |
+
LYRICS = """[verse]
|
| 30 |
+
I’m learning how to fill up
|
| 31 |
+
every space I used to leave,
|
| 32 |
+
teaching my own heart the patience
|
| 33 |
+
that my family needs from me.
|
| 34 |
+
And I’m learning how to soften,
|
| 35 |
+
how to rise above the past—
|
| 36 |
+
Ever’s gonna need a father
|
| 37 |
+
whose love is built to last.
|
| 38 |
+
[pre-chorus]
|
| 39 |
+
Breathe a little deeper,
|
| 40 |
+
love is here to heal.
|
| 41 |
+
Let love lift what used to fall—
|
| 42 |
+
breathe a little deeper, yeah.
|
| 43 |
+
Love is here to heal,
|
| 44 |
+
love is here to heal,
|
| 45 |
+
let love lift what used to fall.
|
| 46 |
+
[verse]
|
| 47 |
+
When I heard your heartbeat for the very first time,
|
| 48 |
+
it broke me open deep inside.
|
| 49 |
+
Pinched my eyes between my fingers,
|
| 50 |
+
’cause that’s when I realized—
|
| 51 |
+
you were healing what was numb in me,
|
| 52 |
+
every beat just whisperin’ “overcome.”
|
| 53 |
+
[pre-chorus]
|
| 54 |
+
Breathe a little deeper,
|
| 55 |
+
love is here to heal.
|
| 56 |
+
Let love lift what used to fall—
|
| 57 |
+
breathe a little deeper, yeah.
|
| 58 |
+
[bass-quartet-rumbles-in]
|
| 59 |
+
Every heartbeat sounded like,
|
| 60 |
+
“We shall overcome, Daddy…
|
| 61 |
+
let’s heal what once was numb.”
|
| 62 |
+
And the joy outran the fear,
|
| 63 |
+
washed away the hurt and pain—
|
| 64 |
+
[pre-chorus]
|
| 65 |
+
Breathe a little deeper,
|
| 66 |
+
love is here to heal.
|
| 67 |
+
Breathe a little deeper,
|
| 68 |
+
love is here to heal.
|
| 69 |
+
Love is here to heal,
|
| 70 |
+
let love lift what used to fall…
|
| 71 |
+
Breathe a little deeper,
|
| 72 |
+
love is here to heal.
|
| 73 |
+
Love is here to heal,
|
| 74 |
+
love is here to heal.
|
| 75 |
+
[bridge]
|
| 76 |
+
Every time I see you wiggling there,
|
| 77 |
+
I’m reminded again and again.
|
| 78 |
+
What keeps playing on repeat
|
| 79 |
+
in my spirit, in my mind,
|
| 80 |
+
is the sound of your heartbeat…
|
| 81 |
+
and I can’t wait to hold you next to mine.
|
| 82 |
+
[interlude]
|
| 83 |
+
You gotta let love— (Oh love… lift us up…)
|
| 84 |
+
Love Lift us up higher—-
|
| 85 |
+
(oh my sweet little Princess Ever Don’t EVER ever ever fear the things you might not yet understand about yourself or father and mother or this world)—
|
| 86 |
+
As long as you let love— Oh love—
|
| 87 |
+
Continue DOing all your heavy lifting Ever-Michelle
|
| 88 |
+
nothing else matters
|
| 89 |
+
when you let love— oh love—
|
| 90 |
+
lift whatever fell or falls…
|
| 91 |
+
[chorus]
|
| 92 |
+
You gotta let love— oh love—Let love—-oh love—-
|
| 93 |
+
Lift what used to fall…
|
| 94 |
+
You gotta let love— oh love—Let love—-oh love—-
|
| 95 |
+
Lift what used to fall…
|
| 96 |
+
You gotta let love— oh love—Let love—-oh love—-
|
| 97 |
+
Lift what used to fall…
|
| 98 |
+
[outro]
|
| 99 |
+
We’re gonna let love stay,
|
| 100 |
+
let our vows endure.
|
| 101 |
+
Oh love… stay… stay…
|
| 102 |
+
We’re gonna let love stay,
|
| 103 |
+
’cause this home is built with love.
|
| 104 |
+
Oh love… stay… stay…
|
| 105 |
+
We’re gonna let love stay,
|
| 106 |
+
let our vows endure—
|
| 107 |
+
this home is made with love,
|
| 108 |
+
and love is here to stay."""
|
| 109 |
+
|
| 110 |
+
|
| 111 |
+
DEFAULT_OUT = Path("minimax_ttm.wav")
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
def build_request_body(*, seed: int, max_frames: int) -> dict[str, object]:
|
| 115 |
+
return {
|
| 116 |
+
"model": "MiniMaxAI/MiniMax-Music3",
|
| 117 |
+
"input": LYRICS,
|
| 118 |
+
"instructions": CAPTION,
|
| 119 |
+
"response_format": "wav",
|
| 120 |
+
"seed": seed,
|
| 121 |
+
"max_new_tokens": max_frames,
|
| 122 |
+
"stream": False,
|
| 123 |
+
}
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def _parser() -> argparse.ArgumentParser:
|
| 127 |
+
parser = argparse.ArgumentParser(description=__doc__)
|
| 128 |
+
parser.add_argument("--server-url", default="http://127.0.0.1:8000")
|
| 129 |
+
parser.add_argument("--out", type=Path, default=DEFAULT_OUT)
|
| 130 |
+
parser.add_argument("--seed", type=int, default=0)
|
| 131 |
+
parser.add_argument("--max-frames", type=int, default=9000)
|
| 132 |
+
parser.add_argument("--timeout", type=float, default=1200)
|
| 133 |
+
return parser
|
| 134 |
+
|
| 135 |
+
|
| 136 |
+
def _post(url: str, body: dict[str, object], timeout: float) -> bytes:
|
| 137 |
+
request = urllib.request.Request(
|
| 138 |
+
url,
|
| 139 |
+
data=json.dumps(body, ensure_ascii=False).encode("utf-8"),
|
| 140 |
+
headers={"Content-Type": "application/json"},
|
| 141 |
+
method="POST",
|
| 142 |
+
)
|
| 143 |
+
try:
|
| 144 |
+
with urllib.request.urlopen(request, timeout=timeout) as response:
|
| 145 |
+
return response.read()
|
| 146 |
+
except urllib.error.HTTPError as exc:
|
| 147 |
+
raise RuntimeError(
|
| 148 |
+
f"HTTP {exc.code}: {exc.read().decode(errors='replace')}"
|
| 149 |
+
) from exc
|
| 150 |
+
except urllib.error.URLError as exc:
|
| 151 |
+
raise RuntimeError(f"cannot connect to {url}: {exc}") from exc
|
| 152 |
+
|
| 153 |
+
|
| 154 |
+
def main() -> int:
|
| 155 |
+
args = _parser().parse_args()
|
| 156 |
+
if args.max_frames < 1:
|
| 157 |
+
raise SystemExit("--max-frames must be positive")
|
| 158 |
+
wav = _post(
|
| 159 |
+
args.server_url.rstrip("/") + "/v1/audio/speech",
|
| 160 |
+
build_request_body(seed=args.seed, max_frames=args.max_frames),
|
| 161 |
+
args.timeout,
|
| 162 |
+
)
|
| 163 |
+
if not wav:
|
| 164 |
+
raise RuntimeError("server returned an empty response")
|
| 165 |
+
output = args.out.expanduser().resolve()
|
| 166 |
+
output.parent.mkdir(parents=True, exist_ok=True)
|
| 167 |
+
output.write_bytes(wav)
|
| 168 |
+
print(f"WAV written to: {output}")
|
| 169 |
+
return 0
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
if __name__ == "__main__":
|
| 173 |
+
raise SystemExit(main())
|