Subscribe: Management & Events

This guide covers managing Subscriber behavior and reacting to runtime events.

Managing Subscriber Streams (React Native)

Detecting When a Stream's Video Dimensions Change

A stream's video dimensions can change if a stream published from a mobile device resizes (for example, due to device orientation changes) or if a screen-sharing source window is resized.

When a stream's video dimensions change, the Session object dispatches a streamPropertyChanged event, with changedProperty set to videoDimensions.

<OTSubscriber
  eventHandlers={{
    streamVideoDimensionsChanged: (event) => {
      console.log('stream video dimensions changed -- stream ID:', event.streamId);
      console.log('new dimensions:', event.width, 'x', event.height);
    },
  }}
/>

Setting the Preferred Frame Rate and Resolution

When subscribing to a stream that uses the scalable video feature, you can set preferredResolution to 'auto' to automatically manage Subscriber video resolution and optimize CPU/network usage.

For advanced control, set the preferred frame rate and resolution for the subscribed stream:

<OTSubscriber
  properties={{
    preferredFrameRate: 15,
    preferredResolution: { width: 640, height: 480 },
  }}
/>

These are hints, not commands. The Media Router selects the closest available layer that fits the subscriber's actual network conditions. They have no effect in relayed sessions, when scalable video is disabled, or when the negotiated codec is H.264. For other techniques to reduce resource usage in large sessions, see the Single Peer Connection guide.

Detecting When Streams Leave a Session

When a remote stream leaves a session, the OTSubscriber component dispatches a streamDestroyed event. The event includes details such as streamId, name, reason, hasAudio, hasVideo, and videoType. For full details on the event and its reason values, see the Subscribe diagnostics guide.

<OTSubscriber
  eventHandlers={{
    streamDestroyed: (event) => {
      console.log('Stream stopped. Reason: ' + event.reason);
    },
  }}
/>

Custom Rendering of Subscribers

By default, OTSubscriber renders child views for subscriber videos. You can also provide a render function to fully control rendering using renderView:

<OTSubscriber
  renderView={(streamId) => (
    <View style={styles.subscriberTile}>
      <OTSubscriberView streamId={streamId} style={styles.video} />
    </View>
  )}
/>

Setting Stream Properties

Set global properties for all subscribers via the subscriberProperties prop on OTSession, or set per-stream properties via the properties prop on OTSubscriber. For the full list of available properties, see the OTSubscriber API reference.

// Global defaults for all subscribers in the session
<OTSession
  subscriberProperties={{
    subscribeToAudio: true,
    subscribeToVideo: true,
  }}
/>

// Per-stream override
<OTSubscriber
  properties={{
    subscribeToAudio: true,
    subscribeToVideo: false,
  }}
/>

Managing Subscriber Streams (iOS Swift)

Manage subscribers, handle events, and adjust preferences in iOS.

Detecting When a Subscriber's Video Is Disabled

func subscriberVideoDisabled(_ subscriber: OTSubscriberKit, reason: OTSubscriberVideoEventReason) {
    print("subscriber video disabled.")
}

Possible Reasons

  • OTSubscriberVideoEventPublisherPropertyChanged
  • OTSubscriberVideoEventQualityChanged
  • OTSubscriberVideoEventSubscriberPropertyChanged

When video resumes:

func subscriberVideoEnabled(_ subscriber: OTSubscriberKit, reason: OTSubscriberVideoEventReason) {
    print("subscriber video enabled.")
}

Getting Information About a Stream

The OTStream object includes:

  • connection — The publishing connection
  • creationTime — Timestamp
  • hasAudio — Bool
  • hasVideo — Bool
  • name — Optional stream name
  • session — Associated session
  • streamId — Unique ID
  • videoDimensions — CGSize
  • videoType — Camera, screen, or custom

You can monitor stats using OTSubscriberKitNetworkStatsDelegate.

See the client observability guide for more details.

Setting the Preferred Frame Rate and Resolution

For scalable video streams, you can set:

  • SubscriberKit.preferredFrameRate
  • SubscriberKit.preferredResolution

Managing Subscriber Streams (JavaScript)

Restricting the Frame Rate of a Subscribed Stream

You can also restrict the frame rate of a Subscriber's video stream.

To restrict the frame rate of a subscriber, call the restrictFrameRate() method of the Subscriber object, passing in true:

subscriber.restrictFrameRate(true);

Pass in false and the frame rate of the video stream is not restricted:

subscriber.restrictFrameRate(false);

When the frame rate is restricted, the Subscriber video frame will update once or less per second. This feature is only available in routed sessions. In relayed sessions, calling this method has no effect.

Restricting the subscriber frame rate has the following benefits:

  • It reduces CPU usage.
  • It reduces the network bandwidth consumed by the app.
  • It lets you subscribe to more streams simultaneously.

Reducing a subscriber's frame rate has no effect on the frame rate of the video in other clients. For other techniques to reduce resource usage in large sessions, see the Single Peer Connection guide.

Detecting When a Subscriber's Audio Is Blocked or Unblocked

Some browsers automatically block audio playback until the user interacts with the page. For the full implementation of handling blocked audio, including how to disable the default playback button and display your own UI, see Displaying a custom UI element when Subscriber audio is blocked.

Also, the Subscriber includes an isAudioBlocked() method which returns true if the audio is blocked or false if it is not.

Detecting When a Subscriber's Video Is Disabled

When the subscriber's video is disabled, the Subscriber object dispatches a videoDisabled event. When the Media Router disables the video of a subscriber, you may want to adjust the user interface related to the subscriber.

The reason property of the videoDisabled event object defines the reason the video was disabled ('publishVideo', 'quality', or 'subscribeToVideo'). For the full description of each reason, see the Subscribe diagnostics guide. Before the video is disabled due to quality, the Subscriber dispatches a videoDisableWarning event. To prevent a stream from having its video disabled due to quality, see the Subscriber audio fallback guide.

subscriber.on('videoDisableWarning', () => {
  showConnectionWarning(subscriber.id);
});

subscriber.on('videoDisableWarningLifted', () => {
  hideConnectionWarning(subscriber.id);
});

subscriber.on('videoDisabled', (event) => {
  if (event.reason === 'quality') {
    showVideoDisabledOverlay(subscriber.id);
  }
});

subscriber.on('videoEnabled', () => {
  hideVideoDisabledOverlay(subscriber.id);
});

By default, the Subscriber displays its own video-disabled indicator when quality is the reason. To replace it with your own UI, set style.videoDisabledDisplayMode to 'off' in the subscribe options. For codec-specific behaviour (e.g. why H.264 streams are not affected by quality-based fallback), see the Video codecs guide.

Getting Subscriber Stats (Web)

The getStats() method of a Subscriber object provides you with information about the subscriber's stream. For the full list of available fields, see the Subscribe diagnostics guide.

The following code logs loss ratios and bit rates every second:

window.setInterval(() => {
  subscriber.getStats((error, stats) => {
    if (error) {
      console.error('Error getting subscriber stats:', error.message);
      return;
    }
    if (stats.video) {
      console.log('video bitrate:', stats.video.bitrate, 'bps');
      const total = stats.video.packetsLost + stats.video.packetsReceived;
      console.log('video packet loss ratio:', total > 0 ? stats.video.packetsLost / total : 0);
    }
    if (stats.audio) {
      console.log('audio bitrate:', stats.audio.bitrate, 'bps');
    }
  });
}, 1000);

To get statistics for a stream published by the local client, you must use a routed session and set the testNetwork option to true when subscribing:

const subscriber = session.subscribe(stream, 'container', {
  testNetwork: true,
});

To get more detailed stream statistics, use subscriber.getRtcStatsReport(). For a full description of all available fields, see the Client Observability guide.

Setting the Preferred Frame Rate and Resolution (Web)

When subscribing to a stream that uses the scalable video feature, you can set preferredResolution to 'auto' to automatically manage Subscriber video resolution and optimize CPU/network usage. For a full explanation of how these hints work, supported values, and limitations, see the Scalable video guide.

Set preferredResolution and preferredFrameRate in the options you pass to Session.subscribe() (or use Subscriber.setPreferredResolution() and Subscriber.setPreferredFrameRate() after subscribing):

// Set at subscribe time using 'auto' (recommended)
const subscriber = session.subscribe(stream, 'container', {
  preferredResolution: 'auto',
});

// Or set explicitly after subscribing
subscriber.setPreferredResolution({ width: 1280, height: 720 });
subscriber.setPreferredFrameRate(30);

// Downgrade for a thumbnail tile
subscriber.setPreferredResolution({ width: 320, height: 240 });
subscriber.setPreferredFrameRate(7);

Managing Subscriber Streams (Android)

Manage subscribers, handle events, and adjust preferences in Android.

Detecting When a Subscriber's Video Is Disabled

When video is disabled:

override fun onVideoDisabled(subscriber: SubscriberKit, reason: String) {
    // Video disabled
}

When video resumes:

override fun onVideoEnabled(subscriber: SubscriberKit, reason: String) {
    // Video resumed
}

The reason parameter explains why the change occurred.

Getting Information About a Stream

The Stream object provides:

  • getConnection() — Connection object
  • getCreationTime() — Creation timestamp
  • hasAudio() — Boolean
  • hasVideo() — Boolean
  • getName() — Stream name
  • getStreamId() — Unique ID
  • getVideoHeight() — Height in pixels
  • getVideoWidth() — Width in pixels
  • getVideoType() — Camera, screen share, or custom

You can also monitor stats:

  • setAudioStatsListener()
  • setVideoStatsListener()
  • setMediaLinkStatsListener()
  • getRtcStatsReport()

Setting the Preferred Frame Rate and Resolution

For scalable video streams, you can set preferences:

  • SubscriberKit.setPreferredFrameRate()
  • SubscriberKit.setPreferredResolution()

Managing Subscriber Streams (Windows)

Manage subscribers, handle events, and adjust preferences in Windows.

Detecting When a Subscriber's Video Is Disabled

The OpenTok Media Router may stop sending video if network conditions degrade.

The subscriber continues receiving audio if available.

When video is disabled, the Subscriber object sends a VideoDisabled event:

subscriber.VideoDisabled += Subscriber_VideoDisabled;

public void Subscriber_VideoDisabled(object sender)
{
    // Display a user interface notification.
}

When video resumes:

subscriber.VideoEnabled += Subscriber_VideoEnabled;

public void Subscriber_VideoEnabled(object sender)
{
    // Video resumes for the subscriber.
}

You may want to adjust the UI in response to these events.

Getting Information About a Stream

The Stream object exposes the following properties:

  • Connection — The publishing connection
  • CreationTime — Stream creation timestamp
  • HasAudio — Whether the stream has audio
  • HasVideo — Whether the stream has video
  • Name — Stream name
  • Id — Unique stream ID
  • Height — Video height in pixels
  • Width — Video width in pixels
  • VideoSourceType — Camera, screen-sharing, or custom source type

Possible VideoSourceType values:

  • VideoSourceType.StreamVideoTypeCamera
  • VideoSourceType.StreamVideoTypeScreen
  • VideoSourceType.StreamVideoTypeCustom

Monitoring Statistics

Use these events to monitor stream statistics:

  • Subscriber.AudioStatsUpdated
  • Subscriber.VideoStatsUpdated
  • Subscriber.MediaLinkStatsUpdated

To retrieve low-level RTC statistics:

subscriber.GetRtcStatsReport();

Setting the Preferred Frame Rate and Resolution

For streams using the scalable video feature, configure:

  • Subscriber.PreferredFramerate
  • Subscriber.PreferredResolution

Managing Subscriber Streams (Linux)

Manage subscribers, handle events, and adjust preferences in Linux.

Detecting When a Stream's Video Is Disabled

The on_stream_has_video_changed callback function of the otc_session_callbacks struct is called when a stream’s video availability changes.

The stream parameter is a pointer to an otc_stream struct.

Use:

otc_stream_get_id(stream)

to retrieve the stream ID.

Getting Information About a Stream

Use the following functions to retrieve stream information:

  • otc_stream_get_connection() — Returns the publishing connection
  • otc_stream_get_creation_time() — Returns the stream creation timestamp
  • otc_stream_has_audio() — Whether the stream is publishing audio
  • otc_stream_has_video() — Whether the stream is publishing video
  • otc_stream_has_audio_track() — Whether the stream has an audio track
  • otc_stream_has_video_track() — Whether the stream has a video track
  • otc_stream_get_name() — Returns the stream name
  • otc_stream_get_id() — Returns the unique stream ID
  • otc_stream_get_video_height() — Returns the video height in pixels
  • otc_stream_get_video_width() — Returns the video width in pixels
  • otc_stream_get_video_type() — Returns the stream video type

Possible video types:

  • OTC_STREAM_VIDEO_TYPE_CAMERA
  • OTC_STREAM_VIDEO_TYPE_SCREEN

Monitoring Statistics

Use these subscriber callback functions:

  • on_audio_stats()
  • on_video_stats()
  • on_media_link_stats()

To retrieve low-level RTC statistics, use:

otc_subscriber_get_rtc_stats_report()

Setting the Preferred Frame Rate and Resolution

For streams using the scalable video feature, you can set preferred frame rate and resolution using:

  • otc_subscriber_set_preferred_framerate()
  • otc_subscriber_set_preferred_resolution()