MIDI Synthesize Audio
The payoff node — make your edited MIDI JSON actually sing in a reference voice
- prompt_audio
- audio
This is where the pack earns its keep. Every other node edits data; this one produces audio. Feed it the edited MIDI JSON (what you want sung) plus a reference audio clip (whose voice you want it sung in), and SoulX-Singer's flow-matching diffusion model renders actual singing. It's the "魔改歌词" - lyrics-remix - payoff, and honestly the whole reason anyone installs this thing.
Inputs that matter
The two required inputs are the whole show:
- midi_json - the target: lyrics, phonemes, duration, pitch, and f0. Usually the output of MIDI Transcribe Audio → MIDI Edit Lyrics or MIDI Lyrics Alignment.
- prompt_audio - the reference voice that supplies the timbre.
Then the optional ones, roughly in order of how often you'll touch them:
- prompt_metadata - recommended even though it's optional. It's the
midi_jsonfrom running MIDI Transcribe Audio on your reference audio. Leave it blank and the node preprocesses the reference internally, which means re-running the whole pipeline on every single render. Pre-transcribe once, cache the string, reuse. The README also ties this to fixing "mumbled diction" - more on that below. - control -
melody(default) orscore.melodyuses the actual f0 contour, which is right when your target came from a real vocal (lyrics edited from a transcribed song) - you get timbre closer to the reference.scoreuses MIDI note pitches: clearer diction, but further from the reference voice. Pickscorewhen the target is a score or instrumental with no reliable f0. - cfg - classifier-free guidance, default 3.0. In
melodymode, if words get swallowed or the diction turns to mush, raise it toward 4–5 for stronger adherence to the lyric phonemes. Too high and you get over-saturation and artifacts - the author says don't push past 5. - n_steps - flow-matching reverse-diffusion steps, default 32, range 8–128. Higher slightly improves quality and linearly slows you down. Leave it alone.
- use_fp16 - default OFF (FP32), which matches the reference implementation and is safest for quality. Turn ON for autocast speed on GPU if VRAM is tight.
- seed (default 12306), auto_shift (default ON, auto-aligns target pitch to the reference's range), and pitch_shift (global semitone shift, −36 to +36) are the rest. Set seed for reproducible renders, ignore the others unless you know why you're changing them.
Output is a single audio AUDIO - wire it to Save Audio or a preview node.
What it needs installed
The ~2.6 GB Soul-AILab/SoulX-Singer model has to be in ComfyUI/models/, and OpenAI's whisper-base (used as the audio encoder) downloads itself to the HuggingFace cache on first run. Both come down with:
cd ~/App/ComfyUI/models
huggingface-cli download Soul-AILab/SoulX-Singer --local-dir Soul-AILab/SoulX-Singer
If the whole pack fails to load, it's almost always the git submodule: the SoulX-Singer engine is vendored as a submodule and cloning without --recursive leaves SoulX-Singer/ empty. Fix with git submodule update --init --recursive in the custom_nodes folder.
Troubleshooting grounded in the changelog
- Mumbled / unclear diction (口齿不清). The author's fix is the
prompt_metadatapath - transcribe the reference audio once and feed itsmidi_jsonin. If you're still getting mush inmelodymode, nudgecfgto 4–5. - Off-key or "turning into a male voice" in
scoremode. This was a real, fixed bug: ROSVOT occasionally quantizes pitch wrong (up to ~4 semitones) at phrase-ending long notes, and long sentences could blow up token counts and break timbre transfer. Recent releases corrected pitch from f0 and cap sub-note splits per phrase. If you hit it, update the pack.melodymode is unaffected since it uses f0 directly. rescale_cfgisn't a parameter. Right - upstreamSoulXSinger.inferdoesn't expose it, so it's hardcoded at 0.75. Nothing to configure.
And manage expectations: this is 32 steps of diffusion over an entire song. It's not instant, and a full song render is a "go make tea" operation, not a "grab a coffee" one.
Inputs (10)
| Name | Type | Default | Description |
|---|---|---|---|
| midi_json | STRING | — | |
| prompt_audio | AUDIO | — | |
| prompt_metadataopt | STRING | — | |
| controlopt | COMBO | melody | 2 options: melody, score |
| seedopt | INT | 123060–2147483647 | — |
| auto_shiftopt | BOOLEAN | true | — |
| pitch_shiftopt | INT | 0-36–36 | — |
| use_fp16opt | BOOLEAN | false | — |
| cfgopt | FLOAT | 3.01–10 | — |
| n_stepsopt | INT | 328–128 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| audio | AUDIO | — |