Remotion LabRemotion Lab
疑難排解找不到指定位置的幀

找不到指定位置的幀

排解 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')} />;
};

相關資源