WebRTC音視頻數據採集 六、第九節 MediaStreamAPI及獲取視頻約束

今天我們來重點介紹一些 MediaStream的方法和事件

在這些方法中主要是和Track相關的,此前我們已經介紹過了。

在webrtc中包括了流的概念和軌的概念。在一個媒體流中可以包含很多的媒體軌,音頻媒體軌,視頻媒體軌。

MediaStream.addTrack()

MediaStream.addTrack()表示向流媒體中加入不同的軌

MediaStream.removeTrack()

將媒體流中不想要的媒體軌移出去

MediaStream.getVideoTracks()

將媒體流中所有的視頻的軌,全部拿到,這樣就可以根據自身的需要,去獲取所需要的視頻的媒體軌

MediaStream.getAudioTracks()

將媒體流中所有的音頻的軌,全部拿到,這樣就可以根據自身的需要,去獲取所需要的音頻的媒體軌

MediaStream.stop()

將媒體流直接關閉掉,這樣它會調每一個媒體軌中的STOP;這樣的話,這個流就結束掉了。

 

除了以上的方法還有一些事件,下面也介紹一下

MediaStream.onaddtrack

就是當我們添加一個媒體軌到媒體流中的時候 ,會觸發這個事件,

MediaStream.onremovetrack

刪除這個媒體軌

MediaStream.onended

當這個流結束的時候,我們會收到一個流結束的事件,非常簡單。

下面我們來實戰一下獲取視頻的約束。

index.html

<html>
  <head>
    <title>捕獲音視頻數據 WebRTC capture video and audio</title>
		<style>
			.none {
				-webkit-filter: none;	
			}

			.blur {
        /* 特效模糊 */
				-webkit-filter: blur(3px);	
			}

			.grayscale {
        /* 特效灰度 */
				-webkit-filter: grayscale(1); 	
			}

			.invert {
        /* 翻轉 */
				-webkit-filter: invert(1);	
			}

			.sepia {
        /* 特效褐色 */
				-webkit-filter: sepia(1);
			}

		</style>
  </head>
  <body>
		<div>
			<label>audio Source:</label>
			<select id="audioSource"></select>
		</div>

		<div>
			<label>audio Output:</label>
			<select id="audioOutput"></select>
		</div>

		<div>
			<label>video Source:</label>
			<select id="videoSource"></select>
    </div>
    <!-- 特效選擇器 -->
    <div>
			<label>Filter:</label>
			<select id="filter">
				<option value="none">None</option>
				<option value="blur">blur</option>
				<option value="grayscale">Grayscale</option>
				<option value="invert">Invert</option>
				<option value="sepia">sepia</option>
			</select>
		</div>
    <!-- 
      我們創建一個video標籤,這個標籤就可以顯示我們捕獲的音視頻數據 
      autoplay 表示當我們拿到視頻源的時候直接播放
      playsinlin  表示在瀏覽器頁面中播放而不是調用第三方工具
     -->
     <!-- 通過audio標籤只獲取音頻 -->
     <!-- 
       controls  表示將暫停和播放按鈕顯示出來,否則它雖然播放聲音,但是不會顯示播放器窗口
       autoplay  默認自動播放
      -->
    <!-- <audio autoplay controls id='audioplayer'></audio> -->
		<table>
			<tr>
				<td><video autoplay playsinline id="player"></video></td>
				<td><video playsinline id="recplayer"></video></td>
				<td><div id='constraints' class='output'></div></td>
			</tr>
			<tr>
				<td><button id="record">Start Record</button></td>
				<td><button id="recplay" disabled>Play</button></td>
				<td><button id="download" disabled>Download</button></td>
			</tr>
		</table>

    <!-- 獲取視頻幀圖片按鈕 -->
		<div>
			<button id="snapshot">Take snapshot</button>
    </div>
    <!-- 獲取視頻幀圖片顯示在canvas裏面 -->
		<div>
			<canvas id="picture"></canvas>
		</div>
    <!-- 引入 adapter.js庫 來做 不同瀏覽器的兼容 -->
    <script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
    <script src="./js/client.js"></script>
  </body>
</html>

client.js

'use strict'

var audioSource = document.querySelector('select#audioSource');
var audioOutput = document.querySelector('select#audioOutput');
var videoSource = document.querySelector('select#videoSource');
// 獲取video標籤
// var videoplay = document.querySelector('video#player');
// 獲取音頻標籤
var audioplay = document.querySelector('audio#audioplayer');

//div
var divConstraints = document.querySelector('div#constraints');

//filter 特效選擇
var filtersSelect = document.querySelector('select#filter');

//picture 獲取視頻幀圖片相關的元素
var snapshot = document.querySelector('button#snapshot');
var picture = document.querySelector('canvas#picture');
picture.width = 640;
picture.height = 480;

// deviceInfos是設備信息的數組
function gotDevices(deviceInfos){
  // 遍歷設備信息數組, 函數裏面也有個參數是每一項的deviceinfo, 這樣我們就拿到每個設備的信息了
	deviceInfos.forEach(function(deviceinfo){
    // 創建每一項
		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);
		}
	})
}

// 獲取到流做什麼, 在gotMediaStream方面裏面我們要傳人一個參數,也就是流,
// 這個流裏面實際上包含了音頻軌和視頻軌,因爲我們通過constraints設置了要採集視頻和音頻
// 我們直接吧這個流賦值給HTML中賦值的video標籤
// 當時拿到這個流了,說明用戶已經同意去訪問音視頻設備了
function gotMediaStream(stream){  
  	// audioplay.srcObject = stream;
  videoplay.srcObject = stream; // 指定數據源來自stream,這樣視頻標籤採集到這個數據之後就可以將視頻和音頻播放出來
  // 通過stream來獲取到視頻的track 這樣我們就將所有的視頻流中的track都獲取到了,這裏我們只取列表中的第一個
  var videoTrack = stream.getVideoTracks()[0];
  // 拿到track之後我們就能調用Track的方法
  var videoConstraints = videoTrack.getSettings(); // 這樣就可以拿到所有video的約束
  // 將這個對象轉化成json格式
  // 第一個是videoConstraints, 第二個爲空, 第三個表示縮進2格
	divConstraints.textContent = JSON.stringify(videoConstraints, null, 2);

  // 當我們採集到音視頻的數據之後,我們返回一個Promise
  return navigator.mediaDevices.enumerateDevices();
}

function handleError(err){
	console.log('getUserMedia error:', err);
}
function start() {
// 判斷瀏覽器是否支持
if(!navigator.mediaDevices ||
  !navigator.mediaDevices.getUserMedia){
  console.log('getUserMedia is not supported!');
}else{
  // 獲取到deviceId
  var deviceId = videoSource.value; 
  // 這裏是約束參數,正常情況下我們只需要是否使用視頻是否使用音頻
  // 對於視頻就可以按我們剛纔所說的做一些限制
  var constraints = { // 表示同時採集視頻金和音頻
    video : {
      width: 640,	// 寬帶
      height: 480,  // 高度
      frameRate:15, // 幀率
      facingMode: 'enviroment', //  設置爲後置攝像頭
      deviceId : deviceId ? deviceId : undefined // 如果deviceId不爲空直接設置值,如果爲空就是undefined
    }, 
    audio : true // 將聲音獲取設爲true
  }
  //  從指定的設備中去採集數據
  navigator.mediaDevices.getUserMedia(constraints)
    .then(gotMediaStream)  // 使用Promise串聯的方式,獲取流成功了
    .then(gotDevices)
    .catch(handleError);
}
}

start();

// 當我選擇攝像頭的時候,他可以觸發一個事件,
// 當我調用start之後我要改變constraints
videoSource.onchange = start;

// 選擇特效的方法
filtersSelect.onchange = function(){
	videoplay.className = filtersSelect.value;
}

// 點擊按鈕獲取視頻幀圖片
snapshot.onclick = function() {
  picture.className = filtersSelect.value;
  // 調用canvas API獲取上下文,圖片是二維的,所以2d,這樣我們就拿到它的上下文了
  // 調用drawImage繪製圖片,第一個參數就是視頻,我們這裏是videoplay,
  // 第二和第三個參數是起始點 0,0
  // 第四個和第五個參數表示圖片的高度和寬度
	picture.getContext('2d').drawImage(videoplay, 0, 0, picture.width, picture.height);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章