2.1、列举媒体设备

文章导读:在上一章的“1.5、Web服务器”中已经明确了Web服务程序在webrtc中的意义,本节继续上章的内容,进一步的完善Web服务程序的其他功能:加入内网穿透功能,实现通过公网地址调试程序。并且讲解通过enumerateDevices方法列举本机电脑可用的媒体设备。阅读建议:理解+实操。

   webrtc对web环境的安全是有要求的,通过http加载的页面不能正常的调用某些核心的功能,因此我们需要搭建出“安全”的web环境——https。作为学习之用,我们无需租用一台云主机,而是换用成本更小的内网穿透工具来部署调试环境。内网穿透的原理如下图2.1.1所示。

 

 

 图 2.1.1 (内网穿透原理图)

如上图所示,虚线部分为“个人电脑”,即我们调试程序的电脑,我们现在搭建好的web服务程序是无法被外部访问的,为了能打通这个限制,我们需要一个辅助工具——穿透客户端程序,当然穿透客户端程序背后是有一个公网服务器来支持,通过穿透客户端程序和穿透服务器的配合,个人电脑上的web服务就可以被外界访问到。本书推荐使用echosite来完成这一穿透过程,其官网为:https://www.echosite.cn/  ,详细的操作方法请参见官网的教程,请读者自行查阅完成。我的内网穿透环境已经搭建好了,接下来演示下如何启动。

  首先,启动我们上一章写好的web服务程序,在项目根目录下输入命令“node index.js ”启动。如下图2.1.2所示。

 

图 2.1.2 (实验内容的web服务)

接着启动内网穿透客户端程序,命令“echosite -config=config.yml start web_a ”。启动结果如下图2.1.3所示。

 

图 2.1.3 (echosite启动截图)

 

由图2.1.3所示,此刻本地的web服务8000端口已经和https://webrtclearn.easy.echosite.cn域名关联起来,这就意味着,只要上面这两程序都启动,我们就能通过https://webrtclearn.easy.echosite.cn来访问到本机的http://localhost:8000web服务。如果这一步实在搞不定的读者,建议与我一对一交流吧。

  至此,服务器程序已经搭建完毕,接下来开始考虑如何进行实现音视频数据的采集(注意:往后所有的网页均在chrome浏览器中运行)。在采集之前,首先得看看本机电脑有哪些支持的媒体设备吧。所以,我们先要来学习一个方法——enumerateDevices,该方法可以列举出本机可用的媒体输入和输出设备,调用的方式为”navigator.mediaDevices.enumerateDevices()“,返回一个Promise 对象,Promise异步结果是一个媒体设备列表数组,每个数组元素的结构为:

{
    deviceID:"",//string,设备唯一标识
    label:"",//string,设备名称
    kind:"",// string,设备类型
    groupID:"",//string ,设备分组id
} 

 其中,deviceID是设备的唯一标识;label是媒体设备名称,如“通讯 - 麦克风 (Realtek High Definition Audio)”。kind是设备类型, 分为:音频输入设备(audioinput)、音频输出设备(audiooutput)、视频输入设备(videoinput)。groupID 表示设备分组ID,不同设备,deviceID肯定不同,但groupID可能相同,如果某些设备的groupID相同,说明这些设备是同一个物理设备,例如一个带麦的音乐播放设备既是音频输入设备又是音频输出设备,虽然同是一个物理设备,但enumerateDevices方法在列举设备列表的时候,会把音频输入、音频的输出看成是两个设备列举出来,但groupID相同。这段描述可能比较抽象,接下来实际的写一段代码来演示,当然本章的案例有更贴近实战的运用,这里先来简单的实现:读取媒体设备列表,并且打印出来。

  在public目录中新建一个网页文件,命名为”demo2.1.html“,如下图2.1.4。

图 2.1.4 (demo 2.1.html)

 

打开网页文件并编辑,代码如下。 

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
        <title>demo 2.1 设备管理</title>
        <script src="./js/demo2.1.js"></script>
    </head>
    <body>
        <!--UI标签代码-->
    </body>
</html>

 在上述的html文件中,我们引入了一个外部JS 文件——“./js/demo 2.1.js”,于是,我们要创建该JS文件,如下图2.1.5所示。

 

 

图 2.1.5 (demo2.1.js)

 打开“demo2.1.js”文件,代码如下。

'use strict'
// 检测浏览器的支持情况
if (!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices) {
    throw new Error("enumerateDevices is not supported");
}
// 列出电脑支持的设备 navigator.mediaDevices.enumerateDevices().then(devices
=> { console.log("devices", devices); }).catch(error => { throw error; //抛出异常 })

  从上述的代码可以看出enumerateDevices方法的层级结构——“enumerateDevices方法位于navigator对象下的mediaDevices对象中”,在JS中,调用层级较深的对象时,为了考虑代码的健壮性,需要做对象的可用判断,如果目标对象不可用就抛出异常。

  上述代码运行结果如下图2.1.6所示。  

 

图 2.1.6 (设备列表读取)

如图2.1.6中,程序把本机中可用的媒体设备列举并打印出来了, 其中label属性没有显示出来,这是因为浏览器出于安全考虑,只对信任的域名开放核心功能的调用。要解决这个问题,先要看看浏览器是否信任该域名。打开浏览器的”设置“的页面并搜索”摄像头“的选项,如下图2.1.7所示。

 

 

图 2.1.7 (浏览器摄像头权限设置)

 

从图2.1.7中可以看出,案例代码的网址“https://webrtclearn.easy.echosite.cn”并没有在允许访问摄像头的范围之内,因此权限不足,label属性不可见。当然,此处也不能手动添加信任网址,怎么办?

  解决的办法就是让程序来“调用”摄像头,引导浏览器弹出询问框,我们再做允许的操作。如下图2.1.8所示。

图 2.1.8 (调用媒体设备询问)

如何调出上图的询问框呢? 很简单,只要调用媒体设备即可,enumerateDevices方法执行时并未唤起询问框,说明该方法并未调用媒体设备。调用媒体设备的代码如下。

if(!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia){
    throw new Error("getUserMedia is not supported");
}
// 调用音频和视频设备 navigator.mediaDevices.getUserMedia({audio:
true,video:true});

上面这段代码是我们“采集”音视频数据时用到的,但先在这里临时用着(仅为了“调用”硬件设备),所以我不打算写到代码文件中(demo2.1.js),而是在“console”控制台直接执行,需要注意的是“getUserMedia”方法需要传一个配置对象进去,于是我传了一个“ {audio:true,video:true}”对象,表示我要调用的硬件设备类型有两种——音频、视频。执行这段代码后即可弹出 如图2.1.8的提示框,我们只需点击“允许”即可。此刻再来看“摄像头的配置选项”,如下图2.1.9所示。我们的域名已经被加入“允许”的域名列表中。同理,音频设备(麦克风)也是如此,这里不在赘述。

 

图 2.1.6(已授权摄像头配置)

当我们再刷新demo2.1.html 页面,控制台打印的效果如下图2.1.7所示。

 

 

图 2.1.7  (设备列表)

如上图 2.1.7 展开的4个设备信息对象中,label属性已经显示出来,并且groupID一样的,说明是同一个物理设备。

  大家也无需担心每次调用都弹出提示框,根据chrome的规范,某一个域名只要加入“信任”的名单, 往后的调用就无需再弹出确认框。

  至此,webrtc设备管理的内容已经讲完。总结,本文的完成了:一、实战环境下的服务程序的搭建,较复杂的地方的是“内网穿透”环境的搭建。二、并且通过编码实现了媒体设备的读取,所用到webrtc API——“enumerateDevices”,更多关于该方法的描述,可以点击这里查阅。总体来讲内容比较简单(得益于webrtc解决了复杂的底层问题),建议读者动手实践。下一节实战内容:采集并展示流媒体。 

 

posted on 2020-03-07 19:44  Rajan  阅读(1295)  评论(0编辑  收藏  举报
扫码和作者预约吧