針對網路開發時,WebRTC 標準提供的 API 可用於存取
連接電腦或智慧型手機的攝影機和麥克風。這些裝置
通常稱為「媒體裝置」,可透過 JavaScript 存取
透過導入 MediaDevices
的 navigator.mediaDevices
物件
存取 API透過這個物件,我們可以列舉所有已連結的裝置、監聽
裝置變更 (裝置連接或中斷連線時),然後開啟裝置
擷取媒體串流 (請見下方說明)。
最常見的方法是透過 getUserMedia()
函式。
傳回的保證會解析為相符媒體的 MediaStream
裝置。這個函式採用單一 MediaStreamConstraints
物件,這個物件會
須指定我們要求的權限舉例來說,如果只要開啟
預設麥克風和攝影機,我們會執行以下操作。
使用 Promise
const constraints = {
'video': true,
'audio': true
}
navigator.mediaDevices.getUserMedia(constraints)
.then(stream => {
console.log('Got MediaStream:', stream);
})
.catch(error => {
console.error('Error accessing media devices.', error);
});
使用 async/await
const openMediaDevices = async (constraints) => {
return await navigator.mediaDevices.getUserMedia(constraints);
}
try {
const stream = openMediaDevices({'video':true,'audio':true});
console.log('Got MediaStream:', stream);
} catch(error) {
console.error('Error accessing media devices.', error);
}
呼叫 getUserMedia()
會觸發權限要求。如果使用者
接受邀請,承諾就會透過含有以下內容的 MediaStream
解決
一部影片和一個音軌。如果權限遭拒,
已擲回 PermissionDeniedError
。沒有相符的裝置時
連線時,系統會擲回 NotFoundError
。
如需 MediaDevices
介面的完整 API 參考資料,請前往 MDN 網頁
文件。
查詢媒體裝置
在更複雜的應用程式中,我們很可能會想查看所有
連接攝影機和麥克風,並對
內容。呼叫函式 enumerateDevices()
即可達成。這將
傳回的保證會解析為描述 MediaDevicesInfo
陣列的
每個已知媒體裝置都不成問題我們可以使用這個功能向使用者顯示 UI
挑選自己偏好的搜尋結果每個 MediaDevicesInfo
都包含一個名為
將 kind
值設為 audioinput
、audiooutput
或 videoinput
,表示
屬於哪一種媒體裝置?
使用 Promise
function getConnectedDevices(type, callback) {
navigator.mediaDevices.enumerateDevices()
.then(devices => {
const filtered = devices.filter(device => device.kind === type);
callback(filtered);
});
}
getConnectedDevices('videoinput', cameras => console.log('Cameras found', cameras));
使用 async/await
async function getConnectedDevices(type) {
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.filter(device => device.kind === type)
}
const videoCameras = getConnectedDevices('videoinput');
console.log('Cameras found:', videoCameras);
監聽裝置變更
大多數電腦都支援在執行階段期間連接各種裝置。它可以是
透過 USB、藍牙耳機或一組外接喇叭連接的網路攝影機。於
為了妥善支援這項功能,網頁應用程式應監聽變更
更加得心應手只要在
navigator.mediaDevices
用於 devicechange
事件。
// Updates the select element with the provided set of cameras
function updateCameraList(cameras) {
const listElement = document.querySelector('select#availableCameras');
listElement.innerHTML = '';
cameras.map(camera => {
const cameraOption = document.createElement('option');
cameraOption.label = camera.label;
cameraOption.value = camera.deviceId;
}).forEach(cameraOption => listElement.add(cameraOption));
}
// Fetch an array of devices of a certain type
async function getConnectedDevices(type) {
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.filter(device => device.kind === type)
}
// Get the initial set of cameras connected
const videoCameras = getConnectedDevices('videoinput');
updateCameraList(videoCameras);
// Listen for changes to media devices and update the list accordingly
navigator.mediaDevices.addEventListener('devicechange', event => {
const newCameraList = getConnectedDevices('video');
updateCameraList(newCameraList);
});
媒體限制
限制條件物件,也就是必須實作 MediaStreamConstraints
介面後,我們將參數傳遞到 getUserMedia()
就能開啟
符合特定需求的媒體裝置規範這個需求
定義過於寬鬆 (音訊和/或視訊),或非常明確 (最低鏡頭需求
或確切的裝置 ID)。建議採用
getUserMedia()
API 會先檢查現有裝置,然後指定
限制條件,deviceId
限制條件。
此外,裝置也會根據限制條件設定 (如果可行)。三
可以啟用麥克風的回音消除功能,也可以設定特定或最小寬度
和攝影機擷取到影片的高度
async function getConnectedDevices(type) {
const devices = await navigator.mediaDevices.enumerateDevices();
return devices.filter(device => device.kind === type)
}
// Open camera with at least minWidth and minHeight capabilities
async function openCamera(cameraId, minWidth, minHeight) {
const constraints = {
'audio': {'echoCancellation': true},
'video': {
'deviceId': cameraId,
'width': {'min': minWidth},
'height': {'min': minHeight}
}
}
return await navigator.mediaDevices.getUserMedia(constraints);
}
const cameras = getConnectedDevices('videoinput');
if (cameras && cameras.length > 0) {
// Open first available video camera with a resolution of 1280x720 pixels
const stream = openCamera(cameras[0].deviceId, 1280, 720);
}
如需 MediaStreamConstraints
介面的完整說明文件,請參閱
MDN 網路
文件。
本機播放
媒體裝置開啟且可用的 MediaStream
後,
可以指派給影片或音訊元素,以便在本機播放串流。
async function playVideoFromCamera() {
try {
const constraints = {'video': true, 'audio': true};
const stream = await navigator.mediaDevices.getUserMedia(constraints);
const videoElement = document.querySelector('video#localVideo');
videoElement.srcObject = stream;
} catch(error) {
console.error('Error opening video camera.', error);
}
}
搭配 getUserMedia()
使用的一般影片元素所需的 HTML 將
通常具有 autoplay
和 playsinline
屬性。autoplay
屬性就會讓指派給元素的新串流自動播放。
playsinline
屬性允許影片內嵌播放,而非只能完整播放
特定行動裝置螢幕上的顯示效果另外,也建議您使用
用於直播 controls="false"
,除非使用者可以暫停
具體做法是指示 Kubernetes 建立並維護
一或多個代表這些 Pod 的物件
<html>
<head><title>Local video playback</title></head>
<body>
<video id="localVideo" autoplay playsinline controls="false"/>
</body>
</html>