> ## Documentation Index
> Fetch the complete documentation index at: https://docs.facebetter.net/llms.txt
> Use this file to discover all available pages before exploring further.

# サードパーティ連携

> ブラウザで Facebetter 美顔を TRTC、Agora、LiveKit などのリアルタイム動画パイプラインに接続します

SDK **2.0.0**。Web には、ネイティブのような統一された「GL テクスチャ前処理コールバック」は**ありません**。推奨パイプラインは次です。

**フレーム取得 → `processImage` → canvas へ描画 → `captureStream` / `MediaStreamTrack` を取り出す → サードパーティ SDK へ渡す（`replaceTrack` またはカスタム動画トラック）。**

認証は `licenseToken` のみです。`init()` の前に自社サーバーで取得します。フロントエンドに `appKey` を**入れないでください**。詳細: [認証とライセンス](/ja/intro/license)、[美顔の実装](/ja/web/implement-beauty)。

```
getUserMedia / vendor preview track
       ↓
HTMLVideoElement
       ↓
BeautyEffectEngine.processImage(...)
       ↓
canvas + putImageData
       ↓
canvas.captureStream() → MediaStreamTrack
       ↓
TRTC / Agora / LiveKit publish or replaceTrack
```

## 推奨パイプライン（ベンダー非依存）

```javascript theme={null}
import {
  BeautyEffectEngine,
  EngineConfig,
  FrameType,
  MirrorMode,
} from 'facebetter';

const engine = new BeautyEffectEngine(new EngineConfig({
  licenseToken: await fetch('/api/facebetter/auth', { method: 'POST' }).then((r) => r.text()),
}));
await engine.setLogConfig({ consoleEnabled: true, level: 2 });
await engine.init();

const video = document.createElement('video');
video.playsInline = true;
video.muted = true;
video.srcObject = await navigator.mediaDevices.getUserMedia({
  video: { width: 1280, height: 720 },
  audio: false,
});
await video.play();

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

function loop() {
  if (engine.initialized && video.readyState >= 2 && video.videoWidth > 0) {
    const result = engine.processImage(
      video,
      video.videoWidth,
      video.videoHeight,
      FrameType.Video,
      MirrorMode.Horizontal, // front camera as needed
    );
    if (result) {
      if (canvas.width !== result.width) canvas.width = result.width;
      if (canvas.height !== result.height) canvas.height = result.height;
      ctx.putImageData(result, 0, 0);
    }
  }
  requestAnimationFrame(loop);
}
loop();

// beauty video track: hand to any RTC / meeting SDK
const beautyStream = canvas.captureStream(30);
const beautyTrack = beautyStream.getVideoTracks()[0];
```

<Tip>
  `processImage` を優先してください。`processTexture` は既存の GPU テクスチャハンドル向けで、**ミラーを適用しません**。通常のライブプレビュー / 配信は上記の canvas パイプラインで十分です。
</Tip>

ページのアンロード時: `beautyTrack.stop()`、`requestAnimationFrame` を止め、`engine.destroy()` します。

***

## サードパーティ SDK への接続

各社の Web API 名はバージョンで変わります。以下は **`beautyTrack` を差し込む**よくある方法だけです。入室、Token、デバイス列挙は相手のドキュメントに従ってください。

### TRTC（Tencent Cloud Web）

よくある 2 つの方針です（使用する `trtc-js-sdk` / TUI バージョンに従います）。

1. **美顔トラックからローカルストリームを作成して公開**（カスタム動画ソース / `MediaStreamTrack` を渡す）
2. **公式どおりカメラストリームを作成してから `replaceTrack(beautyTrack)`** で動画トラックを置換

```javascript theme={null}
// sketch: replace the video track after obtaining a local stream
// const localStream = TRTC.createStream({ ... });
// await localStream.initialize();
// await localStream.replaceTrack(beautyTrack);
// await client.publish(localStream);
```

ネイティブと同じ `onProcessVideoFrame(textureId)` があると思わないでください。

### Agora Web

**カスタム動画トラック**を使うか、既存トラックに `replaceTrack` します。

```javascript theme={null}
import AgoraRTC from 'agora-rtc-sdk-ng';

// approach A: create a custom video track from MediaStreamTrack (API name per current agora-rtc-sdk-ng)
const customVideoTrack = AgoraRTC.createCustomVideoTrack({
  mediaStreamTrack: beautyTrack,
});
await client.publish([customVideoTrack /*, microphoneTrack */]);

// approach B: when a camera track already exists
// await cameraTrack.replaceTrack(beautyTrack);
```

### LiveKit Web

処理済みトラックを LiveKit のローカル動画トラック工場へ渡すか、公開済みトラックを差し替えます。

```javascript theme={null}
import { Room, LocalVideoTrack, createLocalVideoTrack } from 'livekit-client';

// sketch: create and publish from MediaStreamTrack (factory method per livekit-client version)
const track = LocalVideoTrack.createFromMediaStreamTrack(beautyTrack);
await room.localParticipant.publishTrack(track);

// or on an existing LocalVideoTrack:
// await localVideoTrack.replaceTrack(beautyTrack);
```

***

## 注意

| 項目           | 説明                                                                         |
| ------------ | -------------------------------------------------------------------------- |
| 認証           | 自社サーバーから `licenseToken` を取得                                                |
| パフォーマンス      | 同じ canvas を再利用。`captureStream` のフレームレートを制御。毎フレーム新しい canvas を作らない           |
| 音声           | 上の例は動画のみ。マイクトラックは `getUserMedia({ audio: true })` から別途取得して公開               |
| ミラー          | プレビューは `processImage` で `MirrorMode` を使えます。エンコード側と揃えるかは製品要件で判断             |
| ベンダーのアップグレード | `replaceTrack` / `createCustomVideoTrack` の署名は変わります。相手の現行 Web SDK に従ってください |

## トラブルシューティング

| 症状        | 確認                                                                 |
| --------- | ------------------------------------------------------------------ |
| 黒画面       | `video.videoWidth === 0`、`await engine.init()` していない、canvas サイズ未更新 |
| 遠隔側に美顔がない | **beautyTrack** を公開しているか、それとも元のカメラトラックを送り続けているか                    |
| 認証失敗      | プロキシが認証レスポンスをそのまま返しているか。ドメインがコンソールにバインド済みか                         |
| カクつき      | 解像度 / フレームレートを下げる。`processImage` ループが重複していないか                      |

## 関連ドキュメント

* [美顔の実装](/ja/web/implement-beauty)
* [ベストプラクティス](/ja/web/best-practices)
* [エラー処理](/ja/web/error-handling)
* [認証とライセンス](/ja/intro/license)
* [API リファレンス](/ja/web/api-reference)
