Remotionのよくあるレンダリングエラーと解決法
Remotionのよくあるレンダリングエラーと解決法
Remotionのレンダリングで起きる不具合の大半は、ごく限られた原因に集約されます。そして原因さえ分かれば、それぞれに明確な解決法があります。Remotion Studioのプレビューでは問題なく見えるのに、いざレンダリングするとタイムアウトする、黒いフレームで固まる、フォントが反映されずに書き出される——こうした症状のほとんどは、数パターンのどれかに当てはまります。解放されないままのレンダー遅延、Remotionが評価しないCSSアニメーション、誤った方法で参照されたアセット、間違ったコンポーネントで描画された動画、レンダリング中のメモリ上限超過、といった具合です。
本記事では、Remotionでよく起きるレンダリングエラーを取り上げ、それぞれ なぜ 起きるのかを解説し、解決法を示します。上から順に読み進めても、自分の症状に合う箇所へ飛んでも構いません。
1. レンダリングがタイムアウトする
症状: レンダリングがタイムアウトエラーで失敗する。多くの場合、エラーメッセージに delayRender() のハンドルが言及されます。
原因: 非同期処理を待つために delayRender() を呼んだら、タイムアウト(デフォルトで30秒)以内に continueRender() を呼ぶ必要があります。あるコードパス(よくあるのは、呼び忘れたエラー分岐)がハンドルを解放しないままだと、レンダリングはタイムアウトするまでハングします。
解決法: すべての delayRender() に必ず対応する continueRender() があるようにします。catch ブロックの中も忘れずに。失敗時は cancelRender(error) を呼び、ハングさせずに有用なメッセージとともに即座にレンダリングを終了させましょう。
import { useDelayRender } from "remotion";
const { delayRender, continueRender, cancelRender } = useDelayRender();
const load = async () => {
const handle = delayRender("Loading data");
try {
const data = await fetch("/api/data").then((r) => r.json());
// ...use data...
continueRender(handle);
} catch (err) {
cancelRender(err); // never leave the handle open
}
};
処理が正当に30秒を超える場合は、delayRender() の timeoutInMilliseconds で上限を引き上げてください。詳しくは remotion.dev/docs/timeout を参照してください。
2. レンダリングでアニメーションが動かない
症状: ブラウザプレビューではアニメーションが再生されるのに、レンダリングした動画では固まって見える——あるいは最終状態だけが表示される。
原因: CSSトランジション、CSSキーフレームアニメーション、Tailwindのアニメーションクラスでアニメーションさせています。Remotionは各フレームを独立したスナップショットとしてレンダリングし、フレーム間で実時間ベースのCSSアニメーションを実行しません。そのため、これらは正しくレンダリングされません。
解決法: すべての動きを現在のフレームから駆動します。useCurrentFrame() を読み取り、interpolate() で値にマッピングしてください。
import { useCurrentFrame, interpolate } from "remotion";
export const FadeIn: React.FC = () => {
const frame = useCurrentFrame();
const opacity = interpolate(frame, [0, 30], [0, 1], {
extrapolateRight: "clamp",
});
return <div style={{ opacity }}>Hello</div>;
};
時間とともに変化するすべての視覚プロパティは、フレームの関数でなければなりません。レンダリングしたい要素からは transition:、@keyframes、アニメーション系のユーティリティクラスを取り除いてください。
3. 画像やアセットが読み込まれない
症状: レンダリングで画像・音声・動画が欠落する、または「存在するはず」のファイルパスでレンダリングがエラーになる。
原因: アセットを、開発時には動くが本番レンダリングでは動かない相対パスやimportパスで参照しています。Remotionはローカルアセットを public/ フォルダから配信するため、staticFile() で参照する必要があります。
解決法: アセットをプロジェクトルートの public/ に置き、staticFile() で参照します。
import { Img, staticFile } from "remotion";
export const Logo = () => (
<Img src={staticFile("logo.png")} style={{ width: 200 }} />
);
ネストしたフォルダ内のファイルは、public/ からの相対パスを渡します(例:staticFile("brand/logo.png"))。リモートURLはそのまま使え、staticFile() は不要です。詳しくは remotion.dev/docs/staticfile を参照してください。
4. 動画が黒いフレームでレンダリングされる
症状: 埋め込んだ動画がプレビューでは正しく表示されるのに、レンダリング結果では黒くなる、または固まる。
原因: 素のHTML <video> タグを使っています。レンダリング時、Remotionは正確なフレームにシークできるコンポーネントを必要とします。生の <video> 要素はフレーム単位で同期を保てません。
解決法: HTMLタグの代わりにRemotionのメディアコンポーネントを使います。remotion の <OffthreadVideo>、または @remotion/media の <Video> コンポーネントを使うことで、各フレームが正しいタイムスタンプで抽出されます。
import { OffthreadVideo, staticFile } from "remotion";
export const Clip = () => (
<OffthreadVideo src={staticFile("broll.mp4")} muted />
);
クリップの音声を動画にミックスしたくない場合は muted を付けます。クリップを使い回す際に予期せぬ音声の混入を招きやすいポイントです。
5. フォントがちらつく、または反映されない
症状: テキストがフォールバックフォントで表示される、または正しいフォントが一部のフレームでしか出ない。
原因: フレームがキャプチャされた時点で、フォントの読み込みが完了していませんでした。フォントの読み込みは非同期であり、レンダリングがそれを待っていませんでした。
解決法: レンダリングがフォントの読み込みを待つようにします。最もシンプルなのは、読み込みを肩代わりしてくれる @remotion/google-fonts です。FontFace API で読み込むカスタムのローカルフォントの場合は、読み込みを delayRender()/continueRender() で囲み、フォントの準備が整うまでRemotionにフレームを保持させます。
import { useDelayRender, staticFile } from "remotion";
import { useEffect } from "react";
const { delayRender, continueRender } = useDelayRender();
useEffect(() => {
const handle = delayRender("Loading font");
const font = new FontFace(
"Brand",
`url(${staticFile("Brand.woff2")})`
);
font.load().then(() => {
document.fonts.add(font);
continueRender(handle);
});
}, []);
6. メモリ不足になる、または大規模時にクラッシュする
症状: レンダリングがクラッシュする。特にAWS Lambda上や、長尺・高解像度・アセットの多いコンポジションで発生します。
原因: レンダリングが利用可能なメモリまたはディスクを超過しました。Lambda関数にはメモリと一時ストレージの上限が設定でき、動画を多用するコンポジションは負荷が高くなります。
解決法: ローカルレンダリングの場合は、他の重いプロセスを閉じ、チャンク分割でのレンダリングを検討します。@remotion/lambda の場合は、デプロイ時に関数のメモリとディスクサイズを増やし、必要なら関数あたりのコンカレンシーを下げます。多数の <video> 要素を同時に埋め込むよりも <OffthreadVideo> を優先してください。レンダリング時によりメモリ効率が良くなるよう設計されています。単一のコンポジションが極端に長い場合は、セグメントに分割してレンダリングし、あとで結合すればピークメモリを抑えられます。Lambdaとトラブルシューティングのドキュメントは remotion.dev/docs を参照してください。
7. 出力に音声が入らない
症状: 動画はレンダリングされるが音が出ない、またはクリップの音声が意図せず入ってしまう。
原因: 音声を素の <audio> タグ(レンダリング時に同期しません)で追加した、または動画クリップを、音声を消すべきなのにミュートせずに埋め込みました。
解決法: 音声は @remotion/media の <Audio> コンポーネントで追加し、ファイルは staticFile() で参照します。動画の映像だけがほしい場合は、動画コンポーネントに muted を付け、埋め込まれた音声がミックスに漏れ込まないようにします。
import { Audio } from "@remotion/media";
import { staticFile } from "remotion";
export const WithSound = () => <Audio src={staticFile("voiceover.mp3")} />;
クイックリファレンス
| 症状 | 考えられる原因 | 解決法 |
|---|---|---|
| レンダリングがタイムアウトする | continueRender() が呼ばれていない | すべての delayRender() を対応させる。エラー時は cancelRender() |
| アニメーションが固まる | CSS/Tailwindアニメーション | useCurrentFrame() + interpolate() を使う |
| アセットが欠落する | パスの誤り | public/ に置き、staticFile() を使う |
| 動画が黒いフレームになる | 素の <video> タグ | <OffthreadVideo> / @remotion/media を使う |
| フォントが誤る・ちらつく | フォントを待っていない | @remotion/google-fonts または delayRender() |
| メモリ不足 | 上限超過 | Lambdaのメモリ/ディスクを増やす。チャンク分割でレンダリング |
| 音声が出ない/音声が漏れる | 素の <audio> またはミュートし忘れたクリップ | @remotion/media の <Audio>。muted を付ける |
FAQ
Q: Remotionのアニメーションがプレビューでは動くのにレンダリングでは動かないのはなぜ?
ほぼ確実に、CSSトランジション・CSSキーフレーム・Tailwindのアニメーションクラスでアニメーションさせています。Remotionは各フレームを独立してレンダリングし、実時間ベースのCSSアニメーションを評価しません。代わりに、すべての動きを useCurrentFrame() と interpolate() で駆動してください。
Q: Remotionのレンダリングが何度もタイムアウトするのはなぜ?
よくある原因は、continueRender() によって解放されない delayRender() ハンドルで、多くはエラー分岐に潜んでいます。すべてのハンドルを対応させ、catch ブロックで cancelRender(error) を呼び、非同期処理が正当に30秒を超える場合にのみ timeoutInMilliseconds を引き上げてください。
Q: レンダリングした動画に画像が表示されないのはなぜ?
ローカルアセットは public/ フォルダに置き、staticFile() で参照する必要があります。開発時には動く相対パスやimportパスでも、レンダリング時には失敗することがあります。リモートURLはそのまま使えます。
Q: 埋め込んだ動画が出力で黒くなるのはなぜ?
おそらく素のHTML <video> タグを使っています。これはレンダリング時にフレーム単位でシークしません。remotion の <OffthreadVideo> または @remotion/media の <Video> を使い、各フレームが正しいタイムスタンプで抽出されるようにしてください。
Q: フォントのちらつきやフォールバックを止めるには?
レンダリングがフォントの読み込みを待つようにします。@remotion/google-fonts を使うか、FontFace で読み込むカスタムフォントの場合は読み込みを delayRender()/continueRender() で囲み、フォントの準備が整うまでRemotionにフレームを保持させてください。
Q: Lambdaでのメモリ不足エラーを解消するには?
Remotion Lambda関数に設定されたメモリとディスクサイズを増やし、必要なら関数あたりのコンカレンシーを下げ、動画には <OffthreadVideo> を優先し、非常に長いコンポジションはセグメントに分割してあとで結合してください。
RenderCompでもっと速く作る
レンダリングのバグの多くは、アセット・フォント・動画・データ読み込みを正しく組み上げるところから生まれます。RenderComp はプロダクション品質のRemotionテンプレート——イントロ・ロワーサード・SNS対応フォーマット・データビジュアライゼーションなど——を提供します。いずれも正しいパターン(staticFile()、OffthreadVideo、適切なデータ読み込み)が最初から組み込まれ、型付きのpropsがレンダーパイプラインですぐ使える状態になっています。落とし穴が減り、より速く出荷できます。
テンプレート一覧は rendercomp.com でご覧いただけます。初日からレンダリングを始めましょう。