Webex Meetings
Multistream
Multistream enhances meeting experiences by showcasing the most active participants' videos.
The following features have been introduced in SDK version 3.5.0 and later:
- Streams are ordered by participant join time.
- There are two categories: Category-A and Category-B.
- Category-A contains only the active speaker's stream.
- Category-B includes all other streams and may also contain the active speaker's stream as a duplicate.
- The number of streams in Category-B can be limited; additional participants are queued.
- Queued participants replace less active streams when they speak.
- When a stream participant leaves, a random queued participant takes their place.
- Use the Active Speaker API to determine active speakers.
- The ActiveSpeakerChangedEvent is activated when the active speaker changes.
anchorCommon Use Case
anchorFor meetings with more than two participants, multistream can display the active speaker and other attendees simultaneously.
anchorImplement Multistream
anchorClients should implement MediaStreamAvailabilityEvent
as part of CallObserver.onMediaChanged
:
override fun onMediaChanged(event: CallObserver.MediaChangedEvent?) {
event?.let { _event ->
val call = _event.getCall()
when (_event) {
is CallObserver.MediaStreamAvailabilityEvent -> {
// event is CallObserver.MediaStreamAvailabilityEvent
//if (event.isAvailable()) {
// new stream available
//} else {
// stream unavailable
//}
}
else -> {}
}
}
Render a New Stream
Provide a view to render newly available streams, such as when new participants join:
// event is CallObserver.MediaStreamAvailabilityEvent
event.getStream()?.setRenderView(view)
Media Stream Information Changes
Different MediaStreamChangeEventType
are supported. Events trigger when related changes occur:
enum class MediaStreamChangeEventType {
Size,
Membership,
Video,
Audio
}
Register an info change listener to receive updates:
// event is CallObserver.MediaStreamAvailabilityEvent
event.getStream()?.setOnMediaStreamInfoChanged { type, info ->
//type: MediaStreamChangeEventType
//info: MediaStreamChangeEventInfo
}
Set a Media Stream for Category-A
Add or update the active speaker stream in Category-A, which contains only one stream:
// duplicate if true, the same active speaker will also be included in Category-B streams.
fun setMediaStreamCategoryA(duplicate: Boolean, quality: MediaStreamQuality)
enum class MediaStreamQuality {
Undefined,
LD, // 180p
SD, // 360p
HD, // 720p
FHD // 1080p
}
Set Media Streams for Category-B
Adjust the number and quality of Category-B streams:
- If the number of existing B streams is less than
numStreams
, it will add B streams as necessary. - If the number of existing B streams is more than
numStreams
, it will remove the extra B streams.
fun setMediaStreamsCategoryB(numStreams: Int, quality: MediaStreamQuality)
Remove a Media Stream from Category-A
Remove the active speaker stream from Category-A:
fun removeMediaStreamCategoryA()
After the removal of Category-A, if Category-B exists, all streams will have the same priority, and streams will not change based on the active speaker.
Remove Media Streams from Category-B
Remove all streams from Category-B:
fun removeMediaStreamsCategoryB()
anchorPin Media Streams
anchorPin a participant's stream to prevent it from changing, regardless of their speaking or queue status.
- The pinning feature falls under Category-C APIs.
- Pinned streams do not enter the active speaker stage.
The pinning feature is part of the Category-C APIs, available from SDK version 3.6.0 onwards.
Pin or Update a Pinned Stream
To pin or update a pinned stream for a specific participant:
fun setMediaStreamCategoryC(participantId: String, quality: MediaStreamQuality)
enum class MediaStreamQuality {
Undefined,
LD, // 180p
SD, // 360p
HD, // 720p
FHD // 1080p
}
Unpin a Media Stream
To unpin a participant's stream:
fun removeMediaStreamCategoryC(participantId: String)
Check for Pinning Support
To determine if stream pinning is supported:
fun isMediaStreamsPinningSupported() : Boolean
Listen for Media Stream Changes
To listen for changes in media stream properties, register a change listener to handle events:
enum class MediaStreamChangeEventType {
Size,
Membership,
Video,
Audio,
PinState
}
fun setOnMediaStreamInfoChanged(listener: (type: MediaStreamChangeEventType, info: MediaStreamChangeEventInfo) -> Unit)