使用 getUserMedia API獲取麥克風和相機等流媒體


概覽

mediaDevices 是 Navigator 對象的只讀屬性,一個單列對象,可以連接訪問相機和麥克風,屏幕共享等媒體輸入設備

方法

enumerateDevices

請求一個可用的媒體輸入和輸出設備列表,如麥克風、相機、耳機等。返回的 Promise完成狀態中是一個帶有 MediaDeviceInfo 的數組

let mediaDevices = navigator.mediaDevices
if(!mediaDevices || !mediaDevices.enumerateDevices) return console.erorr('瀏覽器不支持enumerateDevices API')
navigator.mediaDevices.enumerateDevices()
.then((devices)=>{
    for (let device of devices){
        console.log(device.kind + ': ' +device.lable + ' id = '+ device.deviceId );
    }
})
.catch(err=>{
    console.error(err)
})

/*
audioinput: undefined id = default
audioinput: undefined id = communications
audioinput: undefined id = ac67d348685a08c75e5017f9a449b3d85f08dcb774c88ab95de82bbf2c0fc820
videoinput: undefined id = e41039bcfbc84d926a0b73cdc1d8b1daf3d67d36c62588202191d918fb076426
audiooutput: undefined id = default
audiooutput: undefined id = communications
audiooutput: undefined id = 015d73652e57bffb21679b937675d32c4d4a43862aba3774aaf0b5f1e983151f
*/

兼容性

getSupportedConstraints

返回一個 MediaTrackSupportedConstraints 對象,其屬性都是客戶端所支持約束的屬性,值為 Boolean 類型

let supportedConstraints = navigator.mediaDevices.getSupportedConstraints()
for (let constraint of Object.keys(supportedConstraints)){
    console.log(constraint)
}
/*
aspectRatio
autoGainControl
brightness
channelCount
colorTemperature
contrast
deviceId
echoCancellation
exposureCompensation
exposureMode
exposureTime
facingMode
focusDistance
focusMode
frameRate
groupId
height
iso
latency
noiseSuppression
pointsOfInterest
resizeMode
sampleRate
sampleSize
saturation
sharpness
torch
volume
whiteBalanceMode
width
zoom
*/

兼容性

getDisplayMedia

提示用戶選擇和授予權限來捕獲顯示或部分的內容,(如分屏共享時分享哪一屏的內容)然后使用 medieaStream Recording API 記錄生成的 stream,或作為 webRTC 會話的一部分進行傳輸。

可以傳遞一個MediaStreamConstraints 對象指定返回要求的 mediaStream

async function startCapture(displayMediaOptions) {
  let captureStream = null;

  try {
    captureStream = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
  } catch(err) {
    console.error("Error: " + err);
  }
  return captureStream;
}

兼容性

getUserMedia

提示用戶給予使用媒體輸入的許可(如麥克風,攝像機),當媒體輸入時產生一個 mediaStream包含所請求的媒體類型的軌道。該流可以包括視頻軌道(攝像機,視頻記錄設備,共屏等硬件或虛擬視頻流源)、音頻軌道(來自麥克風、A/D轉換器等硬件或虛擬音頻源),也可能是其它軌道類型

該方法返回一個Promise對象,成功時 resolve 回調函數帶有mediaStream對象。如果用戶拒絕授予使用權限,或是媒體源不可用,則返回 reject回調

Promise 可能既不會 resolve 也不會reject,因為用戶不必做出選擇,可能只是忽略請求

// 想要獲取一個最接近 1280x720 的相機分辨率
let constraints = { audio: true, video: { width: 1280, height: 720 } };

navigator.mediaDevices.getUserMedia(constraints)
.then(function(mediaStream) {
  let video = document.querySelector('video');
  video.srcObject = mediaStream;
  video.onloadedmetadata = function(e) {
    video.play();
  };
})
.catch(function(err) { console.log(err.name + ": " + err.message); });

參數 constraints

一個mediaStreamConstraints對象指定請求的媒體類型和相對應參數,該對象包含 videoaudio 兩個屬性,必須一個或兩個同時被指定,如果無法找到指定的媒體類型或無法滿足對於的參數要求,Promise將返回 rejected

參數配置

配置 1
 {audio:true,video:true}

屬性設置為 Truthy 則生成的stream 必須具有該類型的軌道,否則調用 getUserMedia會拋出錯誤

配置 2
{
  audio: true,
  video: { width: 1280, height: 720 }
}

表示video的分辨率應為 1280x720 瀏覽器將試着滿足這個請求參數,如果無法滿足要求或選擇覆蓋,則可能返回其它的分辨率

配置 3
{
  audio: true,
  video: {
    width: { min: 1280 },
    height: { min: 720 }
  }
}

此配置要求了最低分辨率,如果達不到要求,promise 將返回 reject;還可配置 max、exact(min == max),而且用戶將不會得到要求授權的提示

配置 4
{
  audio: true,
  video: {
    width: { min: 1024, ideal: 1280, max: 1920 },
    height: { min: 776, ideal: 720, max: 1080 }
  }
}

如果使用ideal,瀏覽器將嘗試找到(如果相機有多個的話)最接近指定值的理想值的設備或相機
意味着上方的第一個分辨率例子可簡寫為:

{
  audio: true,
  video: {
    width: { ideal: 1280 },
    height: { ideal: 720 }
  }
}
配置 5

並不是所有的 constraint 都說數字,如在移動設備上優先使用前置相機

{ audio: true, video: { facingMode: "user" } }

強制使用后置相機

{ audio: true,
 video: {
  facingMode: { exact: "environment" }
   }
}

APP權限配置

"permissions": {
  "audio-capture": {
    "description": "Required to capture audio using getUserMedia()"
  },
  "video-capture": {
    "description": "Required to capture video using getUserMedia()"
  }
}

作為可能涉及重大隱私問題的API,getUserMedia()規范規定了瀏覽器有義務滿足的各種隱私和安全要求。

getUserMedia()是一個強大的功能,只能在安全的環境中使用; 在不安全的情境中,navigator.mediaDevices 是undefined,阻止訪問getUserMedia()
簡而言之,安全上下文是使用HTTPSfile:///URL 方案加載的頁面,或者是從中加載的頁面localhost

在舊的瀏覽器中使用新的API

推薦使用處理了約束的 adapter.jspolyfill 來替代。



// 老的瀏覽器可能根本沒有實現 mediaDevices,所以我們可以先設置一個空的對象
let mediaDevices = navigator.mediaDevices
if (mediaDevices === undefined) {
  mediaDevices = {};
}
// 一些瀏覽器部分支持 mediaDevices。我們不能直接給對象設置 getUserMedia
// 因為這樣可能會覆蓋已有的屬性。這里我們只會在沒有getUserMedia屬性的時候添加它。
if (mediaDevices.getUserMedia === undefined) {
  mediaDevices.getUserMedia = function(constraints) {

    // 首先,如果有getUserMedia的話,就獲得它
    var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

    // 一些瀏覽器根本沒實現它 - 那么就返回一個error到promise的reject來保持一個統一的接口
    if (!getUserMedia) {
      return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
    }

    // 否則,為老的navigator.getUserMedia方法包裹一個Promise
    return new Promise(function(resolve, reject) {
      getUserMedia.call(navigator, constraints, resolve, reject);
    });
  }
}
mediaDevices.getUserMedia({ audio: true, video: true })
.then(function(stream) {
  var video = document.querySelector('video');
  // 舊的瀏覽器可能沒有srcObject
  if ("srcObject" in video) {
    video.srcObject = stream;
  } else {
    // 防止在新的瀏覽器里使用它,應為它已經不再支持了
    video.src = window.URL.createObjectURL(stream);
  }
  video.onloadedmetadata = function(e) {
    video.play();
  };
})
.catch(function(err) {
  console.log(err.name + ": " + err.message);
});

Owen 的個人博客
博客園

兼容性


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM