import os import glob import json import traceback import logging import gradio as gr import numpy as np import librosa import torch import asyncio import edge_tts import sys import io import wave import shutil from datetime import datetime from fairseq import checkpoint_utils from fairseq.data.dictionary import Dictionary from huggingface_hub import snapshot_download from lib.infer_pack.models import ( SynthesizerTrnMs256NSFsid, SynthesizerTrnMs256NSFsid_nono, SynthesizerTrnMs768NSFsid, SynthesizerTrnMs768NSFsid_nono, ) from vc_infer_pipeline import VC from config import Config config = Config() logging.getLogger("numba").setLevel(logging.WARNING) # --- KONFIGURASI DOWNLOAD OTOMATIS DARI REPO MODEL (UPDATED) --- # Mengakses repository baru berdasarkan struktur di screenshot if not os.path.exists("weights"): print("Mendownload weights dan bahan model dari repo Plana-RCV/BanGDream-MyGO...") snapshot_download( repo_id="Plana-Archive/Anime-RCV", local_dir=".", allow_patterns=[ "BanGDream-MyGO/weights/*", "BanGDream-MyGO/hubert_base.pt", "BanGDream-MyGO/rmvpe.pt" ], repo_type="model" ) source_dir = "BanGDream-MyGO" if os.path.exists(source_dir): print(f"Menyusun ulang struktur folder dari {source_dir}...") for item in os.listdir(source_dir): s = os.path.join(source_dir, item) d = os.path.join(".", item) if os.path.isdir(s): if os.path.exists(d): shutil.rmtree(d) shutil.move(s, d) else: shutil.move(s, d) os.rmdir(source_dir) print("Struktur folder berhasil diperbarui.") spaces = True # Setup metode F0 f0method_mode = ["pm", "harvest"] if os.path.isfile("rmvpe.pt"): f0method_mode.insert(2, "rmvpe") def _load_audio_input(tts_text, speed, spaces_limit=20): temp_file = "tts.mp3" if not tts_text or tts_text.strip() == "": return None, None, "EMPTY" if len(tts_text) > 100 and spaces: return None, None, "TOO_LONG" speed_rate = f"{'+' if speed >= 1.0 else '-'}{int(abs(speed - 1.0) * 100)}%" tts_voice_default = "ja-JP-NanamiNeural" asyncio.run(edge_tts.Communicate(tts_text, tts_voice_default, rate=speed_rate).save(temp_file)) audio, sr = librosa.load(temp_file, sr=16000, mono=True) return audio, sr, temp_file def create_vc_fn(model_name, tgt_sr, net_g, vc, if_f0, version, file_index): def vc_fn( tts_text, f0_up_key, f0_method, index_rate, filter_radius, resample_sr, rms_mix_rate, protect, speed_rate, ): logs = [] temp_audio_file = "tts.mp3" try: audio, sr, status = _load_audio_input(tts_text, speed_rate) if status == "EMPTY": return "⚠️ Mohon masukkan teks terlebih dahulu!", None if status == "TOO_LONG": return "❌ Teks terlalu panjang! Maksimal 100 karakter.", None logs.append(f"✨ Model: {model_name}") yield "\n".join(logs), None logs.append("📥 Memuat audio dasar...") logs.append(f"⚙️ Memproses RVC (Pitch: {f0_up_key})...") yield "\n".join(logs), None times = [0, 0, 0] audio_opt = vc.pipeline( hubert_model, net_g, 0, audio, status, times, f0_up_key, f0_method, file_index, index_rate, if_f0, filter_radius, tgt_sr, resample_sr, rms_mix_rate, version, protect, f0_file=None, ) logs.append(f"✅ Selesai pada: {datetime.now().strftime('%H:%M:%S')}") yield "\n".join(logs), (tgt_sr, audio_opt) except Exception as e: traceback.print_exc() return f"❌ Error: {str(e)}", None finally: if os.path.exists(temp_audio_file): os.remove(temp_audio_file) return vc_fn def load_model(): categories = [] folder_info_path = "weights/folder_info.json" if os.path.isfile(folder_info_path): with open(folder_info_path, "r", encoding="utf-8") as f: folder_info = json.load(f) for category_name, category_info in folder_info.items(): if not category_info.get('enable', True): continue category_title = category_info['title'] category_folder = category_info['folder_path'] models = [] model_info_path = os.path.join("weights", category_folder, "model_info.json") if not os.path.exists(model_info_path): continue with open(model_info_path, "r", encoding="utf-8") as f: models_info = json.load(f) for character_name, info in models_info.items(): if not info.get('enable', True): continue base_character_path = os.path.join("weights", category_folder, character_name) cpt_path = os.path.join(base_character_path, info['model_path']) model_cover = os.path.join(base_character_path, info['cover']) model_index = os.path.join(base_character_path, info['feature_retrieval_library']) if not os.path.exists(cpt_path): continue cpt = torch.load(cpt_path, map_location="cpu") tgt_sr, if_f0, version = cpt["config"][-1], cpt.get("f0", 1), cpt.get("version", "v1") if version == "v1": net_g = SynthesizerTrnMs256NSFsid(*cpt["config"], is_half=config.is_half) if if_f0 == 1 else SynthesizerTrnMs256NSFsid_nono(*cpt["config"]) elif version == "v2": net_g = SynthesizerTrnMs768NSFsid(*cpt["config"], is_half=config.is_half) if if_f0 == 1 else SynthesizerTrnMs768NSFsid_nono(*cpt["config"]) if hasattr(net_g, "enc_q"): del net_g.enc_q net_g.load_state_dict(cpt["weight"], strict=False) net_g.eval().to(config.device) net_g = net_g.half() if config.is_half else net_g.float() vc = VC(tgt_sr, config) models.append((character_name, info['title'], info.get("author"), model_cover, version, create_vc_fn(info['model_path'], tgt_sr, net_g, vc, if_f0, version, model_index))) categories.append([category_title, category_folder, category_info.get('description',''), models]) return categories def load_hubert(): global hubert_model torch.serialization.add_safe_globals([Dictionary]) models, _, _ = checkpoint_utils.load_model_ensemble_and_task(["hubert_base.pt"], suffix="",) hubert_model = models[0].to(config.device) hubert_model = hubert_model.half() if config.is_half else hubert_model.float() hubert_model.eval() if __name__ == '__main__': load_hubert() categories = load_model() total_characters = sum(len(cat[3]) for cat in categories) # UPDATED: Background set to White (#ffffff) custom_css = """ .gradio-container { background-color: #ffffff !important; } .tabs { background-color: #ffffff !important; border-radius: 12px; border: 1px solid #d1f2d1 !important; } .primary-btn { background-color: #a8e6cf !important; border: none !important; color: white !important; font-weight: bold !important; } .primary-btn:hover { background-color: #89d9bb !important; } """ with gr.Blocks(theme=gr.themes.Soft(primary_hue="green", secondary_hue="emerald"), css=custom_css) as app: gr.HTML(f"""
RVC-BANG-DREAM • Weights by Plana-Archive
System Status
● ONLINE
Total Characters
{total_characters} Models
Setelah di Generate Voice, audionya akan muncul beberapa detik dan tunggu aja ya!
BanG Dream! RVC Implementation