Video Podcast Maker 製作影片的原理就是在網頁上產生畫出動畫, 透過截圖的方式, 把圖片再存為影片。
我使用Video Podcast Maker 的作品1: https://youtu.be/eBNLJ2zOWOo
我使用Video Podcast Maker 的作品2: https://youtu.be/CI60OD_38ao
Video-Podcast-Maker 使用解說: https://youtu.be/m02HOcXRMg8
說明: 如果你是 Windows 用戶, 不建議安裝到 WSL 裡, 因為反而速度更慢, 實測直接安裝在 Windows 裡, 預覽與render匯出的速度超級快.
Video Podcast Maker
https://github.com/Agents365-ai/video-podcast-maker
AI-powered video podcast creation skill for coding agents. Supports Bilibili & YouTube, multi-language (zh-CN/en-US), 6 TTS engines (Edge/Azure/ElevenLabs/OpenAI/Doubao/CosyVoice), 4K Remotion rendering.
中文 README說明:
https://github.com/Agents365-ai/video-podcast-maker/blob/main/README_CN.md
edge-tts
https://github.com/rany2/edge-tts
Use Microsoft Edge’s online text-to-speech service from Python WITHOUT needing Microsoft Edge or Windows or an API key
安裝環境
# macOS
brew install ffmpeg node python3
# Ubuntu/Debian
sudo apt install ffmpeg nodejs python3 python3-pip
確保系統已安裝必要的工具。如果在 Linux 系統上,通常需要先安裝 python3-venv 套件。
除了上面2個平台, 也可以直接安裝在 Windows 平台, 而不是 Windows 的 WSL 裡, 實際測試, 不管是什麼指令, 直接執行在 Windows 平台上都比在 WSL 快非常的多。
sudo apt update
sudo apt install python3-venv
在 macOS / Ubuntu (WSL) 安裝 pip
python3 -m venv .venv
source .venv/bin/activate
# Python dependencies
pip install azure-cognitiveservices-speech dashscope edge-tts requests
如果你覺得每次重開機之後都要打一長串指令: source .venv/bin/activate 很麻煩,有幾個更直覺的方法。
設定別名
這是最推薦的做法。你可以把啟動指令縮短成一個單字。打開你的設定檔,例如 ~/.zshrc 或 ~/.bashrc。在檔案最後面加入這一行:
alias va="source .venv/bin/activate"
儲存之後重新開啟終端機。以後只要輸入 va 就能直接進入虛擬環境。這非常適合懶人操作,而且不容易出錯。
使用自動化工具
如果你希望進入資料夾就自動啟動,可以使用 direnv 這個工具。安裝後你在專案目錄建立一個 .envrc 檔案。內容寫入 layout python3。這樣你每次用 cd 進入該目錄,系統就會自動幫你切換好環境。離開目錄時也會自動退出。
編輯器內建功能
如果你是用 VS Code 或 PyCharm 寫程式。通常不需要手動執行指令。VS Code 會在視窗右下角讓你選擇直譯器。選好 .venv 路徑後,你每次開啟內建的終端機,它就會自動幫你執行 source 指令。這對初學者來說最友善。
建立 Remotion 專案
這個專案, 如果你跟我一樣使用 wsl, 最好建在 /mnt/c/ 開頭的 path 以下, 方便 Windows 的主機去存取, 例如指令:
cd /mnt/c/your-podcast-list/
說明, 上面只是進去某一個專門放 podcast 的目錄, 還沒建立出新的 podcast 節目用的目錄.
npx create-video@latest your-project-name
cd your-project-name
npm i
npm install remotion @remotion/cli @remotion/player zod
瀏覽器預覽
npx remotion studio src/remotion/index.ts
這行每次打也覺得很麻煩, 因為很長, 而且也記不住, 最好是增加一個 run.sh, 再放入上面的指令.
或使用:
npm run dev
匯出為 mp4
npx remotion render Podcast out.mp4
如果遇到錯誤訊息: Error: Could not find composition with ID Podcast. Available compositions: VideoPodcast
白話文是: Podcast 不存在, 改用 VideoPodcast
npx remotion render VideoPodcast out.mp4
在匯出之前, 建議使用提示詞, 讓影片變成 4K:
修改影片為4K 畫質, 並確定字幕也有被放大.
匯出指定 frame 為 mov
npx remotion render Podcast frame-200.mov --frames=200-200 --codec=prores
匯出影片的第200幀檢查字型(輸出為 frame-200.png):
npx remotion still Podcast frame-200.png --frame=200 --image-format=png
建議同時開啟3個 powershell 的 terminal 環境:
- 瀏覽器預覽指令: npx remotion studio src/remotion/index.ts
- AI的 CLI 視窗
- 檔案的操作視窗
設定環境變數
Add to ~/.zshrc or ~/.bashrc:
# TTS Backend: edge (default, free), azure, doubao, cosyvoice, elevenlabs, google, openai export TTS_BACKEND="edge" # Default (free), or "azure" / "doubao" / "cosyvoice" / "elevenlabs" / "google" / "openai" # Azure TTS (high quality) export AZURE_SPEECH_KEY="your-azure-speech-key" export AZURE_SPEECH_REGION="eastasia" # Volcengine Doubao TTS (alternative backend) export VOLCENGINE_APPID="your-volcengine-appid" export VOLCENGINE_ACCESS_TOKEN="your-volcengine-access-token" export VOLCENGINE_CLUSTER="volcano_tts" # Default cluster, adjust per console config export VOLCENGINE_VOICE_TYPE="BV001_streaming" # Adjust per console voice options # Aliyun CosyVoice TTS (alternative backend) + AI thumbnails export DASHSCOPE_API_KEY="your-dashscope-api-key" # Optional: Edge TTS voice override export EDGE_TTS_VOICE="zh-CN-XiaoxiaoNeural" # ElevenLabs TTS export ELEVENLABS_API_KEY="your-elevenlabs-api-key" # Google Cloud TTS export GOOGLE_TTS_API_KEY="your-google-tts-api-key" # OpenAI TTS export OPENAI_API_KEY="your-openai-api-key" # Optional: Google Gemini for AI thumbnails export GEMINI_API_KEY="your-gemini-api-key"
Then reload: source ~/.zshrc
我實際上只有增加這2行:
export TTS_BACKEND="edge"
export EDGE_TTS_VOICE="zh-TW-YunJheNeural"
如果喜歡另外2個台灣口音的 TTS 要手動切換過去, 其實沒切也沒差, 因為可以在與 AI 對話時, 把環境的男/女各要用什麼聲音參數跟 AI 講, AI 的短期記憶可以幫我們自動配出對應的配音.
如果你有前一個作品, 放在 max-template 目錄下, 使用下列指令把檔案複製目前的專案裡:
cd C:\Max\play\podcast\max-template
xcopy /y/s *.* ..\your-new-project-name\
前置準備應該都OK了, 使用 cli 進入 AI mode:
gemini -y
下一部, 在該資料夾進入 AI, 告訴你的 Agent:
Create a video podcast about [your topic]
---
[Detail]
或是使用:
使用以下素材, 產生男女對話的podcast:
---
[Detail]
如果你已經有前一個 template copy 過來的 script.ts, AI 可能會單純產生對話, 沒放到 script.ts 裡, 建議提示詞:
使用以下素材, 產生男女對話的podcast 到 @src/Script.ts:
---
[Detail]
由於影片都同一個聲音有點單調, 使用提示詞:
影片都同一個聲音有點單調, 影片內容調整為男女對話, 畫面中的字幕依照角色不同, 使用不同顏色文字, 女聲的 TTS 設定值:
EDGE_TTS_VOICE="zh-TW-HsiaoChenNeural"
我個人偏好小陳(zh-TW-HsiaoChenNeural), 因為小余(zh-TW-HsiaoYuNeural)聽起來呆呆的.
如果你遇到產生 tts fail, 有可能是你重開機過, 沒有進入 .venv 環境, 造成 edge-tts 指令無法使用, 看到畫面 tts 產生失敗, 並重新進入 .venv 之後, 可以跟 AI 講:
generate tts fail, try this command: edge-tts --voice zh-TW-HsiaoYuNeural --text "…" --write-media …
想讓語速快一點, 使用提示詞:
生成語音音檔, 讓語速微微加快, 微微減少句子與句子之間的間隔時間, 讓影片步調微微加快.
上面是第一次的專案可以使用, 如果專案裡曾調過語速, 使用上面的提示詞, 會讓語速更加速, 改用指定的值就沒這個問題:
生成語音音檔, 語音生成速度設定為(--rate)=+15%, 縮短句子間隔(PAUSE_BETWEEN_SEGMENTS)至 0.2 秒以加快整體步調
✦ 我將為你調整語音生成邏輯,並重新產生音檔。
為了達到「語速微微加快」與「縮短句子間隔」的要求,我會進行以下修改:
- 調整語速:在 edge-tts 命令中加入 –rate=+15%。
- 縮短間隔:修改 src/Captions/utils.ts 中的 GAP_FRAMES(間隔幀數),從預設值調降,讓句子銜接更緊湊。 首先,我先查看 src/Captions/utils.ts 的內容。 ✓ ReadFile src\Captions\utils.ts
✦ 我將修改 src/generate-tts.ts 以加入語速設定,並確保它會重新產生音檔以套用新的語速。同時,我會調整
src/Captions/utils.ts 中的 PAUSE_BETWEEN_SEGMENTS 來縮短句子間隔。
以下是修改步驟:
- 修改 src/generate-tts.ts:
- 加入 –rate=+15% 參數。
- 暫時移除「檢查檔案是否存在」的邏輯,以強制重新產生。
- 修改 src/Captions/utils.ts:
- 將 PAUSE_BETWEEN_SEGMENTS 從 0.2 縮減至 0.05。
✦ 我接著修改 src/Captions/utils.ts 來縮短間隔時間:
- 將 PAUSE_BETWEEN_SEGMENTS 從 0.2 縮短至 0.08。
- 將開場等待時間 INTRO_DURATION_SECONDS 從 4 縮短至 2。 這樣可以讓影片整體的步調更緊湊、更流暢。
調整畫面大小與時長:
在 Remotion 中修改影片解析度,主要是在 Composition 元件的屬性裡進行設定。以下是具體的做法與細節。
修改 Composition 設定
在專案的入口文件(通常是 Root.tsx 或 index.tsx)中,你會看到定義 Composition 的程式碼。直接修改傳入的 width 與 height 數值即可更換解析度。
TypeScript
import { Composition } from 'remotion';
import { MyVideo } from './MyVideo';
export const RemotionRoot = () => {
return (
<>
<Composition
id="MyComp"
component={MyVideo}
durationInFrames={150}
fps={30}
width={1920}
height={1080}
/>
</>
);
};
常見解析度配置
如果你想要製作不同平台的影片,可以參考以下數值:
- 橫向影片 (16:9):1920×1080
- 直向影片 (9:16):1080×1920
- 正方形影片 (1:1):1080×1080
- 4K 影片:3840×2160
在元件中使用解析度數值
在撰寫影片內容的元件時,建議使用 useVideoConfig 這個 Hook 來取得當前設定的解析度,而不是寫死固定數值。這樣當你在 Root.tsx 修改解析度時,內部的排版也會跟著連動。
TypeScript
import { useVideoConfig } from 'remotion';
export const MyVideo = () => {
const { width, height } = useVideoConfig();
return (
<div style={{
flex: 1,
backgroundColor: 'white',
width: width,
height: height
}}>
解析度是 {width} x {height}
</div>
);
};
渲染時縮放影片
如果你不想修改原始程式碼的解析度,只想在輸出成果時縮小尺寸(例如為了預覽或加快渲染速度),可以在執行 npx remotion render 指令時加上 scale 參數。
例如將原本 1080p 的影片縮放成一半大小輸出:
npx remotion render src/index.tsx MyComp out.mp4 –scale=0.5
注意事項
解析度必須是整數,且某些編碼器(如 H.264)要求寬度與高度必須是 2 的倍數,否則在渲染時可能會報錯或出現綠邊。建議設定時優先選擇偶數。
如果時長在預覽時有錯誤,請使用提示詞:
修正時長錯誤
這樣寫太短, 會誤判意圖是去檢查 mp3 檔案長度為0 時, 字幕沒有被正確生成的錯誤, 要修改影片時長:
修正影片時長錯誤 @src/Root.tsx
✦ 我已經將 public/tts/work2.mp3 的發音優化為 1 拍 (ㄙㄞ / sāi):
🛠️ 修正對照 (Phoneme Mapping)
原始發音 (sài ❌)
之前解法 (sāi 2拍 ❌)
最終解法 (sāi 1拍 ✔️)
使用「腮」的音 (1拍)
我已經更新了 phonemes.json 以反應這個 1 拍的解法:
1 {
2 “mapping”: {
3 “塞”: “sāi (1-beat using homophone 腮)”
4 }
5 }
現在語音發音節奏完美,文字配置與時長也已校正。
發音錯誤的修正
Asking user 我找到音檔都在 public/tts,並由 src/Podcast.tsx 直接引用。專案內沒…
│ 我找到音檔都在 public/tts,並由 src/Podcast.tsx 直接引用。專案內沒找到自動生成這些 mp3 │
│ 的腳本,所以它們很可能是外部用 edge-tts 生成後放進來的。要我現在為那句(final_4.mp3 的內容)用 edge-tts │
│ 重生音檔嗎?要如何處理?
Install edge-tts if needed and synthesize SSML to public/tts/final_4.mp3 (shell)
│ python3 -m pip install –quiet edge-tts && python3 – <<‘PY’
│ import asyncio, edge_tts, os
│ ssml = ”’ │ 學會這些代碼,能讓你避開無謂的爭吵,在各種關係中活得更加游刃有餘。 │ ”’
手動產生 mp3 檔, 再 overwrite 比較快, 直接附上台灣3個口音的指令:
HsiaoChen
edge-tts --voice zh-TW-HsiaoChenNeural--text "學會這些代碼,能讓你避開無謂的爭吵,在各種關係中活得更加游刃有餘" --write-media final_4.mp3
HsiaoYu
edge-tts --voice zh-TW-HsiaoYuNeural--text "學會這些代碼,能讓你避開無謂的爭吵,在各種關係中活得更加游刃有餘" --write-media final_4.mp3
YunJhe
edge-tts --voice zh-TW-YunJheNeural --text "學會這些代碼,能讓你避開無謂的爭吵,在各種關係中活得更加游刃有餘" --write-media final_4.mp3
偏好講的快, 可以使用:
# 女聲
edge-tts --voice zh-TW-HsiaoChenNeural --rate=+15% --text "營運持續計畫嗎" --write-media caption-9-1.mp3
# 男聲
edge-tts --voice zh-TW-YunJheNeural --rate=+15% --text "而 ISO 二二三零一 則是保證公司即便沒了辦公室" --write-media caption-12-2.mp3
製作第二個影片, 這次滿神奇的, 對話字幕會自動用逗號與句號分隔來彈出字幕, 字幕放在 Script.ts, 遇到有問題的句子可以很快地修改要顯示的字幕, 針對有問題的 mp3 也可以在畫面上看到檔名, 直接生成並 overwrite 到 ./public/voiceover/ 目錄下.
不需要去維護多音字的檔案, 直接聽到什麼怪怪的, 看到mp3 的檔名, 重新生成 mp3, 並蓋過去即可.

像現在就是播到 caption-71-1.mp3
這段教學主要說明如何調整 edge-tts 語音合成的語速、音量和音高。當你想要讓生成的聲音聽起來更快、更大聲或更有磁性時,可以使用這三個參數。
參數調整規則
使用 –rate 調整語速,使用 –volume 調整音量,使用 –pitch 調整音高。這份教學特別強調一個技術細節:當你要設定負數數值時,必須使用等號連接參數與數值,例如 –rate=-50%,而不是在中間空一格。這是為了避免電腦程式誤把負號開頭的數值當成另一個新的指令選項。
語速與音量範例
如果你希望語速變慢一半,可以輸入:
edge-tts --rate=-50% --text "Hello, world!" --write-media hello_with_rate_lowered.mp3 --write-subtitles hello_with_rate_lowered.srt
同理,如果希望音量降低一半,指令如下:
edge-tts --volume=-50% --text "Hello, world!" --write-media hello_with_volume_lowered.mp3 --write-subtitles hello_with_volume_lowered.srt
音高調整範例
音高的單位通常使用 Hz。若要降低音高,讓聲音聽起來比較低沉,可以這樣寫:
edge-tts --pitch=-50Hz --text "Hello, world!" --write-media hello_with_pitch_lowered.mp3 --write-subtitles hello_with_pitch_lowered.srt
這些設定能讓你根據需求微調語音的表現方式,產出更符合情境的音檔。
背景音樂很怪, 想使用自己的, 要放到那個 path?
✦ 您應該將自己的背景音樂檔案放到專案根目錄下的 public/ 資料夾中。
具體操作步驟:
- 放置檔案:將您的音樂檔(例如 my-bgm.mp3)放入 /home/max32/my-video-project/public/ 資料夾下。
- 修改程式碼:在 src/Podcast.tsx 中將原本的 URL 換成 staticFile(“您的檔案名稱”)。 我現在為您更新 src/Podcast.tsx,將背景音樂路徑改為指向 public/bgm.mp3(您可以隨時將檔案重新命名為 bgm.mp3 放入 public
資料夾即可生效):
- src=”https://www.soundhelix.com/examples/mp3/SoundHelix-Song-2.mp3″
- src={staticFile(“bgm.mp3”)}
更改使用的字型
change font name from notosans to Maruko Gothic CJKjp Medium
如果很在意頓號,逗號, 可以改用 Maruko Gothic CJKtc Medium,
✓ SearchText ‘notosans’ within src → Found 2 matches
Captions/Subtitles.tsx:3: import { loadFont } from '@remotion/google-fonts/NotoSansTC';
Composition.tsx:5: import { loadFont } from '@remotion/google-fonts/NotoSansTC';
要調整字重有2個解去,
- 調字型的 Style, 例如: Thin / Light / Regular / Medium / Bold / Black
- 直接拿掉 subtitle(cpations) 的加粗, 與其使用 AI, 也許直接拿掉 captions/subtitles 的 fontweight 屬性更快.
下面是能顯著加速 Remotion 匯出的實用方法(含範例指令)。
高優先(大幅加速)
- 將靜態背景預先渲染成圖檔,主合成改用 Img + staticFile → 瀏覽器不用重算複雜濾鏡或粒子動畫。
範例:渲染第 1 幀為背景圖
npx remotion render Podcast frame-bg.png –frames=1-1 –codec=png
在程式中用 - 移除或替換昂貴的 CSS(backdrop-filter、blur(100px)、大量 box-shadow)。改成預先做好的模糊圖或單一陰影圖片。
中等優先(穩定但需修改)
- 減少同時動畫元素數量(例:把 15 個模糊圓圈降到 4)。
- 把重複且不變的圖案合成到一張 sprite 或單一 Canvas,再在畫面上重複繪製(比大量 DOM 元素快)。
系統/CLI 優化(立刻生效)
- 增加並行執行數(根據 CPU):–concurrency
例:用 8 個並行
npx remotion render Podcast out.mov –codec=prores –concurrency=8 - 降低解析度或 FPS(在專案設定/Composition 中修改 width/height、fps),例如把 4K → 1080p 或 60fps → 30fps。
資源與快取
- 用 registerFont() 或 local static font(已做)避免網路載入延遲。
- 確認 webpack cache 有開(Remotion 一般會自動快取 bundle),少改動 bundle 時能復用。
檢查與測量
- 先匯出單一幀檢查效能/品質:
npx remotion render Podcast frame-200.png –frames=200-200 –codec=png - 用小改動逐步驗證哪個優化最有效。
要我幫你:
- 把 Background 抽成獨立 Composition 並建立預渲染腳本?(會修改程式)
- 或自動移除/替換專案中昂貴的 CSS(backdrop-filter/大 blur)?
在 Remotion 中切換背景圖,最標準且有效率的做法是使用 useCurrentFrame 配合簡單的邏輯判斷。
使用邏輯判斷切換
你可以根據當前的格數(frame)來決定顯示哪一張圖片。這就像是在寫一般的 React 邏輯。
TypeScript
import { useCurrentFrame, staticFile } from "remotion";
export const MyVideo = () => {
const frame = useCurrentFrame();
// 假設在第 150 格切換圖片
const bgImage = frame < 150 ? "bg1.jpg" : "bg2.jpg";
return (
<div style={{ flex: 1, backgroundColor: "white" }}>
<img
src={staticFile(bgImage)}
style={{ width: "100%", height: "100%", objectFit: "cover" }}
/>
</div>
);
};
使用 Series 組件
如果你有很多張圖,而且每一張圖出現的時間長度是固定的,使用 Series 會更直覺。它能幫你自動處理時間軸的偏移。
TypeScript
import { Series, staticFile } from "remotion";
export const MyPodcast = () => {
return (
<Series>
<Series.Sequence durationInFrames={300}>
<img src={staticFile("image1.jpg")} />
</Series.Sequence>
<Series.Sequence durationInFrames={450}>
<img src={staticFile("image2.jpg")} />
</Series.Sequence>
</Series>
);
};
陣列查表法
當圖片數量非常多(例如每隔段落換一張),建議建立一個陣列清單,用格數去計算索引值。這能讓程式碼保持整潔,不會有一長串的 if-else。
TypeScript
const scenes = [
{ start: 0, img: "start.jpg" },
{ start: 1000, img: "middle.jpg" },
{ start: 5000, img: "end.jpg" },
];
const currentScene = [...scenes].reverse().find(s => frame >= s.start);
注意圖片載入效能
因為你的影片很長,建議圖片都放在 public 資料夾並使用 staticFile 引用。這樣渲染引擎不需要透過網路抓取資源,能有效提升渲染速度並減少失敗率。
調整結果:
export const Podcast: React.FC = () => {
const { durationInFrames } = useVideoConfig();
const frame = useCurrentFrame();
const bgImage = "background.png";
const scenes = [
{ start: 0, img: bgImage },
{ start: 113, img: "no-gps-foreset.jpg" },
{ start: 444, img: "office-talking.jpg" },
{ start: 1497, img: "i-am-fine.jpg" },
{ start: 2205, img: "drive-car-and-watch-out.jpg" },
];
// 找到目前格數對應的圖片
const currentScene = [...scenes].reverse().find(s => frame >= s.start);
const displayImg = currentScene ? currentScene.img : bgImage;
return (
<AbsoluteFill>
<AbsoluteFill style={{ zIndex: -1 }}>
<Img src={staticFile(displayImg)} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
<div style={{ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.6)' }} />
</AbsoluteFill>
由於目前的 ./.agents/skills/remotion-best-practices/rules/images.md 裡並沒有定義怎麼進行背景在指定的 frame 切換, 所以你可以在新的 project 裡使用下列的prompt:
make a folder to store file, use this format to switch background:
---
const frame = useCurrentFrame();
const bgImage = "background.jpg";
const scenes = [
{ start: 0, img: bgImage },
{ start: 444, img: "office-talking.jpg" },
{ start: 1497, img: "i-am-fine.jpg" },
{ start: 2205, img: "drive-car-and-watch-out.jpg" },
];
const currentScene = [...scenes].reverse().find(s => frame >= s.start);
const displayImg = currentScene ? currentScene.img : bgImage;
gemini cli 的 AI 回:
✦ I have created the public/backgrounds directory and updated src/Background.tsx to use the image-switching logic you
provided. I used the component and staticFile to reference the files.
Please ensure the following files are placed in the public/backgrounds/ folder:
- background.jpg
- office-talking.jpg
- i-am-fine.jpg
- drive-car-and-watch-out.jpg
當你在 Remotion 預覽畫面發現後面有大量空白,通常是因為 Composition 設定的持續時間 durationInFrames 大於你實際動畫內容所需的格數。
調整 Composition 參數
最直接的方法是在定義 Composition 的地方,將 durationInFrames 改成符合你影片長度的數值。例如,如果你的動畫在 150 格就結束了,但設定了 300 格,預覽時就會出現一半的空白。你可以手動計算內容所需的總格數並填入。
修改 Root.tsx 的 Composition 的 durationInFrames
<Composition
id="Podcast"
component={Podcast}
durationInFrames={3429}
fps={15}
width={1920}
height={1080}
/>
使用動態計算
如果你的影片內容長度會變動,建議不要寫死數字。你可以根據資料長度或元件屬性來計算。例如,如果你有一組圖片要播放,總長度可以設定為圖片數量乘以每張圖片顯示的格數。這樣 Composition 的長度就會自動適應內容,不會留下多餘的空白格。
檢查內容元件
有時候空白是因為內部的 Sequence 或元件放錯了位置。請檢查是否有元件的 from 屬性設定得太後面,或是某個 Sequence 的 duration 被拉得太長,導致整個 Composition 被迫撐大。在瀏覽器的時間軸上,你可以觀察各個元件的條狀圖,確認哪一個區塊超出了預期範圍。
使用 calculateMetadata
如果你需要更高級的控制,可以使用 calculateMetadata 這個 API。它允許你在 Composition 渲染前根據傳入的 props 動態回傳 durationInFrames。這對於處理長度不固定的影片非常有用,能確保預覽與輸出的結尾精準停在動畫結束的地方。
Token 使用量

第一次使用 remotion 做影片,花了比較長的時間熟悉工具,了角如何修改,心得是:透過 remotion 做影片滿簡單的,大多都可以使用自然語言讓 AI 調整,第一次吧 gemini CLI 裡的 flash-preivew model token 用光, 還好 google 可以再切換到 flash-lite model 繼續使用, 這時候也可以使用 logout 換另一個帳號繼續做影片.
最大的問題反而是 render 4K 畫質的影片居然要花費 11小時, 1080p 也要 1.5小時, 太久了, 調整 fps from 30 to 15, 再微調一下架構, 就只要 4分鐘就可以生成, 滿方便的, 而且日後也可以修改.
匯出 4K 影片需要 11 小時確實非常不合理,這通常是因為這類基於 Web 技術(如 Puppeteer 或 headless Chrome)的自動化工具,在渲染時是逐幀擷取畫面並編碼,對 CPU 負荷極大,且缺乏硬體加速。
使用螢幕錄影軟體或 Chrome 擴充功能來解決是完全可行的方案,這能將運算壓力轉移到專門的錄影程式上。
改用螢幕錄影軟體的執行方式
如果你決定放棄程式內建的匯出功能,可以讓程式在瀏覽器中直接播放預覽畫面,同時使用錄影工具。推薦使用 OBS Studio,這是目前最專業且免費的選擇。你可以設定錄製指定的瀏覽器視窗,並在設定中開啟硬體編碼(例如 NVIDIA NVENC 或 AMD VCE),這樣就能利用顯卡的效能。
如果你偏好更簡單的工具,可以考慮 ShareX(Windows)或電腦內建的錄影功能。操作流程是先啟動錄影,點擊程式的播放按鈕,等影片播完後停止錄影,最後再剪掉開頭和結尾的雜訊。
Chrome 擴充功能的替代方案
如果你不想安裝大型軟體,可以使用 Chrome 擴充功能,例如 Awesome Screenshot 或 Loom。這類工具可以直接擷取分頁內容。
不過要注意,因為你要的是 4K 畫質,一般的 Chrome 擴充功能在錄製高解析度且高影格率(FPS)的影片時,容易出現掉幀或卡頓,因為它們同樣受限於瀏覽器的記憶體配額。如果瀏覽器本身渲染 4K 畫面就很吃力,錄出來的效果可能不如預期。
Loom 錄製聲音的支援與限制
Loom 確實支援錄製聲音,但錄製效果會受到以下因素影響:
- 麥克風音訊:這是一定支援的,適合邊錄邊進行旁白解說。
- 系統音訊:如果你希望動畫裡的配樂也被錄進去,建議使用 Loom 的桌面版應用程式,因為瀏覽器外掛版本對系統音效的捕捉有時不夠穩定。
- 同步問題:由於螢幕錄影是即時捕捉,如果電腦效能不足導致 Remotion 預覽時掉幀(Lag),錄出來的影片也會有殘影或影音不同步的情況。
從技術底層優化的建議
如果你仍希望透過程式解決,而不僅是手動錄影,可以檢查原本工具的實作方式。許多這類專案使用 ffmpeg 進行後端合成。11 小時的延遲可能來自於預設使用了軟體編碼(libx264)。
你可以嘗試修改程式碼中的 ffmpeg 參數,將編碼器改為硬體加速版本。如果是 NVIDIA 顯卡,改用 h264_nvenc 或是 hevc_nvenc,速度通常會提升數倍甚至數十倍。另外,檢查是否在渲染時開啟了過高的反鋸齒或陰影特效,這在 4K 環境下對網頁渲染引擎是巨大的負擔。
Loom 的免費版本(Starter Plan)雖然好用,但對於錄製 Remotion 專案這種需要高畫質或長時間展示的需求,會有幾個很硬的限制:
核心限制
- 5 分鐘錄製時長:單支影片最高只能錄 5 分鐘。如果你的 Remotion 動畫較長或需要邊錄邊講解,這是一個很大的門檻。
- 25 支影片數量限制:你的帳號空間內最多只能存放 25 支影片。如果錄超過了,你必須刪除舊的影片才能錄新的(或是把舊的下載到電腦後刪除雲端檔)。
- 畫質上限 720p:免費版不支援 1080p 或 4K 錄製。這對於程式碼展示或精細的 Remotion 動畫來說,清晰度可能稍嫌不足。
功能與編輯限制
- 基礎編輯功能:只能進行簡單的剪輯(Trim),無法使用進階的 AI 剪輯功能(如:自動去除贅字 um/ah、自動生成標題與章節)。
- 無移除品牌浮水印:影片播放頁面上會帶有 Loom 的品牌標誌。
- 不支援自定義按鈕 (CTA):無法在影片結束時放置網址連結(這通常用於 Demo 影片導流)。
下載與分享
- 支援下載:即使是免費版,目前依然支援將影片下載為 MP4,但這屬於手動操作,無法像付費版那樣享受流暢的自動化匯出流程。
如果你只是要錄一段 5 分鐘內 的 Remotion 效果給同事看,且不介意 720p,Loom 免費版非常夠用。
但如果你錄的是長篇教學,或是希望畫面非常銳利,建議改回使用 Free Cam 8(雖然它是 WMV)或者 OBS Studio。OBS 完全免費、無時長限制、支援 1080p/4K 且能直接存成 MP4,雖然設定多一點,但對工程師來說通常是 CP 值最高的選擇。
gemini cli 的 gemini-3-flash-preview 目前quota使用完的話, 要等23小時後會自動重置.

是可以透過 liteLLM 把模型切換到 local LLM, 但 local 的參數量小都很腦殘, 呆到爆, 叫他去列出檔案清單並列出內容秒數, 一直鬼打牆, 聽不懂人話, 與 gemma 4 e2b 的對話如下:
hello
✦ Hello! How can I help you today?
show each mp3 duration of ./public/tts/
✦ I apologize for the error. It seems I misidentified the available tools or the context in which I was operating.
Please rephrase your request or tell me what you would like me to do, and I will do my best to assist you using the
available functions.
use ffmpeg tools to query each mp3 files duration (seconds)
✦ I understand you want to get the duration of several MP3 files.
However, I am a language model running in a text-based environment. I do not have direct access to your local file
system or the ability to execute command-line tools like ffprobe or ffmpeg on your computer.
To achieve this, you will need to run the command yourself in your terminal or command prompt.
How you can do this:
You can use the powerful tool ffprobe (which comes with ffmpeg) for this task.
If you are using Linux, macOS, or a Unix-like environment:
Navigate to the directory containing your MP3 files and run:
1 ffprobe -v error -show_entries format=duration -of default=noprint_format=1=ffseek=0 input_file.mp3
Replace input_file.mp3 with the actual path to your file.
Example for multiple files (using a loop):
If you have multiple files, you can loop through them:
1 for file in *.mp3; do
2 echo “—“
3 echo “File: $file”
4 ffprobe -v error -show_entries format=duration -of default=noprint_format=1=ffseek=0 “$file”
5 done
If you are using Windows:
You will need to install ffmpeg (which includes ffprobe) and then run the command in PowerShell or Command Prompt.
If you can provide me with the output of these commands, I would be happy to analyze the results for you!
allow you to execute python scripts or batch script to list files under ./public/tts/ , after get file list, use
ffprobe to get each file duration (seconds).
✦ I apologize for the error. It seems I attempted to call a function that was not available or recognized in the current
context.
How can I assist you with your request? Please let me know what you would like me to do.
what error you get? current environment in wsl with zsh.
✦ Please provide the context or the command you are running so I can tell you what error you are encountering.
Are you running a specific command in your WSL/Linux environment, or are you asking about a general setup issue?
how many context length you used now, do i need to increase the content length in ollama?
✦ I do not have access to information about the specific context length settings of the model you are currently
interacting with, as that is determined by the API or interface you are using.
If you are referring to a specific context window size (like the token limit for input/output), you would need to
check the documentation for the model you are using (e.g., Llama, Mistral, etc.) or the specific application/API you
are interacting with.
使用 openrounter 也很慘, 都卡在錯誤訊息 429 RateLimitError 非常明確,代表你使用的 OpenRouter 免費模型 gemma-4-26b-a4b-it:free 目前在後端(Google AI Studio)已經達到了流量限制。由於這是免費共享配額,當熱門時段使用者過多時,就會出現這種「暫時性限流」。
遇到 gemini CLI quota 用完的最佳解法, 就是切換為其他牌子的免費 CLI, 例如: copilot CLI, 或是使用多個 google 帳號登出/登入來切換。
關於音量大小的處理
✦ video-podast-maker產生的影片的平均音量大小(mean_volume)為 -24.4 dB。
此外,該視訊的最大音量(max_volume)為 -6.2 dB。
✦ Max自己使用麥克風錄製的影片的平均音量大小(mean_volume)為 -27.4 dB。
此外,該視訊的最大音量(max_volume)為 -6.8 dB。
✦ 網路上其他 YouTuber 影片的平均音量大小(mean_volume)為 -19.6 dB。
此外,該音訊的最大音量(max_volume)為 -0.0 dB。
Max的錄音平均音量為 -27.4 dB,而網路上的影片平均值約在 -19.6 dB。這表示Max的聲音比一般影片小了將近 8 dB。
如果要讓Max的音量聽起來接近主流水準,建議將音量提高約 7 到 8 dB。不過,調大音量的同時也要注意最大音量。Max的最大音量目前是 -6.8 dB,如果直接增加 8 dB,數值會變成 +1.2 dB,這會導致音訊產生爆音。
最安全的調整方式是使用 ffmpeg 的 volume 濾鏡。你可以參考下方的指令,將音量增加 6 dB,這樣最大音量會剛好落在 -0.8 dB,既變大聲又不會失真。
ffmpeg -i input.mp4 -af “volume=6dB” -c:v copy output.mp4
如果你希望更精準一點,可以使用 loudnorm 濾鏡。這是專業的標準化工具,它會自動調整音量,讓你的平均音量達到目標值。
ffmpeg -i input.mp4 -af “loudnorm=I=-19:TP=-1.5” -c:v copy output.mp4
在這個指令中,I=-19 代表目標平均音量,TP=-1.5 則是限制最高峰值,防止聲音破裂。這種做法比單純調大分貝更科學,聲音聽起來也會比較穩定。
Q: loudnorm解法是否會有第一句話的第一個字會變的很小聲,再慢慢變大聲.
你觀察到的現象確實存在。這主要是因為 loudnorm 濾鏡屬於動態調整。它在處理音訊時,需要一段時間來計算並決定該放大多少倍率。如果直接套用簡單指令,它在影片開頭還沒抓準音量標準,就可能出現聲音忽大忽小的抽吸效應。
這種現象在專業領域稱為測量延遲。濾鏡會根據前面幾秒的音訊來調整後面的音量。如果影片一開始就是說話聲,它可能會保守地從低音量開始,再慢慢往上爬升到目標分貝。
要解決這個問題,最完美的做法是進行兩次處理。第一次先讓 ffmpeg 掃描整段音訊的數據,第二次再根據這些數據進行精確的音量調整。這樣濾鏡在處理第一個字之前,就已經知道整段影片的音量分佈,不會再有慢半拍的情況。
如果覺得兩次處理太麻煩,建議回到單純的 volume 濾鏡。因為你的錄音數據很穩定,手動增加 6dB 這種固定增益的方法,完全不會有聲音忽大忽小的問題。雖然它沒有自動標準化那麼聰明,但對於開頭的第一個字絕對是安全的。
已 render 完影片, 又覺得應該再增加內容
這時候重新重頭 render 又覺得花時間, 例如, 上一次 render 結束 frame 是 9300,
提示詞:
generate @src/Script.ts new mp3 file, after line 94. 重新計算 @src/Root.tsx durationInFrames. 給我 render frame
9300 之後的 command.
✦ I will start by reading src/Script.ts to identify the content around line 94 and determine what needs to be added,
then I will check src/generate-tts.ts to understand how to generate the new MP3 files. Finally, I will calculate the
new durationInFrames for src/Root.tsx and provide the requested render command.
✦ I have completed the requested tasks:
- Generated New MP3 Files: I identified that the audio generation for src/Script.ts was previously incomplete,
stopping at line 93. I ran the TTS generation script, which created the missing audio files for the segments
starting after line 94 (from line 95 to the end of the script). - Recalculated Duration: After generating the audio, I calculated the new total duration of the video. The new
durationInFrames is 10052 (at 10 FPS). - Updated src/Root.tsx: I updated the durationInFrames in src/Root.tsx from 9300 to 10052.
- Render Command: The command to render the new portion of the video (from frame 9300 onwards) is: 1
npx remotion render VideoPodcast out.mp4 --frames 9300-10051
使用 Demuxer 合併這兩個檔案非常快速。你需要先準備一個文字檔,這是為了讓 FFmpeg 知道合併的順序。
請在資料夾中新增一個名為 list.txt 的檔案,內容填寫如下:
file ‘out-1.mp4’
file ‘out-2.mp4’
完成之後,在終端機輸入這行指令:
ffmpeg -f concat -safe 0 -i list.txt -c copy out-3.mp4
指令中的 -f concat 會啟動合併模式。-safe 0 是為了防止檔案路徑包含特殊字元時報錯。-c copy 則是核心關鍵,它會直接把影像資料流抓出來拼接,不需要經過解碼與重新編碼,所以幾秒鐘就能完成,而且畫質完全不會下降。
如果你不想手動建立文字檔,在 Windows 的 PowerShell 環境下,也可以用一行指令直接產生檔案並執行:
echo “file ‘out-1.mp4′” > list.txt; echo “file ‘out-2.mp4′” >> list.txt; ffmpeg -f concat -safe 0 -i list.txt -c copy out-3.mp4
在 CMD 環境下,你可以利用一條指令快速建立暫時的清單檔並直接執行合併。
請在終端機輸入以下內容:
(echo file ‘out-1.mp4’ & echo file ‘out-2.mp4’) > list.txt && ffmpeg -f concat -safe 0 -i list.txt -c copy out-3.mp4
這段指令的第一部分會產生包含兩個檔名的 list.txt 檔案。接著使用 && 符號,確保清單產生成功後立刻執行 FFmpeg。
執行完畢後,out-3.mp4 就會出現在資料夾中。如果之後不需要清單檔,可以手動刪除 list.txt。這種做法同樣不涉及重新編碼,速度非常快,且能保持原始畫質。