How To Develop Custom Utility Widgets For Interactive Live Streams

Devin Dixon
BingeWave

--

When developing a custom live streaming solution, there will come unique use cases for using some of the essential features utility features of video and audio conferencing. These features include:

  • Mute/Unmute Audio
  • Screensharing
  • Showing/Hiding Video
  • Recording
  • Broadcasting/Restreaming

One of the most powerful components of BingeWave’s interface is the ability to customize the experience completely. The entire UX/UI, design, color and logos can be changed to fit your needs. In this tutorial, we are going to learn how to build the basic utilities to that you can customize them to your needs.

Code And Requirements

Please read the information below on how to download the code and the developer requirements.

Developer Requirements

To create this app, we will be using the following tools and ask that the developer already know the basics of:

  • HTML
  • CSS
  • Javascript

Download The Code

The code in this tutorial is available online at our Github repository and can be downloaded and ran on your local computer. To get the code, please visit:

https://github.com/BingeWave/bingewave-widget-utilities

Organizer Account

Like all of our tutorials, our starting point will be a organizer account. This will allow you to access all our API features. Please read the tutorial on Setting up an Organizer Account if you have not already; it should only take a minute or two.

Watch The Video Tutorial

Watch the video tutorial along with reading the tutorial to see how to implement the features.

Re-Occurring Concepts

Before diving into this tutorial, there are a few re-occurring concepts that you will encounter several times. We are going to define them once here so we do not have to review for each widget.

Session vs. Account

In many of the routes you will call, there is the option of either entering the session_id or the account_id. To explain the difference between the two, a session is the single instance of the user on a device, and the account is all sessions of the user. Take the diagram below:

For example, if I want to disable the video of the user with Session 1, you would pass just the session_id to the disable video endpoint. If you wanted to disable the video for all the sessions, you would pass the account_id to the endpoint.

Participant Properties

When developing a widget, there is an object passed into all widgets called BWProperties. This object holds information about the live event, users, and other info. The item in that object we want to pay attention to is the participant, which contains information about the current screen we are on.

The important items from this user are:

  • is_audio_on: If the audio is mute or unmuted
  • is_video_on: If the video is on or off
  • is_sharing_desktop: If the user is sharing their current desktop or just their video.
  • is_sharing_video: This is NOT related to the desktop; it relates to if their video is shut off to everyone but the host(s)
  • session_id: The id of the current user’s session.

These properties will be used several times throughout the tutorial.

Events

BWEvents is a publisher-subscriber object. This means that a function somewhere in the code will send a message about an event that occurred, and your functions will listen for those events. An example of event listening is the code below:

BWEvents.subscribe('user_join', 'listener_1', function(response){
console.log(`${response.account.first-name} has joined!`);
});

For example, when a user signs up, you can listen for the new user’s information and write your own function to utilize that information. Event listening will be heavily used for audio, video, screen sharing, and other actions that occur in the API.

Namespace

The Namespace is a unique identifier for each Widget. The Namespace prevents naming conflicts if two global items are named the same, such as an id on an element. Namespacing will be used through this tutorial.

Mute/Unmute Audio

Audio is the sounds emitting from one user to another. In this part of the tutorial, we will learn how to unmute and mute a user’s audio input. We are going to start with the documentation of turning sound on and off here:

https://developers.bingewave.com/docs/status#unmuteaudiouser

Per the documentation, there are two routes we want to call.

  1. POST — https://bw.bingewave.com/events/{id}/setUserAudioUnmute
  2. POST — https://bw.bingewave.com/events/{id}/setUserAudioMute

Both of the routes require the ID of the live event, and either the session id or the user id. Now let us turn it into code.

First, head over to the Widgets section and create a widget. If this is your first time creating a widget, widgets are apps that can be overlayed into the live stream. The apps are composed of HTML, CSS, and Javascript. Use the ‘Create Widget’ button to create your first widget, and then proceed to the Interface Builder that contains the HTML, CSS, and Javascript editors.

In the widgets HTML, we are going to make Font Awesome mute and unmute and implement it as such:

The HTML above is doing two important things:

  1. Assigning the ID with Namespace to prevent naming collisions.
  2. The ID also contains the session_id as a dynamic placeholder that will be replaced with the user’s session. The muting/unmuting should only related to the current session.
  3. Assigning an onclick action to call a function with our widgets Namespace.

Now we are going to add a little CSS. The CSS will make sure that when a user mouse hovers over our icons, it becomes a pointer. Paste the following in the CSS editor:

In the code above, we use a namespace to ensure that the CSS class only affects elements defined in our widget and not other widgets.Next, in the Javascript editor, we will write an unmute and mute function to turn on and off the sound. The two functions will look as such:

The code above does the following:

  1. We pull out the fields we are going to be using multiple times. The event_id is the ID of the live event, the session_id for the participant on-screen, and the Namespace.
  2. After we define two functions that will toggle which mic is showing.
  3. We then define that if the audio for the current participant is one, we want to display that is it one; otherwise, we display that it is off.
  4. Using the API route above, we use BWAPI to call the endpoint referenced in the documentation above. If successful, will change the user’s mic icon.
  5. Finally, we set the two functions to the public Namespace. All functions inside a widget are private; assigning to a variable with this makes it public.

When you save your code and click the mic icon, it calls the API endpoint and toggles the mic on and off. We have to do one more addition to your code. There might be an instance where the mic is updated through the API from another source. We need to capture that event when it happens. Using BWEvents, there are the actions of user_mic_muted and user_mic_unmuted.

https://developers.bingewave.com/javascript/bwevents

We are going to implement the ability to listen to those events as such:

In this snippet, we are doing the following:

  1. Creating the subscribers to listen to when the user_mic_muted and user_mic_unmuted events occur.
  2. Checking to make sure that the session_id of the user that muted or unmuted their audio is the same session id of the current participant.
  3. Calling the functions to toggle the mic’s HTML.

And that’s it! Your complete Javascript code for the widget will look as such:

As we move on through the tutorial, many of the widgets will look the same except for broadcasting and recording. Because many of the implementations are so similar, we will keep the next few examples very brief.

Turning Video On and Off

For creating the video functionality, we are going to need a new widget. Start by going back the widgets section and create a new one. Then go to that widgets Interface Builder.

Turning on and off the video is very similar to muting and unmuting the audio, except for a few key differences. We will review those key differences and then post the code for you to compare.

API Endpoints: The API endpoints for turning and off a user’s video is found here: https://developers.bingewave.com/docs/status#videoonuser. But the variables being passed to the endpoint are the same.

Event Subscription: The events that are being subscribed to are now user_video_on and user_video_off.

Icons: The Font Awesome icons are changed to reflect the UI for turning and off a video.

With those slight adjustments in place, our code is now ready. The following should be the HTML, CSS, and Javascript for our video widget:

HTML

CSS

Javascript

Sharing Your Screen

Another example of the similar code being used from the previous two examples is sharing the user’s desktop and then being revered back to sharing to screen. Again it only slight changes to the code, but the same structure applies:

API Endpoints: The API endpoints sharing a user’s screen are found here: https://developers.bingewave.com/queries/status#sharedesktopuser . The values for turning on and off the desktop are the same ones in the video and audio endpoints.

Event Subscription: The events that are being subscribed to are now user_share_desktop and user_share_video.

Icons: The Font Awesome icons are changed to reflect the UI for turning and off a video.

With those slight adjustments in place, our code is now ready. The following should be the HTML, CSS, and Javascript for our video widget:

HTML

CSS

Javascript

Recording Utility

The recording utility is slightly different from sharing a user’s desktop, video, and audio. To begin understanding how recording is different, first, let us look at the API endpoint:

https://developers.bingewave.com/docs/eventcommands#startrecording

The two routes to start and stop a recording are:

  1. POST — https://bw.bingewave.com/events/{id}/startRecording
  2. POST — https://bw.bingewave.com/events/{id}/stopRecording

According to the documentation, the only value needed is the live event id. The problem we will face is the response does not return if the recording has started. We are going to use BWEvents to determine the status of the recording. For the beginning of our code, define some basic HTML of a start and stop record. Copy and paste this into the HTML of your Widget.

We are using the Namespace to ensure that the id we will assign this element is unique and calls the functions defined in the Javascript. Let’s add a little bit of CSS to the CSS section of the widget editor.

In the section, we are doing three things:

  1. We are using our Namespace to make sure out CSS is unique and does not conflict with any other style elements of other widgets or the system.
  2. Having a pointer so when the mouse hovers over our elements, it becomes a pointer.
  3. Making the recording button read

Next, we are going to modify our Javascript. Our Javascript will start by pulling the fields we will use several times into our widget’s global space.

Now we will define two functions that will control what is displayed on the screen.

The code above is doing the following:

  1. The functions ‘displayWhenRecording’ and ‘displayWhenNotRecording’ will be used to toggle the interface to show if something is recording.
  2. The if statement checks BWProperties to see if a recording is in progress and sets the interface using one of the two functions

Now we need the ability to call the API route for starting and stopping the recording. Referencing the documentation for recording mentioned above, our code will look like this:

To understand this snippet:

  1. The functions ‘startRecroding’ and ‘stopRecording’ are the same functions defined in the HTML.
  2. The functions only call the endpoint for starting and stopping a recording session. We are not using the promise returned because it will only tell us the signal was sent.
  3. By default, all functions inside widgets are private. They can be made public by attaching the function using this.

As mentioned above, the startRecording API endpoint just sends the signal; it does not know if the recording has started or not. Now the signal is received, there are three events fired that tell if the recording was successful:

https://developers.bingewave.com/javascript/bwevents

We need to listen for the recording status events, so our code should look like this when we subscribe using BWEvents:

Now we correctly set the interface depending on if a record has started or not. Your complete Javascript code will look like this:

Let’s move on to your last Widget, the broadcasting widget.

Broadcasting Utility

Our last widget is for broadcasting, and it is very similar to recording. Broadcasting is the ability to stream a live event from a video chat to multiple users watching on various devices. An illustration of a broadcast looks as such:

When doing the broadcasting, we only have to change a few things:

  1. Icons: The Icons are changing to better present broadcasting.
  2. Endpoints: The endpoint for broadcasting a stream is https://developers.bingewave.com/queries/eventcommands#startbroadcasting
  3. Events: The events to subscribe to using BWEvents are broadcasting_started, broadcasting_error, broadcasting_stopped.

With the changes in place, it’s time to make a widget. Go through the process of creating a widget, and let’s enter the following HTML, CSS, and Javascript.

HTML Code

CSS Code

Javascript Code

And with that, we now have several of your own custom utilities created for your video experiences.

Continuing With Customization

The goal of this tutorial was to illustrate how everything in the player is completely customizable, including the most basic functionality. If your organization needs a unique experience, you can easily create one.

--

--