mirror of https://github.com/OpenVidu/openvidu.git
openvidu-components: Fixed bug requesting devices
parent
c0e45e8df7
commit
128dd3cfed
|
@ -114,7 +114,7 @@ import { TranslateService } from '../../services/translate/translate.service';
|
||||||
styleUrls: ['./videoconference.component.css'],
|
styleUrls: ['./videoconference.component.css'],
|
||||||
animations: [
|
animations: [
|
||||||
trigger('inOutAnimation', [
|
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 }))])
|
// 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 {
|
} else {
|
||||||
this.log.w('No screen token found. Screenshare feature will be disabled');
|
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() {
|
async ngOnInit() {
|
||||||
this.subscribeToVideconferenceDirectives();
|
this.subscribeToVideconferenceDirectives();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async start() {
|
||||||
await this.deviceSrv.forceInitDevices();
|
await this.deviceSrv.forceInitDevices();
|
||||||
const nickname = this.externalParticipantName || this.storageSrv.getNickname() || `OpenVidu_User${Math.floor(Math.random() * 100)}`;
|
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();
|
this.openviduService.initialize();
|
||||||
if (this.deviceSrv.hasVideoDeviceAvailable() || this.deviceSrv.hasAudioDeviceAvailable()) {
|
if (this.deviceSrv.hasVideoDeviceAvailable() || this.deviceSrv.hasAudioDeviceAvailable()) {
|
||||||
await this.initwebcamPublisher();
|
await this.initwebcamPublisher();
|
||||||
}
|
}
|
||||||
this.isSessionInitialized = true;
|
this.isSessionInitialized = true;
|
||||||
this.onParticipantCreated.emit(this.participantService.getLocalParticipant());
|
this.onParticipantCreated.emit(this.participantService.getLocalParticipant());
|
||||||
|
this.loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async initwebcamPublisher() {
|
private async initwebcamPublisher(): Promise<void> {
|
||||||
try {
|
return new Promise(async (resolve, reject) => {
|
||||||
const publisher = await this.openviduService.initDefaultPublisher(undefined);
|
try {
|
||||||
if (publisher) {
|
const publisher = await this.openviduService.initDefaultPublisher();
|
||||||
publisher.once('accessDenied', (e: any) => this.handlePublisherError(e));
|
|
||||||
publisher.once('accessAllowed', async () => {
|
if (publisher) {
|
||||||
await this.handlePublisherSuccess();
|
publisher.once('accessDenied', (e: any) => {
|
||||||
this.participantReady = true;
|
this.handlePublisherError(e);
|
||||||
});
|
resolve();
|
||||||
// publisher.once('streamPlaying', () => (this.streamPlaying = true));
|
});
|
||||||
|
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() {
|
async ngOnDestroy() {
|
||||||
|
@ -649,8 +661,9 @@ export class VideoconferenceComponent implements OnInit, OnDestroy, AfterViewIni
|
||||||
this.onSessionCreated.emit(session);
|
this.onSessionCreated.emit(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
private handlePublisherError(e: any) {
|
private handlePublisherError(e: any): Promise<void> {
|
||||||
let message: string;
|
let message: string = '';
|
||||||
|
console.log('ERROR!', e);
|
||||||
if (e.name === OpenViduErrorName.DEVICE_ALREADY_IN_USE) {
|
if (e.name === OpenViduErrorName.DEVICE_ALREADY_IN_USE) {
|
||||||
this.log.w('Video device already in use. Disabling video device...');
|
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
|
// Allow access to the room with only mic if camera device is already in use
|
||||||
|
|
|
@ -16,12 +16,12 @@ import { StorageService } from '../storage/storage.service';
|
||||||
providedIn: 'root'
|
providedIn: 'root'
|
||||||
})
|
})
|
||||||
export class DeviceService {
|
export class DeviceService {
|
||||||
private OV: OpenVidu = null;
|
private OV: OpenVidu | null = null;
|
||||||
private devices: Device[];
|
private devices: Device[];
|
||||||
private cameras: CustomDevice[] = [];
|
private cameras: CustomDevice[] = [];
|
||||||
private microphones: CustomDevice[] = [];
|
private microphones: CustomDevice[] = [];
|
||||||
private cameraSelected: CustomDevice;
|
private cameraSelected: CustomDevice | null;
|
||||||
private microphoneSelected: CustomDevice;
|
private microphoneSelected: CustomDevice | null;
|
||||||
private log: ILogger;
|
private log: ILogger;
|
||||||
private videoDevicesDisabled: boolean;
|
private videoDevicesDisabled: boolean;
|
||||||
private audioDevicesDisabled: boolean;
|
private audioDevicesDisabled: boolean;
|
||||||
|
@ -49,30 +49,33 @@ export class DeviceService {
|
||||||
this.clear();
|
this.clear();
|
||||||
try {
|
try {
|
||||||
this.OV = new OpenVidu();
|
this.OV = new OpenVidu();
|
||||||
// Forcing media permissions request.
|
this.devices = await this.OV.getDevices();
|
||||||
// Sometimes, browser doens't launch the media permissions modal.
|
if(this.devices?.some(device => !device.deviceId || !device.label)){
|
||||||
const mediaStream = await this.OV.getUserMedia({ audioSource: undefined, videoSource: undefined });
|
// Forcing media permissions request.
|
||||||
mediaStream?.getAudioTracks().forEach((track) => track.stop());
|
// Sometimes, browser doesn't request the media permissions.
|
||||||
mediaStream?.getVideoTracks().forEach((track) => track.stop());
|
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) {
|
} catch (error) {
|
||||||
this.deviceAccessDeniedError = (<OpenViduError>error).name === OpenViduErrorName.DEVICE_ACCESS_DENIED;
|
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
|
* Initialize only the media devices available
|
||||||
*/
|
*/
|
||||||
async initializeDevices() {
|
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();
|
this.initializeCustomDevices();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,11 +159,11 @@ export class DeviceService {
|
||||||
return this.hasAudioDeviceAvailable() && this._isAudioMuted;
|
return this.hasAudioDeviceAvailable() && this._isAudioMuted;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCameraSelected(): CustomDevice {
|
getCameraSelected(): CustomDevice | null {
|
||||||
return this.cameraSelected;
|
return this.cameraSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
getMicrophoneSelected(): CustomDevice {
|
getMicrophoneSelected(): CustomDevice | null {
|
||||||
return this.microphoneSelected;
|
return this.microphoneSelected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,11 +178,11 @@ export class DeviceService {
|
||||||
}
|
}
|
||||||
|
|
||||||
needUpdateVideoTrack(newVideoSource: string): boolean {
|
needUpdateVideoTrack(newVideoSource: string): boolean {
|
||||||
return this.cameraSelected.device !== newVideoSource;
|
return this.cameraSelected?.device !== newVideoSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
needUpdateAudioTrack(newAudioSource: string): boolean {
|
needUpdateAudioTrack(newAudioSource: string): boolean {
|
||||||
return this.microphoneSelected.device !== newAudioSource;
|
return this.microphoneSelected?.device !== newAudioSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
getCameras(): CustomDevice[] {
|
getCameras(): CustomDevice[] {
|
||||||
|
@ -226,14 +229,14 @@ export class DeviceService {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getCameraByDeviceField(deviceField: any): CustomDevice {
|
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 {
|
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();
|
const storageDevice: CustomDevice = this.storageSrv.getAudioDevice();
|
||||||
if (!!storageDevice && this.microphones.some((device) => device.device === storageDevice.device)) {
|
if (!!storageDevice && this.microphones.some((device) => device.device === storageDevice.device)) {
|
||||||
return storageDevice;
|
return storageDevice;
|
||||||
|
|
|
@ -19,10 +19,10 @@ import { OpenViduEdition } from '../../models/openvidu.model';
|
||||||
})
|
})
|
||||||
export class OpenViduService {
|
export class OpenViduService {
|
||||||
private ovEdition: OpenViduEdition;
|
private ovEdition: OpenViduEdition;
|
||||||
protected OV: OpenVidu = null;
|
protected OV: OpenVidu;
|
||||||
protected OVScreen: OpenVidu = null;
|
protected OVScreen: OpenVidu;
|
||||||
protected webcamSession: Session = null;
|
protected webcamSession: Session;
|
||||||
protected screenSession: Session = null;
|
protected screenSession: Session;
|
||||||
protected videoSource = undefined;
|
protected videoSource = undefined;
|
||||||
protected audioSource = undefined;
|
protected audioSource = undefined;
|
||||||
protected log: ILogger;
|
protected log: ILogger;
|
||||||
|
@ -166,14 +166,14 @@ export class OpenViduService {
|
||||||
* @internal
|
* @internal
|
||||||
* Initialize a publisher checking devices saved on storage or if participant have devices available.
|
* 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 hasVideoDevices = this.deviceService.hasVideoDeviceAvailable();
|
||||||
const hasAudioDevices = this.deviceService.hasAudioDeviceAvailable();
|
const hasAudioDevices = this.deviceService.hasAudioDeviceAvailable();
|
||||||
const isVideoActive = !this.deviceService.isVideoMuted();
|
const isVideoActive = !this.deviceService.isVideoMuted();
|
||||||
const isAudioActive = !this.deviceService.isAudioMuted();
|
const isAudioActive = !this.deviceService.isAudioMuted();
|
||||||
|
|
||||||
let videoSource = null;
|
let videoSource: string | boolean = false;
|
||||||
let audioSource = null;
|
let audioSource: string | boolean = false;
|
||||||
|
|
||||||
if (hasVideoDevices) {
|
if (hasVideoDevices) {
|
||||||
// Video is active, assign the device selected
|
// Video is active, assign the device selected
|
||||||
|
@ -200,7 +200,7 @@ export class OpenViduService {
|
||||||
mirror
|
mirror
|
||||||
};
|
};
|
||||||
if (hasVideoDevices || hasAudioDevices) {
|
if (hasVideoDevices || hasAudioDevices) {
|
||||||
const publisher = await this.initPublisher(targetElement, properties);
|
const publisher = await this.initPublisher(undefined, properties);
|
||||||
this.participantService.setMyCameraPublisher(publisher);
|
this.participantService.setMyCameraPublisher(publisher);
|
||||||
this.participantService.updateLocalParticipant();
|
this.participantService.updateLocalParticipant();
|
||||||
return publisher;
|
return publisher;
|
||||||
|
@ -325,7 +325,7 @@ export class OpenViduService {
|
||||||
|
|
||||||
const properties: PublisherProperties = {
|
const properties: PublisherProperties = {
|
||||||
videoSource: ScreenType.SCREEN,
|
videoSource: ScreenType.SCREEN,
|
||||||
audioSource: hasAudioDevicesAvailable ? this.deviceService.getMicrophoneSelected().device : null,
|
audioSource: hasAudioDevicesAvailable ? this.deviceService.getMicrophoneSelected().device : false,
|
||||||
publishVideo: true,
|
publishVideo: true,
|
||||||
publishAudio: hasAudio,
|
publishAudio: hasAudio,
|
||||||
mirror: false
|
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> {
|
private async createMediaStream(pp: PublisherProperties): Promise<MediaStream> {
|
||||||
let mediaStream: MediaStream;
|
let mediaStream: MediaStream;
|
||||||
const isFirefoxPlatform = this.platformService.isFirefox();
|
const isFirefoxPlatform = this.platformService.isFirefox();
|
||||||
|
|
Loading…
Reference in New Issue