En vez de esperar el render dentro de la request (imposible con la cola nocturna de H3),
ahora el ciclo es async y la cola/worker viven server-side en h3api:
- submit no bloqueante: POST /v1/jobs → se persiste una variación `queued` con h3_job_id y se
responde al instante. video-service expone submitVideoJob() + getJobStatus() (sin polling).
- nueva acción `sync-jobs` en el route de vídeos: avanza los jobs pendientes del capítulo
(queued→processing→ready/error); en `done` descarga el mp4, lo guarda y auto-selecciona la
primera variación lista. Reintenta en el siguiente tick ante fallos de red (no marca error).
- SQLite: columnas `status`/`h3_job_id`/`error` en video_variations + migración idempotente
(filas existentes → 'ready'). video_url pasa a DEFAULT '' (queued aún no tiene vídeo).
- UI: la tarjeta de variación muestra spinner 'En cola'/'Generando…' y estado 'error'; el
player solo con variación 'ready'. La página hace polling cada 45s solo si hay pendientes.
- resolución por plano (16:9 832×480 / 9:16 480×832 vía body.aspect). cost_usd = 0.
NO mergear a master hasta que essia-server dé "live" + H3API_KEY.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sustituye BytePlus Ark/Seedance por el contrato async de essia-server (h3api.essia.coop):
POST /v1/jobs (multipart, mode=ref2va) -> poll GET /v1/jobs/{id} -> download /video (X-API-Key).
Firma de generateVideo/downloadVideo sin cambios (el route no se toca). Env: H3API_BASE_URL, H3API_KEY.
Coste 0 (self-hosted). Sin key no rompe el arranque (lazy).
Limitación anotada: jobs pedidos fuera de la ventana nocturna pueden tardar horas; el polling
síncrono solo es viable en ventana. Cola SQLite + worker pendiente de decidir UX. NO mergear a
master hasta que essia-server confirme "live" + provea H3API_KEY.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Nuevo paquete en mcp-server/ (TypeScript SDK, stdio) que envuelve la API HTTP de Story Studio
y expone 36 tools con prefijo story_ para conducir todo el pipeline: proyectos, idea motriz,
personajes (+assets de imagen), capítulos, guión, pre-escaleta, escaleta, prompts, fondos,
imágenes, vídeos y render. Base URL configurable via STORY_STUDIO_URL (default localhost:3000).
Excluido del build de Next (.dockerignore) — es una herramienta aparte, no se despliega con la app.
Verificado end-to-end contra la app desplegada (list_projects, get_idea_motriz).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- guión conductor: al crear capítulo con virtud sugerida se generaba con GPT-4o pero se descartaba;
ahora se persiste con saveGuionConductor (antes se pagaba y se perdía).
- escaleta GET: la condición de migración nunca se apagaba (planos sin personajes → []), reescribiendo
toda la BD en cada carga; ahora migra solo si hay personajesEnPlano legacy y devuelve lo migrado.
- ficheros huérfanos: al borrar un personaje se elimina su carpeta de imágenes; savePromptsPlanos y
saveFondos borran las imágenes de IDs que desaparecen (los reutilizados no se tocan).
- race en "generar todos": imágenes de plano y variaciones de personaje se persisten por fila
(updatePromptPlano / nuevo updateCharacterAsset) en vez de reescribir todo el set por iteración.
- path traversal: path.basename en los segmentos de URL que forman rutas de fichero (image-service +
serving routes de vídeo/fondo).
- hardcodes de localhost (Remotion chapter-data + CORS) ahora configurables por env con default local.
- IDs de personaje: backfill/dedup de id en generatePersonajes/improvePersonajes (evita 500 y sobrescritura).
- render: cola en memoria con TTL/purga (evita fuga y jobs zombie tras reinicio).
- selectVideoVariation valida pertenencia al plano/capítulo; createProject rechaza slug vacío;
las migraciones loguean el error en vez de tragarlo.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- build script usa --webpack (Next 16 default es Turbopack, incompatible con la config webpack de @remotion)
- tsconfig excluye remotion/ (subproyecto autocontenido con su propio tsconfig; rompía el type-check con un import faltante)
- Dockerfile de producción (build + next start) y .dockerignore que deja fuera projects/ y data/ (llegan por volúmenes)
- CLAUDE.md actualizado al estado real (SQLite, webpack, Ark, Remotion integrado)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>