Communitygithub.com

conversational-video-subtitles

為對話/短影音(Reels、Shorts、TikTok、1:1、16:9)燒錄字幕,依據單字時間軸:每個口語單字,固定底部基線,每行置中(無上移、無橫移;與人臉/手部/火焰重疊時記錄為已接受,可選碰撞上移會記錄原因與像素),說話者以顏色強調或細微標記區分,無歌詞彈跳效果,逐幀符合 WCAG 對比度檢查。

conversational-video-subtitles 是什麼?

此技能專為對話式短影音(如 Reels、Shorts、TikTok)以及 1:1 或 16:9 影片設計,提供專業的字幕燒錄解決方案。它能夠根據單字時間軸(例如來自 ElevenLabs Scribe 或 Groq Whisper),將每個口語單字以固定底部基線、置中且不彈跳的方式顯示,並透過顏色或細微標記區分不同說話者。此技能會自動檢查字幕是否與人臉、手部或重要物件重疊,並在固定模式下記錄重疊(非錯誤),或可選用碰撞上移模式安全避開。此外,它會逐幀驗證 WCAG 對比度(≥ 4.5:1),確保字幕清晰可讀。輸出包括 JSON 清單(manifest)、燒錄預覽影片、純文字 SRT、樣式 ASS 及 WebVTT,並附帶驗證器,確保像素級別的正確性。支援的設定檔包括 karaoke、reveal、cards、kinetic 及 hybrid 等模式,適用於不同對話節奏與風格。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add rocketmandrey/conversational-video-subtitles-skill

在你喜歡的 AI 中提問

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

說明文件

對話式影片字幕

概述

字幕是其獨立的層:它承載每個口語單字,絕不依賴畫面中已有的內容。畫面中的事物標籤(零件名稱、優缺點、箭頭)是不同的圖層,應使用不同的視覺語言(物件旁的標註);切勿因為「畫面已顯示」而從字幕中刪除任何單字。

流程:words.json + forbid.json(字幕不得覆蓋的區域) + config.json + 設定檔 → plan → manifest.json(標準資料) → burn(燒錄預覽 = 視覺真相) / export srt|ass|vtt → validate。

格式角色(請勿混淆):

格式承載內容不承載內容
manifest.json單字、時間、佈局、placement、已接受重疊、含原因的上移、渲染檢查:資料真相來源像素
.srt文字 + 時間粗細、顏色、輪廓、作用中單字、位置。SRT 中絕不承諾樣式
.ass字體系列 + 粗體/\b700、轉換為 libass 指標的字體大小、輪廓、背景框、每個時間片段的作用中單字、位置淡入淡出;需要字體:subtitles=x.ass:fontsdir=fonts
.vtt::cue CSS(字體系列、粗細、透過 text-shadow 的輪廓、背景)+ 每個時間片段的類別 .active_<spk> / .em_<spk> / .dim / .u精確位置;頁面需使用 @font-face 載入字體
燒錄 preview.mp4所有內容:唯一的視覺真相來源—

使用時機

  • 對話短劇、訪談、有旁白的解說影片:直式或方形,最多兩行。
  • 您已有單字時間軸(或音訊:可選用環境金鑰的雲端 STT),且知道人臉 / 手部 / 關鍵道具位置(方框;對於 3D 場景,渲染單色遮罩並框選)。
  • 不適用於歌詞影片(刻意不支援彈跳、縮放的單字)。

演算法

分段(設定檔中的 chunk):暫停超過 pause_s(​​0.35 秒)、句子結尾、說話者變換時強制斷開;當一個區塊已有 2 個以上單字時,逗號處軟斷開;受 max_words、像素寬度(安全區的 max_width_frac)和 max_dur_s(約 1.2 秒的語音閱讀效果良好)限制。區塊絕不結尾於功能詞(не、в、а、and、the…):該詞會移至下一個區塊。若同句中的相鄰區塊可容納單一單字,則合併。單字時長被限制為中位數的 2.5 倍,以免單字懸掛在停頓中。時間:一個單元在其第一個單字前 ≤ 50 毫秒出現,不切斷前一個單字,在其最後一個單字後停留 hold_s,至少 min_show_s。

放置 — placement: {mode: fixed_bottom_center, collision_lift: false}(對話預設)

  1. 整個影片使用一條基線:baseline = safe.bottom - baseline_margin_px(或明確設定)。每個單元在其上底部對齊(y + h = baseline)並在畫面上置中(x + w/2 = W/2)。沒有任何移動:無上移、無橫移、無依說話者 x 偏移。行寬受限制,使置中行保持在安全區內。
  2. 在基線處與禁止框交錯的行保持原位:該單元會獲得 overlap_accepted: [classes],QA 工作表會繪製黃色框「重疊已接受(固定基線)」。這是資訊,不是失敗。與平台 UI 交錯仍是錯誤(縮小字體或拆分片語)。
  3. 選項 collision_lift: true(模式 baseline_lift):說話者下方的 x(align: speaker)或置中並有左/右備用;若每個 x 都交錯,則以整個 lift_step_px 步長上移直至空閒。該單元會獲得 lift = {px, reason: [在基線處命中的類別], t0, t1},清單會列出所有上移在 collision_lifts 中。無原因 → 無上移。僅在簡報要求不惜代價保持臉部清晰時使用。
  4. 絕不捨棄任何單字。

外觀。 輪廓(outline_px)+ 柔和陰影 + 淺色背景,其透明度僅提升到足以使最深色的亮色與其後像素的第 90 百分位數保持 ≥ 4.5:1(WCAG)的程度。說話者以作用中單字的顏色區分,並在混合/卡片模式中加上 4 像素的說話者顏色條;無對話氣泡、無厚重名牌。平靜的動畫:僅透明度淡入淡出,無縮放彈出、無垂直滑動。

QA(scripts/validate.py,也可由 demo 執行):

  • 結構:manifest 與 templates/manifest.schema.json 比對;
  • 行數 ≤ 2;
  • 放置:在 fixed_bottom_center 中,所有單元的 y 基線和 x 中心擴散為 0(0.5 像素容差),且無上移;在 baseline_lift 中,每個上移都在網格上、有原因,且該單元在基線處確實交錯;
  • 在每一幀上與平台 UI 零重疊;禁止框:baseline_lift 中為 0,fixed_bottom_center 中報告為 overlap_accepted(資訊);
  • 每個單字恰好一次、按順序、說話時可見;
  • 對比度 ≥ 4.5 且無彈跳,兩者均由 burn 逐幀測量;
  • 字體解析:檔案存在、Pillow 系列和樣式、OS/2 粗細、fc-scan,以及 libass fontselect 選取宣告的檔案和粗細;
  • 像素:在燒錄幀以及 ASS 的 libass 渲染上,作用中顏色存在,字形底部在佈局的 3 像素內,字幹寬度在宣告粗細的參考點陣圖的 1 像素內,且輪廓在 outline_px 的 1 像素內。

設定檔(profiles/*.json)

設定檔內容最佳用途
karaoke一次 2–4 個單字,說話中的單字為說話者顏色,其餘暗淡最穩定;固定行、解說影片
reveal單字在說話時淡入;佈局預先固定;≤ 2 行平靜的旁白
cards每張卡片一個想法(≤ 8 個單字,2 行),密集面板,關鍵字著色緩慢、可引用的台詞;比說話提前閱讀
kinetic一次一個記號,較大字體僅限重點句;上下文少
hybrid(預設)≤ 3 個單字,單字淡入,在說話中的單字下方加底線,強調色,說話者條對話

研發系統的選項作為參數:tempo = chunk.max_dur_s: 1.2 + timing.min_show_s: 0.83(hybrid 中啟用);stress = emphasis: "energy"(從 --audio 計算的每個說話者單字響度 z 分數),或 "keyword" 搭配 keywords 清單。

指令

python -m subkit demo examples/fixture                     # 5 種設定檔 + hybrid_lift -> 預覽、srt/ass/vtt、validation_report.{md,json}
python -m subkit plan --words W --forbid F --config C [--profile hybrid] [--audio A] -o manifest.json
python -m subkit burn manifest.json --forbid F --video in.mp4 [--audio A] -o preview.mp4 --qa qa.jpg
python -m subkit export manifest.json --format ass -o captions.ass     # srt | ass | vtt
python scripts/check_clean.py                                          # 提交前:無 media/keys/abs 路徑
ELEVENLABS_API_KEY=... python -m subkit stt audio.wav -o words.json     # 可選;或 --provider groq 搭配 GROQ_API_KEY

陷阱

  • libass ≠ Pillow 字體大小。 libass 以 OS/2 winAscent+winDescent 調整大小,並將基線放置在行頂部下方 winAscent 處;匯出會轉換兩者,否則 ASS 文字會縮小約 35%、變細且位置更低。
  • ASS 中的可變字體會回退到預設實例(通常為 Regular)。請提供您使用的粗細的靜態實例(此處為 Onest-Bold.ttf,700)並傳遞 fontsdir。
  • ffmpeg -ss 在 -i 之前會重設時間戳:字幕篩選器隨後會渲染 t=0。在燒錄 ASS 時,請在 -i 之後搜尋。
  • \k/\kf 卡拉 OK 以厘秒為單位,並永久為每個說話中的單字著色;若要「僅當前單字」,請發出時間片段(如匯出所做的那樣)。
  • SRT 沒有樣式:如果交付物需要粗細或強調,請提供 ASS/VTT 或燒錄影片。
  • 浮動行(依說話者 x、遲滯、「看起來更好」的上移)在對話中會看起來像抖動。請保持預設固定模式;在 baseline_lift 中,驗證器會重新檢查每個上移是否確實交錯。
  • 對比度是根據亮色與其後最亮 10% 像素(而非平均值)來判斷:火焰、雪地和亮點會導致平均值失敗。
  • 請勿捨棄已在畫面上繪製的單字。請將已繪製的標籤移至註釋層。
  • templates/safe_zones.json 中的安全區僅為近似值;平台 UI 會變化,因此請在發布前重新檢查。

檢查清單

  • words.json 涵蓋整個語音(雲端 STT 或強制對齊器);說話者已標記
  • forbid.json:人臉、手部、火焰/道具(每個鏡頭)+(align: speaker 的 speakers 框)
  • config:尺寸、fps、safe_zone、說話者顏色(不同的色相,兩者在背景上均 ≥ 4.5:1)
  • plan → manifest;閱讀 overlap_accepted(固定)或 collision_lifts(上移模式,每個都有實際原因)
  • burn → 查看 QA 工作表(青色 = 基線,黃色 = 重疊已接受,橙色 = 含原因的上移)以及實際幀
  • validate 全部 PASS;提供燒錄影片(如果播放器能渲染,則加上 ASS/VTT;SRT 僅作為純文字)

相關技能