Install
openclaw skills install @formula100k/motion-takeover-f100kPlanea TAKEOVERS faceless a pantalla completa para un video de YouTube 16:9 grabado con tu cara, estilo 'Claude Routines': en los momentos clave la pantalla se llena de mockups paso a paso, trazos SVG e imágenes IA, y luego vuelve tu cara. A partir del .srt del video ya cortado arma el plan de 2 carriles (takeovers + overlays ligeros), renderiza cada takeover como PNG 1920×1080 y, si quieres movimiento, lo anima con Higgsfield. Entrega las piezas + una hoja de montaje con el segundo exacto de cada takeover para ponerlas encima en tu editor. En este agente no edita ni compone el video. Activar cuando se diga: 'takeovers para mi video', 'motion graphics fullscreen tipo el video que te mandé', 'mockups paso a paso', 'estilo Claude Routines', 'cortes a gráfica'. NO usar para 9:16 (motion-reels-f100k).
openclaw skills install @formula100k/motion-takeover-f100kEsta versión corre en un agente OpenClaw (servidor + Telegram), no en Claude Code. Antes de seguir, lee la skill
f100k-puente: traduce herramientas y rutas. Lo específico de esta skill:
- No corren aquí: Paso 0 (corte semántico), transcripción con Whisper,
hyperframes render, la composición ffmpeg del Paso 7 niverify_audio_sync.py. Nada se monta sobre su video.- Entrada: la usuaria corta su video en su editor y te manda por Telegram el
.srtde ESA versión cortada (los tiempos tienen que coincidir) + 1 captura de un cuadro con su cara. Con eso armasmotion_board.json(Paso 4) y lo apruebas con ella antes de gastar nada.- Cada takeover: llena
templates/takeover-template.htmly renderízalo a PNG 1920×1080 con Chromium headless; antes de la captura adelanta la animación al final conwindow.__timelines['takeover'].progress(1)para que se vean mockups y trazos completos. Imágenes de escena con el plugin de Higgsfield (nano_banana_2, 16:9).- Si quiere movimiento: anima cada PNG con Higgsfield imagen → video (16:9, movimiento suave, que no deforme el texto), con la duración del takeover. Costo total → ✅ → generar. Revisa que el texto siga legible; si se deforma, entrega el PNG.
- Overlays de modo cara: PNG con fondo transparente (Chromium, fondo omitido) o
capturas-tutorial-formula100k. Sin fondo verde.- Entrega en
entregables/takeover-<fecha>/:motion_board.json,HOJA_MONTAJE.md(inicio y fin de cada takeover en el video cortado, «colócalo encima, opaco, sin mover la pista de voz») y un.zipcon PNG/MP4, por Telegram.
Toma un video grabado con la cara del usuario (16:9) y produce un video_final.mp4 que alterna dos modos:
motion-youtube-f100k).Reproduce el lenguaje visual del video de referencia "Claude Routines Just Launched" (KpG2yBi5I10).
Formato: 1920×1080 (16:9) @30fps.
enable='between(t,inicio,fin)'. JAMÁS se corta ni concatena el video base. La base (_source_cut.mov) no cambia de duración una vez cortada. Verificación ffprobe post-render OBLIGATORIA (Paso 8). (memoria: render-audio-sin-desfase)motion-reels-f100kmotion-youtube-f100keditor-video-formula100kcarrusel-render-formula100kReutiliza íntegro el bloque de instalación de motion-youtube-f100k (Node 22+, hyperframes CLI, paquetes @hyperframes/*, ffmpeg, yt-dlp, Whisper). No lo dupliques: ejecútalo y confirma con hyperframes doctor (Chrome + FFmpeg ✓) y hyperframes --version (≥0.7).
command -v hyperframes &>/dev/null || npm install -g hyperframes
command -v ffmpeg &>/dev/null || brew install ffmpeg
hyperframes doctor
Definir variables:
$VIDEO_SRC — ruta al video grabado (archivo local con cara).$DEST — carpeta de trabajo (la del archivo, o entregables/takeover-$(date +%Y%m%d)/).$SKILL — skills/motion-takeover-f100k (templates + scripts de esta skill).$OUTPUT — $DEST/video_final.mp4.$USER_SHOTS — $DEST/USER/ (capturas reales opcionales que deje el usuario).Los takeovers y overlays se cronometran sobre el transcript y se incrustan sobre el video. Si cortaras después, los cortes caerían encima de las animaciones. Por eso el recorte va aquí y el resto del pipeline trabaja siempre sobre el video ya limpio.
CUT_SCRIPT="skills/editor-video-formula100k/scripts/cut_silences_and_fillers.py"
[ -f "$CUT_SCRIPT" ] || echo "⚠ Falta cut_silences_and_fillers.py — instala editor-video-formula100k"
python3 -c "import numpy" 2>/dev/null || pip3 install --quiet numpy 2>/dev/null || true
mkdir -p "$DEST"
python3 "$CUT_SCRIPT" "$VIDEO_SRC" "$DEST"
# 🔑 La base SAGRADA a partir de aquí:
VIDEO_SRC="$DEST/_source_cut.mov" # video+audio limpio; NO se vuelve a cortar
echo "✅ Base cortada: $VIDEO_SRC"
ffprobe -v error -show_entries format=duration -of default=nokey=1:noprint_wrappers=1 "$VIDEO_SRC"
El corte deja captions.json (word-level, sobre la línea cortada). Se reutiliza en el Paso 2.
Si el usuario insiste en "ya está editado, no cortes" → saltar, pero advertir que el corte semántico es la regla de la casa. Por defecto SIEMPRE se corta.
if [ -f "$DEST/captions.json" ]; then
python3 - << 'EOF'
import json
words = json.load(open("$DEST/captions.json"))
segments = [{'text': w['word'].strip(), 'start_ms': int(w['start']*1000), 'end_ms': int(w['end']*1000)} for w in words]
json.dump(segments, open("$DEST/transcript.json", 'w'), indent=2, ensure_ascii=False)
print(f"♻️ {len(segments)} palabras reutilizadas del corte (sin re-transcribir)")
EOF
fi
Si por alguna razón no hay captions.json, usa el bloque Whisper de motion-youtube-f100k Paso 2.
Idéntico a motion-youtube-f100k Paso 1.5: extrae un frame medio, léelo con Read, determina SUBJECT_X/SUBJECT_Y y calcula SAFE_PILL_CSS, SAFE_CARD_CSS, SAFE_FLOAT_CSS. Estas variables se usan solo para los overlays de modo cara (los takeovers cubren todo el frame, no necesitan zona segura).
DURATION=$(ffprobe -v error -show_entries format=duration -of default=nokey=1:noprint_wrappers=1 "$VIDEO_SRC")
MIDPOINT=$(python3 -c "print(round($DURATION * 0.5, 2))")
ffmpeg -ss $MIDPOINT -i "$VIDEO_SRC" -vframes 1 -q:v 2 /tmp/frame_cara.jpg 2>/dev/null
Recorre el transcript y asigna cada momento a un carril. Objetivo: 3–6 takeovers por video (los momentos más fuertes), el resto overlays ligeros.
| Escena de takeover | Señales en el guion | Qué se construye |
|---|---|---|
steps — secuencia de pasos | "los 3 pasos", "primero… luego… al final", enumeración fuerte | mockups numerados 1→2→3 conectados por SVG paths |
ui — demo de herramienta | "te muestro", "abres Claude/Canva/Notion", "aquí pones…" | mockup de navegador grande (con captura de USER/ si existe) + path que señala |
compare — antes/después grande | "antes me tomaba X, ahora Y", contraste central del video | dos paneles fullscreen + trazo que los divide |
image — metáfora / escena | "imagina que…", concepto abstracto, gancho visual | imagen IA (banana/Higgsfield) fullscreen + título + path de subrayado |
bignum — dato protagonista | una cifra que merece toda la pantalla ("+10.000", "3 horas → 20 min") | número gigante animado + path circular |
motion-youtube-f100kpill labels, comparison card, floating UI, chapter card, kinetic word, quote pull, en zona segura. Mantiene la regla de densidad: 1 motion graphic cada 5s cuando la cara está en cuadro.
Genera $DEST/motion_board.json:
[
{ "lane": "overlay", "type": "pill_labels", "start_ms": 3000, "duration_ms": 4000, "labels": ["sin código","desde cero"] },
{ "lane": "takeover", "scene": "steps", "start_ms": 42000, "duration_ms": 8000,
"title": "Los 3 pasos, sin código", "kicker": "EL SISTEMA",
"steps": [
{"h":"Escribe la rutina","p":"Le dices en lenguaje natural qué quieres."},
{"h":"Programa la hora","p":"Corre sola, sin que tú estés."},
{"h":"Recibe el resultado","p":"Tu contenido listo al despertar."}
],
"paths": ["connector","connector","circle","check"] },
{ "lane": "takeover", "scene": "image", "start_ms": 95000, "duration_ms": 6000,
"title": "Tu equipo invisible", "image_hint": "un escritorio vacío al amanecer, luz cálida, laptop encendida sola" }
]
Presenta el board (los dos carriles, con los takeovers marcados 🎬) y pide aprobación:
AskUserQuestion:
"Este es el plan. 🎬 = takeover fullscreen, • = overlay ligero sobre tu cara.
¿Lo genero tal cual, ajustas algún takeover, o quieres dirección manual?"
Opciones: ["Generar tal cual", "Ajustar takeovers", "Dirección manual"]
Para cada entrada lane:"takeover":
paths se eligen de la librería de gestos.image/bignum o el guion pide una escena real):
banana (Gemini Nano Banana) o el MCP Higgsfield (mcp__higgsfield__generate_image, nano_banana_2, 16:9).$DEST/assets/ y referénciala como <img src="../assets/xxx.png"> dentro de la escena.USER/): si existe $DEST/USER/*.png|jpg, slottéala dentro del .mock .body de una escena ui (reemplaza el placeholder de texto por <img>), para mostrar el software real.Regla: NADA de stock. Si no hay imagen IA ni captura, la escena se resuelve 100% vectorial (mockups + paths + tipografía).
El corazón de la skill. Parte del template templates/takeover-template.html de esta skill (ya probado: fondo de marca opaco 1920×1080, kicker+título, 3 mockups numerados en secuencia, y la capa <svg id="paths">).
Cada <path>/<polyline> se anima con GSAP vía stroke-dashoffset. El helper del template lo hace solo:
function drawIn(sel, at, dur, ease) {
const el = document.querySelector(sel);
const len = el.getTotalLength ? el.getTotalLength() : 1000;
gsap.set(el, { strokeDasharray: len, strokeDashoffset: len });
tl.to(el, { strokeDashoffset: 0, duration: dur, ease: ease || "power2.inOut" }, at);
}
| Gesto | path d / forma | Uso |
|---|---|---|
| connector + flecha | curva Bézier entre dos mockups + <polyline> de punta | unir pasos 1→2→3 (escena steps) |
| subrayado | línea recta/curva bajo una palabra | resaltar el título o una palabra clave |
| círculo a mano | Bézier cerrada irregular | encerrar el mockup/resultado importante |
| check ✓ | <polyline> de 3 puntos | confirmar paso/resultado |
| línea ambiente | curva suave que cruza el fondo | movimiento sutil durante toda la escena |
| flecha señaladora | línea + punta hacia un punto del mockup | escena ui, apuntar a un botón/campo |
#14110F (default) o CREMA #F5EDE0 (variables --bg/--ink/--accent del template). NUNCA #00ff00 aquí (los takeovers no se keyean).back.out), badges numerados con back.out(2).data-composition-id="takeover", window.__timelines["takeover"] = tl.duration_ms del board.Genera una carpeta por takeover: $DEST/takeovers/takeover-N/index.html.
Igual que motion-youtube-f100k Paso 5–6: $DEST/overlays/index.html con body{background:#00ff00}, todos los overlays keyed.
cd "$DEST/overlays" && hyperframes render --format mp4 -o "$DEST/overlays/overlays.mp4"
for d in "$DEST"/takeovers/takeover-*/ ; do
n=$(basename "$d")
(cd "$d" && hyperframes render --format mp4 -o "$DEST/takeovers/$n.mp4")
done
⚠️ SIEMPRE
--format mp4(WebM ignora el CSS background). Los takeovers son opacos → NO llevan colorkey.
Principio: la base (_source_cut.mov) es intocable en duración. Los overlays de cara se keyean encima; cada takeover es un overlay OPACO activado solo en su ventana con enable='between(t,inicio,fin)'. Como el timeline base nunca se corta ni concatena, el audio no puede desfasarse.
Construye el filter_complex dinámicamente. Ejemplo con 1 capa de overlays keyed + 2 takeovers (t=42–50s y t=95–101s):
ffmpeg -y \
-i "$VIDEO_SRC" \
-i "$DEST/overlays/overlays.mp4" \
-i "$DEST/takeovers/takeover-1.mp4" \
-i "$DEST/takeovers/takeover-2.mp4" \
-filter_complex "
[0:v]fps=30,format=yuv420p[base];
[1:v]colorkey=0x00ff00:0.35:0.15[ovl];
[base][ovl]overlay=0:0:eof_action=pass[v1];
[2:v]setpts=PTS-STARTPTS+42/TB[tk1];
[v1][tk1]overlay=0:0:enable='between(t,42,50)':eof_action=pass[v2];
[3:v]setpts=PTS-STARTPTS+95/TB[tk2];
[v2][tk2]overlay=0:0:enable='between(t,95,101)':eof_action=pass[v]
" \
-map "[v]" -map 0:a \
-c:v libx264 -crf 18 -preset fast \
-c:a copy \
"$OUTPUT"
Notas clave:
setpts=PTS-STARTPTS+START/TB y se activa con enable='between(t,START,END)'. Fuera de su ventana no se ve → tapa la cara solo cuando toca.-map 0:a + -c:a copy = el audio original pasa intacto. (Si la fuente es .mov con stream de datos, usa -map 0:1.)-movflags +faststart (cuelga) ni -r 30 al final (rompe el timing).[k:v]setpts…[tkK]; [vPrev][tkK]overlay…enable…[vK].Generador del filtro (opcional, para muchos takeovers): construye el string en Python leyendo motion_board.json (entradas lane:"takeover" ordenadas), asignando índices de input 2,3,4… y encadenando [v1]→[v2]→….
# 1) AUDIO SYNC — guardián no negociable
python3 "$SKILL/scripts/verify_audio_sync.py" "$OUTPUT" --source "$VIDEO_SRC"
# exit 0 = ✅ SYNC OK | exit 1 = ❌ NO publicar, revisar Paso 7
Checklist visual:
verify_audio_sync.py → SYNC OK, Δ < 40ms) — chequear también lip-sync en un frame hablado.open "$OUTPUT"
$DEST/
├── _source_cut.mov ← base SAGRADA (Paso 0), no se re-corta
├── captions.json / transcript.json
├── motion_board.json ← 2 carriles (overlay + takeover)
├── assets/ ← imágenes IA / capturas procesadas
├── USER/ ← (input) capturas reales que dejal usuario
├── overlays/
│ ├── index.html (#00ff00) ← overlays modo cara (keyed)
│ └── overlays.mp4
├── takeovers/
│ ├── takeover-1/index.html (OPACO) ← escena fullscreen
│ ├── takeover-1.mp4
│ └── takeover-2/ …
└── video_final.mp4 ← OUTPUT
| Síntoma | Causa | Fix |
|---|---|---|
| Audio desfasado | se usó cut/concat en vez de overlay | Paso 7: takeover = overlay … enable='between', base intacta |
| Takeover fondo negro | filter_complex sin conversión de la base | fps=30,format=yuv420p[base] primero |
| Takeover no aparece / mal tiempo | falta setpts=PTS-STARTPTS+START/TB | reubicar cada takeover a su timestamp |
| Overlay de cara fondo negro | WebM ignora CSS bg | render MP4 siempre |
| Badge numerado recortado | overflow:hidden del mockup | badge como hermano del .mock (ver template) |
| Path no se dibuja | falta strokeDasharray/offset | usa el helper drawIn() del template |
No decoder for none en MOV | stream de datos | -map 0:1 para audio |
| ffmpeg se cuelga | -movflags +faststart | quitarlo |
| Aspecto | motion-youtube-f100k | motion-takeover-f100k |
|---|---|---|
| Gráficas | Solo overlays en esquinas (cara siempre visible) | Overlays + takeovers fullscreen que tapan la cara por ventanas |
| Firma nueva | — | SVG paths que se dibujan + secuencia de mockups |
| Fondo del asset | Todo green screen keyed | Overlays keyed + takeovers OPACOS de marca |
| Compositing | 1 overlay colorkey | base + colorkey + N overlays opacos con enable=between |
| Imágenes | No genera | banana/Higgsfield + capturas USER/ |
| Riesgo audio | Bajo (overlay no cambia duración) | Blindado con verify_audio_sync.py obligatorio |
Reutiliza de motion-youtube-f100k: onboarding, análisis de cara, los 6 templates de overlay, la regla de densidad.