Proyectos y exportación
Organiza escenas, recursos y salidas en un proyecto; compruébalo y expórtalo
En esta guía aprenderás a trabajar con un proyecto de Gaanim de principio a fin: qué contiene, cómo carga sus recursos, qué pasa cuando guardas un archivo, cómo comprobarlo sin abrir ventana y cómo exportarlo al formato que necesites.
Si todavía no tienes Gaanim instalado ni un proyecto creado, empieza por Instalación: allí están gaanim init, la estructura que genera y cómo se prepara el entorno de Python.
Por qué un proyecto
Gaanim puede abrir un script suelto (gaanim escena.py), pero un proyecto mantiene juntos el código, los recursos y las exportaciones, y se abre igual desde cualquier directorio. Hay dos tipos:
video: una escena animada 16:9 pensada para exportarse.slides: segmentos con nombre, notas y paradas para presentar en vivo (ver Presentaciones).
gaanim sin argumentos abre el Inicio, desde donde puedes crear un proyecto, abrir una carpeta o volver a uno de los diez proyectos recientes. Los scripts sueltos no se añaden a esa lista. Los botones junto a Clear list cambian entre la lista y una cuadrícula de tarjetas con la imagen de cada proyecto, y Gaanim recuerda la elección. La imagen de un proyecto la guarda el editor al abrirlo: el fotograma de scene.thumbnail(t) si el script lo elige, si no el de la primera pausa, y sin pausas el más lleno de unos pocos instantes del primer segmento, el que menos fondo vacío deja ver. Se renueva como mucho cada cinco minutos mientras editas y se guarda en la carpeta de datos de Gaanim, no en el proyecto. Un paquete .gaanim muestra su portada.
Un paquete exportado dentro de la carpeta de un proyecto reciente no aparece aparte: va con su proyecto, que dice hace cuánto se grabó el último y lo reproduce con su botón, y presta su portada al proyecto mientras el editor no le haya guardado una. El buscador junto a Clear list filtra por nombre o ruta. La chincheta fija un proyecto arriba de la lista: los fijados no salen de ella por antigüedad ni con Clear list, solo al quitarlos. Para volver al Inicio desde el editor, usa el botón de la casa de la barra de reproducción.
El manifiesto gaanim.toml
Cada proyecto tiene un gaanim.toml en su raíz:
name = "mi-charla"
kind = "slides"
entry = "main.py"
assets_dir = "assets"
output_dir = "exports"entryes el script que se ejecuta. Debe ser una ruta relativa que quede dentro del proyecto.kindsolo aceptavideooslides.assets_dires la carpeta de recursos que carga la escena.output_dires la carpeta sugerida para las exportaciones.
La referencia de gaanim.toml describe cada clave.
--force en gaanim init actualiza los archivos conocidos del proyecto sin borrar tus recursos ni otras carpetas.
Cargar los recursos del proyecto
Para que las rutas de imágenes, SVG, audio o modelos no dependan del directorio desde el que se abre Gaanim, carga el manifiesto al principio de la escena. Después, las rutas se resuelven dentro de assets_dir:
from gaanim import Scene
scene = Scene(frame=(16, 9))
scene.assets.load_project() # busca gaanim.toml desde la carpeta del script hacia arriba
logo = scene.media.svg("logo.svg") # busca assets/logo.svg
scene.play([logo.animate.fade_in().duration(0.5)])
scene.render()Si no usas manifiesto, scene.assets.assets_dir("assets") fija la carpeta de recursos directamente. Consulta Recursos para los formatos admitidos.
Abrir, comprobar y presentar
Puedes pasar la carpeta del proyecto en lugar de la ruta de main.py:
gaanim mi-charla # vista previa con recarga al guardar
gaanim check mi-charla # ejecuta la escena sin ventana
gaanim check mi-charla --strict # falla también con avisos
gaanim --present --monitor 1 mi-charlaDentro del proyecto, . es la carpeta actual: gaanim . o gaanim check ..
gaanim check ejecuta el script completo, calcula la duración y revisa los segmentos, las notas y las paradas si las hay; en proyectos slides también comprueba el formato 16:9 y los marcadores de plantilla sin rellenar. Úsalo antes de exportar o en integración continua.
Qué pasa al guardar
La vista previa vuelve a ejecutar la escena cada vez que guardas.
Recarga incremental
Los segmentos anteriores al primero que cambió conservan su escena compilada y solo se recompila desde ahí. El aviso de recarga lo indica, por ejemplo replay 0.12s (reused 37/40 segments), y seek dice cuánto tardó en volver a la posición donde estabas. La primera edición en una zona nueva recompila todo una vez; las siguientes en esa zona ya son incrementales.
Si nada de lo que se compila cambió, por ejemplo al guardar sin cambios o al editar solo un comentario, la escena se conserva tal cual y el aviso dice (unchanged, 40 segments). Volver a la posición de trabajo cuesta entonces lo mismo que un salto cualquiera.
Se recompila todo cuando:
- cambia algo global (tema, fuentes, tamaño del lienzo);
- un segmento posterior modifica objetos creados antes, por ejemplo al agrupar un logo que aparece desde el principio;
- desde cualquier segmento que use funciones de Python en tiempo de ejecución (animaciones propias, updaters, funciones reactivas o easings propios).
El resultado siempre es idéntico al de una recarga completa. Para forzar esta última, inicia Gaanim con la variable de entorno GAANIM_INCREMENTAL=0.
Recursos
Guardar un archivo que no sea Python dentro del proyecto (imágenes, SVG, Lottie, WGSL, fuentes, documentos Typst, datos) vuelve a ejecutar el script leyendo de nuevo ese archivo, no el resto: las cachés olvidan solo lo que guardaban de él. La recarga sigue siendo incremental y recompila desde el primer segmento que lo usa; si la escena no lo lee, queda igual (unchanged).
Se ignoran los archivos y carpetas ocultos (.git, .venv, archivos de intercambio del editor), venv, env, __pycache__, exports, snapshots, target, los temporales (~, .swp, .tmp, .bak) y los .lock. Un guardado cuenta por el archivo que guarda: las herramientas que escriben un temporal y lo renombran sobre el archivo (como main.py.tmp.* o el sedXXXXXX de sed -i) y la carpeta, que Windows también da por cambiada, no cuentan como cambios.
Módulos de Python del proyecto
Puedes repartir el código en varios módulos. Antes de cada ejecución, Gaanim descarta de sys.modules los módulos cuyo archivo está dentro del proyecto (salvo en las carpetas ignoradas), así que guardar un .py importado por main.py lo vuelve a importar. Los paquetes instalados y el código fuera del proyecto siguen en caché hasta reiniciar Gaanim.
La raíz del proyecto, su carpeta src/ y la carpeta del script están en sys.path, y __file__, sys.argv[0] y sys.path usan rutas normales, sin el prefijo \\?\ de Windows.
Exportar
Para exportar no cambias el script: se lo pides al ejecutable.
gaanim export mi-video --output mi-video/exports/final.mp4La extensión de --output elige el formato:
| Extensión | Formato | Necesita FFmpeg |
|---|---|---|
.mp4 | video H.264, con el audio de la escena | sí |
.webm | video VP9, con audio; admite transparencia | sí |
.webp | WebP animado; admite transparencia | sí |
.gif | GIF animado | sí |
.png | secuencia de imágenes, una por fotograma; admite transparencia | no |
En una secuencia PNG, un %d o %0Nd en el nombre se sustituye por el número de fotograma (frames/f_%04d.png produce f_0000.png, f_0001.png…); si no, el número se añade al final (frame_00000.png).
Opciones
--quality draftexporta rápido a 30 fps para revisar;standard(la predeterminada) usa 60 fps yproduction, la mejor codificación.--fpselige otra frecuencia:24,25,50o una fracción NTSC como24000/1001.--widthy--heighteligen la resolución en píxeles (1920 × 1080 por defecto). La escena no cambia: sus unidades lógicas se escalan.--fit containo--fit coverpermiten una salida con otra proporción que la escena:containañade bandas ycoverrecorta. Sin--fit, una proporción distinta es un error.--fromy--toexportan solo un tramo. Aceptan segundos o el nombre de un marcador creado conscene.marker("nombre"); el audio se recorta al tramo.--transparentconserva el canal alfa en WebM, MOV, WebP y PNG; la escena necesita un fondo transparente. Un.moves Apple ProRes, para montar la animación en un editor de vídeo.--encoderelige el codificador de MP4:auto(predeterminado) prueba los de hardware y recurre alibx264; también aceptalibx264,nvenc,amf,qsvyvaapi, que no recurren a otro si fallan.
gaanim export --help y la referencia de la línea de comandos listan todas las opciones. Las paradas (scene.stop(...)) no detienen la exportación: el resultado es un video continuo.
Desde el editor
El botón Export de la barra de reproducción abre las mismas opciones. Al pulsar Export, el diálogo se cierra y la exportación sigue en segundo plano: puedes seguir reproduciendo y navegando la escena. La barra de tiempo marca en violeta, bajo cada segmento, la parte ya exportada; la barra de reproducción muestra el porcentaje (pasa el cursor para ver fotogramas y tiempo restante) y una X para cancelar. La terminal desde la que abriste gaanim muestra la misma barra de progreso que gaanim export y el resultado. Al terminar aparece un aviso en la esquina con el archivo y un botón para abrirlo.
En File escribes solo el nombre: la extensión la pone el formato. Al principio es el del proyecto (su carpeta, si el script es main.py, o el nombre del script), en la carpeta output_dir de gaanim.toml. Change… elige otra carpeta con el selector del sistema; pasa el cursor por ella para ver la ruta completa. Si ya existe un archivo con ese nombre, el diálogo avisa de que lo reemplazará y ofrece el siguiente nombre libre (intro-2, intro-3…). Sin nombre no se puede exportar.
El formato PNG exporta un PNG por fotograma (frame_00000.png, frame_00001.png…) para editar o componer en otro programa. Los fotogramas van a una carpeta con el nombre que escribas, y el aviso final abre esa carpeta.
Para guardar solo el fotograma que estás viendo, pulsa Ctrl+Mayús+S (Cmd+Mayús+S en macOS) o el botón de captura de la barra de overlays. Se renderiza aparte, sin overlays ni paneles, a 1920 píxeles en el lado largo, y se guarda en <output_dir>/captures/ con el nombre del script y el instante (main_2.35s.png); nunca reemplaza una captura anterior.
Convertir un script suelto en proyecto
Crea un proyecto con gaanim init video mi-video, reemplaza su main.py por tu script, añade scene.assets.load_project() justo después de crear la Scene y mueve los recursos a assets/. Funciona igual desde main.py que desde un módulo de un paquete del proyecto, como capitulo4/estilo.py: busca el gaanim.toml más cercano subiendo de carpeta.
Si algo falla al abrir o exportar, consulta Solución de problemas.