mcpField
W
webrtc

webrtc

github.com/claude-dev-suite开发46204 次安装2 天前更新
代码仓库

关于 webrtc

提供 WebRTC 点对点连接、信令、数据通道和屏幕共享的实现示例,也涵盖用于群组通话的 LiveKit,以及连接可靠性的生产检查项。

主要功能

  1. 01点对点连接配置
  2. 02Socket.IO 信令
  3. 03数据通道消息传递
  4. 04屏幕共享
  5. 05LiveKit 群组通话示例
  6. 06生产环境可靠性检查

适用场景

  1. 01构建一对一 WebRTC 通话
  2. 02通过数据通道交换消息
  3. 03在通话中共享屏幕
  4. 04使用 SFU 规划群组通话

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/claude-dev-suite/claude-dev-suite --skill webrtc

安装后在 Claude Code 中输入/webrtc确认已加载。

详细介绍

WebRTC

对等连接设置

const config: RTCConfiguration = {
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' },
    { urls: 'turn:turn.example.com', username: 'user', credential: 'pass' },
  ],
};

const pc = new RTCPeerConnection(config);

// Get local media
const stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
stream.getTracks().forEach((track) => pc.addTrack(track, stream));

// Display remote stream
pc.ontrack = (event) => {
  remoteVideo.srcObject = event.streams[0];
};

// ICE candidates — send to remote peer via signaling
pc.onicecandidate = (event) => {
  if (event.candidate) {
    signalingChannel.send({ type: 'ice-candidate', candidate: event.candidate });
  }
};

信令(通过 Socket.IO)

// Caller
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
socket.emit('signal', { type: 'offer', sdp: offer });

// Callee — on receiving offer
socket.on('signal', async (msg) => {
  if (msg.type === 'offer') {
    await pc.setRemoteDescription(msg.sdp);
    const answer = await pc.createAnswer();
    await pc.setLocalDescription(answer);
    socket.emit('signal', { type: 'answer', sdp: answer });
  } else if (msg.type === 'answer') {
    await pc.setRemoteDescription(msg.sdp);
  } else if (msg.type === 'ice-candidate') {
    await pc.addIceCandidate(msg.candidate);
  }
});

数据通道

const dataChannel = pc.createDataChannel('chat', { ordered: true });

dataChannel.onopen = () => dataChannel.send('Hello!');
dataChannel.onmessage = (e) => console.log('Received:', e.data);

// Remote side
pc.ondatachannel = (event) => {
  const channel = event.channel;
  channel.onmessage = (e) => console.log('Received:', e.data);
};

屏幕共享

const screenStream = await navigator.mediaDevices.getDisplayMedia({
  video: { cursor: 'always' },
  audio: true,
});

const videoTrack = screenStream.getVideoTracks()[0];
const sender = pc.getSenders().find((s) => s.track?.kind === 'video');
await sender?.replaceTrack(videoTrack);

videoTrack.onended = () => {
  // User stopped sharing — switch back to camera
  const cameraTrack = localStream.getVideoTracks()[0];
  sender?.replaceTrack(cameraTrack);
};

LiveKit(SFU — 推荐用于群组通话)

import { Room, RoomEvent } from 'livekit-client';

const room = new Room();
await room.connect(LIVEKIT_URL, accessToken);

await room.localParticipant.enableCameraAndMicrophone();

room.on(RoomEvent.TrackSubscribed, (track, publication, participant) => {
  const element = track.attach();
  document.getElementById('remote-videos')!.appendChild(element);
});

room.on(RoomEvent.ParticipantDisconnected, (participant) => {
  console.log(`${participant.identity} left`);
});

反模式

反模式修复方法
未配置 TURN 服务始终配置 TURN,以便穿透 NAT
群组通话(>4 位用户)使用 P2P使用 SFU(LiveKit、mediasoup)
未处理 getUserMedia 错误处理 NotAllowedError、NotFoundError
通过未加密通道传输信令使用 WSS(WebSocket Secure)
未监控连接状态监听 connectionstatechange 事件

生产环境检查清单

  • 已部署并配置 TURN 服务
  • 群组视频(>3 位参与者)使用 SFU
  • 拒绝媒体访问时显示备用 UI
  • 监控连接质量
  • 带宽自适应(simulcast)
  • 按需提供录制功能

评论

支持 Markdown