前端每日一学:WebRTC —— 实现实时音视频通信的完整指南(25日补发)

场景

你需要开发 实时视频会议屏幕共享P2P 文件传输 功能,要求低延迟、高可靠性的端到端通信。


一、核心概念

1. WebRTC 三要素
  • MediaStream(媒体流):音视频输入输出(摄像头、麦克风)
  • RTCPeerConnection:对等连接管理(NAT 穿透、编解码协商)
  • RTCDataChannel:双向数据传输通道
2. 连接建立流程
1. 媒体设备访问 → 2. 信令交换 → 3. ICE 候选收集 → 4. 建立 P2P 连接

二、实战代码示例

步骤 1:获取媒体流
// 获取摄像头和麦克风访问权限
async function getMediaStream() {
  try {
    return await navigator.mediaDevices.getUserMedia({
      video: { width: 1280, height: 720 },
      audio: true
    });
  } catch (err) {
    console.error('媒体设备访问失败:', err);
  }
}

// 在 video 元素显示本地视频
const localVideo = document.getElementById('localVideo');
const stream = await getMediaStream();
localVideo.srcObject = stream;
步骤 2:建立信令服务器(Node.js 示例)
// 使用 Socket.IO 实现信令服务器
const express = require('express');
const socketIO = require('socket.io');

const app = express();
const server = app.listen(3000);
const io = socketIO(server);

io.on('connection', (socket) => {
  socket.on('join', (roomId) => {
    socket.join(roomId);
    socket.to(roomId).emit('user-connected', socket.id);
  });

  socket.on('signal', ({ to, data }) => {
    socket.to(to).emit('signal', { from: socket.id, data });
  });
});
步骤 3:创建对等连接
// 初始化 RTCPeerConnection
const pcConfig = {
  iceServers: [
    { urls: 'stun:stun.l.google.com:19302' }, // 免费 STUN 服务器
    // 需要 TURN 服务器可添加 { urls: 'turn:your-turn-server', credential: 'xxx' }
  ]
};

const pc = new RTCPeerConnection(pcConfig);

// 添加本地媒体流
stream.getTracks().forEach(track => {
  pc.addTrack(track, stream);
});

// 处理 ICE 候选
pc.onicecandidate = ({ candidate }) => {
  if (candidate) {
    socket.emit('signal', { to: remoteUserId, data: { candidate } });
  }
};

// 接收远程流
pc.ontrack = (event) => {
  const remoteVideo = document.getElementById('remoteVideo');
  remoteVideo.srcObject = event.streams[0];
};
步骤 4:发起连接
// 发起方创建 Offer
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
socket.emit('signal', { to: remoteUserId, data: { offer } });

// 接收方处理 Offer
socket.on('signal', async ({ from, data: { offer } }) => {
  await pc.setRemoteDescription(offer);
  const answer = await pc.createAnswer();
  await pc.setLocalDescription(answer);
  socket.emit('signal', { to: from, data: { answer } });
});

// 处理 Answer
socket.on('signal', async ({ data: { answer } }) => {
  await pc.setRemoteDescription(answer);
});

三、高级功能实现

1. 屏幕共享
async function shareScreen() {
  const stream = await navigator.mediaDevices.getDisplayMedia({
    video: { cursor: 'always' },
    audio: true
  });
  const screenTrack = stream.getVideoTracks()[0];
  const sender = pc.getSenders().find(s => s.track.kind === 'video');
  sender.replaceTrack(screenTrack);
}
2. 文件传输(通过 RTCDataChannel)
// 创建数据通道
const dc = pc.createDataChannel('fileTransfer');

dc.onmessage = (event) => {
  const fileChunk = event.data;
  // 处理接收的文件块
};

// 发送文件
async function sendFile(file) {
  const chunkSize = 16384; // 16KB
  const reader = new FileReader();
  let offset = 0;

  reader.onload = () => {
    dc.send(reader.result);
    offset += reader.result.byteLength;
    if (offset < file.size) readChunk(offset);
  };

  const readChunk = (o) => {
    const slice = file.slice(o, o + chunkSize);
    reader.readAsArrayBuffer(slice);
  };

  readChunk(0);
}
3. 网络质量监控
pc.getStats().then(stats => {
  stats.forEach(report => {
    if (report.type === 'candidate-pair' && report.selected) {
      console.log('当前 RTT:', report.currentRoundTripTime);
    }
  });
});

四、性能优化技巧

  1. 编解码选择:优先使用 VP8/VP9 视频编解码
  2. 带宽自适应:使用 RTCRtpSender.setParameters() 动态调整码率
  3. ICE 策略优化:设置 iceTransportPolicy: 'relay' 强制使用 TURN 服务器(高防火墙环境)

五、工具与库

工具/库用途特点
Simple-Peer简化 WebRTC API封装复杂连接逻辑
Twilio云通信平台提供 TURN 服务和 SDK
MediasoupSFU 媒体服务器适合大规模会议系统
WebRTC-internals浏览器内置调试工具查看详细连接状态

六、注意事项

  1. HTTPS 要求:生产环境必须使用 HTTPS
  2. 浏览器兼容性:iOS Safari 对部分功能有限制
  3. NAT 穿透失败:需配置 TURN 服务器作为中继
  4. 设备权限:首次访问需用户明确授权

明日预告WebSocket —— 如何实现实时双向数据通信?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值