利用浏览器实现一个极简拍照功能

1,285 阅读3分钟

本文正在参加「金石计划」

介绍WebRTC

简单介绍一下: WebRTC由Google创立,目的是实现浏览器之间能够快速音视频通信。

现在主流浏览器 Edge, Google, FIrefox... 都支持WebRTC库,表明这项技术已经是很成熟了。

如果你想深入一下

API介绍

了解需要使用到的API,防止“脸盲”

MediaDevices

接口提供访问连接媒体输入的设备,如照相机和麦克风,以及屏幕共享等。它可以使你取得任何硬件资源的媒体数据。我们就要通过该接口中的方法来获取可用的音视频设备列表

MediaDevices.getUserMedia(constraints)

官方解释该方法提示用户允许使用媒体输入,该媒体输入会产生包含所请求媒体类型的轨道。

通俗解释该方法能调用摄像头权限,打开摄像头,并通过它来收集音视频流。

getUserMedia返回一个promise对象,如果调用成功,Promise就能获取到MediaStream对象(音视频数据流),调用失败就会返回报错信息

参数constraints

constraints可以指定MediaStream中包含哪些类型的媒体轨(音频轨、视频轨),并且可为这些媒体轨设置一些限制。

image.png

格式如下:

dictionary MediaStreamConstraints {
     (boolean or MediaTrackConstraints) video = false,
     (boolean or MediaTrackConstraints) audio = false
};
getUserMedia({
  audio: {
      // 开启回音消除
      echoCancellation: true,
      // 降噪
      noiseSuppression: true,
      // 自动增益
      autoGainControl: true
      ...
  },
  video: {
      // 帧数
      frameRate: {min: 20},
      // 分辨率
      width: { ideal: 1280 },
      height: { ideal: 720 },
      ...
  },
});
// 更多可以看MDN中对它的描述

MediaDeviceInfo

该接口表示的是每个输入 / 输出设备的信息。

  • deviceID,设备唯一标识符
  • kind,设备的种类,可用于识别出是音频设备还是视频设备,是输入设备还是输出设备。枚举值:videoinput,audioinput,audiooutput
  • label, 设备名称

实现拍照功能

(电脑需要摄像头才可以接下来的实现)

其实不难,简单的分为三步去实现

  1. 调用摄像头权限,获取视频流,利用video标签将视频呈现在网页上
  2. 利用canvas技术截取视频当前帧,生成图片
  3. 保存图片到本地

获取视频流

html部分:

<video autoplay playsinline id="player">

js部分:

const video = document.querySelector('video');
const meidaStreamContainer = {
    video: true
};
const getMeidaStream = (meidaStream) => {
    video.srcObject = meidaStream;
};
const handleError = (error) => {
    alert('navigator.mediaDevice.getUserMedia error', error)
}
navigator.mediaDevices.getUserMedia(meidaStreamContainer).then(getMeidaStream).catch(handleError)

利用 mediaDecives访问连接媒体的输入设备,调用getUserMedia 方法打开摄像头,并通过它采集音视频流。然后再将采集到的视频流赋值给 HTML 中定义的 video 标签的 srcObject 字段, video 标签就可以从摄像头持续获得视频帧,并将它播放出来。

拍照功能

html部分:

<button id="take-photo">Take Photo</button>
<canvas id="canvas"></canvas>

js部分:

const canvas = document.querySelector('canvas')
    canvas.width = 640
    canvas.height = 480
    const ctx = canvas.getContext('2d')
    document.querySelector('#take-photo').onclick = () => {
        ctx.drawImage(video, 0, 0, canvas.width, canvas.height)
}

drawImage的第一个参数特别重要,既可以是图片 也能是video元素;把html中的video元素当作 drawImage的第一个参数,canvas就能获取到照片

保存照片

html部分:

<button id="save">Save Photo</button>

js部分:

const downLoad = (url) => {
    const a = document.createElement('a')
    a.download = `photo-${+ new Date()}`
    a.href = url
    document.body.appendChild(a)
    a.click()
    a.remove()
}
document.querySelector('#save').onclick = () => {
    downLoad(canvas.toDataURL("image/jpeg"));
}

代码汇总(这里没办法调用摄像头的,需要把代码复制到码上掘金就能正常运行)

总结

本文介绍了如何在浏览器上从视频流中抓取一幅图片,通过上面的介绍,你应该也了解到通过浏览器的 Canvas 来实现这个功能会特别简单。另外WebRTC的超能力还有很多,有机会与大家一起分享出来。