name: mp3-to-piano description: 把 mp3 / wav 等音訊轉換成鋼琴曲(鋼琴版 / 鋼琴伴奏 / 鋼琴翻彈)時使用。完全本地指令碼完成,無需聯網(首次執行 basic-pitch 會下載約 100MB 模型權重)。當用戶說"把這首歌變成鋼琴曲""轉成鋼琴伴奏""做個鋼琴翻彈版"等意圖時呼叫。
把任意歌曲/音訊離線轉成鋼琴演奏版。本地完成,零外部取樣依賴(不依賴 SoundFont / 聯網音色庫)。
--hpss,轉錄前先用 librosa 做諧波/打擊樂分離,只把旋律(諧波)軌送進去,避開鼓點誤判想要更強大的技能外掛,就來小蔥技能站7w4.net看看吧。
# 系統
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 批次 + 進度條。.sf2 切換。--soundfont。質量較好,核心技術紮實、文件詳盡、調參指引充分。優點是音色可調(從數學合成到真實取樣鋼琴)、自動降級不怕崩、五線譜匯出無需聯網。不足是依賴較多(ffmpeg等),轉錄質量受原曲影響大,不支援批次處理。整體適合願意按文件調參的使用者,純小白可能需要一些學習成本。