導入ガイド¶
概要¶
Sora Flutter SDK を利用して Sora に接続する方法について説明します。
前提¶
- Flutter がセットアップ済みであること
Flutter のセットアップ方法については Flutter ドキュメント をご確認ください。
- 利用する Sora 環境があり、接続できる状態であること
Sora については Sora ドキュメント をご確認ください。
- 接続先の Sora シグナリング URL が分かっていること
- 接続先のチャネル ID が決まっていること
1. パッケージを追加する¶
sora_sdk は pub.dev から追加して利用できます。
flutter pub add sora_sdk
または pubspec.yaml に直接追加します。
dependencies:
sora_sdk: ^2026.0.0
追加後に依存関係を取得してください。
flutter pub get
2. SDK を import する¶
接続処理を書く Dart ファイルの先頭に、次の import を追加します。
最初は lib/main.dart や、接続処理を実装するファイルに追加してください。
import 'package:sora_sdk/sora_sdk.dart';
3. 接続設定を作成する¶
role には接続時の送受信方式を指定します。
最初は受信だけを行う recvonly か、送受信を行う sendrecv から始めるのがおすすめです。
final config = SoraConnectionConfig(
signalingUrls: <String>[
'wss://sora.example.com/signaling',
],
channelId: 'example-channel',
role: SoraRole.sendrecv,
video: true,
audio: true,
);
signalingUrls は List<String> で複数指定できます。SDK は先頭から順番に接続を試み、無効な URL は自動でスキップします。
4. SoraConnection を生成する¶
final conn = await Sora.createConnection(config);
Sora.createConnection() の時点で、プラットフォーム側のクライアント初期化と WebRTC クライアントの生成が行われます。
5. 接続状態を確認する¶
接続状態の変化やリモートトラックの追加を確認したい場合は、接続前に conn.events をでイベントを購読します。
イベント購読の例です。下記以外にも購読可能なイベントがあります。 イベントの一覧や発火タイミングの詳細は イベント をご確認ください。
final subscription = conn.events.listen((event) {
switch (event) {
case SoraConnectionStateChangedEvent(:final state):
// 接続状態の変化を確認する
print('connection state: $state');
if (state case SoraDisconnectedState(:final closeInfo)) {
if (closeInfo != null) {
// 切断時に close code / reason を取得できた場合
print('close: ${closeInfo.code} ${closeInfo.reason}');
}
}
case SoraConnectionErrorEvent(:final code, :final message):
// 接続エラーは別イベントで通知される
print('connection error: ${code ?? 'unknown'} ${message ?? ''}');
case SoraTrackEvent(:final track):
if (track.kind == 'video') {
// 受信した映像トラックの追加を確認する
print('remote video added: texture=${track.textureId}');
} else {
// 受信した音声トラックの追加を確認する
print('remote audio added: ${track.trackId}');
}
case SoraRemoveTrackEvent(:final track):
// 受信していたトラックの削除を確認する
print('remote track removed: ${track.trackId}');
default:
break;
}
});
StreamSubscription を使う場合はファイル先頭に import 'dart:async'; が必要です。
6. Sora に接続する¶
recvonly の場合は引数なしで接続します。
await conn.connect();
sendonly / sendrecv の場合は、 MediaDevices.getUserMedia() で MediaStream を作って connect() に渡します。ローカル映像をレンダリングする場合は、この MediaStream に含まれる LocalVideoTrack から textureId を取り出しておきます。
final stream = await MediaDevices.getUserMedia(
const GetUserMediaOptions(audio: true, video: true),
);
final localTextureId = await stream.getVideoTracks().first.textureId;
await conn.connect(stream);
接続が完了すると、 conn.events から SoraConnectionStateChangedEvent として SoraConnectedState が通知されます。
7. Flutter で映像をレンダリングする¶
ローカル映像は LocalVideoTrack.textureId 、リモート映像は conn.events の SoraTrackEvent (kind == 'video') で受け取る textureId を、それぞれ Texture ウィジェットに渡します。
映像レンダリング詳細については 映像レンダリングガイド をご確認ください。
class VideoView extends StatelessWidget {
const VideoView({super.key, required this.textureId});
final int textureId;
@override
Widget build(BuildContext context) {
return Texture(textureId: textureId);
}
}
複数のリモート映像が来る可能性があるため、リスト管理にしておくと扱いやすくなります。
8. Sora 接続の切断とリソース破棄¶
Sora から切断するには disconnect() を呼びます。
接続を再利用する場合は、切断後も同じインスタンスを使って再度 connect() を呼ぶことができます。
完全に使い終わったら、 disconnect() の後に dispose() を呼んでリソースを破棄してください。
await conn.disconnect();
await conn.dispose();
購読している StreamSubscription も破棄する必要があります。
getUserMedia() で作成した LocalMediaStream や track の解放方法は メディアデバイスガイド をご確認ください。
for (final subscription in subscriptions) {
await subscription.cancel();
}
最小サンプル¶
import 'dart:async';
import 'package:sora_sdk/sora_sdk.dart';
Future<void> startSora() async {
final conn = await Sora.createConnection(
SoraConnectionConfig(
signalingUrls: <String>[
'wss://sora.example.com/signaling',
],
channelId: 'example-channel',
role: SoraRole.recvonly,
),
);
final subscriptions = <StreamSubscription<dynamic>>[
conn.events.listen((event) {
switch (event) {
case SoraConnectionStateChangedEvent(:final state):
print('state=$state');
if (state case SoraDisconnectedState(:final closeInfo)) {
if (closeInfo != null) {
print('close=${closeInfo.code} ${closeInfo.reason}');
}
}
case SoraConnectionErrorEvent(:final code, :final message):
print('error=${code ?? 'unknown'} ${message ?? ''}');
case SoraTrackEvent(:final track):
if (track.kind == 'video') {
print('remote texture=${track.textureId}');
}
default:
break;
}
}),
];
try {
await conn.connect();
} catch (_) {
for (final subscription in subscriptions) {
await subscription.cancel();
}
await conn.dispose();
rethrow;
}
// 必要に応じて後で切断する
await conn.disconnect();
for (final subscription in subscriptions) {
await subscription.cancel();
}
await conn.dispose();
}
次に読むページ¶
- 接続オプションを詳しく知りたい場合は シグナリング設定
- イベントは イベント 、
Textureは 映像レンダリングガイド をご確認ください - OS 別の権限やビルドは 対応プラットフォーム と各 OS 向けガイド
- よくある質問は FAQ
- カメラ・マイク: メディアデバイスガイド
- 音声再生: 音声再生ガイド
- DataChannel: DataChannel 経由のシグナリング と リアルタイムメッセージング
- RPC: RPC 機能