Spaces:
Sleeping
Sleeping
from audio_separator.separator import Separator | |
from flask import Flask, request, jsonify, send_file | |
import requests | |
import os | |
import uuid | |
from pathlib import Path | |
import threading | |
import time | |
separator = Separator(output_dir="/tmp") | |
roformer_models = { | |
'BS-Roformer-Viperx-1297.ckpt': 'model_bs_roformer_ep_317_sdr_12.9755.ckpt', | |
'BS-Roformer-Viperx-1296.ckpt': 'model_bs_roformer_ep_368_sdr_12.9628.ckpt', | |
'BS-Roformer-Viperx-1053.ckpt': 'model_bs_roformer_ep_937_sdr_10.5309.ckpt', | |
'Mel-Roformer-Viperx-1143.ckpt': 'model_mel_band_roformer_ep_3005_sdr_11.4360.ckpt' | |
} | |
mdx23c_models = [ | |
'MDX23C_D1581.ckpt', | |
'MDX23C-8KFFT-InstVoc_HQ.ckpt', | |
'MDX23C-8KFFT-InstVoc_HQ_2.ckpt', | |
] | |
mdxnet_models = [ | |
'UVR-MDX-NET-Inst_full_292.onnx', | |
'UVR-MDX-NET_Inst_187_beta.onnx', | |
'UVR-MDX-NET_Inst_82_beta.onnx', | |
'UVR-MDX-NET_Inst_90_beta.onnx', | |
'UVR-MDX-NET_Main_340.onnx', | |
'UVR-MDX-NET_Main_390.onnx', | |
'UVR-MDX-NET_Main_406.onnx', | |
'UVR-MDX-NET_Main_427.onnx', | |
'UVR-MDX-NET_Main_438.onnx', | |
'UVR-MDX-NET-Inst_HQ_1.onnx', | |
'UVR-MDX-NET-Inst_HQ_2.onnx', | |
'UVR-MDX-NET-Inst_HQ_3.onnx', | |
'UVR-MDX-NET-Inst_HQ_4.onnx', | |
'UVR_MDXNET_Main.onnx', | |
'UVR-MDX-NET-Inst_Main.onnx', | |
'UVR_MDXNET_1_9703.onnx', | |
'UVR_MDXNET_2_9682.onnx', | |
'UVR_MDXNET_3_9662.onnx', | |
'UVR-MDX-NET-Inst_1.onnx', | |
'UVR-MDX-NET-Inst_2.onnx', | |
'UVR-MDX-NET-Inst_3.onnx', | |
'UVR_MDXNET_KARA.onnx', | |
'UVR_MDXNET_KARA_2.onnx', | |
'UVR_MDXNET_9482.onnx', | |
'UVR-MDX-NET-Voc_FT.onnx', | |
'Kim_Vocal_1.onnx', | |
'Kim_Vocal_2.onnx', | |
'Kim_Inst.onnx', | |
'Reverb_HQ_By_FoxJoy.onnx', | |
'UVR-MDX-NET_Crowd_HQ_1.onnx', | |
'kuielab_a_vocals.onnx', | |
'kuielab_a_other.onnx', | |
'kuielab_a_bass.onnx', | |
'kuielab_a_drums.onnx', | |
'kuielab_b_vocals.onnx', | |
'kuielab_b_other.onnx', | |
'kuielab_b_bass.onnx', | |
'kuielab_b_drums.onnx', | |
] | |
vrarch_models = [ | |
'1_HP-UVR.pth', | |
'2_HP-UVR.pth', | |
'3_HP-Vocal-UVR.pth', | |
'4_HP-Vocal-UVR.pth', | |
'5_HP-Karaoke-UVR.pth', | |
'6_HP-Karaoke-UVR.pth', | |
'7_HP2-UVR.pth', | |
'8_HP2-UVR.pth', | |
'9_HP2-UVR.pth', | |
'10_SP-UVR-2B-32000-1.pth', | |
'11_SP-UVR-2B-32000-2.pth', | |
'12_SP-UVR-3B-44100.pth', | |
'13_SP-UVR-4B-44100-1.pth', | |
'14_SP-UVR-4B-44100-2.pth', | |
'15_SP-UVR-MID-44100-1.pth', | |
'16_SP-UVR-MID-44100-2.pth', | |
'17_HP-Wind_Inst-UVR.pth', | |
'UVR-De-Echo-Aggressive.pth', | |
'UVR-De-Echo-Normal.pth', | |
'UVR-DeEcho-DeReverb.pth', | |
'UVR-DeNoise-Lite.pth', | |
'UVR-DeNoise.pth', | |
'UVR-BVE-4B_SN-44100-1.pth', | |
'MGM_HIGHEND_v4.pth', | |
'MGM_LOWEND_A_v4.pth', | |
'MGM_LOWEND_B_v4.pth', | |
'MGM_MAIN_v4.pth', | |
] | |
demucs_models = [ | |
'htdemucs_ft.yaml', | |
'htdemucs.yaml', | |
'hdemucs_mmi.yaml', | |
] | |
def roformer_separator(audio, checkpoint_name): | |
full_checkpoint_name = roformer_models[checkpoint_name] | |
separator.load_model(full_checkpoint_name) | |
output_files = separator.separate(audio) | |
stem1 = output_files[0] | |
stem2 = output_files[1] | |
return stem1, stem2 | |
def mdx_vr_separator(audio, checkpoint_name): | |
separator.load_model(checkpoint_name) | |
output_files = separator.separate(audio) | |
stem1 = output_files[0] | |
stem2 = output_files[1] | |
return stem1, stem2 | |
def demucs_separator(audio, checkpoint_name): | |
separator.load_model(checkpoint_name) | |
output_files = separator.separate(audio) | |
stem1 = output_files[0] | |
stem2 = output_files[1] | |
stem3 = output_files[2] | |
stem4 = output_files[3] | |
return stem1, stem2, stem3, stem4 | |
# 任务队列和状态存储 | |
tasks = {} | |
def process_audio_separation(task_id, mp3_url): | |
try: | |
# 下载MP3文件到本地 | |
response = requests.get(mp3_url) | |
if response.status_code != 200: | |
raise Exception("无效的 URL") | |
mp3_filename = mp3_url.split('/')[-1] | |
with open("/tmp/" + mp3_filename, 'wb') as f: | |
f.write(response.content) | |
# 执行音频分离操作 | |
mdxnet_stem1, mdxnet_stem2 = mdx_vr_separator("/tmp/" + mp3_filename, 'UVR-MDX-NET-Inst_HQ_3.onnx') | |
# 生成分离后的文件名 | |
vocals_filename = f"{os.path.splitext(mp3_filename)[0]}_vocals.wav" | |
no_vocals_filename = f"{os.path.splitext(mp3_filename)[0]}_no_vocals.wav" | |
# 保存结果 | |
with open(vocals_filename, 'wb') as file: | |
file.write(mdxnet_stem1) | |
with open(no_vocals_filename, 'wb') as file: | |
file.write(mdxnet_stem2) | |
# 提供文件的永久直链 | |
vocals_url = f"/download/{os.path.basename(vocals_filename)}" | |
no_vocals_url = f"/download/{os.path.basename(no_vocals_filename)}" | |
# 更新任务状态 | |
tasks[task_id] = { | |
"status": "completed", | |
"vocals_url": vocals_url, | |
"no_vocals_url": no_vocals_url | |
} | |
except Exception as e: | |
tasks[task_id] = { | |
"status": "error", | |
"message": str(e) | |
} | |
app = Flask(__name__) | |
def hello(): | |
return "Hello! This is an api server, and it is running successfully. For usage, please contact the person who hosted this api server." | |
def audio_separation(): | |
mp3_url = request.args.get('url') | |
if not mp3_url: | |
return jsonify({"error": "URL parameter is required"}), 400 | |
task_id = str(uuid.uuid4()) | |
tasks[task_id] = {"status": "processing"} | |
# 异步执行任务 | |
threading.Thread(target=process_audio_separation, args=(task_id, mp3_url)).start() | |
return jsonify({"task_id": task_id}), 202 | |
def get_task_status(task_id): | |
task = tasks.get(task_id) | |
if task: | |
return jsonify(task) | |
else: | |
return jsonify({"error": "Task not found"}), 404 | |
def download(filename): | |
return send_file("/tmp/" + filename, as_attachment=True) | |
if __name__ == '__main__': | |
app.run(debug=False) |