Publicar el sitio videolabs
"Publicar" significa que todo el sitio se despliega con todos los laboratorios, cada vez.
Repositorio del sitio: /opt/opus/videolabs (github.com/bigzaqui/videolabs, se despliega en https://videolabs.pages.dev al hacer push a main; GitHub Actions publica la carpeta site/).
Laboratorios: /opt/opus/videolabs/labs/<slug>/ (una carpeta por laboratorio, en el mismo repositorio; el slug es el nombre del MP4 out/<slug>.mp4). Se construyen con la habilidad videolabs_create-video (node engine/cli.mjs <slug> ...).
Los videos viven en el bucket privado de R2 videolabs en <slug>/<slug>.mp4 y se sirven a través de /media/<slug>/<slug>.mp4, que está detrás de una sesión de Turnstile (una solicitud sin sesión devuelve 401).
Credenciales: /opt/opus/videolabs/.env (cargadas por los scripts; plantilla .env.example). Nunca imprimas, copies ni confirmes secretos. El repositorio de GitHub es público (al usuario le parece bien para el audio de narración, scripts, capturas y salida del laboratorio, y no le importa que aparezcan contraseñas desechables de laboratorios destruidos), por lo que ninguna credencial real puede aparecer en ningún archivo. El origen de esta habilidad es skills/videolabs_publish/ en el repositorio, enlazado a ~/.claude/skills mediante scripts/setup.sh.
Qué necesita un laboratorio (verificado por el script)
out/<slug>.mp4(fast-start:moovantes demdat; corregir conffmpeg -i in.mp4 -c copy -movflags +faststart out.mp4),out/player/chapters.json(node engine/cli.mjs <slug> player),out/spot.jpg(póster; capturar un fotograma del diagrama conffmpeg -ss 425 -i out/<slug>.mp4 -frames:v 1 -q:v 3 out/spot.jpg).- Opcional:
out/player/lab.json(denode engine/cli.mjs <slug> playercuando el laboratorio tienelab/lab-meta.json,lab/*.sh,lab/captures/). Si está presente,site/lab.jsmuestra los recursos del laboratorio en la página del laboratorio. Vuelve a ejecutarnode engine/cli.mjs <slug> playerprimero si las capturas olab-meta.jsoncambiaron. labs/<slug>/lab.config.jsoncontitle,descriptionytags. El script agrega o actualiza la entrada ensite/labs.jsona partir de ahí (y completaminutesylessons), por lo que nunca edites el catálogo manualmente. Para un laboratorio nuevo, toma title/description/tags del script del laboratorio si está claro; de lo contrario, pregunta al usuario. Nunca los inventes en silencio.
Pasos
- Planificar.
cd /opt/opus/videolabs && scripts/publish-all.sh --dry-run. Imprime una líneaPLANpor laboratorio (lo que se subirá u omitirá, si tienelab.json), líneasATTENTIONpara laboratorios que no puede publicar (archivo faltante, sin fast-start, sinlab.config.json) y líneasNOTEpara entradas del catálogo sin proyecto. El código de salida 2 significa que hay al menos unaATTENTION. Corrige cada una (escribelab.config.json, ejecutanode engine/cli.mjs <slug> player, crea el póster, ...) y repite hasta que no haya ninguna, o dile al usuario qué laboratorio se omite y por qué. Muéstrale al usuario el plan en pocas líneas, incluyendo qué videos se subirán y su tamaño.- Un laboratorio sin carga registrada (falta
state/<slug>.sha256) se sube. Si el usuario dice que R2 ya tiene exactamente ese archivo, usa--adopt <slug>para registrar su hash en lugar de subirlo.--force-uploadvuelve a subir todo; úsalo solo cuando el usuario pida reemplazar un video (una re-subida puede permanecer en caché hasta 24h para los espectadores).
- Un laboratorio sin carga registrada (falta
- Sincronizar.
scripts/publish-all.sh(mismas banderas). Por cada laboratorio listo, primero comprime el renderizado aout/<slug>.web.mp4(scripts/compress-mp4.sh: AAC mono 64k + x264 CRF 28, aproximadamente -65% de tamaño, ~5 min por 12 min de video, almacenado en caché mientras el renderizado no cambie; el renderizado en sí nunca se modifica), luego sube esa copia web a R2 si cambió, agrega/actualiza la entrada del catálogo desdelab.config.json, copiachapters.json,poster.jpg,lab.json(se elimina de la carpeta del sitio cuando el laboratorio no tiene ninguno), crea la páginaindex.htmlpara un laboratorio nuevo (a partir de la plantilla compartida, con título y descripción), registra el hash del video enstate/<slug>.sha256y actualizaminutes/lessonsensite/labs.json. Las subidas ocurren aquí, antes de que se envíe nada, por lo que la página nunca se publica sin su video. Es seguro volver a ejecutarlo. - Revisar y confirmar. Primero ejecuta
scripts/check-secrets.sh(falla si un valor de.envaparece en algún archivo, si algún archivo asigna un valor a una variable de clave API, token o contraseña, o si hay una clave privada presente) y corrige lo que reporte antes de continuar. Muéstrale al usuariogit statusy un resumen de diferencias del repositorio videolabs (laboratorios nuevos/cambiados,labs.json,state/y cualquier cambio en el código compartido del reproductor, ver más abajo). Si el laboratorio responde a una solicitud de video de GitHub (un issue etiquetado comovideo-request), ponCloses #Nen el cuerpo del mensaje de confirmación para que el push amainlo cierre. Confirma todo, incluyendolabs/*/audio/cuando haya cambiado (mensaje comoPublish labs: ceph-first-steps (new), kafka-in-a-nutshell (lab page), con la línea Co-Authored-By del recordatorio de atribución de la sesión) ygit push origin main(el remoto SSH está configurado). Si el árbol de trabajo tiene cambios en el código compartido del reproductor que no fueron parte de esta solicitud, pregunta antes de incluirlos. - Desplegar. Espera a que la ejecución de GitHub Actions termine (
curl -s https://api.github.com/repos/bigzaqui/videolabs/actions/runs?per_page=1, verificastatus/conclusion; consulta cada ~20 s hasta ~3 min). Si falla, repórtalo y no lo reintentes a ciegas; un error de secreto faltante significa que los secretos del repositorioCLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_IDnecesitan atención. - Verificar cada laboratorio en
site/labs.json(no solo el nuevo):/devuelve 200 y los lista;/labs/<slug>/devuelve 200;/labs/<slug>/chapters.jsondevuelve JSON (no el fallback HTML: el sitio responde 200 para rutas desconocidas, así que verifica el tipo de contenido o el cuerpo);/labs/<slug>/lab.jsondevuelve JSON para los laboratorios que lo tienen;/media/<slug>/<slug>.mp4devuelve 401 sin sesión (prueba que la puerta está activa). La reproducción en sí necesita una sesión de navegador con la verificación de Turnstile, así que di que no se reprodujo. Reporta las URLs:https://videolabs.pages.dev/labs/<slug>/.
Para publicar solo un laboratorio (raro), ejecuta scripts/publish-lab.sh <lab-dir> <slug> "<title>" "<description>" y actualiza site/labs.json manualmente, luego continúa con el paso 3.
Código compartido
site/labs/kafka-in-a-nutshell/index.html es la plantilla de página copiada para cada laboratorio nuevo (título, encabezado y descripción provienen de site/labs.json en tiempo de ejecución), site/lab.js renderiza los recursos del laboratorio cuando un laboratorio tiene lab.json, site/gate.js es la verificación de Turnstile. Cambiarlos afecta a todos los laboratorios en el próximo push, así que compruébalos primero con un laboratorio existente. Los laboratorios existentes mantienen su propia copia de index.html; un cambio en la plantilla los alcanza solo si su copia también se actualiza.