Communitygithub.com

bigzaqui/videolabs

使用 Remotion + ElevenLabs 製作約 30 分鐘的技術影片課程,風格為 Omarchy / Tokyo Night 終端機(Waybar、並排視窗、oh-my-zsh 提示符號、Markdown 標題),所有螢幕元素會與旁白同步出現,包含句子停頓、純字幕、快速遠端渲染,以及附章節的網頁播放器。若主題可實作,會先建立真實實驗環境(qemu/KVM 虛擬機器),並在影片中使用實際指令輸出。將結果發佈到 videolabs 網站(Cloudflare)則由 videolabs_publish 技能處理。

videolabs 是什麼?

videolabs 是一個技術影片製作技能,專為 Claude Code、Cursor 等 AI 代理工具設計,能根據使用者需求產生解說、課程、訓練或實作影片。其核心流程是先與使用者協商大綱與腳本,接著自動執行付費 ElevenLabs 語音合成、提示同步稽核、遠端渲染及最終發佈。支援 Remotion 與 ElevenLabs 工具鏈,並可整合 qemu/KVM 虛擬機器以產生真實指令輸出。結果為約 30 分鐘的影片,採用 Omarchy / Tokyo Night 終端機風格,所有元素與旁白精準同步,並可透過 videolabs_publish 技能發佈到 Cloudflare 網站。

相容平台✓Claude Code✓Codex CLI✓Cursor
npx skills add https://github.com/bigzaqui/videolabs/tree/HEAD/skills/videolabs_create-video

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

videolabs:建立影片(終端機課程風格)

所有內容都存放在同一個儲存庫 /opt/opus/videolabs(github.com/bigzaqui/videolabs,公開:絕不提交憑證;提交前請執行 scripts/check-secrets.sh)。此技能的原始碼位於該儲存庫的 skills/videolabs_create-video/ 中,並由 scripts/setup.sh 連結至 ~/.claude/skills。其設定值(ElevenLabs 和 Cloudflare 金鑰、渲染主機)位於 git 忽略的儲存庫根目錄 .env,請參閱 .env.example。

儲存庫包含:一個通用引擎(Remotion + ElevenLabs 工具,執行 npm ci)和 labs/ 下每個實驗的獨立資料夾。用於「kafka - 快速入門」(26 課 / 18 分鐘)、「ceph - 第一步」(14 課 / 11.6 分鐘),以及早期的「ceph 快速入門」(41 課 / 30 分鐘;其腳本和視覺效果保留在 reference/ 中,作為卡片、比較、量表、樹狀圖、事件、狀態和網站的範例)。這兩個現有實驗都是實作型:每個指令都先在真實實驗環境中執行過(請參閱「真實實驗」)。

/opt/opus/videolabs/
  engine/                       通用工具:engine/cli.mjs <lab> <command>、src/(Remotion)、scripts/
  labs/<slug>//
    lab.config.json             目錄條目(標題、描述、標籤)+ 外觀(品牌、標誌、狀態列、工具名稱、範例片段)
    script/script.md            旁白,每個 ### 標題為一個場景
    visuals.ts                  每個場景顯示的內容 + 提示覆寫
    lab/                        create-lab.sh、destroy-lab.sh、cap.sh、captures/、lab-meta.json
    audio/raw/                  ElevenLabs 輸出(付費;提交至 git)
    out/ data/ public/voiceover/  產生內容,git 忽略
  site/  scripts/publish-all.sh  state/    網站及其發佈(技能 videolabs_publish)

script.md ──cli scenes──▶ data/scenes.json
   └─ cli tts(ElevenLabs 文字計時) ─▶ audio/raw ──pace──▶ public/voiceover/* + data/{durations,captions}.json
visuals.ts + engine/src/cues.ts(提示 = 當該詞語被念出時) ─▶ Remotion ──cli render──▶ out/<slug>.mp4
cli player ─▶ out/player/{chapters.json,lab.json} ──videolabs_publish──▶ videolabs.pages.dev

所有指令:node engine/cli.mjs <lab> <scenes|tts|pace|cues|stills|typecheck|studio|sample|render|player>,以及 list 和 new <slug>(儲存庫的 README.md 中有表格)。實驗資料夾是各課程之間唯一不同的部分;請勿將引擎程式碼複製到實驗中。

工作流程(與使用者協商大綱和腳本;之後的所有步驟無需請求即可執行)

使用者的常駐授權:一旦腳本確定,即可執行付費 ElevenLabs tts、提示稽核、在渲染主機上進行渲染、播放器/海報步驟以及實驗環境拆除,無需再為每個步驟請求許可。之後報告結果和新的影片長度。僅在遇到此工作流程以外的事項時才停下來詢問(例如,對實驗未建立的資源進行破壞性操作,或在使用者未要求的情況下發佈到網站)。

  1. 是實作主題?先建立並執行真實實驗環境(請參閱下面的「真實實驗」)。切勿憑記憶撰寫指令輸出:ceph-first-steps 腳本的初稿在真實叢集上執行後,有十處錯誤。然後根據實際發生的情況編寫腳本。
  2. 先寫腳本,再製作影片。 提議一個大綱(模組 → 課程,並規劃每個課程的圖表),獲得同意後,再編寫 labs/<slug>/script/script.md。修改文字比重新產生音訊便宜得多。以速度 1.0 標記,停頓約等於 160 wpm:1,500 字約等於 9.5 分鐘(含模組卡片);速度 1.08 約等於 168 wpm。在 tts 之後立即檢查 Paced … total X min 行的實際長度,並在渲染前進行調整。對於版本特定的指令,請先檢查當前版本(文件和專案的下載/映像標籤)。格式(由 engine/scripts/build-scenes.mjs 解析):
    ## 模組 1 — 核心架構
    ### S02 · RADOS
    **視覺效果:** 給設計師的備註
    **指令:** `ceph -s` `ceph osd tree`(可選,僅顯示在螢幕上)
    **旁白:**
    一段文字,專為口語朗讀而寫。以口語方式拼寫指令(「ceph dash s」)。
    
    在模組的最後一堂課結尾加上「Module takeaway: …」— 單詞 takeaway 會觸發 takeaways 視窗。
  3. node engine/cli.mjs new <slug> 會建立 labs/<slug>/ 的結構(設定檔、一個三場景的腳本、一個 visuals.ts);填寫 lab.config.json(目錄的標題、描述、標籤;以及外觀的 brand、user、logo、statusbar、statusCmd、networkLabels、session、tools、sample)並執行 node engine/cli.mjs <slug> scenes。
  4. 視覺效果 在 labs/<slug>/visuals.ts 中(類型在 engine/src/types.ts 中,colors 來自 @engine/theme),每個場景 ID 對應一個條目。圖表類型(engine/src/components/Diagrams.tsx):
    • topology:主機(名稱、IP、守護程序晶片、磁碟/副本)位於一條或兩條網路上,可選的狀態列(statusCmd 標籤,預設來自設定檔),以及 flows(在主機之間移動的區塊,從 cue 開始,直到 until)。任何主機/守護程序/磁碟/狀態都可以有 cue(當被念出時出現)和 changes: [{cue, state, label}](磁碟 empty|osd|leader|idle|down|destroyed|new,主機 ok|spare|down|maint)。沒有提示的元素從一開始就可見。使用輔助函數(host(n)、built(n))建立實驗狀態,以便圖表逐課建構。
    • session:一個逼真的 Shell;每個 cmd 在被念出時會自行輸入,然後輸出 out 行;保留最新的行數。host 設定整行的提示符號(預設來自設定檔中的 session.prompt)。可選的緊湊型 topology 位於其上方。對於場景場景,底部的指令列被隱藏。 其他類型:title(fastfetch 卡片;user、額外的 rows)、layers、cards、flow、tree、compare、gauge、terminal(帶有標註的指令輸出)、incident(症狀/檢查/操作)、checklist、states、sites;每個場景可選的 takeaway 和 commandCues。對每個 out 和 symptom 使用 lab/captures/ 中的真實輸出。
  5. 在付費取得音訊前審查視覺效果:node engine/cli.mjs <slug> stills(每個場景一張畫面,比例 60%;S04,S11 --at=12.5 指定時間點)並使用 ffmpeg xstack 拼貼成 2×2 的聯絡表以便檢視。檢查溢出、換行和空白版面。
  6. 語音:在儲存庫根目錄的 .env 中設定 ELEVENLABS_API_KEY / ELEVENLABS_VOICE_ID,然後執行 node engine/cli.mjs <slug> tts(直接執行,無需批准;會略過已存在的檔案;使用 --only=S03,S04 --force 只重新生成旁白有變動的場景,也可節省點數)。它會自動執行 pace。當腳本變長時,告知使用者新的長度。提交 labs/<slug>/audio/(付費輸出)。
  7. 同步稽核:node engine/cli.mjs <slug> cues(在變更任何指令後,也要變更其 commandCues 條目:為 dmesg 設計的晶片卻仍然提示在「smartctl」上,這是一個無聲的不匹配)— 列出揭示每個元素和每個指令行的詞語(MISS = 分散在相鄰元素之間)。使用提示覆寫(如下)修正錯誤的匹配。在旁白或語音變更後重新執行。
  8. 預覽:node engine/cli.mjs <slug> sample(在渲染伺服器上約 1 分鐘),使用 ffmpeg -ss <t> -frames:v 1 和 volumedetect 檢查影格以確保音量(無削波:最大值 < -1 dB)。
  9. 渲染 完整課程(遠端,見下文),然後 node engine/cli.mjs <slug> player,製作海報 labs/<slug>/out/spot.jpg,銷毀實驗 VM,並使用 videolabs_publish 技能發佈整個網站。

使用者已簽署的設計規則

  • 外觀:Omarchy/Hyprland 桌面,Tokyo Night 調色板(src/theme.ts;語意名稱如 rados、mon、cephfs 只是調色板插槽)。Waybar 狀態列,模組作為工作區 0–7,一個狀態(疑難排解模組上的 HEALTH_WARN),課程計數器 07/41。一個並排視窗,2px 方形邊框,無圓角/發光/漸層。每堂課以輸入型 robbyrussell 提示符號 ➜ module-1-core-architecture git:(s03) cat the-daemons.md 開頭,然後是 # 標題。備註顯示為 // 註解,指令顯示為 ❯ cmd 行,takeaways 顯示為浮動視窗 cat sre-takeaway.md,模組分隔線顯示為 cd module-N-… + 大字型標題,開場為 fastfetch。全部使用 JetBrains Mono;Inter 僅用於字幕。它取代了使用者不喜歡的「通用」深色漸層外觀。
  • 提示同步:絕不按時間交錯。每個元素在旁白首次說出其名稱時出現(engine/src/cues.ts:最長的有意義標記、前綴詞幹、從上一個提示向前搜尋)。在實驗的 visuals.ts 中進行覆寫:
    • cue: "=managers" 確切的口語詞語(忽略連字號/標點符號:"=write-ahead"),cue: null = 無詞語,內插。
    • pointCues(比較側)、noteCue(樹狀圖)、linkCue(網站)、cues(標題徽章)、commandCues(指令行,每個場景)。
    • cueLabels() 中的標籤順序必須與 engine/src/components/Visuals.tsx 中渲染器使用的索引順序相符(topology/session 使用 topologyKeys/sessionKeys 中的鍵值遍歷)。
    • 一個向前游標會遍歷場景的所有標籤,因此後面的標籤如果重複使用常見詞語(「three」、「recovery」、「add」),可能會落在後面的出現位置。偏好使用在該時刻附近只出現一次的詞語(「=repeat」、「=begins」),並且務必閱讀 cues 稽核。
  • 字幕:純文字短語,在句子/子句結尾處換行,每行 ≤ 64 個字元,無逐字卡拉 OK 高亮(「令人疲憊不堪」)。
  • 呼吸:engine/scripts/pace.mjs 在原始 ElevenLabs 音訊中的 . ? ! 之後插入 250 ms,在 : ; 之後插入 120 ms,並移動詞語計時。剪切點來自 ffmpeg silencedetect(嚴格 -38 dB/40 ms,然後 -30 dB/20 ms),否則選擇最安靜的 5 ms 視窗,並使用 8 ms 淡入淡出 — 絕不單獨使用 ElevenLabs 詞語邊界(這些邊界會落在詞語內部)。調整 SENTENCE_PAUSE/CLAUSE_PAUSE,重新執行 node engine/cli.mjs <slug> pace(免費;原始音訊保留在 audio/raw/ 中)。速度調整取決於 ffmpeg 版本(7.1.5 和 8.0.1 對同一段 Kafka 音訊分別產生了 17.9 和 17.8 分鐘的速度):請在渲染的位置進行速度調整,或將 data/ 和 public/voiceover/ 複製到渲染主機。
  • 轉場:透過 @remotion/transitions TransitionSeries 實現 15 影格的交叉淡入淡出;它們僅重疊靜音前導(0.4 秒)/ 尾聲(0.8 秒)。engine/src/timeline.ts 減去重疊部分;engine/scripts/player.mjs 和 stills.mjs 鏡像這些常數 — 請保持同步。
  • 使用者選擇的語音:ElevenLabs「Mark」v3p1kjzUvro6S76qmYmH(語音庫;雖然 GET /v1/voices/{id} 會回傳 404,但仍可用於 TTS)、eleven_multilingual_v2、速度 1.08、with-timestamps 端點、previous_text/next_text 以保持連續性。在完整執行前,務必先用一個句子的 TTS 呼叫驗證語音 ID(之前 .env 中的某個 ID 被截斷了)。

每個課程的設定(labs//lab.config.json)

Waybar 中的工作區以及 fastfetch 模組/課程計數會自動跟隨場景。其他課程特定的內容都是設定檔中的資料,而非程式碼:brand(Waybar 名稱)、user(標題卡上的提示符號)、logo(五行程式碼字母)、statusbar(ok/warn 文字、right 文字、warnModule = 顯示警告的模組)、statusCmd 和 networkLabels(topology 場景的預設值)、session.prompt/session.title(終端機工作階段)、tools(自動提示指令行時跳過的指令詞語)、sample(範例片段的場景 ID),以及目錄的 title、description、tags。具有不同外觀的新實驗無需修改引擎;新的圖表類型或狀態則需要(engine/src/types.ts、components、cues.ts),但之後所有實驗都能受益。

採用的 Remotion 實踐(來自 remotion-* 技能)

字型透過 @remotion/google-fonts(絕不依賴系統字型);<Audio> 來自 @remotion/media 並搭配 from;TransitionSeries;calculateMetadata 根據音訊持續時間調整組合大小;使用 interpolate/Easing.bezier 和 translate 進行動畫(無 CSS 轉場)。刻意未採用:Interactive.create/連線組合(僅在 Studio 中手動編輯時有用)、大型社交影片文字最小尺寸、meme 音效。

渲染

  • VIDEOLABS_RENDER_HOST(渲染和實驗伺服器的 SSH 目標,金鑰已設定)來自儲存庫根目錄的 .env:在執行下列指令前,執行 set -a; . /opt/opus/videolabs/.env; set +a,並在您提交的任何內容中寫入該變數,而非文字地址。同一台主機執行實驗 VM。
  • TMPDIR=/var/tmp 由 CLI 設定:/tmp 在這些主機上是一個小的 RAM tmpfs,長時間的音訊混合會在最後一刻因「裝置上無剩餘空間」而失敗。
  • 本地機器(4 vCPU)約需 45 分鐘來處理 30 分鐘的影片。遠端渲染伺服器 $VIDEOLABS_RENDER_HOST(Ubuntu 26.04、24 執行緒、31 GB RAM、RTX 3090 Ti、KVM;Node 22、ffmpeg、rsync 以及來自 apt 的 Chromium 函式庫)以 12–16 的並行度在 3 分鐘內渲染 11.6 分鐘的 ceph 課程,並在 5 分鐘內渲染 18 分鐘的 kafka 課程。儲存庫位於兩台機器的 /opt/opus/videolabs。流程:
    rsync -az --delete --exclude node_modules --exclude out --exclude .env --exclude .git --exclude site --exclude state ./ $VIDEOLABS_RENDER_HOST:/opt/opus/videolabs/   # 從 /opt/opus/videolabs
    ssh $VIDEOLABS_RENDER_HOST 'cd /opt/opus/videolabs/engine && npm ci && cd .. && node engine/cli.mjs <slug> scenes && node engine/cli.mjs <slug> pace && node engine/cli.mjs <slug> render --concurrency=12 --log=error'
    rsync -a $VIDEOLABS_RENDER_HOST:/opt/opus/videolabs/labs/<slug>/out/<slug>.mp4 labs/<slug>/out/ && node engine/cli.mjs <slug> player
    
    (為了保持與您審查過的計時完全相同,請 rsync labs/<slug>/data 和 public/voiceover,而不是在伺服器上執行 scenes/pace。)切勿將 .env 複製到那裡。以分離模式執行長時間渲染(使用 ssh -f -n 啟動的 nohup bash script &),並使用 time 的 real 行上的 Monitor 等待;不要 grep 日誌中的「error」(指令列已有 --log=error)。如果 Waybar/圖表程式碼發生變更,請檢查兩個實驗(stills),因為它們共享該程式碼。
  • 驗證引擎變更:使用新舊程式碼渲染範例片段,並比較 ffmpeg -i a.mp4 -i b.mp4 -lavfi ssim -f null -;重新生成的 scenes/durations/captions.json 和 cues 稽核必須…

[後續內容已截斷,等待翻譯]

Individual skills in this repo

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

相關技能