293 lines
6.5 KiB
Markdown
293 lines
6.5 KiB
Markdown
# WebRTC 生产环境问题解决方案
|
||
|
||
## 问题描述
|
||
|
||
在 `npm run build` 打包后,视频通话功能报错:
|
||
|
||
```
|
||
【CallService】_handleError, errorCode: 60006
|
||
errorMessage: 当前环境不支持 WebRTC
|
||
isMediaDevicesSupported: false
|
||
```
|
||
|
||
开发环境(`npm run dev`)正常,生产环境不正常。
|
||
|
||
## 问题原因
|
||
|
||
WebRTC 的 `getUserMedia` API 有安全限制:
|
||
|
||
1. **HTTPS 要求**:生产环境必须使用 HTTPS 协议
|
||
2. **localhost 例外**:只有 `localhost` 和 `127.0.0.1` 可以在 HTTP 下使用
|
||
3. **权限问题**:浏览器需要用户授权访问摄像头和麦克风
|
||
|
||
开发环境通常使用 `localhost`,所以正常。但生产环境如果使用 HTTP 协议的 IP 地址或域名,就会被浏览器阻止。
|
||
|
||
## 解决方案
|
||
|
||
### 方案1:使用 HTTPS(推荐)
|
||
|
||
#### 1.1 申请 SSL 证书
|
||
|
||
**免费证书**:
|
||
- Let's Encrypt(推荐)
|
||
- 阿里云免费证书
|
||
- 腾讯云免费证书
|
||
|
||
**申请步骤**(以 Let's Encrypt 为例):
|
||
|
||
```bash
|
||
# 安装 certbot
|
||
sudo apt-get update
|
||
sudo apt-get install certbot
|
||
|
||
# 申请证书
|
||
sudo certbot certonly --standalone -d your-domain.com
|
||
```
|
||
|
||
#### 1.2 配置 Nginx HTTPS
|
||
|
||
```nginx
|
||
server {
|
||
listen 443 ssl http2;
|
||
server_name your-domain.com;
|
||
|
||
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
|
||
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
|
||
|
||
# SSL 配置
|
||
ssl_protocols TLSv1.2 TLSv1.3;
|
||
ssl_ciphers HIGH:!aNULL:!MD5;
|
||
ssl_prefer_server_ciphers on;
|
||
|
||
location /admin/ {
|
||
alias /path/to/admin/dist/;
|
||
try_files $uri $uri/ /admin/index.html;
|
||
}
|
||
|
||
location /adminapi/ {
|
||
proxy_pass http://127.0.0.1:8000;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
}
|
||
}
|
||
|
||
# HTTP 重定向到 HTTPS
|
||
server {
|
||
listen 80;
|
||
server_name your-domain.com;
|
||
return 301 https://$server_name$request_uri;
|
||
}
|
||
```
|
||
|
||
#### 1.3 更新前端配置
|
||
|
||
确保 API 请求也使用 HTTPS:
|
||
|
||
```typescript
|
||
// admin/src/utils/request/index.ts
|
||
const baseURL = import.meta.env.VITE_APP_BASE_URL || 'https://your-domain.com'
|
||
```
|
||
|
||
### 方案2:开发环境使用 HTTPS
|
||
|
||
如果需要在开发环境测试 HTTPS:
|
||
|
||
#### 2.1 生成自签名证书
|
||
|
||
```bash
|
||
# 进入 admin 目录
|
||
cd admin
|
||
|
||
# 创建证书目录
|
||
mkdir -p .cert
|
||
|
||
# 生成自签名证书
|
||
openssl req -x509 -newkey rsa:4096 -keyout .cert/key.pem -out .cert/cert.pem -days 365 -nodes
|
||
```
|
||
|
||
#### 2.2 修改 vite.config.ts
|
||
|
||
```typescript
|
||
import * as fs from 'node:fs'
|
||
|
||
export default defineConfig({
|
||
server: {
|
||
host: '0.0.0.0',
|
||
https: {
|
||
key: fs.readFileSync('.cert/key.pem'),
|
||
cert: fs.readFileSync('.cert/cert.pem')
|
||
},
|
||
hmr: true,
|
||
open: true
|
||
},
|
||
// ... 其他配置
|
||
})
|
||
```
|
||
|
||
### 方案3:使用 localhost 访问
|
||
|
||
如果只是测试,可以通过 localhost 访问:
|
||
|
||
1. 在服务器上运行:`npm run preview`
|
||
2. 使用 SSH 隧道转发:
|
||
|
||
```bash
|
||
ssh -L 4173:localhost:4173 user@your-server
|
||
```
|
||
|
||
3. 本地浏览器访问:`http://localhost:4173/admin/`
|
||
|
||
### 方案4:修改 hosts(临时方案)
|
||
|
||
将服务器 IP 映射到 localhost:
|
||
|
||
```bash
|
||
# Windows: C:\Windows\System32\drivers\etc\hosts
|
||
# Linux/Mac: /etc/hosts
|
||
|
||
127.0.0.1 your-domain.local
|
||
```
|
||
|
||
然后通过 `http://your-domain.local` 访问。
|
||
|
||
## 检测 WebRTC 支持
|
||
|
||
### 在线检测
|
||
|
||
访问腾讯云提供的检测页面:
|
||
https://web.sdk.qcloud.com/trtc/webrtc/demo/detect/index.html
|
||
|
||
### 代码检测
|
||
|
||
在视频通话组件中添加检测:
|
||
|
||
```typescript
|
||
// admin/src/components/video-call/index.vue
|
||
|
||
const checkWebRTCSupport = () => {
|
||
const checks = {
|
||
isHttps: window.location.protocol === 'https:' || window.location.hostname === 'localhost',
|
||
hasGetUserMedia: !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia),
|
||
hasRTCPeerConnection: !!window.RTCPeerConnection
|
||
}
|
||
|
||
console.log('WebRTC Support:', checks)
|
||
|
||
if (!checks.isHttps) {
|
||
feedback.msgError('视频通话需要 HTTPS 环境,请使用 HTTPS 访问')
|
||
return false
|
||
}
|
||
|
||
if (!checks.hasGetUserMedia) {
|
||
feedback.msgError('浏览器不支持访问摄像头和麦克风')
|
||
return false
|
||
}
|
||
|
||
return true
|
||
}
|
||
|
||
const open = async (info: CallInfo) => {
|
||
// 先检查支持情况
|
||
if (!checkWebRTCSupport()) {
|
||
return
|
||
}
|
||
|
||
// ... 其他代码
|
||
}
|
||
```
|
||
|
||
## 浏览器权限设置
|
||
|
||
### Chrome
|
||
|
||
1. 点击地址栏左侧的锁图标
|
||
2. 选择"网站设置"
|
||
3. 允许"摄像头"和"麦克风"权限
|
||
|
||
### Firefox
|
||
|
||
1. 点击地址栏左侧的锁图标
|
||
2. 点击"连接安全"
|
||
3. 点击"更多信息"
|
||
4. 选择"权限"标签
|
||
5. 允许"使用摄像头"和"使用麦克风"
|
||
|
||
## 常见问题
|
||
|
||
### Q1: 为什么开发环境正常,生产环境不行?
|
||
|
||
A: 开发环境使用 `localhost`,浏览器允许 HTTP 下使用 WebRTC。生产环境使用 IP 或域名,必须使用 HTTPS。
|
||
|
||
### Q2: 使用了 HTTPS 还是不行?
|
||
|
||
A: 检查:
|
||
1. 证书是否有效(浏览器地址栏有绿色锁图标)
|
||
2. 是否有混合内容(HTTPS 页面加载 HTTP 资源)
|
||
3. 浏览器是否授权了摄像头和麦克风权限
|
||
|
||
### Q3: 如何在内网测试?
|
||
|
||
A:
|
||
1. 使用自签名证书(需要浏览器信任)
|
||
2. 使用 SSH 隧道转发到 localhost
|
||
3. 修改 hosts 文件
|
||
|
||
### Q4: 移动端如何测试?
|
||
|
||
A:
|
||
1. 必须使用 HTTPS
|
||
2. 确保移动设备信任证书
|
||
3. 在移动浏览器中授权摄像头和麦克风
|
||
|
||
## 推荐配置
|
||
|
||
### 生产环境
|
||
|
||
```
|
||
协议: HTTPS
|
||
域名: your-domain.com
|
||
证书: Let's Encrypt 或商业证书
|
||
Web服务器: Nginx with SSL
|
||
```
|
||
|
||
### 测试环境
|
||
|
||
```
|
||
协议: HTTPS (自签名证书)
|
||
域名: test.your-domain.com
|
||
或使用: localhost + SSH隧道
|
||
```
|
||
|
||
## 验证步骤
|
||
|
||
1. **检查协议**:确保使用 HTTPS
|
||
```javascript
|
||
console.log(window.location.protocol) // 应该是 "https:"
|
||
```
|
||
|
||
2. **检查 API 支持**:
|
||
```javascript
|
||
console.log('getUserMedia:', !!navigator.mediaDevices?.getUserMedia)
|
||
console.log('RTCPeerConnection:', !!window.RTCPeerConnection)
|
||
```
|
||
|
||
3. **测试权限**:
|
||
```javascript
|
||
navigator.mediaDevices.getUserMedia({ video: true, audio: true })
|
||
.then(() => console.log('权限已授予'))
|
||
.catch(err => console.error('权限被拒绝:', err))
|
||
```
|
||
|
||
## 总结
|
||
|
||
**最佳解决方案**:为生产环境配置 HTTPS
|
||
|
||
1. 申请 SSL 证书(Let's Encrypt 免费)
|
||
2. 配置 Nginx HTTPS
|
||
3. 更新前端 API 地址为 HTTPS
|
||
4. 测试视频通话功能
|
||
|
||
这样可以确保在任何环境下都能正常使用 WebRTC 功能。
|