Remotion 主題解說影片技能 (50-60 秒) 是做什麼的?
此技能引導您從任何給定主題,建立高品質的 50-60 秒短影音解說影片(適用於 TikTok / YouTube Shorts / Reels 格式:1080x1920 @ 30fps)。
它整合了:
- 來自
remotion-dev/skills的視覺最佳實踐(幀精確的彈簧動畫、限制插值、序列組合、字體層級)。 - AI 語音合成,透過
.env中的TTS_PROVIDER設定:edge(edge-tts-universal,線上,免費) 或cit(CIT Voice Studio,離線越南語配音工作室 - 下載連結: github.com/quyen2867/cit-voice-studio,API 文件:docs/cit-voice-studio.md)。 - 精確時間同步,將語音長度直接對應到 Remotion 的影格序列。
1. 影片結構與時間編排 (50-60 秒 / 1500-1800 影格 @ 30fps)
吸引人的短影片遵循 鉤子-問題-解決方案-價值-結尾 框架:
| 場景 | 名稱 | 時間 | 影格範圍 (@ 30fps) | 目的與視覺元素 |
|---|---|---|---|---|
| 1 | 鉤子 | 0 秒 – 5 秒 | ~150 影格 | 立即吸引注意:大字標題、引發好奇心的問題、浮動徽章。 |
| 2 | 背景 / 痛點 | 5 秒 – 15 秒 | ~300 影格 | 陳述問題或說明此主題為何重要。警告圖示 / 比較。 |
| 3 | 核心概念 第一部分 | 15 秒 – 28 秒 | ~390 影格 | 解釋第一個核心原理:玻璃卡片、插圖圖示、突出的關鍵字。 |
| 4 | 核心概念 第二部分 | 28 秒 – 42 秒 | ~420 影格 | 擴展細節或運作機制:3 步驟流程、流暢的流程圖。 |
| 5 | 實際影響 | 42 秒 – 52 秒 | ~300 影格 | 實際應用、實戰建議或令人印象深刻的數據。 |
| 6 | 結尾與呼籲行動 | 52 秒 – 60 秒 | ~240 影格 | 總結一句有價值的話,呼籲按讚/分享/追蹤及個人品牌曝光。 |
總時長: 1500 – 1800 影格(約 50 – 60 秒)。
2. TTS 語音生成 (edge | cit)
2.1 透過 .env 設定語音
確保 .env 檔案已正確設定(完整範例見 .env.example):
TTS_PROVIDER=edge # edge | cit
TTS_OUTPUT_DIR=public/audio
# Edge TTS (TTS_PROVIDER=edge)
EDGE_TTS_VOICE=vi-VN-HoaiMyNeural # 或 vi-VN-NamMinhNeural, en-US-ChristopherNeural
EDGE_TTS_RATE=+10% # +10% 到 +15% 有助於短影片保持快節奏
# CIT Voice Studio (TTS_PROVIDER=cit)
CIT_TTS_BASE_URL=http://127.0.0.1:8001
CIT_TTS_VOICE=海燈 # 語音列表:docs/cit-voice-studio.md 或 GET /voices
CIT_TTS_SPEED=1.1 # 0.5 - 2.0
當 TTS_PROVIDER=cit 時:
- CIT Voice Studio 應用程式必須正在運行。腳本在生成音頻前會自動呼叫
GET /health;若回報連線失敗,則提示使用者打開應用程式(或從 github.com/quyen2867/cit-voice-studio 下載)。 - 旁白中可以插入情緒標籤
[笑]、[嘆氣]、[清喉嚨]以及暫停標籤[暫停 0.5 秒](這些標籤不會被朗讀出來)。請勿濫用:每個場景最多一個標籤。 - 錯誤
400 Voice not found表示語音名稱錯誤(需區分聲調)。請檢查CIT_TTS_VOICE。
2.2 音頻檔案生成流程
收到主題後,建立旁白腳本檔案,並執行 scripts/generate-tts.ts 腳本以生成音頻:
import { generateTopicVoices } from "../../scripts/generate-tts";
const scenes = [
{
id: "scene1_hook",
text: "你知道 Docker 實際上是什麼,以及為什麼每個程式設計師都需要它嗎?",
},
{
id: "scene2_problem",
text: "以前,『在我的機器上可以跑』這句話在交付產品時總是一場惡夢。",
},
{
id: "scene3_concept1",
text: "Docker 透過 Container 解決了這個問題——將所有程式碼和環境打包成一個獨立的區塊。",
},
{
id: "scene4_concept2",
text: "與笨重的虛擬機器不同,Docker 共享作業系統核心,使其能在瞬間啟動。",
},
{
id: "scene5_impact",
text: "因此,您可以從 AWS、GCP 到廉價的 VPS,在任何伺服器上順暢地部署應用程式。",
},
{
id: "scene6_outro",
text: "追蹤我們的頻道,每天掌握簡潔的科技知識!",
},
];
await generateTopicVoices("DockerShort", scenes);
音頻檔案將自動儲存到 public/audio/<TopicName>/<sceneId>.<ext>(使用 edge 時為 .mp3,使用 cit 時為 .wav),同時會產生一個 manifest.json 檔案,記錄每個場景的準確影格數 (durationInFrames) 和 audioPath。
- 每個場景可選參數:
voice(目前提供者的語音)、rate/pitch/volume(僅限 edge)、speed0.5-2.0(僅限 cit)。 - 已存在的檔案會被重複使用(快取)。若想重新生成(例如修改旁白或更換語音),請先刪除對應的音頻檔案。
3. Remotion 編碼規則(源自 remotion-dev/skills)
撰寫 Remotion 原始碼時,務必 遵守以下原則:
3.1 使用彈簧動畫
不要使用無生命的 CSS keyframes/transitions 或線性 easing。請使用 spring():
import { spring, useCurrentFrame, useVideoConfig } from "remotion";
const frame = useCurrentFrame();
const { fps } = useVideoConfig();
// 為卡片/圖示提供流暢彈性的縮放動畫
const scale = spring({
frame,
fps,
config: {
damping: 12, // 低於 15 可產生自然的彈性
stiffness: 100, // 張力
mass: 0.8,
},
});
const entrance = spring({
frame: frame - 10, // 延遲 10 影格
fps,
from: 50,
to: 0,
});
3.2 安全的插值(務必限制範圍)
始終提供 extrapolateLeft: "clamp" 和 extrapolateRight: "clamp",以防止時間軸超出範圍時數值溢出:
import { interpolate } from "remotion";
const opacity = interpolate(frame, [0, 15], [0, 1], {
extrapolateLeft: "clamp",
extrapolateRight: "clamp",
});
3.3 嵌入音頻與序列同步
Composition 中的每個場景都應使用 <Sequence> 或 <Series> 來精確管理時間:
import { Audio, staticFile, Sequence } from "remotion";
// 在場景元件中 - 從 manifest 取得路徑,請勿硬編碼 .mp3 副檔名(cit 提供者輸出 .wav):
<Sequence from={0} durationInFrames={sceneDuration}>
<Audio src={staticFile(audioManifest.scenes[0].audioPath)} />
<SceneContent />
</Sequence>
- 簡潔的場景切換緩衝區:
- 場景之間的緩衝區應僅設置 +3 到 +4 影格(約 0.1 秒),緊接在語音結束之後。
- 避免設定過長的緩衝區(+15 到 +20 影格),這會造成場景之間的聲音空白或節奏中斷。下一個場景應在上一個句子結束時立即出現,以保持短影片應有的緊湊和吸引人的節奏。
// 計算 Series 中各場景時長的範例
const d1 = audioManifest.scenes[0].durationInFrames + 3;
const d2 = audioManifest.scenes[1].durationInFrames + 3;
// ...
3.4 視覺設計規範(直式 1080x1920)
- 背景:高級深色模式(
bg-slate-950或漸層from-slate-950 via-zinc-900 to-black)搭配微弱的放射光暈 / 網格效果。 - 玻璃擬態卡片:
backdrop-blur-xl bg-white/10 border border-white/20 rounded-3xl p-8 shadow-2xl
- 頻道品牌標題:
- 始終在螢幕上方中間位置顯示品牌元件
⚡ [CHANNEL_NAME](top: 150px,left: 50%搭配 translate-x),該名稱從環境變數CHANNEL_NAME讀取(預設值:"mquyen")。此舉可避免被平台的搜尋列以及「正在追蹤」/「為您推薦」分頁遮擋。
- 始終在螢幕上方中間位置顯示品牌元件
- 針對行動裝置最佳化的字體(1080x1920):
- 主標題:72px - 96px,粗體 font-black,清晰的漸層色。
- 卡片內容 / 引言:40px - 50px,font-extrabold。
- 輔助 / 解釋文字:28px - 36px,font-semibold。
- 類別徽章:28px - 32px,font-black uppercase。
- 居中佈局與單行字幕:
- 主要佈局:所有重要內容區塊必須位於螢幕正中央(垂直
justify-center)。 - 字幕位置:位於中央區塊下方,保留足夠間距(
mt-64),以免被 TikTok/Reels 的底部工具列遮擋。 - 單行格式:字幕僅顯示一行(約 5-7 個字),使用大字型
text-4xl font-black,會自動根據語句分組進行裁剪,並隨著語音進度(durationInFrames)流暢切換。使用藥丸形卡片rounded-full bg-slate-950/95 border-2 border-sky-400/50 px-10 py-5並為關鍵字加上 highlight。
- 主要佈局:所有重要內容區塊必須位於螢幕正中央(垂直
4. 為 Antigravity / Codex 逐步建立影片的流程
收到要求:「建立一個解釋 [主題 X] 的影片」 時:
步驟 1:編寫腳本
- 定義 6 個場景(鉤子、問題、概念 1、概念 2、影響、結尾)。
- 編寫自然、簡潔的旁白,句子要短(每個場景 15-30 個字)。
步驟 2:生成語音 (TTS 生成)
- 讀取
.env中的TTS_PROVIDER以確定使用 edge 還是 cit。 - 建立腳本
scripts/generate-<topic>-audio.ts,呼叫generateTopicVoices,然後執行npx tsx scripts/generate-<topic>-audio.ts。 - 從
manifest.json或src/<TopicName>/audioData.ts取得實際的影格時長列表。
步驟 3:建立程式碼目錄 src/<TopicName>/
標準目錄結構:
src/<TopicName>/
├── <TopicName>.tsx # 主要的 composition,組合各 Series.Sequence
├── types.ts # Schema 與 Props
├── audioData.ts # 音頻時長元數據
└── scenes/
├── Scene1Hook.tsx
├── Scene2Problem.tsx
├── Scene3Concept1.tsx
├── Scene4Concept2.tsx
├── Scene5Impact.tsx
└── Scene6Outro.tsx
步驟 4:在 src/Root.tsx 中註冊 Composition
在 src/Root.tsx 中加入新的 Composition:
<Composition
id="<TopicName>"
component={<TopicName>}
durationInFrames={totalFrames}
fps={30}
width={1080}
height={1920}
defaultProps={{}}
/>
步驟 5:檢查與回報
- 執行
npm run lint以檢查 TypeScript/ESLint 錯誤。 - 提供使用者在 Remotion Studio (
http://localhost:3000) 中開啟 Composition 的連結,或提供渲染 MP4 的指令:npx remotion render <TopicName> out/<TopicName>.mp4