• #html2canvas
  • #MediaRecorder
  • #Animation
  • #Debug

ダウンロード動画でアニメーションが反映されない件(仮説メモ)

症状

  • Download Video ボタン実行で生成される WebM がチカチカするだけで、チャットの出現アニメーションが再現されない
  • プレビューの Play では想定どおりのフェード&スライド表示になるが、録画結果ではメッセージが静止状態のまま
  • 同じフレームが繰り返し記録されているように見える(メッセージが一瞬だけ写る/真っ白になる)

再現条件(現状)

  • apps/web/content/2025-12-03/message-mockup.htmlfile:// で直接開き、Download Video を押下
  • デフォルトの初期メッセージ 2 件でも発生

原因仮説

  1. html2canvas のレンダリング遅延
    • 1フレームごとに html2canvas を実行しており、DOM 変更→描画→待ち時間 30ms のループがリアルタイムに追いついていない
    • canvas.captureStream(0) で 0fps に設定しているため、requestFrame() を呼んでもレンダリング完了前の古いフレームが拾われている可能性
  2. フレームの時間管理ずれ
    • await sleep(30) で待機しているが、html2canvas の非同期処理時間(>100ms)が無視され、結果的に 1 コマを複数回 push → チカチカ
    • hold 区間で同じ canvas インスタンスを複数 push しており、後続で canvas が再利用されると同一フレームが上書きされるリスク
  3. DOM スナップショットが中途半端
    • newElement に opacity/transform を設定した直後にキャプチャしており、レイアウトが安定する前に描画が始まっている
    • scale:2 指定により描画時間がさらに増大
  4. MediaRecorder 設定のミスマッチ
    • stream.framerate=0(デフォルト)だと動画時間の計算がズレ、再生側でのフレーム間隔が不均一になる可能性

録画との整合

  • 手元の WebM 録画でもメッセージ出現が反映されずチカチカする症状が再現し、上記「フレーム重複/タイミングずれ」仮説と一致。

当面試したい切り分け

  • html2canvas 1 回のみ実行し、既存 canvas のピクセルを ctx.putImageData で複製 → フレーム配列に入れてもチカチカするか確認
  • canvas.captureStream(30) に固定し、各フレーム描画後に await new Promise(r => requestAnimationFrame(r)) を挟んで MediaRecorder に一定周期で渡す
  • scale:1 に下げて計測(描画時間短縮効果が大きいか)
  • file:// ではなく npx serve apps/web/content/2025-12-03 などローカル HTTP で開き、Worker/CORS 由来の遅延がないか比較

恒久的な対応案(優先度順)

  1. html2canvas をフレーム毎に回さない
    • 初回のみ DOM→canvas にレンダリングし、以降は Canvas 上でトランジションを直接描く(テキスト配置を自前実装)
    • 労力は高いが最も安定した動画出力が期待できる
  2. フレーム生成と録画を分離
    • 全フレームを ImageBitmap/Blob でプリレンダ→VideoEncoder (WebCodecs) または gifenc で連結
    • MediaRecorder 依存を外すことでフレーム間隔を完全制御
  3. アニメーションを CSS + requestAnimationFrame に寄せる
    • DOM 側で実際にアニメーションを走らせ、captureStream(30) でリアルタイム録画(スクリプトはプレイヤー用と録画用で共用)
    • タイムライン管理を CSS トランジション開始時刻ではなく rAF で司る
  4. 解像度とエンコーディングを下げる暫定策
    • scale:1videoBitsPerSecond を 2〜3Mbps に落としてまず滑らかさを確保

追加で欲しい計測

  • html2canvas 1 回あたりの実測時間(Performance.now で計測)
  • 出力 WebM のフレーム数・再生時間(ffprobe 等)
  • 端末/ブラウザ別の再現性(Chrome/Edge/Firefox)

関連ファイル

  • apps/web/content/2025-12-03/message-mockup.html
  • apps/web/content/2025-12-03/message-mockup.js
  • apps/web/content/2025-12-03/message-mockup.css