本文逐管线列出每一层过滤/处理用到的开源项目、模型与技术(含许可证)。 四条管线共享
core(契约 + 谱面渲染)底座;GUI(Gradio)在最上层把它们串起来。 渲染说明:本文用 Mermaid 流程图,GitHub / VS Code 可直接预览。
flowchart TD
GUI["🖥️ Gradio Web GUI (app.py)"]:::ui
subgraph CORE["musicmaster.core — 共享底座"]
CT["契约 contracts<br/>(F0/Target/TargetF0Frames)"]:::core
RD["谱面渲染 render<br/>Verovio 五线谱 · jianpu-ly+LilyPond 简谱"]:::core
end
GUI --> A & B & C & D
A["🎚️ 管线A 修音换音色 (vocal, GPU)"]:::pa
B["🔊 管线B 人声分离 (separate, GPU)"]:::pb
C["🎤 管线C 扒谱 (transcribe, CPU)"]:::pc
D["🎼 管线D 互转 (convert, CPU)"]:::pd
B -->|"干净主唱"| A
B -->|"清唱/单旋律"| C
C -->|"MusicXML"| D
C --> RD
D --> RD
A --> OUT1["成品人声<br/>在调+干净+仍是你"]:::out
B --> OUT2["人声/伴奏/去和声/干净主唱"]:::out
C --> OUT3["五线谱 + 简谱 + 逐音可信度"]:::out
D --> OUT4["简谱 ⇄ 五线谱"]:::out
classDef ui fill:#6d28d9,color:#fff,stroke:#4c1d95
classDef core fill:#0f766e,color:#fff,stroke:#134e4a
classDef pa fill:#b91c1c,color:#fff,stroke:#7f1d1d
classDef pb fill:#1d4ed8,color:#fff,stroke:#1e3a8a
classDef pc fill:#a16207,color:#fff,stroke:#713f12
classDef pd fill:#15803d,color:#fff,stroke:#14532d
classDef out fill:#334155,color:#fff,stroke:#0f172a
模块互通:分离(B)产出的「去和声干净主唱」既喂给修音(A)当目标旋律参考,也可当扒谱(C)的清唱输入;扒谱(C)产出的 MusicXML 可进互转(D);C/D 都用 core 的渲染层出图。
把跑调清唱修成「在调 + 干净 + 仍是本人音色」。两段式:先修音准(保音色只改音高),再用 SVC 以用户自己的声音重生成(洗掉瑕疵、补弱唱)。
flowchart TD
RAW["用户原始清唱 RAW"]:::in
REF["去和声干净参考 REF<br/>(来自管线B)"]:::in
SELF["用户自己清唱 SELF<br/>(身份锚 ~10-30s)"]:::in
subgraph S1["Stage 1 · 修音准 (DiffPitcher, run_qt4)"]
direction TB
F0["① 目标 f0 提取<br/><b>torchcrepe</b> (CREPE 'full')<br/>锁主旋律 · 抗和声"]:::step
MEL["② 源音色 mel + MCEP 特征<br/><b>WORLD / pyworld</b><br/>(get_world_mel / code_spectral_envelope)"]:::step
DTW["③ 时间对齐<br/><b>fastdtw</b> (MCEP DTW)"]:::step
CLEAN["④ 目标 f0 清洗<br/>(去八度跳/中值滤波/去碎段)"]:::step
DIFF["⑤ 扩散修音高<br/><b>DiffPitcher UNetPitcher</b><br/>+ <b>diffusers</b> DDIMScheduler (eta=0 确定性)"]:::step
VOC1["⑥ 声码器<br/><b>BigVGAN</b> → 24kHz"]:::step
F0 --> DTW
MEL --> DTW --> CLEAN --> DIFF --> VOC1
end
RS["resample 24k → 44.1k<br/><b>librosa</b>"]:::step
subgraph S2["Stage 2 · 换音色=本人 (Seed-VC inference)"]
direction TB
SEM["⑦ 语义特征(音素,声纹无关)<br/><b>OpenAI Whisper</b> (whisper-small)"]:::step
SPK["⑧ 目标音色嵌入<br/><b>CAMPPlus</b> (funasr)"]:::step
F0B["⑨ f0 条件<br/><b>RMVPE</b>"]:::step
DIT["⑩ DiT + flow matching<br/><b>Seed-VC</b>"]:::step
VOC2["⑪ 声码器<br/><b>BigVGAN v2</b> (44kHz)"]:::step
SEM --> DIT
SPK --> DIT
F0B --> DIT --> VOC2
end
RAW --> MEL
REF --> F0
VOC1 --> RS --> DIT
SELF --> SPK
VOC2 --> OUT["🎧 成品:在调 + 干净 + 仍是你"]:::out
classDef in fill:#7f1d1d,color:#fff
classDef step fill:#fee2e2,color:#7f1d1d,stroke:#b91c1c
classDef out fill:#334155,color:#fff
关键设计(血泪经验):
- 目标 f0 用 torchcrepe 而非 WORLD dio —— dio 在副歌高音区会跟错和声(跳三五度),导致「高音发哑」;CREPE 锁主旋律。所以 REF 必须先去和声(管线 B 的第 2 段)。
- 扩散 eta=0(确定性 DDIM)去帧间抖;声码器用 BigVGAN(神经)而非纯 DSP,消除 WORLD 重合成的「坑洼/电音」。
- Stage 2 的 SVC 目标音色 = 用户自己(不是明星)→ 产品定位是「身份保留型美化」,且重生成天然洗掉颤音/失真、补弱唱段。
三段级联,统一经 audio-separator 后端(MIT)加载/推理/下权重。各段可单独启停。
flowchart LR
MIX["混音 (mp3/wav)"]:::in
S1["① 分离<br/><b>BS-RoFormer</b><br/>(ep_317_sdr_12.9755)"]:::step
S2["② 去和声<br/><b>Mel-Band RoFormer Karaoke</b><br/>(gabox_v2)"]:::step
S3["③ 降噪提纯<br/><b>UVR-DeEcho-DeReverb</b>"]:::step
MIX --> S1 -->|"人声"| S2 -->|"纯主唱"| S3 --> LEAD["干净主唱"]:::out
S1 -->|"伴奏"| ACC["伴奏"]:::out
classDef in fill:#1e3a8a,color:#fff
classDef step fill:#dbeafe,color:#1e3a8a,stroke:#1d4ed8
classDef out fill:#334155,color:#fff
| 段 | 默认模型 | 备选(经 audio-separator) | 作用 |
|---|---|---|---|
| 1 分离 | BS-RoFormer | Demucs htdemucs/_ft、karaoke_roformer | 混音 → 人声 + 伴奏 |
| 2 去和声 | Karaoke Mel-Band RoFormer gabox_v2 | becruily、aufr33(实测抽水,不荐) | 人声 → 纯主唱(去 backing vocals) |
| 3 降噪 | UVR-DeEcho-DeReverb | UVR-De-Echo-Normal | 纯主唱 → 干净主唱(不闷) |
默认链由原项目盲听选定。普通分离(Demucs/Spleeter/BS-RoFormer)只分人声/伴奏、不去和声;真正「去 backing vocals」靠第 2 段的 Karaoke RoFormer。
「去专家化外壳」:零调参 + 烂输入门口拦 + 绝不沉默地错(逐音标可信度)。
flowchart TD
AUD["音频(清唱/单旋律)"]:::in
L1["L1 入口质量门 (quality)<br/><b>librosa</b> STFT 测真实有效带宽<br/>+ <b>ffprobe</b> 容器元数据 → 档位/门控/修法"]:::gate
ENG{"L2 选引擎"}:::dec
E1["<b>CREPE</b> 单旋律(默认)<br/>→ 音符级中位数赋音高 + 毛刺平滑<br/>(transcribe2)"]:::step
E2["<b>basic-pitch</b> (Spotify)<br/>通用复音兜底"]:::step
E3["<b>piano_transcription_inference</b><br/>(ByteDance) 钢琴复音"]:::step
KEY["定调<br/><b>Krumhansl-Schmuckler</b> (chroma+K-S)<br/>→ 1=主音(治半音汤)"]:::step
GEN["音符 → 谱<br/><b>music21</b> MusicXML(写正确调号)<br/>+ <b>pretty_midi</b> MIDI"]:::step
L3["L3 逐音可信度 (confidence)<br/>成串调外 × 双算法分歧(<b>CREPE</b>+<b>pyin</b>)<br/>× 跟踪自信 × L1折 → 存疑段标注"]:::gate
R1["五线谱<br/><b>Verovio</b> → staff.svg"]:::step
R2["简谱<br/><b>jianpu-ly</b> → .ly → <b>LilyPond</b> CLI → jianpu.pdf"]:::step
AUD --> L1 --> ENG
ENG -->|"单旋律"| E1
ENG -->|"复音乐器"| E2
ENG -->|"干净钢琴"| E3
E1 --> KEY
E2 --> KEY
E3 --> KEY
KEY --> GEN --> L3
GEN --> R1
GEN --> R2
L3 --> OUT["notes.json + MIDI + MusicXML<br/>+ 五线谱 + 简谱 + 报告.md(含存疑段)"]:::out
classDef in fill:#713f12,color:#fff
classDef step fill:#fef3c7,color:#713f12,stroke:#a16207
classDef gate fill:#fde68a,color:#713f12,stroke:#a16207,stroke-width:3px
classDef dec fill:#f59e0b,color:#fff
classDef out fill:#334155,color:#fff
为什么三层(原项目教训):坏录音上 CREPE 自信、pyin 有声、两算法一致会同时失灵(算法自信地异口同声地错),唯「成串调外/漂移」能暴露 → L3 的主信号就是它。L1 在门口就能拦下「8kHz 假冒 44.1k」的烂输入。调外 ≠ 错(真曲有变化音),故只对成串调外标「存疑」,绝不武断判错。
简谱文本 .jianpu 与五线谱 MusicXML/MIDI/ABC 双向无损互转,以 music21.Score 为枢轴;load_any() 统一导入(= 支持简谱/五线谱导入)。
flowchart LR
JP[".jianpu 简谱文本"]:::in
XML["MusicXML / MIDI / ABC"]:::in
PIVOT["<b>music21</b> Score(枢轴)"]:::step
JP -->|"parse_jianpu"| PIVOT
XML -->|"load_any (music21.converter)"| PIVOT
PIVOT -->|"score_to_jianpu"| JPO[".jianpu"]:::out
PIVOT -->|"score.write"| XMLO["MusicXML"]:::out
PIVOT -->|"渲染"| RND["五线谱(Verovio) / 简谱(jianpu-ly+LilyPond)"]:::out
classDef in fill:#14532d,color:#fff
classDef step fill:#dcfce7,color:#14532d,stroke:#15803d
classDef out fill:#334155,color:#fff
实测:五线谱→简谱→五线谱 往返音高完全一致(本项目示例 examples/twinkle.jianpu 往返逐字无损)。
| 管线·层 | 开源项目 / 模型 | 许可证 | 角色 |
|---|---|---|---|
| A 修音 目标 f0 | torchcrepe (CREPE) | MIT | 锁主旋律抗和声的目标音高 |
| A 修音 音色/对齐 | WORLD / pyworld | MIT/改BSD | 源 mel、MCEP 特征 |
| A 修音 对齐 | fastdtw | MIT | 参考 f0 时间规整 |
| A 修音 扩散 | DiffPitcher (UNetPitcher) | MIT | 保音色改音高的扩散模型 |
| A 修音 调度 | diffusers (DDIMScheduler) | Apache-2.0 | 确定性采样(eta=0) |
| A 修音 声码器 | BigVGAN | MIT | mel → 24kHz 波形 |
| A 换音色 语义 | OpenAI Whisper (small) | MIT | 声纹无关音素特征 |
| A 换音色 音色 | CAMPPlus (funasr) | Apache-2.0 | 目标音色嵌入(身份) |
| A 换音色 f0 | RMVPE | MIT | 歌唱 f0 条件 |
| A 换音色 转换 | Seed-VC | 见上游 | DiT + flow matching 声线转换 |
| A 换音色 声码器 | BigVGAN v2 (44k) | MIT | mel → 44.1kHz 波形 |
| B 分离 后端 | audio-separator | MIT | 统一加载/推理/下权重 |
| B 分离 第1段 | BS-RoFormer | 见上游 | 人声/伴奏分离 |
| B 分离 第2段 | Mel-Band RoFormer Karaoke (gabox_v2) | 见上游(权重视非商用) | 去和声 |
| B 分离 第3段 | UVR DeEcho-DeReverb | 见上游 | 降噪/去混响 |
| B 分离 备选 | Demucs (htdemucs) | MIT(权重 MUSDB18 CC-BY-NC-SA) | 备选分离 |
| C 扒谱 L1 | librosa + ffprobe(FFmpeg) | ISC / LGPL-GPL | 有效带宽/质量门 |
| C 扒谱 引擎① | CREPE | MIT | 单旋律 f0(默认) |
| C 扒谱 引擎① | pyin(librosa) | ISC | 备选/L3 副算法 |
| C 扒谱 引擎② | basic-pitch | Apache-2.0 | 通用复音兜底 |
| C 扒谱 引擎③ | piano_transcription_inference (ByteDance) | MIT码/MAESTRO权重 CC-BY-NC-SA | 钢琴复音 |
| C 扒谱 定调 | Krumhansl-Schmuckler | 公领域算法 | 自动定调写调号 |
| C 扒谱 谱生成 | music21 / pretty_midi | BSD-3 / MIT | MusicXML / MIDI |
| C/D 渲染 五线谱 | Verovio | LGPL-3.0 | MusicXML → SVG(作为库) |
| C/D 渲染 简谱 | jianpu-ly | Apache-2.0 | MusicXML → LilyPond .ly |
| C/D 渲染 简谱图 | LilyPond | GPL-3.0 | .ly → SVG/PDF(仅独立子进程) |
| D 互转 枢轴 | music21 | BSD-3 | 简谱 ⇄ 五线谱(含 MIDI/ABC 导入) |
| GUI | Gradio | Apache-2.0 | 单页 Web 界面 |
| 服务(可选) | FastAPI/Uvicorn/Celery/Redis/boto3 | MIT/BSD/Apache | REST API + 队列 + 对象存储 |
合规:LilyPond/FFmpeg 仅子进程调用、Verovio 作库加载;标注 CC-BY-NC-SA/非商用的权重(Karaoke RoFormer、Demucs MUSDB18、ByteDance MAESTRO)个人/研究可用,商用前需替换或单独授权。完整署名见
NOTICE。
四类重依赖互相冲突(CPU torch vs CUDA torch、TensorFlow vs torch、audio-separator 固定 onnxruntime),因此分 venv:
flowchart TD
CORE["venv-core (CPU)<br/>GUI + 扒谱 + 互转 + 渲染<br/>librosa/music21/crepe(TF)/basic-pitch/verovio/jianpu-ly/gradio"]:::v
SEP["venv-sep (GPU)<br/>分离<br/>audio-separator + cu124 torch"]:::v
NEU["venv-neural (GPU)<br/>修音准<br/>torchcrepe/diffusers/pyworld/fastdtw + cu124 torch"]:::v
SVC["venv-svc (GPU)<br/>换音色<br/>Seed-VC(torch==2.4 等锁定版)"]:::v
GUI["app.py (在 venv-core)"]:::g
GUI -->|"直接 import"| CORE
GUI -->|"子进程"| SEP
GUI -->|"子进程(vocal.correct)"| NEU
GUI -->|"子进程(vocal.voice)"| SVC
classDef v fill:#1e293b,color:#fff,stroke:#475569
classDef g fill:#6d28d9,color:#fff
GUI 跑在 venv-core:同 venv 的扒谱/互转直接函数调用;跨 venv 的分离/修音换音色子进程调用(路径由环境变量配置,见 README)。