AI 作曲这件事,两年前还是"听个响"的水平,现在用开源模型在自己电脑上就能跑出带人声、带编曲、结构完整的整首歌。YuE2就是这一代里比较有代表性的一个:输入一段歌词加几个风格标签,它在本地把整首歌(人声+伴奏)生成出来,中英文都能唱。这篇教程我按"从零到出第一首歌"的顺序,拆成五个步骤来讲——环境准备、权重下载、提示词撰写、推理出片、后期拼接导出,每一步都写清楚为什么这么做、参数怎么定、哪些坑我踩过。适合三类人看:完全没接触过音频生成、但会用命令行的开发者;想给自己写的词配个曲的音乐爱好者;以及想把这套流程接进自己工具链的产品或工程同学。不需要乐理基础,但需要一台显存不算太寒酸的机器,这一点我在第 1 节会先把话说明白。
1. 先搞清楚这个模型能干什么、不能干什么
1.1 它解决的问题和它的能力边界
很多人对 AI 作曲的想象是"我说一句话,它给我一首周杰伦"。实际不是。YuE2 这类模型做的事情,更准确地说是歌词到整首歌的映射(lyrics-to-song):你给它一份带结构标记的歌词,再给它一组风格标签(流派、乐器、人声性别、情绪、语种),它输出一段包含人声演唱和伴奏的完整音频。它不是在"作曲"的语义上创作旋律动机,而是在学习海量音乐数据之后,把"歌词文本 + 风格描述"这个条件,映射成音频 token 序列,再解码成波形。
理解这一点非常关键,因为它直接决定了你的使用姿势。你给的歌词越有结构感、越有韵律、越贴合它训练分布里的常见句式,出来的东西就越像"歌";你给一段散文或者一段极端长的排比句,它大概率会唱得含混、节奏散掉。风格标签也一样,写"赛博朋克古风电子民谣"这种缝合怪,效果往往不如老老实实写"synthwave, female vocal, mid tempo"。
它的边界也很清楚:第一,长音频是分段生成的,整首歌不是一次性出来的,需要你在后面拼接,段落衔接处的处理是手艺活;第二,它不做混音母带,出来的原始音频响度、频响都偏"生",要过一遍后期;第三,它对歌词的咬字准确度并非 100%,中文里多音字、生僻字翻车的概率不低。把这三点心里有数,你的预期就不会跑偏。
1.2 硬件门槛:显存才是真正的门槛
我先说结论:这个模型对显存的要求远高于对算力的要求。CPU 也能跑,但一首三分钟的歌可能要跑上大半个小时甚至更久,属于"能跑但不实用"。真正决定你体验的是显卡显存。
下面这张表是我根据社区反馈和实际部署经验整理的大致区间,注意这是经验值,具体数值跟你的精度选择、分段长度、框架版本都有关系:
| 配置档位 | 显存 | 可行方案 | 典型体验 |
|---|---|---|---|
| 入门 | 8GB | 4bit 量化 + 短分段(20-30 秒) | 能出片,音质有损,速度慢,容易 OOM |
| 主流 | 12-16GB | 8bit 量化或半精度短分段 | 可日常使用,三分钟歌约 15-30 分钟 |
| 舒适 | 24GB | 半精度全量权重 | 分段可以拉长,出片质量接近原版 |
| 宽裕 | 40GB 以上 | 半精度 + 更长上下文 | 段落衔接更自然,返工少 |
磁盘空间别忽略。两个阶段的 7B 级别权重加上声码器、tokenizer 这些附属文件,加起来通常要 30-40GB,我建议你按 60GB 预留,因为下载过程中会有临时文件,加上你后面生成的一堆 wav,很容易撑爆。系统层面,Linux 是最省心的选择,Windows 上要装 WSL2 或者直接配 CUDA 环境,多多少少会多折腾一轮。
注意:不要在一台只有 8GB 显存、内存也才 16GB 的机器上硬刚全量权重,OOM 会以各种你看不懂的形式出现——有时候是显存报错,有时候是进程被系统直接杀掉,日志里什么都没有,排查起来极其痛苦。
2. 五步流程的整体设计与选型考量
2.1 为什么拆成这五步而不是三步
网上很多教程喜欢把"装环境"和"下模型"揉成一步,我特意把它们拆开,原因是这两个环节的失败模式完全不同。环境问题的症状是"import 报错、版本冲突、CUDA 不可用",模型问题的症状是"文件缺失、校验不匹配、加载时 shape 不对"。揉在一起,出问题时你根本不知道是哪一层的事,一通乱试反而把环境搞得更脏。
五个步骤的划分逻辑是这样的:环境准备解决"程序能不能启动",权重下载解决"模型能不能加载",提示词撰写解决"输出是不是你要的",推理执行解决"跑不跑得完",后期处理解决"成品能不能听"。这五件事的依赖是线性的,前一步没通就做下一步,纯属浪费时间。我见过有人模型都没下完就开始调提示词,最后发现是他写的标签模型压根不认,白折腾一晚上。
另外一个考量是可回滚。每一步做完,你都应该留下一个可验证的中间产物:环境装完能import torch并打印 CUDA 可用;权重下完能列出目录结构和文件大小;提示词写完有一个独立的 txt 文件;推理完有一批分段 wav;后期完有一首成品。中间产物在,出问题就能定点回退,不用从头再来。
2.2 三条路线的取舍:全量、量化、云端
在动手之前,你得先选路线。我用一张表把三条路的差别说清楚:
| 路线 | 适用人群 | 优点 | 代价 |
|---|---|---|---|
| 半精度全量权重 | 显存 24GB 以上 | 音质最好,参数空间大,返工成本低 | 下载体积大,对显存挑剔 |
| 量化权重(8bit/4bit) | 显存 8-16GB | 能跑起来,下载体积小 | 音质有损,长分段易崩,调试更玄学 |
| 云端租赁实例 | 偶尔出片、不想买卡 | 一次性成本低,可按小时计费 | 环境要重配,数据传输麻烦,长期不划算 |
我的建议是:如果你只是"想试试",先用云端租一张 24GB 的卡跑通全流程,把五步走完,确认这套东西对你有用,再考虑本地部署。反过来,如果你本来就有 24GB 的卡,直接上全量权重,别在量化上浪费时间——量化省下的那点下载时间,远不如你在"为什么这段人声糊了"上面耗掉的多。
还有一个被很多人忽略的选项:只跑阶段二。这套模型是两阶段的,阶段一负责把歌词和标签转成粗粒度的音频 token,阶段二负责把 token 细化成更高质量的表示。有些折腾党会拿别人的阶段一输出直接喂自己的阶段二,只调后半段。这个玩法对新手不友好,但你要是想省时间,值得知道有这么条路。
3. 第一步与第二步:环境搭建和权重落地
3.1 环境隔离和依赖安装
第一步永远是隔离环境。不要在你的系统 Python 里装这套东西,它对 torch 版本、CUDA 版本、以及若干编译型依赖(比如加速注意力实现的那些包)都很敏感,一旦和你别的项目冲突,你会陷入版本地狱。
# 用 conda 建一个干净的 3.10 环境,3.10 是目前兼容性最好的选择 conda create -n yue2 python=3.10 -y conda activate yue2 # 先装匹配你 CUDA 版本的 torch,这一步装错了后面全白搭 # 假设你是 CUDA 12.1 pip install torch==2.3.0 torchaudio==2.3.0 --index-url https://download.pytorch.org/whl/cu121 # 验证 python -c "import torch; print(torch.__version__, torch.cuda.is_available(), torch.cuda.get_device_name(0))"第三行那个验证是强制动作,不是可选项。输出里cuda.is_available()必须是True,后面还得打印出你的显卡型号。如果这里是False,别往下走了,先解决驱动和 CUDA 版本匹配问题。我见过太多人跳过这一步,然后花两小时在排查"为什么模型加载特别慢",最后发现是在 CPU 上跑。
验证通过之后,再装项目自己的依赖。通常仓库里会有一个 requirements 文件,直接装。这里有个小技巧:先装不带版本锁的核心包,再装锁定版本的。因为有些依赖(特别是编译型的那几个)在不同 CUDA 版本下要装不同的轮子,一刀切锁版本很容易装不上。装不上时第一反应应该是去看它的官方安装说明,而不是降级 Python。
pip install -r requirements.txt # 如果 flash-attn 这类包装不上,先确认你的 CUDA 和 torch 版本,再考虑从源码装 # 实在装不上,很多实现里它是可选的,关掉只是慢一点3.2 权重下载、目录结构和校验
第二步是下权重。这一步最大的坑不是"下不下来",而是"下了一半以为下完了"。我强烈建议你下完之后做三件事:看文件大小、数文件个数、跑一次加载测试。
目录结构通常是这样的(具体命名以你用的仓库说明为准,这里给的是常见布局):
models/ ├── stage1/ # 阶段一权重 │ ├── config.json │ ├── model.safetensors # 或者分片的 bin │ └── tokenizer/ ├── stage2/ # 阶段二权重 │ ├── config.json │ └── model.safetensors └── vae/ # 声码器/解码相关几个实操要点:
第一,优先用带断点续传的下载方式。几十 GB 的文件,网络抖一下就得重来,会疯。命令行工具里支持续传的都可以,下载脚本里如果能加--resume之类的参数就加上。
第二,下完立刻校验。仓库一般会给出文件的 sha256 或者至少给出总大小。如果没给校验值,就对比总大小和文件个数,误差在几 MB 以内可以接受,差出几百 MB 肯定是缺片。
第三,先跑一次最小加载测试再睡觉。写个三行的脚本,把两个阶段的模型都from_pretrained一下,能加载成功、能打印出参数量,才算真的下完了。这个测试大概要花几分钟,但能帮你省掉第二天早上发现要重下的绝望。
注意:如果你的磁盘是机械盘,加载 7B 级权重会非常慢,慢到你怀疑卡死了。这不是 bug。有条件的话把模型放到固态盘上,加载时间能从几分钟降到几十秒。
4. 第三步与第四步:提示词怎么写、参数怎么定
4.1 歌词结构标签的写法
这是整个流程里最"玄学"也最有价值的一环。模型是按段落理解歌词的,你得用结构标签告诉它哪里是主歌、哪里是副歌、哪里该纯器乐。常见的标签长这样:
[intro] [verse] 夜色把城市压成一条线 我数着路灯走完了半条街 [chorus] 别问我为什么还不睡 月光替我回答了一整夜 [bridge] [outro]几个经验性的规则,都是我反复试出来的:
一段别超过四到六行。太长了模型会不知道在哪换气,节奏会糊。你要是词写得多,就多切几段[verse]。
副歌要和主歌有重复元素。模型对"重复"很敏感,副歌里出现主歌的关键词或句式,它给的处理会更像"记忆点"。这也是流行歌本身的规律。
[instrumental]或者空的段落标签很有用。前奏、间奏、尾奏都靠它来撑。你不写,模型可能一上来就开唱,听感很突兀。
中文标签不一定认,英文标签最保险。结构标签用英文的[verse][chorus],正文用中文,这个组合实测最可靠。你要是全用中文标签,有些版本会把它当成歌词直接唱出来,那就尴尬了。
4.2 风格标签的组合逻辑
风格标签不是一个自由发挥的文本框,它有比较明显的"有效区间"。我的做法是分三层写:流派层、乐器层、人声层。
- 流派层:
pop、rock、folk、electronic、jazz、lo-fi,挑一到两个,别超过两个。 - 乐器层:
acoustic guitar、piano、synth pad、drum machine,同样挑一到三个。 - 人声层:
female vocal/male vocal、soft voice、breathy、choir,一到两个就够。
总数控制在五到七个词,效果通常最好。写太多,模型在每个词上分配的注意力被稀释,最后出来一个四不像。这点和写图像生成提示词是一个道理,只是音乐这边更明显,因为音频的时间维度上"稀释"的后果是结构崩掉,而不只是画面变糊。
关于语种:中英文混排它是支持的,但混排会让咬字更不确定。如果歌词主体是中文,风格标签里就别强调english之类的词,容易让它在某些段落突然切换口音。想要纯中文输出,最稳的做法是标签保持中立,靠歌词本身的语言去引导。
4.3 关键参数:时长、分段、采样与种子
推理阶段的参数不多,但每一个都影响结果。我把常用的几个列一下:
| 参数 | 作用 | 我的常用值 | 调整建议 |
|---|---|---|---|
| 分段数(segments) | 决定生成多少个时间窗口 | 按目标时长 ÷ 单段长度算 | 宁可多算一段,不够可以截 |
| 单段时长 | 每个窗口覆盖的秒数 | 25-30 秒 | 显存紧张就降到 20 秒 |
| 采样温度 | 随机性 | 0.9-1.0 | 想要稳定复现就调低 |
| top-k / top-p | 采样范围 | 50 / 0.95 | 一般不动,除非输出特别乱 |
| 随机种子 | 复现性 | 固定一个整数 | 出好片立刻记下种子 |
| 引导强度 | 贴合提示词的程度 | 中等偏上 | 太低了不听指令,太高了发音僵硬 |
关于分段数的计算,这里给个具体例子:你要一首 3 分钟(180 秒)的歌,单段设 30 秒,那分段数就是180 ÷ 30 = 6,再留一段余量设 7。注意实际生成的每段末尾通常会带一点尾巴,拼接时需要裁剪重叠部分,所以宁可多生成一段。
关于温度,我的态度很明确:第一版不要动它。先用默认值跑一版完整的,听感上哪里不对,再针对性地调。旋律太单调就往上加一点,人声飘忽就往下压一点。一上来就把温度拉到 1.3 追求"创意",结果大概率是跑调加乱码。
种子这件事,很多新手会忽略。你跑出来一段副歌特别满意,但记不得种子,下一次就再也复现不了了。我在实践里的做法是:把每次运行的完整参数导出成 json 存档,命名带上时间和种子号。这个习惯看着麻烦,等你需要"上一版那个感觉再来一次"的时候,会感谢自己。
# 伪代码示意,具体参数名请对照你所使用仓库的说明 python infer.py \ --stage1_model ./models/stage1 \ --stage2_model ./models/stage2 \ --genre_txt ./prompts/style.txt \ --lyrics_txt ./prompts/lyrics.txt \ --run_n_segments 7 \ --max_new_tokens 3000 \ --seed 20240613 \ --output_dir ./outputs/take014.4 显存不够时的降级策略
如果你的卡只有 12GB 左右,会频繁遇到显存不足。这时候按下面这个顺序降级,尽量把损失控制住:
先降分段时长,别先降精度。单段从 30 秒降到 20 秒,显存占用会明显下降,而精度不掉。代价是你要多拼几段,段落衔接处要多处理几次,但音质保住了。
再试 8bit 量化。8bit 对音质的影响在可接受范围内,人声的细节会稍微少一点,但整体听感还能接受。
最后才上 4bit。4bit 出来的东西明显发闷,高频细节丢失比较严重,人声会有种"隔着布"的感觉。如果只能跑 4bit,我建议你把它当成"草稿工具"——用它快速验证歌词和结构,等确认方向对了,再租一张大卡跑最终版。
还有一个偏门但有效的办法:关掉不必要的缓存和并行。有些实现会预分配很大的缓冲区,你把它关掉之后显存占用能降几个 GB,代价是速度慢一些。在显存卡着临界点时,这个交换是划算的。
5. 第五步:分段拼接、后期与成品导出
5.1 拼接不是简单 cat 一下
五步流程里,这一步最容易被低估。很多人拿到分段 wav 直接拼起来,结果就是每 30 秒一个突兀的断裂,鼓点断掉、人声被截断。这是因为每段的开头和结尾都不是从"乐句边界"开始的,硬拼一定出问题。
正确的做法是保留重叠 + 交叉淡化。具体操作:让相邻两段有 1-3 秒的重叠区,在重叠区做线性或等功率交叉淡化。用 ffmpeg 就能做,不用非得装大个头的音频软件:
# 假设 a.wav 和 b.wav 有 2 秒重叠 ffmpeg -i a.wav -i b.wav -filter_complex \ "[0][1]acrossfade=d=2:c1=tri:c2=tri" \ merged.wav如果有多段,就两两串起来做。嫌命令行麻烦的话,用任何支持多轨的音频编辑软件手动拖也行,反正就是对齐重叠区、加淡入淡出。
还有个更细的处理:段落的接缝最好落在鼓点或和弦切换处。你在拼接前先听一遍每段的结尾,找到它自然"收住"的那个位置,把裁剪点放在那里,接缝几乎听不出来。这个操作靠耳朵,没什么自动化捷径,但熟练之后很快。
5.2 响度、频响和导出格式
原始输出通常响度偏低、低频偏多、高频偏闷。三步处理就能明显改善:
第一步,高通滤波。切掉 30Hz 以下的超低频,那些基本是噪声,留着只会让整体发浑。
第二步,响度归一化。目标定在 -14 LUFS 左右,这是绝大多数流媒体平台的标准。ffmpeg 里可以用loudnorm滤镜一次搞定:
ffmpeg -i merged.wav -af "highpass=f=30,loudnorm=I=-14:TP=-1.5:LRA=11" \ -ar 44100 -ac 2 final.wav第三步,选导出格式。存档用 wav(44.1kHz / 16bit 或 24bit),分发用 mp3 320kbps 或 aac。别导出成 128kbps 的 mp3,那点文件大小省下来毫无意义,高频全被砍了。
如果你想更进一步,可以做人声和伴奏的分离,单独给人声加一点混响和压缩,再把伴奏垫回去。这个操作对成品的"专业感"提升很明显,但对新手来说不是必需,先跳过也没关系。
注意:所有后期处理都应该是轻量的。AI 生成的音频本身已经有比较明显的"处理痕迹",你再加大量 EQ 和压缩,只会让它更像塑料。宁可少动,不要多动。
6. 常见问题与排查技巧实录
6.1 报错速查表
下面这张表是我和周围人踩过的坑汇总,按"症状"查比按"原因"查快得多:
| 症状 | 最可能的原因 | 处置方式 |
|---|---|---|
CUDA out of memory | 分段太长或精度太高 | 降单段时长,再降精度,关掉预分配缓冲 |
| 进程被系统直接杀掉,无日志 | 系统内存不足,不是显存 | 关掉其他程序,减小 batch,加交换分区 |
| 加载权重卡住不动 | 机械盘 + 大文件 | 换固态盘,或耐心等(真的会加载完) |
| 输出全是噪声 | 声码器权重缺失或错配 | 检查 vae 目录,确认文件和版本对应 |
| 生成的是纯器乐没人声 | 歌词文件为空或标签被当歌词 | 确认 lyrics 文件有内容,标签用英文 |
| 人声咬字含糊 | 歌词太长、句式太绕 | 拆短句子,减少生僻字,副歌简化 |
| 每段之间断裂明显 | 没做重叠和交叉淡化 | 保留 1-3 秒重叠,acrossfade 处理 |
| 同一提示词每次差别巨大 | 种子没固定 | 固定 seed,记录参数存档 |
| 风格标签完全不起作用 | 标签太多太杂 | 砍到 5-7 个词,分三层写 |
6.2 几个从文档里学不到的体会
第一,先跑短的,再跑长的。新手最常见的错误是第一次就跑三分钟。先用 30 秒、一段的量,验证整条链路通不通,从下载到出片跑一遍。链路通了再上时长,能省掉大量"到底是哪一步坏了"的困惑。
第二,别指望一次出好片。我的实际比例大概是十次里有一次能用。所以要建立"批量出草稿 → 挑选 → 精修"的工作流,而不是"一次生成 → 不满意 → 全推翻重来"。批量跑的时候用低精度短分段,挑出方向对的,再用高精度重跑那一段,效率高得多。
第三,把提示词当代码管理。歌词文件、风格标签文件、参数 json,都放进版本管理里,每次改动留 commit 记录。这个习惯听起来有点小题大做,但当你调到第十五版、想回到第七版那个感觉的时候,就知道值了。
第四,注意歌词的"可唱性"。写词的时候心里默念一遍,看能不能一口气念下来。拗口的句子、连续三个仄声字、一句话里塞两个成语,模型唱出来一定别扭。这不是模型的问题,是中文韵律本身的限制,人类歌手遇到这种词也难唱。
第五,遇到莫名其妙的失败,先清空输出目录再跑。有些实现会把中间结果缓存到输出目录,中断之后再跑会读到半截文件,报出一堆看不懂的错。清空重跑往往就好了,这个经验帮我省过不少时间。
第六,别在深夜调参。这条不算技术,但很真实。音频这种东西主观性太强,凌晨三点你觉得绝妙的旋律,第二天早上再听会觉得莫名其妙。重要的判断留到状态好的时候做。
6.3 一次完整的实操记录
为了让你有个具体的参照,我把最近一次出片的过程记一下。目标是做一首两分半的中文民谣,女声,木吉他为主。
歌词写了四段主歌、两段副歌、一个间奏、一个尾奏,总共八个小段。风格标签写成folk, acoustic guitar, female vocal, soft, mid tempo,五个词,语种没写。分段数按150 ÷ 25 = 6,加一段余量设 7,单段 25 秒,种子固定成 20240613,温度用默认值没动。
第一次跑完,七段里有两段的人声严重跑偏,一段的间奏直接没了。判断是间奏那个空标签没被识别,把[instrumental]换成了带一个词的短句重新跑,问题解决。人声跑偏的两段,是把长句拆短之后重跑的,也正常了。
拼接的时候,七段保留了 2 秒重叠,用 acrossfade 串起来,接缝基本听不出来。后期只做了三件事:30Hz 高通、-14 LUFS 归一、导出 44.1kHz wav。整首歌从开始写到出成品,算上下载和调试,用了大概一个下午,其中真正跑推理的时间不到四十分钟。
这个记录里最有参考价值的一点是:问题几乎都出在提示词层,不在参数层。参数用默认值、种子固定住之后,剩下的就是把歌词和标签调到模型能理解的样子。所以如果你时间有限,把精力放在写词和标签上,收益比死磕采样参数高得多。
我个人在实际折腾这套流程的过程中,最大的感受是:AI 作曲目前更像一个"执行者"而不是"创作者"。它能把你脑子里的东西落成音频,但它不知道什么是好。所以你在前面那一步——写词、定风格、判断哪一版更好听——花的时间,才是真正决定成品质量的地方。工具那部分,跑通一次之后就再也不是瓶颈了。