Communitygithub.com

brewed-ops/spatial-film

Spatial Film: el motor cinematográfico detrás de talking-explainer. Crea un motion graphic 3D espacial de producto sin narración de 45 a 90 segundos (una cámara CSS-3D, avances sin cortes duros, el último fotograma enlaza con el primero) con interfaz de producto real, lienzos de terceros fieles a la plataforma (GHL, n8n, Zapier), una banda sonora con tempo nativo y efectos de sonido, renderizado a 1080p60 mediante HyperFrames.

¿Qué es spatial-film?

Spatial Film es un skill especializado para agentes de IA (como Claude Code, Cursor o Codex) que permite la creación de motion graphics 3D de producto de alta calidad, sin narración, en resoluciones de 1080p60. Está diseñado para producir videos de 45 a 90 segundos con una sola cámara CSS-3D, transiciones fluidas (push-throughs sin cortes duros) y un bucle perfecto donde el último fotograma enlaza con el primero. El skill se apoya en HyperFrames para el renderizado final y utiliza cinco workers de escena en paralelo que trabajan contra un único contrato (frame.md + tabla de costuras + andamiaje por escena). Es especialmente útil cuando un usuario solicita explícitamente un 'spatial film' o un 'motion graphic 3D', proporciona un archivo MOTION-PROMPT.md o pide un video de producto con más de 6 escenas y cámara 3D sin locución. Aunque el skill está optimizado para videos sin narración, también contiene maquinaria (en 'explainer-kit') para soportar videos narrados con presentador en pantalla. El flujo de trabajo se organiza en seis fases numeradas, cada una con una puerta de verificación (gate) que debe superarse antes de avanzar. Se incluyen más de 20 scripts de utilidad para tareas como andamiaje, captura de superficies, análisis de música, montaje, verificación de costuras, renderizado y codificación web. El skill impone reglas estrictas de calidad: verdad desde la fuente (la interfaz de producto se porta del HTML/CSS real), una sola cámara con perspectiva 1866px, nitidez a 1080p+ usando zoom CSS, animaciones fluidas a 60 fps basadas en transform y opacidad, costuras como fotogramas compartidos deterministas, y renderizado final desde CLI con GPU de hardware.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/brewed-ops/talking-explainer/tree/main/skills/spatial-film

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Spatial Film

Probado de principio a fin en un vídeo de producto de 60 s (7 escenas, 5 workers en una sola oleada, cada costura exacta al fotograma, comprobación limpia, 1080p60 en 4m19s). La plantilla film.json contiene las barras de escena reales y la hoja de referencia de ese vídeo como ejemplo práctico.

<skill> = la carpeta de este skill (el directorio donde está este SKILL.md). Ejecuta cada script desde la raíz del proyecto de vídeo. python abajo = el comando Python guardado por la comprobación de configuración de explainer-kit en ~/.talking-explainer/config.json (py -3.12 en Windows, python3 en macOS).

Lo que necesitas

  • Node 20+, ffmpeg + ffprobe en PATH, Python 3.10+ con numpy y Pillow.
  • Los skills de HyperFrames: npx hyperframes skills update general-video hyperframes-animation media-use (constructor de paquetes, planos + mapa de animación, ayudante de música). El CLI en sí está fijado por proyecto y se ejecuta a través de npx.
  • Playwright para prerenderizar superficies: npm i -D playwright en la carpeta del vídeo (o configura PLAYWRIGHT_PATH).
  • Opcional, para música con fuente: una cuenta de HeyGen; ejecuta npx hyperframes auth login una vez en tu terminal. Sin ella, usa tu propia pista y comienza la fase 4 en music-analyze.py.
  • Una máquina con GPU para el renderizado final (aún renderiza por la ruta de software, unas 15 veces más lento).

Cómo usar este skill sin desperdiciar contexto

  • Carga UNA referencia de fase a la vez, cuando esa fase comience. Nunca las precargues todas.
  • Los scripts son el código probado. Ejecútalos; nunca regeneres su lógica en línea.
  • La sesión principal nunca lee un archivo de escena completo (20-60KB). Evalúa las escenas por hojas de contacto; corrige con grep -n más un parche exacto.
  • Los workers reciben RUTAS de archivo, no contenido pegado. storyboard.html (60KB+) se busca por id de celda, nunca se lee completo.
  • Lee primero una hoja de contacto; abre solo los PNG de instantánea individuales para comprobar un detalle.

Fases (cada una termina en una puerta - no avances hasta que pase)

#FaseCargarPuerta
0Andamiaje: node <skill>/scripts/new-film.mjs <dir> --name <slug>-la carpeta tiene film.json, frame.md, kit, documentos de plantilla
1Recepción, BRIEF, STORYBOARD, hoja de bocetosreferences/storyboard.md"ok" explícito del usuario registrado bajo ## Bloqueado
2frame.md, kit, superficies prerenderizadasreferences/surfaces.md (+ platform-canvases.md solo si aparecen GHL/n8n/Zapier)sin {{ en frame.md; cada PNG de captura revisado
3Prueba de humo del andamiaje, paquetes, workers paralelosreferences/workers.mdcada escena: lint 0 errores, la hoja de contacto coincide con su bloque
4Música + SFX (ejecutar mientras los workers construyen)references/audio.mdbase musical a BPM nativo, compás 0 en un tiempo fuerte; claves en film.json
5Montaje, comprobación, costuras, renderizado, envíoreferences/verify-ship.mdcomprobación pasa, verificación de costuras todo OK, renderizado con gpu de hardware verificado

Ruta a través de /hyperframes -> /general-video para los pasos de intención y revisión de bocetos (este skill proporciona la forma del proyecto, el contrato, los scripts y las puertas; general-video proporciona el constructor de paquetes y el rol de worker).

Archivos

RutaQué
template/Esqueleto del proyecto: film.json (barras de escena, BPM, bgm, SFX, claves - la ÚNICA fuente de tiempo), frame.md (contrato de verdad de diseño con rellenos), BRIEF.md, STORYBOARD.md, assets/kit.css (kit base del vídeo), assets/fonts/ (Poppins 500/700 + OFL), references/worker-brief.md, references/scene-starter.html (esqueleto de escena limpio de lint), references/snippets.html, package.json (hyperframes 0.8.117 fijado).
surfaces/Reconstrucciones HTML listas de los lienzos de GHL, n8n y Zapier + una página de marketing larga (datos ficticios de Northwind Dental), platform.css, sprite.svg, jobs.json.
scripts/new-film.mjsAndamiaje de un proyecto a partir de la plantilla.
scripts/capture-surfaces.cjsRenderiza src/captures/*.html -> assets/captures/*.png a 2x (jobs.json).
scripts/measure-surface.cjsCajas 1x de elementos en una superficie, para objetivos exactos de anotación/recorte.
scripts/make-harness.py, scripts/test-scene.mjsProyectos de prueba aislados por escena; lint + instantánea de una escena.
scripts/music-search.mjs, sfx-search.mjsCatálogo HeyGen mediante el helper REST de media-use (seguro en Windows).
scripts/music-analyze.py, music-bars.pyTempo solo con numpy + energía por compás (no necesita librosa).
scripts/bgm-cut.pyCorta la base musical en líneas de compás, empalma el propio outro de la pista, fundidos; --b repite para hacer un bucle de una base debajo de un vídeo más largo.
scripts/assemble.pyfilm.json -> index.html (ranuras de escena en la cuadrícula de compases, bgm, SFX con duraciones + carriles).
scripts/seam-check.pyComprueba cada costura (antes / en / después del corte) y el bucle (fotograma 0 vs último) a nivel de píxel.
scripts/render-final.mjsRenderizado CLI con --browser-gpu, registrado en un archivo, modo gpu + ffprobe verificado, luego flash-scan.py.
scripts/flash-scan.pyCada fotograma de un renderizado: un fotograma distinto a ambos vecinos (un elemento mostrado durante 1/60 s) = un error.
scripts/encode-web.mjsCodificación web (H.264 CRF 21, faststart, AAC o --silent) + fotograma de póster.
scripts/blink-fit.py, scripts/build-presenter.pyVídeos narrados: superposiciones de parpadeo para poses de hoja (--band = banda de ojo); la superposición del presentador desde su pista, con sincronía de labios cuando la mascota tiene mouth-fit.json.
scripts/el-tts.py, el-words.py, el-music.pyVídeos narrados mediante ElevenLabs (clave en env EL, nunca en disco): candidatos de voz desde SCRIPT.md, tiempos de palabra de Scribe, una base generada.
scripts/seam-diff.pyDiferencia de costura con la caja del presentador enmascarada (vídeos narrados).
scripts/fromto-scan.pyPre-renderizado: marca props fromTo solo FROM que los workers de renderizado (búsquedas en mitad de escena) nunca aplican. 0 aciertos antes de cada renderizado.
scripts/patch_exact.pyBuscar/reemplazar exacto, seguro con CRLF para correcciones de escena con script (afirma una coincidencia cada una).
scripts/selftest.mjsPrueba de extremo a extremo de que el skill funciona en esta máquina. Debe imprimir PASS.

Vídeos narrados (una locución + un presentador en pantalla)

Probado en un explicador narrado "API vs Webhook" (83 s, vertical y apaisado, voz clonada, presentador mascota, 10 escenas por 5 workers). Las reglas del vídeo musical anteriores siguen vigentes excepto donde estas las reemplazan:

  • Candidatos de voz primero. EL=<key> python <skill>/scripts/el-tts.py . eric=<voice_id> michelle=<voice_id> lee las líneas sangradas de SCRIPT.md y escribe un MP3 por voz en src/audio/voice-candidates/ (clave solo de env, nunca en disco). Deja que el usuario elija de oído, luego transcribe solo la elección.
  • La narración es el reloj. Tiempos de palabra: EL=<key> python <skill>/scripts/el-words.py <voice.mp3> src/timing/voice-words.json (ElevenLabs Scribe - sin modelo local, necesita una clave), o faster-whisper con word_timestamps (idioma configurado, VAD activado; transcribe.py de explainer-kit, gratis y local). Mantén el JSON de palabras en src/timing/. En film.json configura "bpm": 60, "beats_per_bar": 1 para que un "compás" sea 1 s y las duraciones de escena sean segundos simples cortados en las pausas de las frases. Los bloques del storyboard dan tiempos de palabra locales a la escena; las llegadas comienzan ~0.1 s antes y aterrizan en la palabra. Dale a un título al menos ~1 s en pantalla antes del siguiente corte (comprueba el corte contra la ÚLTIMA palabra de la línea que muestra).
  • Extras de film.json (assemble.py + make-harness.py los leen): "audio": [{id, src, dur, volume}] para la voz, "overlays": [{id, track, z}] para una capa de película completa (el presentador) que se sienta sobre cada escena, por lo que nunca aparece en una costura y las escenas permanecen libres de presentador.
  • Presentador desde PNGs de pose: un PNG transparente por pose (prep-mascot.py de explainer-kit recorta, escala y escribe el manifiesto), luego scripts/blink-fit.py <mascot_dir> (opcional, necesita torch; ajusta la banda de ojo BLINK en cada pose mediante NCC; las poses por debajo de 0.70 no reciben parpadeo) y scripts/build-presenter.py (escribe la superposición desde src/presenter-track.json: poses en palabras clave, anclado a la cabeza para que los intercambios nunca salten, balanceo por envolvente de voz, respiración, parpadeos, fx). Nunca edites a mano su salida.
  • Audio: loudnorm a la voz a -16 LUFS / -1.5 dBTP (una ganancia simple limitada a +4.6 dBTP), sidechain-duck de la base debajo de ella fuera de línea (~17 dB por debajo de la voz), SFX bajo (0.1-0.45). Rellena la clave de voz o el duck trunca la base a la longitud de la voz (comprueba la advertencia "bgm 110.25s vs slot 113s"): [1:a]apad=whole_dur=<TOTAL>[k];[0:a][k]sidechaincompress=threshold=0.03:ratio=6:attack=25:release=450,atrim=end=<TOTAL>. Sin base de catálogo (HeyGen busca 500 s o sin inicio de sesión): EL=<key> python <skill>/scripts/el-music.py .media/candidates/bed.mp3 <ms> "<prompt: instrumental, BPM, se sienta debajo de un narrador, sin caídas, termina en un acorde resuelto>" - una pista que se desvanece por sí sola en la duración del vídeo no necesita empalme.
  • Ruido de verificación de costura: el presentador se mueve a través de cada costura, por lo que seam-check.py FALLA solo por eso. Evalúa cada par marcado con scripts/seam-diff.py a.png b.png out.png x0,y0,x1,y1 (enmascara la caja del presentador) - 0.00% fuera de ella es un pase.
  • Ley de tamaño vertical (1080x1920): la banda superior de cada escena lleva un titular real (60-84 px), texto del cuerpo >= 40 px, los objetos usan el ancho completo y la altura por encima del presentador. La primera oleada envió ~33 px de texto en el 45% superior del fotograma; pon estos números en frame.md antes del envío, no después.
  • No es un bucle: un vídeo narrado termina en un bloqueo mantenido; ignora la línea de bucle de seam-check.

Reglas estrictas (las que lo hacen premium y suave)

  1. Verdad desde la fuente. La interfaz de producto se porta del HTML/CSS del propio producto; los lienzos de terceros se reconstruyen a partir de las capturas reales del usuario, nunca de memoria. Solo datos ficticios. Solo funciones que el producto realmente tiene.
  2. Una cámara. Perspectiva 1866 mm (35 mm) en cada escena; una capa de deriva debajo de la capa de cámara para que nada esté nunca quieto; paralaje + desenfoque DOF en hojas lejanas. Sin opacidad/filtro/desbordamiento/clip-path en un padre 3D (lo aplana).
  3. Nítido a 1080p+. Escala UI con CSS zoom (.kit-zoom), nunca transform: scale(>1); crea cada pieza a su tamaño en pantalla más cercano; las capturas son PNG 2x mostrados a resolución nativa o inferior.
  4. Ley de suavidad a 60 fps. Solo transform/opacidad; resortes para aterrizajes, expo/power3 para llegadas, inOut para tramos de cámara; sin lineal, pasos, snap ni redondeo; los tramos de cámara se superponen 0.15-0.3 s y duran 0.6 s+.
  5. Determinista. Una línea de tiempo pausada por escena registrada por última vez en window.__timelines[id], fromTo con inicios explícitos, sin random/reloj/transiciones CSS.
  6. Las costuras son fotogramas compartidos. Cada costura es una imagen exacta que ambos vecinos mantienen ~0.1 s, bloqueada por una placa 2D fuera del soporte. Sin corte duro, sin fotograma vacío, sin fundido a nada. Último fotograma = primer fotograma.
  7. En la cuadrícula. Las escenas son compases enteros/medios; clics, ticks, sellos e intercambios caen en tiempos; música a su tempo nativo cortada en líneas de compás.
  8. Correcciones de contrato, no de escena. Rutas assets/... relativas a la raíz, ids que nunca comienzan con un dígito, ids y clases prefijados con el id de la escena. Una regla que toda escena rompería se corrige una vez en frame.md / worker-brief.
  9. Prohibiciones. Sin emoji, resplandor neón, degradado púrpura a azul, tarjetas con borde izquierdo coloreado, spinners circulares (brillo), personas stock, "Juan Pérez", ritmo de presentación de diapositivas o movimiento que no dice nada.
  10. Finales desde el CLI con GPU de hardware. Nunca Exportación de Studio (ruta de software, ~15 veces más lento).

Cuando algo sale mal

SíntomaCausaCorrección
Lint: error de ruta de asset../assets/ en una subcomposiciónruta relativa a la raíz assets/... (corregir en el contrato)
Lint: id de composición inválidoid comienza con un dígitos01-click, nunca 01-click (film.py lo rechaza)
El constructor de paquetes lanza / paquete > 48 KBdos id de plano, o demasiados rules:un id (Adapt); 2-3 reglas por bloque
UI se ve suaveescalado con transform o empujado hacia la cámara más allá del tamaño creado.kit-zoom, crear al tamaño más cercano
3D de repente planoopacidad/filtro/desbordamiento en un ancestro 3Dmoverlo a la hoja
Costura saltaun lado no mantiene el fotograma compartidoseam-check.py, corregir la placa/pose del lado que se desvía
Costura FALLA un pequeño % pero los fotogramas se ven idénticosuna copia del soporte debajo de la placa duplica su sombrasolo la placa se muestra mientras la sostiene (seam en frame.md)
UI del producto se desvía de la aplicación realreconstruida de memoria o CSS parcialcapturar la aplicación real a 2x (primera sección de surfaces.md)
800+ advertencias duplicate_audio_trackSFX sin data-durationvolver a ejecutar assemble.py
music-search dice sin credencialno has iniciado sesiónel usuario ejecuta npx hyperframes auth login en su terminal
El renderizado va a ~1 fotograma/sGPU de software (exportación Studio)render-final.mjs (CLI, --browser-gpu --workers 6)
El renderizado sigue ejecutándose después de parardetener el shell no detiene nodematar el árbol de procesos (verify-ship.md)
Sin progreso de renderizado visiblesalida canalizada a través de `tail`

Autocomprobación

node <skill>/scripts/selftest.mjs

Crea un vídeo de 2 escenas en una carpeta temporal, luego ejecuta el andamiaje, montaje, check, verificación de costura, un renderizado con GPU de hardware (1920x1080 a 60 fps) y la codificación web. Debe imprimir PASS; ejecútalo en una máquina nueva y después de cualquier edición.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills relacionados