信令
信令是 WebRTC 建立连接之前交换 SDP 和 ICE candidate 的过程。WetRTC 通过 SignalChannel 接口将信令传输与业务逻辑解耦,你可以自由选择任何传输方式。
SignalChannel 接口
ts
interface SignalChannel {
/** 发送信令消息到远端 */
send(data: SignalMessage): Promise<void>
/** 接收远端信令消息,返回取消监听的函数 */
onMessage(handler: (data: SignalMessage) => void): () => void
}
interface SignalMessage {
type: 'offer' | 'answer' | 'ice-candidate' | 'bye'
sdp?: string
candidate?: RTCIceCandidateInit
}示例:WebSocket
ts
const ws = new WebSocket('wss://signal.example.com')
const signal: SignalChannel = {
async send(data) {
ws.send(JSON.stringify(data))
},
onMessage(handler) {
const listener = (e: MessageEvent) => handler(JSON.parse(e.data))
ws.addEventListener('message', listener)
return () => ws.removeEventListener('message', listener)
}
}
const rtc = new WetRTC({ signal })
await rtc.connect()示例:Socket.IO
ts
import { io } from 'socket.io-client'
const socket = io('https://signal.example.com')
const signal: SignalChannel = {
async send(data) {
socket.emit('signal', data)
},
onMessage(handler) {
socket.on('signal', handler)
return () => socket.off('signal', handler)
}
}示例:HTTP 长轮询
ts
let polling = true
const signal: SignalChannel = {
async send(data) {
await fetch('/api/signal', {
method: 'POST',
body: JSON.stringify(data),
})
},
onMessage(handler) {
const poll = async () => {
while (polling) {
const res = await fetch('/api/signal/poll')
if (res.ok) {
handler(await res.json())
}
await new Promise(r => setTimeout(r, 1000))
}
}
poll()
return () => { polling = false }
}
}基类:BaseSignalChannel
如果你的项目中多处使用信令,可以继承 BaseSignalChannel 获得事件能力:
ts
import { BaseSignalChannel } from '@wetspace/wetrtc'
class MySignal extends BaseSignalChannel {
async send(data: SignalMessage) { /* ... */ }
onMessage(handler) { /* ... */ }
}
const signal = new MySignal()
signal.on('error', (err) => console.error('信令错误:', err))
signal.on('closed', () => console.log('信令通道关闭'))信令配置
通过 signalConfig 配置信令超时等行为:
ts
const rtc = new WetRTC({
signal,
signalConfig: {
offerTimeout: 10_000, // offer 超时 (ms)
answerTimeout: 10_000, // answer 超时 (ms)
iceTimeout: 5_000, // ICE 收集超时 (ms)
}
})生产示例:virt-screen + Socket.IO
monorepo 中的 WET 扩展屏 使用 NestJS WebSocket Gateway 转发 WetRTC 信令,并扩展 join-room / peer-left 等房间事件。完整流程、双端 initiator/polite 配对与代码片段见 virt-screen 集成示例。
核心 SignalChannel 实现见文档片段 docs/_snippets/virt-screen/signal-channel-socketio.ts(对应源码 virt-screen/src/renderer/composables/useSignalChannel.ts)。