การเริ่มต้นใช้งานอุปกรณ์สื่อ

เมื่อพัฒนาสำหรับเว็บ มาตรฐาน WebRTC จะมี API สำหรับการเข้าถึงกล้องและไมโครโฟนที่เชื่อมต่อกับคอมพิวเตอร์หรือสมาร์ทโฟน อุปกรณ์เหล่านี้เรียกกันโดยทั่วไปว่าอุปกรณ์สื่อ และเข้าถึงได้ด้วย JavaScript ผ่านออบเจ็กต์ navigator.mediaDevices ซึ่งใช้อินเทอร์เฟซ MediaDevices จากออบเจ็กต์นี้ เราสามารถแจกแจงอุปกรณ์ที่เชื่อมต่อทั้งหมด คอยดูการเปลี่ยนแปลงของอุปกรณ์ (เมื่ออุปกรณ์เชื่อมต่อหรือไม่ได้เชื่อมต่อ) และเปิดอุปกรณ์เพื่อเรียกข้อมูลสตรีมสื่อ (ดูด้านล่าง)

วิธีที่ใช้โดยทั่วไปคือการใช้ฟังก์ชัน getUserMedia() ซึ่งจะแสดงผลสัญญาที่จะระบุค่าเป็น MediaStream สำหรับอุปกรณ์สื่อที่ตรงกัน ฟังก์ชันนี้จะใช้ออบเจ็กต์ MediaStreamConstraints รายการเดียวที่ระบุข้อกำหนดที่เรามี ตัวอย่างเช่น ในการเปิดไมโครโฟนและกล้องเริ่มต้น เราจะดำเนินการต่อไปนี้

การใช้คำสัญญา

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);
    });

การใช้อะซิงโครนัส/รอ

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 ที่มีวิดีโอและแทร็กเสียง 1 แทร็ก หากสิทธิ์ถูกปฏิเสธ ระบบจะส่ง PermissionDeniedError ในกรณีที่ไม่มีอุปกรณ์ที่ตรงกันที่เชื่อมต่ออยู่ ระบบจะส่ง NotFoundError

เอกสารอ้างอิง API ทั้งหมดสำหรับอินเทอร์เฟซ MediaDevices สามารถดูได้ที่เอกสารในเว็บ MDN

กำลังค้นหาอุปกรณ์สื่อ

ในแอปพลิเคชันที่ซับซ้อนขึ้น เรามักต้องการตรวจสอบกล้องและไมโครโฟนที่เชื่อมต่ออยู่ทั้งหมด และให้ความคิดเห็นที่เหมาะสมแก่ผู้ใช้ ซึ่งทำได้ด้วยการเรียกใช้ฟังก์ชัน enumerateDevices() ซึ่งจะแสดงผลสัญญาที่แปลค่าเป็นอาร์เรย์ของ MediaDevicesInfo ที่อธิบายอุปกรณ์สื่อที่รู้จักแต่ละเครื่อง เราสามารถใช้ UI นี้เพื่อนำเสนอ UI แก่ผู้ใช้ แล้วผู้ใช้ให้เลือก URL ที่ต้องการ MediaDevicesInfo แต่ละรายการมีพร็อพเพอร์ตี้ชื่อ kind ที่มีค่า audioinput, audiooutput หรือ videoinput ซึ่งบ่งบอกว่าเป็นอุปกรณ์สื่อประเภทใด

การใช้คำสัญญา

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 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 ชุดหูฟังบลูทูธ หรือชุดลำโพงภายนอก เพื่อให้รองรับการดำเนินการนี้ได้อย่างเหมาะสม เว็บแอปพลิเคชันควรติดตามการเปลี่ยนแปลงของอุปกรณ์สื่อ ซึ่งทำได้ด้วยการเพิ่ม Listener ไปยัง 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() ช่วยให้เราเปิดอุปกรณ์สื่อที่ตรงกับข้อกำหนดบางอย่างได้ ข้อกำหนดนี้อาจมีคำจำกัดความแบบคร่าวๆ (เสียงและ/หรือวิดีโอ) หรือที่เฉพาะเจาะจงมาก (ความละเอียดของกล้องขั้นต่ำหรือรหัสอุปกรณ์ที่แน่นอน) ขอแนะนำให้แอปพลิเคชันที่ใช้ 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 ได้ที่เอกสารในเว็บ MN

การเล่นในเครื่อง

เมื่อเปิดอุปกรณ์สื่อและเรามี 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);
    }
}

HTML ที่จำเป็นสำหรับองค์ประกอบวิดีโอทั่วไปที่ใช้กับ getUserMedia() มักมีแอตทริบิวต์ autoplay และ playsinline แอตทริบิวต์ autoplay จะทำให้สตรีมใหม่ที่กำหนดให้กับองค์ประกอบเล่นโดยอัตโนมัติ แอตทริบิวต์ playsinline อนุญาตให้เล่นวิดีโอในหน้า แทนการเล่นแบบเต็มหน้าจอบนเบราว์เซอร์ในอุปกรณ์เคลื่อนที่บางเบราว์เซอร์ นอกจากนี้ ขอแนะนำให้ใช้ controls="false" สำหรับสตรีมแบบสดด้วย เว้นแต่ผู้ใช้ควรหยุดชั่วคราวได้

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