Skip to content

Commit be92457

Browse files
authored
Add missing connection quality field (#696)
1 parent 639682f commit be92457

4 files changed

Lines changed: 73 additions & 4 deletions

File tree

livekit-rtc/livekit/rtc/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
DisconnectReason,
2828
)
2929
from ._proto.room_pb2 import (
30-
ConnectionQuality,
3130
ConnectionState,
3231
ContinualGatheringPolicy,
3332
DataPacketKind,
@@ -58,6 +57,7 @@
5857
KeyProviderOptions,
5958
)
6059
from .participant import (
60+
ConnectionQuality,
6161
LocalParticipant,
6262
Participant,
6363
RemoteParticipant,

livekit-rtc/livekit/rtc/participant.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import ctypes
1818
import asyncio
1919
import datetime
20+
import enum
2021
import os
2122
import mimetypes
2223
import aiofiles
@@ -29,6 +30,9 @@
2930
from ._proto.room_pb2 import (
3031
TrackPublishOptions,
3132
)
33+
from ._proto.room_pb2 import (
34+
ConnectionQuality as ProtoConnectionQuality,
35+
)
3236
from ._proto.room_pb2 import (
3337
TranscriptionSegment as ProtoTranscriptionSegment,
3438
)
@@ -89,10 +93,29 @@ def __init__(self, message: str) -> None:
8993
self.message = message
9094

9195

96+
class ConnectionQuality(enum.IntEnum):
97+
"""Connection quality reported for a participant."""
98+
99+
QUALITY_UNKNOWN = -1
100+
"""No connection-quality update has been reported yet (no proto equivalent)."""
101+
QUALITY_POOR = ProtoConnectionQuality.QUALITY_POOR
102+
QUALITY_GOOD = ProtoConnectionQuality.QUALITY_GOOD
103+
QUALITY_EXCELLENT = ProtoConnectionQuality.QUALITY_EXCELLENT
104+
QUALITY_LOST = ProtoConnectionQuality.QUALITY_LOST
105+
106+
107+
def _connection_quality_from_proto(value: int) -> ConnectionQuality:
108+
try:
109+
return ConnectionQuality(value)
110+
except ValueError:
111+
return ConnectionQuality.QUALITY_UNKNOWN
112+
113+
92114
class Participant(ABC):
93115
def __init__(self, owned_info: proto_participant.OwnedParticipant) -> None:
94116
self._info = owned_info.info
95117
self._ffi_handle = FfiHandle(owned_info.handle.id)
118+
self._connection_quality = ConnectionQuality.QUALITY_UNKNOWN
96119

97120
@property
98121
@abstractmethod
@@ -152,6 +175,16 @@ def permissions(self) -> proto_participant.ParticipantPermission:
152175
"""The participant's permissions within the room."""
153176
return self._info.permission
154177

178+
@property
179+
def connection_quality(self) -> ConnectionQuality:
180+
"""The participant's most recently reported connection quality.
181+
182+
Returns ``ConnectionQuality.QUALITY_UNKNOWN`` until the first
183+
connection-quality update is received. Updated automatically whenever a
184+
``connection_quality_changed`` event fires for this participant.
185+
"""
186+
return self._connection_quality
187+
155188
@property
156189
def disconnect_reason(
157190
self,

livekit-rtc/livekit/rtc/room.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,12 @@
3333
from ._proto.rpc_pb2 import RpcMethodInvocationEvent
3434
from ._utils import BroadcastQueue
3535
from .e2ee import E2EEManager, E2EEOptions
36-
from .participant import LocalParticipant, Participant, RemoteParticipant
36+
from .participant import (
37+
LocalParticipant,
38+
Participant,
39+
RemoteParticipant,
40+
_connection_quality_from_proto,
41+
)
3742
from .track import RemoteAudioTrack, RemoteVideoTrack
3843
from .track_publication import RemoteTrackPublication, TrackPublication
3944
from .transcription import TranscriptionSegment
@@ -897,12 +902,14 @@ def _on_room_event(self, event: proto_room.RoomEvent) -> None:
897902
)
898903
elif which == "connection_quality_changed":
899904
identity = event.connection_quality_changed.participant_identity
900-
# TODO: pass participant identity
901905
participant = self._retrieve_participant(identity)
906+
quality = _connection_quality_from_proto(event.connection_quality_changed.quality)
907+
if participant:
908+
participant._connection_quality = quality
902909
self.emit(
903910
"connection_quality_changed",
904911
participant,
905-
event.connection_quality_changed.quality,
912+
quality,
906913
)
907914
elif which == "transcription_received":
908915
transcription = event.transcription_received
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
"""Unit tests for the local ConnectionQuality enum and the participant property."""
2+
3+
from livekit import rtc
4+
from livekit.rtc._proto import participant_pb2 as proto_participant
5+
from livekit.rtc._proto import room_pb2 as proto_room
6+
from livekit.rtc.participant import _connection_quality_from_proto
7+
8+
9+
def test_enum_values_align_with_proto() -> None:
10+
CQ = rtc.ConnectionQuality
11+
assert CQ.QUALITY_UNKNOWN == -1
12+
assert CQ.QUALITY_POOR == proto_room.ConnectionQuality.QUALITY_POOR
13+
assert CQ.QUALITY_GOOD == proto_room.ConnectionQuality.QUALITY_GOOD
14+
assert CQ.QUALITY_EXCELLENT == proto_room.ConnectionQuality.QUALITY_EXCELLENT
15+
assert CQ.QUALITY_LOST == proto_room.ConnectionQuality.QUALITY_LOST
16+
# backward compat: still int-comparable like the old proto enum export
17+
assert CQ.QUALITY_GOOD == 1
18+
19+
20+
def test_from_proto_mapping() -> None:
21+
assert _connection_quality_from_proto(1) is rtc.ConnectionQuality.QUALITY_GOOD
22+
assert _connection_quality_from_proto(99) is rtc.ConnectionQuality.QUALITY_UNKNOWN
23+
24+
25+
def test_participant_default_quality_is_unknown() -> None:
26+
owned = proto_participant.OwnedParticipant()
27+
owned.info.identity = "test"
28+
participant = rtc.RemoteParticipant(owned)
29+
assert participant.connection_quality is rtc.ConnectionQuality.QUALITY_UNKNOWN

0 commit comments

Comments
 (0)