如何在getUserMedia()中选择多个后置摄像头中分辨率最高的设备解决画面放大问题
安卓网页后置摄像头画面放大问题修复方案
核心原因有两点:
- 安卓多摄设备枚举的首个后置摄像头多为超广角/长焦副摄,并非原生相机默认使用的广角主摄
- 未指定采集分辨率时,浏览器会自动选择低分辨率采集再拉伸裁切,导致画面看起来被放大
具体优化步骤
- 优化设备选择逻辑,自动识别后置主摄
枚举视频输入设备时,优先选择label包含wide、主摄、back main关键词的设备,若标签无明确标识,可对比各摄像头的最大采集分辨率,主摄通常为分辨率最高的后置摄像头。 - 补充视频采集参数约束
调用getUserMedia时明确指定理想采集分辨率,避免浏览器自动裁切。 - 保留手动切换兜底
原有下拉选择摄像头的逻辑可保留,覆盖特殊设备主摄标识不标准的场景。
优化后完整代码
'use strict'; var videoElement = document.querySelector('video'); var audioSelect = document.querySelector('select#audioSource'); var videoSelect = document.querySelector('select#videoSource'); // 存储所有后置摄像头信息 var rearCameras = []; audioSelect.onchange = getStream; videoSelect.onchange = getStream; // 先申请基础权限,确保枚举设备时能拿到正确的设备标签 getStream({video: true, audio: true}).then(getDevices).then(gotDevices); function getDevices() { return navigator.mediaDevices.enumerateDevices(); } function gotDevices(deviceInfos) { window.deviceInfos = deviceInfos; console.log('Available input and output devices:', deviceInfos); // 清空原有选项 audioSelect.innerHTML = ''; videoSelect.innerHTML = ''; rearCameras = []; for (const deviceInfo of deviceInfos) { const option = document.createElement('option'); option.value = deviceInfo.deviceId; if (deviceInfo.kind === 'audioinput') { option.text = deviceInfo.label || `麦克风 ${audioSelect.length + 1}`; audioSelect.appendChild(option); } else if (deviceInfo.kind === 'videoinput') { option.text = deviceInfo.label || `摄像头 ${videoSelect.length + 1}`; videoSelect.appendChild(option); // 筛选后置摄像头 if (deviceInfo.label.toLowerCase().includes('back') || deviceInfo.label.includes('后置')) { rearCameras.push({ id: deviceInfo.deviceId, label: deviceInfo.label }) } } } // 自动选择最优主摄 if (rearCameras.length > 0) { let mainCamera = rearCameras.find(cam => cam.label.toLowerCase().includes('wide') || cam.label.includes('主摄') || cam.label.includes('广角') ) || rearCameras[0]; videoSelect.value = mainCamera.id; // 重新拉取主摄流 getStream(); } } function getStream(customConstraints) { if (window.stream) { window.stream.getTracks().forEach(track => { track.stop(); }); } const audioSource = audioSelect.value; const videoSource = videoSelect.value; const constraints = customConstraints || { audio: {deviceId: audioSource ? {exact: audioSource} : undefined}, video: { deviceId: videoSource ? {exact: videoSource} : undefined, // 指定理想分辨率,可根据页面video尺寸调整 width: {ideal: videoElement.clientWidth || 1920}, height: {ideal: videoElement.clientHeight || 1080} } }; return navigator.mediaDevices.getUserMedia(constraints). then(gotStream).catch(handleError); } function gotStream(stream) { window.stream = stream; const audioTrack = stream.getAudioTracks()[0]; const videoTrack = stream.getVideoTracks()[0]; if (audioTrack) { audioSelect.selectedIndex = [...audioSelect.options]. findIndex(option => option.text === audioTrack.label); } if (videoTrack) { videoSelect.selectedIndex = [...videoSelect.options]. findIndex(option => option.text === videoTrack.label); // 可打印摄像头能力确认参数 console.log('当前摄像头能力:', videoTrack.getCapabilities()); } videoElement.srcObject = stream; } function handleError(error) { console.error('Error: ', error); }
同类问题效果示例:
内容的提问来源于stack exchange,提问作者HUNG
相关产品推荐
相关产品推荐


