Meme reel
Este skill convierte un tema en un video vertical que incluso el espectador menos informado puede entender. El espectador se ríe con momentos icónicos de series/películas turcas, y entre escena y escena aprende el tema mediante animaciones y narración. El motor es determinista: las escenas HTML se dibujan fotograma a fotograma en Chromium, el audio se sintetiza y mezcla con numpy.
Ejemplo listo: examples/ardupilot-mcp/ (36 seg, 4 memes, 6 escenas de narración). Antes de empezar un nuevo reel, lee sus archivos plan.json, fx.js y scenes/; allí verás todas las características en funcionamiento.
Límites
- No publicar nada. Entrega el video al usuario como archivo. No subas a buffer ni a ninguna otra plataforma ni siquiera como borrador, a menos que el usuario lo apruebe explícitamente en ese momento. Los pasos de publicación están en el skill
buffer-sosyal-icerik. - Cada número y afirmación en pantalla debe estar verificado. Muestra el log, medición, salida de herramienta o fuente proporcionada por el usuario. No incluyas en el video ninguna afirmación que no puedas verificar (por ejemplo, "lo resolvió en 1 minuto").
- No añadir líneas de nota. Incluso si usaste simulación o datos de demostración, no agregues "Nota:" ni líneas de honestidad al video ni a la descripción a menos que el usuario lo solicite explícitamente. No escribas un gancho en el primer fotograma como "un experimento en simulador".
- Copyright: Los clips de series/películas tienen derechos de autor. Si el usuario no ha aceptado el riesgo, pregúntale primero. No elimines el logotipo de la fuente (ej. TRT 1); recorta las marcas de agua publicitarias de terceros (como sitios de apuestas).
- Licencia TTS:
edge-ttsutiliza el servicio gratuito de lectura en voz alta de Edge; su uso comercial está en un área gris. Para publicación comercial, las mismas voces están disponibles con licencia en Azure Speech, o se puede usar la voz del propio usuario.
Texto para compartir
Si el usuario pide un caption (descripción):
- No repitas las frases del video. La descripción cuenta lo que el video no cuenta: qué es el producto, a quién beneficia, dónde se encuentra.
- Escríbelo como si se lo escribieras a un amigo, en turco cotidiano. Al final, una sola pregunta que invite a comentar.
- No añadas "Nota:" ni líneas de honestidad. Las aclaraciones sobre simulación, datos de demostración, uso de inteligencia artificial, etc., no aparecen en el texto de la descripción. Si se requiere una etiqueta de IA, se marca con la propia configuración de la plataforma.
- Los enlaces en la descripción de Instagram no se pueden hacer clic. Si dices "Enlace en el perfil" en el video o el texto, haz que el usuario confirme que el enlace está en el perfil; ninguna API puede modificar la biografía. En la descripción de YouTube escribe el enlace directamente.
Instalación
bash scripts/setup.sh # pip: edge-tts faster-whisper numpy scipy yt-dlp; verifica ffmpeg y Playwright
Los problemas conocidos del entorno (proxy/TLS, control de bots de YouTube, falta de H.264 en Chromium, Whisper y PyAV) y sus soluciones están en references/pitfalls.md. Si te quedas atascado, consulta allí.
Flujo
- Recopilar hechos. Extrae la afirmación del video de su fuente: salida de herramienta, log, medición. Anota los números y tiempos; las escenas usarán estos valores. Si en pantalla aparece un comando de instalación, verifica que el paquete realmente exista en el registro (PyPI, npm) y escribe el comando que el espectador reconozca:
pip install paquete,npm i paquete. Herramientas comouvxson para archivos de configuración MCP; resultan extrañas para el público general. - Escribir el guion (siguiendo la plantilla más abajo). Cada frase de narración dura 2-7 seg, cada meme 1-3 seg.
- Seleccionar memes. Primero consulta el catálogo
references/tr-memes.md(clips verificados con réplica y marca de tiempo). Para un clip nuevo, busca en Dailymotion conpython3 scripts/reel.py search "erdal bakkal", descárgalo y encuentra el segundo exacto de la réplica conreel.py stt. Mide la posición de la cara en el fotograma conreel.py still FUENTE SEGUNDOusando la cuadrícula resultante (cropx). - Configurar el proyecto:
plan.json,style.css,fx.js, si es necesariodata.jsyscenes/*.html. Lo más rápido es copiar y modificar el ejemplo. - Cortar y verificar clips:
reel.py clips PROYECTO. Para cada clip, se imprime lado a lado el texto que Whisper escucha y laquote. Si no coinciden, corrige el tiempo. - Locución:
reel.py tts PROYECTO --verify. Si Whisper escucha mal una palabra, es que TTS también la pronuncia mal; escribe el textosayfonéticamente (ej.ArduPilot em si pi'ye), en pantalla se muestra la forma correcta conshow. - Montaje y vista previa:
reel.py build PROYECTOluegoreel.py preview PROYECTO.build/sheet.pngmuestra 3 fotogramas de cada escena. Abre la hoja y verifica: elementos desbordados o superpuestos, texto que invade la zona segura, pantalla vacía, subtítulos ilegibles. Corrige y repite. - Render:
reel.py render PROYECTO --verify→PROYECTO/out/<titulo>.mp4. La salida muestra la duración, el nivel de audio integrado (debe ser alrededor de -14 LUFS) y el pico;--verifypasa todo el video por Whisper. Si toda la narración y las réplicas de los memes se escuchan correctamente, la música no está ahogando la voz. - Envía el video al usuario. Escribe brevemente qué clips usaste y de qué fuente, los riesgos que conllevan (copyright, licencia TTS, fuente de baja resolución) y las decisiones de edición con las que no estás de acuerdo.
- Ronda de correcciones. Si el usuario pide cambios de texto o imagen en una escena, corrígelos sin alterar la narración ni las duraciones de las escenas, ejecuta
build+preview --atpara ver ese fotograma, y luegoreel.py render PROYECTO --from <segundo de inicio de la escena>. Los fotogramas anteriores se conservan; solo se redibuja desde ese punto. Si la narración cambia, las duraciones se desplazan; entonces es necesario un render completo. - Publicación. Si el usuario dice "publiquemos", pasa al skill
buffer-sosyal-icerik: el video se sube con el paso de alojamiento de allí, y Reel, Shorts y story se sirven desde el mismo archivo. El enlace emergente en la story no se publica automáticamente; consulta la sección de story allí.
Plantilla de guion
Las reglas de gancho y sus justificaciones están en references/hooks.md. Resumen:
| Golpe | Duración | Qué ocurre |
|---|---|---|
| Gancho | 0-3 seg | Empieza en medio de la acción (drone cayendo, error rojo). En el primer fotograma ya debe verse una frase de 4-7 palabras; que el espectador con el sonido apagado también entienda. |
| Meme de reacción | 1-2 seg | Asombro ("¿Qué pasó?"). Inmediatamente después del gancho. |
| Problema | 3-6 seg | Muestra la magnitud del problema con un número concreto (1.558.457 líneas). |
| Memes de reacción | 2-5 seg | Uno o dos memes sobre lo absurdo del problema. Un texto superior (cap) conecta el meme con el tema. |
| Solución | 3-4 seg | Momento de usar el producto; interfaz real o una imitación fiel. |
| Respuesta | 4-7 seg | El hallazgo principal, animado con datos. La escena más larga y la que más "enseña". |
| Valor | 2-3 seg | Gratuito, código abierto, comando de instalación, etc. |
| Meme de empuje | 1-2 seg | Meme que apela al espectador ("¿Qué esperas, Behzat?"). |
| Cierre | 3-5 seg | Qué hacer + lectura "Enlace en el perfil". |
Total 25-36 seg. Si supera los 30 seg, sugiere acortar la frase de narración más larga.
plan.json
{
"title": "<Tema> - Reels <nombre>", // nombre del archivo de salida
"voice": "tr-TR-EmelNeural", "rate": "+6%", // tr-TR-AhmetNeural no devuelve voz en este servicio
"clips": { // fuentes de memes
"neoldu": {"dm": "x587xuk", "start": 37.80, "dur": 1.06, "cropx": 135, "quote": "— ¿Qué pasó?"}
// fuente: "dm" (id de Dailymotion) | "url" (yt-dlp) | "file" (local). mode: "face" (recorte 4:5 del rostro, predeterminado) | "fit" (plano general)
},
"lines": { // narración; "show" es la forma que se ve en pantalla (opcional)
"n1": {"say": "Mi drone cayó desde veinte metros.", "show": "Mi drone cayó desde 20 metros."}
},
"scenes": [ // se reproducen en orden; las duraciones se calculan a partir del audio
{"id": "a", "line": "n1", "html": "scenes/crash.html", "pad": 0.25, "cap": "texto superior opcional"},
{"id": "m1", "clip": "neoldu", "cap": "texto superior opcional"}
],
"music": {"style": "phonk", "bpm": 120, "level": 0.42, "mute": [["a@düştü+0.05", "b"]], "light": []},
"sfx": [{"fx": "boom", "at": "a@düştü+0.1", "gain": 1.0}]
}
Si el número de palabras de show es igual al de say, cada palabra toma su propio tiempo; si no, las palabras se distribuyen uniformemente en la duración del habla. La duración de una escena de meme es la duración del clip; la de una escena de narración es audio + 0,08 seg + pad.
Escribir escenas
Cada escena de narración es un fragmento HTML (scenes/<nombre>.html) y una función FX.<id> en fx.js.
La escena se coloca dentro de <section id="<id>" class="k-<nombre>">. El motor maneja el corte, el zoom de perforación, la animación de cap, el cambio de fotograma del meme y los subtítulos estilo karaoke; FX solo dibuja el movimiento específico de la escena.
FX.d = ({ s, el, t, lt, d, punch, word }) => {
// lt: segundos dentro de la escena, d: duración de la escena, t: segundos del video
// word('motor', 0.5): segundo dentro de la escena en que se dice "motor" (si no se encuentra, 0.5)
pop($('mhead'), lt, word('motor'), 0.3); // aparece elevándose
stamp($('tag2'), lt, word('yetme'), 'translateX(-50%)'); // crece desbordando
type($('cmd'), 'pip install ardupilot-mcp', lt, 0.1, 0.8); // máquina de escribir
};
Funciones auxiliares: seg, clamp, lerp, easeOut, easeInOut, back, interp(serie, t), pop, stamp, type.
Regla: el fotograma debe depender solo de t. No uses setTimeout, Date, transiciones CSS ni aleatoriedad; como los fotogramas se capturan uno por uno, esto provocaría parpadeos y saltos.
Diseño (1080x1920): los 220 px superiores, 400 px inferiores y 150 px derechos son cubiertos por la interfaz de Instagram. El contenido principal debe estar entre y 230-1300. Los subtítulos en y 1350, cap en y 230. Extiende la escena por toda la pantalla; las tarjetas pequeñas dejan espacio vacío en el centro y se ven baratas en un teléfono. Texto mínimo 40 px, números clave 100 px o más.
Lenguaje visual (del ejemplo): fondo azul marino oscuro #0A0F1C, cian #38BDF8 para estado normal, rojo #F43F5E para fallo, verde #34D399 para solución, ámbar #FBBF24 para atención/CTA. Iconos de Tabler (SVG en línea).
Audio
- Narración a -17 dBFS RMS, sonidos de memes ecualizados a -16. La música se reduce ~72% debajo de la narración y ~88% debajo de los memes. El video final se normaliza a -14 LUFS.
- La música es libre de derechos, generada desde el código (phonk a 120 BPM: kick, 808, clap, hi-hat, cowbell). En la ventana
mutela música se silencia; el silencio después del impacto es el golpe más fuerte. - Efectos:
whoosh(transición de escena;"at": "cuts"lo aplica a todas),fall,boom,hit,click(máquina de escribir, contador),beep,tone,ding,riser,sparkle. Los parámetros están enscripts/synth.py. - Anclajes de tiempo: número (segundo absoluto) |
"b"(inicio de escena) |"b.end"|"d@yetme"(la palabra que empieza con "yetme" en esa escena); a todos se les puede añadir+0.1/-0.4. Para repeticiones,every+countountil; en barridos comofallywhoosh, dar solountilextiende el sonido hasta ese momento.
Que no parezca inteligencia artificial
Un video completamente sintético (voz TTS, escenas vectoriales perfectas, cada efecto ajustado exactamente a la palabra) da al espectador la sensación de "lo hizo una IA". Sugiere al usuario lo siguiente, y aplícalo según la disponibilidad:
- Grabación de pantalla real: En lugar de imitar la interfaz del producto, coloca una grabación real de su uso en la escena (dentro de
clips, con"file"+"mode": "fit"). Una sola imagen real da credibilidad a todo el video. - Voz humana: Si el usuario graba sus líneas en el teléfono,
reel.py voice PROYECTO n1 grabacion.m4areemplaza el TTS con esa grabación, recorta el silencio inicial/final y extrae los tiempos de las palabras con Whisper. La parte que más delata al TTS es la entonación. - Lenguaje hablado: Escribe el guion no como algo corporativo, sino como si se lo contaras a un amigo: "Abrí el log", "no fue suficiente".
- Imperfección y ritmo: No hagas todas las escenas de la misma duración. Desfasa algunos efectos 1-2 fotogramas de la palabra, corta la música por completo en una escena. Evita una composición perfectamente simétrica.
- Formato familiar: Una introducción con el propio rostro o voz de la cuenta (1 segundo "mira lo que pasó") resulta más humana que una serie de memes.
Lecciones aprendidas de reels anteriores
- Lo que funciona: clip de meme vertical a pantalla completa con su propio audio; escena corta de narración entre medias; subtítulos palabra por palabra.
- El usuario aun así lo encontró "como hecho por IA". En la siguiente ocasión, ofrece al menos uno de los puntos anteriores (grabación de pantalla real o voz del propio usuario).
- No se deseó añadir notas, advertencias ni líneas de "es una simulación" al cierre ni a la descripción.
- Al empezar un nuevo reel, mira el último reel de la misma cuenta; no reutilices los mismos memes en el mismo orden.
Archivos
scripts/reel.py: todo el flujo (search, stt, still, clips, tts, voice, build, preview, mix, render [--from], all)scripts/engine.js,scripts/base.css: motor de fotogramas y estilos comunesscripts/synth.py: generadores de música y efectosscripts/capture.js: captura de fotogramas con Playwrightreferences/tr-memes.md: clips de memes turcos verificados (id, segundo, réplica, recorte)references/hooks.md: reglas de gancho y ritmo, fuentesreferences/pitfalls.md: problemas de entorno y solucionesexamples/ardupilot-mcp/: proyecto de ejemplo completamente funcional