Skip to content

Instantly share code, notes, and snippets.

@tavoohoh
Last active May 21, 2024 20:52
Show Gist options
  • Save tavoohoh/77c8f4382f3f48d8c1163391dd7df257 to your computer and use it in GitHub Desktop.
Save tavoohoh/77c8f4382f3f48d8c1163391dd7df257 to your computer and use it in GitHub Desktop.
Zoom video
public SessionController = {
join: async () => {
const instance = Store.instance;
instance.loaders = {
...instance.loaders,
join: true,
};
const client = Client.get();
await client.init('en-US', 'Global', {
patchJsMedia: true,
enforceMultipleVideos: true,
enforceVirtualBackground: false,
});
await client.join(
instance.session.topic,
instance.session.token,
instance.session.username,
instance.session.password,
);
Stream.create();
Participants.create();
instance.sessionJoined = true;
instance.clientUserId = client.getCurrentUserInfo().userId;
await instance.AudioController.startAudio();
await instance.VideoController.startVideo();
instance.loaders = {
...instance.loaders,
join: false,
};
instance.SessionController.listeners();
},
leave: async () => {
const instance = Store.instance;
await instance.AudioController.disableAudio();
await instance.VideoController.stopVideo();
instance.VideoController.destroyVideoWithCanvas();
await Client.destroy();
instance.sessionJoined = false;
instance.showControls = false;
},
listeners: () => {
const instance = Store.instance;
const client = Client.get();
client.on('video-active-change', (payload) => {
console.log('video-active-change', payload);
});
client.on('passively-stop-share', () => {
instance.toggleScreen();
});
client.on('user-added', (payload) =>
instance.SessionController.updateParticipants('user-added', payload),
);
client.on('user-removed', (payload) =>
instance.SessionController.updateParticipants('user-removed', payload),
);
client.on('peer-video-state-change', (payload) => {
instance.SessionController.updateParticipants('peer-video-state-change', payload);
instance.emit('set-video-layout');
});
client.on('connection-change', (payload) => {
console.debug('Connection change', payload);
if (payload.state === 'Closed') {
console.info(
'Session ended by the host or the SDK kicked the user',
payload.reason,
);
} else if (payload.state === 'Reconnecting') {
console.info(
'The client side has lost connection with the server. Reconnecting...',
);
} else if (payload.state === 'Connected') {
console.info(
'The client side has reconnected with the server. Reconnected!',
);
} else if (payload.state === 'Fail') {
console.info(
'The client side has failed to reconnect with the server. Failed to reconnect!',
);
}
});
}
}
public VideoController = {
startVideo: async () => {
const instance = Store.instance;
const stream = Stream.get();
if (instance.media.camera) {
await stream.startVideo({ mirrored: true });
}
instance.emit('set-video-layout');
},
stopVideo: async () => {
const instance = Store.instance;
const stream = Stream.get();
await stream.stopVideo();
instance.emit('set-video-layout');
}
}
connectedCallback() {
super.connectedCallback();
this.store.events('set-video-layout', async () => {
setTimeout(async() => {
await this.renderLayout();
}, 10);
window.addEventListener('resize', this.renderLayout.bind(this));
});
this.store.events('toggle-screen', async () => {
await this.handleToggleScreen();
});
}
async renderLayout() {
const client = Client.get();
const stream = Stream.get();
const usersWithVideo = client.getAllUser();
const mockVideos = localStorage.getItem('mockVideosCount');
if (mockVideos) {
for (let i = 0; i < parseInt(mockVideos); i++) {
usersWithVideo[0]['isMock'] = true;
usersWithVideo.push(usersWithVideo[0]);
}
}
this.videoPlayerContainer.value.innerHTML = '';
this.videoPlayerContainer.value.className = this.getVideoLayoutClassName(usersWithVideo.length);
const videoHeight = this.getVideoHeight(usersWithVideo.length);
const videoWidth = this.getVideoWidth(usersWithVideo.length);
for (const user of usersWithVideo) {
if (user.bVideoOn) {
const video = await stream.attachVideo(
user.userId,
2
) as VideoPlayer;
video.className = 'video-player';
video.style['height'] = videoHeight;
video.style['width'] = videoWidth;
video.style['overflow'] = 'hidden';
video.style['background'] = 'black';
video.style['aspect-ratio'] = '1';
const mask = document.createElement('div');
mask.className = 'video-player-mask';
mask.innerHTML = `
<div class="video-player-name">${user.displayName}</div>
`;
mask.appendChild(video as VideoPlayer);
this.videoPlayerContainer.value.appendChild(mask);
} else {
const placeholder = document.createElement('div');
placeholder.className = 'video-player video-placeholder';
const digit = user.userId.toString()[user.userId.toString().length - 1];
const color = COLORS[digit];
placeholder.innerHTML = `
<div class="video-placeholder-name" style="background-color: ${color}">
${user.displayName[0].toUpperCase()}
</div>
`;
this.videoPlayerContainer.value.appendChild(placeholder);
}
}
}
private getVideoLayoutClassName(count: number): string {
return `layout layout-${count}`
}
private getVideoHeight(layout: number): string {
switch (layout) {
case 1:
case 2:
return `${this.meetLayoutContent.value.clientHeight}px`;
default:
return `${(this.meetLayoutContent.value.clientHeight / 2) - GAP}px`;
}
}
private getVideoWidth(layout: number): string {
switch (layout) {
case 1:
return `${this.videoPlayerContainer.value.clientWidth}px`;
case 2:
case 3:
case 4:
return `${(this.videoPlayerContainer.value.clientWidth / 2) - GAP}px`;
case 5:
case 6:
return `${(this.videoPlayerContainer.value.clientWidth / 3) - GAP}px`;
case 7:
case 8:
default:
return `${(this.videoPlayerContainer.value.clientWidth / 4) - GAP}px`;
}
}
private async stopScreenShare() {
const stream = Stream.get();
try {
await stream.stopShareScreen();
this.screenContainer.value.innerHTML = '';
this.videoPlayerContainer.value.style['grid-column'] = '1 / 3';
this.store.loaders = {
...this.store.loaders,
screen: false,
}
this.store.control = {
...this.store.control,
screen: false,
}
} catch (error) {
console.error('Unable to stop screen share', error);
}
await this.renderLayout();
}
private async handleToggleScreen() {
if (this.store.loaders.screen) {
return;
}
this.store.loaders = {
...this.store.loaders,
screen: true,
}
const stream = Stream.get();
if (this.store.control.screen) {
return await this.stopScreenShare();
}
this.videoPlayerContainer.value.style['grid-column'] = '2';
await this.renderLayout();
const startShare = async (tag: 'video' | 'canvas') => {
const element = document.createElement(tag);
element.id = 'screen-share';
element.style.width = '100%';
element.style.height = 'auto';
this.screenContainer.value.appendChild(element);
console.debug('element was appended');
await stream.startShareScreen(element).catch((error) => {
console.error('Error while starting screen share', error);
this.stopScreenShare();
});
};
const tag = stream.isStartShareScreenWithVideoElement() ? 'video' : 'canvas';
console.debug('start will be called');
await startShare(tag);
this.store.control = {
...this.store.control,
screen: true,
}
this.store.loaders = {
...this.store.loaders,
screen: false,
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment