WebRTC 筆記 --- 2. enumerateDevices()

WebRTC 功能使用的筆記紀錄 2.


個人的撰寫程式環境:



  • OS: Ubuntu 18.04 LTS
  • Angular :  6.1.0
  • Angular-cli : 6.1.2
  • Typescript : 2.9.2
以下的程式碼必須建立在會使用Angular、Promise與Typescript的基礎知識喔!
建議在筆電(webcam在筆電是基本配備)或是在桌機上面安裝一台簡單的Webcam才能有效運行WebRTC的功能喔!

enumerateDevices():

這個api是用來列出有哪些多媒體inputoutput可以用~例如:webcam、microphone這些可以使用。其裝置的資訊(MediaDeviceInfo)會以物件陣列(Object in Array)透過Promise回傳。 --- 注1

e.g. :
navigator.mediaDevices.enumerateDevices() .then( devinfo => console.log(devinfo)) .catch( err => console.warn(err));



在Browser的console下也可以直接用命令的方式輸入然後顯示資訊。



在這邊可以看到每個物件都跟我們前一章節提過一樣有label....等 以key : value的方式顯示資訊存在回傳的Array中。這邊我主要關心的是 audioinput / videoinput (--- 注2) ,其他的可以先不用管他。

audioinput:

代表一個audio輸入裝置。例如:麥克風。

videoinput:

代表一個video輸入裝置。例如:網路攝影機。

audioouput:

代表audio輸出裝置。例如:一對頭戴式耳機。


通常我們把audioinputvideoinputdeviceId抓出來後就可以透過上一章節的getUserMedia()的參數Constraints指定那一個webcam與microphone的影像與音軌顯示到 video 這個DOM tag上面。

下面是一個例子的程式碼:
HTML file:
<h4>Test WebRTC</h4> <section> <label for="audioSelect">選擇Audio來源:</label> <select id="audioSelect" (change)="ChangeAudioSource($event.target.value)"> <option *ngFor="let item of audioOption" [value]="item.value"> {{item.text}} </option> </select> </section> <section> <label for="videoSelect">選擇Video來源:</label> <select id="videoSelect" (change)="ChangeVideoSource($event.target.value)"> <option *ngFor="let item of videoOption" [value]="item.value" > {{item.text}} </option> </select> </section> <video id="video" autoplay></video> <button class="stop-button" id="stopbtn" type="button" (click)="stopBtn()"> Stop </button>

Typescript file:
import { Component, OnInit, ElementRef} from '@angular/core'; /* 省略 .... */ export class YourComponent implements OnInit { private el: ElementRef; private videoElement: HTMLVideoElement; public constraints: any; public videoOption = []; public audioOption = []; public videoValue: any; public audioValue: any; constructor( private element: ElementRef ) { this.el = this.element; } ngOnInit() { this.videoElement = <HTMLVideoElement>this.el.nativeElement .querySelector('#video'); navigator.mediaDevices.enumerateDevices() .then( dev => this.gotDevices(dev)) .then( () => this.getStream()) .catch(this.handleError); } gotDevices(deviceInfos) { for (let i = 0; i !== deviceInfos.length; ++i) { const deviceInfo = deviceInfos[i]; if (deviceInfo.kind === 'audioinput') { let audioObj = {value: '', text: ''}; audioObj.value = deviceInfo.deviceId; audioObj.text = deviceInfo.label || 'microphone' + (this.audioOption.length + 1); this.audioOption.push(audioObj); } else if (deviceInfo.kind === 'videoinput') { let videoObj = { value: '', text: ''}; videoObj.value = deviceInfo.deviceId; videoObj.text = deviceInfo.label || 'camera' + (this.videoOption.length + 1); this.videoOption.push(videoObj); } else { console.log(`Found another kind of device: ${deviceInfo}`); } } this.audioValue = this.audioOption[0].value; this.videoValue = this.videoOption[0].value; } getStream() {
this.stopBtn(); // stop stream first this.constraints = { audio: { deviceId: { exact: this.audioValue } }, video: { deviceId: { exact: this.videoValue }, width: 640, height: 480 } }; navigator.mediaDevices.getUserMedia(this.constraints) .then( stream => this.videoElement.srcObject = stream) .catch(this.handleError); } handleError(error) { console.log('Error: ', error); } /** * 按鈕Stop的code. */ stopBtn() { if (this.videoElement.srcObject) { (<MediaStream>this.videoElement.srcObject).getTracks() .forEach( stream => stream.stop()); } } ChangeAudioSource(val) { this.audioValue = val; this.getStream(); } ChangeVideoSource(val) { this.videoValue = val; this.getStream(); } }

這段程式碼主要有幾個重點!

gotDevices()

這個function主要把enumerateDevices() API回來的裝置資訊Array內中把 audioinputvideoinput的物件取各自的deviceIdlabel資訊另存成一個物件,然後在把這個物件依照是來自audioinput的或是videoinput的加到audioOption或是videoOption陣列。

這樣HTML那邊的Select tag就有audio跟video來源的選項可以選。

getStream()

這個function在gotDevices()做完後把選好的audio/video來源寫成getUserMedia()Constraint,並且畫面指定大小為 640*480,接著先把原本的Stream關閉再把stream顯示在 html video tag.

ChangeAudioSource()

這個為我們在Html audio的Select optionchange event function。當使用者改變 Audio的選項時就會來執行這個function,這邊就是把新的Audio source 寫到 audioValue然後再去執行getStream()來顯示新的audio stream

ChangeAudioiSource()

這個為我們在Html video的Select optionchange event function。當使用者改變 Video的選項時就會來執行這個function,這邊就是把新的Video source 寫到 videoValue然後再去執行getStream()來顯示新的video stream

這樣子就可以在多個WebCam下做切換並且在video tag中看到影像與聲音。

------ 待續。

REF:

留言