UNPKG

video-auth-js-sdk

Version:

A SDK to authenticate users with camera through a realtime stream

249 lines (220 loc) 9.44 kB
import '../constants.js' import {errorList} from "../errorHandler.js"; function MediaStreamManager() { const deviceStreams = { videoIn: null, audioIn: null, audioOut: null, screenShare: null }; return { setAudioInput(stream) { deviceStreams.audioIn = stream; }, setVideoInput(stream) { deviceStreams.videoIn = stream; }, setScreenShareInput(stream) { deviceStreams.screenShare = stream; }, getVideoInput() { return deviceStreams.videoIn }, getAudioInput() { return deviceStreams.audioIn; }, getScreenShareInput() { return deviceStreams.screenShare; }, async stopAudioInput() { if (!deviceStreams.audioIn) return; deviceStreams.audioIn.getTracks().forEach(track => { if (!!track) { track.stop(); } }); deviceStreams.audioIn = null; }, async stopVideoInput() { if (!deviceStreams.videoIn) return; deviceStreams.videoIn.getTracks().forEach(track => { track.stop(); }) deviceStreams.videoIn = null; }, async stopScreenShareInput() { if (!deviceStreams.screenShare) return; deviceStreams.screenShare.getTracks().forEach(track => { track.stop(); }) deviceStreams.screenShare = null; } } } function DeviceManager(app) { const config = { mediaStreams: new MediaStreamManager(), streamsMetada: { audioInWatcherId: null } } const deviceManager = { getInputDevicePermission({ audio = false, video = false, }) { return new Promise((resolve, reject) => { if (video && config.mediaStreams.getVideoInput()) { resolve(config.mediaStreams.getVideoInput()); return; } if (audio && config.mediaStreams.getAudioInput()) { resolve(config.mediaStreams.getAudioInput()); return; } navigator.mediaDevices.getUserMedia({audio, video}).then(stream => { if (audio) config.mediaStreams.setAudioInput(stream); if (video) config.mediaStreams.setVideoInput(stream); resolve(stream); }).catch(error => { app.chatEvents.fireEvent('callEvents', { type: 'CALL_ERROR', code: (audio ? 12400 : 12401), message: error, // environmentDetails: getSDKCallDetails() }); reject(app.errorHandler.handleError((audio ? 12400 : 12401))) }); }); }, canChooseAudioOutputDevice() { return !!navigator.mediaDevices.selectAudioOutput; }, changeAudioOutputDevice() { if (!navigator.mediaDevices.selectAudioOutput) { console.warn("selectAudioOutput() not supported."); return; } //Display prompt and log selected device or error navigator.mediaDevices.selectAudioOutput() .then((device) => { console.log(device.kind + ": " + device.label + " id = " + device.deviceId); }) .catch(function (err) { console.log(err.name + ": " + err.message); }); }, grantScreenSharePermission({closeStream = false}, callback = null) { return new Promise((resolve, reject) => { if (config.mediaStreams.getScreenShareInput()) { if (!config.mediaStreams.getScreenShareInput().active) { config.mediaStreams.stopScreenShareInput(); // resolve(config.mediaStreams.getScreenShareInput()); } else { // console.log("exists resolving") resolve(config.mediaStreams.getScreenShareInput()); return; } } navigator.mediaDevices.getDisplayMedia({ audio: false, video: true }).then(stream => { config.mediaStreams.setScreenShareInput(stream); if (closeStream) { config.mediaStreams.stopScreenShareInput(); } callback && callback({ hasError: false }) resolve(stream); }).catch(e => { let error = app.errorHandler.raiseError(errorList.SCREENSHARE_PERMISSION_ERROR, callback, true, { eventName: 'callEvents', eventType: 'CALL_ERROR' }); reject(error); }); }); }, grantUserMediaDevicesPermissions({video = false, audio = false, closeStream = false}, callback = null) { return new Promise(async (resolve, reject) => { try { if (audio) await deviceManager.getInputDevicePermission({audio: true}); if (video) await deviceManager.getInputDevicePermission({ video: { width: 320, framerate: 10 } }); if (closeStream) { if (audio) config.mediaStreams.stopAudioInput(); if (video) config.mediaStreams.stopVideoInput(); } if (callback) callback({hasError: false}); resolve({hasError: false}); } catch (error) { let parsedError = { hasError: true, errorCode: error.code, errorMessage: error.message } if (callback) callback(parsedError); reject(parsedError); } }); }, mediaStreams: config.mediaStreams, watchAudioInputStream(callErrorHandler) { config.streamsMetada.audioInWatcherId && clearInterval(config.streamsMetada.audioInWatcherId) config.streamsMetada.audioInWatcherId = setInterval(() => { if (!config.mediaStreams.getAudioInput()) { clearInterval(config.streamsMetada.audioInWatcherId); return; } const audioTracks = config.mediaStreams.getAudioInput()?.getAudioTracks(); if (audioTracks.length === 0) { callErrorHandler(errorList.NO_AUDIO_TRACKS_AVAILABLE, null, true, {}); clearInterval(config.streamsMetada.audioInWatcherId); // No audio from microphone has been captured return; } // We asked for the microphone so one track const track = audioTracks[0]; if (track.muted) { // Track is muted which means that the track is unable to provide media data. // When muted, a track can't be unmuted. // This track will no more provide data... callErrorHandler(errorList.AUDIO_TRACK_MUTED, null, true, {}); clearInterval(config.streamsMetada.audioInWatcherId); } if (!track.enabled) { // Track is disabled (muted for telephonist) which means that the track provides silence instead of real data. // When disabled, a track can be enabled again. // When in that case, user can't be heard until track is enabled again. callErrorHandler(errorList.AUDIO_TRACK_DISABLED, null, true, {}); } if (track.readyState === "ended") { // Possibly a disconnection of the device // When ended, a track can't be active again // This track will no more provide data callErrorHandler(errorList.AUDIO_TRACK_ENDED, null, true, {}); clearInterval(config.streamsMetada.audioInWatcherId); } }, 10000) } } return deviceManager; }; export {DeviceManager}