Skip to content

RTCPeerConnection

RTCPeerConnection 管理 WebRTC 的 SDP 协商、ICE 连通性检查、媒体轨道与数据通道。一个对等连接可承载多个音视频轨道和多个 RTCDataChannel

创建与添加本地媒体

js
const pc = new RTCPeerConnection({
  iceServers: [
    { urls: 'stun:stun.example.com:3478' },
    {
      urls: 'turns:turn.example.com:5349?transport=tcp',
      username: 'temporary-user',
      credential: 'temporary-credential',
    },
  ],
})

const stream = await navigator.mediaDevices.getUserMedia({
  audio: true,
  video: true,
})

for (const track of stream.getTracks()) {
  pc.addTrack(track, stream)
}

TURN 凭证应由受保护的服务端动态签发,不应写死在前端。

信令事件

以下示例的 sendSignalonSignal 由应用的信令通道实现:

js
pc.addEventListener('icecandidate', ({ candidate }) => {
  if (candidate) sendSignal({ type: 'ice-candidate', candidate })
})

pc.addEventListener('track', ({ streams }) => {
  remoteVideo.srcObject = streams[0]
})

pc.addEventListener('connectionstatechange', () => {
  console.log(pc.connectionState)
})

pc.addEventListener('negotiationneeded', async () => {
  const offer = await pc.createOffer()
  await pc.setLocalDescription(offer)
  sendSignal({ type: 'offer', description: pc.localDescription })
})

收到远端信令时,严格按照描述类型处理。生产环境还应实现 perfect negotiation,避免双方同时发起协商时状态冲突。

js
async function onSignal(message) {
  if (message.type === 'offer') {
    await pc.setRemoteDescription(message.description)
    const answer = await pc.createAnswer()
    await pc.setLocalDescription(answer)
    sendSignal({ type: 'answer', description: pc.localDescription })
  }

  if (message.type === 'answer') {
    await pc.setRemoteDescription(message.description)
  }

  if (message.type === 'ice-candidate') {
    await pc.addIceCandidate(message.candidate)
  }
}

高频状态与方法

API用途
connectionState连接整体状态:newconnectingconnecteddisconnectedfailedclosed
iceConnectionStateICE 路径检查状态,用于诊断网络问题
signalingStateSDP 协商状态,排查 offer/answer 时序错误
addTrack() / removeTrack()添加或停止发送媒体轨道,可能触发重新协商
addTransceiver()显式控制收发方向与编解码器偏好
createDataChannel()创建数据通道
restartIce()请求新一轮 ICE 协商,常用于网络切换后的恢复
getStats()读取码率、丢包、抖动、RTT 与候选信息
close()永久关闭连接;关闭后需新建实例

更换摄像头或切换屏幕共享时,优先使用 RTCRtpSender.replaceTrack();若媒体方向或编解码参数改变,则可能需要重新协商。

基于 MIT 许可发布