Toon Studio
Un pipeline Python de un solo archivo (studio.py, solo stdlib + SDK elevenlabs) que produce un cortometraje animado en MP4 a partir de un guion JSON. Funciona en Windows, macOS y Linux. Sin GPU, sin cuentas adicionales más allá de las claves API que el usuario proporcione.
Configuración (hacer una vez por máquina)
- Python 3.10+.
pip install elevenlabs imageio-ffmpeg(el binario de ffmpeg se incluye con imageio-ffmpeg; se puede sobrescribir con la variable de entornoFFMPEGsi se desea).- Copiar
.env.examplea.envy completar:KIE_API_KEY(obligatoria) - de https://kie.ai - cubre generación de imagen, video y música.ELEVENLABS_API_KEY(recomendada) - de https://elevenlabs.io - generación directa de voz. KIE también revende TTS de ElevenLabs, pero ese endpoint tiene cortes recurrentes; la historia predeterminada enruta la voz al backend directo.- Los modelos por defecto eligen el punto óptimo calidad/precio medido en noviembre 2026:
qwen3/pro-text-to-image(imágenes fijas, ~6.4 créditos),minimax-h3/image-to-video(clips, ~48 créditos / 6 s), SunoV4_5(fondo musical). Cualquier ID de modelo de KIE se puede sustituir medianteKIE_IMAGE_MODEL/KIE_VIDEO_MODEL/KIE_MUSIC_MODEL.
Flujo de trabajo
- Guion. Escribir un
story.json(verexamples/moodcast-eva/story.jsony el docstring del encabezado enstudio.py): título, estilo, personajes (nombre, diseño, descripción de voz,photoopcional para convertir a caricatura una persona real,voice_idopcional de ElevenLabs), escenas (descripción, movimiento, duración 4-15 s, líneas de diálogo con el hablante), music_prompt. O redactar uno con un LLM:python studio.py new "un gatito caballero encuentra una llave dorada" --scenes 3 --out story.json - Construir.
python studio.py build story.json --outdir my-filmEtapas: referencia de personajes -> storyboards (imágenes fijas) -> animación -> locución -> música + mezcla. Cada etapa se almacena en caché; al re-ejecutar solo se genera lo que falta. - Director (opcional, recomendado). Añadir
--directorpara pausar después de los storyboards: ver cada imagen, luego aceptar, regenerar con una nota (r plano más abierto), o intercambiar por tu propia imagen (s ruta.png) antes de gastar créditos de animación. En un agente sin stdin interactivo, usar el protocolo de carpeta:build --stop-after stills, revisar/sobrescribirsceneN.pngen el directorio de salida (opython studio.py regen story.json --outdir DIR <escena#> "nota del director"), luego re-ejecutar el mismo build. - Productor (opcional). Añadir
--producerpara un bucle de corrección post-ensamblaje:r 2re-renderiza el clip de la escena 2,v 2 1re-vocaliza la línea 1 de la escena 2,m 0.2re-mezcla con un fondo musical más fuerte,aacepta. - Verificar primero (sin créditos).
python studio.py check story.jsonvalida el esquema, informa el ajuste del habla por escena (segundos estimados de habla vs. la ventana de la escena), y cotiza el costo en créditos KIE de las etapas faltantes más el saldo actual; aprobar antes de gastar. - Aprobar el reparto (económico).
python studio.py preview story.jsonrenderiza la primera línea de cada voz distinta enpreview_<hablante>.mp3para que el usuario apruebe las voces antes de gastar créditos de video.
Cada build también escribe <film>.srt junto al MP4 (un archivo sidecar de subtítulos con la ubicación exacta de cada línea en la línea de tiempo de la película) y quema los subtítulos en el video por defecto (blanco con contorno oscuro, tercio inferior; deshabilitar con build --no-captions, o reestilizar mediante CAPTION_STYLE en studio.py).
Hechos sobre modelos (no reinventar)
- API de tareas KIE:
POST {KIE_BASE_URL}/api/v1/jobs/createTaskcon{"model", "input": {...}}, consultarGET /api/v1/jobs/recordInfo?taskId=...; éxito =successFlag == 1; resultado endata.response.resultUrls[0]. Subir archivos locales ahttps://kieai.redpandaai.co/api/file-base64-upload(JSON base64), NO a api.kie.ai. - Imágenes de referencia: la familia nano-banana lee
image_input(una lista de URLs); el campoimage_urlsse ignora silenciosamente y produce personajes fuera de lo solicitado. - MiniMax H3 (
minimax-h3/image-to-video): la entrada tomafirst_frame_url, duración entera 4-15, resolución768Po2K. Genera de forma nativa SU PROPIA banda sonora, a menudo música completa con voces, que el estudio silencia por defecto (AMB_VOL = 0.0en studio.py). Aumentar solo para renders que hayas verificado que son efectos de sonido limpios. - Hailuo (
hailuo/2-3-image-to-video-pro):image_url, duración cadena ("6"/"10"), resolución768P/1080P. - Seedance (
bytedance/seedance-2-fast):first_frame_url, duración entera,generate_audio: false. - Música Suno vía KIE:
POST /api/v1/generate(se requiere uncallBackUrlde marcador de posición; consultarGET /api/v1/generate/record-info?taskId=...porstatus == SUCCESS, audio enresponse.sunoData[0].audioUrl). - Todos los prompts de movimiento llevan dos reglas fijas (constantes
NO_SPEAK,AUDIO_FXen studio.py): los personajes nunca mueven los labios (el diálogo fuera de pantalla se leería como sincronización labial incorrecta) y sin música/voces en las bandas sonoras de los clips.
Backends
story.json "backends" enruta cada primitiva de forma independiente: {"image": "kie", "video": "kie", "voice": "elevenlabs", "music": "kie"}. Disponibles: kie (imagen/video/música/voz), elevenlabs (solo voz, API directa), higgsfield (backend CLI alternativo). El valor por defecto para todo es higgsfield a menos que TOON_BACKEND o el backend de la historia diga lo contrario.
Transparencia de costos (medido en KIE, noviembre 2026)
| Modelo | Costo | Notas |
|---|---|---|
| qwen3/pro-text-to-image | ~6.4 créditos/img | 1344x768, referencias funcionan, ~60 s |
| z-image | ~0.8 créditos/img | más barato, menor fidelidad |
| nano-banana-pro | ~18 créditos/img | calidad premium |
| minimax-h3/image-to-video | ~48-56 créditos / 6 s | rápido (~90 s), genera su propio audio |
| hailuo/2-3 i2v pro | ~45 créditos / 6 s | ~130 s |
| seedance-2-fast | ~148.8 créditos / 6 s | movimiento premium |
| Suno V4_5 | ~24 créditos/canción | canción completa, la mezcla la recorta |
Voces ElevenLabs: plan de caracteres (p. ej., eleven_v4 ~ unos cientos de caracteres/línea). Consultar GET /api/v1/chat/credit para el saldo de KIE; el build imprime los créditos restantes después de cada ejecución.
Solución de problemas
- Los personajes se ven mal / ignoran la referencia: verificar que la referencia realmente se subió (el registro muestra el ID de la tarea); nano-banana necesita
image_input, noimage_urls. - Aparecen música o voces extra en la película: banda sonora a nivel de clip de H3 o similar; mantener
AMB_VOL = 0.0, o re-renderizar el clip (es no determinista). - Movimiento de labios sobre la narración: la regla NO_SPEAK generalmente se cumple; si un clip falla, eliminar ese
clipN.mp4y re-ejecutar el build (un render nuevo generalmente lo cumple), o re-renderizar con--producery una nota. - Las tareas de voz de KIE fallan con 500: enrutar
voiceaelevenlabs(directo). - Una generación falló a mitad del build: simplemente re-ejecutar el mismo comando; las etapas terminadas se reutilizan, solo se regenera el activo faltante.