拆解 MusicGen:Meta 开源音乐大模型,到底是怎么跑起来的?

跑完 model.generate() 那段代码,听到 AI 根据"80s synth pop with bassy drums and synth"生成的音乐时,我第一反应是:这东西底层到底是什么逻辑?花了一天时间扒源码,把整个流程清楚了。

一、MusicGen 是什么?

简单说:输入一段文字,输出一段音乐。

Meta(原 Facebook)2023 年开源的,核心架构就三块:

  1. T5 文本编码器:把你写的 prompt 转成 embedding
  2. MusicGen Transformer:自回归生成音频 token
  3. EnCodec 解码器:把 token 变回音频波形

整个流程跟 GPT 写文章一模一样,只不过 GPT 输出的是文字 token,MusicGen 输出的是音频 token。


二、架构长什么样?

先看图:

文本 Prompt ──→ T5 编码器 ──→ 文本 embedding

MusicGen Transformer

(自回归生成 4 个并行的音频 token 流)

EnCodec 解码器

32kHz 音频 (.wav)

几个关键参数:

组件 架构 参数量 输入 输出
MusicGen Transformer Decoder 0.3B-3.3B 文本 embedding 音频 token(4 码本)
T5/Flan-T5 Encoder-only 0.2B-3B 文本 文本 embedding
EnCodec CNN + RVQ - 音频 token 32kHz 音频

这里有个细节:4 个码本(codebook)

还记得上一章手搓的 Music Transformer 吗?也是多 codebook 的。MusicGen 用 4 个并行的 token 流来表示一个时间步的音频,分别对应不同的频率层。这不是拍脑袋定的,是 EnCodec 的 RVQ 量化器天然就输出多层 token。


三、环境搭建:5 分钟跑起来

我用的是魔搭社区(ModelScope),注册个账号就能用免费 GPU。

步骤 1:装依赖

pip install --upgrade pip

pip install --upgrade transformers scipy

pip install torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 --index-url https://download.pytorch.org/whl/cpu

如果用 GPU 环境,直接选预装 torch>=2.6.0 的镜像就行,不用手动装。

步骤 2:加载模型

from modelscope import AutoProcessor, MusicgenForConditionalGeneration

processor = AutoProcessor.from_pretrained("facebook/musicgen-large")

model = MusicgenForConditionalGeneration.from_pretrained("facebook/musicgen-large")

这里有个坑:第一次加载会下载模型权重,musicgen-large 大概 12GB ,得等一会儿。如果网络慢,可以考虑用 musicgen-small(1.2GB)先跑通流程。

步骤 3:生成音乐

prompt = "80s pop track with bassy drums and synth"

tokens = 256

inputs = processor(

text=prompt,

padding=True,

return_tensors="pt",

)

audio_values = model.generate(**inputs, max_new_tokens=tokens)

tokens 控制生成长度,最大 1500,对应约 30 秒音乐。我试了 256,大概 5-6 秒。

步骤 4:听 + 保存

from IPython.display import Audio

from scipy.io import wavfile

sampling_rate = model.config.audio_encoder.sampling_rate

在线听

Audio(audio_values[0], rate=sampling_rate)

保存到文件

wavfile.write("musicgen_out.wav", rate=sampling_rate, data=audio_values.numpy())

跑完就能听到 AI 写的 80 年代合成器流行曲了。说实话,第一次听到生成的鼓点和贝斯时,我愣了几秒------这玩意儿居然真的能听懂"bassy drums"。


四、源码拆解:底层到底在干嘛?

扒了 audiocraft/models/musicgen.py,整个流程比我想象的干净。

1. 模型初始化

class MusicGen(BaseGenModel):

def init(self, name: str, compression_model: CompressionModel,

lm: LMModel, max_duration: tp.Optional[float] = None):

super().init(name, compression_model, lm, max_duration)

self.set_generation_params(duration=15) # 默认生成 15 秒

继承自 BaseGenModel,核心就三个东西:

  • compression_model:EnCodec,负责编解码音频 token
  • lm:Language Model,就是那个 Transformer Decoder
  • max_duration:单次最大生成时长

加载预训练模型直接用静态方法:

model = MusicGen.get_pretrained("facebook/musicgen-small")

这个方法会干三件事:

  1. 从 HuggingFace 下载 LM 权重
  2. 下载 EnCodec 权重
  3. 如果是 melody 模型,会特殊处理 self_wav 条件器(推理时对齐长度、关掉训练时的 mask)

2. 生成参数配置

model.set_generation_params(

use_sampling=True,

top_k=250,

top_p=0.0,

temperature=1.0,

duration=30.0,

cfg_coef=3.0,

extend_stride=18

)

这几个参数得拆开说:

temperature(温度):控制随机性。1.0 是默认,调高到 1.5 会更"疯",调到 0.5 会更保守。

top_k:每一步只在概率最高的 250 个 token 里采样。不设的话就是全词表(1024 个)里采,容易出奇怪的东西。

top_p:核采样。设 0.9 就是只在前 90% 累积概率的 token 里采。跟 top_k 二选一就行。

cfg_coef(Classifier-Free Guidance 系数):这个最有意思。


五、CFG 在自回归模型里怎么玩?

CFG 原本是 Diffusion 模型的技术,MusicGen 把它搬到了 Transformer 自回归生成里。

核心公式:

logits = uncond + cfg_coef * (cond - uncond)

翻译成人话:

  • cond:带文本 prompt 跑出来的 logits
  • uncond:空文本("")跑出来的 logits
  • cond - uncond:文本带来的"改变方向"
  • cfg_coef:放大这个改变方向的强度

举个例子:

prompt = "epic orchestral battle music"

  • cond logits:模型看到这个 prompt,倾向于生成史诗交响乐
  • uncond logits:模型啥提示都没有,按"音乐统计规律"瞎生成
  • cond - uncond:史诗感 - 随机感 = 史诗感的方向
  • cfg_coef=3.0:把这个方向放大 3 倍

效果:

  • cfg_coef 越大,越贴近文本描述,但音质可能变差(过度拟合 prompt)
  • cfg_coef 越小,越"自由发挥",但可能跟 prompt 没关系

默认 3.0 是个经验值,我试了 5.0,生成的音乐确实更"听话",但高频噪声也多了。


六、输入预处理:三种条件怎么组合?

MusicGen 支持三种输入:

  1. 文本描述(descriptions):必须
  2. 音频续写开头(prompt):可选
  3. 旋律参考(melody_wavs):可选(只有 melody 模型支持)

场景 1:纯文本生成

descriptions = ["A calm piano melody with soft strings"]

prompt = None

melody_wavs = None

从零开始生成一段温柔钢琴曲。

场景 2:音频续写

descriptions = ["Lo-fi hip hop beat"]

prompt = torch.randn(1, 1, 160000) # 已有 5 秒音频

melody_wavs = None

给模型一段 lo-fi 开头,让它接着往下写。内部会先把 prompt 音频用 EnCodec 编码成 token,然后接在生成序列前面。

场景 3:旋律 + 文本

descriptions = ["Epic orchestral trailer music"]

prompt = None

melody_wavs = [torch.randn(32000)] # 1 秒旋律

给一段旋律,让模型围绕这个旋律生成史诗管弦乐。注意:这是完全按照给定旋律的音高走向来生成,不是参考风格。

如果是 musicgen-style 模型,那就是参考风格而不是旋律。

场景 4:三者都用

descriptions = ["Jazz piano trio"]

prompt = 已有钢琴片段

melody_wavs = 给定旋律

模型会综合文本风格、开头音频、指定旋律一起生成。这种场景适合"续写 + 旋律约束"的复杂任务。

预处理函数 _prepare_tokens_and_attributes 会把这些输入打包成 ConditioningAttributes 对象,里面包含 text embedding 和 wav conditioning。


七、长音频生成:滑动窗口策略

MusicGen 单次最多生成 30 秒(max_duration)。如果想生成 60 秒怎么办?

不能直接 lm.generate(max_gen_len=4500),会报错。

原因:Transformer 有三个硬限制:

  1. 位置编码长度固定
  2. attention mask 尺寸固定
  3. KV cache 分配大小固定

解决方案:分段滑动生成。

假设:

  • max_duration = 30 秒
  • duration = 70 秒(你想生成的总时长)
  • extend_stride = 10 秒(每次前进的步长)
  • frame_rate = 50 token/秒

计算:

  • max_gen_len = 1500 tokens(30 秒 × 50)
  • stride_tokens = 500 tokens(10 秒 × 50)
  • overlap = 1000 tokens(重叠部分,防止音乐断裂)

生成流程:

  1. 第 1 轮:生成前 30 秒(1500 tokens)
  2. 第 2 轮:输入最后 20 秒(1000 tokens overlap),再生成 30 秒,但只取新前进的 10 秒
  3. 第 3 轮:重复...直到 70 秒

overlap 的作用是保持上下文连贯,不然每一段开头都会很突兀。


八、完整生成流程

把上面所有部分串起来,generate_with_chroma 函数干的事:

def generate_with_chroma(self, descriptions, melody_wavs, melody_sample_rate, ...):

1. 重采样 + 声道转换(44.1kHz stereo → 32kHz mono)

melody_wavs = [convert_audio(wav, melody_sample_rate, self.sample_rate, ...) ...]

2. 构造条件(text + wav)

attributes, prompt_tokens = self._prepare_tokens_and_attributes(...)

3. 生成 token(经过 Transformer + Attention)

tokens = self._generate_tokens(attributes, prompt_tokens, progress)

4. 解码为音频

return self.generate_audio(tokens)

四步走完,输出 [B, C, T] 形状的音频张量。


九、踩过的坑

1. 显存爆炸

musicgen-large 跑 30 秒生成,GPU 要 10GB+ 显存。如果爆显存:

  • musicgen-small(1.2GB)
  • 缩短 duration(15 秒试试)
  • 关掉 CFG(cfg_coef=1.0

2. 生成全是噪声

temperature 设太高(>2.0),模型会疯掉。调回 1.0-1.2 就正常了。

3. 旋律条件不生效

用了错误的模型。musicgen-melody 才支持旋律输入,musicgen-small 只支持文本。加载前看清楚模型名。

4. 下载慢

HuggingFace 国内网络慢,可以加镜像:

os.environ["HF_ENDPOINT"] = "https://hf-mirror.com"

十、跟手搓 Music Transformer 对比

第三章我们自己手搓了一个 Music Transformer,对比一下:

维度 手搓 Transformer MusicGen
模型规模 6 层、512 维、0.3B 12-32 层、1024 维、3.3B
训练数据 72 首钢琴曲 2 万小时音乐
条件控制 无条件 文本 + 旋律 + 音频续写
CFG 有(cfg_coef=3.0)
长音频 不支持 滑动窗口支持
生成质量 能听,单调 商业级,丰富

差距在哪?

  1. 数据量:72 首 vs 2 万小时,差了 300 倍
  2. 模型容量:6 层 vs 32 层,差了 5 倍
  3. 条件控制:无条件自回归 vs 文本/旋律多条件
  4. 训练 trick:我们用的基础 AdamW + warmup,MusicGen 还有 CFG、多阶段训练、数据增强

核心思路是一样的:音频→token→自回归建模→生成→解码。MusicGen 就是把这个流程做到了极致。


十一、下一步能搞什么?

  1. 微调(Fine-tuning):用自己的音乐数据集微调 MusicGen,生成特定风格的音乐
  2. 旋律控制 :用 musicgen-melody 模型,输入一段 hum(哼唱),生成完整编曲
  3. 长音频生成 :调 duration=180,生成 3 分钟完整歌曲
  4. 批量生成:循环生成不同 prompt 的音乐,建自己的 AI 音乐库
  5. 源码魔改 :把 musicgen.py 里的 CFG 逻辑抽出来,加到自己手搓的模型里

十二、写在最后

扒完 MusicGen 源码,我最大的感受是:没有什么黑魔法,都是工程细节堆出来的。

  • CFG 不是 Diffusion 专属,自回归模型也能用
  • 长音频生成不是什么新技术,就是滑动窗口 + overlap
  • 多条件控制就是把不同模态的输入打包成 conditioning attributes

工程细节决定上限。怎么调 cfg_coef、怎么设 extend_stride、怎么处理 overlap、怎么做重采样,这些琐碎的东西堆起来,才有一段能用的 AI 音乐。

Meta 开源 MusicGen,等于把音乐生成的天花板掀开了。接下来就是看社区怎么玩:微调、魔改、加新条件、接 MIDI 控制...

AI 写歌这条路,现在才真正开始。

有问题欢迎提 issue 或者评论区留言。


标签AI音乐 MusicGen Meta 音频生成 Transformer EnCodec 深度学习 开源模型

相关推荐
极光代码工作室1 小时前
基于深度学习的微博情感分析系统
人工智能·深度学习·神经网络·nlp·情感分析
huisheng_qaq2 小时前
【AI入门篇-02】深入理解ChatGPT发展流程
人工智能·gpt·ai·chatgpt·大模型·transfomer
带娃的IT创业者2 小时前
US Cities Are Axing Flock Safety Surveillance Technology: 当监控之眼被蒙上,我们在守护什么?
人工智能·智慧城市·数据治理·公共安全·隐私保护·监控技术·技术伦理
计算机毕业编程指导师2 小时前
【计算机毕设推荐】Python+Spark卵巢癌风险数据可视化系统完整实现 毕业设计 选题推荐 毕设选题 数据分析 机器学习 数据挖掘
hadoop·python·计算机·数据挖掘·spark·毕业设计·卵巢癌
愚公搬代码2 小时前
【愚公系列】《AI漫剧创作一本通》004-剧本拆解,把小说改编为可落地的脚本(爆款AI漫剧,从选择合适的小说开始)
人工智能·ai漫剧
玩转单片机与嵌入式2 小时前
学习嵌入式AI(TInyML),只需掌握这点python基础即可!
人工智能·python·学习
mit6.8242 小时前
从 Vibe Coding 到 Agentic Engineering
人工智能
kay_5452 小时前
YOLO26改进| 主干网络 | 提升长距离特征建模与全局上下文理解能力【CVPR】
人工智能·目标检测·计算机视觉·目标跟踪·论文·yolo26·yolo26改进
ting94520002 小时前
Huddle01 VMs 支持 AI 助手一键部署,MCP 协议重塑云基础设施管理
人工智能