• JavaScript 使用 mediaDevices API 选择摄像头


    大多数智能手机都有前置和后置摄像头,当你在创建视频应用时你可能想要选择或者切换前置、后置摄像头。

    如果你开发的是一款聊天应用,你很可能会想调用前置摄像头,但如果你开发的是一款拍照软件,那么你会更倾向于使用后置摄像头。在这篇文章中我们将探讨如何通过 mediaDevices API 和 media constraints (媒体约束) 选择或者切换摄像头。

    准备工作

    要跟着本文一起动手实践你需要:

    • 一款拥有两个可供测试的摄像头的 iOS 或 Android 设备,如果你的电脑有两个摄像头那也可以

    • ngrok 以便你能通过移动设备轻松访问到你的项目(也因为我觉得 ngrok 炒鸡棒)

    • 这个 GitHub 库 的代码让你起步

    要获取代码,先把这个项目 clone 下来然后 checkout 到 initial-project tag 下。

    git clone https://github.com/philnash/mediadevices-camera-selection.git -b initial-project

    cd mediadevices-camera-selection

    这个起步项目已经为你准备好了一些 HTML 和 CSS,所以我们就可以把注意集中到 JavaScript 上了。你可以直接打开 index.html,但我建议你用一款 webserver 把这些文件托管起来。我喜欢用 npm 的 serve 模块。我在这个库里已经引入了 serve,要使用它你需要先用 npm 安装依赖然后启动这个服务。

    npm install

    npm start

    服务运行起来后,我们要用 ngrok 开启一条隧道。serve 用 5000 端口托管文件,要用 ngrok 开隧道通到这个端口,新开一个命令行窗口输入以下命令:

    `ngrok http 5000`

    好了你现在可以公网访问这个站点了,你可以在移动设备上打开这个网站,这样接下来就可以测试啦。确保你打开的是 HTTPS 的 URL,因为我们用的 API 只能在安全环境下使用。

    网站看起来像这样:

    获取 media stream

    我们的第一个任务是从任意摄像头获取视频流显示到屏幕上。完成这个之后我们再调研如何选择特定摄像头。打开 app.js , 我们以从 DOM 中选择按钮和 video 元素开始:

    // app.js

    const video = document.getElementById('video');

    const button = document.getElementById('button');

    当用户点击或触摸按钮时,我们要使用 mediaDevices API 请求摄像头权限。要这样做,我们要调用 navigator.mediaDevices.getUserMedia ,传递 media constraints 对象。让我们从简单的 constraints 开始,我们只需要视频,因此我们把 video 设置为 true,audio 设置为 false。

    getUserMedia 会返回一个 promise,当 resolve 的时候我们就可以访问到摄像头的媒体流了。把媒体流赋值给 video 元素的 srcObj 属性,我们就能从屏幕上看到视频了。

    button.addEventListener('click', event ={

      const constraints {

        videotrue,

        audiofalse

      };

      navigator.mediaDevices

        .getUserMedia(constraints)

        .then(stream ={

          video.srcObject = stream;

        })

        .catch(error ={

          console.error(error);

        });

    });

    保存文件,重新加载页面然后点击按钮。你应该能看到一个权限对话框请求访问你的摄像头,一旦授权屏幕上就应该会出现视频。在你的电脑和手机上试一试,我在我的 iPhone 上试了,被选择的是前置摄像头。

    如果你用的是一部 iPhone 手机,确认你在 Safari 里尝试,因为其他浏览器貌似并没有效果。

    可用摄像头

    media Devices API 为我们提供了一种枚举所有可用音频和视频输入设备的方式。我们要用 enumerateDevices 函数来为元素:

    const video = document.getElementById('video');

    const button = document.getElementById('button');

    const select = document.getElementById('select');

    enumerateDevices 会返回一个 promise,所以让我们写一个用来接受 promise 结果的函数吧。这个函数接收一个 media device 数组作为参数。

    首先要做的是清空元素看是否选择了特定的设备,然后基于此构造 media constraints 对象。

    这样修改按钮的点击处理函数和 video constraints:

    button.addEventListener('click', event ={

      if (typeof currentStream !== 'undefined'{

        stopMediaTracks(currentStream);

      }

      const videoConstraints {};

      if (select.value === ''{

        videoConstraints.facingMode 'environment';

      else {

        videoConstraints.deviceId { exact: select.value };

      }

      const constraints {

        video: videoConstraints,

        audiofalse

      };

    当我们想通过 deviceId 来选择设备时,使用 exact 约束。 可是对于 facingMode,我们没有使用 exact 约束, 否则在一个无法识别有没有用户或环境模式的设备上将会失败,导致我们什么媒体设备也拿不到。

    当我们获得使用视频的权限时,在点击处理函数内,我们还要修改一些别的东西。把传递给函数的新流赋值给 currentStream 以便后续调用 stop,触发另一次 enumerateDevices 的调用。

    enumerateDevices 返回一个 promise,所以在我们的 then 函数中可以直接返回它,然后链式创建一个新的 then 把结果传递给 gotDevices 函数处理。

    用以下代码替换现有的 getUserMedia 调用:

    button.addEventListener('click', event ={

      if (typeof currentStream !== 'undefined'{

        stopMediaTracks(currentStream);

      }

      const videoConstraints {};

      if (select.value === ''{

        videoConstraints.facingMode 'environment';

      else {

        videoConstraints.deviceId { exact: select.value };

      }

      const constraints {

        video: videoConstraints,

        audiofalse

      };

      navigator.mediaDevices

        .getUserMedia(constraints)

        .then(stream ={

          currentStream = stream;

          video.srcObject = stream;

          return navigator.mediaDevices.enumerateDevices();

        })

        .then(gotDevices)

        .catch(error ={

          console.error(error);

        });

    });

    当你添加完所有的代码,你的 app.js 应该看起来像这个文件一样。刷新页面然后你就能愉快地选择和改变摄像头了。这个页面在移动设备和电脑上都有效。

    下一步

    我们已经看到如何通过使用 facingMode 和 deviceId 约束来选择用户的摄像头。记住,在你有权限使用摄像头之前,facingMode 更可靠,但是选择 deviceId 更加精确。你可以从 GitHub 仓库 中得到所有本文中的代码,你也可以从这里尝试在线版的应用。

    如果你正在使用 Twilio Video 构建视频应用,你可以在调用 connect 或者 createLocalVideoTrack的时候使用这些 constraints。

    对于视频聊天来说,选择和切换摄像头是非常有用的功能,允许用户在你的应用界面准确地选择他们想用的摄像头,并且还能做到在视频通话时分享你的屏幕。

  • 相关阅读:
    Git 使用规范流程
    关于Python的super用法研究
    python中try except处理程序异常的三种常用方法
    break 和 continue 语句, 以及循环中的 else 子句
    杂记(python)
    Request和Response
    MVC项目开发步骤
    Web中单元测试步骤
    JSP中的细节
    WEB中地址的写法
  • 原文地址:https://www.cnblogs.com/zt123123/p/9019862.html
Copyright © 2020-2023  润新知