HB DevTools

Knowledge

ブラウザ完結の背景除去ライブラリ @imgly/background-removal の使い方と onnxruntime-web バージョン固定の落とし穴

@imgly/background-removal を使ってブラウザ上でAI背景除去を実現する方法を解説。WASM/ONNXパイプラインの仕組み、dynamic importによるバンドル最適化、そして onnxruntime-web のバージョン不一致で発生するクラッシュとその対策を紹介します。

ブラウザAIWASMパフォーマンス

1. @imgly/background-removal とは

@imgly/background-removal は、ドイツのメディア処理ライブラリ会社 IMG.LY が開発・OSS公開したブラウザ専用の背景除去ライブラリです。 画像をサーバーへ送らず、ブラウザ上で完結して処理できるため、 プライバシーを重視するユースケースに適しています。

内部では onnxruntime-web を使い、 ONNX形式のAIモデルをWASM(WebAssembly)で実行します。 使用されるモデルは ISNet(Image Segmentation Network)という セグメンテーション用のDNNモデルです。

WASMバイナリとモデルファイルはCDNから動的に取得します。 初回のみダウンロードが発生し、以降はブラウザキャッシュで即起動します。 ライブラリ本体+WASMで数MB超になるため、dynamic import によるコード分割が必須です。

2. WASM/ONNX パイプラインの仕組み

処理フローは以下のとおりです。

ブラウザ
  ├─ JS バインディング(onnxruntime-web npm pkg)
  └─ WASM バイナリ(CDN から fetch: ort-wasm-simd-threaded.wasm 等)
       └─ ONNXモデル(isnet.onnx / isnet_fp16.onnx / isnet_quint8.onnx)
            └─ 推論 → アルファマスク生成 → PNG合成(透過背景)

処理の進捗は progress コールバックで受け取れます。 コールバックの引数 key でフェーズを判別できます。

  • key.startsWith('fetch') または key.startsWith('ort:load') → モデル取得フェーズ
  • それ以外 → 推論フェーズ

UIでは「モデル読み込み中」と「処理中」を別々に表示することで、 ユーザーが処理の段階を把握しやすくなります。

3. 実際の使い方

① dynamic import(バンドル最適化)

トップレベルで import するとビルド時に全バンドルされてしまいます。 実行タイミングでのみ import することでバンドルサイズを削減できます。

// NG: トップレベルに書くとビルド時に全バンドルされる
import { removeBackground } from '@imgly/background-removal'

// OK: 実行タイミングでのみ import → バンドルサイズを削減
const { removeBackground } = await import('@imgly/background-removal')

② progress コールバックでUIフェーズを管理

const resultBlob = await removeBackground(file, {
  model: 'isnet',
  progress: (key: string, current: number, total: number) => {
    const pct = total > 0 ? Math.round((current / total) * 100) : 0
    const isLoadPhase = key.startsWith('fetch') || key.startsWith('ort:load')
    setPhase(isLoadPhase ? 'model-download' : 'processing')
    setProgressPct(pct)
  },
})

③ model オプション(精度 vs 速度)

model オプションで精度と速度のバランスを選択できます。

  • 'isnet' — 最高精度・最低速。フルFP32モデル。
  • 'isnet_fp16' — 標準精度・普通速度。省略時のデフォルト。
  • 'isnet_quint8' — 低精度・最高速。量子化モデル。

戻り値は Blob(MIME: image/png)です。URL.createObjectURL() でプレビューやダウンロードに使用できます。

4. onnxruntime-web バージョン不一致によるクラッシュ

発生したエラー:

Failed to create session: TypeError: r._OrtGetInputOutputMetadata is not a function.
Please check if the publicPath is set correctly.

一見「publicPath の設定ミス」に見えますが、実際の原因はバージョン不一致です。

構造の解説:

@imgly/background-removal@1.7.0
  └─ peerDependency: onnxruntime-web@1.21.0
       ↑ CDN配信のWASMバイナリはこのバージョン向けにビルドされている

npm install 後("^1.21.0" 指定時):
  └─ onnxruntime-web@1.24.2(最新)がインストールされる
       ↑ JS APIが1.24.x仕様に変わり、1.21.0用WASMと不一致 → クラッシュ

@imgly/background-removal はCDNからWASMバイナリを動的に取得します。 このバイナリは peerDependency に指定されたバージョン向けにビルドされています。^(キャレット)による範囲指定でインストールすると、 JSバインディングだけ新バージョンに更新されてWASMバイナリと不一致が生じます。

解決策:

// ❌ キャレット(範囲指定)— JSバインディングだけ更新されてWASMと不一致になる
"onnxruntime-web": "^1.21.0"

// ✅ 完全固定 — peerDependencyに記載のバージョンに合わせる
"onnxruntime-web": "1.21.0"

peerDependency の確認方法:

npm info @imgly/background-removal peerDependencies
# → { 'onnxruntime-web': '1.21.0' }

教訓: WASMやネイティブバイナリを含むライブラリは、 JSバインディングとバイナリのバージョンがペアで動作します。 CDNからバイナリを動的取得するライブラリでは ^ による範囲指定は危険です。 peerDependencyに指定されたバージョンを完全固定で使うことが重要です。

5. 精度チューニングと限界

model: 'isnet' が最大精度のオプションです。 感度・閾値・フェザリングなどの細かいパラメータは現時点のAPIには存在しません。 これ以上の精度向上はライブラリの設定では実現できません。

精度をさらに向上させたい場合の選択肢は以下のとおりです。

  • サーバーサイドAPI(remove.bg、Adobe Firefly等): 精度は大幅に向上しますが、画像をサーバーへ送信するためプライバシー要件と相反します。
  • プライバシー優先ユースケース: ブラウザ完結という制約を受け入れ、isnet モデルでの精度を許容値として設計します。 背景が単色・コントラストが高い画像では十分な精度が得られます。

ブラウザ完結という強みとトレードオフの関係にある点を理解した上で、 ユースケースに合わせて技術選定を行うことが重要です。