2、搭建开发环境:浏览器端环境、Node.js信令服务器搭建、本地媒体流获取
好,咱们正式开始动手了。这一章我带你搭好开发环境。你想想看,做音视频开发,最怕什么?最怕环境没配好,代码跑不起来,然后满世界找 bug。我早期踩过不少这种坑,所以今天咱们一步到位。
本章核心目标:让你能在浏览器里调摄像头、麦克风,同时跑起一个 Node.js 信令服务器。说白了,就是让 WebRTC 的“两端”能互相找到对方。
2.1 浏览器端环境准备
WebRTC 是浏览器原生支持的。你不需要装任何插件。我个人习惯用 Chrome 做主力开发,因为它的 DevTools 对 WebRTC 支持最好。Firefox 也可以,但调试体验差一点。
你需要确认三件事:
- Chrome 版本 ≥ 88(建议用最新稳定版)
- 开启摄像头和麦克风权限(地址栏左边有个小锁图标)
- 本地 HTTP 服务(直接用 file:// 协议有时会报权限错误)
小技巧:我习惯在 Chrome 地址栏输入 chrome://webrtc-internals,这里能看到所有 WebRTC 的内部状态。排查问题的时候特别好用。
2.2 Node.js 信令服务器搭建
信令服务器是 WebRTC 的“媒人”。它不传音视频数据,只传一些控制信息,比如“我想和你通话”、“这是我的网络地址”之类的。
我们用 Node.js + WebSocket 来实现。为什么选 WebSocket?因为它双向通信,延迟低,而且浏览器原生支持。
2.2.1 初始化项目
mkdir webrtc-signaling
cd webrtc-signaling
npm init -y
npm install ws
嗯,这里要注意:ws 库是 Node.js 上最流行的 WebSocket 库。我早期用过 socket.io,但后来发现 ws 更轻量,而且和浏览器的原生 WebSocket API 更匹配。
2.2.2 编写信令服务器
创建一个 server.js 文件:
const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });
// 存储所有连接的客户端
const clients = new Map();
wss.on('connection', (ws, req) => {
const id = Date.now().toString(36);
clients.set(id, ws);
console.log(`客户端 ${id} 已连接`);
// 发送自己的 ID
ws.send(JSON.stringify({ type: 'id', id }));
ws.on('message', (message) => {
const data = JSON.parse(message);
console.log('收到消息:', data);
// 转发消息给目标客户端
if (data.target) {
const targetWs = clients.get(data.target);
if (targetWs) {
targetWs.send(JSON.stringify({
from: id,
type: data.type,
data: data.data
}));
}
}
});
ws.on('close', () => {
clients.delete(id);
console.log(`客户端 ${id} 已断开`);
});
});
console.log('信令服务器已启动,端口: 8080');
避坑指南:我曾经在生产环境遇到过一个问题——客户端断开后没有清理 Map,导致内存泄漏。所以一定要在 close 事件里删除对应的条目。
2.2.3 启动服务器
node server.js
看到 信令服务器已启动,端口: 8080 就说明成功了。
2.3 本地媒体流获取
这是 WebRTC 的第一步——拿到摄像头和麦克风的数据。浏览器提供了 navigator.mediaDevices.getUserMedia() 这个 API。
2.3.1 基础用法
async function getLocalStream() {
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
// 把视频流显示到页面上
const video = document.getElementById('localVideo');
video.srcObject = stream;
video.play();
console.log('获取本地媒体流成功');
return stream;
} catch (err) {
console.error('获取媒体流失败:', err);
}
}
getLocalStream();
HTML 部分:
<video id="localVideo" autoplay muted playsinline></video>
注意:muted 属性很重要。如果不加,你可能会听到自己的回声。因为本地视频默认会播放音频,而麦克风又录到了扬声器的声音,就形成了反馈回路。
2.3.2 设置分辨率
你可以指定想要的视频分辨率:
const stream = await navigator.mediaDevices.getUserMedia({
video: {
width: { ideal: 1280 },
height: { ideal: 720 },
frameRate: { ideal: 30 }
},
audio: true
});
这里用 ideal 而不是 exact。为什么?因为浏览器会尽量满足你的要求,但如果摄像头不支持,它会自动降级。用 exact 的话,一旦不匹配就直接报错。我建议你始终用 ideal,除非你有特殊需求。
2.3.3 常见错误处理
| 错误名称 | 原因 | 解决方法 |
|---|---|---|
| NotAllowedError | 用户拒绝了权限 | 检查浏览器权限设置,或提示用户允许 |
| NotFoundError | 没有找到摄像头/麦克风 | 检查设备是否连接,或使用 enumerateDevices() 列出可用设备 |
| NotReadableError | 设备被其他应用占用 | 关闭其他使用摄像头的程序(如 Zoom、OBS) |
| OverconstrainedError | 指定的约束条件无法满足 | 改用 ideal 而不是 exact |
核心经验:我在做第一个 WebRTC 项目时,花了整整一天排查一个“获取不到视频流”的问题。最后发现是 Chrome 的 HTTPS 限制——getUserMedia 在 HTTP 环境下会被拒绝。所以,请务必用 HTTPS 或 localhost 来测试。
2.4 整体架构图
下面这张图展示了我们搭建的整个环境:浏览器通过 getUserMedia 获取本地媒体流,然后通过 WebSocket 信令服务器交换连接信息,最终建立 P2P 连接。
2.5 完整测试流程
好,现在我们把所有东西串起来跑一遍:
- 启动信令服务器:
node server.js - 在浏览器打开你的 HTML 页面(记得用
http://localhost或 HTTPS) - 允许摄像头和麦克风权限
- 打开 DevTools 的 Console,你应该能看到
获取本地媒体流成功 - 打开
chrome://webrtc-internals,确认 WebRTC 内部状态正常
调试技巧:如果视频没出来,先检查 Console 有没有报错。如果没有报错但画面黑屏,试试在 getUserMedia 的约束里加上 facingMode: 'user',有些笔记本默认会调用后置摄像头。
嗯,到这里环境就搭好了。你可能会问:“为什么信令服务器这么简单?” 没错,它确实简单。WebRTC 的核心是 P2P 传输,信令只是辅助。后面我们会逐步给它加上房间管理、用户列表等功能。
总结一下:今天我们做了三件事——配好了浏览器环境、搭了一个轻量的 Node.js 信令服务器、用 getUserMedia 拿到了本地媒体流。这三样东西,是后面所有 WebRTC 功能的基础。我建议你多跑几遍,直到闭着眼睛都能搭起来。