Spaces:
Running on Zero
Running on Zero
| import os | |
| # Отключаем SSR до импорта Gradio | |
| os.environ["GRADIO_SSR_MODE"] = "false" | |
| import gc | |
| import tempfile | |
| import gradio as gr | |
| import soundfile as sf | |
| import torch | |
| import spaces | |
| from diffusers import ModularPipeline | |
| MODEL_ID = "Cartik/Sonexa-Music-v0.1-Beta" | |
| # ============================================================ | |
| # CONFIG | |
| # ============================================================ | |
| print("=" * 60) | |
| print("Sonexa Music Generation") | |
| print("=" * 60) | |
| print(f"Model: {MODEL_ID}") | |
| print(f"CUDA available: {torch.cuda.is_available()}") | |
| print("=" * 60) | |
| # ============================================================ | |
| # LOAD MODEL | |
| # ============================================================ | |
| print("Loading music model on CPU...") | |
| pipe = ModularPipeline.from_pretrained( | |
| MODEL_ID, | |
| ) | |
| pipe.load_components( | |
| dtype=torch.float32, | |
| ) | |
| # Модель постоянно находится в RAM. | |
| # ZeroGPU выдаёт GPU только при вызове @spaces.GPU. | |
| pipe.to("cpu") | |
| print("Music model loaded successfully!") | |
| # ============================================================ | |
| # MUSIC GENERATION | |
| # ============================================================ | |
| def generate_music(prompt, lyrics, duration): | |
| prompt = (prompt or "").strip() | |
| lyrics = (lyrics or "").strip() | |
| if not prompt: | |
| raise gr.Error( | |
| "Опиши, какую музыку нужно создать." | |
| ) | |
| try: | |
| duration = float(duration) | |
| duration = max(10, min(duration, 120)) | |
| print("=" * 60) | |
| print("GPU GENERATION START") | |
| print(f"Prompt: {prompt}") | |
| print(f"Lyrics: {lyrics[:200]}") | |
| print(f"Duration: {duration}s") | |
| print("=" * 60) | |
| # ZeroGPU выделяет CUDA перед входом сюда. | |
| if not torch.cuda.is_available(): | |
| raise RuntimeError( | |
| "ZeroGPU не выделил CUDA для генерации." | |
| ) | |
| device = "cuda" | |
| print("Moving music model to GPU...") | |
| pipe.to(device) | |
| print("Model moved to GPU.") | |
| generator = torch.Generator( | |
| device=device | |
| ).manual_seed( | |
| int.from_bytes( | |
| os.urandom(4), | |
| "little", | |
| ) | |
| ) | |
| print("Starting inference...") | |
| with torch.inference_mode(): | |
| result = pipe( | |
| prompt=prompt, | |
| lyrics=lyrics, | |
| audio_duration=duration, | |
| generator=generator, | |
| output="audios", | |
| ) | |
| print("Inference finished.") | |
| audio = result[0] | |
| # ==================================================== | |
| # SAVE AUDIO | |
| # ==================================================== | |
| output_file = tempfile.NamedTemporaryFile( | |
| suffix=".wav", | |
| delete=False, | |
| ) | |
| output_path = output_file.name | |
| output_file.close() | |
| # Модель возвращает channel-first audio. | |
| audio_array = ( | |
| audio | |
| .T | |
| .float() | |
| .cpu() | |
| .numpy() | |
| ) | |
| sf.write( | |
| output_path, | |
| audio_array, | |
| pipe.sampling_rate, | |
| ) | |
| print( | |
| f"Music saved: {output_path}" | |
| ) | |
| # Возвращаем модель в RAM. | |
| print("Moving model back to CPU...") | |
| pipe.to("cpu") | |
| print("Model returned to CPU.") | |
| return output_path | |
| except Exception as e: | |
| print("=" * 60) | |
| print("MUSIC GENERATION ERROR") | |
| print("=" * 60) | |
| print(repr(e)) | |
| print("=" * 60) | |
| # Пытаемся вернуть модель в RAM, | |
| # даже если генерация упала. | |
| try: | |
| pipe.to("cpu") | |
| except Exception as cpu_error: | |
| print( | |
| f"Could not move model to CPU: {cpu_error}" | |
| ) | |
| raise gr.Error( | |
| f"Ошибка генерации: {e}" | |
| ) | |
| finally: | |
| gc.collect() | |
| if torch.cuda.is_available(): | |
| try: | |
| torch.cuda.empty_cache() | |
| except Exception: | |
| pass | |
| print("Generation cleanup finished.") | |
| # ============================================================ | |
| # UI | |
| # ============================================================ | |
| with gr.Blocks( | |
| title="Sonexa Music" | |
| ) as demo: | |
| gr.Markdown( | |
| "# Sonexa Music Generation" | |
| ) | |
| gr.Markdown( | |
| "Создавайте музыку по описанию и тексту песни." | |
| ) | |
| with gr.Row(): | |
| # ==================================================== | |
| # INPUT | |
| # ==================================================== | |
| with gr.Column(): | |
| prompt = gr.Textbox( | |
| label="Описание музыки", | |
| placeholder=( | |
| "Energetic electronic music, " | |
| "powerful drums, deep bass, " | |
| "bright synths and an intense drop" | |
| ), | |
| lines=5, | |
| ) | |
| lyrics = gr.Textbox( | |
| label="Текст песни", | |
| placeholder=( | |
| "[Verse]\n" | |
| "Morning light is falling...\n\n" | |
| "[Chorus]\n" | |
| "We keep moving through the night..." | |
| ), | |
| lines=8, | |
| ) | |
| duration = gr.Slider( | |
| minimum=10, | |
| maximum=120, | |
| value=60, | |
| step=10, | |
| label="Длительность (секунды)", | |
| ) | |
| button = gr.Button( | |
| "Создать музыку", | |
| variant="primary", | |
| ) | |
| # ==================================================== | |
| # OUTPUT | |
| # ==================================================== | |
| with gr.Column(): | |
| output = gr.Audio( | |
| label="Результат", | |
| type="filepath", | |
| ) | |
| # ======================================================== | |
| # API | |
| # ======================================================== | |
| button.click( | |
| fn=generate_music, | |
| inputs=[ | |
| prompt, | |
| lyrics, | |
| duration, | |
| ], | |
| outputs=output, | |
| api_name="predict", | |
| ) | |
| # ============================================================ | |
| # QUEUE | |
| # ============================================================ | |
| demo.queue( | |
| max_size=8, | |
| default_concurrency_limit=1, | |
| ) | |
| # ============================================================ | |
| # START | |
| # ============================================================ | |
| print("=" * 60) | |
| print("Starting Gradio...") | |
| print("SSR disabled through environment.") | |
| print("=" * 60) | |
| demo.launch( | |
| server_name="0.0.0.0", | |
| server_port=7860, | |
| show_api=True, | |
| ) |