捕获本地媒体

getUserMedia()在各浏览器的区别:

Chrome‌:
支持版本:53+(标准 API),旧版需前缀 webkitGetUserMedia。
标准用法:navigator.mediaDevices.getUserMedia()。
‌Firefox‌:
支持版本:36+,无前缀。
‌Safari‌:
支持版本:11+(iOS 11+ 和 macOS High Sierra+),旧版需前缀 webkitGetUserMedia。
‌Edge‌:
Chromium 内核版(79+):同 Chrome,无前缀。
旧版 EdgeHTML:部分支持,需前缀 msGetUserMedia。
‌Opera‌:
支持版本:40+,行为与 Chrome 一致。

HTTPS 要求‌
‌所有现代浏览器‌(Chrome、Firefox、Safari、Edge)要求‌非本地环境必须使用 HTTPS‌。
‌例外‌:localhost 和 file:// 协议下允许 HTTP(Safari 对 file:// 限制更严格)。

约束支持(Constraints)‌
‌Chrome/Firefox/Edge‌:
支持常用约束(如 width、height、frameRate)。
支持高级选项(如 noiseSuppression、echoCancellation)。
‌Safari‌:
支持基础约束(如分辨率、设备 ID)。
‌不支持‌ facingMode(前后摄像头切换需通过设备 ID 指定)。
某些音频处理选项可能受限(如 autoGainControl)。

. 权限行为‌
‌桌面浏览器‌:
弹窗请求摄像头/麦克风权限,可单独授权。
‌移动端(iOS Safari)‌:
‌必须由用户手势触发‌(如点击事件),否则直接拒绝。
首次请求会弹窗,后续访问可能静默授权(需用户手动重置)。

移动端特殊限制‌
‌iOS Safari‌:
无法同时请求 audio 和 video(需分开授权)。
视频分辨率受系统限制(通常最高 720p)。
页面跳转或进入后台时,媒体流自动停止。
‌Android Chrome/Firefox‌:
行为接近桌面版,但受设备硬件影响更大。

兼容性代码

// 检测标准化 API
if (navigator.mediaDevices?.getUserMedia) {
  navigator.mediaDevices.getUserMedia({ video: true, audio: true })
    .then(stream => console.log("成功获取媒体流"))
    .catch(error => console.error("错误:", error.name));
} else {
  // 处理旧版浏览器(如 Safari 10-)
  const legacyGetUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
  if (legacyGetUserMedia) {
    legacyGetUserMedia.call(navigator, { video: true }, 
      stream => console.log("成功"), 
      error => console.error("失败")
    );
  }
}

以下是一个完整的、兼容主流浏览器的WebRTC示例代码,包含摄像头/麦克风访问和基础错误处理:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebRTC 兼容性演示</title>
    <!-- 引入 WebRTC 适配库 -->
    <script src="adapter-latest.js"></script>
    <style>
        video {
            width: 400px;
            height: 300px;
            border: 2px solid #333;
            margin: 10px;
        }
        .container {
            margin: 20px;
        }
        button {
            padding: 10px;
            margin: 5px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>WebRTC 媒体演示</h1>
        <video id="localVideo" autoplay playsinline></video>
        <div>
            <button id="startBtn">启动摄像头</button>
            <button id="stopBtn" disabled>停止摄像头</button>
        </div>
        <div id="errorMsg" style="color: red;"></div>
    </div>

    <script>
        const localVideo = document.getElementById('localVideo');
        const startBtn = document.getElementById('startBtn');
        const stopBtn = document.getElementById('stopBtn');
        const errorMsg = document.getElementById('errorMsg');
        
        let localStream = null;

        // 浏览器兼容性处理函数
        async function getMedia(constraints) {
            try {
                // 现代浏览器标准用法
                if (navigator.mediaDevices?.getUserMedia) {
                    return await navigator.mediaDevices.getUserMedia(constraints);
                }
                
                // 旧版浏览器兼容处理
                const legacyGetUserMedia = (
                    navigator.webkitGetUserMedia || 
                    navigator.mozGetUserMedia || 
                    navigator.msGetUserMedia
                );
                
                if (legacyGetUserMedia) {
                    return await new Promise((resolve, reject) => {
                        legacyGetUserMedia.call(navigator, constraints, resolve, reject);
                    });
                }
                
                throw new Error('浏览器不支持媒体设备访问');
            } catch (error) {
                handleError(error);
                throw error;
            }
        }

        // 启动摄像头
        async function startCamera() {
            try {
                errorMsg.textContent = '';
                localStream = await getMedia({ 
                    video: {
                        width: { ideal: 1280 },
                        height: { ideal: 720 },
                        facingMode: "user"
                    }, 
                    audio: true 
                });
                
                localVideo.srcObject = localStream;
                startBtn.disabled = true;
                stopBtn.disabled = false;
            } catch (error) {
                console.error('媒体访问错误:', error);
            }
        }

        // 停止摄像头
        function stopCamera() {
            if (localStream) {
                localStream.getTracks().forEach(track => track.stop());
                localVideo.srcObject = null;
                startBtn.disabled = false;
                stopBtn.disabled = true;
            }
        }

        // 错误处理
        function handleError(error) {
            console.error('错误:', error);
            let message = '发生错误: ';
            
            switch(error.name) {
                case 'NotAllowedError':
                    message += '用户拒绝了权限请求';
                    break;
                case 'NotFoundError':
                    message += '未找到媒体设备';
                    break;
                case 'NotReadableError':
                    message += '设备正在被其他进程使用';
                    break;
                case 'OverconstrainedError':
                    message += '无法满足约束条件';
                    break;
                default:
                    message += error.message;
            }
            
            errorMsg.textContent = message;
        }

        // 事件监听
        startBtn.addEventListener('click', startCamera);
        stopBtn.addEventListener('click', stopCamera);
    </script>
</body>
</html>

adapter-latest.js文件:

上传失败,有需要的人找我,发给你

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐