file://协议下摄像头调用必然失败,因现代浏览器强制要求媒体API须在安全上下文中运行,而file://被明确定义为非安全源,调用getUserMedia()会直接抛出NotAllowedError且不弹权限提示。

VSCode 本身不提供 HTTP 服务,直接双击打开或用 VSCode 内置预览插件(如 Live Server 未启用)运行 index.html,页面走的是 file:// 协议 —— 浏览器会直接拒绝 navigator.mediaDevices.getUserMedia(),连提示都不弹。
为什么 file:// 协议下摄像头调用必然失败
现代浏览器(Chrome、Edge、Firefox、Safari)强制要求媒体设备 API 必须在「安全上下文」中执行。file:// 协议明确被定义为非安全源,无论你代码多正确、权限设置多完善,调用 getUserMedia() 都会立刻抛出 NotAllowedError: Permission denied,且无法恢复。
- 这不是 VSCode 的 bug,也不是你的 HTML/JS 写错了,是浏览器策略铁律
- 即使你在系统设置里已授权 Chrome 访问摄像头,
file://页面也完全不读这个权限 - 控制台错误里
err.name === "NotAllowedError"是最稳定判断依据,别信err.message里的文字描述
Live Server 插件没起作用的常见原因
很多人装了 Live Server 就以为万事大吉,但实际它可能根本没真正启动服务,或者启动在了错误地址上。
- 必须打开**整个文件夹**(File → Open Folder),不是单个 HTML 文件 —— Live Server 只对文件夹根目录下的
index.html或配置指定的入口文件生效 - 检查地址栏:必须是
http://localhost:xxxx/index.html,而不是http://127.0.0.1:xxxx/—— Chrome 94+ 已明确不信任127.0.0.1,只认localhost - 端口被占会导致 Live Server “假启动”:终端显示 “Starting server”,但实际服务未起来,所有请求返回 404 或白屏。用
netstat -ano | findstr "5500"(默认端口)确认 PID,再taskkill /F /pid XXXX干掉冲突进程 - 如果用了 Vite/Webpack 等 dev server,别和 Live Server 同时开 —— 它们监听同一 host:port,后者会被前者静默抢占
就算跑在 localhost,还可能卡在哪
HTTPS 不是唯一门槛,用户交互、iframe 权限、移动端限制这些细节漏一个,照样黑屏或报错。
立即学习“前端免费学习笔记(深入)”;
- 调用
getUserMedia()必须包裹在用户手势中:按钮onclick、touchend、空格键keydown都行;放在window.onload、setTimeout或自动轮播里,Chrome/Safari 直接拒绝 - 如果页面嵌了 iframe(比如内嵌 preview),必须加
allow="camera"属性,否则 sandbox 机制直接拦截,连catch都进不去 - iOS Safari 要求
<video>元素带muted和autoplay才能播放流;没这两个属性,srcObject赋值成功也黑屏 - 部分安卓机或旧版 Chrome 对
facingMode: { exact: "environment" }不兼容,建议 fallback 到字符串写法facingMode: "user"或先枚举设备再选
真正容易被忽略的点是:你以为自己在调试“摄像头调用”,其实前两步(协议、触发时机)就卡死了。先确保 URL 是 http://localhost 开头、点击按钮才执行、控制台没报 NotAllowedError,再往下查设备列表或约束参数 —— 否则所有优化都是无意义的。


















