有,使用demucs进行人声伴奏提取,然后对提取的Basic Pitch 伴奏转录为 MIDI 音符,如果精度不够,demucs可可指定提取单个乐器的伴奏,Demucs 的 htdemucs_6s 模型可以分离出 6 种音轨:鼓、贝斯、其他、人声、钢琴、吉他。
cmd = [ sys.executable, "-m", "demucs", "--two-stems", "other", # 只分离出“其他乐器(伴奏主体)” "-n", "htdemucs_6s", # 指定使用 6 分轨模型 "-o", output_dir, input_audio_path ]如果你只把分离出来的 piano.wav 或 guitar.wav 喂给 Basic Pitch,精度会呈指数级上升
示例代码如下:
import os
import sys
import subprocess
from basic_pitch import ICASSP_2022_MODEL_PATH
from basic_pitch.inference import predict_and_save
# ==============================================================================
# Step 1: 使用 Demucs 进行人声伴奏分离
# ==============================================================================
def separate_vocals(input_audio_path, output_dir):
print("\n[Step 1] 正在使用 Demucs 进行人声与伴奏分离...")
# --two-stems=vocals 参数会将音频分离为人声 (vocals.wav) 和伴奏 (no_vocals.wav)
cmd = [
sys.executable, "-m", "demucs",
"--two-stems", "vocals",
"-o", output_dir,
input_audio_path
]
# 运行 Demucs 分离任务
subprocess.run(cmd, check=True)
# 查找分离出的伴奏文件
track_name = os.path.splitext(os.path.basename(input_audio_path))[0]
# Demucs 默认模型通常输出在 output_dir/htademucs/{track_name}/no_vocals.wav
accompaniment_path = os.path.join(output_dir, "htademucs", track_name, "no_vocals.wav")
# 备用检索:若因版本结构变化导致路径不同,则在输出目录下全局搜索伴奏文件
if not os.path.exists(accompaniment_path):
for root, dirs, files in os.walk(output_dir):
if "no_vocals.wav" in files:
accompaniment_path = os.path.join(root, "no_vocals.wav")
break
if not os.path.exists(accompaniment_path):
raise FileNotFoundError("未能找到分离后的伴奏文件 no_vocals.wav,请检查分离过程。")
print(f"-> 伴奏分离成功!文件保存在: {accompaniment_path}")
return accompaniment_path
# ==============================================================================
# Step 2: 使用 Basic Pitch 将提取的伴奏转录为 MIDI 音符
# ==============================================================================
def extract_melody_to_midi(accompaniment_path, output_dir):
print("\n[Step 2] 正在使用 Spotify Basic Pitch 转录伴奏旋律为 MIDI...")
predict_and_save(
audio_path_list=[accompaniment_path],
output_directory=output_dir,
save_midi=True,
sonify_midi=False, # 新增:是否合成MIDI音频
save_model_outputs=False,
save_notes=False,
model_or_model_path=ICASSP_2022_MODEL_PATH, # 新增:指定模型
onset_threshold=0.5, # 音头阈值 (0~1)。调高(如0.6)可减少幽灵音符;调低(如0.3)可捕捉更多微弱发音
frame_threshold=0.3, # 帧阈值 (0~1)。控制音符持续时的稳定性,调高可减少断断续续的碎音
)
track_name = os.path.splitext(os.path.basename(accompaniment_path))[0]
midi_path = os.path.join(output_dir, f"{track_name}_basic_pitch.mid")
if not os.path.exists(midi_path):
raise FileNotFoundError(f"未能成功生成 MIDI 文件: {midi_path}")
print(f"-> MIDI 转录成功!文件保存在: {midi_path}")
return midi_path
网友回复


