2、环境搭建:浏览器兼容性检查、本地开发环境配置(Node.js、HTTPS证书)、第一个WebRTC Demo
好,咱们正式开始动手了。
这一章说白了就是「把枪擦亮」。环境搭不好,后面全是坑。我见过太多人卡在第一步——不是浏览器不支持,就是本地跑不起来,最后连个摄像头都打不开。嗯,咱们今天就把这事彻底搞定。
2.1 浏览器兼容性:别让浏览器拖后腿
WebRTC 虽然已经是个成熟技术,但不同浏览器的支持程度还是有差异的。我个人习惯,开发时首选 Chrome 或 Edge,调试工具最顺手。
先看看你的浏览器行不行。打开这个页面:
// 最简单的兼容性检测
const checkWebRTC = () => {
const result = {
getUserMedia: !!navigator.mediaDevices?.getUserMedia,
RTCPeerConnection: !!window.RTCPeerConnection || !!window.webkitRTCPeerConnection,
RTCDataChannel: !!window.RTCPeerConnection
};
console.table(result);
if (result.getUserMedia && result.RTCPeerConnection) {
console.log('✅ 你的浏览器支持 WebRTC');
} else {
console.error('❌ 浏览器不支持 WebRTC,请升级到最新版 Chrome 或 Edge');
}
};
checkWebRTC();
这段代码会输出三个关键能力:摄像头/麦克风访问、点对点连接、数据通道。三个都是 true,恭喜你,可以继续了。
getUserMedia 的约束参数要求更严格。所以开发时最好多浏览器测一遍。
2.2 Node.js 环境:你的本地服务器
WebRTC 需要信令服务器来交换连接信息。虽然咱们第一个 Demo 可以纯前端跑,但后面肯定要上 Node.js。先把环境配好。
去 nodejs.org 下载 LTS 版本。安装完验证一下:
node -v # 我目前用的是 v18.16.0
npm -v # 9.5.1
然后创建一个项目目录:
mkdir webrtc-demo
cd webrtc-demo
npm init -y
这会生成一个 package.json。我个人习惯把端口号、域名这些配置单独放一个 .env 文件,但今天咱们先简单点。
2.3 HTTPS 证书:WebRTC 的硬门槛
这里有个重要的事:WebRTC 的 getUserMedia 只能在安全上下文(HTTPS 或 localhost)下使用。
为什么?因为浏览器不想让随便一个 HTTP 网站就能偷开你的摄像头。这个设计很合理,但给本地开发带来了一点麻烦。
解决方案有两种:
| 方案 | 适用场景 | 操作复杂度 |
|---|---|---|
| localhost | 纯本地开发 | ⭐ 最简单 |
| 自签名证书 | 需要局域网测试(手机访问) | ⭐⭐ 中等 |
| mkcert 工具 | 本地 HTTPS 最佳实践 | ⭐⭐ 推荐 |
我推荐用 mkcert,它能让本地证书被系统信任,浏览器不会报红锁。安装方式:
# macOS
brew install mkcert
mkcert -install
# Windows (用管理员 PowerShell)
choco install mkcert
mkcert -install
然后在项目目录生成证书:
mkcert localhost 127.0.0.1 ::1
# 会生成两个文件:
# localhost+2.pem (证书)
# localhost+2-key.pem (私钥)
mkcert -install,结果证书没装进信任根目录,Chrome 一直报 NET::ERR_CERT_AUTHORITY_INVALID。折腾了半小时才发现。记住:一定要以管理员身份运行!
2.4 第一个 WebRTC Demo:打开你的摄像头
好了,环境齐了。咱们写一个最简单的 Demo——打开摄像头并显示在页面上。
先创建一个 index.html:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的第一个 WebRTC Demo</title>
<style>
body { font-family: system-ui, sans-serif; max-width: 600px; margin: 40px auto; padding: 0 20px; }
video { width: 100%; border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
button { padding: 10px 24px; font-size: 16px; border: none; border-radius: 8px; cursor: pointer; margin: 8px 4px; }
.btn-start { background: #4CAF50; color: white; }
.btn-stop { background: #f44336; color: white; }
.status { margin: 12px 0; padding: 8px 16px; background: #f0f8ff; border-radius: 8px; }
</style>
</head>
<body>
<h2>📷 摄像头测试</h2>
<div class="status" id="status">点击「开始」打开摄像头</div>
<video id="localVideo" autoplay playsinline muted></video>
<div>
<button class="btn-start" id="startBtn">开始</button>
<button class="btn-stop" id="stopBtn">停止</button>
</div>
<script>
let localStream = null;
const video = document.getElementById('localVideo');
const status = document.getElementById('status');
document.getElementById('startBtn').addEventListener('click', async () => {
try {
status.textContent = '⏳ 正在请求摄像头权限...';
localStream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
video.srcObject = localStream;
status.textContent = '✅ 摄像头已打开';
} catch (err) {
status.textContent = '❌ 打开失败: ' + err.message;
console.error('getUserMedia error:', err);
}
});
document.getElementById('stopBtn').addEventListener('click', () => {
if (localStream) {
localStream.getTracks().forEach(track => track.stop());
video.srcObject = null;
localStream = null;
status.textContent = '🛑 摄像头已关闭';
}
});
</script>
</body>
</html>
然后启动一个 HTTPS 服务器。用 Node.js 的 https 模块:
// server.js
const https = require('https');
const fs = require('fs');
const path = require('path');
const options = {
key: fs.readFileSync(path.join(__dirname, 'localhost+2-key.pem')),
cert: fs.readFileSync(path.join(__dirname, 'localhost+2.pem'))
};
https.createServer(options, (req, res) => {
const filePath = path.join(__dirname, 'index.html');
const content = fs.readFileSync(filePath, 'utf-8');
res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' });
res.end(content);
}).listen(3000, () => {
console.log('🔒 HTTPS 服务器已启动: https://localhost:3000');
});
运行:
node server.js
打开浏览器访问 https://localhost:3000,点击「开始」按钮。浏览器会弹出摄像头权限请求——允许它。然后你就能在页面上看到自己的脸了。
navigator.mediaDevices.getUserMedia()是 WebRTC 的入口,获取本地媒体流- 返回的
MediaStream对象可以赋值给video.srcObject直接渲染 - 每个轨道(Track)可以单独控制启停
- 必须在 HTTPS 或 localhost 下才能使用
2.5 本章知识体系
下面这张图帮你理清今天搭的环境和它们之间的关系:
从这张图可以看得很清楚:浏览器通过 HTTPS 访问本地 Node.js 服务器,服务器提供页面,页面调用 WebRTC API,最终在页面上展示摄像头画面。每一步都环环相扣。
getUserMedia 的参数。比如把 video: true 改成 video: { width: 1280, height: 720 },看看画面清晰度的变化。或者把 audio: true 去掉,只开摄像头。多动手试试,印象更深。
好了,环境搭好了,第一个 Demo 也跑起来了。你已经在本地拥有了一个完整的 WebRTC 开发环境。接下来就可以往里面加更多东西了——比如点对点通话、屏幕共享、数据通道传输文件……