FlutterでiOSアプリにTRTCを導入してリアルタイム通話を実装する

## 🔧 はじめに：導入の背景と目的

最近、Flutterで開発中のiOSアプリに「1対1のリアルタイムビデオ通話機能」を追加することになりました。要件は以下の通り：

- ネイティブとのブリッジを最小限に抑えつつ、FlutterでUIを完結させたい  
- 映像と音声の品質が高く、グローバルな通信でも安定すること  
- 料金とドキュメントのバランスが良いSDKを選びたい

技術選定の結果、Tencent CloudのTRTC（Tencent Real-Time Communication）SDKがFlutter Pluginも提供しており、品質・コストのバランスも良いため、採用することにしました。

---

## 🔍 技術調査とTRTCを選んだ理由

他に検討した選択肢：

- **WebRTC（自前実装）**：自由度は高いが、ネイティブとの連携やTURN設定が複雑  
- **Agora、Zoom SDK**：使いやすいが、価格やプラグインのカスタマイズ性に課題あり  
- **TRTC**：日本語対応こそ限定的だが、中国国内・APAC地域に強く、Flutter公式Pluginあり

TRTCの評価ポイント：

| 項目             | 内容                                                       |
|------------------|------------------------------------------------------------|
| SDK対応          | Flutter Pluginあり（iOS/Android共通）                     |
| 機能             | 通話、ライブ配信、録画、美顔、音量提示、画面共有など     |
| 技術サポート     | GitHub Issueと中国本家のフォーラム、または商用窓口あり    |
| コスト           | 従量課金制で、試用枠も比較的広い                          |

---

## 📦 セットアップとFlutterプロジェクトの準備

### 1. pubspec.yamlの依存追加：

```yaml
dependencies:
  flutter:
    sdk: flutter
  trtc_cloud: ^1.0.4 # 最新はhttps://pub.dev/packages/trtc_cloud で確認
```

### 2. iOSのネイティブ設定（info.plist）

```xml
<key>NSCameraUsageDescription</key>
<string>カメラの使用が必要です</string>
<key>NSMicrophoneUsageDescription</key>
<string>マイクの使用が必要です</string>
```

### 3. Xcodeでの設定

- iOS Deployment Targetは `12.0` 以上に設定
- `Runner.xcodeproj` > `Build Settings` > `Other Linker Flags` に `-ObjC` を追加

---

## 🚀 TRTC接続実装：Flutterコード（iOS）

### 1. 初期化とローカルビデオ表示の準備

```dart
import 'package:flutter/material.dart';
import 'package:trtc_cloud/trtc_cloud.dart';

class CallPage extends StatefulWidget {
  final int roomId;
  final String userId;
  final String userSig;

  const CallPage({required this.roomId, required this.userId, required this.userSig});

  @override
  _CallPageState createState() => _CallPageState();
}

class _CallPageState extends State<CallPage> {
  late TRTCCloud trtcCloud;
  final int _localViewId = 1001;
  final int _remoteViewId = 1002;

  @override
  void initState() {
    super.initState();
    _initTRTC();
  }

  Future<void> _initTRTC() async {
    trtcCloud = TRTCCloud.sharedInstance();
    await trtcCloud.startLocalPreview(true, _localViewId);
    await trtcCloud.startLocalAudio(TRTCAudioQuality.TRTC_AUDIO_QUALITY_DEFAULT);

    final params = TRTCParams(
      sdkAppId: 1400000000, // TRTC.ioで取得
      userId: widget.userId,
      userSig: widget.userSig,
      roomId: widget.roomId,
      role: TRTCCloudDef.TRTCRoleAnchor,
    );

    await trtcCloud.enterRoom(params, TRTCCloudDef.TRTC_APP_SCENE_VIDEOCALL);
  }

  @override
  void dispose() {
    trtcCloud.exitRoom();
    trtcCloud.stopLocalPreview();
    trtcCloud.stopLocalAudio();
    TRTCCloud.destroySharedInstance();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("TRTCビデオ通話")),
      body: Stack(
        children: [
          TRTCCloudVideoView(viewId: _localViewId), // 自分の映像
          Align(
            alignment: Alignment.topRight,
            child: SizedBox(
              width: 120,
              height: 160,
              child: TRTCCloudVideoView(viewId: _remoteViewId), // 相手の映像
            ),
          ),
        ],
      ),
    );
  }
}
```

### 2. コールバック処理（例：リモートユーザーが入室したとき）

```dart
trtcCloud.registerListener((type, param) {
  if (type == TRTCCloudListener.onUserVideoAvailable) {
    final userId = param["userId"];
    final available = param["available"];
    if (available) {
      trtcCloud.startRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG, _remoteViewId);
    } else {
      trtcCloud.stopRemoteView(userId, TRTCCloudDef.TRTC_VIDEO_STREAM_TYPE_BIG);
    }
  }
});
```

---

## ✅ 実機テスト結果

| テスト環境       | 結果                         |
|------------------|------------------------------|
| iPhone 12（4G） | 映像・音声ともに滑らか       |
| iPhone SE（WiFi）| 通信状態によって300msの遅延あり |
| Androidとの通信 | Flutterプラグインで問題なし  |

弱点：
- 接続エラー時のログがやや分かりづらい（Flutter側に詳細出ない）
- `userSig`の生成が手動だと煩雑（→ 自動生成用にサーバ側実装を検討）

---

## 📝 まとめ

TRTCのFlutterプラグインを用いたiOSでの導入は、FlutterのUI資産を活かしつつ、比較的簡潔に音声・映像通話機能を追加できました。日本語での情報がまだ少ないため、この日記が今後導入を検討する開発者の参考になれば幸いです。

**今後追加予定の機能：**
- 通話中のネットワーク品質監視
- 通話中の録画（Cloud Recording API）
- スクリーン共有やドキュメント表示との連携