Cortometrajes animados tipo caricatura en 3D (three.js + Remotion)
Lo que crea: un cortometraje de 1080x1920, 30 fps, de 45-65 s. Una historia real original contada al estilo de referencia: un gancho absurdo en pasado, escépticos riéndose, "Verás," y un desenlace en una línea. Cartones planos de caricatura se alzan en un mundo 3D pintado con contornos de tinta, luz cálida motivada contra sombra fría, desenfoque de lente y una cámara que nunca corta. Un narrador rápido (~3.7 palabras/s), subtítulos de una palabra, una partitura original y FX de sonido sintetizados, masterizados a -14 LUFS.
Ejemplo trabajado: Los Falsos Compradores (1937, Sylvan Goldman paga a actores para que empujen sus nuevos carritos de compras), que vive en project/src/videos/fake-shoppers/ y project/stories/fake-shoppers/.
Reglas básicas (siempre)
- La historia, personajes, voz y música son propios. Usa la referencia para el estilo y la fórmula, nunca sus guiones, personajes o tomas. Nunca digas el nombre del canal en un video, título o descripción. Los videos de referencia son material de estudio privado: nunca los subas ni los compartas.
- Los hechos se investigan y se citan al inicio del SCRIPT.md de la historia. Las bromas son hipérboles o hechos reales, nunca historias inventadas presentadas como hechos.
- Solo herramientas gratuitas y locales. Usa edge-tts o la propia voz del usuario; sin generadores de pago. Pregunta antes de usar créditos en algún conector.
- Sin pausas en la voz (corta los espacios a 0.07 s, o 0.2 s al final de las oraciones). Los subtítulos están activados (estilo de referencia). El video termina ≤0.5 s después de la última palabra, sin outro ni CTA.
- Revisa
references/TOPICS_DONE.mdantes de elegir un tema. - Dos compuertas de aprobación, luego "solo hazlo" (conservado de la habilidad original):
- Guion: muestra el guion (con sus fuentes) y espera el OK del usuario antes de la voz y el plan de tomas. Después, trabaja sin preguntar hasta la compuerta 2.
- Tablero de revisión: antes del render completo, el usuario ve un borrador a mitad de tamaño en el tablero de revisión, coloca notas en momentos o escenas, y presiona "Se ve bien" (paso 8). Las rondas se repiten hasta entonces; no hay render completo antes.
- El gusto del usuario y las comprobaciones aprendidas (de tableros de revisión pasados). Lee ambos archivos PREFERENCES antes de escribir el guion (paso 2), el plan de tomas (paso 4), los sets (paso 5) y el reparto (paso 6). Revisa ambos archivos CHECKS en el paso 8, junto con las Trampas de legibilidad:
- compartidas por cada habilidad de video:
~/video-editor/review-board/PREFERENCES.md,~/video-editor/review-board/CHECKS.md; - solo este estilo:
references/PREFERENCES.md,references/CHECKS.md.
- compartidas por cada habilidad de video:
- Retomar una historia existente: ejecuta
node ~/video-editor/review-board/cli.mjs show stories/<name>/reviewprimero. Las notas que el usuario envió mientras no había sesión activa se manejan antes que cualquier otra cosa (paso 8.5). - Un render completo. Inícialo en segundo plano, dile al usuario el ETA (~4 fps a 1080, ~10 min para 60 s a 2K), y no lo consultes: el trabajo informa cuando termina. Las vistas previas a
--scale 0.5son gratuitas para repetir.
Este Mac (configurado y probado 2026-11-07)
- Proyecto de trabajo:
~/video-editor/toon3d-shorts/, creado porsetup.sh. Contienesrc/engine(genérico),src/videos/<name>/(una carpeta por video),stories/<name>/(guion, voz, cues, partitura),audio/(kit de síntesis + mezclador),tools/measure.py,scripts/ypublic/. Una copia fresca vive enproject/de esta habilidad. Recrea en cualquier lugar conbash ~/.claude/skills/toon3d-story-shorts/setup.sh <dir>, que ejecuta npm install (versiones fijas) ypip install --user scipy. - Node 24 + Remotion 4.0.539: GPU a través de ANGLE/Metal. Los fotogramas tardan ~1.3 s cada uno después de un paquete de ~20 s; una vista previa completa de 60 s se renderiza en ~45 s a
--scale 0.5. - Python 3.9: numpy, PIL, scipy. ffmpeg-full. whisper-cli con
~/video-editor/models/ggml-large-v3-turbo-q5_0.bin. edge-tts (python3 -m edge_tts). - Estudio de referencia (tuyo para construir, no incluido):
~/video-editor/reference-study/, creado a partir de los cortos de referencia que estudias (descárgalos tú mismo en~/Downloads/reference-shorts/; son material de estudio, nunca los compartas). El estudio del autor midió 19 cortos; los números enreferences/provienen de ahí:STYLE_BIBLE.mdySCRIPTS_ANNOTATED.mdmeasure/(estadísticas por fotograma, transcripciones, hojas de contacto de 2 s / 60 fotogramas, fotogramas a 1 fps, summary.json), que es la línea base paratools/measure.py ours ... --refsframes/ysheets/(vistas a 1 fps / 2 s usadas para comparaciones lado a lado)
- Establece
TMPDIR/REMOTION_TMPen~/video-editor/remotion-tmp(stills.mjs lo hace). Los paquetes de Remotion se acumulan allí. Elimina las carpetas antiguasremotion-webpack-bundle-*solo cuando el usuario esté de acuerdo.
Flujo de trabajo
-
Ideas → tema → hechos. Cuando el usuario no tiene tema, o pide ideas, ejecuta una ronda de ideas (
references/VIRAL_IDEAS.mdtiene los datos, fuentes, rúbrica y reglas de hechos):-
Lo que triunfa ahora (algunas llamadas de investigación en YouTube; pregunta primero si el conector cobra créditos):
- Los cortos más populares del canal de referencia:
youtube_channel_shortscon channel_id<REFERENCE_CHANNEL_ID>(el canal cuyos cortos estudias) y sort_bypopular. Agrega cualquier título nuevo aTOPICS_DONE.md. - Éxitos de nicho:
faceless_outliers_videoscon unaquerysemántica por tipo ganador (ej. "cortometraje animado que revela la razón oculta detrás de un invento, truco o ley histórica extraña, con un final sorpresa"), videoTypeshorts, idiomas["english"], minOutlierScore 3. Ignora los aciertos fuera del nicho (juegos, dispositivos). Anota los patrones de título y agrega las historias tomadas aTOPICS_DONE.md.
- Los cortos más populares del canal de referencia:
-
Candidatos: recopila ~30 historias reales de la lista de fuentes, con WebSearch/WebFetch. Asigna cada una a un tipo ganador: razón oculta detrás de un objeto o práctica antiguos, sistema extranjero o laguna, psicología cerebral, truco o estafa de dinero, fábula o paradoja.
-
Puntúa cada una con la rúbrica de 10 pruebas (de 20). Para las 10 mejores, verifica la novedad con
youtube_search(tiposhorts): descarta una historia ya hecha con más de 1M de vistas en los últimos 12 meses, o encuentra un ángulo fresco. -
Presenta 5-8 ideas con: un título de trabajo en un patrón ganador, el gancho de una línea, el objeto, el mecanismo + analogía, el desglose de puntuación, por qué podría volverse viral (los números de referencia de su tipo) y 2-3 fuentes. Guárdalas todas en
references/IDEAS_BANK.md. El usuario elige una. -
Investiga la elegida:
- ≥2 fuentes sólidas independientes para cada número, fecha, nombre y afirmación;
- leyenda contada como leyenda; burlas dramatizadas marcadas como tales;
- un bloque de hechos (afirmación → enlaces → confianza) al inicio de
stories/<name>/SCRIPT.md.
Para un tema grande, la habilidad de investigación profunda puede hacer este paso.
Un buen tema es una historia real sorprendente con un solo objeto central y un mecanismo oculto que el espectador pueda imaginar, más una analogía cotidiana que lo explique (cuenco de sopa, teléfono deslizándose de una mesa, botones de ascensor).
-
-
Guion (160-240 palabras, 45-65 s). La fórmula medida del canal (
references/STYLE_BIBLE.md§2,SCRIPTS_ANNOTATED.md):- Gancho (hecho en ~5 s, 9-20 palabras): una acción absurda declarada como un hecho, en tiempo pasado ("Pagó a extraños para que fingieran comprar en su propio supermercado."). Alternativas: una afirmación paradójica ("X es ilegal, sin embargo...") o una promesa condicional ("Si alguna vez..."). Nunca una pregunta.
- Escenario: 1-2 líneas en tiempo presente, con números concretos y el año.
- Escépticos: alguien se ríe o se burla, con una cita de burla en personaje. Usa 1-2 burlas por video.
- Pregunta del espectador: "Espera, ¿...?" / "¿Pero cómo?" (una por video aproximadamente).
- Escalada: saltos en el tiempo y repetición ("Semana tras semana", "Para julio..."), más una broma de hipérbole cada 10-15 s ("tan X que Y", una comparación desinflante).
- Giro: "Entonces, una noche/mañana...".
- Revelación: "Verás," en ~65-87 % de la duración, dando el mecanismo real en 1-3 oraciones simples, idealmente a través de la analogía cotidiana. ("Verás," justo después del gancho también funciona como un pivote de contexto).
- Desenlace: una línea declarativa corta que lo reformula todo (los escépticos demostrados equivocados). Corta en ella. Bonus: escribe la última línea para que fluya de vuelta a la primera, para un bucle sin costuras.
- Estilo: gancho en pasado, luego tiempo presente; palabras habladas con contracciones; ~14 palabras por oración; los conectores son "así que / pero / entonces", nunca "y luego". La segunda persona ("Imagina que...") es un modo válido.
- Nunca narres lo que el espectador ya puede ver (conservado de la habilidad original). La voz agrega lo que la imagen no puede: la causa, el número, la broma, lo que está en juego. La imagen muestra la acción.
- Título: una brecha de curiosidad alrededor del objeto, 4-8 palabras, en un patrón ganador ("El [objeto] Que [resultado absurdo]", "Por Qué [grupo] [hizo algo extraño]", "Cómo un [cosa pequeña] [hizo cosa grande]", "Lo Que [objeto] Realmente Significó", "El [persona] Que [paradoja]"). Ofrece 3 opciones con el guion.
- Prueba del gancho: lee la primera oración en voz alta. Debe encajar en menos de ~3 s y sonar incorrecta o imposible. Si necesita contexto, reescríbela.
- Entrega para la compuerta 1: el guion, los 3 títulos y el bloque de hechos con fuentes.
-
Voz en
stories/<name>/voice/:- Genera:
python3 -m edge_tts --voice en-US-AndrewNeural --rate=+14% --text "$(cat ../script.txt)" --write-media raw.mp3, o usa la grabación del usuario. - Ajusta:
python3 scripts/tighten_voice.py raw.mp3 voice.wav --sentence-gap 0.12corta los espacios a 0.07 s, o 0.12 s al final de las oraciones (la referencia tiene ~1 pausa mayor a 0.25 s por video), y genera salida mono de 48 kHz. - Tiempos de palabras: whisper-cli
-l en -ml 1 -sow -ojen una copia de 16 kHz, luego convierte awords.json([{w, a, b}]en segundos). Usa la ortografía del guion, no la de whisper. También cópialo awords_authored.json: la línea de tiempo contra la que se escribe el plan de tomas (story.ts construyeRETIMEa partir del par; archivos idénticos = sin cambios). - La grabación del propio usuario: compara sus palabras con el guion y mide su ritmo (palabras/s, pausas mayores a 0.25 s). Ajustar apenas ayuda a una lectura que ya es ajustada; si es más lenta que los objetivos a continuación, crea una versión con
--tempo 1.1que preserve el tono y deja que el usuario escuche ambas antes de elegir. - Reemplazar la voz después del plan de tomas (mismas palabras, nueva grabación; hecho para Los Falsos Compradores 2026-11-08): no reprogrames nada a mano.
- Mantén los tiempos antiguos como
words_authored.jsony pon los nuevos enwords.json(ortografía del guion, mismo número de palabras). Palabras diferentes significan un nuevo plan de tomas. RETIME = makeRetime(authored, spoken, FPS)(engine/retime.ts) asigna cada fotograma de salida a la línea de tiempo escrita, siguiendo la nueva voz palabra por palabra con suavizado de ±2 palabras (error de inicio medio ~1 f). index.tsx usatotal: RETIME.total, retime: RETIME; cast.ts sigue importandowords_authored.jsonpara la sincronización de labios.- Revisa algunos fotogramas clave en imágenes fijas, luego publica el nuevo borrador en el tablero de revisión con cada escena listada bajo
--changed. - El sonido se mueve con él, sin nada reubicado a mano:
node scripts/retime_cues.mjs <name>mantienecues_authored.jsonuna vez y escribecues.jsonen tiempo de salida (eventos, argsdur, fondos, whooshes) mástimemap.json.python3 score.py music.wav <RETIME.total> timemap.json: los acentos siguen la imagen, la cuadrícula de ritmo sigue la sección por sección. Sin un mapa, la partitura no cambia (verificado muestra por muestra).python3 audio/mix.py stories/<name>/cues.json public/<name>/mix.wav, luego transcribe el mix para confirmar que cada palabra se escucha.
- Mantén los tiempos antiguos como
- Objetivos: 3.6-3.9 palabras/s, gancho termina en ≤6 s. TOTAL = ceil(último final de palabra × 30) + 6 fotogramas.
- Ajusta antes del plan de tomas, nunca después. Cada fotograma de toma se basa en el
words.jsonajustado, así que reajustar después significa reprogramar todo el video. (El ejemplo se saltó esto y mantuvo 10 pausas mayores a 0.25 s, contra la ~1 de la referencia.)
- Genera:
-
Plan de tomas en
src/videos/<name>/story.ts(copia el ejemplo):SHOTS:{id, a, b, light, set}en fotogramas. Un nuevo visual cada ~2.2 s (aproximadamente cada 8 palabras). La acción cae en la palabra clave, 0-3 f antes de su inicio.TRANSITIONS: cómo entra una toma:dissolve(4-8 f) en cambios de lugar o tiempoiris(12-16 f,cx/cy) a través de portillas, mirillas, lentes o relojesdust(20-26 f) cuando un soplo o nube llena el encuadreflash(4 f) solo después del gancho Las tomas en el mismo set sin transición se unen automáticamente mediante un deslizamiento de cámara encadenado centrado en el límite (makeCamAt;chain= 18 f, o un registro por toma entrante dimensionado según el viaje), por lo que el cambio de escenografía aterriza a medio movimiento. Nunca corte duro. Un límite encadenado que viajaría > ~1100 px o giraría > 90° obtiene un dissolve en su lugar.
CAMS: claves por toma{f, dur?, dissolve?, s: f => dolly(pos, look, pushK(f, f0, rate, punch?), {fov, roll})}. Reglas de cámara (references/studies/camera.md, 12 cortometrajes a 30 fps):- Presupuesto de fotogramas: 15-20 % quieto, ~45 % arrastre, ~33 % deslizamiento (3-30 px/f a 540 de ancho), ≤3 % rápido.
- Un nuevo encuadre cada ~1.4 s. La mayoría son pequeños reencuadres: envuelve las claves como
withReframes(CAMS, ENDS)y cada plano largo obtiene un paneo lateral de 14 f de ±5 % de la distancia al sujeto cada 42 f, manteniendo el empuje de esa clave. Marca los planos deliberadamente quietoshold: true. Aproximadamente 4 movimientos rápidos por minuto: pico 35-55 px/f (límite 70), 20-34 f. - Autor ~7 movimientos por 10 s, la mayoría pequeños, movimientos lentos (pico ~10 px/f, 80-150 px de viaje). Usa
withNudges(CAMS, [[shot, baseKeyF, at, dur, ±0.05-0.07], ...])para pequeños reencuadres laterales dentro de planos largos (mantienen el empuje de esa clave), luegowithReframesllena lo que queda. La cámara del ejemplo después de esta re-clave mide dentro de la referencia en cada clase (quieto 19.5 / arrastre 49.9 / deslizamiento 27.1 / rápido 3.5 %, 7.4 movimientos por 10 s; studies/camera.md). - Verifica la dirección de cada empujón en una imagen fija. Muévete hacia el...
[Nota: El contenido se truncó debido a la longitud máxima del prompt. La traducción continuaría para cubrir el resto del SKILL.md, incluyendo los pasos 5-8 y apéndices como la configuración del proyecto, el tablero de revisión, etc., siguiendo las mismas reglas de formato y sin traducir código, rutas de archivo ni comandos.]