WebRTC 客戶端
Web 即時通訊 (WebRTC) 是一組用於瀏覽器和原生應用程式中即時、點對點通訊的標準和 API。
Ktor 中的 WebRTC 客戶端可在多平台專案中實現即時點對點通訊。透過 WebRTC,您可以建置以下功能:
- 視訊與語音通話
- 多人遊戲
- 協作應用程式 (白板、編輯器等)
- 客戶端之間低延遲的資料交換
新增依賴
若要使用 WebRtcClient,您需要在建構腳本中包含 ktor-client-webrtc artifact:
建立客戶端
建立 WebRtcClient 時,請根據您的目標平台選擇一個引擎:
- JS/Wasm:
JsWebRtc– 使用瀏覽器的RTCPeerConnection和媒體設備。 - Android:
AndroidWebRtc– 使用PeerConnectionFactory和 Android 媒體 API。
然後,您可以提供類似於 HttpClient 的平台特定設定。STUN/TURN 伺服器是 ICE 正常運作所必需的。您可以使用現有的解決方案,例如 coturn:
val jsClient = WebRtcClient(JsWebRtc) {
defaultConnectionConfig = {
iceServers = listOf(WebRtc.IceServer("stun:stun.l.google.com:19302"))
}
}val androidClient = WebRtcClient(AndroidWebRtc) {
context = appContext // Required: provide Android context
defaultConnectionConfig = {
iceServers = listOf(WebRtc.IceServer("stun:stun.l.google.com:19302"))
}
}建立連線並協商 SDP
建立 WebRtcClient 後,下一步是建立對等連線。 對等連線是管理兩個客戶端之間即時通訊的核心物件。
為了建立連線,WebRTC 使用會話描述協議 (SDP)。這涉及三個步驟:
- 一個對等端 (呼叫者) 建立一個 offer。
- 另一個對等端 (被呼叫者) 以一個 answer 回應。
- 兩個對等端都應用對方的描述來完成設定。
// 呼叫者建立連線和 offer
val caller = jsClient.createPeerConnection()
val offer = caller.createOffer()
caller.setLocalDescription(offer)
// 透過您的訊號傳輸機制將 offer.sdp 傳送給遠端對等端
// 被呼叫者接收 offer 並建立 answer
val callee = jsClient.createPeerConnection()
callee.setRemoteDescription(
WebRtc.SessionDescription(WebRtc.SessionDescriptionType.OFFER, remoteOfferSdp)
)
val answer = callee.createAnswer()
callee.setLocalDescription(answer)
// 透過訊號傳輸將 answer.sdp 傳送回呼叫者
// 呼叫者應用 answer
caller.setRemoteDescription(
WebRtc.SessionDescription(WebRtc.SessionDescriptionType.ANSWER, remoteAnswerSdp)
)交換 ICE 候選者
SDP 協商完成後,對等端仍需要發現如何跨網路連線。互動式連線建立 (ICE) 允許對等端找到彼此的網路路徑。
- 每個對等端收集自己的 ICE 候選者。
- 這些候選者必須透過您選擇的訊號傳輸通道傳送給另一個對等端。
- 一旦兩個對等端都新增了對方的候選者,連線即可成功。
// 收集並傳送本地候選者
scope.launch {
caller.iceCandidates.collect { candidate ->
// 將 candidate.candidate、candidate.sdpMid、candidate.sdpMLineIndex 傳送給遠端對等端
}
}
// 接收並新增遠端候選者
callee.addIceCandidate(WebRtc.IceCandidate(candidateString, sdpMid, sdpMLineIndex))
// (可選) 等待所有候選者收集完成
callee.awaitIceGatheringComplete()Ktor 不提供訊號傳輸 (Signaling)。使用 WebSockets、HTTP 或其他傳輸方式來交換 offers、answers 和 ICE candidates。
使用資料通道
WebRTC 支援資料通道,讓對等端可以交換任意訊息。這對於聊天、多人遊戲、協作工具或客戶端之間任何低延遲的訊息傳遞都很有用。
建立通道
若要在其中一側建立通道,請使用 .createDataChannel() 方法:
val channel = caller.createDataChannel("chat")然後,您可以在另一側監聽資料通道事件:
scope.launch {
callee.dataChannelEvents.collect { event ->
when (event) {
is DataChannelEvent.Open -> println("Channel opened: ${event.channel}")
is DataChannelEvent.Closed -> println("Channel closed")
else -> {}
}
}
}傳送和接收訊息
通道使用類似 Channel 的 API,這對 Kotlin 開發人員來說很熟悉:
// 傳送訊息
scope.launch { channel.send("hello") }
// 接收訊息
scope.launch { println("received: " + channel.receiveText()) }新增和觀察媒體軌
除了資料通道,WebRTC 還支援用於音訊和視訊的媒體軌。這允許您建置諸如視訊通話或螢幕分享等應用程式。
建立本地軌
您可以從本地設備 (麥克風、相機) 請求音訊或視訊軌:
val audio = rtcClient.createAudioTrack {
echoCancellation = true
}
val video = rtcClient.createVideoTrack {
width = 1280
height = 720
}
val pc = jsClient.createPeerConnection()
pc.addTrack(audio)
pc.addTrack(video)在網路上,這會使用 navigator.mediaDevices.getUserMedia。在 Android 上,它使用 Camera2 API,您必須手動請求麥克風/相機權限。在 iOS 上,它使用 AVFoundation API,您也應該手動請求任何權限。客戶端將嘗試根據指定的約束找到最合適的媒體設備,否則將拋出 WebRtcMedia.DeviceException。
WebRtcClient、WebRtcPeerConnection、WebRtcMedia.Track及其他介面均為AutoCloseable。請確保在不再需要時呼叫close()方法以釋放資源。
接收遠端軌
您也可以監聽遠端媒體軌:
scope.launch {
pc.trackEvents.collect { event ->
when (event) {
is TrackEvent.Add -> println("Remote track added: ${event.track.id}")
is TrackEvent.Remove -> println("Remote track removed: ${event.track.id}")
}
}
}限制
WebRTC 客戶端仍處於實驗階段,並具有以下限制:
- 訊號傳輸未包含在內。您需要實作自己的訊號傳輸 (例如,使用 WebSockets 或 HTTP)。
- 支援的平台為 JavaScript/Wasm 和 Android。iOS、JVM 桌面和 Kotlin/Native 的支援已規劃在未來版本中。
- 權限必須由您的應用程式處理。瀏覽器會提示使用者麥克風和相機的存取權,而 Android 則需要執行時權限請求。
- 目前僅支援基本的音訊和視訊軌。螢幕分享、設備選擇、simulcast 和進階 RTP 功能尚未提供。
- 連線統計資料可用,但因平台而異,且不遵循統一的架構。
