25、WebRTC与AI结合:人脸检测、语音识别、实时字幕生成
说实话,WebRTC 做到一定程度,你会发现一个瓶颈——画面和声音是传过去了,但机器看不懂。我最早做视频会议项目时,客户提了个需求:“能不能自动把发言人框出来?” 当时我第一反应是“这得加个 AI 模块吧?” 后来真做起来才发现,WebRTC 和 AI 的结合,其实比想象中要顺滑得多。
今天我们就聊聊三个最实用的方向:人脸检测、语音识别、实时字幕生成。说白了,就是让 WebRTC 的流里跑点“脑子”。
25.1 为什么要在 WebRTC 里塞 AI?
你想想看,WebRTC 本身只负责传输音视频流。它不关心画面里有没有人,也不管对方说了什么。但实际业务中,这些信息太重要了。
- 人脸检测:自动聚焦发言人、美颜、背景虚化
- 语音识别:会议纪要、关键词提醒、实时翻译
- 实时字幕:听障辅助、嘈杂环境、多语言沟通
我在项目中遇到过最典型的场景:一个跨国会议,有人网络差,声音断断续续。如果有了实时字幕,哪怕音频丢包,文字还能补全信息。这就是 AI 的价值。
核心思路:WebRTC 提供流,AI 消费流。两者通过 MediaStream 和 MediaStreamTrack 桥接。
25.2 整体架构:AI 模块怎么插进去?
先看一张图,你就明白了。
嗯,这里要注意:AI 处理不能阻塞主线程。我早期犯过一个错——直接在 ontrack 回调里跑模型推理,结果画面卡成 PPT。后来改用 OffscreenCanvas 和 Web Worker,才把帧率稳住。
25.3 人脸检测实战
人脸检测在 WebRTC 里最常见的用法是:在本地视频上画框,然后只发送框内区域。这样可以节省带宽,也能保护隐私。
25.3.1 技术选型
| 方案 | 优点 | 缺点 |
|---|---|---|
| TensorFlow.js + FaceMesh | 纯前端,无需后端 | CPU 占用高 |
| MediaPipe | 性能好,支持 GPU | 需要额外加载 WASM |
| OpenCV.js | 经典算法,轻量 | 准确率一般 |
我个人习惯用 MediaPipe。为什么?因为它能跑在 Web Worker 里,不卡主线程。我在一个远程医疗项目里用过,1080p 30fps 的视频,检测延迟控制在 20ms 以内。
25.3.2 核心代码示例
// 1. 获取本地视频流
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
// 2. 初始化 MediaPipe Face Detection
const faceDetector = new FaceDetection({
locateFile: (file) => `https://cdn.jsdelivr.net/npm/@mediapipe/face_detection/${file}`
});
faceDetector.setOptions({
modelSelection: 1, // 0: 短距离, 1: 全距离
minDetectionConfidence: 0.7
});
// 3. 每帧检测
const video = document.createElement('video');
video.srcObject = stream;
await video.play();
async function detectLoop() {
const results = await faceDetector.send({ image: video });
if (results.detections.length > 0) {
// 在 canvas 上画框
drawFaceBox(results.detections);
// 可选:裁剪人脸区域发送
cropAndSendFace(results.detections[0]);
}
requestAnimationFrame(detectLoop);
}
detectLoop();
避坑指南:我曾经把 faceDetector.send() 放在 requestAnimationFrame 里直接跑,结果发现每帧都要等模型推理完才渲染。后来改成 setInterval 每 100ms 检测一次,渲染和检测分离,流畅度提升明显。
25.4 语音识别与实时字幕
语音识别这块,浏览器其实已经给了我们一个好东西——Web Speech API。它支持实时语音识别,而且不需要额外模型。但有个坑:它只能识别麦克风输入,不能直接识别 WebRTC 的远端音频。
25.4.1 识别远端音频的解决方案
我当时的做法是:把远端音频流通过 AudioContext 重新采样,再喂给 SpeechRecognition。说白了就是“偷梁换柱”。
// 1. 获取远端音频流
const remoteStream = peerConnection.getRemoteStreams()[0];
const audioTrack = remoteStream.getAudioTracks()[0];
// 2. 创建 AudioContext 并连接
const audioCtx = new AudioContext();
const source = audioCtx.createMediaStreamSource(new MediaStream([audioTrack]));
const dest = audioCtx.createMediaStreamDestination();
source.connect(dest);
// 3. 用 dest.stream 作为 SpeechRecognition 的输入
const recognition = new webkitSpeechRecognition();
recognition.continuous = true;
recognition.interimResults = true;
recognition.lang = 'zh-CN';
// 注意:SpeechRecognition 默认用麦克风,这里需要 hack
// 实际项目中可以用 AudioWorklet 或 MediaStreamTrackProcessor
recognition.onresult = (event) => {
for (let i = event.resultIndex; i < event.results.length; i++) {
const transcript = event.results[i][0].transcript;
if (event.results[i].isFinal) {
appendSubtitle(transcript); // 最终结果
} else {
showInterimSubtitle(transcript); // 临时结果
}
}
};
recognition.start();
注意:Web Speech API 的 start() 必须在用户交互事件(如点击)中调用,否则会被浏览器拦截。我踩过这个坑,调试了半天才发现是自动播放策略的问题。
25.4.2 字幕渲染
字幕渲染我推荐用 Canvas 覆盖层,而不是 DOM 元素。因为 Canvas 可以跟视频帧同步,不会出现字幕和画面错位的情况。
function renderSubtitle(text, isFinal) {
const canvas = document.getElementById('subtitleCanvas');
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 背景
ctx.fillStyle = 'rgba(0, 0, 0, 0.6)';
ctx.roundRect(10, canvas.height - 60, canvas.width - 20, 50, 10);
ctx.fill();
// 文字
ctx.fillStyle = isFinal ? '#ffffff' : '#aaaaaa';
ctx.font = '24px sans-serif';
ctx.textAlign = 'center';
ctx.fillText(text, canvas.width / 2, canvas.height - 25);
}
25.5 性能优化:别让 AI 拖垮 WebRTC
AI 加进来之后,最头疼的就是性能。我总结了几条经验:
- 降分辨率:人脸检测不需要 4K,320x240 足够。用
canvas.drawImage缩放到小尺寸再送检。 - 跳帧处理:不必每帧都跑 AI,15fps 的检测频率已经够用。
- 分离线程:AI 推理放到 Web Worker,渲染留在主线程。
- 硬件加速:MediaPipe 支持 WebGL 后端,记得开启。
我的经验:在一个在线教育项目里,我们同时跑了人脸检测和语音识别。一开始 CPU 飙到 90%,后来把检测分辨率降到 160x120,帧率降到 10fps,CPU 直接降到 30%。用户根本感觉不到差异。
25.6 完整流程总结
来,我们把今天的内容串一下:
- 采集:getUserMedia 获取本地流,RTCPeerConnection 获取远端流
- 人脸检测:MediaPipe 或 TensorFlow.js,在 Canvas 上画框
- 语音识别:Web Speech API + AudioContext 重采样
- 字幕生成:Canvas 覆盖层,实时渲染文字
- 发送:处理后的视频/音频通过 WebRTC 发送
说白了,WebRTC 和 AI 的结合,就是让流变得“聪明”。你不需要成为 AI 专家,只要知道怎么把模型接进来、怎么优化性能就够了。剩下的,交给浏览器和 GPU。
最后一个小建议:如果你刚开始做,先从语音识别入手。它最简单,效果也最直观。人脸检测涉及 Canvas 绘制和坐标转换,稍微复杂一点。但不管哪个方向,记住一句话——先跑通,再优化。
公众号:蓝海资料掘金营,微信deep3321