の続編
WebRTC
Web Real-Time Communicationの略で、動画や音声、データの相互通信する規格のことです。
It supports video, voice, and generic data to be sent between peers
WebRTC API - Web APIs | MDNが詳しく解説されています。
iOSでのWebRTCライブラリ
iOSアプリでGoogle Smart Device Management APIを使う (2025) - がんばってなんか書くでは
WebRTCのライブラリがないので、情報お待ちしております!
と終わったので、その後の調査から。
残念なことに、Googleからのモバイル向けの公式バイナリは配布停止されています。
PSA: WebRTC M80 Release Notes
WebRTC自体はオープンソースプロジェクトとして公開されているので、https://webrtc.googlesource.com/src を自分でコンパイルすれば使用可能です。
が、Swift Package Managerで手軽に管理したいので、今回は stasel/WebRTC を利用することにします。
Binary Targetとして、ビルド済みxcframeworkをリンクしてくれるので便利。
Smart Device Management APIを介したWebRTC接続
WebRTCの魅力の一つは相互に送受信できることですが、Nest Cam側の映像、音声を受信することに絞って考えます。
Nest Camにはスピーカーが付いているので、音声を送信することもできそうな気がする。
NSMicrophoneUsageDescriptionが必要になるはず。
手順
RTCPeerConnectionを作成 w/RTCDataChannel- SDP Offerを生成
- SDM APIにSDP Offerを送信
- sdm.devices.commands.CameraLiveStream.GenerateWebRtcStream
- SDP Answerを受信
RTCPeerConnectionにAnswer SDPを適用- 受信開始

1. RTCPeerConnectionを作成 w/RTCDataChannel
Factoryが用意されているので、必要な設定を詰めてRTCPeerConnectionを作成。
RTCDataChannelも接続します。
import WebRTC let factory = RTCPeerConnectionFactory() let constraints = RTCMediaConstraints( mandatoryConstraints: [ kRTCMediaConstraintsOfferToReceiveAudio: kRTCMediaConstraintsValueTrue, kRTCMediaConstraintsOfferToReceiveVideo: kRTCMediaConstraintsValueTrue, ], optionalConstraints: nil ) guard let peerConnection = factory.peerConnection( with: RTCConfiguration(), constraints: constraints, delegate: nil ) else { return } let dataChannelConfiguration = RTCDataChannelConfiguration() dataChannelConfiguration.isOrdered = true _ = peerConnection.dataChannel(forLabel: "foobar", configuration: dataChannelConfiguration)
2. SDP Offerを生成
RTCPeerConnectionから、OfferのSDPを生成。
RTCPeerConnection にLocal descriptionとして、適用します。
do { let offer = try await peerConnection.offer(for: constraints) try await peerConnection.setLocalDescription(offer) } catch { ... }
3. SDM APIにSDP Offerを送信
Smart Device Management APIのCommandを使って、WebRTCを生成します。
sdm.devices.commands.CameraLiveStream.GenerateWebRtcStream
POST /enterprises/project-id/devices/device-id:executeCommand { "command" : "sdm.devices.commands.CameraLiveStream.GenerateWebRtcStream", "params" : { "offerSdp" : "\(offer.sdp)" } }
4. SDP Answerを受信
APIレスポンスの answerSdp を使います。
{ "results" : { "answerSdp" : "answerSdp", "expiresAt" : "2020-01-04T18:30:00.000Z", "mediaSessionId" : "Bshco5XLhPxzdJYfQn7Kwtp4yd..." } }
5. RTCPeerConnectionにAnswer SDPを適用
RTCPeerConnection にRemote descriptionとして、適用します。
do { ... try await peerConnection.setRemoteDescription( RTCSessionDescription(type: .answer, sdp: response.results.answerSdp) ) } catch { ... }
6. 受信開始
RTCPeerConnectionからRTCVideoTrackを取り出し、
let videoTrack = peerConnection.transceivers .first(where: { $0.mediaType == .video })? .receiver.track as? RTCVideoTrack
RTCMTLVideoView に表示
import SwiftUI struct VideoView: UIViewRepresentable { var videoTrack: RTCVideoTrack func makeUIView(context: Context) -> RTCMTLVideoView { let view = RTCMTLVideoView() view.videoContentMode = .scaleAspectFit return view } func updateUIView(_ uiView: RTCMTLVideoView, context: Context) { videoTrack.add(uiView) } }
表示
Desing for iPadとして、macOSやvisionOSでも実行可能です。
おわり
- 本日7/4開催 Mobile Act OSAKA 16 のネタを詳しく解説
- Google Nest Camの映像を、WebRTCでアプリに表示できた
宣伝
さらにこの先の拡張について、iOSDC Japan 2025にプロポーザルを応募しています。
お気に入り、応援よろしくお願いします!!!