Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -104,4 +104,90 @@ async def procesar_video(video_input, texto_tts, voz_seleccionada):
|
|
104 |
segments.append(full_segment)
|
105 |
current_time += (SEGMENT_DURATION - OVERLAP)
|
106 |
|
107 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
104 |
segments.append(full_segment)
|
105 |
current_time += (SEGMENT_DURATION - OVERLAP)
|
106 |
|
107 |
+
# Asegurar que haya al menos un segmento
|
108 |
+
if not segments:
|
109 |
+
logging.warning("Video demasiado corto, devolviendo el video original.")
|
110 |
+
video_final = video_original.set_audio(audio_final)
|
111 |
+
else:
|
112 |
+
video_final = concatenate_videoclips(segments, method="compose")
|
113 |
+
video_final = video_final.set_audio(audio_final)
|
114 |
+
|
115 |
+
# Agregar intro y outro
|
116 |
+
intro = VideoFileClip(INTRO_VIDEO, target_resolution=(720, 1280))
|
117 |
+
outro = VideoFileClip(OUTRO_VIDEO, target_resolution=(720, 1280))
|
118 |
+
video_final = concatenate_videoclips([intro, video_final, outro], method="compose")
|
119 |
+
|
120 |
+
# Renderizado final
|
121 |
+
with tempfile.NamedTemporaryFile(suffix=".mp4", delete=False) as tmp:
|
122 |
+
video_final.write_videofile(
|
123 |
+
tmp.name,
|
124 |
+
codec="libx264",
|
125 |
+
audio_codec="aac",
|
126 |
+
fps=24,
|
127 |
+
threads=2,
|
128 |
+
bitrate="3M",
|
129 |
+
ffmpeg_params=[
|
130 |
+
"-preset", "ultrafast",
|
131 |
+
"-crf", "28",
|
132 |
+
"-movflags", "+faststart",
|
133 |
+
"-vf", "scale=1280:720"
|
134 |
+
],
|
135 |
+
verbose=False
|
136 |
+
)
|
137 |
+
eliminar_archivo_tiempo(tmp.name, 1800)
|
138 |
+
logging.info(f"Video final guardado: {tmp.name}")
|
139 |
+
return tmp.name
|
140 |
+
|
141 |
+
except Exception as e:
|
142 |
+
logging.error(f"Fallo general: {str(e)}")
|
143 |
+
raise
|
144 |
+
finally:
|
145 |
+
try:
|
146 |
+
if video_original:
|
147 |
+
video_original.close()
|
148 |
+
if intro:
|
149 |
+
intro.close()
|
150 |
+
if outro:
|
151 |
+
outro.close()
|
152 |
+
for file in temp_files:
|
153 |
+
try:
|
154 |
+
os.remove(file)
|
155 |
+
except Exception as e:
|
156 |
+
logging.warning(f"Error limpiando {file}: {e}")
|
157 |
+
except Exception as e:
|
158 |
+
logging.warning(f"Error al cerrar recursos: {str(e)}")
|
159 |
+
|
160 |
+
# Interfaz Gradio
|
161 |
+
with gr.Blocks() as demo:
|
162 |
+
gr.Markdown("# Editor de Video con IA")
|
163 |
+
|
164 |
+
with gr.Tab("Principal"):
|
165 |
+
video_input = gr.Video(label="Subir video")
|
166 |
+
texto_tts = gr.Textbox(
|
167 |
+
label="Texto para TTS",
|
168 |
+
lines=3,
|
169 |
+
placeholder="Escribe aquí tu texto..."
|
170 |
+
)
|
171 |
+
voz_seleccionada = gr.Dropdown(
|
172 |
+
label="Voz",
|
173 |
+
choices=["es-ES-AlvaroNeural", "es-MX-BeatrizNeural"],
|
174 |
+
value="es-ES-AlvaroNeural"
|
175 |
+
)
|
176 |
+
procesar_btn = gr.Button("Generar Video")
|
177 |
+
video_output = gr.Video(label="Video Procesado")
|
178 |
+
|
179 |
+
with gr.Accordion("Ejemplos de Uso", open=False):
|
180 |
+
gr.Examples(
|
181 |
+
examples=[[EJEMPLO_VIDEO, "¡Hola! Esto es una prueba. Suscríbete al canal."]],
|
182 |
+
inputs=[video_input, texto_tts],
|
183 |
+
label="Ejemplos"
|
184 |
+
)
|
185 |
+
|
186 |
+
procesar_btn.click(
|
187 |
+
procesar_video,
|
188 |
+
inputs=[video_input, texto_tts, voz_seleccionada],
|
189 |
+
outputs=video_output
|
190 |
+
)
|
191 |
+
|
192 |
+
if __name__ == "__main__":
|
193 |
+
demo.queue().launch()
|