基于Chrome的浏览器访问摄像头时出现Permissions Policy违规问题
仅在Chrome系浏览器中调用摄像头时触发Permissions Policy违规,Safari和Firefox可正常运行。错误信息如下:
[Violation] Permissions policy violation: camera is not allowed in this document.
Error accessing the camera: DOMException: Permission denied
相关代码片段:
JS代码
const scanner = document.getElementById('scanner'); const qrCanvas = document.getElementById('qr-canvas'); const qrDataElement = document.getElementById('qr-data'); const scanMenuItemCamera = document.getElementById('scan'); const menuItemsCamera = document.querySelectorAll('.menu-item'); let cameraStream = null; function startCameraFeed() { if (scanner && qrCanvas) { const videoConstraints = { facingMode: 'environment', width: 1280, height: 720 }; if (window.location.protocol === 'https:') { navigator.mediaDevices.getUserMedia({ video: videoConstraints }) .then(stream => { scanner.srcObject = stream; scanner.addEventListener('play', scanCodes); cameraStream = stream; const videoElement = document.getElementById('scanner'); const zoomSlider = document.getElementById('zoomSlider'); zoomSlider.addEventListener('input', (event) => { const scale = parseFloat(event.target.value); videoElement.style.transform = `scale(${scale})`; }); videoElement.style.transform = 'translateZ(0)'; }) .catch(error => console.error('Error accessing the camera:', error)); } else { console.error('Please use a secure connection (HTTPS) to access the camera.'); } } } document.addEventListener('DOMContentLoaded', () => { startCameraFeed(); menuItemsCamera.forEach(menuItemCamera => { menuItemCamera.addEventListener('click', () => { if (menuItemCamera.id === 'scan') { startCameraFeed(); } else { stopCameraFeed(); } }); }); function stopCameraFeed() { if (cameraStream) { cameraStream.getTracks().forEach(track => track.stop()); cameraStream = null; } } scanMenuItemCamera.addEventListener('click', startCameraFeed); });
HTML代码
<div id="controls"> <input type="range" id="zoomSlider" min="1" max="5" step="0.01" value="1"> </div> <video id="scanner" autoplay=""></video> <canvas id="qr-canvas"></canvas> <div id="qr-data" class="background"></div> <a class="menu-item" id="scan"></a>
Chrome对Permissions Policy的执行比其他浏览器更严格,可从以下几个方向排查修复:
检查服务器HTTP头部:确保返回的
Permissions-Policy头部包含camera=()(允许所有来源访问摄像头),或者根据需求指定特定来源,比如camera=(self)仅允许本站点。如果服务器配置了限制摄像头的策略,Chrome会直接拒绝请求。添加HTML meta标签:如果无法修改服务器配置,可在HTML的
<head>中添加meta标签声明权限策略:<meta http-equiv="Permissions-Policy" content="camera=()">检查Chrome站点权限:手动确认当前站点在Chrome中的摄像头权限是否被禁用。操作路径:点击地址栏左侧的锁图标 → 「网站设置」→ 找到「摄像头」选项,设置为「允许」。
优化代码逻辑:当前代码在
DOMContentLoaded时自动调用startCameraFeed,同时scan按钮又绑定了该方法,可能导致重复发起权限请求引发冲突。可修改逻辑,确保仅在用户主动触发(比如点击按钮)时请求摄像头权限,避免页面加载时自动请求:document.addEventListener('DOMContentLoaded', () => { // 移除自动调用startCameraFeed() menuItemsCamera.forEach(menuItemCamera => { menuItemCamera.addEventListener('click', () => { if (menuItemCamera.id === 'scan') { startCameraFeed(); } else { stopCameraFeed(); } }); }); function stopCameraFeed() { if (cameraStream) { cameraStream.getTracks().forEach(track => track.stop()); cameraStream = null; } } scanMenuItemCamera.addEventListener('click', startCameraFeed); });
内容的提问来源于stack exchange,提问作者NDi

