Corto animado: idea → guion → voz → MP4 finalizado
El estilo: personajes caricatura planos 2D tipo bean-head (tarjetas dibujadas en canvas con contornos ciruela) en un mundo 3D colorido con contornos de tinta negra, texturas pintadas, profundidad de campo y cámaras deslizantes. La salida es 1080x1920, 30 fps, exactamente tan larga como la voz. La voz del usuario no se modifica. La música de fondo y los efectos de sonido están sintetizados y se sitúan al 50 % del nivel de voz. Probado en "El soldado que nunca se fue" (19.7 s, 8 tomas).
Reglas
- Las historias, personajes y tomas siempre son originales. Nunca recrees el video de otro creador toma por toma. Ofrece una versión original de la misma idea.
- No uses personas reales, vivas y nombradas como personajes, ni mascotas de marca o logotipos.
- Sin subtítulos a menos que el usuario los solicite. El texto diegético (un mensaje tallado, un cartel) está bien, y debe leerse correctamente (sin reflejo).
- Nunca edites o reajustes el tiempo de la voz. La imagen se sincroniza con ella, y cada reacción visual ocurre 0-3 fotogramas antes de su palabra.
- Niveles de audio: la música de fondo se sitúa al 50 % del nivel de voz (−6 dB, RMS con compuerta). Los efectos de sonido (SFX) se sitúan al 50 % o ligeramente menos, con picos limitados para que ningún golpe sobresalga por encima de la narración. Siempre mezcla con
mix.py, nunca a mano. No uses compresión o ducker que cambie esta proporción; solo una ganancia lineal más un limitador de pico se aplican a toda la mezcla. - Mantén informado al usuario con una lista de tareas. Envía una hoja de contactos de fotogramas fijos antes de la renderización larga.
Etapa 1: Entrada (siempre primero)
Si ya hay un archivo de audio adjunto, salta a la Etapa 4. Si también se proporcionó un guion, úsalo para la sincronización. De lo contrario, haz una AskUserQuestion (o texto plano si esa herramienta no está disponible): "¿Desde dónde empiezas?"
- Voz lista: pídeles que la suban, junto con el texto del guion si lo tienen (el guion hace que la sincronización sea exacta). Ve a la Etapa 4 cuando llegue.
- Tengo un guion, necesito la voz: ajusta el guion según la Etapa 3 si es necesario, devuélvelo con consejos de grabación, pide la subida, luego ve a la Etapa 4.
- Necesito ideas de video y un guion: ve a la Etapa 2. También pregunta la duración objetivo si no lo han dicho. El valor predeterminado es 20-30 s; se permite 45-60 s.
Etapa 2: 10 ideas de video
Da exactamente 10 ideas en una sola respuesta, numeradas, y pide al usuario que responda con un número (o "más"). Cada idea incluye:
- Título (5-8 palabras, que despierte curiosidad, ej. "El soldado que nunca se fue").
- Frase de gancho: la primera oración hablada, una paradoja presentada como hecho ("Un hombre vendió la Torre Eiffel. Dos veces.").
- El giro en una línea (la recompensa irónica que termina el video).
- Por qué se anima bien: los 2-3 grandes momentos visuales (un colapso, una revelación, una persecución).
- Verdad o leyenda: di claramente si es historia documentada, un relato en disputa o folclore.
Qué hace que una idea sea "perfecta" para este formato:
- Una historia sorprendente con una causa y efecto físicos que se puedan mostrar.
- Un personaje común claro, apuestas que escalan y un giro en la última línea.
- Un escenario que se pueda construir con formas 3D simples más tarjetas de caricatura (pueblos, puentes, barcos, castillos, desiertos, laboratorios, palacios).
- Mezcla las 10 entre épocas y temas: antiguo, medieval, 1800s, moderno, ciencia, animales, inventos, desastres, leyes extrañas, accidentes afortunados.
- Para cualquier cosa presentada como verdadera, verifica los datos clave con una búsqueda web antes de ofrecerla. No presentes una leyenda viral como un hecho. Si el usuario la quiere de todos modos, enmárcala como "cuenta la leyenda".
- Nada de personas reales vivas como blanco de una broma, nada gráfico ni político.
Etapa 3: Guion (después de que elijan)
Escribe solo la narración (sin acotaciones en el texto hablado), con un tamaño de aproximadamente 3.7 palabras/s: 20 s ≈ 75 palabras, 30 s ≈ 110, 60 s ≈ 220. Fórmula:
- Gancho (oración 1, sin preámbulo): el hecho absurdo.
- Escenario en 1-2 líneas: cuándo, dónde, quién, un detalle concreto.
- Escalada, 2-4 tiempos, cada vez mayor. Otros dudan o se burlan. Usa una broma de exageración.
- Misterio o giro: "Pero cuando..." / "Verás," introduce el mecanismo real, a menudo con una analogía cotidiana.
- Giro / recompensa: corto, irónico y las últimas palabras del video. Usa inglés hablado sencillo, contracciones, oraciones de unas 8-15 palabras y números escritos como palabras. Nunca describas lo que el espectador ya ve.
Luego responde con:
- El guion en un bloque copiable, con el recuento de palabras y la duración estimada.
- Un plan visual de un párrafo (las tomas que animarás).
- Consejos de grabación: una voz de narrador constante y cálida; ElevenLabs funciona bien (una voz de narrador grave, velocidad alrededor de 1.05-1.1, estabilidad alrededor de 45-55 %). Mp3 o wav está bien. Deja pausas naturales al final de las oraciones. Exporta sin música.
- La petición: "Sube la voz cuando esté lista y haré el video completo." Conserva el texto del guion final. Impulsa la sincronización en la Etapa 4, por lo que no se necesita reconocimiento de voz. Si grabaron una versión modificada, pide el texto final.
Etapa 4: Construir el video (después de que se suba la voz)
Haz todo desde aquí sin parar. Pregunta solo si no se puede resolver la sincronización.
4.0 Obtener el kit
El kit de código se envía dentro de esta carpeta de habilidad en kit/ (motor, herramientas, ejemplo de trabajo, además de three.js r160 empaquetado y la librería toon.ts Pen de github.com/mromidev/claude-animated-shorts, ambos MIT). Localiza la carpeta con find / -name SKILL.md -path "*cartoon-audio-short*" 2>/dev/null y trata su kit/ como solo lectura.
Luego ejecuta bash <skill>/kit/tools/setup.sh ~/shorts/<slug>. Copia el motor y las herramientas en el proyecto, instala three.js empaquetado, elimina los tipos de toon.ts con Node 22 module.stripTypeScriptTypes, y enlaza Playwright. No se necesita red. Si los archivos empaquetados faltan, recurre a npm o un clon de git.
- Requisitos: Node 22.6+, Python 3 con numpy + Pillow, ffmpeg y Playwright con Chromium (
npm i -g playwright && npx playwright install chromiumsi falta). - Si los registros de paquetes están bloqueados, git a través de GitHub generalmente funciona. Nunca deshabilites TLS o evites el proxy.
- Chromium: usa el navegador Playwright preinstalado con
--use-angle=swiftshader --enable-unsafe-swiftshader --ignore-gpu-blocklist. Eso da WebGL por CPU a aproximadamente 3-10 s por fotograma.
4.1 Sincronización
Ejecuta python3 timing.py voice.mp3 script.txt --out work.
- Con whisper o faster-whisper instalado, usa marcas de tiempo de palabras.
- De lo contrario, alinea las frases del guion (divididas por puntuación) con segmentos de voz detectados por silencio, con un DP que empareje sílabas con duración y penalice finales de oraciones dentro de un segmento y largos intervalos dentro de una frase.
- Sin ASR y sin guion, pide el guion. Claude no puede oír audio.
- Verifica
work/phrases.json: las pausas deben caer al final de las oraciones. Total de fotogramas = round(duración × 30).
4.2 Plan de tomas (work/PLAN.md antes del código)
Haz una fila por toma: fotogramas, palabras, escenario, luz, movimiento de cámara, personajes/poses/expresiones, efectos y señal de SFX.
- El fotograma 0 ya es la imagen de gancho.
- Generalmente una toma por frase. Fusiona frases muy pequeñas en la siguiente toma.
- Ilustra cada oración literalmente. Los accesorios llevan los chistes.
- Varía los tamaños de toma: gancho PML → plano general de revelación → plano de dos → inserto de primer plano del objeto clave → primer plano de reacción → movimiento de entorno para la recompensa.
- Usa la luz para los tiempos: día para normal, dorado para declive o drama, azul noche para explicación. Un salto temporal obtiene un destello blanco de 6 fotogramas.
- La línea del giro recibe un golpe (la música se detiene, golpe grave, empuje con balanceo). La recompensa física de la última toma cae en la palabra final.
4.3 Mundo (web/main.js)
Mantén las secciones del motor: materiales toon, contrato de tinta, add/tbox, cielo, luces, tarjetas, objetivos de render/post, applyLight, drawActors, swapForNd, renderFrame. Reemplaza el mundo de ejemplo entre // ---------- world ---------- y // ---------- cards ----------, más las partes de la historia de worldState().
- Construye a partir de primitivas con texturas de lienzo pintado (
paint.js: tablones, vigas, madera podrida, piedra, musgo/hiedra, hierba, tierra, yeso, tejas, mármol, banderas, texto tallado). Escribe nuevos pintores en el mismo estilo plano con costuras oscuras. - Usa
tboxpara densidad de texel constante, un degradado toon de 2 pasos y niebla = color del horizonte. - Fondo: colinas (esferas medio enterradas), montañas (conos + picos de nieve), árboles de ciprés/pino, casas lejanas, carteles pintados de nubes.
- Piezas de escenario (colapsos, caídas, puertas) son grupos pivotados impulsados por progreso 0..1 desde
worldAt(f), con partes suavizadas y escalonadas. - El texto diegético curvo usa UVs planares. Verifica que no esté reflejado.
4.4 Reparto (web/roman.js → web/toon.js)
romanFront(p, outfitKey, opts)dibuja en un lienzo de diseño de 600x1000 con suelas en y=975. La tarjeta mide 2.25 m de alto, por lo que 1 unidad = 0.00225 m.- Agrega conjuntos a
OUTFITS(túnica/capa/armadura/casco/pelo/gorro/barba/delantal/vestido/toga) y nuevos tocados y accesorios en el mismo estilo. - Poses de brazo: colgar, lanza, señalar, arriba, saludar, cadera, vientre, sien (+remolino), levantar, alcanzar (+levantar), mejilla, escudo, cruz, pulgar.
- Expresiones: el conjunto FACE de toon.ts más roncar, terco, entrecerrar. Extiende FACE para más.
- Reconstruye después de ediciones con
cat web/toonbase.js web/roman.js > web/toon.js. Renderiza una hoja de prueba de personajes antes de usar nuevos diseños. - Los carteles giran solo en guiñada, obtienen una mancha de contacto y una sombra con prueba alfa, y nunca son entintados por el pase del mundo.
- Construye claves de tarjeta a partir de valores redondeados con
q()(para que el lienzo se redibuje solo con cambios visibles). - Una parte separada (ej. un casco levantado) es su propia tarjeta, alineada con
headCenter(seed): y = DECK + (partY − hc) × 0.00225.
4.5 Movimiento: suave y vivo (web/motion.js)
- Cámaras:
camFromKeys(keys, f, {kicks}). Usa deslizamientos smootherstep (18-45 f),easeOutpara revelaciones y latigazos, y puntos de pasopath(Catmull-Rom) para movimientos curvos. Cada espera se mueve lentamente y nada está estático durante 4+ fotogramas. Usa 3-5° de balanceo en drama y sacudidas de 7 fotogramas en impactos. - Continuidad: prefiere movimientos continuos (retroceder de un primer plano a un plano general, reenfocar, grúa a través de la cubierta, empujar hacia un objeto). Corte duro solo en saltos de lugar o tiempo, con un destello.
- Los personajes nunca se congelan: aplica
idle(f, seed)a cada tarjeta,blinkAtparpadea, y movimientos de cabeza en palabras acentuadas. - Acciones: anticipación →
backsobreimpulso →springasentamiento. Un pisada es un golpe de 2 fotogramas + nube de polvo + patada. Las risas son un balanceo alternante + movimiento. - Movimiento secundario: ondas de tela de bandera, hojas/polvo/gotas/carteles de efecto Zzz, agua fluyendo. Algo siempre se mueve.
- Caminatas:
walk()da distancia + fase de paso. Pies plantados, movimiento 3-7 %. - Lente: profundidad de campo en primeros planos y planos medios (cInf 8-14 px), enfoque en los ojos. Los planos generales son nítidos. Los reenfoques toman ~14 f.
4.6 Verificación de estilo (antes de la renderización completa)
Renderiza fotogramas fijos en el medio de cada toma más las transiciones y acciones clave: node render.mjs stills/a "5,40,..." luego python3 sheet.py stills/a stills/sheet_a.jpg. Mira la hoja y corrige estas trampas:
- Marco vertical estrecho: mitad del ancho horizontal = d·tan(hfov/2), con hfov = 2·atan(tan(vfov/2)·0.5625). A 4 m y fov 40 eso es ±0.8 m, así que coloca los personajes en profundidad.
- Barandillas o postes a través de las caras (cámara dentro de la barandilla o ~2.5 m arriba). El camino de la cámara a través de casas, techos o arbustos. Accesorios en primer plano a menos de ~2 m. El héroe escondido detrás de un pilar.
- Texto reflejado. Una tarjeta de parte separada desplazada en la dirección incorrecta.
- Grupos de material extruido: 0 = tapas, 1 = lados+arriba.
- Tinta faltante: depura la salida solo de bordes. Radio de tinta ~2.5 px a 1080. El cielo cuenta como profundidad lejana, no una tarjeta. Envía la hoja al usuario con un resumen de una línea por toma, luego comienza la renderización completa.
4.7 Sonido (audio.py → pistas → mix.py)
Reescribe la tabla de señales para la historia; los sintetizadores se quedan. audio.py escribe solo pistas (music.wav, sfx.wav).
- Música: un bucle corto tipo marcha (bombo/caja, bajo pulsado, pad de metales). Se detiene en la línea del giro, luego un drone bajo continúa.
- SFX en eventos (en fotogramas/30): silbidos en movimientos grandes, golpes en pisadas, retumbo + crujido en colapsos, raspado en metal, tintineo en revelaciones, golpe en el giro, chirridos, chasquidos, chapoteo, ronquido, hojas, ambiente de agua.
- Mezcla con
python3 mix.py voice.mp3 music.wav sfx.wav. Establece la música exactamente al 50 % del RMS con compuerta de la voz (−6 dB) y SFX al 50 % con picos limitados a 0.7× el pico de la voz. Imprime los niveles medidos: confirma que la música muestra −6.0 dB frente a la voz y SFX está en ese nivel o por debajo. - Bloquea la sincronización de la imagen antes de hacer el sonido. Cualquier cambio de sincronización significa volver a ejecutar audio.py y mix.py.
4.8 Renderizado + finalización
- Ejecuta
node render.mjs frames "0-<N-1>"con Bashrun_in_background, supervisado por un bucle Monitor que informa el progreso y captura errores o salida del proceso.RESUME=1continúa después de una interrupción. No ejecutes Python pesado al mismo tiempo en máquinas pequeñas. - Ejecuta
bash finish.sh "Título". Aplica una ganancia lineal a aproximadamente −14 LUFS más un limitador de pico de −1 dBFS, codifica H.264 CRF 17 + AAC, ejecuta controles de calidad de congelación/negro y sonoridad, y escribeout/qa_sheet.jpg. Mira la hoja. Los segmentos congelados ≥0.4 s o fotogramas negros necesitan corrección. - Entrega el MP4 con SendUserFile y algunas líneas sobre lo que muestra cada toma. Ofrece subtítulos, ajustes o la siguiente idea de la lista.
Peculiaridades del motor (guardadas en el kit; mantenlas si reconstruyes)
#include <fog_vertex>/<fog_fragment>van en sus propias líneas.- El pase final escribe
linearToOutputTexel(...)(los objetivos de renderizado son HalfFloat lineales). - El pase de normal+profundidad intercambia materiales por malla: mundo → normal/profundidad, tarjetas → máscara con prueba alfa (rgb 0, a = profundidad), manchas/nubes/cielo ocultos, agua → normal plana. La niebla y las sombras están desactivadas durante esto.
- La tinta va solo en el lado cercano de los saltos de profundidad. Las arrugas provienen del producto punto normal. Se omiten los vecinos de tarjeta. La tinta se desvanece a ~140-520 m.
- Profundidad de campo: 48 muestras con una prueba CoC por muestra (sin sangrado de primer plano).
- El sol proviene de az/el por preajuste de luz. La cámara de sombra está centrada en la acción de cada toma.
Arquitectura (referencia para editar el kit)
web/index.htmlcargamain.js(módulo ES) sobre un servidor HTTP local
...
[truncado para traducción]