openvidu-components: Support screen audio

Now screen is always visible and independent of the camera connection. It has its own audio
pull/819/head
Carlos Santos 2023-09-18 11:27:56 +02:00
parent 93e48ce139
commit 287ec58bab
5 changed files with 17 additions and 126 deletions

View File

@ -1301,7 +1301,7 @@ describe('Testing screenshare features', () => {
}); });
it('should show only screen if toggle screensharing with video muted', async () => { it('should show the screen although toggle screensharing with video muted', async () => {
await browser.get(`${url}&prejoin=false`); await browser.get(`${url}&prejoin=false`);
await utils.checkLayoutPresent(); await utils.checkLayoutPresent();
@ -1317,7 +1317,7 @@ describe('Testing screenshare features', () => {
await browser.sleep(1000); await browser.sleep(1000);
await utils.waitForElement('.OV_big'); await utils.waitForElement('.OV_big');
expect(await utils.getNumberOfElements('video')).equals(1); expect(await utils.getNumberOfElements('video')).equals(2);
await screenshareButton.click(); await screenshareButton.click();
@ -1352,7 +1352,7 @@ describe('Testing screenshare features', () => {
expect(isAudioEnabled).to.be.false; expect(isAudioEnabled).to.be.false;
await utils.waitForElement('#statusMic'); await utils.waitForElement('#statusMic');
expect(await utils.getNumberOfElements('#statusMic')).equals(2); expect(await utils.getNumberOfElements('#statusMic')).equals(1);
// Clicking to screensharing button // Clicking to screensharing button
await screenshareButton.click(); await screenshareButton.click();
@ -1360,7 +1360,7 @@ describe('Testing screenshare features', () => {
}); });
it('should show and hide CAMERA stream when muting video with screensharing', async () => { it('should show CAMERA stream always visible when muting video with screensharing', async () => {
await browser.get(`${url}&prejoin=false`); await browser.get(`${url}&prejoin=false`);
await utils.checkLayoutPresent(); await utils.checkLayoutPresent();
@ -1376,10 +1376,10 @@ describe('Testing screenshare features', () => {
const muteVideoButton = await utils.waitForElement('#camera-btn'); const muteVideoButton = await utils.waitForElement('#camera-btn');
await muteVideoButton.click(); await muteVideoButton.click();
expect(await utils.getNumberOfElements('video')).equals(1); expect(await utils.getNumberOfElements('video')).equals(2);
}); });
it('should screenshare has audio active when camera is muted', async () => { it('should screen audio be independent of camera audio', async () => {
let isAudioEnabled; let isAudioEnabled;
const audioEnableScript = 'return document.getElementsByTagName("video")[0].srcObject.getAudioTracks()[0].enabled;'; const audioEnableScript = 'return document.getElementsByTagName("video")[0].srcObject.getAudioTracks()[0].enabled;';
@ -1394,13 +1394,13 @@ describe('Testing screenshare features', () => {
await utils.waitForElement('.OV_big'); await utils.waitForElement('.OV_big');
expect(await utils.getNumberOfElements('video')).equals(2); expect(await utils.getNumberOfElements('video')).equals(2);
expect(await utils.getNumberOfElements('#statusMic')).equals(1); expect(await utils.getNumberOfElements('#statusMic')).equals(0);
// Muting camera video // Muting camera video
const muteVideoButton = await utils.waitForElement('#camera-btn'); const muteVideoButton = await utils.waitForElement('#camera-btn');
await muteVideoButton.click(); await muteVideoButton.click();
expect(await utils.getNumberOfElements('video')).equals(1); expect(await utils.getNumberOfElements('video')).equals(2);
await browser.sleep(500); await browser.sleep(500);
expect(await utils.isPresent('#statusMic')).to.be.false; expect(await utils.isPresent('#statusMic')).to.be.false;
@ -1415,63 +1415,9 @@ describe('Testing screenshare features', () => {
await utils.waitForElement('.camera-type'); await utils.waitForElement('.camera-type');
expect(await utils.getNumberOfElements('video')).equals(2); expect(await utils.getNumberOfElements('video')).equals(2);
expect(await utils.getNumberOfElements('#statusMic')).equals(1); expect(await utils.getNumberOfElements('#statusMic')).equals(0);
}); });
it('should camera come back with audio muted when screensharing', async () => {
let element, isAudioEnabled;
const getAudioScript = (className: string) => {
return `return document.getElementsByClassName('${className}')[0].srcObject.getAudioTracks()[0].enabled;`;
};
await browser.get(`${url}&prejoin=false`);
await utils.checkLayoutPresent();
// Clicking to screensharing button
const screenshareButton = await utils.waitForElement('#screenshare-btn');
await screenshareButton.click();
await utils.waitForElement('.screen-type');
expect(await utils.getNumberOfElements('video')).equals(2);
expect(await utils.getNumberOfElements('#statusMic')).equals(1);
// Mute camera
const muteVideoButton = await utils.waitForElement('#camera-btn');
await muteVideoButton.click();
expect(await utils.getNumberOfElements('video')).equals(1);
expect(await utils.isPresent('#statusMic')).to.be.false;
// Checking if audio is muted after join the room
isAudioEnabled = await browser.executeScript(getAudioScript('screen-type'));
expect(isAudioEnabled).to.be.true;
// Mute audio
const muteAudioButton = await utils.waitForElement('#mic-btn');
await muteAudioButton.click();
await utils.waitForElement('#statusMic');
expect(await utils.getNumberOfElements('#statusMic')).equals(1);
isAudioEnabled = await browser.executeScript(getAudioScript('screen-type'));
expect(isAudioEnabled).to.be.false;
// Unmute camera
await muteVideoButton.click();
await utils.waitForElement('.camera-type');
expect(await utils.getNumberOfElements('video')).equals(2);
expect(await utils.getNumberOfElements('#statusMic')).equals(2);
isAudioEnabled = await browser.executeScript(getAudioScript('camera-type'));
expect(isAudioEnabled).to.be.false;
});
}); });
describe('Testing panels', () => { describe('Testing panels', () => {

View File

@ -536,7 +536,7 @@ export class ToolbarComponent implements OnInit, OnDestroy, AfterViewInit {
this.onScreenshareButtonClicked.emit(); this.onScreenshareButtonClicked.emit();
try { try {
await this.openviduService.toggleScreenshare(); await this.participantService.toggleScreenshare();
} catch (error) { } catch (error) {
this.log.e('There was an error toggling screen share', error.code, error.message); this.log.e('There was an error toggling screen share', error.code, error.message);
if (error && error.name === 'SCREEN_SHARING_NOT_SUPPORTED') { if (error && error.name === 'SCREEN_SHARING_NOT_SUPPORTED') {

View File

@ -326,14 +326,13 @@ export class OpenViduService {
* @param hasAudio * @param hasAudio
* @returns * @returns
*/ */
initScreenPublisher(hasAudio: boolean): Promise<Publisher> { initScreenPublisher(): Promise<Publisher> {
const hasAudioDevicesAvailable = this.deviceService.hasAudioDeviceAvailable();
const properties: PublisherProperties = { const properties: PublisherProperties = {
videoSource: ScreenType.SCREEN, videoSource: ScreenType.SCREEN,
audioSource: hasAudioDevicesAvailable ? this.deviceService.getMicrophoneSelected().device : false, audioSource: true,
publishVideo: true, publishVideo: true,
publishAudio: hasAudio && hasAudioDevicesAvailable, publishAudio: true,
mirror: false mirror: false
}; };
return this.initPublisher(properties); return this.initPublisher(properties);

View File

@ -71,32 +71,9 @@ export class ParticipantService {
* *
*/ */
async publishVideo(publish: boolean): Promise<void> { async publishVideo(publish: boolean): Promise<void> {
const publishAudio = this.isMyAudioActive();
const cameraPublisher = this.getMyCameraPublisher(); const cameraPublisher = this.getMyCameraPublisher();
const screenPublisher = this.getMyScreenPublisher();
// Disabling webcam
if (this.localParticipant.hasCameraAndScreenActives()) {
await this.publishVideoAux(cameraPublisher, publish); await this.publishVideoAux(cameraPublisher, publish);
this.disableWebcamStream();
this.openviduService.unpublishCamera(cameraPublisher);
this.publishAudioAux(screenPublisher, publishAudio);
} else if (this.localParticipant.hasOnlyScreenActive()) {
// Enabling webcam
const hasAudio = this.hasScreenAudioActive();
const sessionId = await this.openviduService.connectWebcamSession(this.getMyNickname(), this.getLocalParticipant().id);
if (sessionId) this.setMyCameraConnectionId(sessionId);
await this.openviduService.publishCamera(cameraPublisher);
await this.publishVideoAux(cameraPublisher, true);
this.publishAudioAux(screenPublisher, false);
this.publishAudioAux(cameraPublisher, hasAudio);
this.enableWebcamStream();
} else {
// Muting/unmuting webcam
await this.publishVideoAux(cameraPublisher, publish);
}
this.updateLocalParticipant(); this.updateLocalParticipant();
} }
/** /**
@ -106,16 +83,10 @@ export class ParticipantService {
*/ */
publishAudio(publish: boolean): void { publishAudio(publish: boolean): void {
if (this.isMyCameraActive()) { if (this.isMyCameraActive()) {
if (this.localParticipant.isScreenActive() && this.hasScreenAudioActive()) {
this.publishAudioAux(this.getMyScreenPublisher(), false);
}
this.publishAudioAux(this.getMyCameraPublisher(), publish); this.publishAudioAux(this.getMyCameraPublisher(), publish);
} else {
this.publishAudioAux(this.getMyScreenPublisher(), publish);
}
this.updateLocalParticipant(); this.updateLocalParticipant();
} }
}
/** /**
* Share or unshare the local participant screen. * Share or unshare the local participant screen.
@ -125,7 +96,6 @@ export class ParticipantService {
async toggleScreenshare() { async toggleScreenshare() {
const screenPublisher = this.getMyScreenPublisher(); const screenPublisher = this.getMyScreenPublisher();
const cameraPublisher = this.getMyCameraPublisher();
const participantNickname = this.getMyNickname(); const participantNickname = this.getMyNickname();
const participantId = this.getLocalParticipant().id; const participantId = this.getLocalParticipant().id;
@ -136,9 +106,7 @@ export class ParticipantService {
this.openviduService.unpublishScreen(screenPublisher); this.openviduService.unpublishScreen(screenPublisher);
} else if (this.localParticipant.hasOnlyCameraActive()) { } else if (this.localParticipant.hasOnlyCameraActive()) {
// I only have the camera published // I only have the camera published
const willWebcamBePresent = this.isMyCameraActive() && this.isMyVideoActive(); const screenPublisher = await this.openviduService.initScreenPublisher();
const hasAudio = willWebcamBePresent ? false : this.isMyAudioActive();
const screenPublisher = await this.openviduService.initScreenPublisher(hasAudio);
screenPublisher.once('accessAllowed', async () => { screenPublisher.once('accessAllowed', async () => {
// Listen to event fired when native stop button is clicked // Listen to event fired when native stop button is clicked
@ -157,33 +125,11 @@ export class ParticipantService {
await this.openviduService.connectScreenSession(participantId, participantNickname); await this.openviduService.connectScreenSession(participantId, participantNickname);
} }
await this.openviduService.publishScreen(screenPublisher); await this.openviduService.publishScreen(screenPublisher);
if (!this.isMyVideoActive()) {
// Disabling webcam
this.disableWebcamStream();
this.updateLocalParticipant();
this.openviduService.unpublishCamera(cameraPublisher);
}
}); });
screenPublisher.once('accessDenied', (error: any) => { screenPublisher.once('accessDenied', (error: any) => {
return Promise.reject(error); return Promise.reject(error);
}); });
} else {
// I only have my screenshare active and I have no camera or it is muted
const hasAudio = this.hasScreenAudioActive();
// Enable webcam
if (!this.openviduService.isWebcamSessionConnected()) {
await this.openviduService.connectWebcamSession(participantId, participantNickname);
}
await this.openviduService.publishCamera(cameraPublisher);
this.publishAudioAux(cameraPublisher, hasAudio);
this.enableWebcamStream();
// Disabling screenshare
this.disableScreenStream();
this.updateLocalParticipant();
this.openviduService.unpublishScreen(screenPublisher);
} }
} }

View File

@ -58,7 +58,7 @@
(onNodeCrashed)="onNodeCrashed()" (onNodeCrashed)="onNodeCrashed()"
(onLangChanged)="onLangChanged($event)" (onLangChanged)="onLangChanged($event)"
> >
<div *ovActivitiesPanel>{{ 'CUSTOM.BUTTON' | translate }}</div> <!-- <div *ovActivitiesPanel>{{ 'CUSTOM.BUTTON' | translate }}</div> -->
<!-- <ov-toolbar *ovToolbar [activitiesPanelButton]="false" <!-- <ov-toolbar *ovToolbar [activitiesPanelButton]="false"
[chatPanelButton]="false"></ov-toolbar> --> [chatPanelButton]="false"></ov-toolbar> -->