
本文介绍如何利用 html5 的 `mediadevices` api 在浏览器中安全、可靠地访问移动设备摄像头,包括枚举所有可用音视频设备、触发原生相机界面,以及处理常见兼容性与权限问题。
现代 Web 应用无需依赖原生 App 即可调用移动设备摄像头——关键在于正确使用标准化的 Web API。核心方案是 navigator.mediaDevices.getUserMedia()(用于直接启动摄像头)和 navigator.mediaDevices.enumerateDevices()(用于获取设备列表),二者均属于 MediaDevices API,已获 Chrome、Safari(iOS 11+)、Firefox 和 Edge 全面支持。
✅ 正确调起移动相机(推荐方式)
在移动端,最可靠的方式是通过 触发系统原生相机界面(capture="environment" 强制后置摄像头;"user" 可选前置):
function handlePhoto(file) {
if (file && file.type.startsWith('image/')) {
const url = URL.createObjectURL(file);
document.getElementById('preview').src = url; // 显示预览
}
}该方案优势明显:无需手动请求权限、兼容性极佳(包括微信内置浏览器)、自动跳转至原生相机并支持拍照/录像/相册切换。
✅ 枚举所有可用摄像头(适用于 PC + 高级控制场景)
若需在桌面端提供多摄像头选择,或在移动端调试设备信息,可使用 enumerateDevices():
async function listCameras() {
try {
// 必须先获得至少一项媒体权限(否则返回空设备列表)
await navigator.mediaDevices.getUserMedia({ video: true });
const devices = await navigator.mediaDevices.enumerateDevices();
const cameras = devices.filter(d => d.kind === 'videoinput');
console.log('可用摄像头:', cameras);
// 示例输出: [{ deviceId: 'abc...', label: 'Front Camera', kind: 'videoinput' }, ...]
} catch (err) {
console.error('无法获取设备列表:', err);
}
}⚠️ 注意事项:
- enumerateDevices() 必须在用户手势(如点击)后且已获得 getUserMedia 权限的前提下调用,否则 label 字段为空(出于隐私保护);
- iOS Safari 对 enumerateDevices() 支持较晚(iOS 13.4+),旧版本可能仅返回默认设备;
- 移动端通常只暴露 1–2 个逻辑摄像头(environment / user),不建议强行“选择”——应优先使用 capture 属性交由系统处理。
✅ 最佳实践总结
| 场景 | 推荐方案 | 说明 |
|---|---|---|
| 通用拍照(含微信、支付宝等内嵌浏览器) | 兼容性最好,零 JS 权限风险,用户体验一致 | |
| 需要实时预览/自定义 UI/滤镜处理 | getUserMedia({ video: true }) + | 需显式请求权限,注意 iOS/Safari 需 playsinline 属性 |
| 多摄像头切换(桌面为主) | enumerateDevices() + getUserMedia({ video: { deviceId: exact: 'xxx' } }) | 仅在可信上下文(HTTPS)及用户授权后生效 |
最后提醒:所有摄像头访问均要求页面运行在 HTTPS 或 localhost 环境下;生产环境务必添加错误处理与降级提示(如“请在支持摄像头的设备上打开”),并尊重用户隐私——避免未经同意持续采集媒体流。










