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:
Pass in false and the frame rate of the video stream is not restricted:
When the frame rate is restricted, the Subscriber video frame will update once or less per second.
This feature is only available in sessions that use the Media Router (sessions with the media mode set to routed), not in sessions with the media mode set to relayed. 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.
Detecting when a subscriber's audio is blocked or unblocked
Some browsers automatically block audio playback, requiring a click event before audio playback starts for subscribers. These browsers include Safari, Firefox 66+, and Chrome 71+.
The Subscriber object displays an audio playback button if audio playback is blocked. You can disable the Subscriber's default audio playback button and display your own UI element that the user will click to start audio playback.
See Displaying a custom UI element when Subscriber audio is blocked.
When the subscriber's audio is blocked, the Subscriber object dispatches a audioBlocked event, and it dispatches an audioUnblocked event when the audio is unblocked:
Also, the Subscriber includes an isAudioBlocked() which returns true if the audio is blocked or false if it is not.
Subscriber audio is unblocked when any of the following occurs:
- The user clicks the default Subscriber audio playback icon
- The OT.unblockAudio() method is called in response to an HTML element dispatching a
clickevent (if you have disabled the default audio playback icon) - The local client gains access to the camera or microphone (for instance, in response to a successful call to
OT.initPublisher()).
For more information, see this Mozilla article about autoplay in Firefox and this Google article about autoplay in Chrome.
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. This can be set to one of the following values:
"publishVideo"— The publisher stopped publishing video by callingpublishVideo(false)."quality"— The Media Router stopped sending video to the subscriber based on stream quality changes. This feature of the Media Router has a subscriber drop the video stream when connectivity degrades. (The subscriber continues to receive the audio stream, if there is one.)Before sending this event, when the Subscriber's stream quality deteriorates to a level that is low enough that the video stream is at risk of being disabled, the Subscriber dispatches a
videoDisableWarningevent.If connectivity improves to support video again, the Subscriber object dispatches a
videoEnabledevent, and the Subscriber resumes receiving video.By default, the Subscriber displays a video disabled indicator when a
videoDisabledevent with this reason is dispatched and removes the indicator when thevideoDisabledevent with this reason is dispatched. You can control the display of this icon by calling thesetStyle()method of the Subscriber, setting thevideoDisabledDisplayModeproperty; or you can set the style when calling theSession.subscribe()method, setting thestyleproperty of thepropertiesparameter.This feature is only available in sessions that use the Media Router (sessions with the media mode set to routed), not in sessions with the media mode set to relayed.
When you publish a stream, you can prevent it from having its video disabled due to stream quality. Set
audioFallbackEnabledtofalsein thepropertiesobject you pass into the OT.initPublisher() method."subscribeToVideo"— The subscriber started or stopped subscribing to video, by callingsubscribeToVideo(false)."codecNotSupported"— The subscriber stopped subscribing to video due to an incompatible codec (see the Video codecs developer guide).
The Subscriber dispatches a videoEnabled event when video resumes:
To prevent video from resuming, in the videoEnabled event listener, call subscribeToVideo(false) on the Subscriber object:
The reason property of the videoEnabled event object defines the reason the video was enabled. This can be set to one of the following values:
"publishVideo"— The publisher started publishing video by callingpublishVideo(true)."quality"— The Media Router resumed sending video to the subscriber based on stream quality changes. This feature of the Media Router has a subscriber drop the video stream when connectivity degrades and then resume the video stream if the stream quality improves.This feature is only available in sessions that use the Media Router (sessions with the media mode set to routed), not in sessions with the media mode set to relayed.
"subscribeToVideo"— The subscriber started or stopped subscribing to video, by callingsubscribeToVideo(false)."codecChanged"— The subscriber video was enabled after a codec change from an incompatible codec (see the Video codecs developer guide).
Detecting when a subscriber's stream's video dimensions change
The stream of a subscriber's video dimensions can change if a stream published from a mobile device resizes, based on a change in the device orientation. It can also occur if the video source is a screen-sharing window and the user publishing the stream resizes the window that is the source for the stream. When the video dimensions change, the Subscriber object dispatches a videoDimensionsChanged event.
The following code resizes a subscriber when the stream's video dimensions change:
Getting information about a stream
The Stream object has the following properties that define the stream:
connection—The Connection object corresponding to the connection that is publishing the stream. You can compare this to theconnectionproperty of the Session object to see if the stream is being published by the local web page.creationTime—The timestamp (a number) for the creation of the stream. This value is calculated in milliseconds. You can convert this value to a Date object by callingnew Date(stream.creationTime).hasAudio—(Boolean) Whether the stream has audio. This property can change if the publisher turns on or off audio (by calling Publisher.publishAudio()). When this occurs, the Session object dispatches astreamPropertyChangedevent.hasVideo—(Boolean) Whether the stream has video.initials-(Boolean) The initials for the stream (if initials were set when the stream's publisher was initialized).name—(String) The name of the stream. This is, by default, displayed when the user mouses over the Subscriber in the HTML DOM. You can, however, customize the UI to hide the name or display it without mousing over.videoDimensions—This object has two properties:widthandheight. Both are numbers. Thewidthproperty is the width of the encoded stream; theheightproperty is the height of the encoded stream. (These are independent of the actual width of Publisher and Subscriber objects corresponding to the stream.) This property can change if a stream published from an iOS device resizes, based on a change in the device orientation.videoType—The type of video: either "camera", "screen", "custom", or undefined. A "screen" video uses screen sharing on the publisher as the video source; a "custom" video uses a VideoTrack element as the video source on the publisher. ThevideoTypeisundefinedwhen a stream is voice-only . This property can change if a stream published from a mobile device changes from a camera to a screen-sharing video type. (see the Voice-only guide)
For more information, see Screen sharing — Web.
The hasAudio, hasVideo, videoDimensions, and videoType properties can change (for example, when the publisher turns on or off video). When this occurs, the Session object dispatches a streamPropertyChanged event (see StreamPropertyChangedEvent.)
The getStats() method of a Subscriber object provides you with information about the subscriber's stream, including the following:
- The total number of audio and video packets lost
- The total number of audio and video packets received
- The total number of audio and video bytes received
- The current average video frame rate
The following code logs the audio packet loss ratio, the audio bit rate, and the video packet loss ratio, and the video bit rate for a subscriber every second:
To get statistics for a stream published by the local client, you must use a session that uses the Media Router (sessions with the media mode set to routed), and you must set the testNetwork property to true in the options object you pass into the Session.subscribe() method:
To get more detailed stream statistics, use the Subscriber.getRtcStatsReport() method. It returns a promise that, on success, resolves with an RtcStatsReport object for the subscribed stream:
Setting the preferred frame rate and resolution
When subscribing to a stream that uses the scalable video feature, you have an option to set preferredResolution to
"auto" to automatically manage Subscriber video resolution based on the size being rendered to optimize the network and CPU usage. For advanced users, you can also manually set the preferred frame rate and resolution for the stream the subscribing client receives from the Media Router. You can set these as the preferredFrameRate and preferredResolution properties of the options you pass into the Session.subscribe() method.
We recommend setting preferredResolution to "auto". With the
"auto" setting, OpenTok.js selects the preferred resolution based on the
dimensions of the Subscriber video in the browser. You can also set the preferred frame rate
and resolution after subscribing to a stream (see Subscriber.setPreferredFrameRate() and Subscriber.setPreferredResolution()).