Remotion LabRemotion Lab
字幕字幕

字幕

在 Remotion 影片中加入同步字幕。

安裝

npm install @remotion/captions

字幕工作流程

在 Remotion 中加入字幕分為四個步驟:

  1. 取得字幕資料 — 從 SRT/VTT 檔案匯入,或用語音辨識產生
  2. 解析字幕 — 將字幕檔轉換成 Remotion 可用的格式
  3. 顯示字幕 — 根據目前幀數顯示對應的字幕文字
  4. 設計樣式 — 設定字型、顏色、位置等視覺效果

匯入 SRT 字幕

import { parseSrt } from "@remotion/captions";
import { staticFile } from "remotion";
 
// 在 calculateMetadata 中載入
export const calculateMetadata = async () => {
  const srtContent = await fetch(staticFile("subtitles.srt")).then(
    (r) => r.text()
  );
  const { segments } = parseSrt({ input: srtContent });
 
  return {
    props: { segments },
  };
};

顯示字幕

根據目前幀數找到對應的字幕段落並顯示:

import { useCurrentFrame, useVideoConfig, AbsoluteFill } from "remotion";
 
interface CaptionSegment {
  text: string;
  startMs: number;
  endMs: number;
}
 
export const CaptionOverlay: React.FC<{
  segments: CaptionSegment[];
}> = ({ segments }) => {
  const frame = useCurrentFrame();
  const { fps } = useVideoConfig();
  const currentTimeMs = (frame / fps) * 1000;
 
  const currentSegment = segments.find(
    (seg) => currentTimeMs >= seg.startMs && currentTimeMs <= seg.endMs
  );
 
  if (!currentSegment) return null;
 
  return (
    <AbsoluteFill
      style={{
        justifyContent: "flex-end",
        alignItems: "center",
        paddingBottom: 80,
      }}
    >
      <div
        style={{
          backgroundColor: "rgba(0, 0, 0, 0.7)",
          color: "white",
          padding: "12px 24px",
          borderRadius: 8,
          fontSize: 36,
          fontWeight: "bold",
          maxWidth: "80%",
          textAlign: "center",
        }}
      >
        {currentSegment.text}
      </div>
    </AbsoluteFill>
  );
};

語音轉字幕

如果你沒有現成的字幕檔,可以用語音辨識服務產生:

  • OpenAI Whisper — 支援多語言,品質好
  • @remotion/install-whisper-cpp — Remotion 提供的 Whisper.cpp 整合
npm install @remotion/install-whisper-cpp

字幕樣式變化

逐字高亮

讓目前正在說的字用不同顏色標示:

const WordHighlight: React.FC<{
  words: { text: string; startMs: number; endMs: number }[];
  currentTimeMs: number;
}> = ({ words, currentTimeMs }) => {
  return (
    <div style={{ display: "flex", flexWrap: "wrap", gap: 8 }}>
      {words.map((word, i) => {
        const isActive =
          currentTimeMs >= word.startMs && currentTimeMs <= word.endMs;
        return (
          <span
            key={i}
            style={{
              color: isActive ? "#fbbf24" : "white",
              fontSize: 40,
              fontWeight: isActive ? "bold" : "normal",
              transition: "color 0.1s",
            }}
          >
            {word.text}
          </span>
        );
      })}
    </div>
  );
};

小結

  • @remotion/captions 解析 SRT/VTT 字幕檔
  • 根據目前幀數對應時間,找到該顯示的字幕段落
  • 可以做逐字高亮等進階效果
  • 語音轉字幕可用 Whisper 整合