| name | thumbnail-simple |
| description | Genera thumbnails de YouTube (1280x720 PNG) con la estética de Horizontes IA — dark mode + cyan, tipografía Space Grotesk + Instrument Serif. Usa Kie AI (Nano Banana 2) para el background y Pillow para composición de texto. Activa cuando el usuario pida un "thumbnail", "miniatura de video", "YT cover", "portada de YouTube", o "cover para video". También se activa cuando el skill planeacion-video llega a Fase 5 y pide generar los assets visuales del video. Genera 1 variante por default, o N variantes si el usuario lo pide explícitamente. |
| metadata | {"version":"1.0.0"} |
Thumbnail Simple — YouTube Thumbnails para Horizontes IA
Skill dedicada a generar thumbnails de YouTube (1280x720) con la estética de Horizontes IA. Reusa el mismo stack técnico de instagram-stories (Kie AI + Pillow) pero enfocado específicamente a thumbnails del canal de Santi.
Cuándo usar
- Usuario pide: "thumbnail", "miniatura", "YT cover", "portada de video"
- El skill
planeacion-video llega a Fase 5 y solicita generar el thumbnail del video planeado
- Necesitas UN thumbnail específico — no múltiples banners para múltiples plataformas
NO usar para:
- Instagram stories → usa
instagram-stories
- Posts / carruseles de IG, LinkedIn banners, Twitter headers → usa
ckm:banner-design si está disponible
- Múltiples tamaños del mismo visual → usa
ckm:banner-design
Setup Requirements
Python packages
pip3 install Pillow
Fonts (una sola vez)
mkdir -p thumbnails/fonts thumbnails/assets thumbnails/output
curl -sL "https://github.com/google/fonts/raw/main/ofl/spacegrotesk/SpaceGrotesk%5Bwght%5D.ttf" \
-o thumbnails/fonts/SpaceGrotesk-Variable.ttf
curl -sL "https://github.com/google/fonts/raw/main/ofl/instrumentserif/InstrumentSerif-Italic.ttf" \
-o thumbnails/fonts/InstrumentSerif-Italic.ttf
Kie AI
Requires KIE_AI_API_KEY en el ambiente. Si no está set, revisa .env o pide al usuario.
Logo (opcional)
Si existe, ponlo en thumbnails/assets/logo.png para overlay en la esquina inferior.
Foto de Santi (opcional)
Si el thumbnail lo requiere, pide al usuario que provea thumbnails/assets/santi.png (PNG con background transparente idealmente).
Inputs esperados
Del usuario o del skill invocador, extrae:
- Texto principal (obligatorio) — el headline grande del thumbnail. Máximo 4-6 palabras. Ej: "50 MIL PESOS. UN AGENTE DE IA."
- Subtítulo (opcional) — texto pequeño contextual. Máximo 6 palabras. Ej: "tutorial completo con Claude Code"
- Concepto del background (obligatorio) — 1 frase descriptiva para generar la imagen con Kie AI. Ej: "celular futurista rodeado de ondas cyan brillantes con dashboard de Notion flotando al lado"
- Incluir foto de Santi (opcional, default: false) — si true, requiere
thumbnails/assets/santi.png
- Número de variantes (opcional, default: 1) — cuántos thumbnails alternativos generar con backgrounds distintos pero mismo texto
- Nombre del archivo de salida (opcional, default:
thumbnail.png) — se guarda en thumbnails/output/
Si el usuario da una idea vaga: tú escribes el texto principal y el concepto del background basándote en la idea. Presenta la propuesta al usuario para aprobación ANTES de generar (consume créditos de Kie AI).
Workflow
Step 1: Generar background con Kie AI
Construye un prompt detallado para Nano Banana 2 en aspect ratio 16:9:
import json, urllib.request, os, time
api_key = os.environ["KIE_AI_API_KEY"]
concept = "<concepto del usuario>"
style_suffix = (
"cinematic lighting, dark background with cyan and teal glow accents, "
"dramatic shadows, high contrast, futuristic atmosphere, 16:9 composition, "
"ultra detailed, no text, no letters, no words, no watermarks"
)
prompt = f"{concept}, {style_suffix}"
payload = json.dumps({
"model": "nano-banana-2",
"input": {
"prompt": prompt,
"aspect_ratio": "16:9",
"resolution": "2K",
"output_format": "png",
},
}).encode()
req = urllib.request.Request(
"https://api.kie.ai/api/v1/jobs/createTask",
data=payload,
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
},
)
resp = json.loads(urllib.request.urlopen(req).read())
task_id = resp["data"]["taskId"]
Después haz polling a https://api.kie.ai/api/v1/jobs/recordInfo?taskId=<id> cada 2 segundos hasta que state == "success". Extrae la URL del resultado y descarga con urllib.request.urlretrieve(url, "thumbnails/assets/bg.png").
Si se piden múltiples variantes: envía N tareas EN PARALELO (no secuencial) y poll todas juntas. Esto ahorra tiempo significativamente.
Step 2: Componer con Pillow
Canvas: 1280x720 RGBA (dimensiones exactas de YouTube thumbnail).
Estructura visual estándar:
from PIL import Image, ImageDraw, ImageFont, ImageFilter
W, H = 1280, 720
BG_DARK = (10, 10, 10)
BG_DARKER = (8, 8, 16)
CYAN = (0, 229, 255)
WHITE = (255, 255, 255)
WHITE_DIM = (200, 205, 215)
bg = Image.open("thumbnails/assets/bg.png").convert("RGBA")
bg = bg.resize((W, H), Image.LANCZOS)
overlay = Image.new("RGBA", (W, H), (0, 0, 0, 130))
bg = Image.alpha_composite(bg, overlay)
draw = ImageDraw.Draw(bg)
Step 3: Tipografía y layout
Texto principal:
- Fuente: Space Grotesk Variable (weight 700 = bold)
- Tamaño: 96-128px dependiendo de la longitud
- 1-3 palabras → 128px
- 4 palabras → 112px
- 5-6 palabras → 96px, wrap a 2 líneas
- Color: blanco (#FFFFFF)
- Alineación: izquierda (posición x=80) si hay sujeto visual a la derecha, centrada si el background es abstracto
- Drop shadow: offset (4, 4), color (0, 0, 0, 180), con leve blur
Subtítulo (si existe):
- Fuente: Instrument Serif Italic
- Tamaño: 42px
- Color: cyan (#00E5FF)
- Posición: directamente debajo del título, con 20px de separación
- Drop shadow: offset (2, 2), color (0, 0, 0, 150)
Wordmark de Horizontes IA (opcional, discreto):
- Fuente: Space Grotesk Variable (weight 500)
- Tamaño: 24px
- Color: cyan semitransparente
- Posición: esquina inferior derecha con padding 32px
- Texto: "HORIZONTES IA" o el logo PNG si está disponible
Línea de acento cyan:
- 4px de altura
- Ancho: 120px
- Color: cyan puro
- Posición: encima del título con 32px de separación
- Propósito: elemento visual de marca
Step 4: Composición de foto de Santi (si include_santi=true)
Si se incluye foto:
santi = Image.open("thumbnails/assets/santi.png").convert("RGBA")
santi_h = 680
santi_w = int(santi.width * (santi_h / santi.height))
santi = santi.resize((santi_w, santi_h), Image.LANCZOS)
paste_x = W - santi_w - 40
paste_y = H - santi_h - 20
bg.paste(santi, (paste_x, paste_y), santi)
Cuando hay foto: mover el texto a la mitad izquierda del canvas. Usar la regla de tercios.
Step 5: Output
flat = Image.new("RGB", (W, H), BG_DARK)
flat.paste(bg, mask=bg.split()[3])
output_path = "thumbnails/output/<filename>.png"
flat.save(output_path, "PNG", optimize=True)
print(f"✅ Thumbnail guardado en: {output_path}")
Output directory: thumbnails/output/
File naming: usa el nombre proporcionado o default thumbnail.png. Si hay múltiples variantes, usa thumbnail-v1.png, thumbnail-v2.png, etc.
Reglas de composición (crítico)
Para maximizar CTR en YouTube:
- Máximo 4-6 palabras en el texto principal. Nunca más.
- Alto contraste: el texto debe ser legible a 200px (vista de mobile feed)
- Safe zone: contenido crítico dentro del 80% central del canvas
- Cara humana (si aplica): debe ser identificable, expresión clara
- Un solo claim visual dominante — no saturar con 5 elementos compitiendo
- Colores saturados: cyan puro, no pastel
- Evitar clichés de AI slop: no flechas rojas gigantes, no círculos rojos sobre la cara, no emojis en el thumbnail
Integración con planeacion-video (Fase 5)
Cuando planeacion-video invoque este skill en Fase 5, espera un prompt con este formato:
Genera un thumbnail para el video "[título del video]".
Especificaciones del brief:
- Texto principal: "[texto grande del brief de thumbnail de Fase 4.4]"
- Subtítulo (si aplica): "[subtítulo]"
- Concepto del background: [descripción visual del brief]
- Paleta: dark (#0a0a0a) + cyan (#00E5FF)
- Incluir foto de Santi: [true/false]
- Output: thumbnails/output/[slug-del-video].png
- Variantes: [N]
Parsea el contexto, extrae los inputs, y genera directamente sin re-preguntar. El objetivo es que Fase 5 sea fluida, no interrumpida.
Defaults (si el usuario no especifica)
- Background concept: "abstract cyan waveforms and geometric shapes floating in deep space"
- Texto principal: "[título del video en CAPS, máximo 6 palabras]"
- Sin foto de Santi
- Sin subtítulo
- 1 variante
- Output:
thumbnails/output/thumbnail.png
Troubleshooting
- Kie AI devuelve error: verifica
KIE_AI_API_KEY en el ambiente con echo $KIE_AI_API_KEY. Si está vacío, carga el .env del proyecto.
- Texto se sale del canvas: reduce el tamaño de fuente en 16px o wrap a 2 líneas.
- Background muy saturado, texto ilegible: aumenta el overlay oscuro de 130 a 160-180.
- Pillow falla cargando fuentes: re-ejecuta el setup de fonts del Step 0.
- Output borroso al subir a YouTube: asegúrate de guardar a 1280x720 exactos, no escalar desde 1920x1080.