Communitygithub.com

影片字幕動畫

將逐字稿或旁白轉換為逐詞精準同步、引人注目的動態字幕,適合 TikTok、Reels 等短影音平台。

影片字幕動畫 是什麼?

這個技能專注於為短影音(9:16 垂直影片)生成高品質的逐詞動畫字幕。它從 Whisper 或 AssemblyAI 等語音辨識工具取得包含時間戳記的逐詞轉寫結果,並將其轉換為每個詞語獨立彈入(pop-in)、當前朗讀詞語高亮(active-word highlight)的動畫效果。技能支援 Remotion 框架(透過 `spring()` 動畫)與純網頁 CSS 動畫兩種實作方式,並提供清晰的字型排版(粗體無襯線字型、外框與陰影)與安全區域擺放建議(中心帶、避開底部 UI),確保字幕在各種背景下都易於閱讀。此外,它還涵蓋了將字幕直接燒錄進影片(burn-in)與輸出獨立的 SRT/VTT 字幕檔兩種工作流程,滿足社群平台分享與無障礙標準的雙重需求。整個流程從轉寫、正規化時間格式、分頁分組,到動畫、排版、輸出,步驟明確,並附有完整的驗證指令碼(contact-sheet.sh, probe-mp4.sh)與參考檔案。

相容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Kreesten-hsh/video/tree/HEAD/.agents/skills/caption-animation

在你喜歡的 AI 中提問

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

說明文件

字幕動畫 (Caption Animation)

將逐字稿或旁白轉換為逐詞精準同步、引人注目的動態字幕:每個詞語在音節處彈入,當前朗讀詞語高亮顯示,文字緊貼旁白節奏。打造能在 TikTok、Reels 和 Shorts 上提升觀看時長的字幕——易讀、節拍精準、並安全地置於畫面構圖內。

使用時機

  • 為短影音垂直影片 (9:16) 製作逐詞或卡拉 OK 風格字幕。
  • 將逐字稿燒錄成開放式字幕,與旁白/配音軌道同步。
  • 將 Whisper/SRT 逐字稿轉換為 Remotion 或網頁上的動畫文字。
  • 將自動產生的字幕重新設計成有品牌風格的「Hormozi 式」揭示效果。

處理流程 (The Pipeline)

階段工作工具
轉寫音訊 → 逐詞時間戳記Whisper (@remotion/install-whisper-cpp), AssemblyAI
正規化→ { text, startMs, endMs }[] 代幣@remotion/captions Caption 型別
分頁將詞語分組為 1–4 個詞的「頁面」createTikTokStyleCaptions()
動畫逐詞彈入 + 當前詞高亮Remotion spring() / CSS
放置安全區域、易讀字型下方排版規則
輸出燒錄 (MP4) 及/或外部 SRT/VTTRemotion 渲染 / 檔案輸出

兩條不可妥協的規則

  1. 逐詞時間,不是逐行時間。 卡拉 OK 字幕只有在每個詞語精準落在音節上時才顯得神奇。務必使用逐詞時間戳記;絕不要透過將行持續時間平均分配來偽造——時間偏移會立刻被察覺。
  2. 可讀性優先於風格。 字幕是在手機、陽光下、靜音狀態下閱讀的。粗體無襯線字型、厚重描邊或陰影、高對比是首要考慮;裝飾其次。沒人能讀懂的字幕只是裝飾,而不是字幕。

從逐字稿取得逐詞時間

Whisper 可以直接輸出逐詞時間戳記。將所有來源正規化為一個統一的代幣形狀,讓渲染器永遠不需要關心詞彙來自何處:

// 字幕代幣 — 下游所有元件消費的唯一形狀
type Token = { text: string; startMs: number; endMs: number };

// 解析 SRT 提示區塊 "00:00:01,200 --> 00:00:01,640" 為毫秒
const toMs = (t: string) => {
  const [h, m, rest] = t.split(":");
  const [s, ms] = rest.split(",");
  return ((+h * 60 + +m) * 60 + +s) * 1000 + +ms;
};

如果只有句子級別的提示,請重新進行逐詞時間轉寫——不要內插。Whisper 的 medium.en 大約比 large 快 2 倍,對於清晰的語音音訊來說已足夠準確。

逐詞彈入 (Remotion)

透過一個錨定在各自 startMs 上的彈簧動畫來驅動每個詞的縮放與不透明度。微小的超調正是讓它感覺「活潑」的關鍵。

import { useCurrentFrame, useVideoConfig, spring, interpolate } from "remotion";

const Word: React.FC<{ token: Token; active: boolean }> = ({ token, active }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const enter = (token.startMs / 1000) * fps;            // 該詞的入場影格
  const p = spring({ frame: frame - enter, fps, config: { damping: 12, mass: 0.6 } });
  const scale = interpolate(p, [0, 1], [0.6, 1]);        // 從 60% → 100% 彈入 (會超調)
  return (
    <span style={{
      display: "inline-block",
      transform: `scale(${scale})`,
      opacity: interpolate(p, [0, 1], [0, 1]),
      color: active ? "#FFE45E" : "#FFFFFF",             // 當前詞高亮
      transition: "color 80ms linear",
    }}>{token.text}&nbsp;</span>
  );
};

透過檢查 frame 是否落在每個代幣的 [startMs, endMs] 區間內來計算 active 狀態。將高亮保持為單一強調色,或是在當前詞後方放置一個填滿的「方塊」——千萬不要同時讓所有詞的顏色都變化。

分頁,而非文字牆

一次顯示 1–4 個詞。使用 Remotion 的 createTikTokStyleCaptions() (或手動分組) 並調整 combineTokensWithinMilliseconds:約 200–500ms 用於真正的逐詞顯示,約 1000–1500ms 用於簡短可讀的短語。

import { createTikTokStyleCaptions } from "@remotion/captions";
const { pages } = createTikTokStyleCaptions({
  captions, combineTokensWithinMilliseconds: 1200,       // 每頁約 2–3 個詞
});

網頁/CSS 彈入 (無 Remotion)

對於 DOM/即時播放器,為每個詞設定與其 startMs 相等的 animation-delay:

.word { display:inline-block; opacity:0; animation: pop .26s cubic-bezier(.34,1.56,.64,1) forwards; }
@keyframes pop { from { opacity:0; transform:translateY(.18em) scale(.7) } to { opacity:1; transform:none } }
.word.active { color:#FFE45E; }
words.forEach(w => { const el = mk(w.text); el.style.animationDelay = `${w.startMs}ms`; track.append(el); });

易讀字型與安全區域擺放 (9:16, 1080×1920)

屬性數值原因
字型粗體/特粗無襯線 (Montserrat, Inter, Helvetica)在小型、雜亂的螢幕上仍可閱讀
大小56–80px (約畫面高度的 8%),最小值 45px在手機上靜音觀看時仍清晰
描邊2–6px 實心黑色外框可在任何背景上辨識
陰影柔和的投影作為描邊的備援在明亮畫面上提供區分
大小寫全大寫或句子形式;高對比填充色衝擊力 + 可掃描性
垂直位置中央區域,約畫面 62–70% 處位於 UI 之上、動作之下
底部安全保持離底部約 280px / 15% 的距離避免遮擋字幕/CTA/音訊 UI
側邊安全保持在中心 80% 寬度內避免遮擋右側欄圖示

將字幕放置在中央區域——不要固定在最底部,那裡是平台 UI (使用者名稱、音訊、按鈕) 所在之處。文字最大約 2 行。

與旁白/配音同步

逐字稿已經包含了確切音訊的時間。將相同的音訊放置在合成下方,並保持時間戳記在音訊的時間基準內——字幕和語音會保持鎖定,無需手動微調。如果重新錄製了配音,請重新轉寫;切勿手動偏移時間。

燒錄 vs 外部 SRT/VTT

燒錄 (開放式字幕)外部 SRT/VTT (封閉式字幕)
位置MP4 中的像素獨立的 .srt/.vtt 檔案
社群平台 (TikTok/Reels)必須——保證顯示、可設定樣式平台通常忽略
無障礙 (ADA/WCAG)單獨使用不符合規範必須 (可切換開啟/關閉)
最佳實踐為社群平台燒錄動畫字幕同時為網頁/SEO 提供外部字幕檔

兩者都輸出:為社群平台燒錄動畫字幕,並從相同代幣寫入一份純文字 SRT/VTT 以滿足無障礙/SEO 播放需求。

輸出檢查清單

  • 逐詞時間戳記 (真實的,來自轉寫)——沒有均分偽造。
  • 逐詞彈入,帶有微小超調;當前詞使用一個強調色。
  • 每頁 1–4 個詞;絕不顯示文字牆。
  • 粗體無襯線字型,56–80px,2–6px 描邊 + 陰影,高對比。
  • 中央區域,離底部約 280px 及側邊欄位有足夠距離。
  • 音訊放置在合成下方;時間戳記在音訊時間基準內。
  • 為社群平台輸出燒錄版,並為無障礙功能輸出外部 SRT/VTT。

交付與驗證 (渲染靜態圖 → MP4)

打包助手 (scripts/): 使用 scripts/contact-sheet.sh sheet.png f-hook.png f-mid.png f-end.png 拼貼您的靜態圖,然後使用 scripts/probe-mp4.sh out.mp4 [WxH] [fps] 驗證編碼。請參閱 scripts/README.md。

字幕作為 Remotion 合成輸出 (<Composition> + zod schema + defaultProps)——所有文字動畫皆由 useCurrentFrame() 驅動影格,絕不使用 Date.now() / Math.random() / 計時器。可交付成果 = out/*.mp4 (已燒錄) + 專案 + 外部 SRT/VTT。預設為 9:16 垂直格式 (1080×1920)。

驗證循環 — 渲染靜態圖 → 檢查 → 編碼。 逐詞時間是最容易出問題的地方;在花費時間進行完整編碼之前,先在確切的影格上檢查它。

# 在起始 / 取樣的中間當前詞影格 / 結束處渲染靜態圖 — 使用已提供屬性 (真實代幣 + 音訊)
npx remotion still Captions out/f-start.png --frame=0   --props='{"captionsSrc":"vo.json"}'
npx remotion still Captions out/f-mid.png   --frame=90  --props='{"captionsSrc":"vo.json"}'
npx remotion still Captions out/f-end.png   --frame=N   --props='{"captionsSrc":"vo.json"}'  # N = durationInFrames-1

# 檢查每個 PNG:
#  - 在影格 90 高亮顯示的詞語,其 [startMs,endMs] 應包含 90/fps (無時間漂移)
#  - 燒錄的字幕清晰可讀:粗體無襯線、描邊+陰影有效、無裁切
#  - 9:16 安全區域:字幕位於中央區域,離頂部約 12% 和底部約 20-35% (字幕/CTA/音訊 UI) 及右側動作欄有足夠距離

npx remotion render Captions out/captions.mp4 --props='{"captionsSrc":"vo.json"}'   # 靜態圖確認無誤後再編碼
npx remotion render Captions out/demo.gif --codec=gif                                # README 示範剪輯

使用 npx remotion compositions 讀取 durationInFrames/fps 並選取當前詞與結束影格。

完成之前:

  1. 靜態圖在影格 0、中間當前詞影格和最後一幀都能乾淨渲染——無缺少字型/音訊。
  2. 在取樣的影格上,正確的詞被高亮顯示 (影格/fps 落在其代幣區間內);無均分偽造。
  3. 燒錄字幕清晰可讀 (描邊+陰影) 且字幕在每個檢查的影格都完全位於 9:16 安全區域內。
  4. 僅由影格驅動——無 Date.now() / Math.random() / 計時器。
  5. 已提供的屬性 (真實代幣,不僅是 defaultProps) 能正確渲染;MP4 + 外部 SRT/VTT 已輸出,GIF 為可選。

參考檔案

  • references/word-timed-captions.md — 端到端建置:Whisper 轉寫和 Caption 型別、完整的 SRT 解析器、帶有當前詞高亮的 Remotion 逐詞時間元件、手動分頁、SRT/VTT 輸出器、各平台安全區域對照表,以及可讀字型規格表。

Individual skills in this repo

This repo contains 3 individual skills — each has its own dedicated page.

相關技能