├── appId.js ├── .DS_Store ├── demo ├── avatars │ ├── male-1.png │ ├── male-2.png │ ├── male-3.png │ ├── male-4.png │ ├── male-5.png │ ├── female-1.png │ ├── female-2.png │ ├── female-3.png │ ├── female-4.png │ └── female-5.png ├── package.json ├── icons │ ├── leave.svg │ ├── mic.svg │ └── mic-off.svg ├── .gitignore ├── public │ └── vite.svg ├── index.html ├── style.css ├── main.js └── package-lock.json ├── images ├── avatars │ ├── brad.png │ ├── male-1.png │ ├── male-2.png │ ├── male-3.png │ ├── male-4.png │ ├── male-5.png │ ├── female-1.png │ ├── female-2.png │ ├── female-3.png │ ├── female-4.png │ └── female-5.png ├── room-preview.png ├── lobby-preview.png └── icons │ ├── leave.svg │ ├── mic.svg │ └── mic-off.svg ├── 7-Displaying-Avatars ├── avatars │ ├── male-1.png │ ├── male-2.png │ ├── male-3.png │ ├── male-4.png │ ├── male-5.png │ ├── female-1.png │ ├── female-2.png │ ├── female-3.png │ ├── female-4.png │ └── female-5.png ├── package.json ├── icons │ ├── leave.svg │ ├── mic.svg │ └── mic-off.svg ├── .gitignore ├── public │ └── vite.svg ├── index.html ├── style.css ├── guide.md └── main.js ├── 1-Basic-Voice-Chat ├── package.json ├── .gitignore ├── icons │ ├── leave.svg │ ├── mic.svg │ └── mic-off.svg ├── index.html ├── public │ └── vite.svg ├── style.css ├── main.js ├── guide.md └── package-lock.json ├── 3-Mic-Mute-Toggle ├── package.json ├── .gitignore ├── icons │ ├── leave.svg │ ├── mic.svg │ └── mic-off.svg ├── index.html ├── public │ └── vite.svg ├── guide.md ├── style.css └── main.js ├── 6-Creating-Rooms ├── package.json ├── .gitignore ├── icons │ ├── leave.svg │ ├── mic.svg │ └── mic-off.svg ├── index.html ├── public │ └── vite.svg ├── style.css ├── guide.md └── main.js ├── 4-RTM-RTC-Integration ├── package.json ├── .gitignore ├── icons │ ├── leave.svg │ ├── mic.svg │ └── mic-off.svg ├── index.html ├── public │ └── vite.svg ├── style.css ├── main.js └── guide.md ├── 5-Displaying-User-Names ├── package.json ├── .gitignore ├── icons │ ├── leave.svg │ ├── mic.svg │ └── mic-off.svg ├── index.html ├── public │ └── vite.svg ├── style.css ├── main.js └── guide.md ├── 2-Active-Speaker-Indicator ├── package.json ├── .gitignore ├── icons │ ├── leave.svg │ ├── mic.svg │ └── mic-off.svg ├── index.html ├── public │ └── vite.svg ├── style.css ├── guide.md └── main.js └── readme.md /appId.js: -------------------------------------------------------------------------------- 1 | const appid = "" 2 | 3 | export default appid; -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/.DS_Store -------------------------------------------------------------------------------- /demo/avatars/male-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/demo/avatars/male-1.png -------------------------------------------------------------------------------- /demo/avatars/male-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/demo/avatars/male-2.png -------------------------------------------------------------------------------- /demo/avatars/male-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/demo/avatars/male-3.png -------------------------------------------------------------------------------- /demo/avatars/male-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/demo/avatars/male-4.png -------------------------------------------------------------------------------- /demo/avatars/male-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/demo/avatars/male-5.png -------------------------------------------------------------------------------- /images/avatars/brad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/images/avatars/brad.png -------------------------------------------------------------------------------- /images/room-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/images/room-preview.png -------------------------------------------------------------------------------- /demo/avatars/female-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/demo/avatars/female-1.png -------------------------------------------------------------------------------- /demo/avatars/female-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/demo/avatars/female-2.png -------------------------------------------------------------------------------- /demo/avatars/female-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/demo/avatars/female-3.png -------------------------------------------------------------------------------- /demo/avatars/female-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/demo/avatars/female-4.png -------------------------------------------------------------------------------- /demo/avatars/female-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/demo/avatars/female-5.png -------------------------------------------------------------------------------- /images/avatars/male-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/images/avatars/male-1.png -------------------------------------------------------------------------------- /images/avatars/male-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/images/avatars/male-2.png -------------------------------------------------------------------------------- /images/avatars/male-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/images/avatars/male-3.png -------------------------------------------------------------------------------- /images/avatars/male-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/images/avatars/male-4.png -------------------------------------------------------------------------------- /images/avatars/male-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/images/avatars/male-5.png -------------------------------------------------------------------------------- /images/lobby-preview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/images/lobby-preview.png -------------------------------------------------------------------------------- /images/avatars/female-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/images/avatars/female-1.png -------------------------------------------------------------------------------- /images/avatars/female-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/images/avatars/female-2.png -------------------------------------------------------------------------------- /images/avatars/female-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/images/avatars/female-3.png -------------------------------------------------------------------------------- /images/avatars/female-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/images/avatars/female-4.png -------------------------------------------------------------------------------- /images/avatars/female-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/images/avatars/female-5.png -------------------------------------------------------------------------------- /7-Displaying-Avatars/avatars/male-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/7-Displaying-Avatars/avatars/male-1.png -------------------------------------------------------------------------------- /7-Displaying-Avatars/avatars/male-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/7-Displaying-Avatars/avatars/male-2.png -------------------------------------------------------------------------------- /7-Displaying-Avatars/avatars/male-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/7-Displaying-Avatars/avatars/male-3.png -------------------------------------------------------------------------------- /7-Displaying-Avatars/avatars/male-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/7-Displaying-Avatars/avatars/male-4.png -------------------------------------------------------------------------------- /7-Displaying-Avatars/avatars/male-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/7-Displaying-Avatars/avatars/male-5.png -------------------------------------------------------------------------------- /7-Displaying-Avatars/avatars/female-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/7-Displaying-Avatars/avatars/female-1.png -------------------------------------------------------------------------------- /7-Displaying-Avatars/avatars/female-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/7-Displaying-Avatars/avatars/female-2.png -------------------------------------------------------------------------------- /7-Displaying-Avatars/avatars/female-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/7-Displaying-Avatars/avatars/female-3.png -------------------------------------------------------------------------------- /7-Displaying-Avatars/avatars/female-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/7-Displaying-Avatars/avatars/female-4.png -------------------------------------------------------------------------------- /7-Displaying-Avatars/avatars/female-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/divanov11/Voice-Chat-Rooms/HEAD/7-Displaying-Avatars/avatars/female-5.png -------------------------------------------------------------------------------- /demo/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "1-basic-voice-chat", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "vite": "^4.0.0" 13 | } 14 | } -------------------------------------------------------------------------------- /1-Basic-Voice-Chat/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "1-basic-voice-chat", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "vite": "^4.0.0" 13 | } 14 | } -------------------------------------------------------------------------------- /3-Mic-Mute-Toggle/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "1-basic-voice-chat", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "vite": "^4.0.0" 13 | } 14 | } -------------------------------------------------------------------------------- /6-Creating-Rooms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "1-basic-voice-chat", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "vite": "^4.0.0" 13 | } 14 | } -------------------------------------------------------------------------------- /4-RTM-RTC-Integration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "1-basic-voice-chat", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "vite": "^4.0.0" 13 | } 14 | } -------------------------------------------------------------------------------- /5-Displaying-User-Names/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "1-basic-voice-chat", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "vite": "^4.0.0" 13 | } 14 | } -------------------------------------------------------------------------------- /7-Displaying-Avatars/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "1-basic-voice-chat", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "vite": "^4.0.0" 13 | } 14 | } -------------------------------------------------------------------------------- /2-Active-Speaker-Indicator/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "1-basic-voice-chat", 3 | "private": true, 4 | "version": "0.0.0", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "devDependencies": { 12 | "vite": "^4.0.0" 13 | } 14 | } -------------------------------------------------------------------------------- /demo/icons/leave.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /images/icons/leave.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /1-Basic-Voice-Chat/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /1-Basic-Voice-Chat/icons/leave.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /3-Mic-Mute-Toggle/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /3-Mic-Mute-Toggle/icons/leave.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /6-Creating-Rooms/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /6-Creating-Rooms/icons/leave.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /7-Displaying-Avatars/icons/leave.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /4-RTM-RTC-Integration/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /4-RTM-RTC-Integration/icons/leave.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /5-Displaying-User-Names/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /5-Displaying-User-Names/icons/leave.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /7-Displaying-Avatars/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /2-Active-Speaker-Indicator/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | 15 | # Editor directories and files 16 | .vscode/* 17 | !.vscode/extensions.json 18 | .idea 19 | .DS_Store 20 | *.suo 21 | *.ntvs* 22 | *.njsproj 23 | *.sln 24 | *.sw? 25 | -------------------------------------------------------------------------------- /2-Active-Speaker-Indicator/icons/leave.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo/icons/mic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/icons/mic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /6-Creating-Rooms/icons/mic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /1-Basic-Voice-Chat/icons/mic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /3-Mic-Mute-Toggle/icons/mic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /4-RTM-RTC-Integration/icons/mic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /7-Displaying-Avatars/icons/mic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /2-Active-Speaker-Indicator/icons/mic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /5-Displaying-User-Names/icons/mic.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /demo/icons/mic-off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /images/icons/mic-off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /6-Creating-Rooms/icons/mic-off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /1-Basic-Voice-Chat/icons/mic-off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /3-Mic-Mute-Toggle/icons/mic-off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /4-RTM-RTC-Integration/icons/mic-off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /7-Displaying-Avatars/icons/mic-off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /2-Active-Speaker-Indicator/icons/mic-off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /5-Displaying-User-Names/icons/mic-off.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Voice Rooms Chat App 2 | 3 | A simple voice chat app using the Agora RTC And RTM Web SDK. 4 | 5 | Watch the complete video course [here!](https://youtu.be/abka2ug0kbs) 6 | 7 | **Room** 8 | 9 | 10 | **Lobby** 11 | 12 | 13 | 14 | ### Installation 15 | 16 | > Ensure you have Node JS installed 17 | 18 | 19 | ``` 20 | git clone https://github.com/divanov11/Voice-Chat-Rooms 21 | 22 | cd Voice-Chat-Rooms/demo 23 | 24 | npm install 25 | ``` 26 | 27 | Add you APP ID Inside of `appid.js` 28 | 29 | > NOTE: Get this from your Agora console when you initiate a new project. 30 | 31 | ```js 32 | //appId.js 33 | const appid = "YOU AGORA APP ID" 34 | 35 | export default appid; 36 | ``` 37 | 38 | Start Development server 39 | 40 | ``` 41 | npm run dev 42 | ``` 43 | 44 | ### Features 45 | - Create/Join breakout rooms 46 | - Active speaker volume indicator 47 | - Display user names and avatars 48 | 49 | -------------------------------------------------------------------------------- /1-Basic-Voice-Chat/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 |
13 | 14 |

15 | 16 |
17 | 18 | 19 |
20 |
21 | 22 |
23 | 24 | 25 |
26 | 27 |
28 | 29 |
30 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /3-Mic-Mute-Toggle/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 |
13 | 14 |

15 | 16 |
17 | 18 | 19 |
20 |
21 | 22 |
23 | 24 | 25 |
26 | 27 |
28 | 29 |
30 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /4-RTM-RTC-Integration/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 |
13 | 14 |

15 | 16 |
17 | 18 | 19 |
20 |
21 | 22 |
23 | 24 | 25 |
26 | 27 |
28 | 29 |
30 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /5-Displaying-User-Names/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 |
13 | 14 |

15 | 16 |
17 | 18 | 19 |
20 |
21 | 22 |
23 | 24 | 25 |
26 | 27 |
28 | 29 |
30 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /2-Active-Speaker-Indicator/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 |
13 | 14 |

15 | 16 |
17 | 18 | 19 |
20 |
21 | 22 |
23 | 24 | 25 |
26 | 27 |
28 | 29 |
30 |
31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /6-Creating-Rooms/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 |
13 | 14 |

15 | 16 |
17 | 18 | 19 |
20 |
21 | 22 |
23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
32 |
33 | 34 |
35 | 36 |
37 |
38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /demo/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /1-Basic-Voice-Chat/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /3-Mic-Mute-Toggle/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /6-Creating-Rooms/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /7-Displaying-Avatars/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /4-RTM-RTC-Integration/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /5-Displaying-User-Names/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /2-Active-Speaker-Indicator/public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /3-Mic-Mute-Toggle/guide.md: -------------------------------------------------------------------------------- 1 | # Mic Mute Toggle 2 | 3 | Adding the ability to toggle mute and unmute during a conversation. 4 | 5 | 6 | ### Toggle Mic Method 7 | 8 | Before getting started we want to add an initial state to our mic. 9 | 10 | **Mic Initial State** 11 | 12 | At the top of our `main.js` file create a variable for our mic state and set it to `true`, as in the mic is muted. 13 | 14 | ```js 15 | let micMuted = true 16 | ``` 17 | 18 | To set the initial state for the mic let's add the following inside of the `initRtc` method, just underneath the `createMicrophoneAudioTrack`. This will ensure that our mic is off when we first join a room: 19 | 20 | ```js 21 | const initRtc = async () => { 22 | //.. 23 | //audioTracks.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack(); 24 | audioTracks.localAudioTrack.setMuted(micMuted) 25 | //.. 26 | } 27 | ``` 28 | 29 | **Toggle Mic Method** 30 | 31 | This method will toggle our mic, our mic state, and the mic icon to show an active/inactive state. 32 | 33 | The logic here is simple: 34 | 35 | - When this method is triggered, if the mic is muted, update the mic icon image and color, change the state to reflect the opposite status, then call the `setMuted()` method. 36 | 37 | `setMuted` takes the value of either true or false and changes the status of our audio. 38 | 39 | We also want to add an event handler to trigger this function. 40 | 41 | 42 | ```js 43 | const toggleMic = async (e) => { 44 | if (micMuted){ 45 | e.target.src = 'icons/mic.svg' 46 | e.target.style.backgroundColor = 'ivory' 47 | micMuted = false 48 | }else{ 49 | e.target.src = 'icons/mic-off.svg' 50 | e.target.style.backgroundColor = 'indianred' 51 | 52 | micMuted = true 53 | } 54 | audioTracks.localAudioTrack.setMuted(micMuted) 55 | } 56 | 57 | document.getElementById('mic-icon').addEventListener('click', toggleMic) 58 | ``` 59 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 |
13 | 14 |

15 | 16 |
17 | 18 | 19 |
20 |
21 | 22 |
23 |
24 |

Select An Avatar:

25 |
26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 | 38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
47 |
48 | 49 |
50 | 51 |
52 |
53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /7-Displaying-Avatars/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite App 8 | 9 | 10 |
11 | 12 |
13 | 14 |

15 | 16 |
17 | 18 | 19 |
20 |
21 | 22 |
23 |
24 |

Select An Avatar:

25 |
26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 | 38 |
39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
47 |
48 | 49 |
50 | 51 |
52 |
53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /1-Basic-Voice-Chat/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap'); 2 | 3 | :root { 4 | font-family: 'Roboto', sans-serif; 5 | font-size: 16px; 6 | color-scheme: dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | } 10 | 11 | a { 12 | color: #646cff; 13 | text-decoration: none; 14 | } 15 | a:hover { 16 | color: #535bf2; 17 | } 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | #container{ 24 | max-width: 800px; 25 | margin: 0 auto; 26 | padding: 1em; 27 | } 28 | 29 | #room-header{ 30 | justify-content: space-between; 31 | align-items: center; 32 | padding: 1em 0; 33 | display: none; 34 | } 35 | 36 | #room-header-controls{ 37 | display: flex; 38 | } 39 | 40 | #room-header-controls > img { 41 | margin: 0 2px; 42 | } 43 | 44 | .control-icon{ 45 | background-color: indianred; 46 | border: none; 47 | padding: 0.5em; 48 | height: 20px; 49 | cursor: pointer; 50 | border-radius: 5px; 51 | } 52 | 53 | 54 | 55 | #members{ 56 | display: flex; 57 | flex-wrap: wrap; 58 | } 59 | 60 | .speaker{ 61 | border:2px solid #fff; 62 | display: flex; 63 | flex-direction: column; 64 | align-items: center; 65 | width: 120px; 66 | text-align: center; 67 | margin: 0.5em; 68 | } 69 | 70 | #avatars{ 71 | display: flex; 72 | flex-wrap: wrap; 73 | margin: 1em 0; 74 | } 75 | 76 | .avatar-selection{ 77 | height: 50px; 78 | width: 50px; 79 | object-fit: contain; 80 | border: 2px solid #FFF; 81 | border-radius: 50%; 82 | opacity: .5; 83 | cursor: pointer; 84 | margin: 0.25em; 85 | } 86 | 87 | .user-avatar{ 88 | height: 75px; 89 | width: 75px; 90 | object-fit: contain; 91 | border: 2px solid #FFF; 92 | border-radius: 50%; 93 | } 94 | 95 | #form input{ 96 | width: 100%; 97 | padding: 1em; 98 | margin-bottom:2em; 99 | box-sizing: border-box; 100 | } 101 | 102 | #form label{ 103 | margin-bottom: 0.5em; 104 | } 105 | 106 | #form-fields{ 107 | display: flex; 108 | flex-direction: column; 109 | } -------------------------------------------------------------------------------- /3-Mic-Mute-Toggle/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap'); 2 | 3 | :root { 4 | font-family: 'Roboto', sans-serif; 5 | font-size: 16px; 6 | color-scheme: dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | } 10 | 11 | a { 12 | color: #646cff; 13 | text-decoration: none; 14 | } 15 | a:hover { 16 | color: #535bf2; 17 | } 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | #container{ 24 | max-width: 800px; 25 | margin: 0 auto; 26 | padding: 1em; 27 | } 28 | 29 | #room-header{ 30 | justify-content: space-between; 31 | align-items: center; 32 | padding: 1em 0; 33 | display: none; 34 | } 35 | 36 | #room-header-controls{ 37 | display: flex; 38 | } 39 | 40 | #room-header-controls > img { 41 | margin: 0 2px; 42 | } 43 | 44 | .control-icon{ 45 | background-color: indianred; 46 | border: none; 47 | padding: 0.5em; 48 | height: 20px; 49 | cursor: pointer; 50 | border-radius: 5px; 51 | } 52 | 53 | 54 | 55 | #members{ 56 | display: flex; 57 | flex-wrap: wrap; 58 | } 59 | 60 | .speaker{ 61 | border:2px solid #fff; 62 | display: flex; 63 | flex-direction: column; 64 | align-items: center; 65 | width: 120px; 66 | text-align: center; 67 | margin: 0.5em; 68 | } 69 | 70 | #avatars{ 71 | display: flex; 72 | flex-wrap: wrap; 73 | margin: 1em 0; 74 | } 75 | 76 | .avatar-selection{ 77 | height: 50px; 78 | width: 50px; 79 | object-fit: contain; 80 | border: 2px solid #FFF; 81 | border-radius: 50%; 82 | opacity: .5; 83 | cursor: pointer; 84 | margin: 0.25em; 85 | } 86 | 87 | .user-avatar{ 88 | height: 75px; 89 | width: 75px; 90 | object-fit: contain; 91 | border: 2px solid #FFF; 92 | border-radius: 50%; 93 | } 94 | 95 | #form input{ 96 | width: 100%; 97 | padding: 1em; 98 | margin-bottom:2em; 99 | box-sizing: border-box; 100 | } 101 | 102 | #form label{ 103 | margin-bottom: 0.5em; 104 | } 105 | 106 | #form-fields{ 107 | display: flex; 108 | flex-direction: column; 109 | } -------------------------------------------------------------------------------- /6-Creating-Rooms/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap'); 2 | 3 | :root { 4 | font-family: 'Roboto', sans-serif; 5 | font-size: 16px; 6 | color-scheme: dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | } 10 | 11 | a { 12 | color: #646cff; 13 | text-decoration: none; 14 | } 15 | a:hover { 16 | color: #535bf2; 17 | } 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | #container{ 24 | max-width: 800px; 25 | margin: 0 auto; 26 | padding: 1em; 27 | } 28 | 29 | #room-header{ 30 | justify-content: space-between; 31 | align-items: center; 32 | padding: 1em 0; 33 | display: none; 34 | } 35 | 36 | #room-header-controls{ 37 | display: flex; 38 | } 39 | 40 | #room-header-controls > img { 41 | margin: 0 2px; 42 | } 43 | 44 | .control-icon{ 45 | background-color: indianred; 46 | border: none; 47 | padding: 0.5em; 48 | height: 20px; 49 | cursor: pointer; 50 | border-radius: 5px; 51 | } 52 | 53 | 54 | 55 | #members{ 56 | display: flex; 57 | flex-wrap: wrap; 58 | } 59 | 60 | .speaker{ 61 | border:2px solid #fff; 62 | display: flex; 63 | flex-direction: column; 64 | align-items: center; 65 | width: 120px; 66 | text-align: center; 67 | margin: 0.5em; 68 | } 69 | 70 | #avatars{ 71 | display: flex; 72 | flex-wrap: wrap; 73 | margin: 1em 0; 74 | } 75 | 76 | .avatar-selection{ 77 | height: 50px; 78 | width: 50px; 79 | object-fit: contain; 80 | border: 2px solid #FFF; 81 | border-radius: 50%; 82 | opacity: .5; 83 | cursor: pointer; 84 | margin: 0.25em; 85 | } 86 | 87 | .user-avatar{ 88 | height: 75px; 89 | width: 75px; 90 | object-fit: contain; 91 | border: 2px solid #FFF; 92 | border-radius: 50%; 93 | } 94 | 95 | #form input{ 96 | width: 100%; 97 | padding: 1em; 98 | margin-bottom:2em; 99 | box-sizing: border-box; 100 | } 101 | 102 | #form label{ 103 | margin-bottom: 0.5em; 104 | } 105 | 106 | #form-fields{ 107 | display: flex; 108 | flex-direction: column; 109 | } -------------------------------------------------------------------------------- /4-RTM-RTC-Integration/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap'); 2 | 3 | :root { 4 | font-family: 'Roboto', sans-serif; 5 | font-size: 16px; 6 | color-scheme: dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | } 10 | 11 | a { 12 | color: #646cff; 13 | text-decoration: none; 14 | } 15 | a:hover { 16 | color: #535bf2; 17 | } 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | #container{ 24 | max-width: 800px; 25 | margin: 0 auto; 26 | padding: 1em; 27 | } 28 | 29 | #room-header{ 30 | justify-content: space-between; 31 | align-items: center; 32 | padding: 1em 0; 33 | display: none; 34 | } 35 | 36 | #room-header-controls{ 37 | display: flex; 38 | } 39 | 40 | #room-header-controls > img { 41 | margin: 0 2px; 42 | } 43 | 44 | .control-icon{ 45 | background-color: indianred; 46 | border: none; 47 | padding: 0.5em; 48 | height: 20px; 49 | cursor: pointer; 50 | border-radius: 5px; 51 | } 52 | 53 | 54 | 55 | #members{ 56 | display: flex; 57 | flex-wrap: wrap; 58 | } 59 | 60 | .speaker{ 61 | border:2px solid #fff; 62 | display: flex; 63 | flex-direction: column; 64 | align-items: center; 65 | width: 120px; 66 | text-align: center; 67 | margin: 0.5em; 68 | } 69 | 70 | #avatars{ 71 | display: flex; 72 | flex-wrap: wrap; 73 | margin: 1em 0; 74 | } 75 | 76 | .avatar-selection{ 77 | height: 50px; 78 | width: 50px; 79 | object-fit: contain; 80 | border: 2px solid #FFF; 81 | border-radius: 50%; 82 | opacity: .5; 83 | cursor: pointer; 84 | margin: 0.25em; 85 | } 86 | 87 | .user-avatar{ 88 | height: 75px; 89 | width: 75px; 90 | object-fit: contain; 91 | border: 2px solid #FFF; 92 | border-radius: 50%; 93 | } 94 | 95 | #form input{ 96 | width: 100%; 97 | padding: 1em; 98 | margin-bottom:2em; 99 | box-sizing: border-box; 100 | } 101 | 102 | #form label{ 103 | margin-bottom: 0.5em; 104 | } 105 | 106 | #form-fields{ 107 | display: flex; 108 | flex-direction: column; 109 | } -------------------------------------------------------------------------------- /5-Displaying-User-Names/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap'); 2 | 3 | :root { 4 | font-family: 'Roboto', sans-serif; 5 | font-size: 16px; 6 | color-scheme: dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | } 10 | 11 | a { 12 | color: #646cff; 13 | text-decoration: none; 14 | } 15 | a:hover { 16 | color: #535bf2; 17 | } 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | #container{ 24 | max-width: 800px; 25 | margin: 0 auto; 26 | padding: 1em; 27 | } 28 | 29 | #room-header{ 30 | justify-content: space-between; 31 | align-items: center; 32 | padding: 1em 0; 33 | display: none; 34 | } 35 | 36 | #room-header-controls{ 37 | display: flex; 38 | } 39 | 40 | #room-header-controls > img { 41 | margin: 0 2px; 42 | } 43 | 44 | .control-icon{ 45 | background-color: indianred; 46 | border: none; 47 | padding: 0.5em; 48 | height: 20px; 49 | cursor: pointer; 50 | border-radius: 5px; 51 | } 52 | 53 | 54 | 55 | #members{ 56 | display: flex; 57 | flex-wrap: wrap; 58 | } 59 | 60 | .speaker{ 61 | border:2px solid #fff; 62 | display: flex; 63 | flex-direction: column; 64 | align-items: center; 65 | width: 120px; 66 | text-align: center; 67 | margin: 0.5em; 68 | } 69 | 70 | #avatars{ 71 | display: flex; 72 | flex-wrap: wrap; 73 | margin: 1em 0; 74 | } 75 | 76 | .avatar-selection{ 77 | height: 50px; 78 | width: 50px; 79 | object-fit: contain; 80 | border: 2px solid #FFF; 81 | border-radius: 50%; 82 | opacity: .5; 83 | cursor: pointer; 84 | margin: 0.25em; 85 | } 86 | 87 | .user-avatar{ 88 | height: 75px; 89 | width: 75px; 90 | object-fit: contain; 91 | border: 2px solid #FFF; 92 | border-radius: 50%; 93 | } 94 | 95 | #form input{ 96 | width: 100%; 97 | padding: 1em; 98 | margin-bottom:2em; 99 | box-sizing: border-box; 100 | } 101 | 102 | #form label{ 103 | margin-bottom: 0.5em; 104 | } 105 | 106 | #form-fields{ 107 | display: flex; 108 | flex-direction: column; 109 | } -------------------------------------------------------------------------------- /2-Active-Speaker-Indicator/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap'); 2 | 3 | :root { 4 | font-family: 'Roboto', sans-serif; 5 | font-size: 16px; 6 | color-scheme: dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | } 10 | 11 | a { 12 | color: #646cff; 13 | text-decoration: none; 14 | } 15 | a:hover { 16 | color: #535bf2; 17 | } 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | #container{ 24 | max-width: 800px; 25 | margin: 0 auto; 26 | padding: 1em; 27 | } 28 | 29 | #room-header{ 30 | justify-content: space-between; 31 | align-items: center; 32 | padding: 1em 0; 33 | display: none; 34 | } 35 | 36 | #room-header-controls{ 37 | display: flex; 38 | } 39 | 40 | #room-header-controls > img { 41 | margin: 0 2px; 42 | } 43 | 44 | .control-icon{ 45 | background-color: indianred; 46 | border: none; 47 | padding: 0.5em; 48 | height: 20px; 49 | cursor: pointer; 50 | border-radius: 5px; 51 | } 52 | 53 | 54 | 55 | #members{ 56 | display: flex; 57 | flex-wrap: wrap; 58 | } 59 | 60 | .speaker{ 61 | border:2px solid #fff; 62 | display: flex; 63 | flex-direction: column; 64 | align-items: center; 65 | width: 120px; 66 | text-align: center; 67 | margin: 0.5em; 68 | } 69 | 70 | #avatars{ 71 | display: flex; 72 | flex-wrap: wrap; 73 | margin: 1em 0; 74 | } 75 | 76 | .avatar-selection{ 77 | height: 50px; 78 | width: 50px; 79 | object-fit: contain; 80 | border: 2px solid #FFF; 81 | border-radius: 50%; 82 | opacity: .5; 83 | cursor: pointer; 84 | margin: 0.25em; 85 | } 86 | 87 | .user-avatar{ 88 | height: 75px; 89 | width: 75px; 90 | object-fit: contain; 91 | border: 2px solid #FFF; 92 | border-radius: 50%; 93 | } 94 | 95 | #form input{ 96 | width: 100%; 97 | padding: 1em; 98 | margin-bottom:2em; 99 | box-sizing: border-box; 100 | } 101 | 102 | #form label{ 103 | margin-bottom: 0.5em; 104 | } 105 | 106 | #form-fields{ 107 | display: flex; 108 | flex-direction: column; 109 | } -------------------------------------------------------------------------------- /demo/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap'); 2 | 3 | :root { 4 | font-family: 'Roboto', sans-serif; 5 | font-size: 16px; 6 | color-scheme: dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | } 10 | 11 | a { 12 | color: #646cff; 13 | text-decoration: none; 14 | } 15 | a:hover { 16 | color: #535bf2; 17 | } 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | #container{ 24 | max-width: 800px; 25 | margin: 0 auto; 26 | padding: 1em; 27 | } 28 | 29 | #room-header{ 30 | justify-content: space-between; 31 | align-items: center; 32 | padding: 1em 0; 33 | display: none; 34 | } 35 | 36 | #room-header-controls{ 37 | display: flex; 38 | } 39 | 40 | #room-header-controls > img { 41 | margin: 0 2px; 42 | } 43 | 44 | .control-icon{ 45 | background-color: indianred; 46 | border: none; 47 | padding: 0.5em; 48 | height: 20px; 49 | cursor: pointer; 50 | border-radius: 5px; 51 | } 52 | 53 | 54 | 55 | #members{ 56 | display: flex; 57 | flex-wrap: wrap; 58 | } 59 | 60 | .speaker{ 61 | /* border:2px solid #fff; 62 | border-radius: 50%; */ 63 | 64 | margin: 0.5em; 65 | display: flex; 66 | flex-direction: column; 67 | align-items: center; 68 | width: 120px; 69 | text-align: center; 70 | } 71 | 72 | #avatars{ 73 | display: flex; 74 | flex-wrap: wrap; 75 | margin: 1em 0; 76 | } 77 | 78 | .avatar-selection{ 79 | height: 50px; 80 | width: 50px; 81 | object-fit: contain; 82 | border: 2px solid #FFF; 83 | border-radius: 50%; 84 | opacity: .5; 85 | cursor: pointer; 86 | margin: 0.25em; 87 | } 88 | 89 | .user-avatar{ 90 | height: 75px; 91 | width: 75px; 92 | object-fit: contain; 93 | border: 2px solid #FFF; 94 | border-radius: 50%; 95 | } 96 | 97 | #form input{ 98 | width: 100%; 99 | padding: 1em; 100 | margin-bottom:2em; 101 | box-sizing: border-box; 102 | } 103 | 104 | #form label{ 105 | margin-bottom: 0.5em; 106 | } 107 | 108 | #form-fields{ 109 | display: flex; 110 | flex-direction: column; 111 | } -------------------------------------------------------------------------------- /7-Displaying-Avatars/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap'); 2 | 3 | :root { 4 | font-family: 'Roboto', sans-serif; 5 | font-size: 16px; 6 | color-scheme: dark; 7 | color: rgba(255, 255, 255, 0.87); 8 | background-color: #242424; 9 | } 10 | 11 | a { 12 | color: #646cff; 13 | text-decoration: none; 14 | } 15 | a:hover { 16 | color: #535bf2; 17 | } 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | #container{ 24 | max-width: 800px; 25 | margin: 0 auto; 26 | padding: 1em; 27 | } 28 | 29 | #room-header{ 30 | justify-content: space-between; 31 | align-items: center; 32 | padding: 1em 0; 33 | display: none; 34 | } 35 | 36 | #room-header-controls{ 37 | display: flex; 38 | } 39 | 40 | #room-header-controls > img { 41 | margin: 0 2px; 42 | } 43 | 44 | .control-icon{ 45 | background-color: indianred; 46 | border: none; 47 | padding: 0.5em; 48 | height: 20px; 49 | cursor: pointer; 50 | border-radius: 5px; 51 | } 52 | 53 | 54 | 55 | #members{ 56 | display: flex; 57 | flex-wrap: wrap; 58 | } 59 | 60 | .speaker{ 61 | /* border:2px solid #fff; 62 | border-radius: 50%; */ 63 | 64 | margin: 0.5em; 65 | display: flex; 66 | flex-direction: column; 67 | align-items: center; 68 | width: 120px; 69 | text-align: center; 70 | } 71 | 72 | #avatars{ 73 | display: flex; 74 | flex-wrap: wrap; 75 | margin: 1em 0; 76 | } 77 | 78 | .avatar-selection{ 79 | height: 50px; 80 | width: 50px; 81 | object-fit: contain; 82 | border: 2px solid #FFF; 83 | border-radius: 50%; 84 | opacity: .5; 85 | cursor: pointer; 86 | margin: 0.25em; 87 | } 88 | 89 | .user-avatar{ 90 | height: 75px; 91 | width: 75px; 92 | object-fit: contain; 93 | border: 2px solid #FFF; 94 | border-radius: 50%; 95 | } 96 | 97 | #form input{ 98 | width: 100%; 99 | padding: 1em; 100 | margin-bottom:2em; 101 | box-sizing: border-box; 102 | } 103 | 104 | #form label{ 105 | margin-bottom: 0.5em; 106 | } 107 | 108 | #form-fields{ 109 | display: flex; 110 | flex-direction: column; 111 | } -------------------------------------------------------------------------------- /1-Basic-Voice-Chat/main.js: -------------------------------------------------------------------------------- 1 | import './style.css' 2 | import AgoraRTC from "agora-rtc-sdk-ng" 3 | 4 | import appid from '../appId.js' 5 | 6 | const token = null 7 | const rtcUid = Math.floor(Math.random() * 2032) 8 | 9 | let roomId = "main" 10 | 11 | let audioTracks = { 12 | localAudioTrack: null, 13 | remoteAudioTracks: {}, 14 | }; 15 | 16 | let rtcClient; 17 | 18 | 19 | const initRtc = async () => { 20 | rtcClient = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" }); 21 | 22 | 23 | rtcClient.on('user-joined', handleUserJoined) 24 | rtcClient.on("user-published", handleUserPublished) 25 | rtcClient.on("user-left", handleUserLeft); 26 | 27 | 28 | await rtcClient.join(appid, roomId, token, rtcUid) 29 | audioTracks.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack(); 30 | await rtcClient.publish(audioTracks.localAudioTrack); 31 | 32 | 33 | document.getElementById('members').insertAdjacentHTML('beforeend', `

${rtcUid}

`) 34 | } 35 | 36 | 37 | let handleUserJoined = async (user) => { 38 | console.log('USER:', user) 39 | document.getElementById('members').insertAdjacentHTML('beforeend', `

${user.uid}

`) 40 | } 41 | 42 | let handleUserPublished = async (user, mediaType) => { 43 | await rtcClient.subscribe(user, mediaType); 44 | 45 | if (mediaType == "audio"){ 46 | audioTracks.remoteAudioTracks[user.uid] = [user.audioTrack] 47 | user.audioTrack.play(); 48 | } 49 | } 50 | 51 | let handleUserLeft = async (user) => { 52 | delete audioTracks.remoteAudioTracks[user.uid] 53 | document.getElementById(user.uid).remove() 54 | } 55 | 56 | 57 | let lobbyForm = document.getElementById('form') 58 | 59 | const enterRoom = async (e) => { 60 | e.preventDefault() 61 | initRtc() 62 | 63 | lobbyForm.style.display = 'none' 64 | document.getElementById('room-header').style.display = "flex" 65 | } 66 | 67 | let leaveRoom = async () => { 68 | audioTracks.localAudioTrack.stop() 69 | audioTracks.localAudioTrack.close() 70 | rtcClient.unpublish() 71 | rtcClient.leave() 72 | 73 | document.getElementById('form').style.display = 'block' 74 | document.getElementById('room-header').style.display = 'none' 75 | document.getElementById('members').innerHTML = '' 76 | } 77 | 78 | lobbyForm.addEventListener('submit', enterRoom) 79 | document.getElementById('leave-icon').addEventListener('click', leaveRoom) 80 | -------------------------------------------------------------------------------- /2-Active-Speaker-Indicator/guide.md: -------------------------------------------------------------------------------- 1 | # Active Speaker Volume Indicator 2 | 3 | Adding active speaker indicators to view who is currently talking in a voice chat room. 4 | 5 | 6 | ### Create and Initialize Volume Indicator 7 | 8 | To add active speaker recognition we have a method called `enableAudioVolumeIndicator` which reports the volume of each user in the channel. This is reported by triggering the `AgoraRTCClient.on("volume-indicator")` call back every two seconds. 9 | 10 | Checking the volume every two seconds is too long of a delay to get an active reading so we will use the `AgoraRTC.setParameter('AUDIO_VOLUME_INDICATION_INTERVAL')` method to customize the callback to trigger every 200ms. This will give us a more accurate reading 11 | 12 | 1. Customize the volume indicator with the `setParameter` method and then enable the indicator with `enableAudioVolumeIndicator`. 13 | 14 | 2. On each callback loop through each volume and console out the volume level and user id to visually see what's happening. What we are looking for is a reading above the resting rate. 15 | 16 | I found that a reading every `200ms` gives me a resting volume at about 30 for anything over 50 means someone is speaking. You should play with these settings and see what works best for you 17 | 18 | 3. Last thing we want to do with this indicator is get the current user's id. Let's find the HTML element that represents them in the dom, and either add a green border to their wrapper or set this back to its original color. 19 | 20 | > NOTE: AgoraRTC.setParameter(...) is part of agoras internal API and not officially documented as the public docs/SDK so you will see a warning when you use it. 21 | 22 | 23 | ```js 24 | let initVolumeIndicator = async () => { 25 | 26 | //1 27 | AgoraRTC.setParameter('AUDIO_VOLUME_INDICATION_INTERVAL', 200); 28 | rtcClient.enableAudioVolumeIndicator(); 29 | 30 | //2 31 | rtcClient.on("volume-indicator", volumes => { 32 | volumes.forEach((volume) => { 33 | console.log(`UID ${volume.uid} Level ${volume.level}`); 34 | 35 | //3 36 | try{ 37 | let item = document.getElementsByClassName(`user-rtc-${volume.uid}`)[0] 38 | 39 | if (volume.level >= 50){ 40 | item.style.borderColor = '#00ff00' 41 | }else{ 42 | item.style.borderColor = "#fff" 43 | } 44 | }catch(error){ 45 | console.error(error) 46 | } 47 | 48 | 49 | }); 50 | }) 51 | } 52 | ``` 53 | 54 | This method should be initialized at the bottom of the `initRtc` function. 55 | 56 | ```js 57 | const initRtc = async () => { 58 | //... 59 | initVolumeIndicator() 60 | } 61 | ``` -------------------------------------------------------------------------------- /2-Active-Speaker-Indicator/main.js: -------------------------------------------------------------------------------- 1 | import './style.css' 2 | import AgoraRTC from "agora-rtc-sdk-ng" 3 | 4 | import appid from '../appId.js' 5 | 6 | const token = null 7 | const rtcUid = Math.floor(Math.random() * 2032) 8 | 9 | let roomId = "main" 10 | 11 | let audioTracks = { 12 | localAudioTrack: null, 13 | remoteAudioTracks: {}, 14 | }; 15 | 16 | let rtcClient; 17 | 18 | 19 | const initRtc = async () => { 20 | rtcClient = AgoraRTC.createClient({ mode: "rtc", codec: "vp8" }); 21 | 22 | 23 | rtcClient.on('user-joined', handleUserJoined) 24 | rtcClient.on("user-published", handleUserPublished) 25 | rtcClient.on("user-left", handleUserLeft); 26 | 27 | 28 | await rtcClient.join(appid, roomId, token, rtcUid) 29 | audioTracks.localAudioTrack = await AgoraRTC.createMicrophoneAudioTrack(); 30 | await rtcClient.publish(audioTracks.localAudioTrack); 31 | 32 | 33 | document.getElementById('members').insertAdjacentHTML('beforeend', `

${rtcUid}

`) 34 | 35 | initVolumeIndicator() 36 | } 37 | 38 | let initVolumeIndicator = async () => { 39 | 40 | //1 41 | AgoraRTC.setParameter('AUDIO_VOLUME_INDICATION_INTERVAL', 200); 42 | rtcClient.enableAudioVolumeIndicator(); 43 | 44 | //2 45 | rtcClient.on("volume-indicator", volumes => { 46 | volumes.forEach((volume) => { 47 | console.log(`UID ${volume.uid} Level ${volume.level}`); 48 | 49 | //3 50 | try{ 51 | let item = document.getElementsByClassName(`user-rtc-${volume.uid}`)[0] 52 | 53 | if (volume.level >= 50){ 54 | item.style.borderColor = '#00ff00' 55 | }else{ 56 | item.style.borderColor = "#fff" 57 | } 58 | }catch(error){ 59 | console.error(error) 60 | } 61 | 62 | 63 | }); 64 | }) 65 | } 66 | 67 | 68 | let handleUserJoined = async (user) => { 69 | console.log('USER:', user) 70 | document.getElementById('members').insertAdjacentHTML('beforeend', `

${user.uid}

`) 71 | } 72 | 73 | let handleUserPublished = async (user, mediaType) => { 74 | await rtcClient.subscribe(user, mediaType); 75 | 76 | if (mediaType == "audio"){ 77 | audioTracks.remoteAudioTracks[user.uid] = [user.audioTrack] 78 | user.audioTrack.play(); 79 | } 80 | } 81 | 82 | let handleUserLeft = async (user) => { 83 | delete audioTracks.remoteAudioTracks[user.uid] 84 | document.getElementById(user.uid).remove() 85 | } 86 | 87 | 88 | let lobbyForm = document.getElementById('form') 89 | 90 | const enterRoom = async (e) => { 91 | e.preventDefault() 92 | initRtc() 93 | 94 | lobbyForm.style.display = 'none' 95 | document.getElementById('room-header').style.display = "flex" 96 | } 97 | 98 | let leaveRoom = async () => { 99 | audioTracks.localAudioTrack.stop() 100 | audioTracks.localAudioTrack.close() 101 | rtcClient.unpublish() 102 | rtcClient.leave() 103 | 104 | document.getElementById('form').style.display = 'block' 105 | document.getElementById('room-header').style.display = 'none' 106 | document.getElementById('members').innerHTML = '' 107 | } 108 | 109 | lobbyForm.addEventListener('submit', enterRoom) 110 | document.getElementById('leave-icon').addEventListener('click', leaveRoom) 111 | -------------------------------------------------------------------------------- /6-Creating-Rooms/guide.md: -------------------------------------------------------------------------------- 1 | # Creating Rooms 2 | 3 | Creating dynamic from names from login form. 4 | 5 | **Form room name** 6 | 7 | The first thing we'll need to do is add a room name field to the login form. We will then take this field value and update our `roomId` variable. Currently, this is set to `let roomId = 'main'` and we want to change this so we can have users join more than one room. 8 | 9 | For a little styling let's also add some `