记录–h5调用手机摄像头踩坑

  • 记录–h5调用手机摄像头踩坑已关闭评论
  • 118 次浏览
  • A+
所属分类:Web前端
摘要

一般业务也很少接触摄像头,有也是现成的工具库扫个二维码。难得用一次,记录下踩坑。


这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助

记录--h5调用手机摄像头踩坑

1. 背景

一般业务也很少接触摄像头,有也是现成的工具库扫个二维码。难得用一次,记录下踩坑。

2.调用摄像头的方法

2.1. input

<!-- 调用相机 --> <input type="file" accept="image/*" capture="camera"> <!-- 调用摄像机 --> <input type="file" accept="video/*" capture="camcorder"> <!-- 调用录音机 --> <input type="file" accept="audio/*" capture="microphone">

这个就不用多说了,缺点就是没办法自定义界面,它是调用的系统原生相机界面。

2.2. mediaDevices

由于我需要自定义界面,就像下面这样:

记录--h5调用手机摄像头踩坑

所以我选择了这个方案,这个api使用起来其实很简单:

<!-- 创建一个video标签用来播放摄像头的视屏流 --> <video id="video" autoplay="autoplay" muted width="200px" height="200px"></video> <button onclick="getMedia()">开启摄像头</button>

async getMedia() {     // 获取设备媒体的设置,通常就video和audio     const constraints = {       // video配置,具体配置可以看看mdn         video: {               height: 200,               wdith: 200,           },       // 关闭音频         audio: false       };       this.video = document.getElementById("video");       // 使用getUserMedia获取媒体流     // 媒体流赋值给srcObject     this.video.srcObject = await window.navigator.mediaDevices.getUserMedia(constraints);     // 直接播放就行了     this.video.play();   }

记录--h5调用手机摄像头踩坑

可以看到这个效果。

这个api的配置可以参考MDN

// 截图拍照 takePhoto() {       const video = document.getElementById("video");       // 借助canvas绘制视频的一帧     const canvas = document.getElementById("canvas");       const ctx = canvas.getContext('2d');       ctx.drawImage(this.video, 0, 0, 300, 300);   }, // 停止 stopMedia() {       // 获取媒体流     const stream = this.video.srcObject;       const tracks = stream.getTracks();       // 停止所有轨道     tracks.forEach(function (track) {           track.stop();     })       this.video.srcObject = null;   }

3.坑

如果你复制我的代码,在localhost上肯定能运行,但是你想在手机上试试的时候就会发现很多问题。

3.1. 需要https

由于浏览器的安全设置,除了localhosthttps连接,你都没办法获取到navigator.mediaDevices,打印出来是undefined。如果要在手机上测试,你要么用内网穿透代理一个https,要么部署在https域名的服务器上测试。

3.2. 设置前后摄像头

默认是使用user设备,也就是前摄像头,想要使用后摄像头也是有配置的,

async getMedia() {     // ...     let constraints = {           video: {               height: 200,               wdith: 200,               // environment设备就是后置             facingMode: { exact: "environment" },           },           audio: false       };     // ... }

3.3. 设置显示区域大小

我的需求是铺满整个设备,所以我想当然的直接把video样式宽高设置成容器大小:

#video {     width: 100%;     height: 100%; }   async getMedia() {     // ....     // 将宽高设置成容器大小     const pageSize = document.querySelector('.page').getBoundingClientRect()       let constraints = {       video: {               height: pageSize.height,               width: pageSize.width,               facingMode: { exact: "environment" },         },           audio: false       };     //.... }

记录--h5调用手机摄像头踩坑

发现这个视频横着而且没有铺满屏幕。

通过输出video的信息可以看到,设备返回的视频流宽高是反的:

记录--h5调用手机摄像头踩坑

 所以配置换一下就行了:

    let constraints = {           video: {               height: pageSize.width,               width: pageSize.height,           },       };

本文转载于:

https://juejin.cn/post/7287965561035210771

如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

 记录--h5调用手机摄像头踩坑