iPad Safari如何在浏览器回到前台后恢复<video>的摄像头流播放
解决方案
问题根因
iPad端Safari切换到后台时,会主动暂停摄像头媒体流、释放媒体轨道资源,切回前台后原有流已失效,因此出现黑屏。
实现步骤
- 将摄像头初始化逻辑封装为可复用函数,调用前先销毁旧流避免资源占用
- 监听页面可见性变化事件,切回前台时自动触发重新初始化流
- 给video标签添加必要属性适配Safari移动端特性
调整HTML的video标签
<!-- 必须添加playsinline属性避免Safari强制全屏,减少流异常概率 --> <video id="video" playsinline autoplay></video>
完整JS实现代码
let g_stream = null; const video = document.getElementById('video'); // 封装摄像头初始化逻辑 function initCameraStream() { // 先停止旧的流轨道,释放摄像头资源 if (g_stream) { g_stream.getTracks().forEach(track => track.stop()); g_stream = null; } if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { navigator.mediaDevices.getUserMedia({ video: true }).then(function(stream) { video.srcObject = stream; g_stream = stream; // 处理play返回的promise,避免Safari无交互场景下抛播放异常 video.play().catch(err => { console.warn('视频播放失败,请检查摄像头权限:', err); }); }).catch(err => { console.error('摄像头获取失败:', err); }); } } // 页面初始化调用 initCameraStream(); // 监听页面可见性变化,切回前台时重新加载流 document.addEventListener('visibilitychange', () => { if (document.visibilityState === 'visible') { // 加短延迟等待Safari页面状态恢复完成,避免调用时机过早失败 setTimeout(initCameraStream, 100); } }); // 兼容Safari往返缓存(Back/Forward Cache)恢复场景 window.addEventListener('pageshow', (e) => { if (e.persisted) { setTimeout(initCameraStream, 100); } });
注意事项
- 可在
initCameraStream中增加状态锁,避免短时间内重复调用getUserMedia - iOS 15以下版本的Safari可适当延长
setTimeout的延迟时间到300ms,适配旧版本页面恢复逻辑
内容的提问来源于stack exchange,提问作者Bin Chen
相关产品推荐
相关产品推荐

