GetUserMedia: примеры (JAVASCRIPT)

Использование JavaScript функции getUserMedia на практике
Раздел: Медиа, Камера/Микрофон
getUserMedia(constraints: MediaStreamConstraints): Promise

Основы функции getUserMedia

Метод getUserMedia() является частью API WebRTC и предоставляет доступ к медиаустройствам пользователя, таким как камера и микрофон, через браузер. Функция используется для захвата аудио и видео потоков в реальном времени для последующей обработки, записи или передачи.

Метод вызывается через объект navigator.mediaDevices. Основной сценарий применения - видеозвонки, запись видео и аудио, фотографирование через веб-камеру, анализ медиаданных.

Аргументы функции

Функция принимает один обязательный аргумент - объект ограничений (constraints):

  • audio: Boolean или объект с настройками аудио
  • video: Boolean или объект с настройками видео
  • preferCurrentTab (новое): Предпочтение захвата с текущей вкладки

Возвращаемое значение

Функция возвращает Promise, который разрешается объектом MediaStream, содержащим запрошенные медиапотоки. В случае ошибки Promise отклоняется с объектом DOMException.

Базовые примеры использования

Пример 1: Запрос доступа только к камере

async function getCamera() {
    try {
        const stream = await navigator.mediaDevices.getUserMedia({ 
            video: true,
            audio: false 
        });
        console.log('Получен видеопоток');
        return stream;
    } catch (error) {
        console.error('Ошибка доступа к камере:', error);
    }
}
// Результат: MediaStream объект с видеодорожкой

Пример 2: Запрос аудио и видео с ограничениями

const constraints = {
    audio: {
        sampleRate: 44100,
        channelCount: 2
    },
    video: {
        width: { min: 640, ideal: 1280, max: 1920 },
        height: { min: 480, ideal: 720, max: 1080 },
        facingMode: 'user'
    }
};

navigator.mediaDevices.getUserMedia(constraints)
    .then(stream => {
        console.log('Разрешение видео:', stream.getVideoTracks()[0].getSettings().width);
    })
    .catch(err => {
        console.log(err.name + ': ' + err.message);
    });
// Результат при успехе: разрешение видео близкое к 1280x720

Альтернативные API в JavaScript

getDisplayMedia() - захват содержимого экрана или окна приложения. Используется для скринкастинга и записи презентаций.

async function captureScreen() {
    try {
        return await navigator.mediaDevices.getDisplayMedia({
            video: true,
            audio: true
        });
    } catch (err) {
        console.error('Ошибка захвата экрана:', err);
    }
}

enumerateDevices() - получение списка доступных медиаустройств без запроса разрешений. Помогает предварительно определить доступное оборудование.

Выбор API зависит от задачи: getUserMedia для камеры/микрофона, getDisplayMedia для захвата экрана.

Решения на других языках программирования

Python (OpenCV) - библиотека для захвата видео с камеры

import cv2

cap = cv2.VideoCapture(0)
while True:
    ret, frame = cap.read()
    cv2.imshow('Camera', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cap.release()

Java (JavaCV) - кроссплатформенное решение для работы с медиа

C++ (libwebrtc) - низкоуровневая библиотека WebRTC

Основное отличие JavaScript реализации - работа в песочнице браузера с обязательным запросом разрешения пользователя.

Распространенные ошибки

Ошибка 1: Необработанный отказ в разрешении

// Неправильно
navigator.mediaDevices.getUserMedia({ video: true });

// Правильно
navigator.mediaDevices.getUserMedia({ video: true })
    .then(stream => {
        // обработка успеха
    })
    .catch(error => {
        if (error.name === 'NotAllowedError') {
            console.log('Пользователь отказал в доступе');
        } else if (error.name === 'NotFoundError') {
            console.log('Устройство не найдено');
        }
    });

Ошибка 2: Несовместимые ограничения

// Может вызвать OverconstrainedError
const constraints = {
    video: {
        width: { exact: 5000 }, // Неподдерживаемое значение
        height: { exact: 5000 }
    }
};

История изменений API

Раньше метод был доступен как navigator.getUserMedia(), но теперь является частью navigator.mediaDevices. Добавлена поддержка Promise вместо callback.

В современных браузерах добавлены новые возможности:

  • Свойство preferCurrentTab для Screen Capture API
  • Улучшенная обработка устройств с несколькими камерами
  • Поддержка HDR видео в некоторых реализациях
  • Автоматический выбор качества в зависимости от сетевых условий

Расширенные сценарии применения

Пример 1: Запись аудио с визуализацией

Пример javascript
let audioContext, analyser, microphone;

async function startAudioAnalysis() {
    const stream = await navigator.mediaDevices.getUserMedia({
        audio: {
            echoCancellation: false,
            noiseSuppression: false,
            autoGainControl: false
        }
    });
    
    audioContext = new AudioContext();
    analyser = audioContext.createAnalyser();
    microphone = audioContext.createMediaStreamSource(stream);
    
    microphone.connect(analyser);
    analyser.fftSize = 2048;
    
    // Визуализация аудио
    const bufferLength = analyser.frequencyBinCount;
    const dataArray = new Uint8Array(bufferLength);
    
    function draw() {
        analyser.getByteTimeDomainData(dataArray);
        // отрисовка волны
        requestAnimationFrame(draw);
    }
    draw();
}

Пример 2: Переключение между камерами

Пример javascript
let currentStream;

async function switchCamera() {
    if (currentStream) {
        currentStream.getTracks().forEach(track => track.stop());
    }
    
    const devices = await navigator.mediaDevices.enumerateDevices();
    const videoDevices = devices.filter(device => device.kind === 'videoinput');
    
    if (videoDevices.length < 2) {
        console.log('Только одна камера доступна');
        return;
    }
    
    const currentDevice = currentStream 
        ? currentStream.getVideoTracks()[0].getSettings().deviceId
        : null;
    
    const nextDevice = videoDevices.find(
        device => device.deviceId !== currentDevice
    );
    
    currentStream = await navigator.mediaDevices.getUserMedia({
        video: { deviceId: { exact: nextDevice.deviceId } }
    });
    
    // Применение нового потока к видео элементу
    videoElement.srcObject = currentStream;
}

Пример 3: Захват с логированием метаданных

Пример javascript
async function captureWithMetadata() {
    const stream = await navigator.mediaDevices.getUserMedia({
        video: {
            advanced: [{
                width: 1920,
                height: 1080,
                frameRate: { ideal: 60 }
            }]
        }
    });
    
    const videoTrack = stream.getVideoTracks()[0];
    const settings = videoTrack.getSettings();
    const capabilities = videoTrack.getCapabilities();
    
    console.log('Текущие настройки:', {
        resolution: `${settings.width}x${settings.height}`,
        frameRate: settings.frameRate,
        deviceId: settings.deviceId
    });
    
    console.log('Возможности устройства:', {
        supportedResolutions: capabilities.width ? 
            `от ${capabilities.width.min} до ${capabilities.width.max}` : 'не определено',
        supportedFramerates: capabilities.frameRate ?
            `от ${capabilities.frameRate.min} до ${capabilities.frameRate.max}` : 'не определено'
    });
    
    return stream;
}

JS getUserMedia function comments

En
GetUserMedia Prompts the user for permission to use a media input (camera, microphone)