浏览器禁止 file:// 协议下调用摄像头,必须通过 http://localhost 或 https:// 启动并由用户点击等手势触发 getUserMedia(),且 video 元素需设 autoplay、playsinline 和 srcObject。

浏览器不会让 index.html 直接“调用”摄像头——它必须由用户主动触发(比如点击按钮),且需运行在安全上下文(https 或 localhost)中,否则 navigator.mediaDevices.getUserMedia() 会直接拒绝或静默失败。
为什么点开 index.html 文件双击打不开摄像头
本地双击打开的 file:// 协议不被视为安全上下文,所有现代浏览器(Chrome、Edge、Firefox)都会直接拒绝 getUserMedia() 请求,控制台报错:NotAllowedError: Permission denied 或直接无响应。这不是代码写错了,是协议限制。
- 必须通过本地服务器启动:用
python3 -m http.server 8000、npx serve、VS Code Live Server 插件等 - 确保地址栏显示的是
http://localhost:xxxx或https://开头,而非file:/// - 某些旧版 Safari 对
localhost的权限策略更严格,建议用127.0.0.1替代
getUserMedia() 调用必须由用户手势触发
自动播放、页面加载时就调用 getUserMedia() 是被禁止的(防止恶意偷采)。浏览器只允许在 click、touchstart 等明确用户操作回调中发起请求。
- 不能写在
DOMContentLoaded或load事件里 - 按钮必须是真实可交互元素(
<button>或带role="button"的<div>),禁用pointer-events: none - 示例正确写法:
document.querySelector('#startBtn').addEventListener('click', async () => { try { const stream = await navigator.mediaDevices.getUserMedia({ video: true }); document.getElementById('video').srcObject = stream; } catch (err) { console.error('获取摄像头失败:', err.name); // 常见:NotAllowedError、NotFoundError } });
常见错误:视频黑屏但没报错
这通常不是权限问题,而是媒体流未正确绑定到 <video> 元素,或元素缺失必要属性。
立即学习“前端免费学习笔记(深入)”;
-
<video>标签必须有autoplay和playsinline(iOS Safari 必需)属性 - 不能用
src赋值,必须用srcObject(src只接受 URL) - 移动端需额外处理:iOS Safari 要求
webkit-playsinline,部分安卓 WebView 需muted(即使只用摄像头) - 检查控制台是否有
TypeError: Failed to set the 'srcObject' property—— 多因元素未挂载完成或被重复赋值
最易被忽略的一点:iOS Safari 在非全屏 <video> 上开启摄像头后,若用户切出页面再切回,流可能中断且不会自动恢复,需要监听 visibilitychange 手动重连。这不是 bug,是系统级资源管控策略。



















