Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1027,6 +1027,7 @@ def run_app(prompt_type, prompt_ia, prompt_manual, musica_file, selected_voice):
|
|
| 1027 |
return output_video, output_file, status_msg
|
| 1028 |
|
| 1029 |
|
|
|
|
| 1030 |
# Interfaz de Gradio
|
| 1031 |
with gr.Blocks(title="Generador de Videos con IA", theme=gr.themes.Soft(), css="""
|
| 1032 |
.gradio-container {max-width: 800px; margin: auto;}
|
|
@@ -1044,23 +1045,25 @@ with gr.Blocks(title="Generador de Videos con IA", theme=gr.themes.Soft(), css="
|
|
| 1044 |
value="Generar Guion con IA"
|
| 1045 |
)
|
| 1046 |
|
| 1047 |
-
# Contenedores para controlar la visibilidad
|
| 1048 |
with gr.Column(visible=True) as ia_guion_column:
|
| 1049 |
prompt_ia = gr.Textbox(
|
| 1050 |
label="Tema para IA",
|
| 1051 |
lines=2,
|
| 1052 |
-
placeholder="Ej: Un paisaje natural con montañas y ríos al amanecer...",
|
| 1053 |
max_lines=4,
|
| 1054 |
value=""
|
|
|
|
| 1055 |
)
|
| 1056 |
|
| 1057 |
with gr.Column(visible=False) as manual_guion_column:
|
| 1058 |
prompt_manual = gr.Textbox(
|
| 1059 |
label="Tu Guion Completo",
|
| 1060 |
lines=5,
|
| 1061 |
-
placeholder="Ej: En este video exploraremos los misterios del océano
|
| 1062 |
max_lines=10,
|
| 1063 |
value=""
|
|
|
|
| 1064 |
)
|
| 1065 |
|
| 1066 |
musica_input = gr.Audio(
|
|
@@ -1068,17 +1071,20 @@ with gr.Blocks(title="Generador de Videos con IA", theme=gr.themes.Soft(), css="
|
|
| 1068 |
type="filepath",
|
| 1069 |
interactive=True,
|
| 1070 |
value=None
|
|
|
|
| 1071 |
)
|
| 1072 |
|
| 1073 |
-
# --- Selección de Voz ---
|
| 1074 |
voice_dropdown = gr.Dropdown(
|
| 1075 |
label="Seleccionar Voz para Guion",
|
| 1076 |
-
choices=AVAILABLE_VOICES,
|
| 1077 |
-
value=DEFAULT_VOICE_ID,
|
| 1078 |
interactive=True
|
|
|
|
| 1079 |
)
|
| 1080 |
# --- FIN COMPONENTE ---
|
| 1081 |
|
|
|
|
| 1082 |
generate_btn = gr.Button("✨ Generar Video", variant="primary")
|
| 1083 |
|
| 1084 |
with gr.Column():
|
|
@@ -1086,11 +1092,13 @@ with gr.Blocks(title="Generador de Videos con IA", theme=gr.themes.Soft(), css="
|
|
| 1086 |
label="Previsualización del Video Generado",
|
| 1087 |
interactive=False,
|
| 1088 |
height=400
|
|
|
|
| 1089 |
)
|
| 1090 |
file_output = gr.File(
|
| 1091 |
label="Descargar Archivo de Video",
|
| 1092 |
interactive=False,
|
| 1093 |
-
visible=False
|
|
|
|
| 1094 |
)
|
| 1095 |
status_output = gr.Textbox(
|
| 1096 |
label="Estado",
|
|
@@ -1098,44 +1106,51 @@ with gr.Blocks(title="Generador de Videos con IA", theme=gr.themes.Soft(), css="
|
|
| 1098 |
show_label=False,
|
| 1099 |
placeholder="Esperando acción...",
|
| 1100 |
value="Esperando entrada..."
|
|
|
|
| 1101 |
)
|
| 1102 |
|
| 1103 |
-
#
|
| 1104 |
prompt_type.change(
|
| 1105 |
lambda x: (gr.update(visible=x == "Generar Guion con IA"),
|
| 1106 |
gr.update(visible=x == "Usar Mi Guion")),
|
| 1107 |
inputs=prompt_type,
|
| 1108 |
-
outputs=[ia_guion_column, manual_guion_column]
|
| 1109 |
)
|
| 1110 |
|
| 1111 |
-
#
|
| 1112 |
generate_btn.click(
|
|
|
|
| 1113 |
lambda: (None, None, gr.update(value="⏳ Procesando... Esto puede tomar varios minutos.", interactive=False)),
|
| 1114 |
outputs=[video_output, file_output, status_output],
|
| 1115 |
-
queue=True,
|
| 1116 |
).then(
|
|
|
|
| 1117 |
run_app,
|
| 1118 |
-
|
| 1119 |
-
|
|
|
|
|
|
|
|
|
|
| 1120 |
).then(
|
|
|
|
| 1121 |
lambda video_path, file_path, status_msg: gr.update(visible=file_path is not None),
|
| 1122 |
inputs=[video_output, file_output, status_output],
|
| 1123 |
outputs=[file_output]
|
| 1124 |
)
|
| 1125 |
|
|
|
|
| 1126 |
gr.Markdown("### Instrucciones:")
|
| 1127 |
gr.Markdown("""
|
| 1128 |
1. **Clave API de Pexels:** Asegúrate de haber configurado la variable de entorno `PEXELS_API_KEY` con tu clave.
|
| 1129 |
2. **Selecciona el tipo de entrada**: "Generar Guion con IA" o "Usar Mi Guion".
|
| 1130 |
-
3. **Sube música** (opcional).
|
| 1131 |
-
4. **Selecciona la voz** deseada.
|
| 1132 |
5. **Haz clic en "✨ Generar Video"**.
|
| 1133 |
-
6. Espera
|
| 1134 |
-
7.
|
| 1135 |
-
8. Revisa `video_generator_full.log` si hay errores.
|
| 1136 |
""")
|
| 1137 |
gr.Markdown("---")
|
| 1138 |
-
gr.Markdown("Desarrollado por [Tu Nombre/Empresa/Alias]")
|
| 1139 |
|
| 1140 |
if __name__ == "__main__":
|
| 1141 |
logger.info("Verificando dependencias críticas...")
|
|
@@ -1146,17 +1161,17 @@ if __name__ == "__main__":
|
|
| 1146 |
temp_clip.close()
|
| 1147 |
logger.info("Clips base de MoviePy creados y cerrados exitosamente. FFmpeg parece accesible.")
|
| 1148 |
except Exception as e:
|
| 1149 |
-
logger.critical(f"Fallo al crear clip base de MoviePy. Error: {e}", exc_info=True)
|
|
|
|
| 1150 |
except Exception as e:
|
| 1151 |
-
|
| 1152 |
|
| 1153 |
-
#
|
| 1154 |
-
os.environ['GRADIO_SERVER_TIMEOUT'] = '6000' #
|
| 1155 |
-
# -------------------
|
| 1156 |
|
| 1157 |
logger.info("Iniciando aplicación Gradio...")
|
| 1158 |
try:
|
| 1159 |
app.queue(max_size=1).launch(server_name="0.0.0.0", server_port=7860, share=False)
|
| 1160 |
except Exception as e:
|
| 1161 |
logger.critical(f"No se pudo iniciar la app: {str(e)}", exc_info=True)
|
| 1162 |
-
raise
|
|
|
|
| 1027 |
return output_video, output_file, status_msg
|
| 1028 |
|
| 1029 |
|
| 1030 |
+
```python
|
| 1031 |
# Interfaz de Gradio
|
| 1032 |
with gr.Blocks(title="Generador de Videos con IA", theme=gr.themes.Soft(), css="""
|
| 1033 |
.gradio-container {max-width: 800px; margin: auto;}
|
|
|
|
| 1045 |
value="Generar Guion con IA"
|
| 1046 |
)
|
| 1047 |
|
| 1048 |
+
# Contenedores para los campos de texto para controlar la visibilidad
|
| 1049 |
with gr.Column(visible=True) as ia_guion_column:
|
| 1050 |
prompt_ia = gr.Textbox(
|
| 1051 |
label="Tema para IA",
|
| 1052 |
lines=2,
|
| 1053 |
+
placeholder="Ej: Un paisaje natural con montañas y ríos al amanecer, mostrando la belleza de la naturaleza...",
|
| 1054 |
max_lines=4,
|
| 1055 |
value=""
|
| 1056 |
+
# visible=... <-- ¡NO DEBE ESTAR AQUÍ!
|
| 1057 |
)
|
| 1058 |
|
| 1059 |
with gr.Column(visible=False) as manual_guion_column:
|
| 1060 |
prompt_manual = gr.Textbox(
|
| 1061 |
label="Tu Guion Completo",
|
| 1062 |
lines=5,
|
| 1063 |
+
placeholder="Ej: En este video exploraremos los misterios del océano. Veremos la vida marina fascinante y los arrecifes de coral vibrantes. ¡Acompáñanos en esta aventura subacuática!",
|
| 1064 |
max_lines=10,
|
| 1065 |
value=""
|
| 1066 |
+
# visible=... <-- ¡NO DEBE ESTAR AQUÍ!
|
| 1067 |
)
|
| 1068 |
|
| 1069 |
musica_input = gr.Audio(
|
|
|
|
| 1071 |
type="filepath",
|
| 1072 |
interactive=True,
|
| 1073 |
value=None
|
| 1074 |
+
# visible=... <-- ¡NO DEBE ESTAR AQUÍ!
|
| 1075 |
)
|
| 1076 |
|
| 1077 |
+
# --- COMPONENTE: Selección de Voz ---
|
| 1078 |
voice_dropdown = gr.Dropdown(
|
| 1079 |
label="Seleccionar Voz para Guion",
|
| 1080 |
+
choices=AVAILABLE_VOICES, # Usar la lista obtenida al inicio
|
| 1081 |
+
value=DEFAULT_VOICE_ID, # Usar el ID de la voz por defecto calculada
|
| 1082 |
interactive=True
|
| 1083 |
+
# visible=... <-- ¡NO DEBE ESTAR AQUÍ!
|
| 1084 |
)
|
| 1085 |
# --- FIN COMPONENTE ---
|
| 1086 |
|
| 1087 |
+
|
| 1088 |
generate_btn = gr.Button("✨ Generar Video", variant="primary")
|
| 1089 |
|
| 1090 |
with gr.Column():
|
|
|
|
| 1092 |
label="Previsualización del Video Generado",
|
| 1093 |
interactive=False,
|
| 1094 |
height=400
|
| 1095 |
+
# visible=... <-- ¡NO DEBE ESTAR AQUÍ!
|
| 1096 |
)
|
| 1097 |
file_output = gr.File(
|
| 1098 |
label="Descargar Archivo de Video",
|
| 1099 |
interactive=False,
|
| 1100 |
+
visible=False # <-- ESTÁ BIEN AQUÍ
|
| 1101 |
+
# visible=... <-- ¡NO DEBE ESTAR AQUÍ si ya está visible=False arriba!
|
| 1102 |
)
|
| 1103 |
status_output = gr.Textbox(
|
| 1104 |
label="Estado",
|
|
|
|
| 1106 |
show_label=False,
|
| 1107 |
placeholder="Esperando acción...",
|
| 1108 |
value="Esperando entrada..."
|
| 1109 |
+
# visible=... <-- ¡NO DEBE ESTAR AQUÍ!
|
| 1110 |
)
|
| 1111 |
|
| 1112 |
+
# Evento para mostrar/ocultar los campos de texto según el tipo de prompt
|
| 1113 |
prompt_type.change(
|
| 1114 |
lambda x: (gr.update(visible=x == "Generar Guion con IA"),
|
| 1115 |
gr.update(visible=x == "Usar Mi Guion")),
|
| 1116 |
inputs=prompt_type,
|
| 1117 |
+
outputs=[ia_guion_column, manual_guion_column] # Apuntar a las Columnas contenedoras
|
| 1118 |
)
|
| 1119 |
|
| 1120 |
+
# Evento click del botón de generar video
|
| 1121 |
generate_btn.click(
|
| 1122 |
+
# Acción 1 (síncrona): Resetear salidas y establecer estado
|
| 1123 |
lambda: (None, None, gr.update(value="⏳ Procesando... Esto puede tomar varios minutos.", interactive=False)),
|
| 1124 |
outputs=[video_output, file_output, status_output],
|
|
|
|
| 1125 |
).then(
|
| 1126 |
+
# Acción 2 (asíncrona): Llamar a la función principal
|
| 1127 |
run_app,
|
| 1128 |
+
# PASAR TODOS LOS INPUTS DE LA INTERFAZ que run_app espera
|
| 1129 |
+
inputs=[prompt_type, prompt_ia, prompt_manual, musica_input, voice_dropdown], # <-- Pasar los 5 inputs a run_app
|
| 1130 |
+
# run_app retornará los 3 outputs esperados
|
| 1131 |
+
outputs=[video_output, file_output, status_output],
|
| 1132 |
+
queue=True # ← ÚNICO CAMBIO: evita timeout en procesos largos
|
| 1133 |
).then(
|
| 1134 |
+
# Acción 3 (síncrona): Hacer visible el enlace de descarga
|
| 1135 |
lambda video_path, file_path, status_msg: gr.update(visible=file_path is not None),
|
| 1136 |
inputs=[video_output, file_output, status_output],
|
| 1137 |
outputs=[file_output]
|
| 1138 |
)
|
| 1139 |
|
| 1140 |
+
|
| 1141 |
gr.Markdown("### Instrucciones:")
|
| 1142 |
gr.Markdown("""
|
| 1143 |
1. **Clave API de Pexels:** Asegúrate de haber configurado la variable de entorno `PEXELS_API_KEY` con tu clave.
|
| 1144 |
2. **Selecciona el tipo de entrada**: "Generar Guion con IA" o "Usar Mi Guion".
|
| 1145 |
+
3. **Sube música** (opcional): Selecciona un archivo de audio (MP3, WAV, etc.).
|
| 1146 |
+
4. **Selecciona la voz** deseada del desplegable.
|
| 1147 |
5. **Haz clic en "✨ Generar Video"**.
|
| 1148 |
+
6. Espera a que se procese el video. Verás el estado.
|
| 1149 |
+
7. La previsualización aparecerá si es posible, y siempre un enlace **Descargar Archivo de Video** se mostrará si la generación fue exitosa.
|
| 1150 |
+
8. Revisa `video_generator_full.log` para detalles si hay errores.
|
| 1151 |
""")
|
| 1152 |
gr.Markdown("---")
|
| 1153 |
+
gr.Markdown("Desarrollado por [Tu Nombre/Empresa/Alias - Opcional]")
|
| 1154 |
|
| 1155 |
if __name__ == "__main__":
|
| 1156 |
logger.info("Verificando dependencias críticas...")
|
|
|
|
| 1161 |
temp_clip.close()
|
| 1162 |
logger.info("Clips base de MoviePy creados y cerrados exitosamente. FFmpeg parece accesible.")
|
| 1163 |
except Exception as e:
|
| 1164 |
+
logger.critical(f"Fallo al crear clip base de MoviePy. A menudo indica problemas con FFmpeg/ImageMagick. Error: {e}", exc_info=True)
|
| 1165 |
+
|
| 1166 |
except Exception as e:
|
| 1167 |
+
logger.critical(f"Fallo al importar MoviePy. Asegúrate de que está instalado. Error: {e}", exc_info=True)
|
| 1168 |
|
| 1169 |
+
# Solución para el timeout de Gradio - Añadir esta línea
|
| 1170 |
+
os.environ['GRADIO_SERVER_TIMEOUT'] = '6000' # 600 segundos = 10 minutos
|
|
|
|
| 1171 |
|
| 1172 |
logger.info("Iniciando aplicación Gradio...")
|
| 1173 |
try:
|
| 1174 |
app.queue(max_size=1).launch(server_name="0.0.0.0", server_port=7860, share=False)
|
| 1175 |
except Exception as e:
|
| 1176 |
logger.critical(f"No se pudo iniciar la app: {str(e)}", exc_info=True)
|
| 1177 |
+
raise
|