Skip to content

Commit

Permalink
Fix failure to leave when the only remaining participants are hidden (#…
Browse files Browse the repository at this point in the history
…537)

* ref: Inline conference.memberCount.

* fix: Exclude hidden participants from muted/jigasi count.

Fixes failure to leave when the only remaining participants are hidden
(for example, a transcriber).
  • Loading branch information
bgrozev authored Feb 20, 2024
1 parent 0529453 commit 2d3b5c1
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 4 deletions.
38 changes: 36 additions & 2 deletions src/main/kotlin/org/jitsi/jibri/selenium/pageobjects/CallPage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,12 @@ class CallPage(driver: RemoteWebDriver) : AbstractPageObject(driver) {
return result
}

/** Returns the number of participants excluding hidden participants. */
fun getNumParticipants(): Int {
val result = driver.executeScript(
"""
try {
return APP.conference.membersCount;
return (APP.conference._room.getParticipants().$PARTICIPANT_FILTER_SCRIPT).length + 1;
} catch (e) {
return e.message;
}
Expand Down Expand Up @@ -203,13 +204,15 @@ class CallPage(driver: RemoteWebDriver) : AbstractPageObject(driver) {
}

/**
* Return how many of the participants are Jigasi clients
* Return how many of the participants are Jigasi clients.
* Note: excludes any participants that are hidden (for example transcribers)
*/
fun numRemoteParticipantsJigasi(): Int {
val result = driver.executeScript(
"""
try {
return APP.conference._room.getParticipants()
.$PARTICIPANT_FILTER_SCRIPT
.filter(participant => participant.getProperty("features_jigasi") == true)
.length;
} catch (e) {
Expand All @@ -226,6 +229,28 @@ class CallPage(driver: RemoteWebDriver) : AbstractPageObject(driver) {
}
}

/** How many of the participants are hidden or hiddenFromRecorder. */
fun numHiddenParticipants(): Int {
val result = driver.executeScript(
"""
try {
return APP.conference._room.getParticipants()
.filter(p => (p.isHidden() || p.isHiddenFromRecorder())
.length;
} catch (e) {
return e.message;
}
""".trimMargin()
)
return when (result) {
is Number -> result.toInt()
else -> {
logger.error("error running numHiddenParticipants script: $result ${result::class.java}")
0
}
}
}

/**
* Return true if ICE is connected.
*/
Expand Down Expand Up @@ -267,12 +292,14 @@ class CallPage(driver: RemoteWebDriver) : AbstractPageObject(driver) {
* Returns a count of how many remote participants are totally muted (audio
* and video). We ignore jigasi participants as they maybe muted in their presence
* but also hard muted via the device, and we later ignore their state.
* Note: Excludes hidden participants.
*/
fun numRemoteParticipantsMuted(): Int {
val result = driver.executeScript(
"""
try {
return APP.conference._room.getParticipants()
.$PARTICIPANT_FILTER_SCRIPT
.filter(participant => participant.isAudioMuted() && participant.isVideoMuted()
&& participant.getProperty("features_jigasi") !== true)
.length;
Expand Down Expand Up @@ -353,4 +380,11 @@ class CallPage(driver: RemoteWebDriver) : AbstractPageObject(driver) {
else -> true
}
}

companion object {
/**
* Javascript to apply a filter to the list of participants to exclude ones which should be hidden from jibri.
*/
const val PARTICIPANT_FILTER_SCRIPT = "filter(p => !(p.isHidden() || p.isHiddenFromRecorder()))"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,14 @@ class MediaReceivedStatusCheck(
val numParticipants = callPage.getNumParticipants() - 1
val numMutedParticipants = callPage.numRemoteParticipantsMuted()
val numJigasiParticipants = callPage.numRemoteParticipantsJigasi()
val numHiddenParticipants = callPage.numHiddenParticipants()
// We don't get any mute state for Jigasi participants, so to prevent timing out when only Jigasi participants
// may be speaking, always count them as "muted"
val allClientsMuted = (numMutedParticipants + numJigasiParticipants) == numParticipants
logger.info(
"Jibri client receive bitrates: $bitrates, num participants: $numParticipants, " +
"numMutedParticipants: $numMutedParticipants, numJigasis: $numJigasiParticipants, " +
"all clients muted? $allClientsMuted"
"numHiddenParticipants: $numHiddenParticipants, all clients muted? $allClientsMuted"
)
clientsAllMutedTransitionTime.maybeUpdate(allClientsMuted)
val downloadBitrate = bitrates.getOrDefault("download", 0L) as Long
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ class MediaReceivedStatusCheckTest : ShouldSpec() {
override fun isolationMode(): IsolationMode? = IsolationMode.InstancePerLeaf

private val clock: FakeClock = spyk()
private val callPage: CallPage = mockk()
private val callPage: CallPage = mockk {
every { numHiddenParticipants() } returns 0
}
private val logger: Logger = mockk(relaxed = true)

private val check = MediaReceivedStatusCheck(logger, clock)
Expand Down

0 comments on commit 2d3b5c1

Please sign in to comment.