🎬

Tooscut — ブラウザで動くGPU加速映像エディタ

WebGPU + Rust/WASMでネイティブ級リアルタイム合成をブラウザで実現する仕組み

Tooscutはブラウザタブ1つで動くNLE(Non-Linear Editor)だ。DaVinci ResolveやPremiere Proをインストールせず、URLにアクセスするだけで映像編集を始められる。

ただ「ブラウザ映像エディタ」と聞くと普通はおもちゃレベルを想像する。Tooscutが違うのは、レンダリングエンジン全体がRust/WASM + WebGPUで動くという点だ。JavaScriptはUI担当のみ。実際のフレーム合成はGPUで処理される。

3層アーキテクチャ

React UI(TanStack Start)→ TypeScriptレンダーエンジン → Rust/WASMコンポジター。コードベースはTypeScript 80%、Rust 20%の比率。そのRust 20%が性能の核心を全て担う。

GPU加速が実際に何をするか

明るさ・コントラスト・彩度・ブラー・色相回転 — これらのエフェクトが全て1つのWGSLフラグメントシェーダー内で動く。スライダーを動かすとGPUユニフォーム値だけが変わり、シェーダーが即座に再実行される。CPUは触らない。

ブラーを例にすると、13×13ガウシアンカーネルがシェーダー内にハードコードされている。sigma値に応じてステップサイズをスケーリングする方式で、ブラー強度を変えてもテクスチャパスの追加は不要だ。

リアルタイムプレビューパイプライン

ここが一番巧妙な部分だ。

  1. メインスレッドでrequestAnimationFrameループを回す
  2. 現在時刻に表示されるクリップだけをフィルタリング(ソート済み配列 + 二分探索)
  3. HTMLVideoElementからcreateImageBitmap()でビデオフレームを抽出
  4. ImageBitmapをWeb Workerにtransfer(コピーではない)
  5. Worker内のWASMコンポジターがWebGPUでOffscreenCanvasに直接合成

4番がポイントだ。ImageBitmap transferはゼロコピー — メインスレッドのメモリの所有権をWorkerに移すだけで複製コストがない。テクスチャアップロードもcopy_external_image_to_textureでGPUに直接転送する。

メモリ管理

WASM linear memoryはV8ヒープにカウントされない。GPUバッファはVRAMに、BitmapはネイティブアロケーションJavaScript。ビデオファイルは全体をメモリに載せずオンデマンドでデコードする。この構造のおかげで4K映像もブラウザタブのメモリ制限に引っかからない。

エクスポート

FrameRendererPoolで複数のWeb Workerを並列実行する。各Workerに独立したWASMコンポジターがあり、フレームを分割してレンダリングする。MediaBunnyライブラリがMP4マルチプレクシングを担当。

JSから直接WebGPUを使えばいいのでは?

使える。WebGPUはJavaScript APIなのでJSから直接呼ぶのが本来の正攻法だ。GPUで動くシェーダーコード(WGSL)はJSでもRustでも完全に同一で、ブラー・明るさ・コントラストなどのエフェクト性能に差はない。

差が出るのはGPU外でCPUが処理する部分だ。毎フレーム、キーフレーム補間(ベジエカーブ)、4×4行列演算、ユニフォームバッファパッキング(128バイト、16バイトアラインメント)を16.6ms以内に終わらせる必要がある。

処理JSRust/WASM
キーフレーム補間V8 JIT最適化に依存コンパイル時最適化、SIMD可能
ユニフォームバッファArrayBufferの手動オフセット計算Pod deriveで構造体→バイト自動変換
オーディオミキシング(~128サンプル)GCジッターリスクGCなし — リアルタイムオーディオに致命的差

結論:トラック3〜4個、エフェクト1〜2個ならJSで十分だ。トラック10個以上+キーフレーム数十個+オーディオエフェクトチェーンになるとJSのGC(ガベージコレクション)がランダムにフレームを落とす。オーディオは~128サンプル(~2.9ms)単位のコールバックで、GCが挟まると音が途切れる。TooscutがRustを選んだ本当の理由は速度ではなくGCのない決定論的タイミングだ。

レンダリングパイプライン詳細

フレーム合成フロー

Main Thread requestAnimationFrameループ → 現在時刻の可視クリップをフィルタリング(二分探索)→ buildRenderFrame()でキーフレーム評価 + Transform/Effects統合
Video Decode HTMLVideoElementcreateImageBitmap() → ImageBitmapをWorkerにtransfer(ゼロコピー)
Web Worker Comlinkプロキシ → WASM Compositor.renderFrame() → WebGPUパイプライン実行 → OffscreenCanvasに直接出力
GPU テクスチャアップロード(copy_external_image_to_texture) → バーテックスシェーダー(フルスクリーンクワッド)→ フラグメントシェーダー(エフェクトチェーン)→ アルファブレンディング合成

GPUエフェクトシェーダー実装

全エフェクトが単一WGSLフラグメントシェーダー内で順次適用される。ユニフォームバッファ1つ(128バイト)で全パラメータを伝達。

エフェクト シェーダー実装 性能特性
ブラー 13×13ガウシアンカーネル、sigmaベースステップスケーリング シングルパス — 追加テクスチャ不要
明るさ color.rgb * brightness 乗算1回
コントラスト (rgb - 0.5) * contrast + 0.5 ベクトル演算1回
彩度 luminance(dot積)ベース mix(grayscale, color, saturation) dot + mix演算
色相回転 RGB → HSL変換 → H += radian → HSL → RGB 色空間変換2回
トランジション UV座標ベース smoothstepマスキング(Wipe L/R/U/D) ピクセル単位条件分岐なし

適用順序:ブラー → 明るさ → コントラスト → 彩度 → 色相回転 → トランジション → 不透明度 → clamp

Rust/WASMクレート構成

クレート 役割 コア技術
compositor GPU合成エンジン — メディア/テキスト/図形/ライン描画 wgpu, glyphon, cosmic-text
keyframe キーフレーム補間 — Linear/Step/Bezier 時間的一貫性キャッシュ(順次O(1)、シークO(log n))
audio-engine AudioWorkletマルチトラックミキサー — EQ/コンプ/リバーブ ~128サンプル単位リアルタイムPCM出力
types 共有型定義 — tsify-nextでTS型自動生成 serde + wasm-bindgen

メモリ管理戦略

  • WASM linear memory — V8ヒープにカウントされない。DevToolsのJSヒープサイズとは別
  • GPUバッファ — VRAMに格納。TextureManagerが同サイズテクスチャはデータ更新のみで再生成しない
  • ビデオデコード — 全体ロードなし。オンデマンドバッファリングウィンドウ方式。プレビューはHTMLVideoElement(ブラウザ最適化)、エクスポートはMediaBunny(フレーム精度)
  • ImageBitmap transfer — メインスレッド→Worker移動時に所有権移転(ゼロコピー)。複製コストなし

開発者バックグラウンド

Mohamad Mohebifar — Codemod共同創業者 & CTO。Meta、Brex、Shopify出身。コード変換/トランスパイラー10年+のキャリア。WorldSkills 2015銅メダル(Web Design & Development)。目標は「映像編集版Photopea」— インストールなしで日常的な編集作業の80%をカバーすること。

実践ステップ

1

tooscut.appにアクセス → ブラウザで直接エディタ実行(インストール不要)

2

File System Access APIでローカルファイルを直接参照 — アップロード/ダウンロードなしで編集可能

3

タイムラインにビデオ・オーディオ・画像・テキスト・図形クリップを配置

4

キーフレームパネルで位置・サイズ・不透明度・エフェクトにベジエカーブアニメーション適用

5

エクスポート時にFrameRendererPoolが並列Workerでレンダリング → MP4出力

メリット

  • インストールゼロ — URLアクセスだけでプロ編集機能利用
  • GPU加速リアルタイムエフェクト — スライダー操作時レンダリング遅延なし
  • Local-first — メディアファイルがサーバーに送信されない
  • Rust/WASMエンジン — ネイティブの90〜95%性能

デメリット

  • WebGPU必須 — Safari非対応、Firefox不安定(事実上Chrome専用)
  • 8Kマルチトラックやカラーグレーディングのようなハイエンド作業はDaVinci Resolve領域
  • Elastic License 2.0 — OSI定義のオープンソースではない(商用ホスティング制限)

ユースケース

YouTube動画カット編集 — デスクトップアプリインストールなしで素早く 出張中に借りたPCで映像編集が必要なとき Chromebook等アプリインストールが制限された環境 プライバシー優先 — ファイルをサーバーにアップロードできない場合