Remotion LabRemotion Lab
媒體整合短影音自動上字幕:用 Whisper 幫你逐字跳動字幕
captionswhispershortstiktokclaude-codeintermediate

短影音自動上字幕:用 Whisper 幫你逐字跳動字幕

從音訊轉錄、解析 SRT、到做出 TikTok 風格逐字高亮字幕——完整的短影音字幕工作流,全程 Claude Code 指令驅動。

成品預覽

這支 15 秒的 demo 是用接下來的步驟做出來的: Gemini 2.5 Pro TTS(Charon 聲音)生成旁白 → Whisper 轉錄出 word-level 時間戳 → Remotion 排版 → 渲染 MP4。 整個流程沒有任何手動上字幕、沒有剪輯軟體。

🔊 記得打開聲音,字幕會跟著旁白逐字跳動。


這篇會做出什麼

一支 9:16 直式短影音,主角是一段旁白音訊,畫面上會出現逐字跳動、當前字高亮的字幕——就是你在 TikTok、IG Reels 看到的那種字幕。

整個流程全部用 Claude Code 指令完成,你不需要:

  • 手動對時間軸
  • 用 CapCut / Premiere 上字幕
  • 寫任何一行 interpolate()

你只需要準備一段 .mp3.wav 旁白檔案。


前置知識

建議先完成這兩篇:

專案設定建議:9:16 短影音尺寸 1080×1920,30 fps。下面 Step 1 的 prompt 會幫你設好。


Step 1:建立短影音專屬的 Composition

打開你的 Remotion 專案,在 Claude Code 裡輸入:

在現有的 Remotion 專案裡新增一個 Composition:
- id: "ShortsCaptions"
- 尺寸 1080x1920(9:16 直式)
- fps: 30
- durationInFrames 先設 450(15 秒)
- 新建 src/compositions/ShortsCaptions.tsx 作為主元件
- 背景色 #0f172a
- 中央放一個暫時的 placeholder 文字「短影音字幕 Demo」
- 記得在 src/Root.tsx 註冊這個 Composition

Claude 會建立 ShortsCaptions.tsx、在 Root.tsx 加上 <Composition>。打開 Remotion Studio 確認左側列表能看到它,中央預覽是深藍背景加上標題。

💡 短影音尺寸相關的細節可以進一步閱讀 /docs/composition


Step 2:準備旁白並用 Whisper 轉錄

把你準備好的旁白音訊放進專案的 public/ 資料夾:

public/
└── audio/
    └── voiceover.mp3

接著在 Claude Code 裡輸入:

幫我用 @remotion/install-whisper-cpp 安裝 Whisper.cpp,然後寫一個 Node.js 腳本
scripts/transcribe.mjs,做這些事:

1. 讀取 public/audio/voiceover.mp3
2. 如果需要,先用 ffmpeg 轉成 16kHz wav
3. 用本地 Whisper 轉錄成 SRT 檔
4. 把 SRT 存到 public/captions/voiceover.srt

安裝完成後直接執行一次腳本,讓我看看 SRT 檔的內容。

Claude 會:

  1. npm install @remotion/install-whisper-cpp 並下載模型
  2. 建立 scripts/transcribe.mjs,用 Whisper.cpp 產生 SRT
  3. 執行腳本,把 SRT 存到 public/captions/voiceover.srt

你會看到類似這樣的 SRT 檔:

1
00:00:00,000 --> 00:00:02,400
大家好,我是 Claude
 
2
00:00:02,400 --> 00:00:05,100
今天要示範 Remotion 的字幕功能
 
...

💡 Whisper 不是唯一選擇。OpenAI 雲端、ElevenLabs、其他本地模型的比較可以看 /docs/captions-transcribing


Step 3:在影片裡播放旁白

有了音訊檔,先讓 Composition 把聲音放進去:

在 ShortsCaptions.tsx 中:
- 用 <Audio> 元件載入 staticFile("audio/voiceover.mp3")
- 把 placeholder 文字拿掉
- 改成上方 1/3 空白,中央到下方預留字幕區

Claude 會用 staticFile()<Audio>。在 Studio 按下播放,你應該可以聽到旁白。

💡 staticFile() 如何把 public/ 的檔案轉成可載入的 URL,細節在 /docs/staticfile。音訊元件完整 API 則看 /docs/audio/docs/audio-importing


Step 4:解析 SRT 並做出基本字幕顯示

現在把 SRT 轉成 Remotion 看得懂的 Caption 陣列,並逐句顯示:

在 ShortsCaptions.tsx 裡加上字幕邏輯:

1. 使用 @remotion/captions 的 parseSrt() 解析
   staticFile("captions/voiceover.srt") 的內容(用 fetch 讀取)
2. 把每一條 caption 包成一個 <Sequence>,用 startMs / endMs 對應
   to frame 的換算(記得用 fps = 30)
3. 字幕放在畫面下方 1/4 的位置
4. 字體大小 72px,Noto Sans TC 粗體,白色
5. 加一層黑色半透明外框提高可讀性
6. 整個 captions 區塊用 <AbsoluteFill> 疊在 Audio 上層

不要做任何花俏的動畫,先讓基本字幕能對到時間軸就好。

這一步會用到四個核心 API:

回到 Studio 按播放,你應該看到字幕準確地跟著旁白一句一句出現。


Step 5:升級成「當前字高亮」的 TikTok 風格

整句顯示太陽春了。現在加上逐字跳動效果:

把 ShortsCaptions.tsx 改成「當前字高亮」的 TikTok 風格:

1. 把 parseSrt() 的每一條 caption 再切成 word-level 的片段
   (如果 Whisper SRT 沒有 word timestamps,就用句子長度平均分配)
2. 每個 word 一個 <Sequence>,只在它的時間區間顯示
3. 當前字用亮黃色 #facc15、比其他字大 15%、並加一個 spring() 彈跳
   scale 從 0.8 → 1.0,damping 12
4. 前後三個字顯示為白色 + 60% opacity,用來給觀眾上下文
5. 文字置中對齊,最多顯示 7 個字
6. 超過 7 個字就以當前字為中心做 window scroll

動畫用 spring(),不要用 CSS transition。

這一步做完你就有 TikTok/IG Reels 風格的逐字字幕了。核心概念:

  • spring() 做彈跳縮放(/docs/spring
  • 每個字都是獨立的 <Sequence>,可以精準控制顯示/隱藏
  • useCurrentFrame() + 時間區間換算決定「哪個字是當前字」

💡 TikTok 風格分頁字幕、逐字高亮的完整範例與變體在 /docs/captions-displaying/docs/animated-captions 都有。


Step 6:加背景影片(可選)

純色背景配字幕已經可用,但短影音通常會放一段 B-roll 背景:

在字幕下面加一層背景影片:

1. 在 public/video/ 放一個 background.mp4
2. 用 <OffthreadVideo> 而不是 <Video> 載入
   (渲染時比較穩定)
3. 影片要覆蓋整個 1080x1920,用 objectFit: "cover"
4. 影片要靜音(muted)因為我們只要旁白聲音
5. 上面疊一層半透明黑色 rgba(0,0,0,0.4) 讓字幕更清楚

為什麼用 <OffthreadVideo> 而不是 <Video> 渲染時 Remotion 會用 FFmpeg 精準提取每一幀,不會遇到瀏覽器影片元件的時間碼飄移問題,短影音這種要求幀準確的場景尤其重要。詳細說明在 /docs/offthreadvideo


Step 7:匯出 SRT 燒進影片 + 輸出 MP4

想讓上傳到 YouTube Shorts 時附 SRT 檔(平台會讓觀眾開關字幕):

1. 渲染整支影片成 MP4:
   npx remotion render src/index.ts ShortsCaptions out/shorts.mp4
2. 同時把 captions 匯出成獨立的 SRT 檔到 out/shorts.srt
   用 @remotion/captions 的 serializeSrt() 即可
3. 在 render 時用 --codec h264,crf 設 20

💡 匯出 SRT/VTT 的完整流程在 /docs/captions-exporting


完成!回顧學到的概念

一支 15 秒的短影音做完,你實際上已經摸過了 Remotion 字幕生態系的幾乎所有核心 API:

概念用在哪
<Composition> 9:16 尺寸Step 1
Whisper 轉錄 + SRTStep 2
<Audio> + staticFile()Step 3
parseSrt() 解析字幕Step 4
<Sequence> 控制字幕顯示區間Step 4、5
<AbsoluteFill> 疊層Step 4
spring() + useCurrentFrame()Step 5
逐字 word-level 時間軸Step 5
<OffthreadVideo> 渲染安全的背景影片Step 6
serializeSrt() 匯出獨立字幕檔Step 7

本篇涵蓋的官方文件

核心字幕 API:

相關媒體 API:

動畫基礎:


常見問題

Q:Whisper 轉出來的時間戳不準怎麼辦? A:用 large-v3 模型會比 base 精準很多,代價是下載時間與運算時間。或者改用雲端 API,品質更穩定——可以看 /docs/captions-transcribing 的方案比較。

Q:字幕跟音訊對不上? A:確認 <Audio> 沒有被 <Sequence> 包在奇怪的 from 裡面造成偏移。也要確認你的 fps 跟 SRT 時間戳的換算正確:frame = Math.round(seconds * fps)

Q:為什麼要 <OffthreadVideo> 而不是 <Video> A:<Video> 在瀏覽器端(Studio 預覽)比較流暢,但渲染時會靠 HTMLVideoElement,時間碼容易飄。<OffthreadVideo> 直接用 FFmpeg 抓幀,渲染精度高。完整差異看 /docs/offthreadvideo

Q:字幕在 Studio 看得到,渲染出來卻沒有? A:檢查字型是否用了 @remotion/fonts 正確載入,特別是 Noto Sans TC 這類非預設字型。也確認 SRT 檔放在 public/ 而不是 src/src/ 裡的東西不會被當成靜態資產)。


下一步

接下來可以挑戰:

有問題歡迎到 FB 社群 討論!