RoomとP2PRoom・SFURoomの併用
概要
Room(type: default。以下 Room)は P2P 通信と SFU 通信を同一 Room 内で Publish することが可能な新しいタイプの Room です。
Room を使うことで、以下のユースケースに対応できます。
- 録音・録画(SFUを利用)と同時に P2P で通話を行う
- SFU で通話をしながら P2P でデータ通信を行う
- 人数に応じて P2P/SFU での通話を使い分ける
Room は既存の P2PRoom および SFURoom と相互接続が可能であり、アプリ側で段階的に移行することが可能です。
Roomに対応しているSDK
2025年10月現在、Room に対応している SDK は以下の通りです。
- JavaScript SDK(v2.0.0以降)
- iOS SDK(v3.1.0以降)
- Android SDK(v3.3.0以降)
P2PRoom/SFURoomとの違い
P2PRoom/SFURoom は、作成した時点で通信方式が固定されます。 P2P と SFU を併用したい場合はそれぞれに対応する Room を作成する必要があり、SkyWay Auth Token や Member などのリソース管理が複雑になる問題がありました。
// 通信方式を指定してP2PRoomを作成する const room = await SkyWayRoom.FindOrCreate(context, { type: "p2p" }); const me = await room.join(); // 通信方式は必ずP2Pになる await me.publish(audio);
一方、Room は作成した時点ではなく、Publish 時に通信方式を指定します。
// 作成時点では通信方式が固定されない const room = await SkyWayRoom.FindOrCreate(context); const me = await room.join(); // Publish時に通信方式指定する await me.publish(audio, {type: "p2p"}); // 同一Memberから異なる通信方式でPublishすることもできる await me.publish(video, {type: "sfu"});
このように、1つの Room 内で P2P と SFU を柔軟に併用できます。
P2PRoom/SFURoomとの相互接続
SDK のアップデート時に、Room を利用するアプリと P2PRoom/SFURoom を利用するアプリが混在するケースがあります。 この場合、Room と P2PRoom/SFURoom を相互に接続することが可能です。
ただし、注意点があります。 Room に対応していないバージョンの SDK において SFURoom から Publish を行った場合、対向の Room からは Publication が2つあるように見えます。 そのため、イベントをハンドリングする際にフィルター処理を行う必要があります。
JavaScript SDK
// Publisher側(SFURoomを使用) const room = await SkyWayRoom.FindOrCreate(context, { type: "sfu", name: "room1" }); const me = await room.join(); await me.publish(audio);
// Subscriber側(Roomを使用) const room = await SkyWayRoom.FindOrCreate(context, { name: "room1" }); const me = await room.join(); room.onStreamPublished.add((e) => { // P2PのPublicationの場合はスキップする if (e.publication.type == "p2p") return me.subscribe(e.publication) });
iOS SDK
// Publisher側(SFURoomを使用) let roomInit: Room.InitOptions = .init() roomInit.name = "room1" let room = try? await SFURoom.findOrCreate(with: roomInit) let me = try? await room?.join(with: nil) _ = try? await me?.publish(audio, options: nil)
// Subscriber側(Roomを使用) let roomInit: Room.InitOptions = .init() roomInit.name = "room1" self.room = try? await Room.findOrCreate(with: roomInit) self.room?.delegate = self self.me = try? await self.room?.join(with: nil) // MARK: - RoomDelegate func room(_ room: Room, didPublishStreamOf publication: RoomPublication) { if publication.type == .P2P { return } Task { try? await self.me?.subscribe(publicationId: publication.id, options: nil) } }
Android SDK
// Publisher側(SFURoomを使用) val room = SFURoom.findOrCreate(name = "room1") val me = room?.join(memberInit) me.publish(audio)
// Subscriber側(Roomを使用) val room = SFURoom.findOrCreate(name = "room1") val me = room?.join(memberInit) room?.onStreamPublishedHandler = Any@{ // P2PのPublicationの場合はスキップする if (it.type == RoomPublication.Type.P2P) return@Any me.subscribe(it) }
通信方式の切り替え
Publish した後に通信方式を変更することはできません。 通信方式を切り替えたい場合は、一度 Unpublish してから再度 type を変更して Publish してください。