name: mp3-to-piano description: 把 mp3 / wav 等音频转换成钢琴曲(钢琴版 / 钢琴伴奏 / 钢琴翻弹)时使用。完全本地脚本完成,无需联网(首次运行 basic-pitch 会下载约 100MB 模型权重)。当用户说"把这首歌变成钢琴曲""转成钢琴伴奏""做个钢琴翻弹版"等意图时调用。
把任意歌曲/音频离线转成钢琴演奏版。本地完成,零外部采样依赖(不依赖 SoundFont / 联网音色库)。
--hpss,转录前先用 librosa 做谐波/打击乐分离,只把旋律(谐波)轨送进去,避开鼓点误判# 系统
ffmpeg # 在 PATH 中,或用环境变量 FFMPEG_EXE 指定绝对路径
# Python —— 必须 3.9~3.11(3.12+ 装不上 basic-pitch:其依赖 numpy<2/TF 无新版 wheel)
pip3 install basic-pitch pretty_midi numpy scipy soundfile
# 注意:basic-pitch 会顺带安装 tensorflow/jax,若遇到 ml_dtypes 版本冲突,执行:
# pip3 install "ml-dtypes==0.5.1"
# 真实钢琴采样渲染(--soundfont 用,可选但推荐)
# 引擎 A(优先,纯 pip,3.9 也能用):
pip3 install tinysoundfont
# 引擎 B(回退,需系统库):pip install pyfluidsynth + 系统装 fluidsynth
# 钢琴 SoundFont:FreePats UprightPianoKW(CC0, 6MB) / FluidR3_GM / Salamander Grand
脚本启动时会自动做环境自检(Python 版本 / ffmpeg / basic-pitch),不通过会给出修复指引后退出。
关于模型权重:basic-pitch 安装包内已自带 ONNX 格式模型(nmp.onnx),装有 onnxruntime 时无需 TensorFlow、无需联网下载权重,开箱即用。只有走 TF 后端才需要首次联网下载约 100MB 权重。
在「无 ffmpeg + 默认 Python 3.13」的 Windows 机器上,按以下方式可完整跑通:
# 1) 用系统已有的 Python 3.9~3.11 建 venv(py -0 可列出已装版本)
py -3.9 -m venv venv39
venv39/Scripts/python.exe -m pip install basic-pitch pretty_midi numpy scipy soundfile
# 2) 没有 ffmpeg?用 imageio-ffmpeg 拿静态二进制,再用 FFMPEG_EXE 指过去
venv39/Scripts/python.exe -m pip install imageio-ffmpeg
# 二进制位置:<venv>/Lib/site-packages/imageio_ffmpeg/binaries/ffmpeg-win-*.exe
# 3) 运行(FFMPEG_EXE 指向上面的二进制;沙箱中建议加 PYTHONDONTWRITEBYTECODE=1
# 避免向系统 Python 目录写 __pycache__ 被拦截)
FFMPEG_EXE="<ffmpeg绝对路径>" PYTHONDONTWRITEBYTECODE=1 \
venv39/Scripts/python.exe scripts/mp3_to_piano.py 输入.mp3 -o 输出.mp3
实测环境:Windows + Python 3.9.5 + basic-pitch 0.4.0(ONNX 后端)+ imageio-ffmpeg 静态二进制,端到端通过。
python3.11 scripts/mp3_to_piano.py 输入.mp3 -o 输出.mp3
| 参数 | 默认值 | 说明 |
|---|---|---|
input |
必填 | 输入 mp3 路径 |
-o/--output |
<输入名>_piano.mp3 |
输出 mp3 路径 |
--reverb |
0.18 |
混响量 0–0.6,越大空间感越强 |
--gain |
0.9 |
整体音量增益 |
--onset |
0.5 |
转录 onset 阈值,越低音符越密 |
--frame |
0.3 |
转录 frame 阈值,越低音符越密 |
--min-note |
21 |
最低音高 MIDI 号(默认 A0),过滤低频误判 |
--max-note |
108 |
最高音高 MIDI 号(默认 C8) |
--soundfont |
无 | 可选:传入真实钢琴 .sf2 用采样渲染(更真实)。引擎顺序:tinysoundfont(纯 pip,优先)→ fluidsynth(回退)。tinysoundfont 缺依赖时自动回退并提示 |
--no-pedal |
关 | --soundfont 时关闭延音踏板(默认踩下,连奏更自然;关掉各音更分明、更"颗粒") |
--tail |
0.35 |
--soundfont 时每个音的松键延音尾巴秒数。真实钢琴连奏的核心手段(小体积 SF2 的踏板常无效,靠延长余响衔接邻音);越大越连奏、过大发糊 |
--hpss |
关 | 转录前用 HPSS 谐波/打击乐分离,只把旋律(谐波)轨喂给 basic-pitch。减少鼓点/打击乐误判导致的怪音与节奏漂移(流行/电音/鼓点重的歌强烈建议开;纯钢琴/人声独唱提升小可不开)。零额外依赖(librosa 已随 basic-pitch 环境可用) |
--merge-gap |
0.09 |
同音高、间隙小于此值(秒)的相邻音符合并为一个长音。越大越合并(修碎音),过大会吞掉快速重复音 |
--min-note-len |
0.045 |
丢弃时值小于此值(秒)的孤立超短音(二次去转录噪声)。越大越去噪,但快歌装饰音易丢;与 basic-pitch 自带 ~127ms 阈值互补 |
--vel-smooth |
0.5 |
力度向全曲均值压缩比例 0–1。越大力度越均匀(去"忽大忽小顿挫"),越小越保留原动态 |
--keep-midi |
关 | 保留转录+清理后的中间 MIDI(输出同名 .mid),便于逐音对比调试 / 手动改谱后再渲染 |
--sf2-preset |
无 | --soundfont 时强制指定预设编号(先用 tinysoundfont 列出 preset 名后选);不填则自动选名字含 piano 的预设 |
--max-voices |
0(不限制) |
复音限制器:同一时刻最多保留 N 个最响的音,重叠中的弱音被剔除 → 直接去糊。满编流行歌经 basic-pitch 转录后常堆叠成大量同时响的音,numpy 合成器等权叠在一起就糊;设 4~6 可显著突出旋律与关键和声(例:陈晓东《比我幸福》原版平均复音 4.67、偏糊,限到 4 后明显干净) |
--from |
无 | 再导入模式:传入你修改过的 .musicxml 或导出的 .mid,跳过转录/HPSS 直接渲染更优钢琴曲(人机协作精修闭环) |
--no-score |
关 | 不导出可编辑五线谱 .musicxml;默认会导出,便于你在打谱软件里修改后 --from 回灌 |
--png |
关 | 额外渲染一张五线谱视图 PNG(纯本地生成,无需联网),方便直接预览 |
--snap-to-key |
关 | 调性吸附:先估计调性,把离调(疑似转录错音)就近吸附回音阶修掉;已在音阶内的音不动,不会破坏正确旋律与和声 |
--quantize |
0(不量化) |
节奏量化:把音符对齐到网格(每拍分数)。8=八分、16=十六分、32=三十二分;让"犹豫/抢拍"对齐更稳 |
--preset |
无 | 一键配方:ballad(干净抒情) / pop(满编流行) / solo(清唱独奏)。预设作参数基底,任何显式 CLI 参数都会覆盖它 |
--no-report |
关 | 不输出转录质检报告 <输出名>_质检报告.txt;默认会输出 |
--hpss 先分离打击乐再转录,低频鼓点误判可减少约 68%(实测《Four Leaf Clover》音符数 2984→1107、低频音符 397→127),音符更干净、更连贯--onset 0.3 --frame 0.2--onset 0.6,或收窄 --min-note 36(去掉低音区底鼓误判)--reverb 0.3pip install tinysoundfont + 一个钢琴 SoundFont(如 FreePats UprightPianoKW / FluidR3_GM.sf2),用 --soundfont 渲染。引擎自动选 tinysoundfont,缺依赖再回退 fluidsynth。觉得太糊可加 --no-pedal 让各音更分明。--keep-midi 导出 MIDI 听一遍,定位是转录层还是渲染层问题;再调 --merge-gap 0.12(更积极合并碎音)、--vel-smooth 0.7(力度更平)、--min-note-len 0.06(更去噪)。默认值已是 v1–v6 最佳配方,大部分歌无需动。--max-voices 4(或 5/6)直接砍掉同时响的弱音;再配 --reverb 0.12(降混响让各音更分明)、--vel-smooth 0.25(保留原动态、别压平)、--merge-gap 0.10(轻微合并碎音)。"干净抒情歌"预设(实测《比我幸福》A/B 明显更清晰):
--hpss --max-voices 4 --merge-gap 0.10 --vel-smooth 0.25 --reverb 0.12 --min-note-len 0.06
仍觉得糊就把 --max-voices 降到 3;觉得太单薄就升到 5~6。这招只改密度不改变音色——想要"真钢琴"质感仍要走 SoundFont(见上)。--soundfont 指向 Salamander Grand / FluidR3_GM 等长采样 SF2。渲染器会自动探测余响长度:短采样(余响<1.5s)保持常踩踏板+尾巴;长采样(余响>1.5s)自动关掉常踩踏板、改用自然衰减衔接(否则会糊)。即你换上大钢琴,踏板会"自动生效",不用改代码。本技能在真实歌曲《Four Leaf Clover》(5:40) 上迭代了 5 版,以下为可复用的实证结论,不是拍脑袋建议。
--soundfont)--onset 0.5 --frame 0.3)+ 调性过滤 + 软量化 → 音色最接近钢琴,但被听出「节奏像业余人弹、偶发怪音」(这是转录层问题,不是合成层)。--soundfont)--tail 松键延音尾巴:间隙段 RMS 0.0196(无尾) → 0.0904(尾 0.35s),衔接度 4.6×。--tail 0.35 + 混响 0.18 + 音符清理)→ 非静音帧 93% → 98.3%,连奏回来且保留真钢琴音色。# 默认数学合成(稳,先听个大概)
python scripts/mp3_to_piano.py song.mp3 -o out.mp3
# 真实钢琴采样(推荐,音色天花板高)
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --soundfont piano.sf2
# 采样版太糊 → 收尾巴
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --soundfont piano.sf2 --tail 0.15
# 采样版想要各音分明、颗粒感 → 关踏板
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --soundfont piano.sf2 --no-pedal
# 大编制长采样 SF2(如 Salamander Grand)→ 踏板真正生效,可让尾巴交给踏板
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --soundfont salamander.sf2
# 转录太稀疏/丢旋律
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --onset 0.3 --frame 0.2
# 噪声/鼓点误判多
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --onset 0.6 --min-note 36
# 鼓点重/节奏飘/怪音多(最大杠杆)→ 先分离打击乐再转录
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --soundfont piano.sf2 --hpss
⚠️ 关键边界:
--soundfont只换音色、不动转录。若听完觉得「节奏业余/有怪音」,那是 basic-pitch 转录层的问题,靠音色参数(reverb/tail/pedal)解决不了,需回到--onset/--frame重新转录或换 MIDI 重编。
--hpss,v6 最大杠杆落地)--hpss 是性价比最高的「流畅度提升」开关,流行/电音/鼓点重的歌默认就该开;纯钢琴独奏或清唱人声提升有限、可不开。--merge-gap / --min-note-len / --vel-smooth,并新增 --keep-midi(保留中间 MIDI 便于调试)。这些参数与"歌的风格"相关,不同歌曲可微调,但默认值已是 v1–v6 迭代出的最佳配方,大部分歌无需动。_detect_ringout() 在渲染前自动探测 SF2 单音余响长度,自适应选择「常踩踏板+尾巴」还是「自然衰减」策略,并新增 --sf2-preset 指定钢琴预设。意义:当前自带的 UprightPianoKW 余响仅 0.2s(极短采样),必须靠 --tail 补连奏;而一旦你换成余响数秒的大编制三角钢琴,渲染器会自动切到自然衰减、让踏板真正生效,连奏更自然且不糊。这部分代码已就绪,只等你提供更大的 SF2 即可见效(见下节)。中等杠杆的"真收益"——让延音踏板真正生效、连奏接近录音级——需要更长的采样 SF2(当前自带的 UprightPianoKW 仅 6MB、余响 0.2s,踏板无效)。渲染器已自适应就绪,你只需提供更大的 SF2:
SalamanderGrandpiano 仓库的 .sf2 发布物.sf2 钢琴采样若本机拉不动,请在有正常网络的机器上下好,再拷到本机 soundfonts/ 目录(tinysoundfont C 引擎支持 .sf2 / .sf3)。
2. 列预设选钢琴(可选):若默认选的预设不是你想要的钢琴,先用脚本打印 preset 名再 --sf2-preset <编号> 指定。
3. 渲染:python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --soundfont <大钢琴>.sf2
- 渲染器会自动探测到余响 >1.5s → 关掉常踩踏板、改用自然衰减,连奏自然且不糊。
4. 若仍想用常踩踏板:传较小的 --tail 0.2 之类,避免长采样叠加发糊。
注:当前
soundfonts/piano.sf2是 6MB 的 UprightPianoKW,音色已足够"真钢琴",只是连奏靠尾巴模拟。换大编制是"锦上添花"而非"必须"——且本机网络拉大文件困难,按需再操作即可。
把"机器转录"升级成"人机协作":机器先出初稿五线谱,你用打谱软件精修,再一键渲染成更优质的钢琴曲。
默认每次转换都会在同目录导出 <输出名>.musicxml(钢琴双行谱 Grand Staff,标准 MusicXML)。这是一个可编辑的乐谱文件,用 MuseScore(免费,https://musescore.org)或任意打谱软件打开即可看到并修改音高、时值、和声。
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 # 自动产出 out.musicxml(可编辑五线谱)
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --png # 额外渲染一张五线谱视图 out_score.png(纯本地,方便直接预览)
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --no-score # 不想要 musicxml 时关掉
在打谱软件里改好乐谱(修正错音、调整节奏、重编和声…)→ 另存为 .musicxml(或导出 .mid)→ 用 --from 直接渲染,跳过转录、直接出钢琴曲:
python scripts/mp3_to_piano.py 原曲.mp3 -o 精修版.mp3 --from 我改好的谱子.musicxml
python scripts/mp3_to_piano.py 原曲.mp3 -o 精修版.mp3 --from 我改好的谱子.mid
--from 模式下所有渲染参数(--reverb / --soundfont / --hpss 等)照常生效,HPSS/转录会自动跳过。
这形成一个可不断打磨的正循环:机器出初稿 → 你精修 → 渲染试听 → 再精修,直到满意。(想保留精修谱子供复用,配 --keep-midi 即可。)
midi_to_musicxml:把转录 MIDI 写成双行谱 MusicXML(高/低音谱表按音高自动分配,和弦用 <chord/>,音符按 4/4 小节切分),无任何第三方库。musicxml_to_midi:把用户改过的 .musicxml 解析回 MIDI(支持 <note>/<chord>/<rest>/<backup>/<forward> 与多小节顺序),供渲染消费。render_score_png:纯 numpy + zlib 本地画五线谱视图 PNG,不依赖 Pillow/LilyPond/MuseScore/联网,任意环境都能出图。之前"换首歌就崩"是两个独立 bug,现已固化进代码,不再依赖手动绕过:
UnicodeEncodeError 中断。已在脚本顶部 sys.stdout/stderr.reconfigure(encoding='utf-8'),与系统编码彻底绝缘——无需再手动设 PYTHONUTF8=1。--soundfont 的 SF2 被 tinysoundfont 拒载,就裸 traceback。现改为三级降级链:
tinysoundfont(纯 pip) → fluidsynth(需系统库) → 内置 numpy 合成器,任意一级失败都打印清晰的 [降级] 提示并继续下一级,永远产出可用结果,不再神秘崩溃。.sf2。本机自带的 UprightPianoKW 在 v8 实测仍会被 tinysoundfont 拒(触发降级到 numpy)——这是 SF2 兼容性而非代码问题,换一个 tinysoundfont 支持的 SF2 即生效。在 v8 的"转录+五线谱闭环"基础上,把"按歌型选参 + 自动修错音 + 节奏对齐 + 效果自检"固化进脚本,全部纯 Python 实现,不新增任何依赖。
把"按歌型选参数"做成三个配方,省去记忆一长串 flag:
| 预设 | 适用 | 关键参数 |
|---|---|---|
ballad |
干净抒情歌 | --max-voices 4 --snap-to-key --quantize 8 --vel-smooth 0.5 --reverb 0.22(去鼓压力小) |
pop |
满编流行歌 | --hpss --max-voices 5 --snap-to-key --quantize 16 --vel-smooth 0.4(鼓点多,先分离再限复音) |
solo |
清唱 / 独奏 | --max-voices 0 --snap-to-key off --quantize 0 --vel-smooth 0.6(尽量保真,不误伤装饰音) |
预设是参数基底:任何显式 CLI 参数都会覆盖预设同名项;未显式给出的参数沿用预设值。
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --preset pop
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --preset ballad --reverb 0.3 # 预设基础上微调
basic-pitch 转录流行歌时,常把人声/贝斯/鼓误判成离调怪音。开启后会先估计调性(按时长加权的音阶覆盖率选大/小调),再把"音阶级不在音阶内"的音就近吸附回音阶、修掉疑似错音;已在音阶内的音不动,因此不会破坏原本正确的旋律与和声。调性估计偏保守,仅在明显离调时位移,不改变整体调式。
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --snap-to-key
把转录出来"犹豫/抢拍"的起止时间对齐到规整节奏,听感更稳。网格基于估计拍速(拍速估偏时自动夹到 [40,240] 防崩)。
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --quantize 16 # 十六分网格
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --quantize 8 # 八分网格(更柔)
每次转换默认在同目录写出 <输出名>_质检报告.txt,包含:估计调性、拍速、总时长、音符总数 / 密度、音域、峰值同时音数、离调(疑似错音)占比、本次生效的处理选项、清洗前后音数对比。离调占比高时报告会主动提示"开 --snap-to-key / 满编歌加 --hpss --max-voices"。用 --no-report 可关闭。
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 # 自动产出 out_质检报告.txt
python scripts/mp3_to_piano.py song.mp3 -o out.mp3 --no-report # 不想要报告
注:质检报告基于 basic-pitch 原始转录统计,调性/拍速为"估计值"仅供方向性参考,不保证绝对准确(尤其满编歌)。它用于快速判断"这版转录烂不烂、该往哪个方向调",而非定音鼓式精确分析。
--quantize(显式节奏量化) 与 --snap-to-key(调性吸附) 缓解,但要达到"录音级准",仍需更强转录器(如 demucs 分离后转录)或经五线谱 --from 人工精修闭环。<输出名>_质检报告.txt(调性/拍速/密度/音域/峰值复音/离调占比/处理选项/清洗前后对比),离调占比高会自动建议调 --snap-to-key / --hpss / --max-voices。--hpss 分离打击乐(只把旋律轨喂给转录器,实测低频误判 -68%);若要更彻底的「人声 / 鼓 / 贝斯 / 其他」四轨分离,可用 demucs 分离后再分别转录,产出「人声旋律钢琴版 / 纯伴奏钢琴版」——翻弹用户最常要的两种形态(demucs 需装 torch,本机网络慢,优先级低于 --hpss)。--min-note-len 已暴露(v7):快歌装饰音/grace note 会被 basic-pitch 默认 ~127ms 阈值静默丢弃导致「丢音」;现已暴露为 --min-note-len(默认 0.045s)可微调。--dir 批量 + 进度条。这个技能的最新版本可以在7w4.net小葱技能站找到。
.sf2 切换。--soundfont。质量较好,核心技术扎实、文档详尽、调参指引充分。优点是音色可调(从数学合成到真实采样钢琴)、自动降级不怕崩、五线谱导出无需联网。不足是依赖较多(ffmpeg等),转录质量受原曲影响大,不支持批量处理。整体适合愿意按文档调参的用户,纯小白可能需要一些学习成本。