← Tech
▚Tech

YuE2 on 16 GB: Two Patches and One Retracted Finding

Field report: the official yue2-infer runtime versus ComfyUI's nodes — truncation flags, semantic CFG, per-stage timing, and a corrected claim that the model ignores BPM.

TL;DR — Moving YuE2 off ComfyUI and onto the project's own yue2-infer runtime surfaced a truncation flag, a CFG knob and a per-stage receipt that the ComfyUI nodes never expose — and the first thing they proved was that a conclusion I had written down three days earlier was wrong.

A week of local K-pop generation with YuE2 on one RTX 5080 (16 GB), first through ComfyUI's built-in nodes, then rebuilt on the official Python runtime. Reporting date: 15 September 2026. The delta is observability, not audio quality — and observability is what corrected a published finding.

Retraction first: YuE2 follows BPM

Prior finding: the model ignores tempo instructions. That was wrong. Tempo written into the generated score, against the tempo requested in the style prompt, all 28 runs:

Requested in style Written into the score
112 BPM 118
118 BPM 122
124 BPM 128
126 BPM 128–132
132 BPM 132
136 BPM 134
140 BPM 145
144 BPM 140

Mean absolute error 3.5 BPM, monotonic. The failure case that produced the original claim was a prompt containing a range — "128–145" — which yielded a score marked 177. One malformed input, over-generalised. Single integer works.

Capability gap: node graph vs official request

ComfyUI exposes eleven sampling inputs across YuE2GenerateABC and YuE2GenerateMusic. The official request schema carries seven fields: id, style, lyrics, cot, seed, abc, cfg_scale. The gaps are asymmetric.

Capability ComfyUI YuE2 nodes Official yue2-infer 0.1.6
Truncation reporting none truncated.abc and truncated.semantic in result.json
Semantic CFG (cfg_scale) not exposed at all request field; defaults 1.0 for full/melody, 1.01 for off
Conditioning-mode contract a mode string, no rules cot = full / melody / off, each with a documented ABC-input contract
Synthesis steps whatever you set on KSampler (the template ships 20) the release preset is fixed: 32 midpoint steps, context 24576
Per-stage timing none seconds and tokens/s for ABC, semantic, NAR and VAE separately
Reproducibility receipt none weight SHA-256, config hash, request, seed, decoder identity, artifact hashes
Re-decode a finished song not offered latent.npy is saved; swap the decoder without regenerating the music
Memory levers none offload_ar, memory_budget_gib, vae_core_frames, query_chunk_size
Plan round-trip manual string wiring between nodes plan.save() / SymbolicPlan.load() with integrity validation

Assessment: these are instrumentation, not quality. Their absence means a bad result and a misread result are indistinguishable.

Runtime: two patches for 16 GB

Documented baseline is "a BF16-capable NVIDIA GPU with 24GB memory and one active request per pipeline." Two stock failures on 16 GB:

  • USE_FLASH_ATTENTION was not enabled for build. Windows PyTorch wheels ship without the kernel; YuE2's auto-detection tests only for operator existence and a seqused_k schema mention. The operator is registered on Windows, so detection passes and execution fails. Backend is keyword-only and not forwarded by the pipeline — default GraphAR to cuDNN. CUDA graphs retained.
  • NAR OOM, single 3.77 GiB allocation. On CUDA the NAR attention helper sets block size to full query length. Fix: offload_ar (moves the ~6 GB AR model to CPU during synthesis) plus query_chunk_size=2048. Both inside the documented API; mathematically identical splits.

Throughput after the patches, project example: 213.8 s of audio in 238.7 s. ABC 20.5 s, semantic 48.7 s, NAR 161.4 s (68%), VAE 4.0 s. ComfyUI's apparent 4x speed advantage is 20 sampler steps against the release preset's 32.

Signal: truncated resolves the length question

ComfyUI: request 180 s, receive 98 s, no way to distinguish a cut-off song from a finished one. The official runtime writes truncated.abc and truncated.semantic to result.json.

29 runs, both flags false in all 29. Not truncated — finished. Length is a function of lyric volume; the project's 213-second example simply carries more words. One boolean retired a week of speculation and a workaround script.

Language: determined by lyrics, not by the style token

Controlled test — lyrics held fixed, language token varied, automatic transcription measuring detected language and lyric fidelity:

Lyrics Language token in style Language detected Lyric fidelity
Korean Korean Korean, 97% 74%
Korean English Korean, 97% 57%
Korean none Korean, 97% 71%
English English English, 69% 28%
English Korean English, 71% 3%
Korean + English mixed both Korean, 89% 19%

Korean lyrics tagged English still read as Korean at 97% confidence. The mismatch costs fidelity, not language: the English track fell 28% → 3% and degenerated to "Ah, ah, ah." Omitting the token is near-free; the project's showcase example names no language and sings entirely in Chinese. Mixed-language lyrics scored lowest of any condition at 19%.

Notes-per-syllable: bounded on both sides

  • Korean: 185 syllables / 208 notes → 1.12 → faithful (74%)
  • English: 119 syllables / 240 notes → 2.02 → half filled with "oh oh oh" (28%)

Too few notes per syllable produces rapping; too many produce invented vocalisations. Usable band ≈ 1.0–1.3.

Korean lyrics — 1.12 notes per syllable. The written hook is what you hear.
English lyrics — 2.02 notes per syllable. Same model, same settings, same day. Listen to what fills the spare notes.

Candidate selection is part of the published protocol

Documentation, generation page: "One pipeline call produces one candidate. The benchmark's candidate selection is a separate evaluation step." Benchmark page: "Standard YuE2 selects the lower-PER candidate from two generations."

Scores in context: YuE2 best-of-8 6.9632 SongBench average, Suno v5 6.8721, Suno v6 6.5562, unselected YuE2 6.7316. Eight seed-only variations measured here: 0, 31, 44, 45, 50, 57, 66, 70% lyric fidelity. The worst had normal audio — 136 s, normal dynamics and spectrum — and an empty transcript. Audible, unintelligible. A single call samples that distribution blind.

Best of eight (seed 832010) — 70% lyric fidelity.
Worst of eight (seed 836046) — 0%. Identical lyrics, identical style prompt, identical settings. Only the seed differs.

All four clips were generated locally by YuE2 for this write-up, at 128 kbps. Nothing was edited, mixed or re-taken.

FAQ

Can YuE2 run on a 16 GB GPU?

Yes, with two changes. The documented baseline is a 24 GB NVIDIA card, and a stock install fails twice on 16 GB: once because the Windows PyTorch wheel has no FlashAttention kernel, and once because the non-autoregressive synthesis stage feeds its whole query sequence into a single attention call. Forcing the cuDNN attention backend, enabling offload_ar, and chunking the query fixed both without changing the output. A 213.8-second song then took 238.7 seconds end to end.

Does the style prompt control BPM in YuE2?

Yes, if you write a single number. Across 28 runs the tempo written into the generated score tracked the requested BPM with a mean absolute error of 3.5 BPM, monotonically from 112 to 144. A tempo range in the prompt ("128–145") is what breaks it — that produced a score marked 177 BPM.

Why does YuE2 sing "oh oh oh" instead of my lyrics?

Usually because there are more notes in the plan than syllables in the lyrics. In a matched pair, Korean lyrics at 185 syllables over 208 notes (1.12 notes per syllable) were sung faithfully, while English lyrics at 119 syllables over 240 notes (2.02) were half-filled with vocalisations. Aim for roughly 1.0–1.3 notes per syllable.

Should I mix languages in one set of lyrics?

No. In this test the bilingual lyric set scored the lowest fidelity of any condition, 19%, and the transcript degraded at each point where the language switched mid-line.

Is one generation enough?

No. Eight runs that differed only by seed scored 0, 31, 44, 45, 50, 57, 66 and 70% on lyric fidelity. The published benchmark numbers use candidate selection, so a single unselected call is not the same setting.


Sources: YuE2 repository (multimodal-art-projection/YuE), YuE2 generation docs, YuE2 benchmark results, generation and covers reference, m-a-p/YuE2-3B on Hugging Face, WildSongBench dataset.

Image: Johann Ernst Bach, Magnificat autograph manuscript, Public domain, via Wikimedia Commons.

#yue2#comfyui#music-generation#local-ai#pytorch#benchmarks#rtx-5080

← Back to all posts