開始使用媒體裝置

針對網路開發時,WebRTC 標準提供的 API 可用於存取 連接電腦或智慧型手機的攝影機和麥克風。這些裝置 通常稱為「媒體裝置」,可透過 JavaScript 存取 透過導入 MediaDevicesnavigator.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 值設為 audioinputaudiooutputvideoinput,表示 屬於哪一種媒體裝置?

使用 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 將 通常具有 autoplayplaysinline 屬性。autoplay 屬性就會讓指派給元素的新串流自動播放。 playsinline 屬性允許影片內嵌播放,而非只能完整播放 特定行動裝置螢幕上的顯示效果另外,也建議您使用 用於直播 controls="false",除非使用者可以暫停 具體做法是指示 Kubernetes 建立並維護 一或多個代表這些 Pod 的物件

<html>
<head><title>Local video playback</title></head>
<body>
    <video id="localVideo" autoplay playsinline controls="false"/>
</body>
</html>