UNPKG

@tencentcloud/roomkit-web-vue3

Version:

<h1 align="center"> TUIRoomKit</h1> Conference (TUIRoomKit) is a product suitable for multi-person audio and video conversation scenarios such as business meetings, webinars, and online education. By integrating this product, you can add room management,

206 lines (199 loc) 6.31 kB
import { TUIRoomDeviceMangerEvents, TUIMediaDeviceType, TUIAudioRoute, } from '@tencentcloud/tuiroom-engine-js'; import { MediaDeviceState } from '../../type'; import useGetRoomEngine from '../../../hooks/useRoomEngine'; import useDeviceManager from '../../../hooks/useDeviceManager'; import { isWeChat, isElectron } from '../../../utils/environment'; import TUIMessageBox from '../../../components/common/base/MessageBox'; import { TUIToast, TOAST_TYPE } from '@tencentcloud/uikit-base-component-vue3'; import i18n from '../../../locales'; import { WARNING_MESSAGE, MESSAGE_DURATION } from '../../../constants/message'; import { roomService } from '../../../services'; import useAudioDeviceState, { testAudioVolume, } from './audioDeviceManagerState'; const { microphoneState, currentMicrophoneDevice, currentMicrophoneId, currentSpeakerDevice, currentSpeakerId, isMicrophoneTesting, isSpeakerTesting, currentAudioRoute, } = useAudioDeviceState(); const roomEngine = useGetRoomEngine(); const deviceManager = useDeviceManager(); const { t } = i18n.global; class Microphone { static instance: Microphone; constructor() { if (!Microphone.instance) { Microphone.instance = this; } return Microphone.instance; } private onTestMicVolume(options: { volume: number }) { testAudioVolume.value = options.volume; } public async startMicDeviceTest(options: { interval: number }) { await roomEngine.instance?.startMicDeviceTest(options); isMicrophoneTesting.value = true; deviceManager.instance?.on( TUIRoomDeviceMangerEvents.onTestMicVolume, this.onTestMicVolume ); } public async stopMicDeviceTest() { await roomEngine.instance?.stopMicDeviceTest(); isMicrophoneTesting.value = false; deviceManager.instance?.off( TUIRoomDeviceMangerEvents.onTestMicVolume, this.onTestMicVolume ); } public async checkMicrophonePermission() { const audioStream = await navigator.mediaDevices.getUserMedia({ audio: { deviceId: currentMicrophoneId.value }, }); audioStream.getAudioTracks()[0].stop(); } public async openLocalMicrophone() { if ( microphoneState.value === MediaDeviceState.NotSupportCapture && !isWeChat ) { TUIMessageBox({ title: t('Note'), message: t('The current browser does not support capturing audio'), confirmButtonText: t('Sure'), }); return; } if ( microphoneState.value === MediaDeviceState.NoDeviceDetected && !isWeChat ) { TUIMessageBox({ title: t('Note'), message: t('Microphone not detected on current device'), confirmButtonText: t('Sure'), }); return; } try { await this.checkMicrophonePermission(); } catch (error) { TUIMessageBox({ title: t('Note'), message: t( 'The current device is not authorized, please allow access to the device permissions', { deviceType: t('microphone') } ), confirmButtonText: t('Sure'), }); return; } if (microphoneState.value === MediaDeviceState.DeviceOffAndDisabled) { let warningMessage = ''; if (roomService.roomStore.isAudience) { warningMessage = WARNING_MESSAGE.UNMUTE_LOCAL_MIC_FAIL_AUDIENCE; } else if (roomService.roomStore.isMicrophoneDisableForAllUser) { warningMessage = WARNING_MESSAGE.UNMUTE_LOCAL_MIC_FAIL_MUTE_ALL; } TUIToast({ type: TOAST_TYPE.WARNING, message: t(warningMessage), duration: MESSAGE_DURATION.NORMAL, }); return; } try { await roomEngine.instance?.openLocalMicrophone(); } catch (error: any) { // At this point the microphone has begun to pick up if ( error.code === 0 && error.message === 'you have already mute the audio' ) { return; } throw error; } } public async closeLocalMicrophone() { await roomEngine.instance?.closeLocalMicrophone(); } public async muteLocalAudio() { await roomEngine.instance?.muteLocalAudio(); } public async unmuteLocalAudio() { await roomEngine.instance?.unmuteLocalAudio(); } public async setCurrentDevice(options: { deviceId: string }) { const { deviceId } = options; await deviceManager.instance?.setCurrentDevice({ type: TUIMediaDeviceType.kMediaDeviceTypeAudioInput, deviceId, }); currentMicrophoneDevice.value = deviceManager.instance?.getCurrentDevice({ type: TUIMediaDeviceType.kMediaDeviceTypeAudioInput, }) || null; } } class Speaker { private speakerTestPlayer: HTMLAudioElement | null = null; public async startSpeakerDeviceTest(options: { filePath: string }) { if (isElectron) { deviceManager.instance?.startSpeakerDeviceTest(options); return; } this.speakerTestPlayer = document?.createElement('audio'); if ( this.speakerTestPlayer && typeof this.speakerTestPlayer.loop !== 'undefined' ) { this.speakerTestPlayer.loop = true; } await this.speakerTestPlayer?.setSinkId(currentSpeakerId.value); this.speakerTestPlayer.src = options.filePath; this.speakerTestPlayer.play(); isSpeakerTesting.value = true; } public async stopSpeakerDeviceTest() { if (isElectron) { deviceManager.instance?.stopSpeakerDeviceTest(); return; } if (this.speakerTestPlayer) { this.speakerTestPlayer.pause(); this.speakerTestPlayer.currentTime = 0; } isSpeakerTesting.value = false; } public async setCurrentDevice(options: { deviceId: string }) { const { deviceId } = options; await deviceManager.instance?.setCurrentDevice({ type: TUIMediaDeviceType.kMediaDeviceTypeAudioOutput, deviceId, }); currentSpeakerDevice.value = deviceManager.instance?.getCurrentDevice({ type: TUIMediaDeviceType.kMediaDeviceTypeAudioOutput, }) || null; } public async setAudioRoute(options: { route: TUIAudioRoute }) { await deviceManager.instance?.setAudioRoute(options); currentAudioRoute.value = options.route; } } export default function useAudioDeviceManager() { return { microphone: new Microphone(), speaker: new Speaker(), }; }