「100%ローカル」はメディアファイルの話 — WhisperとffmpegをWASMに押し込んだ代償
ブラウザ完結の動画エディタrescriptを実際に動かして確かめたこと
「100%ローカル」という言葉は、メディアファイルが外に出ないという意味だ。何のデータも出ないという意味ではない。そしてローカルで動かす代償は、初回のモデルダウンロードと、サーバー設定が要る SharedArrayBuffer として返ってくる。読み終えれば、「ローカルファースト」のツールを選ぶとき何を確かめるか、似たものを自分で作るとき何を覚悟するかがわかる。
動かしてみたもの
Threadsでrescript(github.com/wassgha/rescript)が共有されていた。「文字起こしのテキストを消すと、動画・音声がその区間だけ切れる、100%ブラウザローカルのエディタ」だ。クローンして実際に動かしてみた(2026-08-24)。
npm install 741 packages / node_modules 1.3GB
起動 Next.js 16、Ready in 273ms
文字起こし サンプル動画(11.5秒)を正確に文字起こし。話者分離・単語ごとのタイムラインまで
自分で作った3文のサンプルが、誤字なくそのまま出てきた。文字起こしの品質は良かった。
ローカルの中身
サーバーがないのではなく、モデルとffmpegを丸ごとブラウザに押し込んだ構造だ。READMEによると、文字起こしはtransformers.jsでWhisper(baseとsmallのtimestamped版)を動かし、区間の切り出しと書き出しはマルチスレッド版のffmpeg.wasm(WebAssemblyにコンパイルしたffmpeg)が担う。WebGPUがあれば推論に使い、なければWASMにフォールバックする。
代償1 — 動かす条件
READMEはChromium系ブラウザを勧めていて、Web版には SharedArrayBuffer が必要だと書いている。マルチスレッドのffmpegがスレッド間でメモリを共有するのに使うものだ。問題は、これが crossOriginIsolated の状態でしか使えないことだ。そのためには、ページを配信するサーバーがヘッダーを2つ送る必要がある。
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
ローカルで処理するためにサーバー設定を触ることになる。require-corp を有効にすると、CORP・CORSヘッダーのない外部の画像やスクリプトが止まるので、既存のサービスに入れるなら外部リソースから点検する。
代償2 — 初回実行
ファイルを読み込んだ直後に「音声モデルをダウンロード中… 4%」と出た。モデルをブラウザに落としてくる。容量とかかる時間はまだ測れていない。サーバーで文字起こしするなら、ユーザーが味わわなくて済む待ち時間だ。
ところでテレメトリは既定でON
READMEによると、匿名の利用統計とクラッシュレポート(Sentryに送られる)が既定でオンになっている。設定 → Privacyでオフにできる。オフにした後にネットワークリクエストが実際に消えるかは、まだ確かめていない。
悪いことだと言いたいのではない。READMEに正直に書いてある。ただ「ローカル」と聞いたら、何がローカルなのかを別に確かめる必要がある、という話だ。
ライセンスもMITではない。PolyForm Noncommercial 1.0.0で、以前のリリースだけがMITのまま残っている。評価・学習は問題ないが、コードを商用サービスに持ち込むのはだめだ。考え方だけ参考にして自分で作るのは関係ない。
「ローカル」を見るときに確かめること
| 質問 | クラウドの文字起こしサービス | rescriptのようなブラウザローカル |
|---|---|---|
| メディアファイルは出ていくか | 出る(アップロード) | 出ない |
| それ以外に出るもの | サービス次第 | 利用統計・クラッシュレポート(既定でON) |
| 初回実行 | すぐ使える | モデルのダウンロード |
| サーバー側の要件 | なし(他社のサーバー) | COOP/COEPヘッダー |
| 処理速度 | サーバーの性能 | ユーザーの端末・WebGPUの有無 |
社内の映像のようにファイル自体を外に出せないなら、ローカルが合う。低スペック端末のユーザーが多い、あるいは最初の画面を早く出したいなら、サーバー側のほうがいい。
まだ切り分けられていないことがひとつある。ビデオのプレビューが黒い画面だった(video.readyState = 0)。音声はデコードされて文字起こしもできたので、音声トラックは読めている。合成テスト動画(testsrc2)のせいかアプリの問題かは、実際に撮った映像でもう一度見る必要がある。
ブラウザ内でAIモデルやWASMを動かす機能を検討しているなら、negabaroに相談してほしい。この記事と同じように、まず動かしてどこで詰まるかから一緒に見る。
キーポイント
「ローカル」はメディアファイルが出ないという意味。テレメトリ・クラッシュレポートは別に確認
マルチスレッドのffmpeg.wasmはSharedArrayBufferが必要で、サーバーがCOOP/COEPヘッダーを送る必要がある
初回実行時にモデルのダウンロード待ちが発生する
ライセンスを見る。rescriptはPolyForm Noncommercialで商用利用不可