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

2.1. input

 1
 2<input type="file" accept="image/*" capture="camera">
 3
 4<input type="file" accept="video/*" capture="camcorder">
 5
 6<input type="file" accept="audio/*" capture="microphone">

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

2.2. mediaDevices

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

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

 1
 2<video id="video" autoplay="autoplay" muted width="200px" height="200px"></video>
 3<button onclick="getMedia()">开启摄像头</button>
 1async getMedia() {
 2    
 3    const constraints = {  
 4    
 5        video: {  
 6            height: 200,  
 7            wdith: 200,  
 8        },  
 9    
10        audio: false  
11    };  
12    this.video = document.getElementById("video");  
13    
14    
15    this.video.srcObject = await window.navigator.mediaDevices.getUserMedia(constraints);
16    
17    this.video.play();  
18}

可以看到这个效果。

这个api的配置可以参考MDN

 1
 2takePhoto() {  
 3    const video = document.getElementById("video");  
 4    
 5    const canvas = document.getElementById("canvas");  
 6    const ctx = canvas.getContext('2d');  
 7    ctx.drawImage(this.video, 0, 0, 300, 300);  
 8},
 9
10stopMedia() {  
11    
12    const stream = this.video.srcObject;  
13    const tracks = stream.getTracks();  
14    
15    tracks.forEach(function (track) {  
16        track.stop();
17    })  
18    this.video.srcObject = null;  
19}

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

3.1. 需要https

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

3.2. 设置前后摄像头

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

 1async getMedia() {
 2    
 3    let constraints = {  
 4        video: {  
 5            height: 200,  
 6            wdith: 200,  
 7            
 8            facingMode: { exact: "environment" },  
 9        },  
10        audio: false  
11    };
12    
13}

3.3. 设置显示区域大小

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

 1#video {
 2    width: 100%;
 3    height: 100%;
 4}
 1async getMedia() {
 2    
 3    
 4    const pageSize = document.querySelector('.page').getBoundingClientRect()  
 5    let constraints = {  
 6    video: {  
 7            height: pageSize.height,  
 8            width: pageSize.width,  
 9            facingMode: { exact: "environment" },
10        },  
11        audio: false  
12    };
13    
14}

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

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

所以配置换一下就行了:

 1    let constraints = {  
 2        video: {  
 3            height: pageSize.width,  
 4            width: pageSize.height,  
 5        },  
 6    };
个人笔记记录 2021 ~ 2025