2、环境搭建:浏览器兼容性检查、本地HTTPS服务器搭建(Node.js)、第一个WebRTC页面

说实话,很多初学者一上来就急着写代码,结果卡在最基础的环境上。我见过太多人花了一整天,最后发现是浏览器不支持,或者没有HTTPS导致摄像头打不开。所以这一章,咱们先把地基打牢。

2.1 浏览器兼容性检查

WebRTC 虽然已经是个成熟技术了,但不同浏览器的支持程度还是有差异的。我自己的习惯是,开工前先跑一遍兼容性检测,省得后面踩坑。

2.1.1 哪些浏览器支持?

目前主流浏览器基本都支持 WebRTC,但细节上有些区别:

浏览器 WebRTC 支持情况 备注
Chrome / Edge (Chromium) ✅ 完整支持 开发首选,调试工具最全
Firefox ✅ 完整支持 部分 API 命名略有不同
Safari ✅ 支持(iOS 11+) H.264 编码支持更好
Opera ✅ 支持 和 Chrome 内核一致
IE / 旧版 Edge ❌ 不支持 别想了,换浏览器吧

2.1.2 快速检测方法

打开浏览器控制台,输入下面这行代码:

navigator.mediaDevices.getUserMedia === undefined ? 
  console.log('❌ 不支持') : console.log('✅ 支持')

如果返回 true,恭喜你,环境没问题。如果返回 false 或者报错,嗯……你可能需要换个浏览器。

💡 我的小技巧: 我一般会在项目入口文件里加一段检测脚本,如果浏览器不支持,直接弹个提示,而不是让用户一脸懵。

2.2 为什么必须用 HTTPS?

这个问题我经常被问到。说白了,就是浏览器出于安全考虑,不允许在非安全环境下调用摄像头和麦克风。

你想想看,如果随便一个 HTTP 网站都能偷偷打开你的摄像头,那多吓人?所以 Chrome、Firefox 这些浏览器强制要求:调用 getUserMedia 必须在 HTTPS 环境下

⚠️ 注意: localhost 是个例外。在本地开发时,浏览器允许通过 http://localhost 访问媒体设备。但如果你要用手机测试,或者想模拟真实网络环境,就必须搭建 HTTPS 服务器。

2.3 搭建本地 HTTPS 服务器(Node.js)

我个人比较喜欢用 Node.js 搭本地服务器,轻量又灵活。下面是我常用的两种方式。

2.3.1 方式一:使用 http-server(最简单)

如果你只是想快速跑起来,用这个:

# 安装
npm install -g http-server

# 启动(默认 HTTP)
http-server . -p 8080

但这样是 HTTP,不是 HTTPS。要启用 HTTPS,需要先生成证书。

2.3.2 生成自签名证书

打开终端,执行以下命令:

openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out cert.pem

过程中会问你一些问题,随便填就行。重要的是,你会得到两个文件:

  • key.pem —— 私钥
  • cert.pem —— 证书
🔑 关键点: 自签名证书浏览器会提示不安全,但没关系,点击「高级」→「继续前往」就行了。这是本地开发,安全风险可控。

2.3.3 方式二:用 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, 'key.pem')),
  cert: fs.readFileSync(path.join(__dirname, 'cert.pem'))
};

https.createServer(options, (req, res) => {
  // 设置静态文件服务
  let filePath = path.join(__dirname, req.url === '/' ? 'index.html' : req.url);
  let extname = path.extname(filePath);
  let contentType = 'text/html';

  // 根据文件扩展名设置 Content-Type
  switch (extname) {
    case '.js': contentType = 'text/javascript'; break;
    case '.css': contentType = 'text/css'; break;
    case '.json': contentType = 'application/json'; break;
    case '.png': contentType = 'image/png'; break;
    case '.jpg': contentType = 'image/jpg'; break;
  }

  fs.readFile(filePath, (err, content) => {
    if (err) {
      res.writeHead(404);
      res.end('File not found');
    } else {
      res.writeHead(200, { 'Content-Type': contentType });
      res.end(content);
    }
  });
}).listen(3000, () => {
  console.log('✅ HTTPS 服务器已启动:https://localhost:3000');
});

然后运行:

node server.js

打开浏览器访问 https://localhost:3000,看到提示不安全?别慌,点「高级」→「继续前往」就行。

💡 避坑指南: 我曾经在 Windows 上折腾了半天,发现 OpenSSL 没装。如果你也遇到类似问题,记得先检查 openssl version 能不能跑。

2.4 第一个 WebRTC 页面

好了,环境搭好了,咱们来写第一个页面。这个页面很简单:点击按钮,打开摄像头,把画面显示在页面上。

2.4.1 创建 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 页面</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      max-width: 800px;
      margin: 0 auto;
      padding: 20px;
      text-align: center;
    }
    video {
      width: 100%;
      max-width: 640px;
      border: 2px solid #333;
      border-radius: 8px;
      margin: 20px 0;
    }
    button {
      padding: 12px 24px;
      font-size: 16px;
      background: #4CAF50;
      color: white;
      border: none;
      border-radius: 4px;
      cursor: pointer;
    }
    button:hover {
      background: #45a049;
    }
    #status {
      margin: 10px 0;
      color: #666;
    }
  </style>
</head>
<body>
  <h1>📷 WebRTC 音视频采集</h1>
  <p id="status">点击下方按钮打开摄像头</p>
  <video id="localVideo" autoplay playsinline></video>
  <br>
  <button id="startBtn">打开摄像头</button>
  <button id="stopBtn" disabled>关闭摄像头</button>

  <script>
    const localVideo = document.getElementById('localVideo');
    const startBtn = document.getElementById('startBtn');
    const stopBtn = document.getElementById('stopBtn');
    const status = document.getElementById('status');
    let localStream = null;

    // 检查浏览器是否支持
    if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
      status.textContent = '❌ 您的浏览器不支持 WebRTC';
      startBtn.disabled = true;
    }

    // 打开摄像头
    startBtn.addEventListener('click', async () => {
      try {
        status.textContent = '⏳ 正在请求摄像头权限...';
        
        const constraints = {
          video: {
            width: { ideal: 1280 },
            height: { ideal: 720 }
          },
          audio: false  // 先不要音频,后面章节再讲
        };

        localStream = await navigator.mediaDevices.getUserMedia(constraints);
        localVideo.srcObject = localStream;
        
        status.textContent = '✅ 摄像头已打开';
        startBtn.disabled = true;
        stopBtn.disabled = false;
      } catch (err) {
        status.textContent = `❌ 打开摄像头失败:${err.message}`;
        console.error('getUserMedia 错误:', err);
      }
    });

    // 关闭摄像头
    stopBtn.addEventListener('click', () => {
      if (localStream) {
        localStream.getTracks().forEach(track => track.stop());
        localVideo.srcObject = null;
        localStream = null;
        
        status.textContent = '🛑 摄像头已关闭';
        startBtn.disabled = false;
        stopBtn.disabled = true;
      }
    });
  </script>
</body>
</html>

2.4.2 运行效果

index.html 放到你的项目目录里,启动 HTTPS 服务器,然后访问 https://localhost:3000。点击「打开摄像头」,浏览器会弹出权限请求,允许后就能看到自己的脸了。

🎯 核心知识点:
  • getUserMedia 是 WebRTC 的入口 API,用于获取音视频流
  • constraints 参数可以指定分辨率、帧率等
  • 返回的 MediaStream 对象可以直接赋值给 <video> 元素的 srcObject
  • 记得用 autoplay 属性,否则画面不会自动播放

2.5 本章知识体系

下面这张图帮你理清本章的核心逻辑:

环境搭建核心流程 ① 浏览器兼容性检测 navigator.mediaDevices ② 搭建HTTPS服务器 Node.js + 自签名证书 ③ 编写WebRTC页面 getUserMedia + video 关键细节 ⚠️ 必须使用HTTPS localhost 除外,但手机测试必须HTTPS ✅ 自签名证书可用 浏览器提示不安全,点「继续前往」 📱 移动端注意事项 iOS Safari 需添加 playsinline 属性 🔧 调试技巧 Chrome DevTools → Media 面板

2.6 常见问题与解决

我在教学和项目中遇到过不少新手踩坑,这里列几个最常见的:

  • 摄像头打不开? 先检查是不是 HTTPS,再检查浏览器权限设置。Chrome 地址栏左边有个小锁图标,点开看看摄像头权限是不是被禁了。
  • 画面黑屏? 确认 <video> 标签加了 autoplayplaysinline 属性。iOS 上不加 playsinline 会默认全屏播放。
  • 证书报错? 自签名证书第一次访问时,浏览器会拦截。记得手动点击「高级」→「继续前往」。
  • 手机访问不了? 确保手机和电脑在同一个局域网,然后用电脑的 IP 地址访问,比如 https://192.168.1.100:3000
💡 我的经验: 我曾经在 Safari 上调试时发现摄像头画面是镜像的,后来才知道这是正常现象——本地预览时镜像,实际传输时是正常的。别被这个吓到。

好了,环境搭建就到这里。你现在应该有一个能正常工作的 HTTPS 服务器,并且成功打开了摄像头。下一章咱们会深入 getUserMedia 的各种参数配置,包括分辨率、帧率、音频等。


公众号:蓝海资料掘金营,微信deep3321