当前位置: 首页 > article >正文

电脑端调用摄像头拍照:从基础到实现

文章目录

    • 1. 了解`navigator.mediaDevices.getUserMedia` API
    • 2. 创建 HTML 结构
    • 3. 编写 JavaScript 代码
      • 3.1 打开摄像头
      • 3.2 拍照
    • 4. 完整代码
    • 5. 测试
    • 6. 注意事项及部署

在现代 Web 开发中,调用摄像头进行拍照是一个常见的功能,尤其是在需要用户上传头像、进行身份验证或实时交互的场景中。本文将逐步介绍如何在电脑端通过 HTML 和 JavaScript 调用摄像头进行拍照,并上传照片。我们将使用navigator.mediaDevices.getUserMedia API 来实现这一功能。

1. 了解navigator.mediaDevices.getUserMedia API

  • MediaDevices.getUserMedia() API

  • navigator.mediaDevices.getUserMedia 是一个现代浏览器提供的 API,用于访问用户的摄像头和麦克风。MediaDevices.getUserMedia() 会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D 转换器等等),也可能是其他轨道类型。它返回一个 Promise 对象,成功后会resolve回调一个 MediaStream 对象。若用户拒绝了使用权限,或者需要的媒体源不可用,promise 会reject回调一个 PermissionDeniedError 或者 NotFoundError

  • 通过这个 API,我们可以请求设备的媒体输入,并将其流式传输到 HTML 的 <video> 元素中。

主要步骤

  1. 请求用户权限:在使用摄像头之前,必须请求用户的权限。
  2. 获取媒体流:通过navigator.mediaDevices.getUserMedia获取媒体流。
  3. 显示视频流:将媒体流绑定到 <video> 元素中。
  4. 拍照:使用 <canvas> 元素捕获视频帧并生成图片。

2. 创建 HTML 结构

首先,我们需要创建一个简单的 HTML 页面,包含一个视频元素、一个画布元素和两个按钮(一个用于打开摄像头,一个用于拍照)。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>摄像头拍照</title>
    <style>
      .btn {
        display: flex;
        width: 40%;
        height: 80px;
        align-items: center;
        justify-content: space-around;
      }
      .btn div {
        background-color: purple;
        color: white;
        border-radius: 10px;
        padding: 1rem;
      }
    </style>
  </head>
  <body>
    <div></div>
    <video id="video" autoplay style="width: 200px; height: 200px"></video>
    <canvas
      id="canvas"
      width="200"
      height="200"
      style="border: 5px dotted yellowgreen"
    ></canvas>
    <div class="btn">
      <div id="open">打开摄像头</div>
      <div id="photo">拍照</div>
    </div>
  </body>
</html>

3. 编写 JavaScript 代码

3.1 打开摄像头

当点击 打开摄像头 按钮时,我们需要调用navigator.mediaDevices.getUserMedia来请求摄像头权限,并将视频流绑定到 <video> 元素中。

let open = document.querySelector("#open");
let video = document.querySelector("#video");

open.onclick = () => {
  let constraints = {
    video: { width: 200, height: 200 },
    audio: false,
  };

  navigator.mediaDevices
    .getUserMedia(constraints)
    .then((stream) => {
      video.srcObject = stream;
      video.play();
    })
    .catch((error) => {
      console.error("摄像头打开失败:", error);
    });
};

3.2 拍照

当点击拍照 按钮时,我们需要使用 <canvas> 元素捕获当前视频帧,并将其转换为图片。

let photo = document.querySelector("#photo");
let canvas = document.querySelector("#canvas");

photo.onclick = () => {
  let ctx = canvas.getContext("2d");
  ctx.drawImage(video, 0, 0, 200, 200);

  // 将画布内容转换为 Base64 格式
  let url = canvas.toDataURL("image/png");
  console.log("Base64 URL: ", url);

  // 将画布内容转换为 Blob 对象
  canvas.toBlob((blob) => {
    let blobUrl = URL.createObjectURL(blob);
    let file = new window.File([blob], "封面图.png", { type: "image/png" });
    console.log("Blob URL: ", blobUrl);
    console.log("创建的新文件:", file);

    // 使用FormData上传图片
    let formData = new FormData();
    formData.append("img", file);

    fetch("http://localhost:8000", {
      method: "post",
      body: formData,
    })
      .then((response) => {
        if (response.ok) {
          console.log("文件上传成功");
        } else {
          console.error("文件上传失败");
        }
      })
      .catch((error) => {
        console.error("图片上传失败:", error);
      });
  });
};

4. 完整代码

将上述 HTML 和 JavaScript 代码组合在一起,完整的 HTML 文件如下:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>摄像头拍照</title>
    <style>
      .btn {
        display: flex;
        width: 40%;
        height: 80px;
        align-items: center;
        justify-content: space-around;
      }
      .btn div {
        background-color: purple;
        color: white;
        border-radius: 10px;
        padding: 1rem;
      }
    </style>
  </head>
  <body>
    <div></div>
    <video id="video" autoplay style="width: 200px; height: 200px"></video>
    <canvas
      id="canvas"
      width="200"
      height="200"
      style="border: 5px dotted yellowgreen"
    ></canvas>
    <div class="btn">
      <div id="open">打开摄像头</div>
      <div id="photo">拍照</div>
    </div>
    <script>
      let open = document.querySelector("#open");
      let video = document.querySelector("#video");
      let photo = document.querySelector("#photo");
      let canvas = document.querySelector("#canvas");

      open.onclick = () => {
        let constraints = {
          video: { width: 200, height: 200 },
          audio: false,
        };

        navigator.mediaDevices
          .getUserMedia(constraints)
          .then((stream) => {
            video.srcObject = stream;
            video.play();
          })
          .catch((error) => {
            console.error("摄像头打开失败:", error);
          });
      };

      photo.onclick = () => {
        let ctx = canvas.getContext("2d");
        ctx.drawImage(video, 0, 0, 200, 200);

        // 将画布内容转换为Base64格式
        let url = canvas.toDataURL("image/png");
        console.log("Base64 URL: ", url);

        // 将画布内容转换为Blob对象
        canvas.toBlob((blob) => {
          let blobUrl = URL.createObjectURL(blob);
          let file = new window.File([blob], "封面图.png", {
            type: "image/png",
          });
          console.log("Blob URL: ", blobUrl);
          console.log("创建的新文件:", file);

          // 使用FormData上传图片
          let formData = new FormData();
          formData.append("img", file);

          fetch("http://localhost:8000", {
            method: "post",
            body: formData,
          })
            .then((response) => {
              if (response.ok) {
                console.log("文件上传成功");
              } else {
                console.error("文件上传失败");
              }
            })
            .catch((error) => {
              console.error("图片上传失败:", error);
            });
        });
      };
    </script>
  </body>
</html>

5. 测试

测试:在本地运行 HTML 文件,使用 live Server,确保摄像头可以正常打开,并且拍照功能可以正常工作。

截图
FormData
在这里插入图片描述

6. 注意事项及部署

  • 部署:将 HTML 文件部署到支持 HTTPS 的服务器上,因为navigator.mediaDevices.getUserMedia需要在 HTTPS 环境下工作。
  • 浏览器支持:确保目标浏览器支持navigator.mediaDevices.getUserMedia API。
  • 错误处理:在实际应用中,需要对可能出现的错误进行处理,例如用户拒绝权限请求。

http://www.kler.cn/a/549779.html

相关文章:

  • 力扣动态规划-32【算法学习day.126】
  • 第1章大型互联网公司的基础架构——1.1 单机房的内部架构
  • 领域驱动设计叕创新,平安保险申请DDD专利
  • 回顾Golang的Channel与Select第一篇
  • Docker-常见命令
  • android 源码切换分支
  • 升级 SpringBoot3 全项目讲解 — 别再使用 Optional 了,请使用 Jspecify 来替代它
  • 【Axure教程】数字滚动效果
  • boolen盲注与时间盲注,sqli-labs第八关与第九关
  • 回调函数
  • linux笔记3----防火墙(ubuntu)
  • 本地音乐播放器(有UI界面)
  • Python VsCode DeepSeek接入
  • 从零开始学Python爬虫:(二)使用基本库urllib(下)
  • React 中的状态和属性有什么区别?
  • 在 Go 中实现事件溯源:构建高效且可扩展的系统
  • iOS事件传递和响应
  • springboot245-springboot项目评审系统(源码+论文+PPT+部署讲解等)
  • word文档提取信息
  • 从安装软件到flask框架搭建可视化大屏(二)——创建一个flask页面,搭建可视化大屏,零基础也可以学会