Agora.ioからWeb用のバーチャル背景機能(β)がリリースされました

この記事では公式ドキュメントの[Use the Virtual Background Extension](https://docs.agora.io/en/Video/virtual_background_web_ng?platform=Web)を翻訳した内容になります。

## 概要
この*agora-extension-virtual-background*拡張機能は、バーチャル背景機能を実装するためにAgora Web SDK（v4.10.0以降）と一緒に使用されます。
この機能により、ユーザーは実際の背景をぼかしたり、単色または画像に置き換えたりすることができます。
この拡張機能は、オンライン会議、オンラインクラス、ライブストリーミングなどのシナリオに適用できます。
個人のプライバシーを保護し、視聴者が気を散らすのを減らすのに役立ちます。

次の図は、拡張機能がどのように機能するかを示しています。
![1647325748630.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/4583fc21-05b1-0614-254e-774635a24979.png)

**2022/7/5追記**
WebSDK　v4.12.0から背景に動画を設定する事ができるようになりました。
![1654508267206.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/0d1b1e2c-b793-57f4-e815-8b59d083af90.gif)


## 注意事項
 - この拡張機能は、カメラでキャプチャされたビデオにユーザーが1人しかいない場合に最適に機能します。
 - バーチャル背景拡張機能のブラウザサポートは次のとおりです。
   - より優れたバーチャル背景を実現するために、Agoraは最新バージョンのデスクトップChromeでこの機能を使用することをお勧めします。
   - Agoraは、FirefoxおよびSafariブラウザでバーチャル背景機能を有効にすることを推奨していません。FirefoxでWebアプリをバックグラウンド処理すると、ビデオがフリーズする可能性がありますが、Safariでのパフォーマンスは、ブラウザー自体のパフォーマンスの問題のために低下する可能性があります。
   - Agoraは、モバイルブラウザでバーチャル背景機能を有効にすることを推奨していません。
 - バーチャル背景機能には、高いパフォーマンス要件があります。コンピュータが次の要件を満たしていることを確認してください。
   - CPU：Intel Corei5 4コア以上
   - 8GRAM以上
   - 64 Bit OS

## 処理概要
Agora Web SDKの一般的な送信パイプラインは、キャプチャ、前処理、エンコード、送信、デコード、後処理、再生などの一連の手順で構成されています。前処理段階で、拡張機能はパイプラインのオーディオおよびビデオデータを変更して、バーチャル背景やノイズキャンセルなどの機能を実装できます。
![1647326674232.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/fcf7eb90-239b-fb69-bcf8-c490fb0972ae.png)

## 実装方法
以下のようにバーチャル背景拡張機能を組み込みます。
 - クイックスタートガイドを参照して、Web SDK（v4.10.0以降）を組み込み、プロジェクトに基本的なビデオ通話機能を実装してください。
 - npmを介してバーチャル背景拡張機能をプロジェクトに組み込みます。
 - 拡張機能をインストールするには、次のコマンドを実行します。
```
npm install agora-extension-virtual-background
```
 - 拡張機能をインポートするには、次のいずれかの方法を使用します。

方法1：JavaScriptファイルに次のコードを追加します。

```javascript
import {VirtualBackgroundExtension} from "agora-extension-virtual-background";
```

方法2：HTMLファイルでScriptタグを使用します。インポートすると、VirtualBackgroundExtensionオブジェクトをJavaScriptファイルで直接使用できます。
```javascript
<script src="./agora-extension-virtual-background.js"></script>
```

 -  Wasm依存ファイルを動的にロードする：バーチャル背景拡張機能はWasmファイルに依存します。node_modules/agora-extension-virtual-background/wasms以下にWasmファイルがあります。WasmファイルをCDNまたは静的リソースサーバーに公開する必要があります。以降の手順で呼び出すときは、WasmファイルのURLを渡す必要があります。拡張機能は、Wasmファイルを動的にロードします。

:::note warn
注意事項
WasmファイルのホストURLがWebアプリケーションのホストURLと同じでない場合は、CORSポリシーを有効にします。
HTTPSドメインへのHTTPリソースのロードはブラウザのセキュリティポリシーによってブロックされているため、WasmファイルをHTTPサービスに配置しないでください。
:::

 - バーチャル背景拡張機能を登録します。
```javascript
// Create a client object
var client = AgoraRTC.createClient({mode: "rtc", codec: "vp8"});
// Create a VirtualBackgroundExtension instance
const extension = new VirtualBackgroundExtension();
// Register the extension
AgoraRTC.registerExtensions([extension]);
```
 - バーチャル背景拡張機能を初期化します。
```javascript
processor = extension.createProcessor();
```
- 拡張機能を初期化するために呼び出します。この方法では、WasmモジュールのURLを渡す必要があります。リソースのロードまたは拡張機能の初期化が失敗した場合、このメソッドは例外をスローします。この例外をキャッチし、それに応じて処理します。

```javascript
await processor.init("./assets/wasms");
```

- ローカルカメラトラックを作成した後、videoTrack.pipeでvideoTrack.processorDestination拡張機能をSDKのメディア処理パイプラインに挿入します。
```javascript
localTracks.videoTrack.pipe(processor).pipe(localTracks.videoTrack.processorDestination);
```

- processor.setOptionsで仮想背景タイプを選択し、設定を行います。Agoraは次の設定をサポートしています。

背景として単色を設定
```javascript
processor.setOptions({type: 'color', color: '#00ff00'});
```

画像を背景として設定
```javascript
processor.setOptions({type: 'img', source: HTMLImageElement});
```

元の背景をぼかす(低:1、中:2、高:3)
```javascript
processor.setOptions({type: 'blur', blurDegree: 2});
```

- processor.enableで、仮想バックグラウンド機能を有効にします。
```javascript
await processor.enable();
```

setOptionsをコールしない場合、デフォルトで元の背景をぼかす（低)になります。切り替えはsetOptionsを呼び出すだけです。


## サンプルコード
```javascript
import AgoraRTC from "agora-rtc-sdk-ng";
import {VirtualBackgroundExtension} from "agora-extension-virtual-background";

// Create a client object
var client = AgoraRTC.createClient({mode: "rtc", codec: "vp8"});
// Create a VirtualBackgroundExtension instance
const extension = new VirtualBackgroundExtension();
// Register the extension
AgoraRTC.registerExtensions([extension]);

let processor = null;
var localTracks = {
  videoTrack: null,
  audioTrack: null
};

// Initialization
async function getProcessorInstance() {
  if (!processor && localTracks.videoTrack) {
    // Create a VirtualBackgroundProcessor instance
    processor = extension.createProcessor();

      try {
        // Initialize the extension and pass in the URL of the Wasm file
        await processor.init("./assets/wasms");
        } catch(e) {
          console.log("Fail to load WASM resource!");return null;
          }
    // Inject the extension into the video processing pipeline in the SDK
    localTracks.videoTrack.pipe(processor).pipe(localTracks.videoTrack.processorDestination);
  }
  return processor;
}

// Join a channel
async function join() {
  // Add event listeners
  client.on("user-published", handleUserPublished);
  client.on("user-unpublished", handleUserUnpublished);

  [options.uid, localTracks.audioTrack, localTracks.videoTrack] = await Promise.all([
    // Join a channel
    client.join(options.appid, options.channel, options.token || null),
    // Create a local microphone track and camera track
    localTracks.audioTrack || AgoraRTC.createMicrophoneAudioTrack(),
    localTracks.videoTrack || AgoraRTC.createCameraVideoTrack({encoderConfig: '720p_4'})
  ]);

  // Play local tracks
  localTracks.videoTrack.play("local-player");
}

// Set a solid color as the background
async function setBackgroundColor() {
  if (localTracks.videoTrack) {
    document.getElementById("loading").style.display = "block";

    let processor = await getProcessorInstance();

    try {
      processor.setOptions({type: 'color', color: '#00ff00'});
      await processor.enable();
    } finally {
      document.getElementById("loading").style.display = "none";
    }

    virtualBackgroundEnabled = true;
  }
}

// Blur the user's actual background
async function setBackgroundBlurring() {
  if (localTracks.videoTrack) {
    document.getElementById("loading").style.display = "block";

    let processor = await getProcessorInstance();

    try {
      processor.setOptions({type: 'blur', blurDegree: 2});
      await processor.enable();
    } finally {
      document.getElementById("loading").style.display = "none";
    }

    virtualBackgroundEnabled = true;
  }
}

// Set an image as the background
async function setBackgroundImage() {
    const imgElement = document.createElement('img');

    imgElement.onload = async() => {
      document.getElementById("loading").style.display = "block";

      let processor = await getProcessorInstance();

      try {
        processor.setOptions({type: 'img', source: imgElement});
        await processor.enable();
      } finally {
        document.getElementById("loading").style.display = "none";
      }

      virtualBackgroundEnabled = true;
    }
    imgElement.src = '/images/background.png';
}
```

Agoraは多くのサンプルコードを[GitHub](https://github.com/AgoraIO/API-Examples-Web/tree/main/Demo)に公開しています。
このバーチャル背景の[サンプル](https://github.com/AgoraIO/API-Examples-Web/tree/main/Demo/virtualBackground)も公開されています。


## 最後に                                                                                                    
[**agora.ioに関するお問い合わせはこちらから**](https://jp.vcube.com/lp/agora?utm_campaign=Agora&utm_source=Qiita&arc_id=2faf9b350a0bd0303059)   
[<img width="912" alt="スクリーンショット 0001-08-15 13.41.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/300377/5d815376-9b89-08fa-9434-6fa7e8e67bcf.png">](https://jp.vcube.com/lp/agora?utm_campaign=Agora&utm_source=Qiita&arc_id=2faf9b350a0bd0303059)