Veröffentliche die Videolabs-Seite
„Veröffentlichen“ bedeutet, dass die gesamte Seite mit allen Labs jedes Mal bereitgestellt wird.
Site-Repo: /opt/opus/videolabs (github.com/bigzaqui/videolabs, deployed auf https://videolabs.pages.dev bei Push auf main; GitHub Actions veröffentlicht den Ordner site/).
Labs: /opt/opus/videolabs/labs/<slug>/ (ein Ordner pro Lab, im selben Repo; der Slug ist der MP4-Name out/<slug>.mp4). Sie werden mit der Fertigkeit videolabs_create-video erstellt (node engine/cli.mjs <slug> ...).
Videos befinden sich im privaten R2-Bucket videolabs unter <slug>/<slug>.mp4 und werden über /media/<slug>/<slug>.mp4 ausgeliefert, das sich hinter einer Turnstile-Sitzung befindet (eine Anfrage ohne Sitzung gibt 401 zurück).
Anmeldeinformationen: /opt/opus/videolabs/.env (wird von den Skripten geladen; Vorlage .env.example). Gib niemals Geheimnisse aus, kopiere sie oder committe sie. Das GitHub-Repo ist öffentlich (der Benutzer hat nichts dagegen, dass Erzähl-Audio, Skripte, Aufnahmen und Lab-Ausgaben dort erscheinen, und stört sich nicht an Wegwerf-Passwörtern zerstörter Labs), daher darf keine echte Anmeldeinformation in irgendeiner Datei auftauchen. Der Quellcode dieser Fertigkeit befindet sich in skills/videolabs_publish/ im Repo und wird durch scripts/setup.sh in ~/.claude/skills verlinkt.
Was ein Lab benötigt (vom Skript geprüft)
out/<slug>.mp4(Fast-Start:moovvormdat; korrigieren mitffmpeg -i in.mp4 -c copy -movflags +faststart out.mp4),out/player/chapters.json(node engine/cli.mjs <slug> player),out/spot.jpg(Poster; ein Diagramm-Bild extrahieren mitffmpeg -ss 425 -i out/<slug>.mp4 -frames:v 1 -q:v 3 out/spot.jpg).- Optional
out/player/lab.json(vonnode engine/cli.mjs <slug> player, wenn das Lablab/lab-meta.json,lab/*.sh,lab/captures/hat). Falls vorhanden, zeigtsite/lab.jsdie Lab-Ressourcen auf der Lab-Seite an. Führe zuerstnode engine/cli.mjs <slug> playererneut aus, wenn sich Aufnahmen oderlab-meta.jsongeändert haben. labs/<slug>/lab.config.jsonmittitle,descriptionundtags. Das Skript fügt den Eintrag insite/labs.jsonhinzu oder aktualisiert ihn (und fülltminutesundlessonsaus), bearbeite den Katalog also nie von Hand. Für ein neues Lab übernimm Titel/Beschreibung/Tags aus dem Lab-Skript, falls klar, ansonsten frage den Benutzer. Erfinde sie niemals stillschweigend.
Schritte
- Planung.
cd /opt/opus/videolabs && scripts/publish-all.sh --dry-run. Es gibt einePLAN-Zeile pro Lab aus (was hochgeladen oder übersprungen wird, ob eslab.jsonhat),ATTENTION-Zeilen für Labs, die nicht veröffentlicht werden können (fehlende Datei, nicht Fast-Start, keinelab.config.json) undNOTE-Zeilen für Katalogeinträge ohne Projekt. Exit-Code 2 bedeutet, dass es mindestens eineATTENTIONgibt. Behebe jede einzelne (schreibelab.config.json, führenode engine/cli.mjs <slug> playeraus, erstelle das Poster, ...) und wiederhole den Vorgang, bis es keine mehr gibt, oder teile dem Benutzer mit, welches Lab ausgelassen wird und warum. Zeige dem Benutzer den Plan in wenigen Zeilen an, einschließlich welche Videos hochgeladen werden und deren Größe.- Ein Lab ohne aufgezeichneten Upload (
state/<slug>.sha256fehlt) wird hochgeladen. Wenn der Benutzer sagt, dass R2 bereits genau diese Datei enthält, verwende--adopt <slug>, um seinen Hash aufzuzeichnen, anstatt hochzuladen.--force-uploadlädt alles erneut hoch; verwende es nur, wenn der Benutzer darum bittet, ein Video zu ersetzen (ein erneuter Upload kann bis zu 24 Stunden zwischengespeichert bleiben).
- Ein Lab ohne aufgezeichneten Upload (
- Synchronisation.
scripts/publish-all.sh(gleiche Flags). Für jedes bereite Lab komprimiert es zuerst den Render zuout/<slug>.web.mp4(scripts/compress-mp4.sh: Mono AAC 64k + x264 CRF 28, etwa -65% Größe, ~5 Min pro 12 Min Video, zwischengespeichert solange der Render unverändert ist; der Render selbst wird nie modifiziert), lädt dann diese Web-Kopie zu R2 hoch, wenn geändert, fügt den Katalogeintrag auslab.config.jsonhinzu/aktualisiert ihn, kopiertchapters.json,poster.jpg,lab.json(aus dem Site-Ordner entfernt, wenn das Lab keines hat), erstellt die Seiteindex.htmlfür ein neues Lab (aus der gemeinsamen Vorlage, mit Titel und Beschreibung), zeichnet den Video-Hash instate/<slug>.sha256auf und aktualisiertminutes/lessonsinsite/labs.json. Die Uploads erfolgen hier, bevor etwas gepusht wird, sodass die Seite niemals ohne ihr Video live geht. Es ist sicher, das Skript erneut auszuführen. - Überprüfen und committen. Führe zuerst
scripts/check-secrets.shaus (es schlägt fehl, wenn ein Wert aus.envin einer Datei erscheint, wenn eine Datei einen Wert einer API-Key-, Token- oder Passwort-Variable zuweist, oder wenn ein privater Schlüssel vorhanden ist) und behebe alles, was es meldet, bevor du fortfährst. Zeige dem Benutzergit statusund eine Diff-Zusammenfassung des Videolabs-Repos (neue/geänderte Labs,labs.json,state/und alle Änderungen am gemeinsamen Player-Code, siehe unten). Wenn das Lab eine GitHub-Videoanfrage beantwortet (ein Issue mit dem Labelvideo-request), fügeCloses #Nin den Commit-Nachrichtentext ein, damit der Push aufmaines schließt. Committe alles, einschließlichlabs/*/audio/, wenn es sich geändert hat (Nachricht wiePublish labs: ceph-first-steps (new), kafka-in-a-nutshell (lab page), mit der Co-Authored-By-Zeile aus der Sitzungs-Attributionserinnerung) undgit push origin main(SSH-Remote ist eingerichtet). Wenn der Arbeitsbaum Änderungen am gemeinsamen Player-Code enthält, die nicht Teil dieser Anfrage waren, frage, bevor du sie einbeziehst. - Bereitstellen. Warte auf den GitHub Actions-Durchlauf (
curl -s https://api.github.com/repos/bigzaqui/videolabs/actions/runs?per_page=1, überprüfestatus/conclusion; poll ungefähr alle 20 s bis zu ~3 Min). Wenn es fehlschlägt, melde es und versuche es nicht blind erneut; ein Fehler wegen fehlender Geheimnisse bedeutet, dass die Repository-GeheimnisseCLOUDFLARE_API_TOKEN/CLOUDFLARE_ACCOUNT_IDAufmerksamkeit benötigen. - Überprüfe jedes Lab in
site/labs.json(nicht nur das neue):/gibt 200 zurück und listet sie auf;/labs/<slug>/gibt 200 zurück;/labs/<slug>/chapters.jsongibt JSON zurück (nicht den HTML-Fallback: die Seite antwortet mit 200 für unbekannte Pfade, überprüfe also den Content-Type oder den Body);/labs/<slug>/lab.jsongibt JSON für Labs zurück, die eines haben;/media/<slug>/<slug>.mp4gibt 401 ohne Sitzung zurück (beweist, dass das Gate aktiv ist). Die Wiedergabe selbst benötigt eine Browser-Sitzung mit der Turnstile-Prüfung, sage also, dass sie nicht abgespielt wurde. Melde die URLs:https://videolabs.pages.dev/labs/<slug>/.
Um nur ein Lab zu veröffentlichen (selten), führe scripts/publish-lab.sh <lab-dir> <slug> "<title>" "<description>" aus und aktualisiere site/labs.json von Hand, fahre dann mit Schritt 3 fort.
Gemeinsamer Code
site/labs/kafka-in-a-nutshell/index.html ist die Seitenvorlage, die für jedes neue Lab kopiert wird (Titel, Überschrift und Beschreibung stammen zur Laufzeit aus site/labs.json), site/lab.js rendert Lab-Ressourcen, wenn ein Lab lab.json hat, site/gate.js ist die Turnstile-Prüfung. Änderungen an ihnen wirken sich beim nächsten Push auf jedes Lab aus, überprüfe sie daher zuerst an einem bestehenden Lab. Bestehende Labs behalten ihre eigene Kopie von index.html; eine Vorlagenänderung erreicht sie nur, wenn auch ihre Kopie aktualisiert wird.