Suggestions

close search

Customizing the UI — Web

These are the adjustments you can make to customize the user interface of OpenTok videos:

Setting the initial position and dimensions of a video

When you publish a video, you can specify the DOM element (or its ID) that the publisher will replace. You can also specify the initial width and height of the publisher:

// Replace the first parameter with ID of the target DOM element:
var publisher = OT.initPublisher('myPublisherElementId',
                                 {width:400, height:300});
session.publish(publisher);

You can also set the insertMode property of the options you pass into the OT.initPublisher() method to 'append' to have the publisher appended as a child of the DOM element (container) you specify:

var publisherOptions = {
  insertMode: 'append',
  width: 400,
  height: 300
};
var publisher = OT.initPublisher('publisherContainerElementId', publisherOptions);
session.publish(publisher);

Similarly, when you subscribe to a stream, you can specify the target DOM element (or its ID). You can also specify the initial width and height of the subscriber:

var options = {width: 400, height: 300, insertMode: 'append'}
var subscriber = session.subscribe(stream, 'containerElementId', options);

You can also specify the initial width and height of as a percentage of the size of the parent DOM element:

var publisherOptions = {
  insertMode: 'append',
  width: '100%',
  height: '100%'
};
var publisher = OT.initPublisher(publisherContainerElement, publisherOptions);
session.publish(publisher);

If you do not specify a replace element ID (or set it to null), the application appends a new DOM element to the HTML body. The default width is 264 pixels, and the default height is 198 pixels.

If you want to apply multiple CSS rules, apply it to the parent (container) DOM element:

<style>
    #publisherContainer.large
    { width: 640px; height: 480px; }
    #publisherContainer.small
    { width:100px; height: 100px; }
</style>
<div id="publisherContainer"></div>
<script>
    var publisher = OT.initPublisher('publisherContainer',
    {width: '100%', height: '100%', insertMode: 'append'}
</script>

To apply a different size to a video on a mobile device, use CSS media queries:

<style>
    #publisherContainer
    { width: 100px; height: 100px; }
    @media screen and (max-width: 650px) {
    #publisherContainer
    { width: 89px; height: 50px; }
    }
</style>
<div id="publisherContainer"></div>
<script>
    var publisher = OT.initPublisher('publisherContainer',
    {width: '100%', height: '100%', insertMode: 'append'}
</script>

If you will want to dynamically resize the video, set the insertMode to 'append' and set the height and width to '100%'.

See the next section for information on resizing or repositioning a publisher or subscriber video.

Resizing or repositioning a video

The element property of the Publisher or Subscriber object is its HTML DOM element. You can reposition this in the HTML DOM and resize the element by editing its style.width and style.height properties, just as you would any other DOM element:

document.getElementById("target").appendChild(publisher.element);
publisher.element.style.width = "100px";
publisher.element.style.height = "75px";

If you specify the initial width and height of the Publisher or Subscriber object as a percentage (such as "100%:), you can resize it by resizing one of its parent elements. The following example includes a function that resizes a Publisher:

<script type="text/javascript">
    var publisherOptions = {
        insertMode: "append",
        height: "100%",
        width: "100%"
    }
    var publisher = OT.initPublisher("publisherContainer", publisherOptions);
    session.publish(publisher);

    function resizePublisher() {
        var publisherContainer = document.getElementById("publisherContainer");
        publisherContainer.style.width = "1000px";
        publisherContainer.style.height = "750px";
    }
</script>

<div id="container">
    <div id="publisherContainer"></div>
    <a href="javascript:resizePublisher()">resize</a>
</div>

See the previous section, Setting the initial dimensions of a video for information on setting the initial position and dimensions of a publisher or subscriber.

Important: If you disable the default user interface of the publisher or subscriber by setting insertDefaultUI to false when instantiating the Publisher or Subscriber object, the element property of the Publisher or Subscriber will be undefined. Listen for the videoElementCreated event and use the element property of the event object to access the HTML DOM element for the Publisher or Subscriber. See Directly accessing the video element for a Publisher or Subscriber.

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 Creating a token.

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

Displaying or hiding the name in a video

When you publish a stream, you can specify a name to be displayed in the video (see the previous section).

When you create a Publisher, you can specify whether the name is displayed in the Publisher video, by setting the style.nameDisplayMode property of the options you pass into the OT.initPublisher() method:

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

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

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

When you subscribe to a stream, you can specify whether the name is displayed in the Subscriber video, by setting the style.nameDisplayMode property of the options you pass into the Session.subscribe() method:

// Replace the first two parameters with the stream and target element ID:
var subscriber = session.subscribe(stream,
  "mySubscriber",
  {
    style: { nameDisplayMode: "off" }
  });

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

Displaying or hiding the mute audio button

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. For a Subscriber, the user can click to toggle the speaker 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:

var 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:

Similarly, 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:

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

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

Adjusting video cropping and letterboxing

You can specify cropping or letterboxing of a Publisher or Subscriber's video by setting the fitMode property of the options you pass into OT.initPublisher() or Session.subscribe(). Pass in one of the following two strings:

For example, the following code initializes a publisher with the video element letterboxed:

var publisher = OT.initPublisher("publisher-element-id",
  {fitMode: "contain"});

The following code subscribes to a stream with the video element cropped:

var subscriber = session.subscribe(stream,
  "subscriber-element-id",
  {fitMode: "cover"});

Getting a snapshot image of a video

The following code captures and displays a static image of the Publisher video:

var imgData = publisher.getImgData();
var img = document.createElement("img");
img.setAttribute("src", "data:image/png;base64," + imgData);

// Replace with the parent DIV for the img
document.getElementById("containerId").appendChild(img);

The following code captures and displays a static image of a Subscriber video:

var imgData = subscriber.getImgData();
var img = document.createElement("img");
img.setAttribute("src", "data:image/png;base64," + imgData);

// Replace with the parent DIV for the img
document.getElementById("containerId").appendChild(img);

Setting an image to display in audio-only mode

You can use the backgroundImageURI style of a Subscriber to set the image to be displayed when there is no video. The value you set can be the URL of an image on the web. It can also be a data: URL, such as one that you obtain using the getImgData() method of the Subscriber object (see the previous section).

The following code sets the background image of the Subscriber. When the call to Session.subscribe() completes successfully, the background image is set. If there is a video stream, the background is set to a static image captured from the subscriber video; otherwise it is set to an image loaded from a web URL:

var subscriber = session.subscribe(event.stream, 'subscriberElement', function(error) {
  if (error) {
    console.log(error.message)'
    return;
  }
  if (subscriber.stream.hasVideo) {
    var imgData = subscriber.getImgData();
    subscriber.setStyle('backgroundImageURI', imgData);
  } else {
    subscriber.setStyle('backgroundImageURI',
      'https://tokbox.com/img/styleguide/tb-colors-cream.png'
    );
  }
});

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-righthand 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.)

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:

The videoDisableWarning and videoDisableWarningLifted events are only available in sessions that use the OpenTok 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.

Hiding all built-in user interface controls for videos

The Publisher and Subscriber objects include the following built-in user interface controls:

You can disable all of these by setting the showControls property to false in the properties parameter you pass into the OT.initPublisher() method or the Session.subscribe() method.

For example, the following code creates a Publisher object that includes no built-in user interface controls:

var publisherOptions = {
     showControls: false
  };
var publisher = OT.initPublisher(
  'publisher-element-id', // Replace with the replacement element ID
  publisherOptions
);

The following code creates a Subscriber object that includes no built-in user interface controls:

var subscriberOptions = {
     showControls: false
  };
var subscriber = session.subscribe(stream,
  'subscriber-element-id', // Replace with the replacement element ID
  subscriberOptions
);

You can control the display of individual user interface controls by leaving the showControls property set to true (the default); then see these topics:

Directly accessing the video element for a Publisher or Subscriber

You can disable the default user interface elements for a Publisher or Subscriber and access the HTML video element directly. When publishing or subscribing to a stream, set the insertDefaultUI property to false when calling the OT.initPublisher() or Session.subscribe() method. If you set this option to false, OpenTok.js does not insert a default UI element in the HTML DOM, and the element property of the Publisher or Subscriber object is undefined. Instead, the Publisher element dispatches a videoElementCreated event when the video element (or in Internet Explorer the object element containing the video) is created. The element property of the event object is a reference to the video (or object) element. Add it to the HTML DOM to display the video.

The following code initializes a publisher and inserts its video element into the HTML DOM:

var publisher = OT.initPublisher({insertDefaultUI: false});
publisher.on('videoElementCreated', function(event) {
  document.getElementById('publisher-video-parent-id').appendChild(event.element);
});

The following code subscribes to a stream and inserts its video element into the HTML DOM:

var subscriber = session.subscribe(stream, {insertDefaultUI: false});
subscriber.on('videoElementCreated', function(event) {
  document.getElementById('subscriber-video-parent-id').appendChild(event.element);
});

If you set the insertDefaultUI property to false, do not set the targetElement parameter when calling OT.initPublisher() or Session.subscribe(). (This results in an error.)

The default user inteface element contains user interface controls, a video loading indicator, and automatic video cropping or letter-boxing, in addition to the video. If you leave insertDefaultUI set to true (the default), you can control individual user inteface settings using the fitMode, showControls, and style options. See the other topics in this page.