17、WebRTC与AI结合:实时语音识别、人脸特效、背景替换

说实话,WebRTC 本身只是个传输管道。真正让实时通信变得「聪明」的,是 AI。

我最早接触这个方向,是在一个远程会议项目里。客户说:「能不能把背景换成海滩?」我当时心想,这不就是绿幕抠像吗?但后来发现,在浏览器里做实时背景替换,坑比想象中多得多。

这一章,我们就聊聊 WebRTC 和 AI 怎么结合。重点放在三个方向:实时语音识别人脸特效背景替换。这些都是我在实际项目中踩过坑、也填过坑的地方。

17.1 实时语音识别:让机器听懂你在说什么

实时语音识别,说白了就是把麦克风采集到的音频流,一边传一边转成文字。

在 WebRTC 里,音频流通常通过 MediaStream 获取。然后我们可以把它喂给语音识别引擎。

17.1.1 浏览器原生方案:Web Speech API

最简单的做法,是用浏览器自带的 SpeechRecognition API。它不需要额外引入 SDK,开箱即用。

const recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition)();
recognition.lang = 'zh-CN';
recognition.interimResults = true;
recognition.continuous = true;

recognition.onresult = (event) => {
  for (let i = event.resultIndex; i < event.results.length; i++) {
    const transcript = event.results[i][0].transcript;
    console.log('识别结果:', transcript);
  }
};

// 从 WebRTC 获取音频流
navigator.mediaDevices.getUserMedia({ audio: true })
  .then((stream) => {
    // 注意:SpeechRecognition 默认使用麦克风,不需要手动传 stream
    recognition.start();
  });
注意:Web Speech API 在部分浏览器(比如 Firefox)上不支持。而且它依赖网络服务,离线环境下无法使用。

我在一个教育类项目里用过这个方案。当时学生端需要实时转写老师说的话。结果发现,如果网络延迟高,识别结果会滞后好几秒。嗯,这里要注意:实时性要求高的场景,建议用 WebSocket 对接专门的语音识别服务

17.1.2 服务端方案:WebSocket + ASR

更靠谱的做法,是把音频流通过 WebSocket 发送到服务端,由 ASR(自动语音识别)引擎处理。

// 客户端:通过 WebRTC 获取音频,然后发送到服务端
const peerConnection = new RTCPeerConnection();
const audioTrack = localStream.getAudioTracks()[0];
peerConnection.addTrack(audioTrack, localStream);

// 同时,把音频数据通过 WebSocket 发送
const socket = new WebSocket('wss://your-asr-server.com/ws');
const mediaRecorder = new MediaRecorder(localStream, { mimeType: 'audio/webm' });

mediaRecorder.ondataavailable = (event) => {
  if (event.data.size > 0) {
    socket.send(event.data);
  }
};

mediaRecorder.start(100); // 每 100ms 发送一次
经验之谈:我曾经在医疗问诊项目里用这个方案。当时踩了一个坑:音频编码格式不匹配。服务端只认 PCM,但浏览器默认输出的是 Opus。解决办法是在服务端做转码,或者用 AudioContext 在浏览器端先解码再编码。

17.2 人脸特效:给视频流加点「魔法」

人脸特效,比如加个兔子耳朵、戴个墨镜,本质上是对视频帧做实时图像处理。

在 WebRTC 里,我们需要拦截视频轨道,逐帧处理,再放回去。

17.2.1 核心流程:MediaStream -> Canvas -> 替换轨道

基本思路是这样的:

  1. getUserMedia 获取原始视频流
  2. CanvasWebGL 逐帧绘制,叠加特效
  3. 把 Canvas 的流通过 captureStream() 转换成新的 MediaStream
  4. 用新流替换掉原始流
const video = document.createElement('video');
video.srcObject = localStream;
video.play();

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

function processFrame() {
  ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
  // 在这里叠加特效,比如画个眼镜
  drawGlasses(ctx);
  requestAnimationFrame(processFrame);
}

processFrame();

const processedStream = canvas.captureStream(30);
// 替换掉原始视频轨道
const sender = peerConnection.getSenders().find(s => s.track.kind === 'video');
sender.replaceTrack(processedStream.getVideoTracks()[0]);
关键点:人脸检测通常用 face-api.jsMediaPipe。我建议用 MediaPipe,它支持 WebGL 加速,性能更好。

17.2.2 避坑指南:性能与延迟

我曾经在一个直播项目里做美颜特效。一开始用纯 Canvas 逐帧处理,结果 CPU 直接拉满,帧率掉到 10fps 以下。

后来改用 WebGL 着色器,性能提升了好几倍。说白了,图像处理一定要走 GPU

性能警告:每帧处理时间不要超过 16ms(60fps 的要求)。如果特效复杂,建议降低分辨率或帧率。比如先缩放到 640x480 再处理。

17.3 背景替换:从绿幕到 AI 抠图

背景替换,早期靠绿幕。现在靠 AI 语义分割。

最流行的方案是 MediaPipe Selfie Segmentation。它能在浏览器里实时分割出人像区域。

17.3.1 实现步骤

  1. 加载 MediaPipe 模型
  2. 对每一帧视频做分割,得到人像蒙版
  3. 用蒙版合成新背景
// 使用 @mediapipe/selfie_segmentation
const selfieSegmentation = new SelfieSegmentation({
  locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/selfie_segmentation/${file}`
});

selfieSegmentation.setOptions({
  modelSelection: 1, // 0: 通用, 1: 景观(效果更好但更慢)
});

selfieSegmentation.onResults((results) => {
  // results.segmentationMask 是蒙版
  // 用蒙版合成背景
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.drawImage(results.image, 0, 0);
  ctx.globalCompositeOperation = 'destination-in';
  ctx.drawImage(results.segmentationMask, 0, 0);
  // 再绘制新背景
  ctx.globalCompositeOperation = 'destination-over';
  ctx.drawImage(backgroundImage, 0, 0);
});
小技巧:如果背景是纯色(比如蓝色或绿色),可以用色度键抠图,速度更快。但 AI 分割的优点是:不需要绿幕,任何背景都能换。

17.3.2 我踩过的坑

有一次,用户反馈背景替换后,边缘有「毛刺」。我排查了半天,发现是蒙版分辨率太低。

解决办法:把蒙版放大到和视频同尺寸,再做边缘羽化。嗯,这个细节很容易被忽略。

17.4 知识体系总览

下面这张图,概括了 WebRTC + AI 的核心逻辑。你可以把它当作一个参考框架。

WebRTC + AI 实时处理架构 MediaStream 音频/视频原始流 AI 处理引擎 语音识别 / 人脸检测 语义分割 / 特效叠加 新 MediaStream 替换轨道后发送 语音识别分支 • Web Speech API(浏览器原生) • WebSocket + 服务端 ASR • 实时转写 / 字幕生成 人脸特效分支 • Canvas / WebGL 逐帧处理 • MediaPipe 人脸关键点 • 美颜 / 贴纸 / 滤镜 背景替换分支 • 色度键抠图(绿幕) • AI 语义分割(MediaPipe) • 边缘羽化 / 合成 核心原则 性能优先 → 走 GPU 处理 | 延迟控制 → 每帧 < 16ms | 兼容性 → 降级方案

17.5 总结与建议

WebRTC 和 AI 的结合,其实就三件事:拿流、处理、放回去

但真正落地时,性能、延迟、兼容性,每一个都是硬骨头。

我个人建议,先从简单的特效开始,比如加个滤镜。等熟悉了 Canvas 和 MediaStream 的交互,再上人脸检测和背景替换。

如果你在项目中遇到问题,可以回头看看这一章的避坑指南。很多坑,我都替你踩过了。

一句话总结:AI 让 WebRTC 从「能看见」变成「能理解」。但别忘了,实时性永远是第一位的。

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