Spaces:
Runtime error
Runtime error
Carlexxx
commited on
Commit
·
af382fb
1
Parent(s):
c0e5fc7
aduc-sdr
Browse files- audio_specialist.py +25 -3
- prompts/sound_director_prompt.txt.txt +27 -0
audio_specialist.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
-
# audio_specialist.py
|
| 2 |
# Especialista ADUC para geração de áudio, com gerenciamento de memória GPU.
|
|
|
|
| 3 |
|
| 4 |
import torch
|
| 5 |
import logging
|
|
@@ -24,6 +25,10 @@ except ImportError:
|
|
| 24 |
logger = logging.getLogger(__name__)
|
| 25 |
|
| 26 |
class AudioSpecialist:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 27 |
def __init__(self, workspace_dir):
|
| 28 |
self.device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 29 |
self.cpu_device = torch.device("cpu")
|
|
@@ -38,6 +43,7 @@ class AudioSpecialist:
|
|
| 38 |
self._load_models_to_cpu()
|
| 39 |
|
| 40 |
def _load_models_to_cpu(self):
|
|
|
|
| 41 |
try:
|
| 42 |
logger.info("Verificando e baixando modelos MMAudio, se necessário...")
|
| 43 |
self.model_config.download_if_needed()
|
|
@@ -66,12 +72,14 @@ class AudioSpecialist:
|
|
| 66 |
self.net = None
|
| 67 |
|
| 68 |
def to_gpu(self):
|
|
|
|
| 69 |
if self.device == 'cpu': return
|
| 70 |
logger.info(f"Movendo especialista de áudio para a GPU ({self.device})...")
|
| 71 |
self.net.to(self.device, self.dtype)
|
| 72 |
self.feature_utils.to(self.device, self.dtype)
|
| 73 |
|
| 74 |
def to_cpu(self):
|
|
|
|
| 75 |
if self.device == 'cpu': return
|
| 76 |
logger.info("Descarregando especialista de áudio da GPU...")
|
| 77 |
self.net.to(self.cpu_device)
|
|
@@ -79,7 +87,18 @@ class AudioSpecialist:
|
|
| 79 |
gc.collect()
|
| 80 |
if torch.cuda.is_available(): torch.cuda.empty_cache()
|
| 81 |
|
| 82 |
-
def generate_audio_for_video(self, video_path: str, prompt: str,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 83 |
if self.net is None:
|
| 84 |
raise gr.Error("Modelo MMAudio não está carregado. Não é possível gerar áudio.")
|
| 85 |
|
|
@@ -89,6 +108,9 @@ class AudioSpecialist:
|
|
| 89 |
logger.info(f"--- Duração: {duration_seconds:.2f}s")
|
| 90 |
logger.info(f"--- Prompt (Descrição da Cena): '{prompt}'")
|
| 91 |
|
|
|
|
|
|
|
|
|
|
| 92 |
if duration_seconds < 1:
|
| 93 |
logger.warning("Fragmento muito curto (<1s). Retornando vídeo silencioso.")
|
| 94 |
logger.info("------------------------------------------------------")
|
|
@@ -137,5 +159,5 @@ try:
|
|
| 137 |
WORKSPACE_DIR = config['application']['workspace_dir']
|
| 138 |
audio_specialist_singleton = AudioSpecialist(workspace_dir=WORKSPACE_DIR)
|
| 139 |
except Exception as e:
|
| 140 |
-
logger.error(f"Não foi possível inicializar o AudioSpecialist: {e}")
|
| 141 |
audio_specialist_singleton = None
|
|
|
|
| 1 |
+
# audio_specialist.py
|
| 2 |
# Especialista ADUC para geração de áudio, com gerenciamento de memória GPU.
|
| 3 |
+
# Copyright (C) 4 de Agosto de 2025 Carlos Rodrigues dos Santos
|
| 4 |
|
| 5 |
import torch
|
| 6 |
import logging
|
|
|
|
| 25 |
logger = logging.getLogger(__name__)
|
| 26 |
|
| 27 |
class AudioSpecialist:
|
| 28 |
+
"""
|
| 29 |
+
Especialista responsável por gerar áudio para fragmentos de vídeo.
|
| 30 |
+
Gerencia o carregamento e descarregamento de modelos de áudio da VRAM.
|
| 31 |
+
"""
|
| 32 |
def __init__(self, workspace_dir):
|
| 33 |
self.device = "cuda" if torch.cuda.is_available() else "cpu"
|
| 34 |
self.cpu_device = torch.device("cpu")
|
|
|
|
| 43 |
self._load_models_to_cpu()
|
| 44 |
|
| 45 |
def _load_models_to_cpu(self):
|
| 46 |
+
"""Carrega os modelos MMAudio para a memória da CPU na inicialização."""
|
| 47 |
try:
|
| 48 |
logger.info("Verificando e baixando modelos MMAudio, se necessário...")
|
| 49 |
self.model_config.download_if_needed()
|
|
|
|
| 72 |
self.net = None
|
| 73 |
|
| 74 |
def to_gpu(self):
|
| 75 |
+
"""Move os modelos e utilitários para a GPU antes da inferência."""
|
| 76 |
if self.device == 'cpu': return
|
| 77 |
logger.info(f"Movendo especialista de áudio para a GPU ({self.device})...")
|
| 78 |
self.net.to(self.device, self.dtype)
|
| 79 |
self.feature_utils.to(self.device, self.dtype)
|
| 80 |
|
| 81 |
def to_cpu(self):
|
| 82 |
+
"""Move os modelos de volta para a CPU e limpa a VRAM após a inferência."""
|
| 83 |
if self.device == 'cpu': return
|
| 84 |
logger.info("Descarregando especialista de áudio da GPU...")
|
| 85 |
self.net.to(self.cpu_device)
|
|
|
|
| 87 |
gc.collect()
|
| 88 |
if torch.cuda.is_available(): torch.cuda.empty_cache()
|
| 89 |
|
| 90 |
+
def generate_audio_for_video(self, video_path: str, prompt: str, duration_seconds: float) -> str:
|
| 91 |
+
"""
|
| 92 |
+
Gera áudio para um arquivo de vídeo, aplicando um prompt negativo para evitar fala.
|
| 93 |
+
|
| 94 |
+
Args:
|
| 95 |
+
video_path (str): Caminho para o vídeo silencioso.
|
| 96 |
+
prompt (str): Descrição da cena para guiar a geração de SFX.
|
| 97 |
+
duration_seconds (float): Duração do áudio a ser gerado.
|
| 98 |
+
|
| 99 |
+
Returns:
|
| 100 |
+
str: Caminho para o novo arquivo de vídeo com áudio.
|
| 101 |
+
"""
|
| 102 |
if self.net is None:
|
| 103 |
raise gr.Error("Modelo MMAudio não está carregado. Não é possível gerar áudio.")
|
| 104 |
|
|
|
|
| 108 |
logger.info(f"--- Duração: {duration_seconds:.2f}s")
|
| 109 |
logger.info(f"--- Prompt (Descrição da Cena): '{prompt}'")
|
| 110 |
|
| 111 |
+
negative_prompt = "speech, human voice, talking, vocals, music, singing, dialogue"
|
| 112 |
+
logger.info(f"--- Negative Prompt: '{negative_prompt}'")
|
| 113 |
+
|
| 114 |
if duration_seconds < 1:
|
| 115 |
logger.warning("Fragmento muito curto (<1s). Retornando vídeo silencioso.")
|
| 116 |
logger.info("------------------------------------------------------")
|
|
|
|
| 159 |
WORKSPACE_DIR = config['application']['workspace_dir']
|
| 160 |
audio_specialist_singleton = AudioSpecialist(workspace_dir=WORKSPACE_DIR)
|
| 161 |
except Exception as e:
|
| 162 |
+
logger.error(f"Não foi possível inicializar o AudioSpecialist: {e}", exc_info=True)
|
| 163 |
audio_specialist_singleton = None
|
prompts/sound_director_prompt.txt.txt
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ROLE: AI Sound Director & Foley Artist
|
| 2 |
+
|
| 3 |
+
# GOAL:
|
| 4 |
+
You are the sound director for a film. Your task is to create a single, rich, and descriptive prompt for an audio generation model (like MMAudio). This prompt must describe the complete soundscape for the CURRENT scene, considering what happened before and what will happen next to ensure audio continuity.
|
| 5 |
+
|
| 6 |
+
# CRITICAL RULES (MUST FOLLOW):
|
| 7 |
+
1. **NO SPEECH OR VOICES:** The final prompt must NOT include any terms related to human speech, dialogue, talking, voices, singing, or narration. The goal is to create a world of ambient sounds and specific sound effects (SFX).
|
| 8 |
+
2. **FOCUS ON THE PRESENT:** The audio must primarily match the CURRENT visual scene (Keyframe Kn) and its textual description (Ato_n).
|
| 9 |
+
3. **USE THE PAST FOR CONTINUITY:** Analyze the "Previous Audio Prompt" to understand the established soundscape. If a sound should logically continue from the previous scene, include it (e.g., "the continued sound of a gentle breeze...").
|
| 10 |
+
4. **USE THE FUTURE FOR FORESHADOWING:** Analyze the FUTURE keyframe and scene description. If appropriate, introduce subtle sounds that hint at what's to come. (e.g., if the next scene is a storm, you could add "...with the faint, distant rumble of thunder in the background.").
|
| 11 |
+
5. **BE DESCRIPTIVE:** Use evocative language. Instead of "dog bark", use "the sharp, excited yapping of a small dog". Combine multiple elements into a cohesive soundscape.
|
| 12 |
+
|
| 13 |
+
# CONTEXT FOR YOUR DECISION:
|
| 14 |
+
|
| 15 |
+
- **Previous Audio Prompt (what was just heard):**
|
| 16 |
+
{audio_history}
|
| 17 |
+
|
| 18 |
+
- **VISUAL PAST (Keyframe Kn-1):** [PAST_IMAGE]
|
| 19 |
+
- **VISUAL PRESENT (Keyframe Kn):** [PRESENT_IMAGE]
|
| 20 |
+
- **VISUAL FUTURE (Keyframe Kn+1):** [FUTURE_IMAGE]
|
| 21 |
+
|
| 22 |
+
- **CURRENT Scene Description (Ato_n):** "{present_scene_desc}"
|
| 23 |
+
- **CURRENT Motion Prompt (what the camera is doing):** "{motion_prompt}"
|
| 24 |
+
- **FUTURE Scene Description (Ato_n+1):** "{future_scene_desc}"
|
| 25 |
+
|
| 26 |
+
# RESPONSE FORMAT:
|
| 27 |
+
Respond with ONLY the final, single-line prompt string for the audio generator.
|