Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import os | |
| import asyncio | |
| import shutil | |
| from datetime import datetime | |
| import urllib.request | |
| import zipfile | |
| import gdown | |
| import requests | |
| import logging | |
| # Настройка логирования | |
| logging.basicConfig(level=logging.INFO) | |
| # Константы | |
| f0_min = 50 | |
| f0_max = 1100 | |
| rvc_models_dir = './models' | |
| input_folder = './input' | |
| output_folder = './output' | |
| # Создание необходимых директорий | |
| os.makedirs(rvc_models_dir, exist_ok=True) | |
| os.makedirs(input_folder, exist_ok=True) | |
| os.makedirs(output_folder, exist_ok=True) | |
| # Общие функции | |
| async def run_command_async(command): | |
| """Асинхронный запуск команд.""" | |
| process = await asyncio.create_subprocess_shell( | |
| command, | |
| stdout=asyncio.subprocess.PIPE, | |
| stderr=asyncio.subprocess.PIPE | |
| ) | |
| stdout, stderr = await process.communicate() | |
| if process.returncode != 0: | |
| logging.error(f"Error: {stderr.decode()}") | |
| return stdout.decode() | |
| def get_models_list(): | |
| """Получение списка моделей.""" | |
| models = [] | |
| if os.path.exists(rvc_models_dir): | |
| models = [d for d in os.listdir(rvc_models_dir) if os.path.isdir(os.path.join(rvc_models_dir, d))] | |
| return models | |
| # Функции для первой вкладки | |
| def process_uploaded_files(files): | |
| """Обработка загруженных файлов.""" | |
| if os.path.exists(input_folder): | |
| shutil.rmtree(input_folder) | |
| os.makedirs(input_folder, exist_ok=True) | |
| for file in files: | |
| shutil.copy(file.name, input_folder) | |
| return f"Uploaded {len(files)} files to {input_folder}" | |
| async def convert_voice( | |
| voicemodel_name, | |
| pitch_vocal, | |
| method_pitch, | |
| hop_length, | |
| index_rate, | |
| filter_radius, | |
| rms, | |
| protect, | |
| output_format | |
| ): | |
| """Конвертация голоса.""" | |
| current_time = datetime.now().strftime("%Y-%m-%d_%H-%M-%S") | |
| output_ai_vocals_folder = os.path.join(output_folder, current_time) | |
| os.makedirs(output_ai_vocals_folder, exist_ok=True) | |
| output_test = { | |
| "mp3": "-ab 320k", | |
| "wav": "-c:a pcm_s32le", | |
| "flac": "-c:a flac -af aformat=s16" | |
| }[output_format] | |
| for filename in os.listdir(input_folder): | |
| if filename.endswith(("wav", "mp3", "flac")): | |
| input_path = os.path.join(input_folder, filename) | |
| base_name = os.path.splitext(filename)[0] | |
| output_filename = f"mono_{base_name}_{current_time}_{method_pitch}_{pitch_vocal}.{output_format}" | |
| output_path = os.path.join(output_ai_vocals_folder, output_filename) | |
| # Выполнение команды RVC | |
| await run_command_async( | |
| f"python3 -m rvc.cli.rvc_cli -i \"{input_path}\" -m \"{voicemodel_name}\" -p {pitch_vocal} " | |
| f"-ir {index_rate} -fr {filter_radius} -rms {rms} -f0 \"{method_pitch}\" " | |
| f"-hop {hop_length} -pro {protect} -f0min {f0_min} -f0max {f0_max} -f \"wav\"" | |
| ) | |
| # Конвертация в нужный формат | |
| await run_command_async( | |
| f"ffmpeg -y -i ./output/Voice_Converted.wav " | |
| f"-vn -ar 44100 -ac 1 {output_test} \"{output_path}\"" | |
| ) | |
| return [os.path.join(output_ai_vocals_folder, f) for f in os.listdir(output_ai_vocals_folder) if f.endswith(output_format)] | |
| # Функции для второй вкладки | |
| def extract_zip(extraction_folder, zip_name): | |
| """Распаковка архива.""" | |
| os.makedirs(extraction_folder, exist_ok=True) | |
| with zipfile.ZipFile(zip_name, 'r') as zip_ref: | |
| zip_ref.extractall(extraction_folder) | |
| os.remove(zip_name) | |
| model_file = next((f for f in os.listdir(extraction_folder) if f.endswith('.pth')), None) | |
| index_file = next((f for f in os.listdir(extraction_folder) if f.endswith('.index')), None) | |
| if model_file: | |
| os.rename(os.path.join(extraction_folder, model_file), | |
| os.path.join(extraction_folder, model_file)) | |
| if index_file: | |
| os.rename(os.path.join(extraction_folder, index_file), | |
| os.path.join(extraction_folder, index_file)) | |
| async def download_model(url, dir_name): | |
| """Скачивание модели.""" | |
| try: | |
| zip_path = os.path.join(rvc_models_dir, f"{dir_name}.zip") | |
| extraction_path = os.path.join(rvc_models_dir, dir_name) | |
| if os.path.exists(extraction_path): | |
| return f"Error: Directory {dir_name} already exists!" | |
| if 'drive.google.com' in url: | |
| file_id = url.split("file/d/")[1].split("/")[0] if "file/d/" in url else url.split("id=")[1].split("&")[0] | |
| gdown.download(id=file_id, output=zip_path, quiet=False) | |
| elif 'huggingface.co' in url: | |
| urllib.request.urlretrieve(url, zip_path) | |
| elif 'pixeldrain.com' in url: | |
| file_id = url.split("pixeldrain.com/u/")[1] | |
| response = requests.get(f"https://pixeldrain.com/api/file/{file_id}") | |
| with open(zip_path, 'wb') as f: | |
| f.write(response.content) | |
| extract_zip(extraction_path, zip_path) | |
| return f"Model {dir_name} successfully installed!" | |
| except Exception as e: | |
| return f"Error: {str(e)}" | |
| # Создание интерфейса | |
| with gr.Blocks() as demo: | |
| gr.Markdown("# VBach Lite WEBUI") | |
| with gr.Tabs(): | |
| # Первая вкладка | |
| with gr.TabItem("Замена вокала"): | |
| with gr.Row(): | |
| with gr.Column(): | |
| file_input = gr.File(file_count="multiple", label="Загрузить один или несколько файлов") | |
| upload_status = gr.Textbox(label="Статус загрузки") | |
| file_input.upload( | |
| fn=process_uploaded_files, | |
| inputs=file_input, | |
| outputs=upload_status | |
| ) | |
| with gr.Accordion("Настройки RVC:", open=True): | |
| voicemodel_name = gr.Dropdown( | |
| choices=get_models_list(), | |
| label="Имя модели", | |
| value="senko" if "senko" in get_models_list() else None | |
| ) | |
| refresh_btn = gr.Button("Обновить") | |
| pitch_vocal = gr.Slider(-48, 48, value=0, step=12, label="Высота тона") | |
| method_pitch = gr.Dropdown( | |
| ["fcpe", "rmvpe+", "mangio-crepe"], | |
| value="rmvpe+", | |
| label="Метод извлечения тона" | |
| ) | |
| hop_length = gr.Slider(0, 255, value=73, step=1, label="Длина шага для mangio-crepe") | |
| index_rate = gr.Slider(0, 1, value=1, step=0.05, label="ИИ-акцент") | |
| filter_radius = gr.Slider(0, 7, value=7, step=1, label="Радиус фильтра") | |
| rms = gr.Slider(0, 1, value=0, step=0.1, label="Нормализация") | |
| protect = gr.Slider(0, 0.5, value=0.35, step=0.05, label="Защита согласных") | |
| output_format = gr.Dropdown( | |
| ["flac", "wav", "mp3"], | |
| value="mp3", | |
| label="Формат вывода" | |
| ) | |
| convert_btn = gr.Button("Преобразовать!", variant="primary") | |
| with gr.Column(): | |
| output_files = gr.Files(label="Аудио с преобразованным вокалом") | |
| # Обработчики | |
| refresh_btn.click( | |
| fn=lambda: gr.update(choices=get_models_list()), | |
| outputs=voicemodel_name | |
| ) | |
| convert_btn.click( | |
| fn=convert_voice, | |
| inputs=[ | |
| voicemodel_name, | |
| pitch_vocal, | |
| method_pitch, | |
| hop_length, | |
| index_rate, | |
| filter_radius, | |
| rms, | |
| protect, | |
| output_format | |
| ], | |
| outputs=output_files | |
| ) | |
| # Вторая вкладка | |
| with gr.TabItem("Скачать модель"): | |
| with gr.Row(): | |
| with gr.Column(): | |
| gr.Markdown("## Здесь можно скачать модель по ссылке на архив с нею") | |
| url_input = gr.Textbox( | |
| label="Ссылка на архив с моделью", | |
| placeholder="хаггингфейс.ко/модель.zip" | |
| ) | |
| dir_name_input = gr.Textbox( | |
| label="Имя модели", | |
| placeholder="Имя модели" | |
| ) | |
| download_btn = gr.Button("Скачать модель", variant="primary") | |
| install_status = gr.Textbox(label="Статус скачивания модели") | |
| download_btn.click( | |
| fn=download_model, | |
| inputs=[url_input, dir_name_input], | |
| outputs=install_status | |
| ) | |
| with gr.Column(): | |
| gr.Markdown("## Проверить список моделей") | |
| model_list = gr.Textbox( | |
| value="\n".join(get_models_list()), | |
| lines=10, | |
| label="Установленные модели" | |
| ) | |
| refresh_models_btn = gr.Button("Обновить") | |
| refresh_models_btn.click( | |
| fn=lambda: gr.update(value="\n".join(get_models_list())), | |
| outputs=model_list | |
| ) | |
| if __name__ == "__main__": | |
| demo.launch(server_name="0.0.0.0", server_port=7860) |