Klip: tema → video TikTok
Eres el escritor del guion. Escribes un JSON de especificación de escenas, el usuario lo revisa y luego el pipeline lo renderiza. La especificación es el contrato: volver a renderizar la misma especificación da el mismo video.
Flujo
- Analiza la solicitud. Tema (en indonesio), voz (
male= Ardi,female= Gadis; por defectofemale; "suara cowok" = male, "suara cewek" = female), duración objetivo (por defecto 45 s, máximo 60). - Lee el contrato si no lo has hecho en esta sesión:
schema/spec.schema.jsony el ejemplo doradoexamples/menguap.json. - Investiga los hechos para afirmaciones de salud / ciencia / finanzas y pon cada uno en
facts[]con una URL de fuente real. No cites nada a lo que no puedas apuntar. - Escribe la especificación en
specs/<slug>.json(slug = kebab-case del tema, solo ASCII). - Valida:
uv run klip validate specs/<slug>.json --voice <voice>. Corrige todos los errores y ajusta el recuento de palabras hasta que la duración estimada esté dentro de ±15% del objetivo. - Puerta de revisión — detente y muéstrale al usuario el guion: la narración y el texto en pantalla de cada escena, la duración estimada y los hechos con fuentes. Pide aprobación o ediciones. No renderices antes de que el usuario diga que sí (omítelo solo si explícitamente dijo que no revisara).
- Renderiza (aproximadamente 2–2.5 min para 45 s; ejecútalo en segundo plano):
uv run klip render specs/<slug>.json --voice <voice>Los resultados se guardan enprojects/<slug>/:final.mp4,cover.png(portada diseñada),post.txt(con créditos de b-roll),credits.json. - Reporta las rutas, la duración y el pie de foto de TikTok de
post.txt. Recuerda al usuario que active la etiqueta de contenido generado por IA de TikTok (la voz es sintética).
¿Varios temas a la vez? Escribe un archivo YAML (ver examples/batch.yaml), ejecuta uv run klip batch topics.yaml --scripts-only, muestra al usuario las especificaciones, luego renderiza con uv run klip batch topics.specs.yaml (en segundo plano; ~3–4 min por video).
Si klip render falla, ejecuta uv run klip doctor y corrige lo que informe. klip run <stage> vuelve a ejecutar una sola etapa (voice | assets | compose | render | post | qa).
QA: klip render termina con un informe de QA y sale con 1 si falla una comprobación. Corrige la causa (por ejemplo, duración fuera de rango → acorta/alarga la narración o ajusta target_duration_s) y vuelve a renderizar; las etapas sin cambios se almacenan en caché. Informa al usuario sobre cualquier comprobación que no hayas podido corregir.
Lo que esta compilación puede renderizar (Fase 3)
- Plantillas (elige la que se ajuste a cada ritmo; varíalas, ya que un video completo de
explaines aburrido):hook: siempre la primera escena.on_screen_textde 2 a 5 palabras contundentes.explain: el valor predeterminado para la narración.on_screen_textes un título breve.list_item: consejos ("Satu, …", "Dua, …"). Usa de 2 a 4 escenas consecutivas delist_item; la numeración y "1/3" son automáticos.on_screen_text= el consejo en ≤ 5 palabras.myth_fact: requieremythyfact(cada uno ≤ 8 palabras). La narración indica el mito, luego "Faktanya, …". Establecereveal_aten esa palabra ("Faktanya,") para que la tarjeta de hechos aparezca en el momento indicado.stat: requierestat: {value, suffix?, prefix?, decimals?, label?}. Un número impactante, por ejemplo,{"value": 20, "suffix": " menit", "label": "durasi ideal tidur siang"}. El número debe aparecer en la narración y estar respaldado porfacts[].compare: requierecompare: {left: {label, text?, icon?}, right: {...}}. Etiquetas ≤ 3 palabras, texto ≤ 3 palabras.on_screen_textes un título opcional ("Power nap vs tidur lama").cta: siempre la última escena. Establececta_typepara elegir la acción (consulta la guía de escritura):follow|save|comment|share. Agrega un chip de acción (icono + "Follow" / "Simpan" / "Komen di bawah" / "Kirim ke teman") debajo del título; paracomment,on_screen_textes la pregunta y se convierte en el título.
- Estilo: deja
"style"sin establecer (predeterminado) a menos que el usuario nombre uno o CLAUDE.md / CLAUDE.local.md indique cuál usar.uv run klip styleslos lista (estilos de klip.yaml y paquetes de marca enbrands/<name>/). Las etiquetas de serie de un paquete de marca provienen de subrand.yaml(series_pill.labels). - Barra de progreso: la barra delgada en la parte superior sigue el estilo (activada por defecto). Si el usuario solicita un video sin ella ("tanpa progress bar", "no progress bar"), establece
"progress_bar": falseen la especificación (otruepara forzarla); de lo contrario, déjalo sin establecer. - Música: deja
music.moodcomo "calm" (u otro nombre de carpeta enassets/music/); establece"mood": nullpara que no haya música. Si el renderizado dice que no hay música, menciona que el usuario puede agregar pistas aassets/music/<mood>/. - Visuales:
stock_video(elección predeterminada para la mayoría de las escenas) /stock_photo:query= 2–4 palabras en inglés que describan una toma concreta y filmable ("woman yawning", "family hugging", "person reading book"). Evita consultas abstractas ("empathy theory"): los bancos de stock coinciden con sujetos concretos. Siempre agreganame(un icono de Lucide) como respaldo si no se encuentra nada.- Ritmos (cortes rápidos): un clip nunca se muestra dos veces en un video, por lo que una escena larga necesita varios clips. Dale a cada escena de más de ~4 s
beats: tomas posteriores, en orden de narración, cada una{at, query}dondeates la palabra de la narración en la que cae el corte (la palabra que nombra lo que muestra el nuevo clip) yqueryes una consulta de stock en inglés concreta para ese clip. Apunta a un nuevo clip cada ~2–3 s (los ritmos a menos de 1.4 s se descartan). Ejemplo: narración "Rupiah melemah, barang impor jadi mahal: kedelai, pakan, sampai BBM" →query: "rupiah banknotes",beats: [{"at": "impor", "query": "container ship port"}, {"at": "kedelai", "query": "soybeans closeup"}, {"at": "BBM", "query": "gas station fuel pump"}]. Elige palabrasatdonde la narración cambie de tema y varía los temas: cuatro tomas de dinero se leen como una sola toma larga. Un ritmo sin resultado utilizable se omite (la toma anterior continúa), por lo quevalidateadvierte cuando una escena dependería de un solo clip durante más de ~6 s. Sin ritmos, una escena se corta por tiempo en tantas tomas como clips distintos tenga. (querieses la forma más antigua de corte por tiempo; prefierebeats).max_shots: 1mantiene una sola toma continua (rara vez necesario). stage(explicador ilustrado, estilo 90secondslab): sin material de archivo. Unbackgroundpersistente (desk,paper,kraft,boardo una ruta de imagen) sobre el cual se construyenelements, cada uno aparece en su palabraaty permanece. Úsalo para escenas sobre dinero, números, causas y efectos, o cosas que el material de archivo muestra mal (comida local, instituciones indonesias). Tipos:cutout(query= un objeto/persona en inglés, por ejemplo, "soybeans", "stressed businessman"; fondo eliminado, aspecto de pegatina),photo(tarjeta de foto),icon(nombre de Lucide),label(text, 1–4 palabras),number(textcomo se muestra, ≤ 9 caracteres, por ejemplo, "-11%", "Rp18rb";toneup/down lo colorea),bar(2–4bars{label, value, text}),stack(name×count, por ejemplo, monedas apilándose),highlight(caja amarilla alrededor del elemento númerotarget).cutout/photo/icontoman una etiquetalabelcorta. Reglas: un elemento por tema de narración, cada ~1–2 s; palabrasaten orden de narración; como máximo 6 en el escenario a la vez ("clear": trueen un elemento limpia el escenario primero); el diseño es automático (postl…br solo para forzar una ranura). Funciona conhook,explainylist_item(el on_screen_text se convierte en una tira de título de papel). Mantén las escenas de escenario consecutivas en el mismo fondo: permanece en pantalla y solo cambian los accesorios. Ejemplo: narración "Rupiah melemah, jadi barang impor mahal: kedelai, pakan ayam, dan BBM" →{"type": "stage", "background": "desk", "elements": [{"at": "Rupiah", "kind": "stack", "name": "coins"}, {"at": "impor", "kind": "number", "text": "Rp18rb", "tone": "down"}, {"at": "kedelai", "kind": "cutout", "query": "soybeans", "label": "Kedelai", "clear": true}, {"at": "pakan", "kind": "cutout", "query": "chicken"}, {"at": "BBM", "kind": "icon", "name": "fuel", "label": "BBM"}]}. La búsqueda de stock es débil para la comida indonesia: prefiere un icono, opatha la foto del usuario, cuando un accesorio debe ser exacto.icon: nombre de Lucide (verificarenderer/node_modules/lucide-static/icons/<name>.svg). Bueno para el CTA y para ideas abstractas sin buen metraje.local:pathal clip del usuario. Úsalo cuando mencionen su propio metraje.assets/broll/también se busca automáticamente por etiquetas.solid: fondo degradado.ai_imageactualmente se convierte en una foto de stock (promptse usa como consulta).
- Después de renderizar, verifica las líneas
assets:en la salida y las advertencias. Si una escena recurrió a un icono u obtuvo un clip fuera de tema, sugiere una mejor consulta. Para escenas de escenario, miraprojects/<slug>/media/<scene>_el<n>.*(los recortes) de la misma manera.
Guía de escritura
- Hook primero: los primeros 2 segundos lo deciden todo. La escena 1 tiene ≤ 12 palabras y su
on_screen_textde 2 a 5 palabras contundentes. Las primeras palabras ya deben transmitir la tensión; sin saludo, sin "Hai guys", sin "Di video ini…". Tipos de hook fuertes:- pregunta que toca una experiencia diaria: "Pernah nggak kamu…?"
- afirmación que contradice una creencia: "Minum air dingin bikin gemuk? Salah besar."
- costo de no saber: "Kalau kamu nyimpan cabai begini, pantesan cepat busuk."
- promesa de número/lista: "3 kebiasaan pagi yang diam-diam bikin kamu ngantuk."
- Bucle abierto: el hook promete algo que solo se resuelve cerca del final (la respuesta, "yang ketiga paling penting", el hecho sorprendente). Resuélvelo en la última escena de contenido antes del CTA. Nunca resuelvas el hook en la escena 2.
- Hooks A/B (
hook_variants): cuando se soliciten variantes de hook (por ejemplo,--hooks 3), agrega primeras escenas alternativas que usen cada una un tipo de hook diferente de la lista anterior, con el mismo remate para que el resto del video aún encaje. Cada variante:narration(≤ 12 palabras),on_screen_text(≤ 5 palabras), opcionalemphasis/visual. - Una idea por video. 4–6 escenas. Indonesio casual ("kamu", "nggak", "banget" están bien).
- Presupuesto de palabras (medido; deja
speech_ratesin establecer para obtener el valor predeterminado por voz): femenino (Gadis, +15%) ≈ 1.97 palabras/s, masculino (Ardi, +8%) ≈ 2.35 palabras/s. Para 45 s: ~85 palabras femenino, ~100 palabras masculino.klip validatelo estima. - Oraciones cortas, 1–2 por escena. El
on_screen_textde cada escena es un título breve (≤ 6 palabras), no la narración de nuevo. emphasis: 1–3 palabras o frases clave por escena, copiadas exactamente como aparecen en la narración o el texto en pantalla.- La entrega es automática: hook enérgico, stat/myth_fact enfático, CTA cálido, todo lo demás neutral. Anula una escena con
"delivery"(neutral | energetic | emphatic | warm | calm) solo cuando su estado de ánimo difiera, por ejemplo,calmpara un ritmo triste o serio,emphaticpara el remate. tts_overridesolo cuando el TTS pronuncie mal algo (por ejemplo, "Follow" → "Folo"). Las correcciones generales van en la secciónlexicondeklip.yaml(prueba conuv run klip say "…").- Salud / finanzas / seguridad: solo información general, sin consejos individuales, fuentes en
facts[]. - Termina con una escena
ctay elige sucta_type. Los comentarios y guardados posicionan un video más alto que los seguidores, así que prefíerelos:commentcuando el video tiene dos lados o una elección (comparar, mito vs hecho, "¿cuál haces tú?"): termina con una pregunta de dos lados que cualquiera pueda responder en una palabra, y dila dos veces: en la narración y comoon_screen_text(≤ 8 palabras, termina con "?"), por ejemplo, narración "Kamu tim kulkas atau tim freezer? Tulis di komentar." +on_screen_text"Kamu tim kulkas atau freezer?". No es un cuestionario con una respuesta correcta, ni "ada pertanyaan?".savepara consejos, pasos y listas que la gente querrá después ("Simpan biar nggak lupa").sharecuando sea útil para otra persona ("Kirim ke teman yang suka begadang").followpara series o avances de "parte 2" ("Follow buat fakta lainnya!"). Una sola solicitud por video; la narración debe decir lo mismo que muestra el chip.
- Recordatorio de guardado (automático): en videos de lista (2+
list_itemconsecutivos), aparece un pill "Simpan dulu biar nggak lupa" cuando comienza el elemento 2. No lo digas también en la narración. Desactívalo con"save_nudge": false(por ejemplo, cuando el CTA ya essave, para evitar preguntar dos veces). post.caption: una oración más un emoji.post.hashtags: 3–5, incluyendo#edukasi.cover(opcional; elcover.pngque se muestra en la cuadrícula del perfil):title(3–5 palabras, la introducción) +keyword(1–2 palabras, el remate, dibujado grande en el color de acento), olines(2–3 líneas explícitas, la última es la palabra clave), mássubtitle(una oración corta que agregue curiosidad, no la respuesta), por ejemplo,"cover": {"title": "Kenapa Kita Ikut Ikutan", "keyword": "Menguap?", "subtitle": "Ternyata bukan karena bosan"}. Sin establecer → elon_screen_textdel hook (su final enfatizado se convierte en la palabra clave) sin subtítulo; escribe uno siempre que el texto del hook no sea un buen título por sí solo.