5-1 webrtc 获取音视频设备
通过获取到所有的音频和视频设备,返回的值是一个promise,这是javaScript中一个特有的对象,在promsie中有一个特有的结构体,
,在这个结构体中存放了非常重要的几个信息,deviceid为这个设备的唯一标志符,第二个label就是设备的名字,比如内置音频设备,内置音频输入设备等
首先解释一个背景,JavaScript中是使用单线程去处理整个逻辑的,为了防止被阻塞,大量使用了异步调用,而promise就是异步调用的一种方式,也是目前大家比较认可的一种方式,下面了解一下它的基本思想,首先创建一个promise时要传给它一个handle的处理函数,handle的处理函数处理它的主要逻辑,处理完成后,如果成功了,就会调用resolve这个函数,如果失败了就会调用reject这个函数,这样就创建了一个promise,promise可以注册两个方法,then和catch,then就是当整个逻辑处理成功后,会收到
on_resolve 这个处理事件,当收到这个事件时,就可以处理一些逻辑,catch就是当失败了,收到失败事件的时候,处理一些失败的逻辑,当然then是依赖式的,如果失败了还可以返回一个promise,可以继续then,一直做好几个处理,它的核心是在prmise里存放了几个状态,第一个是没有执行的handing的状态,第二个当开始执行handle这个逻辑时的运行状态,当处理成功后进入resolve里,会改为成功状态,如果失败了,进入到reject里,把它设置为出错状态。当你注册这个函数之后,就可以根据promise里面的状态机,它如果成功了,就可以调用then里面注册的方法,如果失败了,就可以调用catch注册的方法,这就是它的基本逻辑。
我们接着看这个函数,世纪上在这个函数里就运用了promise,注册了一个handle,所以当这个函数执行的时候就返回一个promise,在我们用的时候,拿到这个promise,我们就给他注册两个函数,一个是then方法,一个是catch方法,如果成功了,它就会调用我们注册的then调用我们成功的逻辑,如果失败了,就会调用失败的逻辑。
项目目录如下:
client.js
'use strict'
// 如果浏览区不支持,打印信息
if(!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices){
console.log('emumerateDevices is not supported!');
}else {
//如果调用成功,可以直接调用then方法,因为本身这个对象也是一个promise
//then方法中传一个参数,就是我们自己的函数,如果出错了就catch,调用出错函数
navigator.mediaDevices.enumerateDevices()
.then(gotDevices)
.catch(handleError);
}
function gotDevices(deviceInfos) {
//当我们拿到deviceInfo这个数组之后,就遍历这个数组中的每一项
//而在每一项中我们又可以注册一个匿名函数去处理每一项的内容,参数就是数组中的每一项
deviceInfos.forEach(function (deviceInfo) {
//打印设备信息
console.log(deviceInfo.kind + "label = "
+ deviceInfo.label + ":id = "
+ deviceInfo.deviceId + ": groupId ="
+ deviceInfo.groupId);
})
}
function handleError(err) {
console.log(err.name + " : " + err.message);
}
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebRTC get audio and video devices</title>
</head>
<body>
<!--通过script引入js代码,当我们打开页面的时候,js代码就会执行,交给底层的V8引擎去解析渲染-->
<script src="./js/client.js"></script>
</body>
</html>
server.js
'use strict'
var http = require('http');
var https = require('https');
var fs = require('fs');
var express = require('express');
var serveIndex = require('serve-index');
//实例化express模块
var app = express();
app.use(serveIndex('./public'));
//发布指定的静态目录作为发布路径
app.use(express.static('./public'));
//http server 监听80端口
var http_server = http.createServer(app);
http_server.listen(80, '0.0.0.0’);
var options = {
key : fs.readFileSync('./cert/2498161_andy-upp.top.key'),
cert: fs.readFileSync('./cert/2498161_andy-upp.top.pem')
}
//https server
var https_server = https.createServer(options, app);
https_server.listen(443, '0.0.0.0');
通过浏览器访问可以获取到音视频设备的信息
5-2 在页面中显示获取到的设备
目录结构
代码
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WebRTC get audio and video devices</title>
</head>
<body>
<!--选择读入类型,并且在这些类型里选择读入设备-->
<div>
<label>audio input device:</label>
<select id="audioSource"></select>
</div>
<div>
<label>audio output device</label>
<select id="audioOutput"></select>
</div>
<div>
<label>video input device:</label>
<select id="videoSource"></select>
</div>
<!--通过script引入js代码,当我们打开页面的时候,js代码就会执行,交给底层的V8引擎去解析渲染-->
<script src="./js/client.js"></script>
</body>
</html>
client.js
'use strict'
//获取select这个元素中id为audioSource的元素
var audioSource = document.querySelector("select#audioSource");
var audioOutput = document.querySelector("select#audioOutput");
var videoSource = document.querySelector("select#videoSource");
// 如果浏览区不支持,打印信息
if(!navigator.mediaDevices || !navigator.mediaDevices.enumerateDevices){
console.log('emumerateDevices is not supported!');
}else {
//如果调用成功,可以直接调用then方法,因为本身这个对象也是一个promise
//then方法中传一个参数,就是我们自己的函数,如果出错了就catch,调用出错函数
navigator.mediaDevices.enumerateDevices()
.then(gotDevices)
.catch(handleError);
}
function gotDevices(deviceInfos) {
//当我们拿到deviceInfo这个数组之后,就遍历这个数组中的每一项
//而在每一项中我们又可以注册一个匿名函数去处理每一项的内容,参数就是数组中的每一项
deviceInfos.forEach(function (deviceInfo) {
//打印设备信息
console.log(deviceInfo.kind + "label = "
+ deviceInfo.label + ":id = "
+ deviceInfo.deviceId + ": groupId ="
+ deviceInfo.groupId);
//创建option元素
var option = document.createElement('option');
option.text = deviceInfo.label;
option.value = deviceInfo.deviceId;
//将设备信息添加到不同的元素中去
if(deviceInfo.kind === 'audioinput'){
audioSource.appendChild(option);
}else if(deviceInfo.kind === 'audiooutput'){
audioOutput.appendChild(option);
}else if(deviceInfo.kind === 'videoinput'){
videoSource.appendChild(option);
}
})
}
function handleError(err) {
console.log(err.name + " : " + err.message);
}
页面显示效果