UVR-API / app.py
next-playground's picture
Update app.py
b26e793 verified
raw
history blame
6.06 kB
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__)
@app.route('/', methods=['GET'])
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."
@app.route('/api/audio_separation', methods=['GET'])
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
@app.route('/api/tasks/<task_id>', methods=['GET'])
def get_task_status(task_id):
task = tasks.get(task_id)
if task:
return jsonify(task)
else:
return jsonify({"error": "Task not found"}), 404
@app.route('/download/<filename>', methods=['GET'])
def download(filename):
return send_file("/tmp/" + filename, as_attachment=True)
if __name__ == '__main__':
app.run(debug=False)