WEBRTC 实现浏览器拍照

2023-09-01 09:09:40 浏览数 (2)

最近的几个需求都涉及到了扫码和拍照之类的功能,扫码用的是插件 html5-qrcode,拍照就自己写了一下,没多少行代码。

用的是 WEBRTC 的 api 然后把视频流画到 canvas 里面,再保存成图片,直接上代码:

代码语言:javascript复制
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    *{
      margin: 0;
      padding: 0;
      list-style: none;
    }
  </style>
</head>
<body>
<div>
  <video id="cameraVideo" autoplay="true"></video>
</div>
<button onclick="takePhoto()">开始</button>
<button onclick="snapPhoto()">拍照</button>
<button onclick="closePhoto()">关闭</button>

<script>
  let mediaStream = null;
  var track = null;

  function takePhoto () {
    navigator.mediaDevices
      .getUserMedia({
        video: true,
      })
      .then(function (stream) {
        let video = document.getElementById('cameraVideo');
        video.srcObject = stream;
        mediaStream = stream;
        track = stream.getTracks()[0];
      })
      .catch(function (err) {
        console.log(err);
      });
  }

  function snapPhoto () {
    var canvas = document.createElement('canvas');
    let videoEl = document.getElementById('cameraVideo');
    let videoH = videoEl.videoHeight;
    let videoW = videoEl.videoWidth;
    canvas.width = videoW;
    canvas.height = videoH;
    var video = document.getElementById('cameraVideo');
    var ctx = canvas.getContext('2d');
    ctx.drawImage(video, 0, 0, videoW, videoH);
    canvas.toBlob(function(blob){
      var file = new File([blob], Date.now().toString()   '.png', {
        type: "image/png",
        lastModified: Date.now()
      });
      download(Date.now().toString()   '.png', file);
    });
  }

  function closePhoto () {
    if (mediaStream !== null) {
      if (mediaStream.stop) {
          mediaStream.stop();
      }
    };
    if (track !== null) {
        if (track.stop) {
            track.stop();
        }
    };

    var video = document.getElementById('cameraVideo');
    video.src = "";
  }

  const download = (fileName, blob) => {
    const link = document.createElement("a");
    link.href = URL.createObjectURL(blob);
    link.download = fileName;
    link.click();
    link.remove();
    URL.revokeObjectURL(link.href);
  };
</script>
</body>
</html>

一开始用的是简写 navigator.getUserMedia,结果 ios 居然不行,后面 navigator.mediaDevices.getUserMedia 就可以了,也是神奇。

还有要注意,如果不想视频拍照的时候全屏(移动端),给 video 加上属性 webkit-playsinline playsinline x5-video-player-type="h5-page"

另外视频可以设置前置和后置摄像头,分辨率,video 是对象,user 是前置,environment 是后置,width/height 是分辨率,移动端可能还反着来,就是这个分辨率一直不知道是怎么可以设置全,因为拍照的框是固定的,所以很难设置的刚好,如果只是播放视频还好,通过判断分辨率然后用 css 控制 object-fit,是 cover 还是 contain,如果是 fill 就有肯能变形。

代码语言:javascript复制
{
  facingMode: 'environment',
  width: { ideal: 720 },
  height: { ideal: 1280 },
}

要是有人对这个分辨率有很好的理解,求指教,毕竟现在的项目有可能要解决满框。

也可以到 GitHub 下载对应的代码:https://github.com/wade3po/demoCode

0 人点赞