Communitygithub.com

bigzaqui/videolabs

发布整个 videolabs 网站 (https://videolabs.pages.dev):同步仓库中 labs 文件夹下的每个实验室到网站(仅当视频发生变化时才上传到 Cloudflare R2、播放器资源、实验室资源、目录),提交并推送 videolabs 仓库,以便 GitHub Actions 部署到 Cloudflare Pages,然后验证每个实验室。当用户想要发布、部署、添加、更新或重新上传视频实验室到 videolabs.pages.dev 时使用。一次运行会发布所有实验室,而不仅仅是一个。

videolabs 是什么?

该技能用于全量发布 videolabs 网站,每次部署均包含所有实验室。它通过一个编排脚本执行完整的工作流程:首先在计划阶段(dry-run)检查每个实验室的必备文件(如 fast-start MP4、章节 JSON、海报图片、lab.config.json),并报告缺失或错误;然后在上传阶段自动压缩渲染视频(使用 x264 CRF 28 + mono AAC 64k,节省约 65% 大小),仅在上传内容变化时才同步到 Cloudflare R2 私有存储桶,同时更新网站目录、章节文件、海报和实验室页面;接着会运行秘密检查脚本防止任何真实凭据泄露,并在提交时以描述性信息(包含 `Closes #N` 用于关闭 GitHub 视频请求 issues)提交所有变更;最后,它会等待 GitHub Actions 部署成功(轮询约 3 分钟),并验证每个实验室的页面(主页、实验室详情页、章节 JSON、实验室资源 JSON)以及媒体网关是否正常工作(无会话返回 401)。该技能支持 Cloudflare R2、GitHub Actions 和 Cloudflare Pages 平台,可安全重复运行,不会重复上传相同哈希的视频。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/bigzaqui/videolabs/tree/HEAD/skills/videolabs_publish

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

发布 videolabs 网站

“发布”意味着整个站点每次部署都会包含所有实验室。

站点仓库:/opt/opus/videolabs (github.com/bigzaqui/videolabs,推送到 main 时部署到 https://videolabs.pages.dev;GitHub Actions 发布 site/ 文件夹)。 实验室:/opt/opus/videolabs/labs/<slug>/(每个实验室一个文件夹,位于同一仓库;slug 是 MP4 文件名 out/<slug>.mp4)。它们通过 videolabs_create-video 技能构建(node engine/cli.mjs <slug> ...)。 视频存储在私有 R2 存储桶 videolabs 中,路径为 <slug>/<slug>.mp4,通过 /media/<slug>/<slug>.mp4 提供服务,该路径受 Turnstile 会话保护(没有会话的请求返回 401)。 凭据:/opt/opus/videolabs/.env(由脚本加载;模板为 .env.example)。切勿打印、复制或提交密钥。GitHub 仓库是公开的(用户对此可以接受,因为旁白音频、脚本、截图和实验室输出都将公开,并且不介意已销毁实验室的临时密码出现在那里),因此任何文件中都不能出现真正的凭据。此技能的源代码位于仓库的 skills/videolabs_publish/ 中,通过 scripts/setup.sh 链接到 ~/.claude/skills。

实验室需要的内容(由脚本检查)

  • out/<slug>.mp4(快速启动:moov 在 mdat 之前;使用 ffmpeg -i in.mp4 -c copy -movflags +faststart out.mp4 修复),out/player/chapters.json(node engine/cli.mjs <slug> player),out/spot.jpg(海报;使用 ffmpeg -ss 425 -i out/<slug>.mp4 -frames:v 1 -q:v 3 out/spot.jpg 抓取一个图表帧)。
  • 可选 out/player/lab.json(当实验室有 lab/lab-meta.json、lab/*.sh、lab/captures/ 时,来自 node engine/cli.mjs <slug> player)。如果存在,site/lab.js 会在实验室页面上显示实验室资源。如果截图或 lab-meta.json 发生变化,请先重新运行 node engine/cli.mjs <slug> player。
  • labs/<slug>/lab.config.json 包含 title、description 和 tags。脚本会据此添加或更新 site/labs.json 中的条目(并填充 minutes 和 lessons),因此切勿手动编辑目录。对于新实验室,如果脚本中明确,则使用其标题/描述/标签;否则询问用户。切勿静默地凭空编造它们。

步骤

  1. 计划 cd /opt/opus/videolabs && scripts/publish-all.sh --dry-run。它会为每个实验室打印一行 PLAN(将上传或跳过什么,是否有 lab.json),为无法发布的实验室打印 ATTENTION 行(缺少文件、不是 fast-start、没有 lab.config.json),以及为没有项目的目录条目打印 NOTE 行。退出代码 2 表示存在至少一个 ATTENTION。逐一修复每个问题(编写 lab.config.json,运行 node engine/cli.mjs <slug> player,制作海报……)并重复,直到没有错误,或告知用户哪个实验室被遗漏以及原因。用几行向用户展示计划,包括将上传哪些视频以及它们的大小。
    • 没有已记录的上传(缺少 state/<slug>.sha256)的实验室将被上传。如果用户说 R2 中已有完全相同的文件,请使用 --adopt <slug> 记录其哈希值而不是上传。--force-upload 会重新上传所有内容;仅在用户要求替换视频时使用(重新上传后,查看者可能最多会看到 24 小时的缓存)。
  2. 同步 scripts/publish-all.sh(相同的标志)。对于每个准备好的实验室,它首先将渲染压缩为 out/<slug>.web.mp4(scripts/compress-mp4.sh:单声道 AAC 64k + x264 CRF 28,大小约减少 65%,每 12 分钟视频约需 5 分钟,当渲染未更改时会缓存;渲染本身永不修改),然后如果发生更改,将该 Web 副本上传到 R2,根据 lab.config.json 添加/更新目录条目,复制 chapters.json、poster.jpg、lab.json(当实验室没有时,从站点文件夹中移除),为新实验室创建页面 index.html(使用共享模板,包含标题和描述),在 state/<slug>.sha256 中记录视频哈希,并刷新 site/labs.json 中的 minutes/lessons。上传在此处完成,先于任何推送,因此页面在没有视频的情况下永远不会上线。可以安全地再次运行。
  3. 审查和提交 首先运行 scripts/check-secrets.sh(如果 .env 中的值出现在任何文件中,如果某个文件为 API 密钥、令牌或密码变量分配了值,或者存在私钥,则会失败)并修复其报告的问题,然后再继续。向用户展示 git status 和 videolabs 仓库的 diff 摘要(新增/更改的实验室、labs.json、state/ 以及对共享播放器代码的任何更改,见下文)。如果实验室回答了 GitHub 视频请求(标记为 video-request 的 issue),请在提交消息正文中添加 Closes #N,以便推送到 main 时关闭该 issue。提交所有内容,包括更改后的 labs/*/audio/(消息类似于 Publish labs: ceph-first-steps (new), kafka-in-a-nutshell (lab page),并包含会话归属提醒中的 Co-Authored-By 行)并执行 git push origin main(已设置 SSH 远程)。如果工作树中对共享播放器代码的更改不属于此请求,请先询问是否包含它们。
  4. 部署 等待 GitHub Actions 运行完成(curl -s https://api.github.com/repos/bigzaqui/videolabs/actions/runs?per_page=1,检查 status/conclusion;大约每 20 秒轮询一次,最多约 3 分钟)。如果失败,报告它并且不要盲目重试;缺失密钥的错误意味着需要处理仓库密钥 CLOUDFLARE_API_TOKEN / CLOUDFLARE_ACCOUNT_ID。
  5. 验证 site/labs.json 中的每个实验室(不仅仅是新的):/ 返回 200 并列出它们;/labs/<slug>/ 返回 200;/labs/<slug>/chapters.json 返回 JSON(不是 HTML 后备方案:站点对未知路径返回 200,因此请检查内容类型或正文);/labs/<slug>/lab.json 为拥有该文件的实验室返回 JSON;/media/<slug>/<slug>.mp4 在没有会话时返回 401(证明网关已启动)。播放本身需要带有 Turnstile 检查的浏览器会话,因此说明它未被播放。报告 URL:https://videolabs.pages.dev/labs/<slug>/。

要仅发布一个实验室(很少见),运行 scripts/publish-lab.sh <lab-dir> <slug> "<title>" "<description>" 并手动更新 site/labs.json,然后继续执行步骤 3。

共享代码

site/labs/kafka-in-a-nutshell/index.html 是每个新实验室复制的页面模板(标题、标题行和描述在运行时来自 site/labs.json),site/lab.js 在实验室有 lab.json 时渲染实验室资源,site/gate.js 是 Turnstile 检查。更改它们会影响下次推送时的每个实验室,因此请首先对照现有实验室检查它们。现有实验室会保留自己的 index.html 副本;模板更改只有在它们的副本也更新时才会影响到它们。

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相关技能