Changelog → Video con Marca
Entrada: un archivo changelog .md (temas + elementos, como el digest semanal de HyperFrames).
Salida: un proyecto HyperFrames limpio, con "seam-gate green" en
projects/active/weekly-changelog-<rango>/. Renderiza solo cuando se solicite.
Carga primero, sin excepción: motion-doctrine (+ cut-the-curve,
oversized-cursor si aparece un cursor, seam-craft) y captions-overlay.
Esta skill proporciona el pipeline específico del changelog; la doctrina proporciona la
ley del movimiento.
La directiva principal: visualizar, no enumerar
Cada tema se ilustra mediante un mock animado de la interfaz real o un
análogo fiel que representa el cambio en la experiencia — nunca viñetas de texto.
Enruta cada tema/elemento a través de references/visualization-registry.md ANTES de
escribir el guion; el registro decide ui-recreate / ui-analog / terminal / checklist.
La lista de verificación (checklist) es el ÚLTIMO recurso, reservado para elementos
genuinamente no visuales (listas de correcciones de fiabilidad).
Pipeline
0 · Inicializar el proyecto DESDE los activos de ESTA skill — sin excepción
Haz esto antes de escribir cualquier composición HTML. Omitirlo siempre produce un video que se parece a un proyecto similar que construiste antes, NO a la marca de esta skill — ese es el error más común que hace que esta skill se desvíe de la marca. Los activos, fuentes y andamio de la skill son la skill; el prompt de SKILL.md es un enrutador.
mkdir -p project/assets/fonts
cp <SKILL_DIR>/assets/fonts/*.woff2 project/assets/fonts/
cp <SKILL_DIR>/assets/bgm.mp3 project/bgm.mp3
ffmpeg -y -stream_loop 15 -i <SKILL_DIR>/assets/bg-pattern.mp4 -t <TOTAL> \
-vf "scale=1080:1080,fps=30,eq=saturation=0.72,[email protected]:t=fill" \
-an -c:v libx264 -crf 20 -pix_fmt yuv420p project/assets/bg-pattern-<TOTAL>s.mp4
cp <SKILL_DIR>/examples/master-skeleton.html project/index.html
Luego lee references/build-spec.md de principio a fin (sin saltos) — define los tokens de marca (TT Norms Pro + ABC Solar Display + TT Norms Mono, crema #f5f6f4, verde racionado #5ef17c, tarjetas de vidrio con bordes tintados en verde, forma de píldora kicker/sec-chip, riel de subtítulos de 32px en top: 990) que cada escena hereda del andamio.
Solo ENTONCES comienza los pasos 1-6 a continuación. Los pasos 1-4 (analizar, enrutar, guion, VO) planifican lo que va dentro del andamio; el paso 5 rellena los marcadores de posición (<RANGE>, <TOTAL>, <CUT_N>, <DUR_N>, cuerpos de escena) dentro del project/index.html ya copiado — NO reescribes el cromo, las fuentes, la paleta o el esqueleto de diseño del andamio.
Si te sorprendes a ti mismo usando cp en el index.html de un video anterior, o escribiendo tus propias declaraciones @font-face, o diseñando un fondo shader WebGL en lugar de usar el bg-pattern MP4 codificado anteriormente: DETENTE. Elimina el index.html actual y reinicia desde la copia del andamio maestro (master-skeleton). Reconstruir el contenido de la escena sobre el andamio correcto es más barato que reequipar la marca en el andamio incorrecto.
1 · Analizar + corte editorial
- Extraer: rango de semanas, estadísticas principales (lanzamientos, commits), temas, elementos.
- Presupuesto: 45-60s en total. Título ≤2s, outro ≤3.5s, 4 temas ≈ 9-12s cada uno.
- Por tema, mantener UNA visualización principal + como máximo 3 elementos hablados. Todo lo demás existe solo como el puntero del "digest completo" en el outro. Cortar es el trabajo: un changelog con 30 elementos sigue produciendo ≤14 compases hablados.
- Ordenar temas por historia: función estrella → superficie del producto → rendimiento → fiabilidad (el digest generalmente ya se lee de esta manera).
2 · Enrutamiento de visualización
Para cada tema, elige la superficie de references/visualization-registry.md
y escribe una línea: tema → superficie → las 2-4 acciones secuenciadas que realiza el mock, cada una vinculada a una frase del guion. Si ninguna superficie del registro encaja y no existe un análogo fiel, es una escena de lista de verificación (checklist) — no inventes una interfaz falsa para algo que no podemos representar honestamente.
3 · Guion de dos capas (hablado vs. mostrado)
Escribe el guion como líneas de tokens según references/script-voice.md:
registro conversacional, cada término técnico lleva una forma fonética spoken
desde references/lexicon.json mientras que display mantiene la ortografía estándar.
Los subtítulos muestran display; la voz en off lee spoken. Cualquier término que no esté en el léxico:
DETENTE y pregunta al usuario cómo se pronuncia, luego agrégalo al léxico.
Guárdalo como script-tokens.json en el proyecto.
4 · VO — Annie (HeyGen, fijada)
# solo texto de la capa hablada; words JSON = marcas de tiempo reales del TEXTO HABLADO
# Ruta nativa del repositorio: la skill changelog-video se ejecuta desde la raíz del repositorio hyperframes,
# por lo que usa el ayudante TTS hyperframes-media directamente (sin paso de instalación `npx hyperframes
# skills`). Si has copiado la skill en otro repositorio, reemplaza con
# tu propia ruta al archivo heygen-tts.mjs de media-use / hyperframes-media.
node skills/hyperframes-media/scripts/heygen-tts.mjs ./vo-spoken.txt \
-o voiceover.mp3 --words vo-words.json \
--voice 330290724a1b470fb63153f34d4c0183 # Annie — realista (no sustituir)
Requiere CLI heygen ≥0.3.0 autenticada (heygen auth login --oauth).
Luego alinear las marcas de tiempo habladas de vuelta a los tokens mostrados:
node <SKILL_DIR>/scripts/align-captions.mjs \
--tokens script-tokens.json --words vo-words.json --out captions.json
captions.json es la entrada para el riel de subtítulos (ortografía mostrada, tiempo hablado).
El alineador imprime advertencias MISMATCH — resuelve cada una antes de construir
(generalmente una ortografía del léxico que el TTS renderiza como múltiples palabras). El audio
es el reloj: todos los tiempos de los compases provienen de vo-words.json; una regeneración del VO reabre
cada costura.
Las marcas de tiempo de palabras son una puerta dura. Antes de pasar al paso 5, verifica
que vo-words.json no esté vacío y tenga un array words: [...] con start/end
por palabra. Si está vacío (0 bytes) o falta el array — un modo de fallo conocido
cuando el proveedor TTS devuelve audio pero sin carga útil de marcas de tiempo — NO continúes
sin ellos. Alternativa: alinear forzosamente el audio producido contra el guion mostrado
usando whisper local:
uvx --from openai-whisper whisper voiceover.mp3 \
--model base.en --language en --word_timestamps True \
--output_format json --output_dir .
# luego ejecuta align-captions.mjs con --words voiceover.json (misma forma)
Whisper malinterpreta las representaciones TTS ("gee-sap" → "gsap", "heyjen" → "hey Jen",
etc.) — los subtítulos siguen usando la ortografía de DISPLAY de script-tokens.json;
whisper solo proporciona las marcas de tiempo. align-captions.mjs maneja la unión.
Esta alternativa es la diferencia entre una compilación con subtítulos y una
silenciosamente sin subtítulos.
5 · Construcción
Sigue references/build-spec.md exactamente: tokens de marca + fuentes (incluidas
en <SKILL_DIR>/assets/), la codificación del fondo animado, andamio de escena,
cromo, riel de subtítulos, un momento de verde racionado por escena. Luego el orden
de la doctrina: ledger.json (todas las costuras ordinarias cut-the-curve LEFT) → seam-stamp
→ compases internos en palabras VO → verificación seam-gate.
Los subtítulos no son opcionales. El andamio maestro incluye una IIFE de riel de subtítulos
que lee un array LINES — dejar ese array vacío es un error enviado, no una
elección de estilo. Pobla desde captions.json antes de proceder al paso 6:
// pegar en lugar de "const LINES = /* … */ []" en la IIFE del riel de subtítulos:
const LINES = /* contenido de captions.json */ [
{ id: 0, end: 2.74, w: [["This", 0.0], ["week,", 0.30], …] },
…
];
Si se omitió align-captions.mjs o LINES está [], la verificación de fotogramas en
el paso 6 fallará — no lo ocultes eliminando #cap-line del
andamio.
6 · Compuertas (todo en verde antes de presentar)
node packages/cli/bin/hyperframes.mjs check --caption-zone "x0=0;y0=.90;x1=1;y1=1;severity=error;seek=.02,.06,.10,.14,.18,.22,.26,.30,.34,.38,.42,.46,.50,.54,.58,.62,.66,.70,.74,.78,.82,.86,.90,.94,.98"(o la CLIhyperframesinstalada desde la skillskills/hyperframes-cli/local del repositorio) — 0 errores (contraste: texto tenue ≥ .66 alpha; contenido de la escena permanece por encima del riel de subtítulos). NO usesnpx hyperframes@latest; la CLI local del repositorio es la fuente de verdad para el contrato de composición que esta skill produce.seam-gate.mjs verify— 0 fallos.- Reinicia el servidor de vista previa (almacena en caché el paquete), verifica 3-4 compases
mediante
__player.seeken la página de composición sin procesar. - NO renderices a menos que el usuario lo solicite. Después de un render solicitado, verifica
fotogramas del MP4 (
ffmpeg -ss <t> … -frames:v 1): subtítulos presentes, video de fondo no negro, sin fotogramas pequeños/congelados. - Compuerta de presencia de subtítulos — fallo duro. Muestra 3-4 fotogramas distribuidos a lo largo de
la ventana de voz del VO (por ejemplo,
t=3,t=15,t=30,t=42para un VO de 48s) y confirma que el riel de subtítulos entop: 990renderiza texto visible en cada uno. Si algún fotograma en un intervalo de voz carece de subtítulos, la compilación se envía sin subtítulos — trátalo como una compuerta roja y vuelve a verificar la población deLINESdel paso 5. Esto es exactamente lo que salió mal en la compilación v4 del 13-20 de julio.
Diseño del proyecto
projects/active/weekly-changelog-<rango>/
├── index.html # maestro de un solo documento (escenas como diapositivas, costuras selladas)
├── ledger.json # libro mayor vectorial (entrada para seam-stamp)
├── script-tokens.json # guion de dos capas (fuente de verdad para VO + subtítulos)
├── vo-spoken.txt # generado: capa hablada, una línea
├── voiceover.mp3 + vo-words.json + captions.json
├── bgm.mp3 # copia de <SKILL_DIR>/assets/bgm.mp3 (la pista de la casa) a menos que el usuario proporcione una
└── assets/fonts/ + assets/bg-pattern-<dur>s.mp4
Antipatrones
| No hacer | En su lugar |
|---|---|
| Diapositivas con viñetas para cambios de interfaz | Mock de la superficie que representa el cambio |
| Interfaz falsa para elementos no representables | Escena honesta de lista de verificación (checklist) |
| "JSON"/"CLI" simple en el texto TTS | Formas habladas del léxico; la capa mostrada permanece estándar |
| Ortografía fonética en subtítulos | Los subtítulos siempre renderizan la capa de visualización |
| Adivinar la pronunciación de un término desconocido | Preguntar, luego aumentar el léxico |
| Hablar cada elemento del changelog | ≤3 por tema; el enlace del digest lleva el resto |
| Acentos verdes en todas partes | Un momento verde por escena (#5ef17c) |
| Empezar desde el index.html de un video anterior | Paso 0 — copiar examples/master-skeleton.html de esta skill en project/index.html, siempre |
Declaraciones @font-face / shader WebGL / BGM personalizados hechos a mano | Paso 0 — copiar los assets/ de esta skill textualmente; los activos de la skill SON la marca |
| Entregar sin invalidación de CloudFront | Ejecutar aws cloudfront create-invalidation en la distribución E2BSLVSZ7FG3U0 para la ruta exacta después de cualquier reemplazo en S3 — de lo contrario, el CDN almacena en caché el archivo antiguo |
Enviar con el array LINES vacío en el andamio | El paso 4 debe producir un captions.json poblado; el paso 5 debe pegarlo en la IIFE; la compuerta 5 del paso 6 debe confirmar subtítulos en los fotogramas renderizados. Un LINES vacío = envío sin subtítulos = rehacer la ejecución |
No tener vo-words.json → saltar subtítulos y enviar de todos modos | Recurrir a alineación forzada con whisper en el audio producido; los subtítulos no son opcionales |