Upload 2 files
Browse files- api_client.py +39 -25
api_client.py
CHANGED
|
@@ -114,35 +114,32 @@ class APIClient:
|
|
| 114 |
def tts_matxa(self, text: str, voice: str = "central/grau") -> dict:
|
| 115 |
"""
|
| 116 |
Llama al space 'tts' para sintetizar audio.
|
|
|
|
| 117 |
|
| 118 |
Args:
|
| 119 |
text (str): Texto a sintetizar.
|
| 120 |
-
voice (str): Voz de Matxa a usar (p.ej. 'central/
|
| 121 |
|
| 122 |
Returns:
|
| 123 |
-
dict: {'
|
| 124 |
"""
|
| 125 |
if not self.tts_url:
|
| 126 |
raise ValueError("La URL del servei TTS no està configurada (API_TTS_URL)")
|
| 127 |
|
| 128 |
-
#
|
| 129 |
if len(text) > 480:
|
| 130 |
url = f"{self.tts_url.rstrip('/')}/tts/text_long"
|
| 131 |
-
data = {
|
| 132 |
-
"texto": text,
|
| 133 |
-
"voice": voice,
|
| 134 |
-
"formato": "mp3"
|
| 135 |
-
}
|
| 136 |
else:
|
| 137 |
url = f"{self.tts_url.rstrip('/')}/tts/text"
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
|
|
|
| 143 |
|
| 144 |
try:
|
| 145 |
-
r =
|
| 146 |
r.raise_for_status()
|
| 147 |
|
| 148 |
# Devolver los bytes directamente para que el cliente los pueda concatenar
|
|
@@ -201,10 +198,18 @@ class APIClient:
|
|
| 201 |
except requests.exceptions.RequestException as e:
|
| 202 |
return {"error": str(e)}
|
| 203 |
|
| 204 |
-
def rebuild_video_with_ad(self, video_path: str, srt_path: str) -> dict:
|
| 205 |
"""
|
| 206 |
Llama al space 'tts' para reconstruir un vídeo con audiodescripció a partir de un SRT.
|
| 207 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 208 |
"""
|
| 209 |
if not self.tts_url:
|
| 210 |
raise ValueError("La URL del servei TTS no està configurada (API_TTS_URL)")
|
|
@@ -212,18 +217,24 @@ class APIClient:
|
|
| 212 |
url = f"{self.tts_url.rstrip('/')}/tts/srt"
|
| 213 |
|
| 214 |
try:
|
| 215 |
-
|
| 216 |
-
|
| 217 |
-
|
| 218 |
-
|
| 219 |
-
|
| 220 |
-
|
| 221 |
-
|
| 222 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 223 |
|
| 224 |
# El servidor devuelve un ZIP, lo procesamos en memoria
|
| 225 |
with zipfile.ZipFile(io.BytesIO(r.content)) as z:
|
| 226 |
-
# Buscamos el archivo .mp4 dentro del ZIP
|
| 227 |
for filename in z.namelist():
|
| 228 |
if filename.endswith('.mp4'):
|
| 229 |
video_bytes = z.read(filename)
|
|
@@ -237,6 +248,9 @@ class APIClient:
|
|
| 237 |
return {"error": str(e)}
|
| 238 |
except zipfile.BadZipFile:
|
| 239 |
return {"error": "La respuesta del servidor no fue un archivo ZIP válido."}
|
|
|
|
|
|
|
|
|
|
| 240 |
|
| 241 |
|
| 242 |
def refine_narration(self, dialogues_srt: str, frame_descriptions_json: str = "[]", config_path: str = "config.yaml") -> dict:
|
|
|
|
| 114 |
def tts_matxa(self, text: str, voice: str = "central/grau") -> dict:
|
| 115 |
"""
|
| 116 |
Llama al space 'tts' para sintetizar audio.
|
| 117 |
+
Usa /tts/text para textos cortos (<480 chars) o /tts/text_long para textos largos.
|
| 118 |
|
| 119 |
Args:
|
| 120 |
text (str): Texto a sintetizar.
|
| 121 |
+
voice (str): Voz de Matxa a usar (p.ej. 'central/grau').
|
| 122 |
|
| 123 |
Returns:
|
| 124 |
+
dict: {'mp3_bytes': bytes} o {'error': str}
|
| 125 |
"""
|
| 126 |
if not self.tts_url:
|
| 127 |
raise ValueError("La URL del servei TTS no està configurada (API_TTS_URL)")
|
| 128 |
|
| 129 |
+
# Usar endpoint apropiado según la longitud del texto
|
| 130 |
if len(text) > 480:
|
| 131 |
url = f"{self.tts_url.rstrip('/')}/tts/text_long"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 132 |
else:
|
| 133 |
url = f"{self.tts_url.rstrip('/')}/tts/text"
|
| 134 |
+
|
| 135 |
+
data = {
|
| 136 |
+
"texto": text,
|
| 137 |
+
"voice": voice,
|
| 138 |
+
"formato": "mp3"
|
| 139 |
+
}
|
| 140 |
|
| 141 |
try:
|
| 142 |
+
r = self.session.post(url, data=data, timeout=self.timeout * 2) # Más tiempo para textos largos
|
| 143 |
r.raise_for_status()
|
| 144 |
|
| 145 |
# Devolver los bytes directamente para que el cliente los pueda concatenar
|
|
|
|
| 198 |
except requests.exceptions.RequestException as e:
|
| 199 |
return {"error": str(e)}
|
| 200 |
|
| 201 |
+
def rebuild_video_with_ad(self, video_path: str, srt_path: str, voice: str = "central/grau") -> dict:
|
| 202 |
"""
|
| 203 |
Llama al space 'tts' para reconstruir un vídeo con audiodescripció a partir de un SRT.
|
| 204 |
+
Usa el endpoint /tts/srt que devuelve un ZIP con el vídeo final.
|
| 205 |
+
|
| 206 |
+
Args:
|
| 207 |
+
video_path: Ruta al archivo de vídeo original
|
| 208 |
+
srt_path: Ruta al archivo SRT con las audiodescripciones
|
| 209 |
+
voice: Voz de Matxa (por defecto 'central/grau')
|
| 210 |
+
|
| 211 |
+
Returns:
|
| 212 |
+
dict: {'video_bytes': bytes} o {'error': str}
|
| 213 |
"""
|
| 214 |
if not self.tts_url:
|
| 215 |
raise ValueError("La URL del servei TTS no està configurada (API_TTS_URL)")
|
|
|
|
| 217 |
url = f"{self.tts_url.rstrip('/')}/tts/srt"
|
| 218 |
|
| 219 |
try:
|
| 220 |
+
with open(video_path, 'rb') as video_file:
|
| 221 |
+
with open(srt_path, 'rb') as srt_file:
|
| 222 |
+
files = {
|
| 223 |
+
'video': (os.path.basename(video_path), video_file, 'video/mp4'),
|
| 224 |
+
'srt': (os.path.basename(srt_path), srt_file, 'application/x-subrip')
|
| 225 |
+
}
|
| 226 |
+
data = {
|
| 227 |
+
"voice": voice,
|
| 228 |
+
"ad_format": "mp3",
|
| 229 |
+
"include_final_mp4": "1"
|
| 230 |
+
}
|
| 231 |
+
|
| 232 |
+
r = self.session.post(url, files=files, data=data, timeout=self.timeout * 5)
|
| 233 |
+
r.raise_for_status()
|
| 234 |
|
| 235 |
# El servidor devuelve un ZIP, lo procesamos en memoria
|
| 236 |
with zipfile.ZipFile(io.BytesIO(r.content)) as z:
|
| 237 |
+
# Buscamos el archivo video_con_ad.mp4 dentro del ZIP
|
| 238 |
for filename in z.namelist():
|
| 239 |
if filename.endswith('.mp4'):
|
| 240 |
video_bytes = z.read(filename)
|
|
|
|
| 248 |
return {"error": str(e)}
|
| 249 |
except zipfile.BadZipFile:
|
| 250 |
return {"error": "La respuesta del servidor no fue un archivo ZIP válido."}
|
| 251 |
+
except Exception as e:
|
| 252 |
+
print(f"Error inesperat: {e}")
|
| 253 |
+
return {"error": str(e)}
|
| 254 |
|
| 255 |
|
| 256 |
def refine_narration(self, dialogues_srt: str, frame_descriptions_json: str = "[]", config_path: str = "config.yaml") -> dict:
|