本文详解如何修复 web 应用中摄像头无法启动的问题,重点纠正 `navigator.mediadevices.getusermedia()` 的错误调用方式,并完整集成 face-api.js 实现基于浏览器的人脸检测、关键点定位与表情识别。
在浏览器中接入摄像头并实现实时 AI 分析(如人脸检测),是前端计算机视觉项目的关键第一步。你当前代码的核心问题在于 getUserMedia() 的调用方式——它不接受回调函数作为第二、第三个参数,而是返回一个 Promise,应使用 .then() 和 .catch() 处理成功与失败逻辑。旧式“success/failure 回调”写法已废弃,且在现代浏览器(尤其是 Chrome 73+)中会导致静默失败或 NotAllowedError / NotFoundError,这正是你尝试多种设备和权限后仍无视频流的原因。
✅ 正确的初始化方式如下:
const video = document.getElementById('video');
// ✅ 正确:返回 Promise,链式处理
navigator.mediaDevices.getUserMedia({
video: {
width: { ideal: 1280 },
height: { ideal: 720 }
}
})
.then(stream => {
video.srcObject = stream;
video.play(); // 显式调用 play() 提升兼容性
})
.catch(err => {
console.error('❌ 摄像头访问被拒绝或不可用:', err.name, err.message);
alert('请检查摄像头权限、硬件连接,或尝试在 HTTPS 环境下运行(本地 localhost 除外)');
});
⚠️ 注意事项:
- 必须在安全上下文运行:getUserMedia() 要求页面处于 https:// 或 http://localhost(含 127.0.0.1)。Live Server 在 VS Code 中默认满足此条件,但若通过 file:// 直接打开 HTML 将必然失败。
- :尤其在移动端或新版 Chrome 中,未静音的自动播放会被阻止;muted 是必要属性。
- 模型加载与视频就绪需解耦:你原代码中将模型加载 Promise.all(…).then(startVideo) 与 video.addEventListener(‘play’, …) 混用,易导致 canvas 初始化早于视频尺寸就绪。推荐改为监听 loadeddata 或显式等待 video.readyState === 4。
? 完整可运行的优化结构示例(整合 face-api.js):