openvidu-toggle-hand 🔗
openvidu-toggle-hand is an Angular app developed with openvidu-angular library and its powerful components for customization. It features a toggle hand button that allows participants to ask for a turn to speak. This tutorial uses the addition of a very simple feature to demonstrate the power of openvidu-angular library and how to customize and extend its pre-built components.
Running this tutorial 🔗
To run the tutorial you need the three components stated in OpenVidu application architecture: an OpenVidu deployment, your server application and your client application. In this order:
1. Run OpenVidu deployment 🔗
Using Docker Engine:
# WARNING: this container is not suitable for production deployments of OpenVidu
# Visit https://docs.openvidu.io/en/stable/deployment
docker run -p 4443:4443 --rm -e OPENVIDU_SECRET=MY_SECRET openvidu/openvidu-dev:2.28.0
2. Run your preferred server application sample 🔗
For more information visit Application server.
3. Run the client application tutorial 🔗
You need NPM and Angular CLI to serve the application. Check them with the following command:
npm -v
ng v
To serve the tutorial:
# Using the same repository openvidu-tutorials from step 2
cd openvidu-tutorials/openvidu-components/openvidu-toggle-hand
npm install
ng serve
Go to http://localhost:4200
to test the app once the server is running.
To test the application with other devices in your network, visit this FAQ
Understanding the code 🔗
This application is a simple Angular app using openvidu-angular library. It uses prebuilt components to
The files we are going to focus on are the following ones:
app/app.module.ts
: app file where openvidu-angular library is initialized.app/app.component.ts
: component file with all the logic. It requests OpenVidu tokens and handles the toggle hand feature.app/app.component.html
: component template view where openvidu-angular components can be placed and customized.
First, we need to install the openvidu-angular library. You can check how to do that here. After that we are ready to include openvidu-angular components into our app.
Let's focus on the app.component.html
template to see how to customize the VideoconferenceComponent to achieve the toggle hand feature.
For remote participants, we need to know when someone has requested the turn to speak and show an icon on top of their video stream, so everybody knows they want to take the floor. To achieve this we subscribe to the onSessionCreated
output event of ov-videoconference
element.
<ov-videoconference (onSessionCreated)="onSessionCreated($event)" [tokens]="tokens" [prejoin]="true">
...
</ov-videoconference>
The onSessionCreated
method is invoked when the OpenVidu Session has been initialized. We use this event to subscribe to the handToggle
signal so we know when a remote participant has raised their hand. To do this, we use the signal method provided by openvidu-browser SDK.
onSessionCreated(session: Session) {
this.session = session;
this.handleRemoteHand();
}
handleRemoteHand() {
// Subscribe to hand toggling events from other participants
this.session.on(`signal:${SignalApp.HAND_TOGGLE}`, (event: any) => {
const connectionId = event.from.connectionId;
const participant = <ParticipantAppModel>this.participantService.getRemoteParticipantByConnectionId(connectionId);
if (participant) {
participant.toggleHandRaised();
this.participantService.updateRemoteParticipants();
}
});
}
For the local participant, we need to include a custom button in the ToolbarComponent. We do so by adding an element tagged with the ToolbarAdditionalButtonsDirective (*ovToolbarAdditionalButtons
).
<ov-videoconference (onSessionCreated)="onSessionCreated($event)" [tokens]="tokens" [prejoin]="true">
<div *ovToolbarAdditionalButtons>
<button toolbar-btn mat-icon-button (click)="handleLocalHand()" [class.active-btn]="hasHandRaised">
<mat-icon matTooltip="Toggle hand">front_hand</mat-icon>
</button>
</div>
...
</ov-videoconference>
This button allows the local user to raise their hand. Whenever it is clicked, method handleLocalHand
is called.
handleLocalHand() {
// Get local participant with ParticipantService
const participant = <ParticipantAppModel>this.participantService.getLocalParticipant();
// Toggle the participant hand with the method we wil add in our ParticipantAppModel
participant.toggleHandRaised();
// Refresh the local participant object for others component and services
this.participantService.updateLocalParticipant();
// Send a signal with the new value to others participant using the openvidu-browser signal
const remoteConnections = this.openviduService.getRemoteConnections();
if (remoteConnections.length > 0) {
//Sending hand toggle signal to others
const signalOptions: SignalOptions = {
type: SignalApp.HAND_TOGGLE,
to: remoteConnections
};
this.session.signal(signalOptions);
}
}
This method shows an icon on the local video to let the user know they have requested the turn to speak, and send a handToggle
signal to the rest of users. This signal will trigger the handleRemoteHand
method as explained above.
We also need to customize the StreamComponent injecting a new element when a participant raises their hand:
<ov-videoconference (onSessionCreated)="onSessionCreated($event)" [tokens]="tokens" [prejoin]="true">
...
<div *ovStream="let stream" style="height: 100%">
<ov-stream [stream]="stream"></ov-stream>
<button mat-icon-button @inOutHandAnimation id="hand-notification" *ngIf="stream.participant.hasHandRaised">
<mat-icon>front_hand</mat-icon>
</button>
</div>
...
</ov-videoconference>
Now, using the StreamDirective (*ovStream
) we can customize the StreamComponent and we can add whatever we want to it. In this case we simply add an icon button indicating the participant has raised their hand.
We also add the hand notification to the participants panel. We handle this using the ParticipantPanelItemElementsDirective (*ovParticipantPanelItemElements
). In this case we simply add an icon button indicating the participant has raised their hand.
<ov-videoconference (onSessionCreated)="onSessionCreated($event)" [tokens]="tokens" [prejoin]="true">
...
<div *ovParticipantPanelItemElements="let participant">
<button mat-icon-button *ngIf="participant.hasHandRaised">
<mat-icon>front_hand</mat-icon>
</button>
</div>
</ov-videoconference>
As you can see we assign a participant variable to the *ovParticipantPanelItemElements
directive (let participant
). In this way we are able access the participant's properties in our custom HTML template. In this case, the hasHandRaised
property.
Following this line of reasoning, we need a new property (hasHandRaised
) in the ParticipantAbstractModel. We have to extend the ParticipantAbstractModel from openvidu-angular library. See ParticipantAppModel
class under app/models/
folder:
import { ParticipantAbstractModel } from 'openvidu-angular';
export class ParticipantAppModel extends ParticipantAbstractModel {
hasHandRaised: boolean;
toggleHandRaised() {
this.hasHandRaised = !this.hasHandRaised;
}
}
Once we have extended the ParticipantAbstractModel, we need to configure openvidu-angular library to use this new class. To achieve this we add a participantFactory
in app.module.ts
and assign it to the OpenViduAngularConfig
:
const config: OpenViduAngularConfig = {
production: environment.production,
participantFactory: (props: ParticipantProperties, streamModel: StreamModel) => new ParticipantAppModel(props, streamModel)
};
Now we can get our custom hasHandRaised
participant property in the ParticipantsPanelComponent and in the StreamComponent.
Deploying openvidu-toggle-hand 🔗
1) Build the docker image 🔗
Under the root project folder, you can see the openvidu-components/docker/
directory. Here it is included all the required files yo make it possible the deployment with OpenVidu.
First of all, you will need to create the openvidu-toggle-hand docker image. Under openvidu-components/docker/
directory you will find the create_image.sh
script. This script will create the docker image with the openvidu-basic-node as application server and the static files.
./create_image.sh openvidu/openvidu-toggle-hand-demo:X.Y.Z openvidu-toggle-hand
The script needs two parameters:
- The name of the docker image to create.
- The name of the tutorial folder.
This script will create an image named openvidu/openvidu-toggle-hand-demo:X.Y.Z
. This name will be used in the next step.
2) Deploy the docker image 🔗
Time to deploy the docker image. You can follow the Deploy OpenVidu based application with Docker guide for doing this.