功能点:html页面实现移动端拍照上传
实现:JSAPI(navigator.mediaDevices.getUserMedia)+ Video标签
(网上相关文章很多,此处不多详述)
问题场景重现:
部分安卓机(如华为,Android12)通过浏览器访问H5,开启拍摄以后,打开原生相机,再切回到浏览器页面上,拍摄中断。
若界面上有选择图片功能,部分安卓机跳转到手机图片选择器后再返回,也会出现拍摄中断问题。
尝试过方案:
1、通过video事件捕获异常,但onpause、onabort、onerror、onend等事件均没被触发。
2、通过监听H5网页切换前后台事件(visibilitychange),进入后台先将video通过onpause事件暂停,回到前台再通过onplay事件恢复播放。然而并没有用,媒体流不能恢复。
最终解决方案:
通过监听H5网页切换前后台事件(visibilitychange),回到前台时,监测video.currentTime属性,若500毫秒内数值没有变化,说明视频流已经终止,需重新初始化getUserMedia事件。
(PS:查阅了很久,这种方式暂时是最适合本人项目需求的,dom操作方式怕影响性能效果,若有更好的方法,烦请各位留个言~)
核心代码如下:
// ReactJs
const videoStream = null;
const videoRef = useRef(null);
<video
ref={videoRef}
playsInline
webkit-playsinline="true"
x5-playsinline="true"
x5-video-player-type="h5"
x5-video-player-fullscreen="false"
controlsList="noplaybackrate nodownload"
></video>;
// 监听视频流是否正常工作
const videoTimeupdate = useCallback(() => {
const { current: video } = videoRef;
const currentTime = video?.currentTime || 0;
clearTimeout(timer);
setTimer(
setTimeout(() => {
const newCurrentTime = video?.currentTime || 0;
const isStop = newCurrentTime - currentTime < 0.1;
if (isStop && videoAuth) {
// 拍摄时长不变 且 网页已授权允许调用摄像头
destoryFunc(); // 销毁视频流
initVideo(); // 重新初始化
}
}, 500)
);
}, [timer, videoAuth, destoryFunc]);
// 销毁视频流
const destoryFunc = () => {
videoStream.getTracks().forEach((track) => track.stop());
};
// 初始化
const initVideo = () => {
navigator.mediaDevices
.getUserMedia({
video: {
facingMode: "environment", // 后置摄像头
},
})
.then((stream) => {
const { current: video } = videoRef;
video.srcObject = stream;
videoStream = stream;
})
.catch(() => {});
};