Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -14,7 +14,6 @@ import random
|
|
14 |
from transformers import pipeline
|
15 |
import torch
|
16 |
import asyncio
|
17 |
-
from nltk.tokenize import sent_tokenize
|
18 |
|
19 |
nltk.download('punkt', quiet=True)
|
20 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
@@ -23,15 +22,12 @@ logger = logging.getLogger(__name__)
|
|
23 |
PEXELS_API_KEY = os.getenv("PEXELS_API_KEY")
|
24 |
MODEL_NAME = "DeepESP/gpt2-spanish"
|
25 |
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
voice_names = [f"{v['Name']} ({v['Gender']}, {v['LocaleName']})" for v in voices]
|
30 |
-
return voice_names, voices
|
31 |
-
except:
|
32 |
-
return ["Voz Predeterminada (Femenino, es-ES)"], [{'ShortName': 'es-ES-ElviraNeural'}]
|
33 |
|
34 |
-
|
|
|
35 |
|
36 |
def generar_guion_profesional(prompt):
|
37 |
try:
|
@@ -47,10 +43,12 @@ def generar_guion_profesional(prompt):
|
|
47 |
"2. Tres secciones detalladas con subt铆tulos\n"
|
48 |
"3. Conclusi贸n impactante\n"
|
49 |
"Usa un estilo natural para narraci贸n:",
|
|
|
50 |
temperature=0.7,
|
51 |
top_k=50,
|
52 |
top_p=0.95,
|
53 |
-
num_return_sequences=1
|
|
|
54 |
)
|
55 |
guion = response[0]['generated_text']
|
56 |
if len(guion.split()) < 100:
|
@@ -90,6 +88,8 @@ def generar_guion_profesional(prompt):
|
|
90 |
驴Listos para profundizar? 隆Empecemos!
|
91 |
"""
|
92 |
|
|
|
|
|
93 |
def buscar_videos_avanzado(prompt, guion, num_videos=5):
|
94 |
try:
|
95 |
oraciones = sent_tokenize(guion)
|
@@ -125,6 +125,7 @@ def buscar_videos_avanzado(prompt, guion, num_videos=5):
|
|
125 |
return response.json().get('videos', [])[:num_videos]
|
126 |
|
127 |
async def crear_video_profesional(prompt, custom_script, voz_index, musica=None):
|
|
|
128 |
try:
|
129 |
guion = custom_script if custom_script else generar_guion_profesional(prompt)
|
130 |
logger.info(f"Guion generado ({len(guion.split())} palabras)")
|
@@ -146,13 +147,6 @@ async def crear_video_profesional(prompt, custom_script, voz_index, musica=None)
|
|
146 |
clip = VideoFileClip(temp_video.name).subclip(0, min(10, video['duration']))
|
147 |
clips.append(clip)
|
148 |
video_final = concatenate_videoclips(clips)
|
149 |
-
if musica:
|
150 |
-
musica_clip = AudioFileClip(musica.name)
|
151 |
-
if musica_clip.duration < duracion_total:
|
152 |
-
musica_clip = musica_clip.loop(duration=duracion_total)
|
153 |
-
else:
|
154 |
-
musica_clip = musica_clip.subclip(0, duracion_total)
|
155 |
-
audio = CompositeAudioClip([audio, musica_clip.volumex(0.25)])
|
156 |
video_final = video_final.set_audio(audio)
|
157 |
output_path = f"video_output_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
|
158 |
video_final.write_videofile(output_path, fps=24, threads=2)
|
@@ -161,25 +155,26 @@ async def crear_video_profesional(prompt, custom_script, voz_index, musica=None)
|
|
161 |
logger.error(f"Error cr铆tico: {str(e)}")
|
162 |
return None
|
163 |
finally:
|
164 |
-
if os.path.exists(
|
165 |
-
os.remove(
|
166 |
|
167 |
-
def
|
|
|
168 |
return asyncio.run(crear_video_profesional(prompt, custom_script, voz_index, musica))
|
169 |
|
170 |
with gr.Blocks(title="Generador de Videos") as app:
|
171 |
with gr.Row():
|
172 |
with gr.Column():
|
173 |
prompt = gr.Textbox(label="Tema del video")
|
174 |
-
custom_script = gr.TextArea(label="
|
175 |
voz = gr.Dropdown(VOICE_NAMES, label="Voz", value=VOICE_NAMES[0])
|
176 |
musica = gr.File(label="M煤sica de fondo (opcional)", file_types=["audio"])
|
177 |
btn = gr.Button("Generar Video", variant="primary")
|
178 |
with gr.Column():
|
179 |
output = gr.Video(label="Resultado", format="mp4")
|
180 |
-
|
181 |
btn.click(
|
182 |
-
fn=
|
183 |
inputs=[prompt, custom_script, voz, musica],
|
184 |
outputs=output
|
185 |
)
|
|
|
14 |
from transformers import pipeline
|
15 |
import torch
|
16 |
import asyncio
|
|
|
17 |
|
18 |
nltk.download('punkt', quiet=True)
|
19 |
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
|
|
22 |
PEXELS_API_KEY = os.getenv("PEXELS_API_KEY")
|
23 |
MODEL_NAME = "DeepESP/gpt2-spanish"
|
24 |
|
25 |
+
# Obtener voces de edge-tts de forma s铆ncrona (wrapper)
|
26 |
+
def get_voices_sync():
|
27 |
+
return asyncio.run(edge_tts.list_voices())
|
|
|
|
|
|
|
|
|
28 |
|
29 |
+
VOICES = get_voices_sync()
|
30 |
+
VOICE_NAMES = [f"{v['Name']} ({v['Gender']}, {v['LocaleName']})" for v in VOICES]
|
31 |
|
32 |
def generar_guion_profesional(prompt):
|
33 |
try:
|
|
|
43 |
"2. Tres secciones detalladas con subt铆tulos\n"
|
44 |
"3. Conclusi贸n impactante\n"
|
45 |
"Usa un estilo natural para narraci贸n:",
|
46 |
+
max_length=1000,
|
47 |
temperature=0.7,
|
48 |
top_k=50,
|
49 |
top_p=0.95,
|
50 |
+
num_return_sequences=1,
|
51 |
+
truncation=True
|
52 |
)
|
53 |
guion = response[0]['generated_text']
|
54 |
if len(guion.split()) < 100:
|
|
|
88 |
驴Listos para profundizar? 隆Empecemos!
|
89 |
"""
|
90 |
|
91 |
+
from nltk.tokenize import sent_tokenize
|
92 |
+
|
93 |
def buscar_videos_avanzado(prompt, guion, num_videos=5):
|
94 |
try:
|
95 |
oraciones = sent_tokenize(guion)
|
|
|
125 |
return response.json().get('videos', [])[:num_videos]
|
126 |
|
127 |
async def crear_video_profesional(prompt, custom_script, voz_index, musica=None):
|
128 |
+
voz_archivo = None
|
129 |
try:
|
130 |
guion = custom_script if custom_script else generar_guion_profesional(prompt)
|
131 |
logger.info(f"Guion generado ({len(guion.split())} palabras)")
|
|
|
147 |
clip = VideoFileClip(temp_video.name).subclip(0, min(10, video['duration']))
|
148 |
clips.append(clip)
|
149 |
video_final = concatenate_videoclips(clips)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
video_final = video_final.set_audio(audio)
|
151 |
output_path = f"video_output_{datetime.now().strftime('%Y%m%d_%H%M%S')}.mp4"
|
152 |
video_final.write_videofile(output_path, fps=24, threads=2)
|
|
|
155 |
logger.error(f"Error cr铆tico: {str(e)}")
|
156 |
return None
|
157 |
finally:
|
158 |
+
if voz_archivo and os.path.exists(voz_archivo):
|
159 |
+
os.remove(voz_archivo)
|
160 |
|
161 |
+
def run_async_wrapper(prompt, custom_script, voz, musica):
|
162 |
+
voz_index = VOICE_NAMES.index(voz)
|
163 |
return asyncio.run(crear_video_profesional(prompt, custom_script, voz_index, musica))
|
164 |
|
165 |
with gr.Blocks(title="Generador de Videos") as app:
|
166 |
with gr.Row():
|
167 |
with gr.Column():
|
168 |
prompt = gr.Textbox(label="Tema del video")
|
169 |
+
custom_script = gr.TextArea(label="Guion personalizado (opcional)")
|
170 |
voz = gr.Dropdown(VOICE_NAMES, label="Voz", value=VOICE_NAMES[0])
|
171 |
musica = gr.File(label="M煤sica de fondo (opcional)", file_types=["audio"])
|
172 |
btn = gr.Button("Generar Video", variant="primary")
|
173 |
with gr.Column():
|
174 |
output = gr.Video(label="Resultado", format="mp4")
|
175 |
+
|
176 |
btn.click(
|
177 |
+
fn=run_async_wrapper,
|
178 |
inputs=[prompt, custom_script, voz, musica],
|
179 |
outputs=output
|
180 |
)
|