General Customization

There are a number of adjustments you can make to customize the Vonage Video user interface:

Adding a name for a published stream

When you create a Publisher, you can (optionally) specify a name to be displayed in the video:

// Replace the first parameter with the target element ID:
var publisher = OT.initPublisher("myPublisher",
                                 {name: "John"})
session.publish(publisher);

You can use this name to identify the client.

Note that you can also add metadata about the client when you create a token. This name is not automatically displayed in the video. However, by adding the data when you create a token, you can add information more securely (since tokens are created on the server, not on the client. For more information, see Token creation.

Clients can choose to hide the name in a Publisher or Subscriber view. See this section

Adding a mute button for a publisher

By default, the user interface for a Publisher or a Subscriber includes a mute audio button. For a Publisher, the user can click to toggle the mic on and off.

When you publish a stream, you can specify whether the mute button is displayed by passing a style.buttonDisplayMode property into the OT.initPublisher() method:

const publisher = OT.initPublisher(
  'publisher-element-id', // Replace with the replacement element ID
  {
     name: 'John',
     style: {buttonDisplayMode: 'on'}
  }
);
session.publish(publisher);

The style.buttonDisplayMode property can be set to one of three values:

  • "auto" — The mute button is displayed when the stream is first displayed and when the user mouses over the video (the default).
  • "off" — The mute button is not displayed.
  • "on" — The mute button is displayed.

Once you have created the Publisher, you can change the mute button display mode, by calling the setStyle() method of the Publisher object. See the documentation for Publisher.setStyle().

Adding a mute button for a subscriber

By default, the user interface for a Publisher or a Subscriber includes a mute audio button. For a Subscriber, the user can click to toggle the speaker on and off.

When you subscribe to a stream, you can specify whether the mute speaker is displayed by passing a style.buttonDisplayMode property into the Session.subscribe() method:

const subscriber = session.subscribe(stream,
  'subscriber-element-id', // Replace with the replacement element ID
  {
     style: {buttonDisplayMode: 'on'}
  }
);

The style.buttonDisplayMode property can be set to one of three values:

  • "auto" — The mute button is displayed when the stream is first displayed and when the user mouses over the video (the default).
  • "off" — The mute button is not displayed.
  • "on" — The mute button is displayed.

Once you have created the Subscriber, you can change the mute button display mode, by calling the setStyle() method of the Subscriber object. See the documentation for Subscriber.setStyle().

Adding a button to toggle the publisher's camera

There is no default user interface element to toggle the camera used by the publisher. However, you can add and element, such as a button, that calls the swapCamera method of the Publisher object:

mPublisher.swapCamera();

Note that the cameraPosition property is not available in the PublisherKit class. If you are using the PublisherKit class to implement a custom video capturer, you can define the camera used in the custom video capturing code.

Adjusting user interface when video is enabled or disabled

A Subscriber objects dispatches the following events related to the video being enabled or disabled for the subscriber's stream:

  • videoEnabled — Dispatched when the video has been enabled after it was previously disabled.
  • videoDisabled — Dispatched when the video has been disabled. The reason property of the event object indicates why the video was disabled. (This event object is an VideoEnabledChangedEvent object.)
  • videoDisableWarning — Dispatched when the Media Router determines that the stream quality has degraded and the video will be disabled if the quality degrades more. If the quality degrades further, the Subscriber disables the video and dispatches a videoDisabled event.
  • videoDisableWarningLifted — The video has been enabled after it was previously disabled.

The videoDisableWarning and videoDisableWarningLifted events are only available in sessions that use the Media Router (sessions with the media mode set to routed).

By default, the Subscriber displays a video disabled warning indicator and a video disabled indicator when the videoDisableWarning and videoDisableWarningLifted events are dispatched. You can disable the default display of the indicator by setting the videoDisabledDisplayMode style setting of the Subscriber object.

The following example uses the videoDisabledDisplayMode style setting to have the video disabled warning indicator and a video disabled indicator blink every one second when the videoDisableWarning and videoDisableWarningLifted events are dispatched:

var indicatorBlinker = new IndicatorBlinker(subscriber);

var IndicatorBlinker = function(subscriber) {
  var timer;
  var indicatorOn = false;
  subscriber.on({
    videoDisabled: function(event) {
      start();
    },
    videoDisableWarning: function(event) {
      start();
    },
    videoDisableWarningLifted: function(event) {
      stop();
    },
    videoEnabled: function(event) {
      stop();
    }
  });
  var start = function() {
    subscriber.setStyle('videoDisabledDisplayMode', 'on');
    if (timer) {
      clearInterval(timer);
    }
    timer = setInterval(function() {
      if (indicatorOn) {
        subscriber.setStyle('videoDisabledDisplayMode', 'off');
      } else {
        subscriber.setStyle('videoDisabledDisplayMode', 'on');
      }
      indicatorOn = !indicatorOn;
    }, 1000);
    indicatorOn = true;
  };
  var stop = function() {
    if (timer) {
      clearInterval(timer);
    }
  };
};

You can also set the videoDisabledDisplayMode style to 'off' and add your own user interface elements based on the videoDisableWarning, videoDisabled, videoDisableWarningLifted, and videoEnabled events.

Displaying an indicator element when a session is being archived

When a archive of a session starts recording (or if you connect to a session that is being recorded), the Session.ArchiveListener.onArchiveStarted(session, name) method is called. When the recording stops the Session.ArchiveListener.onArchiveStopped(session, name) method is called. You can add a user interface element, such as an icon displayed in a publisher view, to indicate that a video is being recorded:

@Override
public void onArchiveStarted(Session session, String id, String name) {
    // Display the archive indicator
}

@Override
public void onArchiveStopped(Session session, String id, String name) {
    // Hide the archive indicator
}

Adjusting user interface based on audio levels

Publisher and Subscriber objects dispatch audioLevelUpdated events periodically to report the audio level. You can use these events to display an audio level indicator. You can also use these events to detect active speakers in a session.

The following example adjusts the value of a meter element that shows volume of a subscriber. The code sets the audioLevelDisplayMode style to 'off', which disables the default audio level meter displayed in the Subscriber. Note that the audio level is adjusted logarithmically and a moving average is applied:

subscriber.setStyle('audioLevelDisplayMode', 'off');
var movingAvg = null;
subscriber.on('audioLevelUpdated', function(event) {
  if (movingAvg === null || movingAvg <= event.audioLevel) {
    movingAvg = event.audioLevel;
  } else {
    movingAvg = 0.7 * movingAvg + 0.3 * event.audioLevel;
  }

  // 1.5 scaling to map the -30 - 0 dBm range to [0,1]
  var logLevel = (Math.log(movingAvg) / Math.LN10) / 1.5 + 1;
  logLevel = Math.min(Math.max(logLevel, 0), 1);
  document.getElementById('subscriberMeter').value = logLevel;
});

The example assumes that there is an HTML meter element with the ID "subscriberMeter".

Note that in audio-only mode, a Publisher or Subscriber DOM element displays a volume indicator by default (in the upper right-hand corner of the element). You can disable this default user interface element and display your own volume meter. See the next topic, Adjusting user interface when video is enabled or disabled.

You can also use the audioLevelUpdated event to determine when a publisher or subscriber's audio is loud enough for long enough to label the participant as having started talking. Or, if the audio has been quiet for long enough, you can identify the participant as having stopped talking:

var subscriber = session.subscribe(event.stream);

SpeakerDetection(subscriber, function() {
  console.log('started talking');
}, function() {
  console.log('stopped talking');
});

var SpeakerDetection = function(subscriber, startTalking, stopTalking) {
  var activity = null;
  subscriber.on('audioLevelUpdated', function(event) {
    var now = Date.now();
    if (event.audioLevel > 0.2) {
      if (!activity) {
        activity = {timestamp: now, talking: false};
      } else if (activity.talking) {
        activity.timestamp = now;
      } else if (now- activity.timestamp > 1000) {
        // detected audio activity for more than 1s
        // for the first time.
        activity.talking = true;
        if (typeof(startTalking) === 'function') {
          startTalking();
        }
      }
    } else if (activity && now - activity.timestamp > 3000) {
      // detected low audio activity for more than 3s
      if (activity.talking) {
        if (typeof(stopTalking) === 'function') {
          stopTalking();
        }
      }
      activity = null;
    }
  });
};

(Instead of logging to the console, your app could adjust a user interface element when the user starts and stops talking.

Using a custom video renderer

The Subscriber and Publisher classes implement a standard video renderer that renders the stream and provides user interface controls for displaying the stream name and muting the microphone or camera. You can use the SubscriberKit and PublisherKit classes to implement a custom video renderer.

The Android SDK includes a BaseVideoRenderer class. Override this class to create a custom video renderer.

After instantiating a PublisherKit object, you can set a custom video renderer by calling the setRenderer() method of the PublisherKit object:

mPublisher = new PublisherKit(MyClass.this, "publisher");

// Use a custom video renderer.
// MyVideoRenderer extends BaseVideoRenderer
mRenderer = new MyVideoRenderer();
mPublisher.setRenderer(new mRenderer);

The SubscriberKit class also has a setRenderer() method.

The onFrame() method of the BaseVideoRenderer class is called when a new frame is available:

public void onFrame(Frame frame) {
    // The new frame is available.
}

The frame is a BaseVideoRenderer.Frame object. This object includes a getBuffer() that returns the byte buffer containing the video frame data. You can use this byte buffer to add the video frame image to the publisher's view.

For an example, see the OpenTokVideoRenderer class in the OpenTokHelloWorld sample application.

You can also set up a publisher to use a custom video capturer.