第二章 浏览器兼容性与环境搭建:别让环境卡住你的第一个Demo
说实话,我见过太多人兴致勃勃想玩WebRTC,结果卡在环境搭建这一步。明明代码写得没问题,浏览器就是不给面子。今天咱们就把这事彻底捋清楚。
2.1 主流浏览器对WebRTC的支持情况
WebRTC这玩意儿,现在主流浏览器基本都支持了。但支持归支持,细节上还是有差异的。我整理了一张表,你一看就明白。
| 浏览器 | WebRTC支持版本 | 核心API前缀 | 备注 |
|---|---|---|---|
| Chrome | 28+ | webkit | 最稳定,推荐开发首选 |
| Firefox | 22+ | moz | 早期有前缀,现在基本统一 |
| Safari | 11+ | webkit | iOS上必须用webkit前缀 |
| Edge | 12+(Chromium版79+) | 无(Chromium版) | 旧版Edge已死,不用管 |
| Opera | 20+ | webkit | 跟Chrome内核一样 |
嗯,这里要注意:Chrome和Safari虽然都用webkit前缀,但实现细节不完全一样。我在项目中遇到过Safari上getUserMedia返回的音频轨道格式跟Chrome不同,导致后续编码出问题。所以别偷懒,每个浏览器都得测。
2.2 getUserMedia API的兼容性处理
getUserMedia是WebRTC的入口,也是坑最多的地方。说白了,就是浏览器厂商各自为政的那段历史遗留问题。
核心问题:不同浏览器对getUserMedia的调用方式不同,有的用navigator.getUserMedia,有的用navigator.webkitGetUserMedia,还有的用navigator.mozGetUserMedia。
怎么解决?我习惯写一个适配函数,一次性搞定所有情况。
// 兼容性适配函数
function getGetUserMedia() {
// 标准API
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
return navigator.mediaDevices.getUserMedia.bind(navigator.mediaDevices);
}
// 老式前缀API
const getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia;
if (getUserMedia) {
// 包装成Promise风格
return function(constraints) {
return new Promise(function(resolve, reject) {
getUserMedia.call(navigator, constraints, resolve, reject);
});
};
}
// 都不支持,抛出错误
return function() {
return Promise.reject(new Error('浏览器不支持getUserMedia'));
};
}
// 使用示例
const myGetUserMedia = getGetUserMedia();
myGetUserMedia({ video: true, audio: true })
.then(function(stream) {
console.log('获取到媒体流:', stream);
})
.catch(function(err) {
console.error('获取失败:', err);
});
个人经验:我建议你直接用navigator.mediaDevices.getUserMedia这个标准API,然后加一个polyfill兜底。因为从2018年以后,主流浏览器都支持标准API了。老式前缀API主要是为了兼容那些万年不更新的浏览器。
你想想看,如果用户还在用Chrome 27这种古董,那咱们也没必要伺候了,对吧?直接提示升级浏览器就行。
2.3 搭建本地HTTPS开发环境
这是个大坑。WebRTC要求页面必须在HTTPS环境下运行,或者localhost也行。为什么?因为getUserMedia涉及摄像头和麦克风权限,浏览器不允许在非安全环境下调用。
警告:千万别想着用HTTP直接开发WebRTC!浏览器会直接拒绝getUserMedia请求,连错误提示都不给。我曾经因为这个排查了半天,最后发现是协议问题。
搭建本地HTTPS环境,我推荐两种方式:
方式一:使用mkcert(推荐)
mkcert是一个小工具,能一键生成受信任的本地证书。我个人最喜欢这种方式,因为浏览器不会报不安全。
# 1. 安装mkcert
# macOS
brew install mkcert
# Windows (用choco)
choco install mkcert
# Linux
sudo apt install libnss3-tools
wget https://github.com/FiloSottile/mkcert/releases/latest/download/mkcert-v1.4.4-linux-amd64
chmod +x mkcert-v1.4.4-linux-amd64
sudo mv mkcert-v1.4.4-linux-amd64 /usr/local/bin/mkcert
# 2. 初始化本地CA
mkcert -install
# 3. 生成证书(替换成你的域名或IP)
mkcert localhost 127.0.0.1 ::1
# 4. 启动HTTPS服务器(用Node.js举例)
const https = require('https');
const fs = require('fs');
const express = require('express');
const app = express();
app.use(express.static('public'));
const options = {
key: fs.readFileSync('localhost+2-key.pem'),
cert: fs.readFileSync('localhost+2.pem')
};
https.createServer(options, app).listen(443, () => {
console.log('HTTPS服务器已启动: https://localhost');
});
方式二:使用http-server + 自签名证书
如果你不想装mkcert,也可以用Node.js的http-server配合自签名证书。不过浏览器会提示不安全,需要手动信任。
# 1. 安装http-server
npm install -g http-server
# 2. 生成自签名证书(用openssl)
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
# 3. 启动HTTPS服务器
http-server -S -C cert.pem -K key.pem -p 443
小技巧:如果你只是本地测试,直接用localhost就行,不需要HTTPS。但一旦涉及摄像头权限,必须用HTTPS。我习惯在开发时用localhost,部署时再切HTTPS。
2.4 浏览器兼容性检测工具
写代码之前,先检测一下当前浏览器是否支持WebRTC。我写了一个检测函数,你可以直接拿去用。
function checkWebRTCSupport() {
const result = {
supported: false,
details: {}
};
// 检测getUserMedia
result.details.getUserMedia = !!(navigator.mediaDevices &&
navigator.mediaDevices.getUserMedia);
// 检测RTCPeerConnection
result.details.RTCPeerConnection = !!(window.RTCPeerConnection ||
window.webkitRTCPeerConnection ||
window.mozRTCPeerConnection);
// 检测RTCDataChannel
result.details.RTCDataChannel = !!(window.RTCDataChannel ||
window.webkitRTCDataChannel);
// 综合判断
result.supported = result.details.getUserMedia &&
result.details.RTCPeerConnection;
return result;
}
// 使用
const support = checkWebRTCSupport();
console.log('WebRTC支持情况:', support);
if (!support.supported) {
alert('您的浏览器不支持WebRTC,请升级到最新版Chrome或Firefox');
}
嗯,这里要注意:检测结果只是参考,实际运行中可能因为权限问题导致失败。比如用户拒绝了摄像头权限,getUserMedia就会报错。所以代码里一定要加错误处理。
2.5 本章知识体系
我把这章的核心逻辑画了张图,方便你理解整体脉络。
这张图把本章的三个核心模块串起来了。你从浏览器支持开始,然后处理API兼容性,最后搭建安全环境。每一步都有坑,但按这个流程走,基本不会出大问题。
总结一下:
- 主流浏览器都支持WebRTC,但细节有差异,必须测
- getUserMedia要写适配函数,兼容老式前缀
- 本地开发用localhost,部署必须HTTPS
- mkcert是最省心的HTTPS方案
- 别忘了加错误处理,用户可能拒绝权限
好了,环境搭好了,下一章咱们就开始写第一个WebRTC Demo。到时候你会发现,前面这些准备工作都是值得的。