openvidu-components: Fixed bug requesting devices

pull/750/head
csantosm 2022-08-17 17:54:39 +02:00
parent c0e45e8df7
commit 128dd3cfed
3 changed files with 69 additions and 54 deletions

View File

@ -114,7 +114,7 @@ import { TranslateService } from '../../services/translate/translate.service';
styleUrls: ['./videoconference.component.css'],
animations: [
trigger('inOutAnimation', [
transition(':enter', [style({ opacity: 0 }), animate('300ms ease-out', style({ opacity: 1 }))]),
transition(':enter', [style({ opacity: 0 }), animate('300ms ease-out', style({ opacity: 1 }))])
// transition(':leave', [style({ opacity: 1 }), animate('50ms ease-in', style({ opacity: 0.9 }))])
])
]
@ -286,7 +286,8 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
} else {
this.log.w('No screen token found. Screenshare feature will be disabled');
}
this.loading = false;
this.start();
}
}
@ -434,32 +435,43 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
async ngOnInit() {
this.subscribeToVideconferenceDirectives();
}
private async start() {
await this.deviceSrv.forceInitDevices();
const nickname = this.externalParticipantName || this.storageSrv.getNickname() || `OpenVidu_User${Math.floor(Math.random() * 100)}`;
this.participantService.initLocalParticipant({local: true, nickname});
this.participantService.initLocalParticipant({ local: true, nickname });
this.openviduService.initialize();
if (this.deviceSrv.hasVideoDeviceAvailable() || this.deviceSrv.hasAudioDeviceAvailable()) {
await this.initwebcamPublisher();
}
this.isSessionInitialized = true;
this.onParticipantCreated.emit(this.participantService.getLocalParticipant());
this.loading = false;
}
private async initwebcamPublisher() {
try {
const publisher = await this.openviduService.initDefaultPublisher(undefined);
if (publisher) {
publisher.once('accessDenied', (e: any) => this.handlePublisherError(e));
publisher.once('accessAllowed', async () => {
await this.handlePublisherSuccess();
this.participantReady = true;
});
// publisher.once('streamPlaying', () => (this.streamPlaying = true));
private async initwebcamPublisher(): Promise<void> {
return new Promise(async (resolve, reject) => {
try {
const publisher = await this.openviduService.initDefaultPublisher();
if (publisher) {
publisher.once('accessDenied', (e: any) => {
this.handlePublisherError(e);
resolve();
});
publisher.once('accessAllowed', async () => {
await this.handlePublisherSuccess();
this.participantReady = true;
resolve();
});
}
} catch (error) {
this.actionService.openDialog(error.name.replace(/_/g, ' '), error.message, true);
this.log.e(error);
reject();
}
} catch (error) {
this.actionService.openDialog(error.name.replace(/_/g, ' '), error.message, true);
this.log.e(error);
}
});
}
async ngOnDestroy() {
@ -649,8 +661,9 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
this.onSessionCreated.emit(session);
}
private handlePublisherError(e: any) {
let message: string;
private handlePublisherError(e: any): Promise<void> {
let message: string = '';
console.log('ERROR!', e);
if (e.name === OpenViduErrorName.DEVICE_ALREADY_IN_USE) {
this.log.w('Video device already in use. Disabling video device...');
// Allow access to the room with only mic if camera device is already in use

View File

@ -16,12 +16,12 @@ import { StorageService } from '../storage/storage.service';
providedIn: 'root'
})
export class DeviceService {
private OV: OpenVidu = null;
private OV: OpenVidu | null = null;
private devices: Device[];
private cameras: CustomDevice[] = [];
private microphones: CustomDevice[] = [];
private cameraSelected: CustomDevice;
private microphoneSelected: CustomDevice;
private cameraSelected: CustomDevice | null;
private microphoneSelected: CustomDevice | null;
private log: ILogger;
private videoDevicesDisabled: boolean;
private audioDevicesDisabled: boolean;
@ -49,30 +49,33 @@ export class DeviceService {
this.clear();
try {
this.OV = new OpenVidu();
// Forcing media permissions request.
// Sometimes, browser doens't launch the media permissions modal.
const mediaStream = await this.OV.getUserMedia({ audioSource: undefined, videoSource: undefined });
mediaStream?.getAudioTracks().forEach((track) => track.stop());
mediaStream?.getVideoTracks().forEach((track) => track.stop());
this.devices = await this.OV.getDevices();
if(this.devices?.some(device => !device.deviceId || !device.label)){
// Forcing media permissions request.
// Sometimes, browser doesn't request the media permissions.
await this.OV.getUserMedia({ audioSource: undefined, videoSource: undefined });
}
await this.initializeDevices();
this.updateAudioDeviceSelected();
this.updateVideoDeviceSelected();
this._isVideoMuted = this.storageSrv.isVideoMuted() || this.libSrv.videoMuted.getValue();
this._isAudioMuted = this.storageSrv.isAudioMuted() || this.libSrv.audioMuted.getValue();
this.log.d('Media devices', this.cameras, this.microphones);
} catch (error) {
this.deviceAccessDeniedError = (<OpenViduError>error).name === OpenViduErrorName.DEVICE_ACCESS_DENIED;
}
await this.initializeDevices();
this.updateAudioDeviceSelected();
this.updateVideoDeviceSelected();
this._isVideoMuted = this.storageSrv.isVideoMuted() || this.libSrv.videoMuted.getValue();
this._isAudioMuted = this.storageSrv.isAudioMuted() || this.libSrv.audioMuted.getValue();
this.log.d('Media devices', this.cameras, this.microphones);
}
/**
* Initialize only the media devices available
*/
async initializeDevices() {
this.devices = await this.OV.getDevices();
if(this.devices?.some(device => !device.deviceId || !device.label)){
this.devices = await this.OV?.getDevices() as Device [];
}
this.initializeCustomDevices();
}
@ -156,11 +159,11 @@ export class DeviceService {
return this.hasAudioDeviceAvailable() && this._isAudioMuted;
}
getCameraSelected(): CustomDevice {
getCameraSelected(): CustomDevice | null {
return this.cameraSelected;
}
getMicrophoneSelected(): CustomDevice {
getMicrophoneSelected(): CustomDevice | null {
return this.microphoneSelected;
}
@ -175,11 +178,11 @@ export class DeviceService {
}
needUpdateVideoTrack(newVideoSource: string): boolean {
return this.cameraSelected.device !== newVideoSource;
return this.cameraSelected?.device !== newVideoSource;
}
needUpdateAudioTrack(newAudioSource: string): boolean {
return this.microphoneSelected.device !== newAudioSource;
return this.microphoneSelected?.device !== newAudioSource;
}
getCameras(): CustomDevice[] {
@ -226,14 +229,14 @@ export class DeviceService {
}
private getCameraByDeviceField(deviceField: any): CustomDevice {
return this.cameras.find((opt: CustomDevice) => opt.device === deviceField || opt.label === deviceField);
return <CustomDevice>this.cameras.find((opt: CustomDevice) => opt.device === deviceField || opt.label === deviceField);
}
private getMicrophoneByDeviceField(deviceField: any): CustomDevice {
return this.microphones.find((opt: CustomDevice) => opt.device === deviceField || opt.label === deviceField);
return <CustomDevice>this.microphones.find((opt: CustomDevice) => opt.device === deviceField || opt.label === deviceField);
}
private getMicrophoneFromStogare(): CustomDevice {
private getMicrophoneFromStogare(): CustomDevice | undefined {
const storageDevice: CustomDevice = this.storageSrv.getAudioDevice();
if (!!storageDevice && this.microphones.some((device) => device.device === storageDevice.device)) {
return storageDevice;

View File

@ -19,10 +19,10 @@ import { OpenViduEdition } from '../../models/openvidu.model';
})
export class OpenViduService {
private ovEdition: OpenViduEdition;
protected OV: OpenVidu = null;
protected OVScreen: OpenVidu = null;
protected webcamSession: Session = null;
protected screenSession: Session = null;
protected OV: OpenVidu;
protected OVScreen: OpenVidu;
protected webcamSession: Session;
protected screenSession: Session;
protected videoSource = undefined;
protected audioSource = undefined;
protected log: ILogger;
@ -166,14 +166,14 @@ export class OpenViduService {
* @internal
* Initialize a publisher checking devices saved on storage or if participant have devices available.
*/
async initDefaultPublisher(targetElement: string | HTMLElement): Promise<Publisher> {
async initDefaultPublisher(): Promise<Publisher> {
const hasVideoDevices = this.deviceService.hasVideoDeviceAvailable();
const hasAudioDevices = this.deviceService.hasAudioDeviceAvailable();
const isVideoActive = !this.deviceService.isVideoMuted();
const isAudioActive = !this.deviceService.isAudioMuted();
let videoSource = null;
let audioSource = null;
let videoSource: string | boolean = false;
let audioSource: string | boolean = false;
if (hasVideoDevices) {
// Video is active, assign the device selected
@ -200,7 +200,7 @@ export class OpenViduService {
mirror
};
if (hasVideoDevices || hasAudioDevices) {
const publisher = await this.initPublisher(targetElement, properties);
const publisher = await this.initPublisher(undefined, properties);
this.participantService.setMyCameraPublisher(publisher);
this.participantService.updateLocalParticipant();
return publisher;
@ -325,7 +325,7 @@ export class OpenViduService {
const properties: PublisherProperties = {
videoSource: ScreenType.SCREEN,
audioSource: hasAudioDevicesAvailable ? this.deviceService.getMicrophoneSelected().device : null,
audioSource: hasAudioDevicesAvailable ? this.deviceService.getMicrophoneSelected().device : false,
publishVideo: true,
publishAudio: hasAudio,
mirror: false
@ -450,7 +450,6 @@ export class OpenViduService {
}
}
//TODO: Uncomment this section when replaceTrack issue is fixed
private async createMediaStream(pp: PublisherProperties): Promise<MediaStream> {
let mediaStream: MediaStream;
const isFirefoxPlatform = this.platformService.isFirefox();