🥷
[iOS] 新SkyWayとSFUの初歩
はじめに
NTT Communicationsさんが提供している新SkyWayをちょこっと触ることになったのでまとめます。
Room, Core, SFU Botの3つライブラリが用意されていますが、その中のRoomを使っていきます。
また、SFUとP2Pがありますが、そのSFUを触ります
色々
用語
-
Room
- 通話を行うグループ。Roomを作成してRoomに参加したユーザー同士で通話を行う
-
Stream
- Room上で送受信ができるメディアのこと
- 3種類のStreamが提供されている
-
AudioStream
- ユーザーのマイク音声など
-
VideoStream
- ユーザーのカメラ映像など
-
DataStream
- 任意のメッセージ
-
AudioStream
-
Publish
- MemberがStreamをRoomに公開すること
- StreamをPublishするとRoom上にStreamに対応するPublicationというリソースが作成される
具体例
- Roomに入室する
let roominit = Room.InitOptions()
// Roomの名前
roominit.name = ""
// Roomを作成して入室する
let _ = try? await SFURoom.join(with: roominit)
// nameからRoomを探してなければ作成して入室する
let _ = try? await SFURoom.findOrCreate(with: roominit)
- Roomから退室する
// 入室
let room = try? await SFURoom.findOrCreate(with: roominit)
try await member.leave()
// または
room.leave(member)
// Roomを閉じずにRoomインスタンスを解放する
// これ以降roomのインスタンスにアクセスするとクラッシュするので注意
room.dispose()
// delegateも解放する
room.delegate = nil
room = nil
- Roomを閉じる
// Roomを閉じて、入室しているすべてのユーザーを退室させる
// 退室時と同様にこれ以降roomのインスタンスにアクセスするとクラッシュするので注意
try await room.close()
room.delegate = nil
room = nil
Roomが閉じられた時にRoomDelegateのfunc roomDidClose(_ room: Room)が呼ばれる
func roomDidClose(_ room: Room) {
// この中で保持しているroomの解放を行うのがよさそう
// delegate経由でもらうroomにアクセスしてもクラッシュするので注意
}
Publish
- カメラから映像を取得してPublishする
// フロントカメラを取得
let camera = CameraVideoSource.supportedCameras().first(where: { $0.position == .front })
// 背面のカメラを取得
let camera = CameraVideoSource.supportedCameras().first(where: { $0.position == .back })
// Streamを作成
let localVideoStream = CameraVideoSource.shared().createStream()
let _ = try? await member.publish(localVideoStream, options: nil)
- 端末の音声を取得してPublishする
// Streamを作成
let audioStream = MicrophoneAudioSource().createStream()
let audioPublication = try? await member?.publish(audioStream, options: nil)
// muteにする場合
audioPublication.disable()
// unmuteにする場合
audioPublication.enable()
- DataをPublishする&送信
let dataSource = DataSource()
// Streamを作成
let localDataStream = dataSource.createStream()
let _ = try? await member?.publish(localDataStream, options: nil)
// 文字列を送る
localDataStream.write("SkyWay")
// Data型を送る
localDataStream.write(data)
Subscribe
subscribeするためにはmemberのsubscribeを実行する
member.subscribe(publicationId: "id", options: nil)
では実際にpublicationIdをどうやって取得するかですが、RoomDelegateの以下を使うのがよさそうです
// StreamがPublishされた後に呼ばれる
func room(_ room: Room, didPublishStreamOf publication: RoomPublication) {
let publicationId = publication.id
}
// RoomのPublicationの数が変化した後に呼ばれる
func roomPublicationListDidChange(_ room: SkyWayRoom.Room) {
let publications = room.publications
}
- DataのSubscribe
Dataをsubscribeするには一手間必要で、RemoteDataStreamDelegateを使う必要がありそうです。(SFUでは利用できないので注意)
// StreamがPublishされた後に呼ばれる
func room(_ room: Room, didPublishStreamOf publication: RoomPublication) {
Task {
let subscription = try? await member?.subscribe(publicationId: publication.id, options: nil)
// dataかどうかを確認する
if publication.contentType == .data, let stream = subscription?.stream as? RemoteDataStream {
// RemoteDataStreamDelegate
stream.delegate = self
}
}
}
// RemoteDataStreamDelegate
func remoteDataStream(_ stream: RemoteDataStream, didReceiveData data: Data) {
// ここで取得できる
}
Tips
- Context Delegate
ContextのDelegateを使った場合は、必要なくなればnilを入れないとリークするので注意
Context.delegate = self
// 例えばroomをcloseするタイミング
Context.delegate = nil
...TDC
Discussion