infobip-rtc
Version:
Infobip RTC JavaScript SDK - Infobip WebRTC API Implementation
201 lines • 8.07 kB
JavaScript
import "webrtc-adapter";
import { CameraOrientation } from "../call/options/CameraOrientation";
import { findIndex, uniqBy } from 'lodash-es';
import { VideoOptionsUtil } from "../util/VideoOptionsUtil";
export class DefaultDevice {
constructor(logger) {
this.logger = logger;
this.deviceKindNames = {
"audioinput": "Microphone",
"audiooutput": "Speaker",
"videoinput": "Camera"
};
this.getMicrophoneDefaults = () => ({
noiseSuppression: true,
echoCancellation: true
});
this.getCameraDefaults = (hdResolution = false, cameraVideoFrameRate) => ({
width: hdResolution ? 1280 : 640,
height: hdResolution ? 720 : 480,
frameRate: VideoOptionsUtil.limitFps(cameraVideoFrameRate) || DefaultDevice.CAMERA_VIDEO_FPS_DEFAULT
});
this.getScreenShareDefaults = (screenShareFrameRate) => ({
width: {
max: 1920
},
height: {
max: 1080
},
frameRate: VideoOptionsUtil.limitFps(screenShareFrameRate) || DefaultDevice.SCREEN_SHARE_FPS_DEFAULT,
cursor: "always"
});
}
getAudioInputDevices() {
return this.getDevices("audioinput")
.then(devices => this.updateDevices(devices));
}
getAudioOutputDevices() {
return this.getDevices("audiooutput")
.then(devices => this.updateDevices(devices));
}
getVideoInputDevices() {
return this.getDevices("videoinput")
.then(devices => this.updateDevices(devices));
}
setAudioInputDevice(id) {
this.audioInputDevice = {
deviceId: id,
kind: "audioinput"
};
}
unsetAudioInputDevice() {
this.audioInputDevice = null;
}
getAudioInputDevice() {
return this.audioInputDevice?.deviceId;
}
audioInputDeviceShouldChange() {
return this.getAudioInputDevices()
.then(devices => {
return devices.findIndex(device => device.deviceId === this.audioInputDevice?.deviceId) === -1 && devices.length > 0;
})
.catch(() => {
return false;
});
}
setVideoInputDevice(id) {
this.videoInputDevice = {
deviceId: id,
kind: "videoinput"
};
}
unsetVideoInputDevice() {
this.videoInputDevice = null;
}
getVideoInputDevice() {
return this.videoInputDevice?.deviceId;
}
getCameraOrientation() {
return this.cameraOrientation;
}
async getLocalStream(audio = true, video = false, cameraOrientation = CameraOrientation.FRONT, hdResolution = false, useExactDevice = true, cameraVideoFrameRate) {
let mediaConstraints = {};
let devices = [];
try {
this.cameraOrientation = cameraOrientation;
if (audio) {
if (this.audioInputDevice) {
const audioDevices = await this.getDevices("audioinput");
devices.push(...audioDevices);
const audioDeviceConstraints = this.getDeviceConstraint(audioDevices, this.audioInputDevice);
mediaConstraints.audio = this.getAudioConstraints(audioDeviceConstraints);
}
else {
mediaConstraints.audio = this.getAudioConstraints(null);
}
}
if (video) {
if (this.videoInputDevice) {
const videoDevices = await this.getDevices("videoinput");
devices.push(...videoDevices);
const videoDeviceConstraints = this.getDeviceConstraint(videoDevices, this.videoInputDevice, useExactDevice);
mediaConstraints.video = this.getVideoConstraints(videoDeviceConstraints, cameraOrientation, hdResolution, cameraVideoFrameRate);
}
else {
mediaConstraints.video = this.getVideoConstraints(null, cameraOrientation, hdResolution, cameraVideoFrameRate);
}
}
return await navigator.mediaDevices.getUserMedia(mediaConstraints);
}
catch (error) {
if (error) {
this.logger.error(`Failed to request device audio=${audio} video=${video} with constraints ${mediaConstraints && JSON.stringify(mediaConstraints)} (${devices && JSON.stringify(devices)}) - ${error}`);
}
throw error;
}
}
getDisplayMedia(displayOptions, screenShareFrameRate) {
const constraints = {
video: this.getScreenShareDefaults(screenShareFrameRate),
...(displayOptions && { monitorTypeSurfaces: "include" }),
};
if (displayOptions) {
constraints.video.displaySurface = displayOptions.allowedDisplayOptions[0];
}
if (displayOptions && !displayOptions.allowedDisplayOptions.includes("monitor")) {
constraints.monitorTypeSurfaces = "exclude";
}
return navigator.mediaDevices.getDisplayMedia?.(constraints) ??
Promise.reject("Screen share is not supported.");
}
getAudioConstraints(deviceId = null) {
return {
...this.getMicrophoneDefaults(),
deviceId
};
}
getVideoConstraints(deviceId = null, cameraOrientation = CameraOrientation.FRONT, hdResolution = false, cameraVideoFrameRate) {
return {
...this.getCameraDefaults(hdResolution, cameraVideoFrameRate),
facingMode: cameraOrientation,
deviceId
};
}
getDeviceConstraint(devices, inputDevice, useExactDevice = true) {
if (!inputDevice)
return null;
let videoInputDeviceExists = findIndex(devices, {
kind: inputDevice.kind,
deviceId: inputDevice.deviceId
}) !== -1;
return videoInputDeviceExists && useExactDevice ? { exact: inputDevice.deviceId } : null;
}
async getDevices(deviceKind = null) {
const mediaDevices = await this.enumerateDevices(deviceKind);
if (mediaDevices.length === 0) {
return [];
}
if (mediaDevices[0].label) {
return this.filterDevices(mediaDevices, deviceKind);
}
else {
return this.getUserMediaDevices(deviceKind);
}
}
filterDevices(mediaDeviceInfos, deviceKind) {
if (deviceKind) {
let devices = mediaDeviceInfos.filter(device => device.kind === deviceKind);
return uniqBy(devices, 'deviceId');
}
return uniqBy(mediaDeviceInfos, 'deviceId');
}
async getUserMediaDevices(deviceKind) {
let constraints = deviceKind === 'videoinput' ? { video: true } : { audio: true };
const stream = await navigator.mediaDevices.getUserMedia(constraints);
this.stopTracks(stream);
return await this.enumerateDevices(deviceKind);
}
async enumerateDevices(deviceKind) {
const mediaDevices = await navigator.mediaDevices.enumerateDevices();
return this.filterDevices(mediaDevices, deviceKind);
}
stopTracks(stream) {
stream.getTracks().forEach((track) => track.stop());
}
updateDevices(devices) {
return devices.map((device, index) => {
return this.generateCustomMediaDeviceInfo(device, index + 1);
});
}
generateCustomMediaDeviceInfo(mediaDeviceInfo, index) {
let deviceKindName = this.deviceKindNames[mediaDeviceInfo.kind];
let customMediaDeviceInfo = mediaDeviceInfo.toJSON();
if (!mediaDeviceInfo.label) {
customMediaDeviceInfo.label = mediaDeviceInfo.deviceId === "default" ? `Default ${deviceKindName}` : `${deviceKindName} ${index}`;
}
return customMediaDeviceInfo;
}
}
DefaultDevice.CAMERA_VIDEO_FPS_DEFAULT = 24;
DefaultDevice.SCREEN_SHARE_FPS_DEFAULT = 8;
//# sourceMappingURL=DefaultDevice.js.map