anime-reel
Entrada: un guion + un MP3 de voz por línea (el usuario adjunta ambos). Salida: un reel 9:16 y una copia 16:9, cada uno con el audio original, más una copia en 720p de menos de 20 MB para WhatsApp.
Reglas estrictas (cada ejecución)
- Dibujar todo en código: canvas HTML, renderizado fotograma a fotograma en Chrome sin cabeza, codificado con ffmpeg. Sin metraje de archivo, sin generadores de imágenes. Usar
engine/como base; extenderlo, no reemplazarlo, para que el aspecto se mantenga igual en cada ejecución. - Temporizar cada palabra con alineación forzada (torchaudio MMS_FA mediante
scripts/align.py). Nunca adivinar tiempos. Si falla la alineación para una línea, detenerse y decirle al usuario por qué; no recurrir a espaciado uniforme. - Mostrar una hoja de contacto de fotogramas antes del renderizado completo y esperar aprobación.
- Preguntar antes de sobrescribir cualquier archivo existente.
encode.shse niega a sobrescribir y sale con código 2; transmitir eso al usuario. - Mantener el audio original intacto en el MP4 final (las líneas de voz solo se colocan en una línea de tiempo, nunca se reprocesan). Sin música de fondo a menos que el usuario lo pida.
Método
- Configuración. Ejecutar
bash scripts/check_setup.sh(ffmpeg, Node, puppeteer, torch/torchaudio, uroman). Corregir cualquier cosa que falte antes de continuar. Ejecutarbash scripts/sfx.sh <proyecto>/sfxpara sintetizar sonidos de golpe/whoosh/impacto/pop con ffmpeg. - Dividir el guion en tomas. Una toma por línea de voz. Para cada una, escribir:
id,speaker,text(exactamente lo que dice el MP3), ruta deaudio,place(rooftop, office, street, bedroom, sky, o agregar una nueva ramadrawPlace),camera(static|push|pull|pan+amount),cast,slots(left/center/right) yfx. Guardar comoshots.json(esquema enscripts/build_timeline.py). Mostrar la lista de tomas y permitir que el usuario la corrija si es ambiguo. - Personajes. Definir cada uno en
characters(name, skin, hair, hairStyle spiky|bob|long|short, eye, outfit, accent,color= color de subtítulo de ese personaje). Deben ser originales, nunca copiados de anime existente. Aspecto anime: ojos grandes con brillo, contornos gruesos y limpios, color plano más exactamente una sombra. Renderizar la hoja del personaje y mantener el JSON como fuente única de verdad para que los personajes nunca cambien entre tomas:node scripts/render_frames.mjs sheet timeline.json landscape out/character_sheet.png - Alinear y sincronizar labios.
python3 scripts/build_timeline.py shots.json timeline.json workejecuta MMS_FA por línea (temporización de palabras) y construye la curva de apertura de boca de cada personaje a partir de la sonoridad de esa línea de voz (mouth.py). Los parpadeos y movimientos ociosos están integrados en el motor. Para líneas que no estén en inglés,align.pyromaniza con uroman mientras mantiene la ortografía original en pantalla. - Trucos de anime en líneas clave (agregar a
fx, tiempos en segundos desde el inicio de la toma):speedlinesen revelaciones y determinación,impact(fotogramas blancos/negros intermitentes, consfx: "impact") en la línea más importante,shakeen golpes,chibi(+who,sfx: "pop") en reacciones cómicas. Usar con moderación: aproximadamente un truco cada 2-3 tomas, para que sigan impactando. - Subtítulos y sonido. Los subtítulos de 2-3 palabras ya los maneja el motor, con la palabra hablada en el color del hablante y el resto en blanco. Los efectos de sonido se sitúan en las mismas pistas que los golpes visuales (mediante
fx[].sfx). Mezclar conpython3 scripts/build_timeline.py shots.json timeline.json work. - Hoja de contacto, luego aprobación. Elegir ~12 tiempos distribuidos a lo largo del episodio, incluyendo cada truco:
node scripts/render_frames.mjs stills timeline.json portrait work/stills 0.5,2.0,...bash scripts/contact_sheet.sh work/stills out/contact_sheet.pngMostrarout/contact_sheet.pngy detenerse. No renderizar el video completo hasta que el usuario lo apruebe. - Renderizar tras la aprobación, para cada orientación (
portrait= 1080x1920,landscape= 1920x1080, 30 fps):node scripts/render_frames.mjs video timeline.json portrait work/reel_silent.mp4bash scripts/encode.sh work/reel_silent.mp4 work/audio.wav out/<nombre>_9x16Repetir para landscape conout/<nombre>_16x9.encode.shmultiplexa audio AAC 256k y escribe la copia_720p.mp4(objetivo ~17 MB, siempre por debajo de 20 MB). Verificar tamaños conls -lhe informarlos.
Configuración de renderizado
- 9:16: 1080x1920, 30 fps, H.264 yuv420p, CRF 16, AAC 256k, faststart. 16:9: 1920x1080, misma configuración.
- Copia para WhatsApp: 720p (720x1280 o 1280x720), bitrate calculado a partir de la duración para mantenerse por debajo de 20 MB.
- Los subtítulos se sitúan aproximadamente al 68% de altura en 9:16 (libres de los 250 px superiores y 420 px inferiores de la UI de la aplicación) y ~86% en 16:9.
Archivos en este skill
engine/engine.js,engine/index.html: motor canvas (personajes, lugares, líneas de velocidad, fotogramas de impacto, temblor, chibi, subtítulos, badge).scripts/:check_setup.sh,sfx.sh,align.py,mouth.py,build_timeline.py,build_audio.py,render_frames.mjs,contact_sheet.sh,encode.sh.