├── src
├── assets
│ └── .gitkeep
├── styles.css
├── environments
│ ├── environment.prod.ts
│ └── environment.ts
├── favicon.ico
├── app
│ ├── app.component.css
│ ├── app.component.html
│ ├── app.module.ts
│ ├── app.component.spec.ts
│ └── app.component.ts
├── tsconfig.app.json
├── index.html
├── tsconfig.spec.json
├── tslint.json
├── browserslist
├── main.ts
├── test.ts
├── karma.conf.js
└── polyfills.ts
├── .vscode
└── settings.json
├── projects
└── angular-agora-rtc
│ ├── src
│ ├── lib
│ │ ├── AgoraConfig.ts
│ │ ├── Device.ts
│ │ ├── angular-agora-rtc.service.spec.ts
│ │ ├── angular-agora-rtc.module.ts
│ │ ├── angular-agora-rtc.component.spec.ts
│ │ ├── agora-local-component.html
│ │ ├── agora-local.component.css
│ │ ├── AgoraClient.ts
│ │ ├── Stream.ts
│ │ ├── angular-agora-rtc.service.ts
│ │ └── agora-local.component.ts
│ ├── public_api.ts
│ └── test.ts
│ ├── node_modules
│ └── agora-rtc-sdk
│ │ ├── LICENSE.md
│ │ ├── README.md
│ │ └── package.json
│ ├── ng-package.prod.json
│ ├── tsconfig.spec.json
│ ├── ng-package.json
│ ├── package.json
│ ├── tslint.json
│ ├── package-lock.json
│ ├── tsconfig.lib.json
│ ├── karma.conf.js
│ └── README.md
├── e2e
├── src
│ ├── app.po.ts
│ └── app.e2e-spec.ts
├── tsconfig.e2e.json
└── protractor.conf.js
├── .editorconfig
├── tsconfig.json
├── .gitignore
├── package.json
├── tslint.json
├── angular.json
└── README.md
/src/assets/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "git.ignoreLimitWarning": true
3 | }
--------------------------------------------------------------------------------
/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/src/lib/AgoraConfig.ts:
--------------------------------------------------------------------------------
1 | export class AgoraConfig{
2 | AppID:string;
3 | }
--------------------------------------------------------------------------------
/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AgoraIO-Community/Angular-Agora-RTC/HEAD/src/favicon.ico
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/src/lib/Device.ts:
--------------------------------------------------------------------------------
1 | export class Device {
2 | deviceId:string;
3 | groupId:string;
4 | kind:string;
5 | label:string;
6 | }
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/node_modules/agora-rtc-sdk/LICENSE.md:
--------------------------------------------------------------------------------
1 | See [here](https://www.agora.io/en/sdk-license-agreement/?_ga=2.210801749.1535711986.1520219996-1414345485.1520219996) for licensing.
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/node_modules/agora-rtc-sdk/README.md:
--------------------------------------------------------------------------------
1 | # AgoraRTC SDK (Web)
2 | For publishing npm package AgoraRTC SDK (Web).
3 | Get more infomation from [https://www.agora.io](https://www.agora.io/en/).
--------------------------------------------------------------------------------
/src/app/app.component.css:
--------------------------------------------------------------------------------
1 | #agora_local{
2 | height: 500px;
3 | width: 500px;
4 | display: inline-block;
5 | }
6 |
7 | .remote-containers div{
8 | height: 250px;
9 | width: 250px;
10 | }
--------------------------------------------------------------------------------
/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
--------------------------------------------------------------------------------
/src/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "module": "es2015",
6 | "types": []
7 | },
8 | "exclude": [
9 | "src/test.ts",
10 | "**/*.spec.ts"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/e2e/src/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo() {
5 | return browser.get('/');
6 | }
7 |
8 | getParagraphText() {
9 | return element(by.css('app-root h1')).getText();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/e2e/tsconfig.e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "module": "commonjs",
6 | "target": "es5",
7 | "types": [
8 | "jasmine",
9 | "jasminewd2",
10 | "node"
11 | ]
12 | }
13 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/ng-package.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "../../dist/angular-agora-rtc",
4 | "lib": {
5 | "entryFile": "src/public_api.ts"
6 | },
7 | "whitelistedNonPeerDependencies": [
8 | "agora-rtc-sdk",
9 | "material-design-icons"
10 | ]
11 | }
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts"
12 | ],
13 | "include": [
14 | "**/*.spec.ts",
15 | "**/*.d.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/ng-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "../../dist/angular-agora-rtc",
4 | "deleteDestPath": false,
5 | "lib": {
6 | "entryFile": "src/public_api.ts"
7 | },
8 | "whitelistedNonPeerDependencies": [
9 | "agora-rtc-sdk",
10 | "material-design-icons"
11 | ]
12 | }
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AngularAgoraRTCDemo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/spec",
5 | "module": "commonjs",
6 | "types": [
7 | "jasmine",
8 | "node"
9 | ]
10 | },
11 | "files": [
12 | "test.ts",
13 | "polyfills.ts"
14 | ],
15 | "include": [
16 | "**/*.spec.ts",
17 | "**/*.d.ts"
18 | ]
19 | }
20 |
--------------------------------------------------------------------------------
/e2e/src/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 |
3 | describe('workspace-project App', () => {
4 | let page: AppPage;
5 |
6 | beforeEach(() => {
7 | page = new AppPage();
8 | });
9 |
10 | it('should display welcome message', () => {
11 | page.navigateTo();
12 | expect(page.getParagraphText()).toEqual('Welcome to AngularAgoraRTCDemo!');
13 | });
14 | });
15 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-agora-rtc",
3 | "version": "0.0.9",
4 | "homepage": "https://github.com/Only1MrAnderson/Angular-Agora-RTC#readme",
5 | "peerDependencies": {
6 | "@angular/common": "^6.0.0-rc.0 || ^6.0.0",
7 | "@angular/core": "^6.0.0-rc.0 || ^6.0.0"
8 | },
9 | "dependencies": {
10 | "agora-rtc-sdk": "^2.3.1"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/src/public_api.ts:
--------------------------------------------------------------------------------
1 | /*
2 | * Public API Surface of angular-agora-rtc
3 | */
4 |
5 | export * from './lib/angular-agora-rtc.service';
6 | export * from './lib/agora-local.component';
7 | export * from './lib/angular-agora-rtc.module';
8 | export * from './lib/AgoraClient';
9 | export * from './lib/Stream';
10 | export * from './lib/Device';
11 | export * from './lib/AgoraConfig';
--------------------------------------------------------------------------------
/src/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "app",
8 | "camelCase"
9 | ],
10 | "component-selector": [
11 | true,
12 | "element",
13 | "app",
14 | "kebab-case"
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/browserslist:
--------------------------------------------------------------------------------
1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 | # For IE 9-11 support, please uncomment the last line of the file and adjust as needed
5 | > 0.5%
6 | last 2 versions
7 | Firefox ESR
8 | not dead
9 | # IE 9-11
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tslint.json",
3 | "rules": {
4 | "directive-selector": [
5 | true,
6 | "attribute",
7 | "lib",
8 | "camelCase"
9 | ],
10 | "component-selector": [
11 | true,
12 | "element",
13 | "lib",
14 | "kebab-case"
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | platformBrowserDynamic().bootstrapModule(AppModule)
12 | .catch(err => console.log(err));
13 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/src/lib/angular-agora-rtc.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, inject } from '@angular/core/testing';
2 |
3 | import { AngularAgoraRtcService } from './angular-agora-rtc.service';
4 |
5 | describe('AngularAgoraRtcService', () => {
6 | beforeEach(() => {
7 | TestBed.configureTestingModule({
8 | providers: [AngularAgoraRtcService]
9 | });
10 | });
11 |
12 | it('should be created', inject([AngularAgoraRtcService], (service: AngularAgoraRtcService) => {
13 | expect(service).toBeTruthy();
14 | }));
15 | });
16 |
--------------------------------------------------------------------------------
/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { BrowserModule } from '@angular/platform-browser';
2 | import { NgModule } from '@angular/core';
3 | import { AngularAgoraRtcModule, AgoraConfig } from 'angular-agora-rtc';
4 |
5 | import { AppComponent } from './app.component';
6 |
7 | const agoraConfig: AgoraConfig = {
8 | AppID: 'ksdfjlkdsjfklsdjf',
9 | };
10 |
11 | @NgModule({
12 | declarations: [
13 | AppComponent
14 | ],
15 | imports: [
16 | BrowserModule,
17 | AngularAgoraRtcModule.forRoot(agoraConfig)
18 | ],
19 | providers: [],
20 | bootstrap: [AppComponent]
21 | })
22 | export class AppModule { }
23 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "./dist/out-tsc",
6 | "sourceMap": true,
7 | "declaration": false,
8 | "moduleResolution": "node",
9 | "emitDecoratorMetadata": true,
10 | "experimentalDecorators": true,
11 | "target": "es5",
12 | "typeRoots": [
13 | "node_modules/@types"
14 | ],
15 | "lib": [
16 | "es2017",
17 | "dom"
18 | ],
19 | "paths": {
20 | "angular-agora-rtc": [
21 | "dist/angular-agora-rtc"
22 | ],
23 | "angular-agora-rtc/*": [
24 | "dist/angular-agora-rtc/*"
25 | ]
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * In development mode, to ignore zone related error stack frames such as
11 | * `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can
12 | * import the following file, but please comment it out in production mode
13 | * because it will have performance impact when throw error
14 | */
15 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
16 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-agora-rtc",
3 | "version": "0.0.7",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "agora-rtc-sdk": {
8 | "version": "2.3.1",
9 | "resolved": "https://registry.npmjs.org/agora-rtc-sdk/-/agora-rtc-sdk-2.3.1.tgz",
10 | "integrity": "sha512-QLQKlwtugjR0wY9qE2igM97UI83dpYQENLeqodnCV1Dz9x+AncVdB+WX1m5kO726vHUGsI/wW1i1rtN5vyY9iA=="
11 | },
12 | "material-design-icons": {
13 | "version": "3.0.1",
14 | "resolved": "https://registry.npmjs.org/material-design-icons/-/material-design-icons-3.0.1.tgz",
15 | "integrity": "sha1-mnHEh0chjrylHlGmbaaCA4zct78="
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: any;
11 |
12 | // First, initialize the Angular testing environment.
13 | getTestBed().initTestEnvironment(
14 | BrowserDynamicTestingModule,
15 | platformBrowserDynamicTesting()
16 | );
17 | // Then we find all the tests.
18 | const context = require.context('./', true, /\.spec\.ts$/);
19 | // And load the modules.
20 | context.keys().map(context);
21 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | /node_modules
10 |
11 | /project/angular-agora-rtc/node_modules
12 |
13 | # IDEs and editors
14 | /.idea
15 | .project
16 | .classpath
17 | .c9/
18 | *.launch
19 | .settings/
20 | *.sublime-workspace
21 |
22 | # IDE - VSCode
23 | .vscode/*
24 | !.vscode/settings.json
25 | !.vscode/tasks.json
26 | !.vscode/launch.json
27 | !.vscode/extensions.json
28 |
29 | # misc
30 | /.sass-cache
31 | /connect.lock
32 | /coverage
33 | /libpeerconnection.log
34 | npm-debug.log
35 | yarn-error.log
36 | testem.log
37 | /typings
38 |
39 | # System Files
40 | .DS_Store
41 | Thumbs.db
42 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/src/lib/angular-agora-rtc.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule, ModuleWithProviders } from '@angular/core';
2 | import { AgoraLocalComponent } from './agora-local.component';
3 | import { AgoraConfig } from './AgoraConfig';
4 | import { AngularAgoraRtcService } from './angular-agora-rtc.service';
5 | import { CommonModule } from '@angular/common';
6 |
7 | @NgModule({
8 | imports: [
9 | CommonModule
10 | ],
11 | declarations: [AgoraLocalComponent],
12 | exports: [AgoraLocalComponent]
13 | })
14 | export class AngularAgoraRtcModule {
15 | static forRoot(config: AgoraConfig): ModuleWithProviders{
16 | return {
17 | ngModule: AngularAgoraRtcModule,
18 | providers: [AngularAgoraRtcService, {provide: 'config', useValue: config}]
19 | };
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/src/lib/angular-agora-rtc.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { AgoraLocalComponent } from './agora-local.component';
4 |
5 | describe('AgoraLocalComponent', () => {
6 | let component: AgoraLocalComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(async(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [ AgoraLocalComponent ]
12 | })
13 | .compileComponents();
14 | }));
15 |
16 | beforeEach(() => {
17 | fixture = TestBed.createComponent(AgoraLocalComponent);
18 | component = fixture.componentInstance;
19 | fixture.detectChanges();
20 | });
21 |
22 | it('should create', () => {
23 | expect(component).toBeTruthy();
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'core-js/es7/reflect';
4 | import 'zone.js/dist/zone';
5 | import 'zone.js/dist/zone-testing';
6 | import { getTestBed } from '@angular/core/testing';
7 | import {
8 | BrowserDynamicTestingModule,
9 | platformBrowserDynamicTesting
10 | } from '@angular/platform-browser-dynamic/testing';
11 |
12 | declare const require: any;
13 |
14 | // First, initialize the Angular testing environment.
15 | getTestBed().initTestEnvironment(
16 | BrowserDynamicTestingModule,
17 | platformBrowserDynamicTesting()
18 | );
19 | // Then we find all the tests.
20 | const context = require.context('./', true, /\.spec\.ts$/);
21 | // And load the modules.
22 | context.keys().map(context);
23 |
--------------------------------------------------------------------------------
/e2e/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/lib/config.ts
3 |
4 | const { SpecReporter } = require('jasmine-spec-reporter');
5 |
6 | exports.config = {
7 | allScriptsTimeout: 11000,
8 | specs: [
9 | './src/**/*.e2e-spec.ts'
10 | ],
11 | capabilities: {
12 | 'browserName': 'chrome'
13 | },
14 | directConnect: true,
15 | baseUrl: 'http://localhost:4200/',
16 | framework: 'jasmine',
17 | jasmineNodeOpts: {
18 | showColors: true,
19 | defaultTimeoutInterval: 30000,
20 | print: function() {}
21 | },
22 | onPrepare() {
23 | require('ts-node').register({
24 | project: require('path').join(__dirname, './tsconfig.e2e.json')
25 | });
26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
27 | }
28 | };
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../../out-tsc/lib",
5 | "target": "es2015",
6 | "module": "es2015",
7 | "moduleResolution": "node",
8 | "declaration": true,
9 | "sourceMap": true,
10 | "inlineSources": true,
11 | "emitDecoratorMetadata": true,
12 | "experimentalDecorators": true,
13 | "importHelpers": true,
14 | "types": [],
15 | "lib": [
16 | "dom",
17 | "es2015"
18 | ]
19 | },
20 | "angularCompilerOptions": {
21 | "annotateForClosureCompiler": true,
22 | "skipTemplateCodegen": true,
23 | "strictMetadataEmit": true,
24 | "fullTemplateTypeCheck": true,
25 | "strictInjectionParameters": true,
26 | "flatModuleId": "AUTOGENERATED",
27 | "flatModuleOutFile": "AUTOGENERATED"
28 | },
29 | "exclude": [
30 | "src/test.ts",
31 | "**/*.spec.ts"
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/src/lib/agora-local-component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | videocam
7 |
8 | phone
9 |
10 | mic
11 | mic_off
12 |
13 | videocam
14 | videocam_off
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/src/lib/agora-local.component.css:
--------------------------------------------------------------------------------
1 | @import url('https://fonts.googleapis.com/icon?family=Material+Icons');
2 |
3 | p {
4 | font-family: Lato;
5 | }
6 |
7 | .video-container{
8 | height: 100vh;
9 | display: flex;
10 | flex-wrap: wrap;
11 | flex-direction: row;
12 | justify-content: center;
13 | }
14 |
15 | .agora_local{
16 | background-color: #404040;
17 | height: 250px;
18 | width: 250px;
19 | border: black 1px solid;
20 | margin: 8px;
21 | }
22 | #agora_local{
23 | height: 250px;
24 | width: 250px;
25 | }
26 |
27 | .agora_remote{
28 | background-color: #404040;
29 | height: 250px;
30 | width: 250px;
31 | border: black 1px solid;
32 | margin: 8px;
33 | }
34 |
35 | .video-buttons{
36 | width: 250px;
37 | top: 210px;
38 | position: relative;
39 | text-align: center;
40 | z-index: 999;
41 | }
42 |
43 | .video-buttons i{
44 | cursor: pointer;
45 | }
46 |
47 | .endCall{
48 | color: red;
49 | }
50 |
51 | .startCall{
52 | color: white;
53 | }
54 |
55 | .mic{
56 | color: white;
57 | }
58 |
--------------------------------------------------------------------------------
/src/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../coverage'),
20 | reports: ['html', 'lcovonly'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false
30 | });
31 | };
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../../coverage'),
20 | reports: ['html', 'lcovonly'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false
30 | });
31 | };
32 |
--------------------------------------------------------------------------------
/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, async } from '@angular/core/testing';
2 | import { AppComponent } from './app.component';
3 | describe('AppComponent', () => {
4 | beforeEach(async(() => {
5 | TestBed.configureTestingModule({
6 | declarations: [
7 | AppComponent
8 | ],
9 | }).compileComponents();
10 | }));
11 | it('should create the app', async(() => {
12 | const fixture = TestBed.createComponent(AppComponent);
13 | const app = fixture.debugElement.componentInstance;
14 | expect(app).toBeTruthy();
15 | }));
16 | it(`should have as title 'app'`, async(() => {
17 | const fixture = TestBed.createComponent(AppComponent);
18 | const app = fixture.debugElement.componentInstance;
19 | expect(app.title).toEqual('app');
20 | }));
21 | it('should render title in a h1 tag', async(() => {
22 | const fixture = TestBed.createComponent(AppComponent);
23 | fixture.detectChanges();
24 | const compiled = fixture.debugElement.nativeElement;
25 | expect(compiled.querySelector('h1').textContent).toContain('Welcome to AngularAgoraRTCDemo!');
26 | }));
27 | });
28 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/src/lib/AgoraClient.ts:
--------------------------------------------------------------------------------
1 | export class AgoraClient {
2 | aesMode: string;
3 | aespassword: string;
4 | configPublisher: any; // function
5 | disableDualStream: any; // function
6 | enableDualStream: any; // function
7 | gatewayClient: {}; // add object
8 | highStream: any; // ? type
9 | highStreamState: number;
10 | init: any; // function
11 | isDualStream: boolean;
12 | join: any; // function
13 | key: any; // ? string
14 | leave: any; // function
15 | lowStream: any; // ?
16 | lowStreamParameter: any // ?
17 | lowStreamState: number;
18 | on: any; // function
19 | proxyServer: any; // ?
20 | publish: any; // function
21 | renewChannelKey: any; // function
22 | setEncryptionMode: any; // function
23 | setEncryptionSecret: any; // function
24 | setLiveTranscoding: any; // function
25 | setLowStreamParameter: any; // function
26 | setProxyServer: any; // function
27 | setRemoteVideoStreamType: any; // function
28 | setTurnServer: any; // function
29 | startLiveStreaming: any; // function
30 | stopLiveStreaming: any; // function
31 | subscribe: any; // function
32 | turnServer: any; // function
33 | unpublish: any; // function
34 | unsubscribe: any; // function
35 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-agora-rtcdemo",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "ng serve",
7 | "build": "ng build",
8 | "test": "ng test",
9 | "lint": "ng lint",
10 | "e2e": "ng e2e"
11 | },
12 | "private": true,
13 | "dependencies": {
14 | "@angular/animations": "^6.0.3",
15 | "@angular/common": "^6.0.3",
16 | "@angular/compiler": "^6.0.3",
17 | "@angular/core": "^6.0.3",
18 | "@angular/forms": "^6.0.3",
19 | "@angular/http": "^6.0.3",
20 | "@angular/platform-browser": "^6.0.3",
21 | "@angular/platform-browser-dynamic": "^6.0.3",
22 | "@angular/router": "^6.0.3",
23 | "angular-agora-rtc": "0.0.2",
24 | "core-js": "^2.5.4",
25 | "rxjs": "^6.0.0",
26 | "zone.js": "^0.8.26"
27 | },
28 | "devDependencies": {
29 | "@angular/compiler-cli": "^6.0.3",
30 | "@angular-devkit/build-ng-packagr": "~0.6.8",
31 | "@angular-devkit/build-angular": "~0.6.8",
32 | "ng-packagr": "^3.0.0-rc.2",
33 | "tsickle": ">=0.25.5",
34 | "tslib": "^1.7.1",
35 | "typescript": "~2.7.2",
36 | "@angular/cli": "~6.0.8",
37 | "@angular/language-service": "^6.0.3",
38 | "@types/jasmine": "~2.8.6",
39 | "@types/jasminewd2": "~2.0.3",
40 | "@types/node": "~8.9.4",
41 | "codelyzer": "~4.2.1",
42 | "jasmine-core": "~2.99.1",
43 | "jasmine-spec-reporter": "~4.2.1",
44 | "karma": "~1.7.1",
45 | "karma-chrome-launcher": "~2.2.0",
46 | "karma-coverage-istanbul-reporter": "~2.0.0",
47 | "karma-jasmine": "~1.1.1",
48 | "karma-jasmine-html-reporter": "^0.2.2",
49 | "protractor": "~5.3.0",
50 | "ts-node": "~5.0.1",
51 | "tslint": "~5.9.1"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/node_modules/agora-rtc-sdk/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "_from": "agora-rtc-sdk",
3 | "_id": "agora-rtc-sdk@2.3.1",
4 | "_inBundle": false,
5 | "_integrity": "sha512-QLQKlwtugjR0wY9qE2igM97UI83dpYQENLeqodnCV1Dz9x+AncVdB+WX1m5kO726vHUGsI/wW1i1rtN5vyY9iA==",
6 | "_location": "/agora-rtc-sdk",
7 | "_phantomChildren": {},
8 | "_requested": {
9 | "type": "tag",
10 | "registry": true,
11 | "raw": "agora-rtc-sdk",
12 | "name": "agora-rtc-sdk",
13 | "escapedName": "agora-rtc-sdk",
14 | "rawSpec": "",
15 | "saveSpec": null,
16 | "fetchSpec": "latest"
17 | },
18 | "_requiredBy": [
19 | "#USER",
20 | "/"
21 | ],
22 | "_resolved": "https://registry.npmjs.org/agora-rtc-sdk/-/agora-rtc-sdk-2.3.1.tgz",
23 | "_shasum": "ba99637ee0d28b3b6453965876e7e35f8d76cfd8",
24 | "_spec": "agora-rtc-sdk",
25 | "_where": "/Users/andrewanderson/Desktop/development/Agora/AngularAgoraRTCDemo/projects/angular-agora-rtc",
26 | "author": {
27 | "name": "agora"
28 | },
29 | "bugs": {
30 | "url": "https://github.com/AgoraIO/web-archive/issues"
31 | },
32 | "bundleDependencies": false,
33 | "deprecated": false,
34 | "description": "AgoraRTC SDK for web",
35 | "homepage": "https://github.com/AgoraIO/web-archive#readme",
36 | "keywords": [
37 | "Agora",
38 | "Webrtc",
39 | "Javascript"
40 | ],
41 | "license": "SEE LICENSE IN LICENSE.md",
42 | "main": "AgoraRTCSDK.min.js",
43 | "name": "agora-rtc-sdk",
44 | "repository": {
45 | "type": "git",
46 | "url": "git+https://github.com/AgoraIO/web-archive.git"
47 | },
48 | "scripts": {
49 | "test": "echo \"Error: no test specified\" && exit 1"
50 | },
51 | "version": "2.3.1"
52 | }
53 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/src/lib/Stream.ts:
--------------------------------------------------------------------------------
1 | export class Stream {
2 | addEventListener: any; // function
3 | audio: boolean;
4 | audioEnabled: boolean;
5 | audioLevelHelper: any // ?
6 | aux_stream: any; // ?
7 | close: any; // function
8 | disableAudio: any; // function
9 | disableVideo: any; // function
10 | dispatchEvent: any; // function
11 | dispatchSocketEvent: any; // function
12 | dispatcher: any; // event listener
13 | enableAudio: any; // function
14 | enableVideo: any; // function
15 | getAttributes: any; // function
16 | getAudioLevel: any; // function
17 | getId: any; // function
18 | getStats: any; // function
19 | hasAudio: any; // function
20 | hasScreen: any; // function
21 | hasVideo: any; // function
22 | init: any; // function
23 | initialized: boolean;
24 | isAudioOn: any; // function
25 | isVideoOn: any; // function
26 | local: boolean;
27 | lowStream: any; //?
28 | mirror: boolean;
29 | muteAudio: any; // ?
30 | muteVideo: any; // ?
31 | on: any; // function
32 | onClose: any // ?
33 | params:
34 | { streamID: number, audio: boolean, cameraId: string, microphoneId: string, video: boolean }
35 | play: any; // function
36 | player: any; // ?
37 | removeEventListener: any; // function
38 | screen: boolean;
39 | screenAttributes: { width: number, height: number, maxFr: number, minFr: number }
40 | setScreenProfile: any; // function
41 | setVideoBitRate: any; // function
42 | setVideoFrameRate: any; // function
43 | setVideoProfile: any; // function
44 | setVideoProfileCustom: any; // function
45 | setVideoProfileCustomPlus: any; // function
46 | setVideoResolution: any; // function
47 | stop: any; // function
48 | streamLanyl // ?
49 | streamId: number;
50 | unmuteAudio: any; // ?
51 | unmuteVideo: any; // ?
52 | url: any; //?
53 | video: boolean;
54 | videoEnabled: boolean;
55 | videoHeight: number;
56 | videoSize: Array
57 | videoWidth: number;
58 | }
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/src/lib/angular-agora-rtc.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, Inject } from '@angular/core';
2 | import * as AgoraRTC from 'agora-rtc-sdk';
3 | import { Subject, BehaviorSubject } from 'rxjs';
4 | import { AgoraConfig } from './AgoraConfig';
5 | import { AgoraClient } from './AgoraClient';
6 |
7 | @Injectable({
8 | providedIn: 'root'
9 | })
10 | export class AngularAgoraRtcService {
11 |
12 | public audioDevices: any[];
13 | public videoDevices: any[];
14 |
15 | public client: AgoraClient;
16 |
17 | constructor(
18 | @Inject('config') private config:AgoraConfig
19 | ) {
20 | if (!this.checkSystemRequirements()) {
21 | this.logger('error', 'Web RTC is not supported');
22 | } else{
23 | this.getDevices();
24 | }
25 | }
26 |
27 | checkSystemRequirements() {
28 | return AgoraRTC.checkSystemRequirements();
29 | }
30 |
31 | private getDevices() {
32 | AgoraRTC.getDevices((devices) => {
33 | let audioDevices = devices.filter(device => {
34 | return device.kind === 'audioinput' && device.deviceId !== 'default'
35 | });
36 | let videoDevices = devices.filter(device => {
37 | return device.kind === 'videoinput' && device.deviceId !== 'default'
38 | });
39 | this.audioDevices = audioDevices;
40 | this.videoDevices = videoDevices;
41 | });
42 | }
43 |
44 | createClient(mode: string = 'interop', codec: string = 'vp8') {
45 | this.client = AgoraRTC.createClient({ mode: mode, codec: codec });
46 | this.client.init(this.config.AppID);
47 | }
48 |
49 | createStream(streamID: any, audio: boolean, cameraId: string = this.videoDevices[0].deviceId, microphoneId: string = this.audioDevices[0].deviceId, video: boolean, screen: boolean) {
50 | return AgoraRTC.createStream({streamID, audio, cameraId, microphoneId, video, screen});
51 | }
52 |
53 | logger(type: string, message: string) {
54 | switch (type) {
55 | case 'error':
56 | AgoraRTC.Logger.error(message);
57 | break;
58 | case 'warning':
59 | AgoraRTC.Logger.warning(message);
60 | break;
61 | case 'info':
62 | AgoraRTC.Logger.info(message);
63 | break;
64 | case 'debug':
65 | AgoraRTC.Logger.debug(message);
66 | break;
67 | default:
68 | AgoraRTC.Logger.error(message);
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { AngularAgoraRtcService, Stream } from 'angular-agora-rtc';
3 |
4 | @Component({
5 | selector: 'app-root',
6 | templateUrl: './app.component.html',
7 | styleUrls: ['./app.component.css']
8 | })
9 | export class AppComponent {
10 | title = 'AgoraDemo';
11 | localStream: Stream
12 | remoteCalls: any = [];
13 |
14 | constructor(
15 | private agoraService: AngularAgoraRtcService
16 | ) {
17 | this.agoraService.createClient();
18 | }
19 |
20 | startCall() {
21 | this.agoraService.client.join(null, '1000', null, (uid) => {
22 | this.localStream = this.agoraService.createStream(uid, true, null, null, true, false);
23 | this.localStream.setVideoProfile('720p_3');
24 | this.subscribeToStreams();
25 | });
26 | }
27 |
28 | private subscribeToStreams() {
29 | this.localStream.on("accessAllowed", () => {
30 | console.log("accessAllowed");
31 | });
32 | // The user has denied access to the camera and mic.
33 | this.localStream.on("accessDenied", () => {
34 | console.log("accessDenied");
35 | });
36 |
37 | this.localStream.init(() => {
38 | console.log("getUserMedia successfully");
39 | this.localStream.play('agora_local');
40 | this.agoraService.client.publish(this.localStream, function (err) {
41 | console.log("Publish local stream error: " + err);
42 | });
43 | this.agoraService.client.on('stream-published', function (evt) {
44 | console.log("Publish local stream successfully");
45 | });
46 | }, function (err) {
47 | console.log("getUserMedia failed", err);
48 | });
49 |
50 | this.agoraService.client.on('error', (err) => {
51 | console.log("Got error msg:", err.reason);
52 | if (err.reason === 'DYNAMIC_KEY_TIMEOUT') {
53 | this.agoraService.client.renewChannelKey("", () => {
54 | console.log("Renew channel key successfully");
55 | }, (err) => {
56 | console.log("Renew channel key failed: ", err);
57 | });
58 | }
59 | });
60 |
61 | this.agoraService.client.on('stream-added', (evt) => {
62 | const stream = evt.stream;
63 | this.agoraService.client.subscribe(stream, (err) => {
64 | console.log("Subscribe stream failed", err);
65 | });
66 | });
67 |
68 | this.agoraService.client.on('stream-subscribed', (evt) => {
69 | const stream = evt.stream;
70 | if (!this.remoteCalls.includes(`agora_remote${stream.getId()}`)) this.remoteCalls.push(`agora_remote${stream.getId()}`);
71 | setTimeout(() => stream.play(`agora_remote${stream.getId()}`), 2000);
72 | });
73 |
74 | this.agoraService.client.on('stream-removed', (evt) => {
75 | const stream = evt.stream;
76 | stream.stop();
77 | this.remoteCalls = this.remoteCalls.filter(call => call !== `#agora_remote${stream.getId()}`);
78 | console.log(`Remote stream is removed ${stream.getId()}`);
79 | });
80 |
81 | this.agoraService.client.on('peer-leave', (evt) => {
82 | const stream = evt.stream;
83 | if (stream) {
84 | stream.stop();
85 | this.remoteCalls = this.remoteCalls.filter(call => call === `#agora_remote${stream.getId()}`);
86 | console.log(`${evt.uid} left from this channel`);
87 | }
88 | });
89 | }
90 |
91 | }
92 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [
3 | "node_modules/codelyzer"
4 | ],
5 | "rules": {
6 | "arrow-return-shorthand": true,
7 | "callable-types": true,
8 | "class-name": true,
9 | "comment-format": [
10 | true,
11 | "check-space"
12 | ],
13 | "curly": true,
14 | "deprecation": {
15 | "severity": "warn"
16 | },
17 | "eofline": true,
18 | "forin": true,
19 | "import-blacklist": [
20 | true,
21 | "rxjs/Rx"
22 | ],
23 | "import-spacing": true,
24 | "indent": [
25 | true,
26 | "spaces"
27 | ],
28 | "interface-over-type-literal": true,
29 | "label-position": true,
30 | "max-line-length": [
31 | true,
32 | 140
33 | ],
34 | "member-access": false,
35 | "member-ordering": [
36 | true,
37 | {
38 | "order": [
39 | "static-field",
40 | "instance-field",
41 | "static-method",
42 | "instance-method"
43 | ]
44 | }
45 | ],
46 | "no-arg": true,
47 | "no-bitwise": true,
48 | "no-console": [
49 | true,
50 | "debug",
51 | "info",
52 | "time",
53 | "timeEnd",
54 | "trace"
55 | ],
56 | "no-construct": true,
57 | "no-debugger": true,
58 | "no-duplicate-super": true,
59 | "no-empty": false,
60 | "no-empty-interface": true,
61 | "no-eval": true,
62 | "no-inferrable-types": [
63 | true,
64 | "ignore-params"
65 | ],
66 | "no-misused-new": true,
67 | "no-non-null-assertion": true,
68 | "no-shadowed-variable": true,
69 | "no-string-literal": false,
70 | "no-string-throw": true,
71 | "no-switch-case-fall-through": true,
72 | "no-trailing-whitespace": true,
73 | "no-unnecessary-initializer": true,
74 | "no-unused-expression": true,
75 | "no-use-before-declare": true,
76 | "no-var-keyword": true,
77 | "object-literal-sort-keys": false,
78 | "one-line": [
79 | true,
80 | "check-open-brace",
81 | "check-catch",
82 | "check-else",
83 | "check-whitespace"
84 | ],
85 | "prefer-const": true,
86 | "quotemark": [
87 | true,
88 | "single"
89 | ],
90 | "radix": true,
91 | "semicolon": [
92 | true,
93 | "always"
94 | ],
95 | "triple-equals": [
96 | true,
97 | "allow-null-check"
98 | ],
99 | "typedef-whitespace": [
100 | true,
101 | {
102 | "call-signature": "nospace",
103 | "index-signature": "nospace",
104 | "parameter": "nospace",
105 | "property-declaration": "nospace",
106 | "variable-declaration": "nospace"
107 | }
108 | ],
109 | "unified-signatures": true,
110 | "variable-name": false,
111 | "whitespace": [
112 | true,
113 | "check-branch",
114 | "check-decl",
115 | "check-operator",
116 | "check-separator",
117 | "check-type"
118 | ],
119 | "no-output-on-prefix": true,
120 | "use-input-property-decorator": true,
121 | "use-output-property-decorator": true,
122 | "use-host-property-decorator": true,
123 | "no-input-rename": true,
124 | "no-output-rename": true,
125 | "use-life-cycle-interface": true,
126 | "use-pipe-transform-interface": true,
127 | "component-class-suffix": true,
128 | "directive-class-suffix": true
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/
22 | // import 'core-js/es6/symbol';
23 | // import 'core-js/es6/object';
24 | // import 'core-js/es6/function';
25 | // import 'core-js/es6/parse-int';
26 | // import 'core-js/es6/parse-float';
27 | // import 'core-js/es6/number';
28 | // import 'core-js/es6/math';
29 | // import 'core-js/es6/string';
30 | // import 'core-js/es6/date';
31 | // import 'core-js/es6/array';
32 | // import 'core-js/es6/regexp';
33 | // import 'core-js/es6/map';
34 | // import 'core-js/es6/weak-map';
35 | // import 'core-js/es6/set';
36 |
37 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
38 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
39 |
40 | /** IE10 and IE11 requires the following for the Reflect API. */
41 | // import 'core-js/es6/reflect';
42 |
43 |
44 | /** Evergreen browsers require these. **/
45 | // Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
46 | import 'core-js/es7/reflect';
47 |
48 |
49 | /**
50 | * Web Animations `@angular/platform-browser/animations`
51 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
52 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
53 | **/
54 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
55 |
56 | /**
57 | * By default, zone.js will patch all possible macroTask and DomEvents
58 | * user can disable parts of macroTask/DomEvents patch by setting following flags
59 | */
60 |
61 | // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
62 | // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
63 | // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
64 |
65 | /*
66 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
67 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
68 | */
69 | // (window as any).__Zone_enable_cross_context_check = true;
70 |
71 | /***************************************************************************************************
72 | * Zone JS is required by default for Angular itself.
73 | */
74 | import 'zone.js/dist/zone'; // Included with Angular CLI.
75 |
76 |
77 |
78 | /***************************************************************************************************
79 | * APPLICATION IMPORTS
80 | */
81 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/src/lib/agora-local.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core';
2 | import { AngularAgoraRtcService } from './angular-agora-rtc.service';
3 | import { Stream } from './Stream';
4 |
5 | @Component({
6 | selector: 'agora-rtc',
7 | templateUrl: 'agora-local-component.html',
8 | styleUrls: ['agora-local.component.css']
9 | })
10 | export class AgoraLocalComponent {
11 |
12 | activeCall: boolean = false;
13 | audioEnabled: boolean = true;
14 | videoEnabled: boolean = true;
15 | localStream: Stream
16 | remoteCalls: any = [];
17 |
18 | constructor(
19 | private agoraService: AngularAgoraRtcService
20 | ) {
21 | this.agoraService.createClient();
22 | }
23 |
24 | startCall() {
25 | this.activeCall = true;
26 | this.agoraService.client.join(null, '1000', null, (uid) => {
27 | this.localStream = this.agoraService.createStream(uid, true, null, null, true, false);
28 | this.localStream.setVideoProfile('720p_3');
29 | this.subscribeToStreams();
30 | });
31 | }
32 |
33 | private subscribeToStreams() {
34 | this.localStream.on("accessAllowed", () => {
35 | console.log("accessAllowed");
36 | });
37 | // The user has denied access to the camera and mic.
38 | this.localStream.on("accessDenied", () => {
39 | console.log("accessDenied");
40 | });
41 |
42 | this.localStream.init(() => {
43 | console.log("getUserMedia successfully");
44 | this.localStream.play('agora_local');
45 | this.agoraService.client.publish(this.localStream, function (err) {
46 | console.log("Publish local stream error: " + err);
47 | });
48 | this.agoraService.client.on('stream-published', function (evt) {
49 | console.log("Publish local stream successfully");
50 | });
51 | }, function (err) {
52 | console.log("getUserMedia failed", err);
53 | });
54 |
55 | this.agoraService.client.on('error', (err) => {
56 | console.log("Got error msg:", err.reason);
57 | if (err.reason === 'DYNAMIC_KEY_TIMEOUT') {
58 | this.agoraService.client.renewChannelKey("", () => {
59 | console.log("Renew channel key successfully");
60 | }, (err) => {
61 | console.log("Renew channel key failed: ", err);
62 | });
63 | }
64 | });
65 |
66 | this.agoraService.client.on('stream-added', (evt) => {
67 | const stream = evt.stream;
68 | this.agoraService.client.subscribe(stream, (err) => {
69 | console.log("Subscribe stream failed", err);
70 | });
71 | });
72 |
73 | this.agoraService.client.on('stream-subscribed', (evt) => {
74 | const stream = evt.stream;
75 | if (!this.remoteCalls.includes(`agora_remote${stream.getId()}`)) this.remoteCalls.push(`agora_remote${stream.getId()}`);
76 | setTimeout(() => stream.play(`agora_remote${stream.getId()}`), 2000);
77 | });
78 |
79 | this.agoraService.client.on('stream-removed', (evt) => {
80 | const stream = evt.stream;
81 | stream.stop();
82 | this.remoteCalls = this.remoteCalls.filter(call => call !== `#agora_remote${stream.getId()}`);
83 | console.log(`Remote stream is removed ${stream.getId()}`);
84 | });
85 |
86 | this.agoraService.client.on('peer-leave', (evt) => {
87 | const stream = evt.stream;
88 | if (stream) {
89 | stream.stop();
90 | this.remoteCalls = this.remoteCalls.filter(call => call === `#agora_remote${stream.getId()}`);
91 | console.log(`${evt.uid} left from this channel`);
92 | }
93 | });
94 | }
95 | leave() {
96 | this.agoraService.client.leave(() => {
97 | this.activeCall = false;
98 | document.getElementById('agora_local').innerHTML = "";
99 | console.log("Leavel channel successfully");
100 | }, (err) => {
101 | console.log("Leave channel failed");
102 | });
103 | }
104 |
105 | toggleAudio() {
106 | this.audioEnabled = !this.audioEnabled;
107 | if (this.audioEnabled) this.localStream.enableAudio();
108 | else this.localStream.disableAudio();
109 | }
110 |
111 | toggleVideo() {
112 | this.videoEnabled = !this.videoEnabled;
113 | if (this.videoEnabled) this.localStream.enableVideo();
114 | else this.localStream.disableVideo();
115 | }
116 |
117 | }
118 |
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "AngularAgoraRTCDemo": {
7 | "root": "",
8 | "sourceRoot": "src",
9 | "projectType": "application",
10 | "prefix": "app",
11 | "schematics": {},
12 | "architect": {
13 | "build": {
14 | "builder": "@angular-devkit/build-angular:browser",
15 | "options": {
16 | "outputPath": "dist/AngularAgoraRTCDemo",
17 | "index": "src/index.html",
18 | "main": "src/main.ts",
19 | "polyfills": "src/polyfills.ts",
20 | "tsConfig": "src/tsconfig.app.json",
21 | "assets": [
22 | "src/favicon.ico",
23 | "src/assets"
24 | ],
25 | "styles": [
26 | "src/styles.css"
27 | ],
28 | "scripts": []
29 | },
30 | "configurations": {
31 | "production": {
32 | "fileReplacements": [
33 | {
34 | "replace": "src/environments/environment.ts",
35 | "with": "src/environments/environment.prod.ts"
36 | }
37 | ],
38 | "optimization": true,
39 | "outputHashing": "all",
40 | "sourceMap": false,
41 | "extractCss": true,
42 | "namedChunks": false,
43 | "aot": true,
44 | "extractLicenses": true,
45 | "vendorChunk": false,
46 | "buildOptimizer": true
47 | }
48 | }
49 | },
50 | "serve": {
51 | "builder": "@angular-devkit/build-angular:dev-server",
52 | "options": {
53 | "browserTarget": "AngularAgoraRTCDemo:build"
54 | },
55 | "configurations": {
56 | "production": {
57 | "browserTarget": "AngularAgoraRTCDemo:build:production"
58 | }
59 | }
60 | },
61 | "extract-i18n": {
62 | "builder": "@angular-devkit/build-angular:extract-i18n",
63 | "options": {
64 | "browserTarget": "AngularAgoraRTCDemo:build"
65 | }
66 | },
67 | "test": {
68 | "builder": "@angular-devkit/build-angular:karma",
69 | "options": {
70 | "main": "src/test.ts",
71 | "polyfills": "src/polyfills.ts",
72 | "tsConfig": "src/tsconfig.spec.json",
73 | "karmaConfig": "src/karma.conf.js",
74 | "styles": [
75 | "src/styles.css"
76 | ],
77 | "scripts": [],
78 | "assets": [
79 | "src/favicon.ico",
80 | "src/assets"
81 | ]
82 | }
83 | },
84 | "lint": {
85 | "builder": "@angular-devkit/build-angular:tslint",
86 | "options": {
87 | "tsConfig": [
88 | "src/tsconfig.app.json",
89 | "src/tsconfig.spec.json"
90 | ],
91 | "exclude": [
92 | "**/node_modules/**"
93 | ]
94 | }
95 | }
96 | }
97 | },
98 | "AngularAgoraRTCDemo-e2e": {
99 | "root": "e2e/",
100 | "projectType": "application",
101 | "architect": {
102 | "e2e": {
103 | "builder": "@angular-devkit/build-angular:protractor",
104 | "options": {
105 | "protractorConfig": "e2e/protractor.conf.js",
106 | "devServerTarget": "AngularAgoraRTCDemo:serve"
107 | },
108 | "configurations": {
109 | "production": {
110 | "devServerTarget": "AngularAgoraRTCDemo:serve:production"
111 | }
112 | }
113 | },
114 | "lint": {
115 | "builder": "@angular-devkit/build-angular:tslint",
116 | "options": {
117 | "tsConfig": "e2e/tsconfig.e2e.json",
118 | "exclude": [
119 | "**/node_modules/**"
120 | ]
121 | }
122 | }
123 | }
124 | },
125 | "angular-agora-rtc": {
126 | "root": "projects/angular-agora-rtc",
127 | "sourceRoot": "projects/angular-agora-rtc/src",
128 | "projectType": "library",
129 | "prefix": "lib",
130 | "architect": {
131 | "build": {
132 | "builder": "@angular-devkit/build-ng-packagr:build",
133 | "options": {
134 | "tsConfig": "projects/angular-agora-rtc/tsconfig.lib.json",
135 | "project": "projects/angular-agora-rtc/ng-package.json"
136 | },
137 | "configurations": {
138 | "production": {
139 | "project": "projects/angular-agora-rtc/ng-package.prod.json"
140 | }
141 | }
142 | },
143 | "test": {
144 | "builder": "@angular-devkit/build-angular:karma",
145 | "options": {
146 | "main": "projects/angular-agora-rtc/src/test.ts",
147 | "tsConfig": "projects/angular-agora-rtc/tsconfig.spec.json",
148 | "karmaConfig": "projects/angular-agora-rtc/karma.conf.js"
149 | }
150 | },
151 | "lint": {
152 | "builder": "@angular-devkit/build-angular:tslint",
153 | "options": {
154 | "tsConfig": [
155 | "projects/angular-agora-rtc/tsconfig.lib.json",
156 | "projects/angular-agora-rtc/tsconfig.spec.json"
157 | ],
158 | "exclude": [
159 | "**/node_modules/**"
160 | ]
161 | }
162 | }
163 | }
164 | }
165 | },
166 | "defaultProject": "AngularAgoraRTCDemo"
167 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## angular-agora-rtc
2 | > Angular 6 wrapper for Agora RTC client from https://www.agora.io/en/
3 |
4 | [](https://badge.fury.io/js/angular-agora-rtc)
5 | 
6 |
7 |
8 | ### Installation
9 | Install angular-agora-rtc and from npm:
10 | ```bash
11 | npm install angular-agora-rtc --save
12 | ```
13 |
14 | ### Examples
15 |
16 | ### Introduction
17 |
18 |
19 | ### Setup
20 |
21 | In your app's main module, import `AngularAgoraRtcModule` and `AgoraConfig` from `angular-agora-rtc` and add the module to the imports array. Create an instance of `AgoraConfig` and set `AppID` equal to the value found in your project list on Agora.io.
22 |
23 | ```ts
24 | import { BrowserModule } from '@angular/platform-browser';
25 | import { NgModule } from '@angular/core';
26 | import { AngularAgoraRtcModule, AgoraConfig } from 'angular-agora-rtc';
27 |
28 | import { AppComponent } from './app.component';
29 |
30 | const agoraConfig: AgoraConfig = {
31 | AppID: '1239021930912039-02193',
32 | };
33 |
34 | @NgModule({
35 | declarations: [
36 | AppComponent
37 | ],
38 | imports: [
39 | BrowserModule,
40 | AngularAgoraRtcModule.forRoot(agoraConfig)
41 | ],
42 | providers: [],
43 | bootstrap: [AppComponent]
44 | })
45 | export class AppModule { }
46 | ```
47 |
48 | You can then inject the `AngularAgoraRtcService` into your components constructor and call `createClient()` to create the broadcast client object
49 | **Note:** The broadcast client object can only be created once per call session.
50 | ```ts
51 | import { AngularAgoraRtcService } from 'angular-agora-rtc';
52 | ...
53 | constructor(
54 | private agoraService: AngularAgoraRtcService,
55 | ) {
56 | this.agoraService.createClient();
57 | }
58 | ...
59 | ```
60 |
61 | Once the client is created and initialization is complete, the user can now join the session by calling `client.join()`. Pass the channel key, channel name, and user ID to the method parameters:
62 | ```ts
63 | this.agoraService.client.join(null, '1000', null, (uid) => {
64 | });
65 | ```
66 | * Channel key: String used for broadcast security. For low security requirements, pass null as the parameter value.
67 | * Channel name: String that provides a unique channel name for the Agora session. This should be a numerical value for the Web SDK. The sample app uses channel.value (the value from the Channel UI text field).
68 | * User ID: The user ID is a 32-bit unsigned integer ranging from 1 to (2^32-1). If you set the user ID to null, the Agora server allocates a user ID and returns it in the onSuccess callback. If you decide to enter a specific user ID, make sure the integer is unique or an error will occur.
69 |
70 | **Note:** Users in the same channel can talk to each other, but users with different app IDs cannot call each other even if they join the same channel.
71 |
72 | Once this method is called successfully, the SDK triggers the callback with the user id as the parameter.
73 |
74 | ### Create and Manage a Stream
75 | * Host a Stream
76 | * Create a Stream
77 | * Set the Stream Video Profile
78 | * Set the Stream Event Listeners for Camera and Microphone Access
79 |
80 | #### Host a Stream
81 | If a user who has joined the stream will act as the host, the app must create a stream.
82 |
83 | #### Create a Stream
84 |
85 | If the user is a host, start the stream using the `this.agoraService.createStream()` method. The sample app passes in an object with the following properties:
86 | `this.localStream = this.agoraService.createStream(uid, true, null, null, true, false);`
87 |
88 | * streamID: The stream ID. Normally the stream ID is set as the user ID, which can be retrieved from the client.join() callback.
89 | * audio: Indicates if this stream contains an audio track.
90 | * cameraId: (Optional, defaults to first camera device found) All available video devices can be found by calling `agoraService.videoDevices`
91 | * microphoneId: (Optional, defaults to the first audio device found) All available audio devices can be found by calling `agoraService.audioDevices`
92 | * video: Indicates if this stream contains a video track.
93 | * screen: Indicates if this stream contains a screen sharing track. Currently screen sharing is only supported by the Google Chrome Explorer.
94 |
95 | The createStream object is set up for additional optional attributes. See the Agora API documentation for more information.
96 |
97 | #### Set the Stream Video Profile
98 | If the user is a host, the video profile must be set. The sample app sets the video profile to 720p_3, which represents a resolution of 1280x720, frame rate (fps) of 30, and a bitrate (kbps) of 1710. See the Agora API documentation for additional video profile options.
99 | `localStream.setVideoProfile('720p_3');`
100 |
101 | #### Set the Stream Event Listeners for Camera and Microphone Access
102 |
103 | Once the stream has been set up and configured, the sample app adds event listeners using the `localStream.on()` method to check for the user's microphone and camera permissions. These event listeners are used for debugging and to send alerts to request permissions. The sample app uses console logs to check if access to the camera and microphone was allowed or denied by the user.
104 |
105 | ```ts
106 | // The user has granted access to the camera and mic.
107 | this.localStream.on("accessAllowed", () => {
108 | console.log("accessAllowed");
109 | });
110 | // The user has denied access to the camera and mic.
111 | this.localStream.on("accessDenied", () => {
112 | console.log("accessDenied");
113 | });
114 | ```
115 | Next, the sample app initializes the stream by calling the `localStream.init()` method. Once initialized, the stream's host publishes the stream using the `client.publish()` method.
116 |
117 | ```ts
118 | this.localStream.init(() => {
119 | console.log("getUserMedia successfully");
120 | this.localStream.play('agora_local');
121 | this.agoraService.client.publish(this.localStream, (err) => console.log("Publish local stream error: " + err));
122 | this.agoraService.client.on('stream-published', (evt) => console.log("Publish local stream successfully"));
123 | }, (err) => console.log("getUserMedia failed", err));
124 | ```
125 |
126 | #### Setup Client Error Handling
127 | Passing error into the `client.on()` method will return the error type `err.reason`. The sample app uses this error type for debugging and re-invoking methods that failed.
128 |
129 | Since the Channel Key has an expiration, the sample app checks for the error `DYNAMIC_KET_TIMEOUT` in the `onFailure` callback. It then renews the channel key using the `client.renewChannelKey()` method.
130 |
131 | **Note:** If the channel key is not renewed, the communication to the SDK will disconnect.
132 |
133 | ```ts
134 | this.agoraService.client.on('error', (err) => {
135 | console.log("Got error msg:", err.reason);
136 | if (err.reason === 'DYNAMIC_KEY_TIMEOUT') {
137 | this.agoraService.client.renewChannelKey("",() =>{
138 | console.log("Renew channel key successfully");
139 | }, (err) =>{
140 | console.log("Renew channel key failed: ", err);
141 | });
142 | }
143 | });
144 | ```
145 | #### Add a Stream to the Client
146 | The stream-added event listener detects when a new stream is added to the client. The sample app subscribes the newly added stream to the client after a new stream is added to the client
147 | ```ts
148 | this.agoraService.client.on('stream-added', (evt) => {
149 | const stream = evt.stream;
150 | this.agoraService.client.subscribe(stream, (err) => {
151 | console.log("Subscribe stream failed", err);
152 | });
153 | });
154 | ```
155 | #### Subscribe a Stream to the Client and Add to the DOM
156 | The sample app uses the `stream-subscribed` event listener to detect when a new stream has been subscribed to the client, and to retrieve its stream ID using the `stream.getId()` method.
157 | ```ts
158 | this.agoraService.client.on('stream-subscribed', (evt) => {
159 | const stream = evt.stream;
160 | if (!this.remoteCalls.includes(`agora_remote${stream.getId()}`)) this.remoteCalls.push(`agora_remote${stream.getId()}`);
161 | setTimeout(() => stream.play(`agora_remote${stream.getId()}`), 1000);
162 | });
163 | ```
164 | Once the stream has been added to the `remoteCalls` array, the sample app sets a one second timeout to allow the change detection to run and render the new div. Then to play the stream we call the stream.play() method, passing in the string agora_remote followed by the stream ID.
165 |
166 | #### Remove a Stream from the Client
167 | If the stream is removed from the client, the `stream-removed` event listener is called, the sample app stops the stream from playing by calling the `stream.stop()` method. We then remove the stream from the `remoteCalls` array using the `filter()` method.
168 |
169 | ```ts
170 | this.agoraService.client.on('stream-removed', (evt) => {
171 | const stream = evt.stream;
172 | stream.stop();
173 | this.remoteCalls = this.remoteCalls.filter(call => call === `#agora_remote${stream.getId()}`);
174 | console.log(`Remote stream is removed ${stream.getId()}`);
175 | });
176 | ```
177 |
178 | #### Remove a Peer from the Client
179 | When the sample app detects that a peer leaves the client using the `peer-leave` event listener, it stops the stream from playing. We then remove the stream from the `remoteCalls` array using the `filter()` method.
180 | ```ts
181 | this.agoraService.client.on('peer-leave', (evt) => {
182 | const stream = evt.stream;
183 | if (stream) {
184 | stream.stop();
185 | this.remoteCalls = this.remoteCalls.filter(call => call === `#agora_remote${stream.getId()}`);
186 | console.log(`${evt.uid} left from this channel`);
187 | }
188 | });
189 | ```
190 | #### Leave a Channel
191 | The `client.leave()` method removes the user from the current video call (channel). The sample app checks if the action succeeds or fails using the `onSuccess` and `onFailure` callbacks.
192 | ```ts
193 | leave() {
194 | this.agoraService.client.leave(() => {
195 | console.log("Leavel channel successfully");
196 | }, (err) => {
197 | console.log("Leave channel failed");
198 | });
199 | }
200 | ```
201 |
202 |
--------------------------------------------------------------------------------
/projects/angular-agora-rtc/README.md:
--------------------------------------------------------------------------------
1 | ## angular-agora-rtc
2 | > Angular 6 wrapper for Agora RTC client from https://www.agora.io/en/
3 |
4 | [](https://badge.fury.io/js/angular-agora-rtc)
5 | 
6 |
7 |
8 | ### Installation
9 | Install angular-agora-rtc and from npm:
10 | ```bash
11 | npm install angular-agora-rtc --save
12 | ```
13 |
14 | ### Examples
15 |
16 | ### Introduction
17 |
18 |
19 | ### Setup
20 |
21 | In your app's main module, import `AngularAgoraRtcModule` and `AgoraConfig` from `angular-agora-rtc` and add the module to the imports array. Create an instance of `AgoraConfig` and set `AppID` equal to the the value found in your project list on Agora.io.
22 |
23 | ```ts
24 | import { BrowserModule } from '@angular/platform-browser';
25 | import { NgModule } from '@angular/core';
26 | import { AngularAgoraRtcModule, AgoraConfig } from 'angular-agora-rtc';
27 |
28 | import { AppComponent } from './app.component';
29 |
30 | const agoraConfig: AgoraConfig = {
31 | AppID: '1239021930912039-02193',
32 | };
33 |
34 | @NgModule({
35 | declarations: [
36 | AppComponent
37 | ],
38 | imports: [
39 | BrowserModule,
40 | AngularAgoraRtcModule.forRoot(agoraConfig)
41 | ],
42 | providers: [],
43 | bootstrap: [AppComponent]
44 | })
45 | export class AppModule { }
46 | ```
47 |
48 | You can then inject the `AngularAgoraRtcService` into your components constructor and call `createClient()` to create the broadcast client object
49 | **Note:** The broadcast client object can only be created once per call session.
50 | ```ts
51 | import { AngularAgoraRtcService } from 'angular-agora-rtc';
52 | ...
53 | constructor(
54 | private agoraService: AngularAgoraRtcService,
55 | ) {
56 | this.agoraService.createClient();
57 | }
58 | ...
59 | ```
60 |
61 | Once the client is created and initialization is complete, the user can now join the session by calling `client.join()`. Pass the channel key, channel name, and user ID to the method parameters:
62 | ```ts
63 | this.agoraService.client.join(null, '1000', null, (uid) => {
64 | });
65 | ```
66 | * Channel key: String used for broadcast security. For low security requirements, pass null as the parameter value.
67 | * Channel name: String that provides a unique channel name for the Agora session. This should be a numerical value for the Web SDK. The sample app uses channel.value (the value from the Channel UI text field).
68 | * User ID: The user ID is a 32-bit unsigned integer ranging from 1 to (2^32-1). If you set the user ID to null, the Agora server allocates a user ID and returns it in the onSuccess callback. If you decide to enter a specific user ID, make sure the integer is unique or an error will occur.
69 |
70 | **Note:** Users in the same channel can talk to each other, but users with different app IDs cannot call each other even if they join the same channel.
71 |
72 | Once this method is called successfully, the SDK triggers the callback with the user id as the parameter.
73 |
74 | ### Create and Manage a Stream
75 | * Host a Stream
76 | * Create a Stream
77 | * Set the Stream Video Profile
78 | * Set the Stream Event Listeners for Camera and Microphone Access
79 |
80 | #### Host a Stream
81 | If a user who has joined the stream will act as the host, the app must create a stream.
82 |
83 | #### Create a Stream
84 |
85 | If the user is a host, start the stream using the `this.agoraService.createStream()` method. The sample app passes in an object with the following properties:
86 | `this.localStream = this.agoraService.createStream(uid, true, null, null, true, false);`
87 |
88 | * streamID: The stream ID. Normally the stream ID is set as the user ID, which can be retrieved from the client.join() callback.
89 | * audio: Indicates if this stream contains an audio track.
90 | * cameraId: (Optional, defaults to first camera device found) All available video devices can be found by calling `agoraService.videoDevices`
91 | * microphoneId: (Optional, defaults to the first audio device found) All available audio devices can be found by calling `agoraService.audioDevices`
92 | * video: Indicates if this stream contains a video track.
93 | * screen: Indicates if this stream contains a screen sharing track. Currently screen sharing is only supported by the Google Chrome Explorer.
94 |
95 | The createStream object is set up for additional optional attributes. See the Agora API documentation for more information.
96 |
97 | #### Set the Stream Video Profile
98 | If the user is a host, the video profile must be set. The sample app sets the video profile to 720p_3, which represents a resolution of 1280x720, frame rate (fps) of 30, and a bitrate (kbps) of 1710. See the Agora API documentation for additional video profile options.
99 | `localStream.setVideoProfile('720p_3');`
100 |
101 | #### Set the Stream Event Listeners for Camera and Microphone Access
102 |
103 | Once the stream has been set up and configured, the sample app adds event listeners using the `localStream.on()` method to check for the user's microphone and camera permissions. These event listeners are used for debugging and to send alerts to request permissions. The sample app uses console logs to check if access to the camera and microphone was allowed or denied by the user.
104 |
105 | ```ts
106 | // The user has granted access to the camera and mic.
107 | this.localStream.on("accessAllowed", () => {
108 | console.log("accessAllowed");
109 | });
110 | // The user has denied access to the camera and mic.
111 | this.localStream.on("accessDenied", () => {
112 | console.log("accessDenied");
113 | });
114 | ```
115 | Next, the sample app initializes the stream by calling the `localStream.init()` method. Once initialized, the stream's host publishes the stream using the `client.publish()` method.
116 |
117 | ```ts
118 | this.localStream.init(() => {
119 | console.log("getUserMedia successfully");
120 | this.localStream.play('agora_local');
121 | this.agoraService.client.publish(this.localStream, (err) => console.log("Publish local stream error: " + err));
122 | this.agoraService.client.on('stream-published', (evt) => console.log("Publish local stream successfully"));
123 | }, (err) => console.log("getUserMedia failed", err));
124 | ```
125 |
126 | #### Setup Client Error Handling
127 | Passing error into the `client.on()` method will return the error type `err.reason`. The sample app uses this error type for debugging and re-invoking methods that failed.
128 |
129 | Since the Channel Key has an expiration, the sample app checks for the error `DYNAMIC_KET_TIMEOUT` in the `onFailure` callback. It then renews the channel key using the `client.renewChannelKey()` method.
130 |
131 | **Note:** If the channel key is not renewed, the communication to the SDK will disconnect.
132 |
133 | ```ts
134 | this.agoraService.client.on('error', (err) => {
135 | console.log("Got error msg:", err.reason);
136 | if (err.reason === 'DYNAMIC_KEY_TIMEOUT') {
137 | this.agoraService.client.renewChannelKey("",() =>{
138 | console.log("Renew channel key successfully");
139 | }, (err) =>{
140 | console.log("Renew channel key failed: ", err);
141 | });
142 | }
143 | });
144 | ```
145 | #### Add a Stream to the Client
146 | The stream-added event listener detects when a new stream is added to the client. The sample app subscribes the newly added stream to the client after a new stream is added to the client
147 | ```ts
148 | this.agoraService.client.on('stream-added', (evt) => {
149 | const stream = evt.stream;
150 | this.agoraService.client.subscribe(stream, (err) => {
151 | console.log("Subscribe stream failed", err);
152 | });
153 | });
154 | ```
155 | #### Subscribe a Stream to the Client and Add to the DOM
156 | The sample app uses the `stream-subscribed` event listener to detect when a new stream has been subscribed to the client, and to retrieve its stream ID using the `stream.getId()` method.
157 | ```ts
158 | this.agoraService.client.on('stream-subscribed', (evt) => {
159 | const stream = evt.stream;
160 | if (!this.remoteCalls.includes(`agora_remote${stream.getId()}`)) this.remoteCalls.push(`agora_remote${stream.getId()}`);
161 | setTimeout(() => stream.play(`agora_remote${stream.getId()}`), 1000);
162 | });
163 | ```
164 | Once the stream has been added to the `remoteCalls` array, the sample app sets a one second timeout to allow the change detection to run and render the new div. Then to play the stream we call the stream.play() method, passing in the string agora_remote followed by the stream ID.
165 |
166 | #### Remove a Stream from the Client
167 | If the stream is removed from the client, the `stream-removed` event listener is called, the sample app stops the stream from playing by calling the `stream.stop()` method. We then remove the stream from the `remoteCalls` array using the `filter()` method.
168 |
169 | ```ts
170 | this.agoraService.client.on('stream-removed', (evt) => {
171 | const stream = evt.stream;
172 | stream.stop();
173 | this.remoteCalls = this.remoteCalls.filter(call => call === `#agora_remote${stream.getId()}`);
174 | console.log(`Remote stream is removed ${stream.getId()}`);
175 | });
176 | ```
177 |
178 | #### Remove a Peer from the Client
179 | When the sample app detects that a peer leaves the client using the `peer-leave` event listener, it stops the stream from playing. We then remove the stream from the `remoteCalls` array using the `filter()` method.
180 | ```ts
181 | this.agoraService.client.on('peer-leave', (evt) => {
182 | const stream = evt.stream;
183 | if (stream) {
184 | stream.stop();
185 | this.remoteCalls = this.remoteCalls.filter(call => call === `#agora_remote${stream.getId()}`);
186 | console.log(`${evt.uid} left from this channel`);
187 | }
188 | });
189 | ```
190 | #### Leave a Channel
191 | The `client.leave()` method removes the user from the current video call (channel). The sample app checks if the action succeeds or fails using the `onSuccess` and `onFailure` callbacks.
192 | ```ts
193 | leave() {
194 | this.agoraService.client.leave(() => {
195 | console.log("Leavel channel successfully");
196 | }, (err) => {
197 | console.log("Leave channel failed");
198 | });
199 | }
200 | ```
201 |
202 |
--------------------------------------------------------------------------------