找不到指定位置的幀
排解 Remotion 中「No frame found at position」錯誤,了解影片幀提取失敗的原因與修復方式。
找不到指定位置的幀
錯誤訊息
Error: No frame found at position X.
或類似的變體:
No frame was found at the requested timestamp.
Could not extract frame at position X from video.
其中 X 是請求的時間位置(秒)或幀號。
錯誤發生的時機
此錯誤通常在 Remotion 嘗試從影片中提取特定時間點的幀時發生,常見於:
- 使用
<OffthreadVideo>元件渲染包含影片的 Composition - 在渲染過程中,
<Video>元件需要讀取特定幀 - 使用
getVideoMetadata()或相關 API 查詢影片資訊時 - 在接近影片結尾的幀進行渲染時
常見原因與解決方案
原因一:影片不支援 Seeking(可定位)
最常見的原因是使用了不支援 seeking 的影片格式或串流協定。Remotion 的逐幀渲染機制需要能夠跳轉至影片中的任意時間點,若影片不支援此操作,就會出現此錯誤。
常見的不可 seek 格式:
- 純 RTSP / HLS 直播串流
- 部分 MPEG-TS(
.ts)格式的影片 - 沒有索引(moov atom)的 MP4 檔案
解決方案:使用可正確 seek 的影片格式(標準 MP4),並確保影片的 moov atom 在檔案開頭(faststart):
# 使用 FFmpeg 重新封裝影片,將 moov atom 移至開頭
ffmpeg -i input.mp4 -movflags faststart -c copy output.mp4詳見不可 seek 的媒體。
原因二:請求的時間點超出影片時長
若你嘗試提取的幀位置超過了影片實際的時長,就會出現此錯誤。
診斷方式:確認 Composition 的時長是否超過所使用影片的時長:
import { getVideoMetadata } from '@remotion/media-utils';
import { useEffect } from 'react';
// 在開發環境中確認影片時長
useEffect(() => {
getVideoMetadata('https://example.com/video.mp4').then((meta) => {
console.log('影片時長:', meta.durationInSeconds, '秒');
});
}, []);若 Composition 較長,可以使用 <Video> 或 <OffthreadVideo> 的 loop 屬性讓影片循環播放:
import { OffthreadVideo, staticFile } from 'remotion';
export const MyComp: React.FC = () => {
return (
<OffthreadVideo
src={staticFile('background.mp4')}
loop // 自動循環,避免超出影片時長
/>
);
};或使用 endAt 屬性限制播放時長在有效範圍內:
<OffthreadVideo
src={staticFile('clip.mp4')}
endAt={90} // 只播放到第 90 幀
/>原因三:影片末尾的幀提取問題
某些影片在最後幾幀可能無法被正確提取,這是部分編碼格式的已知限制。
解決方案:使用 endAt 稍微提前影片的結束點:
<OffthreadVideo
src={staticFile('video.mp4')}
endAt={durationInFrames - 2} // 提前 2 幀結束,避免邊界問題
/>原因四:影片檔案損壞或格式不完整
若影片檔案本身有問題(下載不完整、傳輸中斷等),也可能無法在特定位置找到幀。
驗證影片檔案:
# 使用 FFmpeg 檢查影片完整性
ffmpeg -v error -i input.mp4 -f null -
# 取得影片詳細資訊
ffprobe -v quiet -print_format json -show_format -show_streams input.mp4若有錯誤輸出,表示影片檔案可能損壞,需要重新取得來源檔案。
原因五:並行渲染時的競態條件
在高並行渲染(多個影格同時渲染)的情況下,若影片伺服器無法快速響應多個 seek 請求,可能偶發此錯誤。
解決方案:降低並行數量:
npx remotion render MyComposition out/video.mp4 --concurrency=4或在 Node.js API 中設定:
await renderMedia({
composition,
serveUrl,
codec: 'h264',
outputLocation: 'out/video.mp4',
concurrency: 4,
});原因六:網路資源無法訪問
若影片來源是網路 URL,可能因為網路問題、CORS 限制或伺服器拒絕導致無法取得特定幀。
確認資源可訪問:
# 測試影片是否可下載
curl -I https://example.com/video.mp4確認回應包含 Accept-Ranges: bytes 標頭,這表示伺服器支援 Range 請求(seeking 所需)。
使用 <Video> 與 <OffthreadVideo> 的差異
<Video>:依賴瀏覽器的原生影片播放,可能在某些 seek 操作上遇到問題<OffthreadVideo>:使用 Mediabunny / FFmpeg 逐幀提取,更可靠但對影片格式要求更嚴格
若使用 <Video> 時遇到幀提取問題,嘗試改用 <OffthreadVideo>:
// 改用 OffthreadVideo
import { OffthreadVideo, staticFile } from 'remotion';
export const MyComp: React.FC = () => {
return <OffthreadVideo src={staticFile('video.mp4')} />;
};