Sausage Erectos X ブラウザ内動画生成——Canvas録画とSNS最適化

ブラウザ内動画生成──Canvas録画からSNS投稿までの技術

Sausage Erectosのカスタマイザーでは、ユーザーが自分のフィギュアを回転させた動画を生成し、直接SNSにシェアできる。この機能の技術的な裏側を解説する。

Canvas.captureStream() の仕組み

ブラウザのCanvas要素から動画ストリームを取得する方法として、captureStream()APIを使用している。

const canvas = document.getElementById('three-canvas');
const stream = canvas.captureStream(30); // 30fps でキャプチャ

このAPIはCanvasの描画内容をリアルタイムでMediaStreamに変換する。Three.jsのレンダリングループが回っている間、フレームが自動的にキャプチャされる。

引数のフレームレートは「最大フレームレート」であり、Canvasの描画が追いつかない場合はフレームがドロップされる。安定した動画を得るためには、レンダリングパフォーマンスの確保が前提条件になる。

MediaRecorder APIの使い方

キャプチャしたストリームを動画ファイルに変換するのがMediaRecorder APIだ。

const recorder = new MediaRecorder(stream, {
  mimeType: 'video/webm;codecs=vp9',
  videoBitsPerSecond: 5000000, // 5Mbps
});

const chunks = [];
recorder.ondataavailable = (e) => {
  if (e.data.size > 0) chunks.push(e.data);
};

recorder.onstop = () => {
  const blob = new Blob(chunks, { type: 'video/webm' });
  const url = URL.createObjectURL(blob);
  // ダウンロードリンクを生成
};

recorder.start();
setTimeout(() => recorder.stop(), 5000); // 5秒間録画

フレームレート制御──30fps vs 60fps

フレームレートの選択は、品質とファイルサイズのトレードオフだ。

30fps: ファイルサイズ小、SNS投稿に十分な品質
       推定ファイルサイズ: 5秒で約3MB(5Mbps時)
60fps: 滑らかな動き、ファイルサイズ大
       推定ファイルサイズ: 5秒で約5MB(5Mbps時)

SNS投稿用途では30fpsで十分だ。60fpsは、スローモーション編集を前提とする場合にのみ推奨している。

エンコード形式──WebM vs MP4

ブラウザのMediaRecorder APIが標準でサポートするのはWebM形式(VP8/VP9コーデック)だ。しかし、多くのSNSプラットフォームはMP4(H.264)を推奨している。

// ブラウザのサポートを確認
const types = [
  'video/webm;codecs=vp9',
  'video/webm;codecs=vp8',
  'video/mp4;codecs=h264', // Safariのみサポート
];
const supported = types.filter(t => MediaRecorder.isTypeSupported(t));

Chrome/FirefoxではWebMを生成し、必要に応じてFFmpeg.wasm(ブラウザ内で動作するFFmpeg)でMP4に変換する戦略を取っている。SafariはネイティブでMP4をサポートする。

SNS別の最適動画サイズ

各SNSプラットフォームで最適な動画サイズが異なる:

Instagram投稿:  1080×1080(正方形)  最大60秒
Instagramリール: 1080×1920(9:16縦長)最大90秒
TikTok:         1080×1920(9:16縦長)最大10分
X(Twitter):    1280×720(16:9横長) 最大140秒
YouTube Shorts: 1080×1920(9:16縦長)最大60秒

カスタマイザーでは、録画開始前にプラットフォームを選択すると、自動的にCanvas のアスペクト比とリサイズが調整される仕組みにしている。

録画中のUI非表示テクニック

動画にUI要素(ボタン、スライダーなど)が映り込まないようにする必要がある。

function startRecording() {
  // UIを非表示
  document.querySelector('.controls').style.display = 'none';
  document.querySelector('.panel').style.display = 'none';

  // カメラの自動回転を開始
  autoRotate = true;

  // 次のフレームから録画開始(UI非表示が反映されてから)
  requestAnimationFrame(() => {
    recorder.start();
  });
}

ポイントはrequestAnimationFrameで1フレーム待つことだ。display: noneの反映とCanvasの再描画が完了してから録画を開始しないと、最初のフレームにUIが映り込む。

録画中は、カメラを自動回転させてフィギュアの全方位を見せる「ターンテーブル」モードを提供している。回転速度は5秒で1周がデフォルトだ。

動画は静止画の100倍の情報量を持つ。ブラウザ内でその情報量を生成できることは、Web技術の驚異的な進歩の証だ。

← ブログ一覧に戻る