Skip to content

Instantly share code, notes, and snippets.

@Dhaiwat10
Created November 3, 2021 03:17
Show Gist options
  • Save Dhaiwat10/ffda13b29edc250dcfdaaf94e3ff985e to your computer and use it in GitHub Desktop.
Save Dhaiwat10/ffda13b29edc250dcfdaaf94e3ff985e to your computer and use it in GitHub Desktop.
AgoraRTC TypeScript implementation
import AgoraRTC, {
IAgoraRTCClient,
IAgoraRTCRemoteUser,
ILocalAudioTrack,
ILocalVideoTrack,
IMicrophoneAudioTrack,
} from 'agora-rtc-sdk-ng';
import { RtcTokenBuilder, RtcRole } from 'agora-access-token';
const REMOTE_USER_OFFSET = 10000;
const ACTIVE_STREAM_CLASSNAME = 'agora-active-stream';
class Stream {
selfMuted: boolean;
joined: boolean;
client: IAgoraRTCClient;
screenClient: IAgoraRTCClient;
appId: string;
appCertificate: string;
channelId: string;
token: string;
userId: number;
localAudioTrack: IMicrophoneAudioTrack | null = null;
localVideoTrack: ILocalVideoTrack | null = null;
localScreenTrack:
| ILocalVideoTrack
| [ILocalVideoTrack, ILocalAudioTrack]
| null = null;
activeStreamId: string | null = null;
constructor(
appId: string,
appCertificate: string,
channelId: string,
userId: number,
token: string
) {
this.selfMuted = false;
this.joined = false;
this.appId = appId;
this.appCertificate = appCertificate;
this.channelId = channelId;
this.userId = userId;
this.token = token;
this.client = AgoraRTC.createClient({ mode: 'rtc', codec: 'vp8' });
this.screenClient = AgoraRTC.createClient({ mode: 'rtc', codec: 'vp8' });
this.client.on('user-published', this.onUserPublished);
this.client.on('user-unpublished', this.onUserUnpublished);
}
join = async () => {
this.joined = true;
await this.client.join(this.appId, this.channelId, this.token, this.userId);
this.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack();
this.localVideoTrack = await AgoraRTC.createCameraVideoTrack();
await this.client.publish([this.localAudioTrack, this.localVideoTrack]);
console.log('Logging client after publishing', this.client);
const localPlayerContainer = document.createElement('div');
localPlayerContainer.id = this.userId.toString();
localPlayerContainer.style.width = '20vw';
localPlayerContainer.style.height = '11.25vw';
localPlayerContainer.addEventListener('click', () => {
this.changeActiveStream(localPlayerContainer.id);
});
document
.getElementsByClassName('agora-streams')[0]
.append(localPlayerContainer);
this.localVideoTrack.play(localPlayerContainer);
};
leave = async () => {
this.joined = false;
this.localAudioTrack?.close();
this.localVideoTrack?.close();
const localPlayerContainer = document.getElementById(
this.userId.toString()
);
localPlayerContainer && localPlayerContainer.remove();
this.client.remoteUsers.forEach((user) => {
const playerContainer = document.getElementById(user.uid.toString());
playerContainer && playerContainer.remove();
});
await this.client.leave();
};
onUserPublished = async (
user: IAgoraRTCRemoteUser,
mediaType: 'video' | 'audio'
) => {
await this.client.subscribe(user, mediaType);
if (mediaType === 'video') {
const remoteVideoTrack = user.videoTrack;
const remotePlayerContainer = document.createElement('div');
remotePlayerContainer.id = user.uid.toString();
remotePlayerContainer.addEventListener('click', () => {
this.changeActiveStream(remotePlayerContainer.id);
});
remotePlayerContainer.style.width = '20vw';
remotePlayerContainer.style.height = '11.25vw';
document
.getElementsByClassName('agora-streams')[0]
.append(remotePlayerContainer);
remoteVideoTrack!.play(remotePlayerContainer);
}
if (mediaType === 'audio') {
const remoteAudioTrack = user.audioTrack;
remoteAudioTrack!.play();
}
};
startScreenShare = async () => {
const newUserId = +this.userId + REMOTE_USER_OFFSET;
const screenToken = generateToken(
this.appId,
this.appCertificate,
this.channelId,
newUserId
);
await this.screenClient.join(
this.appId,
this.channelId,
screenToken,
newUserId
);
const screenTrack = await AgoraRTC.createScreenVideoTrack(
{
encoderConfig: '1080p_1',
},
'auto'
);
this.localScreenTrack = screenTrack;
await this.screenClient.publish(screenTrack);
return screenTrack;
};
stopScreenShare = async () => {
await this.screenClient.unpublish(this.localScreenTrack!);
if (Array.isArray(this.localScreenTrack)) {
this.localScreenTrack[0]?.close();
} else {
this.localScreenTrack?.close();
}
const screenElement = document.getElementById(
(this.userId + REMOTE_USER_OFFSET).toString()
);
screenElement && screenElement?.remove();
await this.screenClient.leave();
// this.screenAudioTrack?.close();
// this.screenVideoTrack?.close();
};
onUserUnpublished = (user: IAgoraRTCRemoteUser) => {
const remotePlayerContainer = document.getElementById(user.uid.toString());
remotePlayerContainer && remotePlayerContainer.remove();
};
toggleMuteSelf = () => {
this.localAudioTrack?.setVolume(this.selfMuted ? 100 : 0);
this.selfMuted = !this.selfMuted;
};
changeActiveStream = (id: string) => {
const currentActiveStream = document.getElementsByClassName(
ACTIVE_STREAM_CLASSNAME
)[0];
currentActiveStream?.classList.remove(ACTIVE_STREAM_CLASSNAME);
if (this.activeStreamId !== id) {
const newActiveStream = document.getElementById(id);
newActiveStream?.classList.add(ACTIVE_STREAM_CLASSNAME);
this.activeStreamId = id;
} else {
this.activeStreamId = null;
}
};
}
const generateToken = (
appId: string,
appCertificate: string,
roomId: string,
userId: number
) => {
const currentTimestamp = Math.floor(Date.now() / 1000);
const expirationTimeInSeconds = 3600;
const privilegeExpiredTs = currentTimestamp + expirationTimeInSeconds;
try {
const token = RtcTokenBuilder.buildTokenWithUid(
appId,
appCertificate,
roomId,
userId,
RtcRole.PUBLISHER,
privilegeExpiredTs
);
return token;
} catch (error) {
console.log(error);
return null;
}
};
export { Stream, generateToken };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment