今天我們開始學習WebRTC内容了,首先我們看一下WebRTC如何進行裝置管理。
在 WebRTC 的規範中,給我們提供一個重要的API,叫
enumerateDevices
通過這個API 我們就可以擷取到電腦中的音頻和視訊裝置,首先我們來看一下它的基本格式
/**
* 基本格式 通過navigator.mediaDevices下的enumerateDevices方法擷取所有的音頻和視訊裝置
* 最後它傳回的值是一個Promise,這是JavaScript中特有的一個對象
*/
var ePromise = navigator.mediaDevices.enumerateDevices();
在Promise裡面有個重要的結構體
MediaDevicesInfo
在這個結構體裡面存放幾個非常重要的資訊
deviceID就是這個裝置的唯一辨別符
label就是裝置的名字,就是我們人可讀的,比如說内置音頻裝置,内置音頻輸入裝置、内置音頻輸出裝置或者是耳機等等一些人 可讀的裝置名字。
kind表示裝置的種類,比如音頻輸入裝置、視訊輸出裝置、還有視訊輸入裝置
groupID表示組ID,就是兩個裝置GroupID相同的組ID,說明是同一個實體裝置,以音頻 為例,同一個裝置裡面包含兩種類型,一種是輸入一種是輸出
以上就是enumerateDevices的基本資訊,通過調用這個API就可以拿到音頻和視訊裝置了,就非常簡單。
——————————————————————————————————————————————————————
下面我們簡單介紹一些JavaScript中的Promise
上圖很好的解釋了JavaScript中的Promise是什麼東西,我們都知道JavaScript是使用單線程去處理整個邏輯的,是以為了防止它被阻塞,大量使用了這個異步調用。這個Promise就是異步調用其中的一種方式。也是現在比較流行,也是大家比較認可的一種方式,下面介紹一下它的基本思想。
首先你在建立Promise的時候要傳給它一個handle的處理函數,這個handle處理函數是用來處理你的主要邏輯,在它處理之後,如果成功了會 調用 這個處理函數中的resolve函數,如果失敗了它就會調用reject這個函數,這樣就建立好了一個Promise.
Promise可以通過兩個方法,一個是then一個是catch, then就是當我整個邏輯處理成功之後會收到這個on_resolve事件,收到這個事件之後就處理一些邏輯,這就是它這個then。catch就是失敗了,當失敗的時候處理一些失敗的邏輯,then這個 如果 成功之後,它是一個鍊式的,可以繼續寫一個then。
它有幾個狀态,第一個是未執行的一個狀态,第二個當你執行handle的邏輯的時候賦予這個運作狀态,當這個處理成功之後進入這個resolve改為成功狀态,如果失敗了進入 reject裡面設定為出錯狀态。當你注冊這個函數之後你 就可以根據Promise裡面這個狀态機如果成功了就調用這個then方法 ,如果失敗了就 調用這個catch方法 ,這就是它的基本邏輯 。
——————————————————————————————————————————————————————
我們回到上面enumerateDevices的函數,實際上在這個 函數裡面它就new 了一個Promise,并且給它注冊了一個handle,是以當它這個 函數執行的時候它 就傳回一個Promise,在我們用的時候拿到這個Promise之後,我們就給他注冊兩個函數,一個是then的方法一個是catch的方法,如果成功了他就會調用then我們成功的一些邏輯,如果失敗了就會調用失敗那些處理邏輯,這就是javaScript中的Promise的基本思想。
那麼接下來我們就通過一個實際的例子,如何通過WebRTC的API來擷取到我們的音視訊裝置,我們先建立一個檔案夾devide,在檔案夾裡面建一個index.html
<html>
<head>
<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 src="./js/client.js"></script>
</body>
</html>
我在裡面引入我們編寫的腳本client.js,這樣當我們打開頁面的時候,這個JavaScript代碼就會執行 ,就是chrome浏覽器會給他交到底層的V8引擎去解析然後去渲染,這樣我們的Html就算寫完了。
下面我們來實作client.js
// 1、使用嚴格文法
'use strict'
var audioSource = document.querySelector("select#audioSource");
var audioOutput = document.querySelector("select#audioOutput");
var videoSource = document.querySelector("select#videoSource");
// 2、首先判斷浏覽器是否支援此方法,在浏覽器支援的情況下才調用
if(!navigator.mediaDevices ||
!navigator.mediaDevices.enumerateDevices){
console.log('enumerateDevices is not supported!');
}else {
navigator.mediaDevices.enumerateDevices()
.then(gotDevices)
.catch(handleError);
}
// 3、實作gotDevices,在gotDevices就可以得到我們剛說的 deviceInfos 了
function gotDevices(deviceInfos){
// 5、當我們拿到deviceInfos這個數組之後我們就開始周遊這個數組
// 在這個每一項裡面實際上我們可以注冊一個匿名函數去處理每一項的内容,它的參數就是每一項的值
deviceInfos.forEach( function(deviceInfo){
console.log(deviceInfo.kind + ": label = "
+ deviceInfo.label + ": id = "
+ deviceInfo.deviceId + ": groupId = "
+ deviceInfo.groupId);
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);
}
});
}
// 4、在handleError裡面會傳回一個錯誤
function handleError(err){
console.log(err.name + " : " + err.message);
}
儲存之後,我們運作node server.js
我們可以看到有輸入裝置,label沒有顯示,id是default,我們看到前兩個groupId是一樣的,第三個是視訊的輸入裝置,proupId不一樣了,第四個 是音頻的輸入裝置,這個輸入和輸出裝置實體裝置是一樣的,是以他們有同一個groupId;