# [知識篇]MediaStreams API - getUserMedia 介紹

# 學習目標

本章你將會了解到:

  • getUserMedia 包含哪些功能
  • 如何使用getUserMedia來擷取本機影音流(Video/Audio streams)

# 簡介

var promise = navigator.mediaDevices.getUserMedia(constraints);

透過mediaDevices.getUserMedia,會提示使用者是否給予存取多媒體數據的許可,同意後會產生MediaStream物件, 裡面包含了請求的存取的多媒體數據,例如:視頻(透過本機內建的視訊鏡頭或是外接裝置等),音頻(透過本機內建的麥克風或是外接裝置等)。

並且會回傳Promise物件,但該API所回傳的promise可能不會resolve或是reject,取決於使用者行為,可能沒有允許也沒拒絕! 使用上可能就要注意到,並針對流程進行處理。

  • constraints :

該參數是基於MediaStreamConstraints物件, 用於指定存取的多媒體數據的類型及相關參數。

先來看看基本範例:

// 同時請求不帶任何參數的音頻和視頻:
{ audio: true, video: true }

注意: 該參數包含video與audio兩種類型,可以單純指定其一或如範例同時指定兩種類型,但不能完全都不指定! 當沒有指定任一時或是瀏覽器不支援參數的設定等,會拋出promise.reject返回失敗的狀態。

進階一點的話,如指定視頻畫素:

{
  video: { width: 1280, height: 720 }
}

更多細節可以看看:MDN文件

# 實作範例

# 在html上加上video tag

<!-- index.html -->
<video autoplay></video>

# 透過getUserMedia來取得多媒體數據流

// 這邊我們單純只想取得video
const mediaStreamConstraints = {
  video: true
};

function handleMediaStreamError(error) {
  console.log('navigator.getUserMedia error: ', error);
}

function gotLocalMediaStream(mediaStream) {
  // console.log(mediaStream)
  const localStream = mediaStream;

  // 取的video html element( HTMLMediaElement ).
  const localVideo = document.querySelector('video');
  // Older browsers may not have srcObject.
  if ("srcObject" in localVideo) {
    localVideo.srcObject = localStream;
  } else {
    // Avoid using this in new browsers, as it is going away.
    localVideo.src = window.URL.createObjectURL(localStream);
  }
}

navigator.mediaDevices
  .getUserMedia(mediaStreamConstraints)
  .then(gotLocalMediaStream)
  .catch(handleMediaStreamError)

# Try it

在瀏覽器上打開你的index.html,結果應該會如下圖所示:

webcam

# 實作講解

本次實作主要就是透過navigator.mediaDevices.getUserMedia(),來取得使用者的同意, 如果同意的話,將會回傳MediaStream object,裡面會包含從webcam拿到影音流資料,並透過Javascript來操作。

navigator.mediaDevices
  .getUserMedia(/** setting media constraints */)
  .then(/** handle Success */)
  .catch(/** handle Error */)

取的MediaStream object後,可以利用HTMLMediaElement.srcObject屬性,將其顯示在網頁上。

function gotLocalMediaStream(mediaStream) {
  const localStream = mediaStream;
  const localVideo = document.querySelector('video');

  if ("srcObject" in localVideo) {
    localVideo.srcObject = localStream;
  } else {
    localVideo.src = window.URL.createObjectURL(localStream);
  }
}

注意: 因為srcObject屬性的支援度還沒有很全面,如果再沒有支援的情況下,必須用URL.createObjectURL()轉換後賦值給HTMLMediaElement.src

# 補充

實作後試想一下幾個蠻好奇的地方:

  • consolemediaStream object,裡面究竟存了哪些資料或提供了哪些api能夠使用。
  • 如果改變constraints的設定後,會產生怎樣的變化。
const mediaStreamConstraints = {
  video: {
    width: {min: 1280},
    height: {min: 720}
  }
};

# 總結

本章節了解到:

  • 如何使用getUserMedia來存取多媒體數據流
  • 設定constraints的功用
  • 如何透過HTMLMediaElement的屬性將video stream顯示到網頁上