ionic-capacitor: Added mute and toggle media devices
This commit is contained in:
parent
3b7ab62b4c
commit
cc87de9541
@ -7,9 +7,9 @@
|
||||
"ng": "ng",
|
||||
"start": "ng serve",
|
||||
"build": "ng build",
|
||||
"android": "ionic cap run android -l --external",
|
||||
"ios": "ionic cap run ios",
|
||||
"sync": "ionic capacitor sync android --watch",
|
||||
"android": "ionic capacitor run android",
|
||||
"ios": "ionic capacitor run ios",
|
||||
"sync": "ionic capacitor sync android",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e"
|
||||
|
||||
@ -1,61 +1,55 @@
|
||||
<ion-app class="transparent">
|
||||
<ion-header>
|
||||
<ion-toolbar color="dark">
|
||||
<img
|
||||
class="demo-logo"
|
||||
src="assets/images/openvidu_vert_white_bg_trans_cropped.png"
|
||||
/>
|
||||
<ion-buttons slot="primary">
|
||||
<ion-button
|
||||
color="light"
|
||||
href="https://github.com/OpenVidu/openvidu-tutorials/tree/master/openvidu-ionic"
|
||||
>
|
||||
<ion-icon slot="icon-only" name="logo-github"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-header>
|
||||
<ion-toolbar color="dark">
|
||||
<img class="demo-logo" src="assets/images/openvidu_vert_white_bg_trans_cropped.png" />
|
||||
<ion-buttons slot="primary">
|
||||
<ion-button color="light" href="https://github.com/OpenVidu/openvidu-tutorials/tree/master/openvidu-ionic">
|
||||
<ion-icon slot="icon-only" name="logo-github"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
||||
<ion-content class="ion-padding transparent" *ngIf="!session">
|
||||
<div id="img-div">
|
||||
<img src="assets/images/openvidu_grey_bg_transp_cropped.png" />
|
||||
</div>
|
||||
<h1 align="center" id="title">Join a video session</h1>
|
||||
<ion-item>
|
||||
<ion-label position="floating">Participant</ion-label>
|
||||
<ion-input [(ngModel)]="myUserName"></ion-input>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label position="floating">Session</ion-label>
|
||||
<ion-input [(ngModel)]="mySessionId"></ion-input>
|
||||
</ion-item>
|
||||
<ion-content class="ion-padding transparent" *ngIf="!session">
|
||||
<div id="img-div">
|
||||
<img src="assets/images/openvidu_grey_bg_transp_cropped.png" />
|
||||
</div>
|
||||
<h1 align="center" id="title">Join a video session</h1>
|
||||
<ion-item>
|
||||
<ion-label position="floating">Participant</ion-label>
|
||||
<ion-input [(ngModel)]="myUserName"></ion-input>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label position="floating">Session</ion-label>
|
||||
<ion-input [(ngModel)]="mySessionId"></ion-input>
|
||||
</ion-item>
|
||||
|
||||
<ion-button
|
||||
id="join-button"
|
||||
[disabled]="!mySessionId && !myUserName"
|
||||
(click)="joinSession()"
|
||||
expand="block"
|
||||
shape="round"
|
||||
color="primary"
|
||||
>
|
||||
<ion-icon slot="start" name="videocam"></ion-icon>
|
||||
Join
|
||||
</ion-button>
|
||||
<ion-button
|
||||
id="join-button"
|
||||
[disabled]="!mySessionId && !myUserName"
|
||||
(click)="joinSession()"
|
||||
expand="block"
|
||||
shape="round"
|
||||
color="primary"
|
||||
>
|
||||
<ion-icon slot="start" name="videocam"></ion-icon>
|
||||
Join
|
||||
</ion-button>
|
||||
|
||||
<ion-fab vertical="bottom" horizontal="end" slot="fixed">
|
||||
<ion-fab-button
|
||||
id="settings-button"
|
||||
[disabled]="!mySessionId && !myUserName"
|
||||
(click)="presentSettingsAlert()"
|
||||
size="small"
|
||||
color="dark"
|
||||
>
|
||||
<ion-icon name="settings"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab>
|
||||
</ion-content>
|
||||
<ion-fab vertical="bottom" horizontal="end" slot="fixed">
|
||||
<ion-fab-button
|
||||
id="settings-button"
|
||||
[disabled]="!mySessionId && !myUserName"
|
||||
(click)="presentSettingsAlert()"
|
||||
size="small"
|
||||
color="dark"
|
||||
>
|
||||
<ion-icon name="settings"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab>
|
||||
</ion-content>
|
||||
|
||||
<ion-content [scrollEvents]="true" (ionScroll)="refreshVideos()" *ngIf="session" class="transparent">
|
||||
<ion-content [scrollEvents]="true" *ngIf="session" class="transparent">
|
||||
<div id="session-header">
|
||||
<h1 id="session-title">{{ mySessionId }}</h1>
|
||||
</div>
|
||||
@ -77,8 +71,20 @@
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
|
||||
<ion-fab vertical="bottom" horizontal="center" slot="fixed">
|
||||
<ion-fab-button size="small" color="danger" (click)="leaveSession()">
|
||||
<ion-fab vertical="bottom" horizontal="end" slot="fixed">
|
||||
<ion-fab-button class="action-button" color="light" id="camButton" (click)="swapCamera()">
|
||||
<ion-icon name="camera-reverse-sharp"></ion-icon>
|
||||
</ion-fab-button>
|
||||
|
||||
<ion-fab-button (click)="toggleMicrophone()" class="action-button">
|
||||
<ion-icon name="{{ microphoneIcon }}"></ion-icon>
|
||||
</ion-fab-button>
|
||||
|
||||
<ion-fab-button (click)="toggleCamera()" class="action-button">
|
||||
<ion-icon name="{{ cameraIcon }}"></ion-icon>
|
||||
</ion-fab-button>
|
||||
|
||||
<ion-fab-button color="danger" (click)="leaveSession()" class="action-button">
|
||||
<ion-icon name="power"></ion-icon>
|
||||
</ion-fab-button>
|
||||
</ion-fab>
|
||||
|
||||
@ -24,3 +24,7 @@
|
||||
ion-col {
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
import { Component, HostListener, OnDestroy, OnInit } from '@angular/core';
|
||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
|
||||
import { OpenVidu, Publisher, Session, StreamEvent, StreamManager, Subscriber } from 'openvidu-browser';
|
||||
import { Device, OpenVidu, Publisher, PublisherProperties, Session, StreamEvent, StreamManager, Subscriber } from 'openvidu-browser';
|
||||
import { throwError as observableThrowError } from 'rxjs';
|
||||
import { catchError } from 'rxjs/operators';
|
||||
import { AlertController, Platform } from '@ionic/angular';
|
||||
@ -34,6 +34,16 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
mySessionId: string;
|
||||
myUserName: string;
|
||||
|
||||
cameraIcon = 'videocam';
|
||||
microphoneIcon = 'mic';
|
||||
|
||||
private devices: Device[];
|
||||
private cameras: Device[];
|
||||
private microphones: Device[];
|
||||
private cameraSelected: Device;
|
||||
private microphoneSelected: Device;
|
||||
private isFrontCamera = true;
|
||||
|
||||
constructor(
|
||||
private httpClient: HttpClient,
|
||||
private platform: Platform,
|
||||
@ -61,6 +71,8 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
|
||||
this.OV = new OpenVidu();
|
||||
|
||||
this.initDevices();
|
||||
|
||||
// --- 2) Init a session ---
|
||||
|
||||
this.session = this.OV.initSession();
|
||||
@ -113,14 +125,14 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
// Init a publisher passing undefined as targetElement (we don't want OpenVidu to insert a video
|
||||
// element: we will manage it on our own) and with the desired properties
|
||||
const publisher: Publisher = this.OV.initPublisher(undefined, {
|
||||
audioSource: undefined, // The source of audio. If undefined default microphone
|
||||
videoSource: undefined, // The source of video. If undefined default webcam
|
||||
audioSource: this.microphones[0].deviceId, // The source of audio. If undefined default microphone
|
||||
videoSource: this.cameras[0].deviceId, // The source of video. If undefined default webcam
|
||||
publishAudio: true, // Whether you want to start publishing with your audio unmuted or not
|
||||
publishVideo: true, // Whether you want to start publishing with your video enabled or not
|
||||
resolution: '640x480', // The resolution of your video
|
||||
frameRate: 30, // The frame rate of your video
|
||||
insertMode: 'APPEND', // How the video is inserted in the target element 'video-container'
|
||||
mirror: true // Whether to mirror your local video or not
|
||||
mirror: this.isFrontCamera // Whether to mirror your local video or not
|
||||
});
|
||||
|
||||
// --- 6) Publish your stream ---
|
||||
@ -149,6 +161,43 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
this.generateParticipantInfo();
|
||||
}
|
||||
|
||||
async swapCamera() {
|
||||
try {
|
||||
const newCamera = this.cameras.find((cam) => cam.deviceId !== this.cameraSelected.deviceId);
|
||||
if (!!newCamera) {
|
||||
this.isFrontCamera = !this.isFrontCamera;
|
||||
const pp: PublisherProperties = {
|
||||
videoSource: newCamera.deviceId,
|
||||
audioSource: false,
|
||||
mirror: this.isFrontCamera
|
||||
};
|
||||
|
||||
// Stopping the video tracks after request for another MediaStream
|
||||
this.publisher.stream.getMediaStream().getVideoTracks().forEach((track) => {
|
||||
track.stop();
|
||||
});
|
||||
const newTrack = await this.OV.getUserMedia(pp);
|
||||
const videoTrack: MediaStreamTrack = newTrack.getVideoTracks()[0];
|
||||
await (this.publisher as Publisher).replaceTrack(videoTrack);
|
||||
this.cameraSelected = newCamera;
|
||||
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
toggleCamera() {
|
||||
const publish = !this.publisher.stream.videoActive;
|
||||
(this.publisher as Publisher).publishVideo(publish, true);
|
||||
this.cameraIcon = publish ? 'videocam' : 'eye-off';
|
||||
}
|
||||
|
||||
toggleMicrophone() {
|
||||
const publish = !this.publisher.stream.audioActive;
|
||||
(this.publisher as Publisher).publishAudio(publish);
|
||||
this.microphoneIcon = publish ? 'mic' : 'mic-off';
|
||||
}
|
||||
|
||||
async presentSettingsAlert() {
|
||||
const alert = await this.alertController.create({
|
||||
header: 'OpenVidu Server config',
|
||||
@ -185,6 +234,16 @@ export class AppComponent implements OnInit, OnDestroy {
|
||||
await alert.present();
|
||||
}
|
||||
|
||||
private async initDevices() {
|
||||
this.devices = await this.OV.getDevices();
|
||||
|
||||
this.cameras = this.devices.filter((d) => d.kind === 'videoinput');
|
||||
this.microphones = this.devices.filter((d) => d.kind === 'audioinput' && d.label !== 'Default');
|
||||
|
||||
this.cameraSelected = this.cameras[0];
|
||||
this.microphoneSelected = this.microphones[0];
|
||||
}
|
||||
|
||||
private checkAndroidPermissions(): Promise<void> {
|
||||
console.log('Requesting Android Permissions');
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user