import os import sys import time import gradio as gr import spaces from huggingface_hub import snapshot_download from pathlib import Path import tempfile from pydub import AudioSegment import traceback # افزودن پوشه src به مسیر سیستم sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), 'src'))) from models.inference.moda_test import LiveVASAPipeline, emo_map, set_seed # --- تنظیمات اولیه --- set_seed(42) DEFAULT_CFG_PATH = "configs/audio2motion/inference/inference.yaml" DEFAULT_MOTION_MEAN_STD_PATH = "src.datasets/mean.pt" DEFAULT_SILENT_AUDIO_PATH = "src/examples/silent-audio.wav" OUTPUT_DIR = "gradio_output" WEIGHTS_DIR = "pretrain_weights" REPO_ID = "lixinyizju/moda" PERSIAN_EMOTION_MAP = { "خنثی (Neutral)": "Neutral", "خوشحال (Happy)": "Happy", "عصبانی (Angry)": "Angry", "غمگین (Sad)": "Sad", "متعجب (Surprise)": "Surprise" } # --- دانلود وزنها --- def download_weights(): motion_model_file = os.path.join(WEIGHTS_DIR, "moda", "net-200.pth") if not os.path.exists(motion_model_file): print("📥 در حال دانلود مدلها...") try: snapshot_download(repo_id=REPO_ID, local_dir=WEIGHTS_DIR, local_dir_use_symlinks=False, resume_download=True) except Exception as e: print(f"Error downloading: {e}") # --- تبدیل صدا --- def ensure_wav_format(audio_path): if audio_path is None: return None audio_path = Path(audio_path) if audio_path.suffix.lower() == '.wav': return str(audio_path) try: audio = AudioSegment.from_file(audio_path) with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as tmp_file: wav_path = tmp_file.name audio.export(wav_path, format='wav', parameters=["-ar", "16000", "-ac", "1"]) return wav_path except Exception as e: raise gr.Error(f"فرمت فایل صوتی نامعتبر است: {e}") # --- لود اولیه --- os.makedirs(OUTPUT_DIR, exist_ok=True) download_weights() print("⏳ در حال لود مدل...") try: pipeline = LiveVASAPipeline(cfg_path=DEFAULT_CFG_PATH, motion_mean_std_path=DEFAULT_MOTION_MEAN_STD_PATH) print("✅ مدل با موفقیت لود شد.") except Exception as e: print(f"❌ خطا در لود مدل: {e}") pipeline = None emo_name_to_id = {v: k for k, v in emo_map.items()} # --- **جاوا اسکریپت جدید برای نمایش پیام خطای زیبا** --- js_func = """ () => { const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.addedNodes.length) { mutation.addedNodes.forEach((node) => { // فقط روی المانهای مربوط به خطای گرادیو کار کن if (node.nodeType === 1 && (node.classList.contains('toast-body') || node.classList.contains('error'))) { const originalText = node.innerText; // Regex برای پیدا کردن اعداد زمان const regex = /(\d+)s requested vs. (\d+)s left/; const match = originalText.match(regex); // اگر متن خطا مربوط به Quota بود و قبلا ترجمه نشده بود if (match && !node.dataset.translated) { const requested = match[1]; const left = match[2]; // **ساخت کارت HTML زیبا** const prettyHtml = `
سهمیه رایگان GPU شما برای پردازش یک ویدیوی ${requested} ثانیهای کافی نیست.