ffmpeg.wasmでSharedArrayBufferエラーが出るときの解決法
ffmpeg.wasm をWebアプリに組み込んだとき、SharedArrayBuffer is not defined や Atomics is not defined といったエラーが出て動作しないことがあります。このエラーはセキュリティ仕様の変更によるものです。
典型的なエラーメッセージ
SharedArrayBuffer is not defined
ReferenceError: SharedArrayBuffer is not defined
Cannot use SharedArrayBuffer in a cross-origin isolated context
Uncaught (in promise) ReferenceError: Atomics is not defined
原因
SharedArrayBuffer は Spectre/Meltdown 脆弱性対策として、2018年以降のブラウザでは Cross-Origin Isolated なページでのみ使用できるよう制限されました。
ffmpeg.wasm は内部でマルチスレッド処理のために SharedArrayBuffer を使います。そのため、ページが Cross-Origin Isolated である必要があります。
Cross-Origin Isolated にするための条件
ページのHTTPレスポンスヘッダーに以下の両方が必要です:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
解決方法1: サーバーでHTTPヘッダーを設定する(推奨)
Nginx
location / {
add_header Cross-Origin-Opener-Policy "same-origin";
add_header Cross-Origin-Embedder-Policy "require-corp";
}
Apache (.htaccess)
Header always set Cross-Origin-Opener-Policy "same-origin"
Header always set Cross-Origin-Embedder-Policy "require-corp"
Netlify (_headers ファイル)
/*
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Vercel (vercel.json)
{
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "Cross-Origin-Opener-Policy", "value": "same-origin" },
{ "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" }
]
}
]
}
Node.js / Express
app.use((req, res, next) => {
res.setHeader('Cross-Origin-Opener-Policy', 'same-origin');
res.setHeader('Cross-Origin-Embedder-Policy', 'require-corp');
next();
});
解決方法2: Service Worker(coi-serviceworker)を使う
サーバー設定を変更できない場合(GitHub Pages、Astro の静的サイトなど)は coi-serviceworker を使います。これはService Workerがリクエストを横断してCOOP/COEPヘッダーを注入する手法です。
セットアップ手順
1. coi-serviceworker.js を public ディレクトリに置く
gzuidhof/coi-serviceworker から最新版をダウンロードし、サイトのルートに配置します。
2. HTMLに登録コードを追加する
<script>
if (!self.crossOriginIsolated) {
navigator.serviceWorker.register('/coi-serviceworker.js').then(function(reg) {
if (!navigator.serviceWorker.controller) {
// Service Worker が新規登録された場合はリロードが必要
window.location.reload();
}
}).catch(function(e) {
console.warn('coi-serviceworker registration failed:', e);
});
}
</script>
注意点:
- Service Workerは同一オリジンのリクエストにのみ機能します
- HTTPSまたはlocalhost環境でのみ動作します
- 初回アクセス時にページリロードが発生します(次回以降は不要)
解決方法3: credentialless モード(Chrome 96+)
COEP: require-corp の代わりに credentialless を使うと、サードパーティリソース(Google Fonts、CDNなど)をクレデンシャルなしで読み込めます。
Cross-Origin-Embedder-Policy: credentialless
注意: Firefox 119+、Safari 17+ で対応。旧ブラウザでは
require-corpにフォールバックが必要です。
ブラウザの動作確認
ページが正しく Cross-Origin Isolated になっているかは以下で確認できます:
console.log(self.crossOriginIsolated); // true であれば OK
または Chrome DevTools の Console で確認してください。
Astroプロジェクトでの設定例
Astroのdev serverでも設定が必要です:
// astro.config.mjs
export default defineConfig({
vite: {
server: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
},
preview: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
},
},
});
静的ビルドをNetlifyやVercelにデプロイする場合は上記の各設定ファイルを使います。
ffmpeg.wasm が動作する環境の条件まとめ
| 条件 | 詳細 |
|---|---|
| HTTPS または localhost | HTTP本番環境では Service Worker が動作しない |
| SharedArrayBuffer 対応ブラウザ | Chrome 68+, Firefox 79+, Safari 15+ |
| COOP/COEP ヘッダー | サーバーで設定 または Service Worker で注入 |
| WebAssembly 対応 | 現在の主要ブラウザはすべて対応 |
関連ツール
当サイトのブラウザツールはすべてこの問題に対応しています:
関連リソース
よく使うオプション・フィルタ・コーデック設定をまとめた PDF チートシートです。手元に置いておくと調べる時間を短縮できます。
関連記事
一次ソース: developer.mozilla.org — SharedArrayBuffer / gzuidhof/coi-serviceworker