Communitygithub.com

aliflazuardi/klip

Convierte un tema en indonesio en un video completo para TikTok (MP4 1080x1920 con voz en off y subtítulos sincronizados con las palabras) usando el pipeline Klip de este repositorio. Úsalo cuando el usuario diga /klip, "buat video tentang…", "make a TikTok about…", o pida renderizar una especificación Klip.

¿Qué es klip?

Esta habilidad transforma un tema en indonesio en un video profesional para TikTok listo para publicar, con dimensiones 1080×1920, voz en off (masculina o femenina, con locutores indonesios) y subtítulos sincronizados palabra por palabra. El proceso comienza cuando el usuario proporciona un tema; la habilidad investiga hechos reales (salud, ciencia, finanzas) con fuentes verificables, y genera una especificación JSON de escenas ("scene spec") que el usuario revisa antes de la renderización. Soporta múltiples plantillas visuales (hook, explain, list_item, myth_fact, stat, compare, cta) y estilos de vídeo (stock footage, escenografías ilustradas con elementos animados, iconos Lucide, clips locales). El pipeline completo incluye validación automática de duración y palabras, renderización en segundo plano (aproximadamente 2–2.5 minutos para 45 segundos de video), y genera un archivo MP4, una portada PNG, un texto de publicación con créditos y metadatos JSON. También permite procesar varios temas en lote mediante un archivo YAML. Está diseñado para entornos de desarrollo con Python (uv), Node.js y configuración YAML, y se integra perfectamente con Claude Code, Cursor o Codex para flujos de trabajo de creación de contenido.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/aliflazuardi/klip/tree/HEAD/.claude/skills/klip

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

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

  1. Analiza la solicitud. Tema (en indonesio), voz (male = Ardi, female = Gadis; por defecto female; "suara cowok" = male, "suara cewek" = female), duración objetivo (por defecto 45 s, máximo 60).
  2. Lee el contrato si no lo has hecho en esta sesión: schema/spec.schema.json y el ejemplo dorado examples/menguap.json.
  3. 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.
  4. Escribe la especificación en specs/<slug>.json (slug = kebab-case del tema, solo ASCII).
  5. 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.
  6. 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).
  7. 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 en projects/<slug>/: final.mp4, cover.png (portada diseñada), post.txt (con créditos de b-roll), credits.json.
  8. 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 explain es aburrido):
    • hook: siempre la primera escena. on_screen_text de 2 a 5 palabras contundentes.
    • explain: el valor predeterminado para la narración. on_screen_text es un título breve.
    • list_item: consejos ("Satu, …", "Dua, …"). Usa de 2 a 4 escenas consecutivas de list_item; la numeración y "1/3" son automáticos. on_screen_text = el consejo en ≤ 5 palabras.
    • myth_fact: requiere myth y fact (cada uno ≤ 8 palabras). La narración indica el mito, luego "Faktanya, …". Establece reveal_at en esa palabra ("Faktanya,") para que la tarjeta de hechos aparezca en el momento indicado.
    • stat: requiere stat: {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 por facts[].
    • compare: requiere compare: {left: {label, text?, icon?}, right: {...}}. Etiquetas ≤ 3 palabras, texto ≤ 3 palabras. on_screen_text es un título opcional ("Power nap vs tidur lama").
    • cta: siempre la última escena. Establece cta_type para 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; para comment, on_screen_text es 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 styles los lista (estilos de klip.yaml y paquetes de marca en brands/<name>/). Las etiquetas de serie de un paquete de marca provienen de su brand.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": false en la especificación (o true para forzarla); de lo contrario, déjalo sin establecer.
  • Música: deja music.mood como "calm" (u otro nombre de carpeta en assets/music/); establece "mood": null para que no haya música. Si el renderizado dice que no hay música, menciona que el usuario puede agregar pistas a assets/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 agrega name (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} donde at es la palabra de la narración en la que cae el corte (la palabra que nombra lo que muestra el nuevo clip) y query es 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 palabras at donde 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 que validate advierte 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. (queries es la forma más antigua de corte por tiempo; prefiere beats). max_shots: 1 mantiene una sola toma continua (rara vez necesario).
    • stage (explicador ilustrado, estilo 90secondslab): sin material de archivo. Un background persistente (desk, paper, kraft, board o una ruta de imagen) sobre el cual se construyen elements, cada uno aparece en su palabra at y 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 (text como se muestra, ≤ 9 caracteres, por ejemplo, "-11%", "Rp18rb"; tone up/down lo colorea), bar (2–4 bars {label, value, text}), stack (name × count, por ejemplo, monedas apilándose), highlight (caja amarilla alrededor del elemento número target). cutout/photo/icon toman una etiqueta label corta. Reglas: un elemento por tema de narración, cada ~1–2 s; palabras at en orden de narración; como máximo 6 en el escenario a la vez ("clear": true en un elemento limpia el escenario primero); el diseño es automático (pos tl…br solo para forzar una ranura). Funciona con hook, explain y list_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, o path a la foto del usuario, cuando un accesorio debe ser exacto.
    • icon: nombre de Lucide (verifica renderer/node_modules/lucide-static/icons/<name>.svg). Bueno para el CTA y para ideas abstractas sin buen metraje.
    • local: path al clip del usuario. Úsalo cuando mencionen su propio metraje. assets/broll/ también se busca automáticamente por etiquetas.
    • solid: fondo degradado. ai_image actualmente se convierte en una foto de stock (prompt se 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, mira projects/<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_text de 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), opcional emphasis/visual.
  • Una idea por video. 4–6 escenas. Indonesio casual ("kamu", "nggak", "banget" están bien).
  • Presupuesto de palabras (medido; deja speech_rate sin 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 validate lo estima.
  • Oraciones cortas, 1–2 por escena. El on_screen_text de 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, calm para un ritmo triste o serio, emphatic para el remate.
  • tts_override solo cuando el TTS pronuncie mal algo (por ejemplo, "Follow" → "Folo"). Las correcciones generales van en la sección lexicon de klip.yaml (prueba con uv run klip say "…").
  • Salud / finanzas / seguridad: solo información general, sin consejos individuales, fuentes en facts[].
  • Termina con una escena cta y elige su cta_type. Los comentarios y guardados posicionan un video más alto que los seguidores, así que prefíerelos:
    • comment cuando 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 como on_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?".
    • save para consejos, pasos y listas que la gente querrá después ("Simpan biar nggak lupa").
    • share cuando sea útil para otra persona ("Kirim ke teman yang suka begadang").
    • follow para 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_item consecutivos), 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 es save, para evitar preguntar dos veces).
  • post.caption: una oración más un emoji. post.hashtags: 3–5, incluyendo #edukasi.
  • cover (opcional; el cover.png que 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), o lines (2–3 líneas explícitas, la última es la palabra clave), más subtitle (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 → el on_screen_text del 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.

Skills relacionados