Spaces:
Running
Running
File size: 3,630 Bytes
e976963 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
import gc
import hashlib
import os
import shlex
import subprocess
import librosa
import numpy as np
import soundfile as sf
import gradio as gr
from rvc import Config, load_hubert, get_vc, rvc_infer
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
rvc_models_dir = os.path.join(BASE_DIR, 'rvc_models')
output_dir = os.path.join(BASE_DIR, 'song_output')
def get_rvc_model(voice_model):
model_dir = os.path.join(rvc_models_dir, voice_model)
rvc_model_path = next((os.path.join(model_dir, f) for f in os.listdir(model_dir) if f.endswith('.pth')), None)
rvc_index_path = next((os.path.join(model_dir, f) for f in os.listdir(model_dir) if f.endswith('.index')), None)
if rvc_model_path is None:
error_msg = f'В каталоге {model_dir} отсутствует файл модели.'
raise Exception(error_msg)
return rvc_model_path, rvc_index_path
def convert_to_stereo(audio_path):
wave, sr = librosa.load(audio_path, mono=False, sr=44100)
if type(wave[0]) != np.ndarray:
stereo_path = f'Voice_stereo.wav'
command = shlex.split(f'ffmpeg -y -loglevel error -i "{audio_path}" -ac 2 -f wav "{stereo_path}"')
subprocess.run(command)
return stereo_path
else:
return audio_path
def get_hash(filepath):
with open(filepath, 'rb') as f:
file_hash = hashlib.blake2b()
while chunk := f.read(8192):
file_hash.update(chunk)
return file_hash.hexdigest()[:11]
def display_progress(percent, message, progress=gr.Progress()):
progress(percent, desc=message)
def voice_change(voice_model, vocals_path, output_path, pitch_change, f0_method, index_rate, filter_radius, rms_mix_rate, protect, crepe_hop_length):
rvc_model_path, rvc_index_path = get_rvc_model(voice_model)
device = 'cuda:0'
config = Config(device, True)
hubert_model = load_hubert(device, config.is_half, os.path.join(rvc_models_dir, 'hubert_base.pt'))
cpt, version, net_g, tgt_sr, vc = get_vc(device, config.is_half, config, rvc_model_path)
rvc_infer(rvc_index_path, index_rate, vocals_path, output_path, pitch_change, f0_method, cpt, version, net_g,
filter_radius, tgt_sr, rms_mix_rate, protect, crepe_hop_length, vc, hubert_model)
del hubert_model, cpt
gc.collect()
def song_cover_pipeline(uploaded_file, voice_model, pitch_change, index_rate=0.5, filter_radius=3, rms_mix_rate=0.25, f0_method='rmvpe',
crepe_hop_length=128, protect=0.33, output_format='mp3', progress=gr.Progress()):
if not uploaded_file or not voice_model:
raise Exception('Убедитесь, что поле ввода песни и поле модели голоса заполнены.')
display_progress(0, '[~] Запуск конвейера генерации AI-кавера...', progress)
if not os.path.exists(uploaded_file):
error_msg = f'{uploaded_file} не существует.'
raise Exception(error_msg)
song_id = get_hash(uploaded_file)
song_dir = os.path.join(output_dir, song_id)
os.makedirs(song_dir, exist_ok=True)
orig_song_path = convert_to_stereo(uploaded_file)
ai_cover_path = os.path.join(song_dir, f'Converted_Voice.{output_format}')
if os.path.exists(ai_cover_path):
os.remove(ai_cover_path)
display_progress(0.5, '[~] Преобразование вокала...', progress)
voice_change(voice_model, orig_song_path, ai_cover_path, pitch_change, f0_method, index_rate,
filter_radius, rms_mix_rate, protect, crepe_hop_length)
return ai_cover_path
|