Skip to content

Commit b828b15

Browse files
authored
expose rtc session stats (#429)
1 parent 6c1ec73 commit b828b15

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

livekit-rtc/livekit/rtc/__init__.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,15 @@
5454
Participant,
5555
RemoteParticipant,
5656
)
57-
from .room import ConnectError, DataPacket, Room, RoomOptions, RtcConfiguration, SipDTMF
57+
from .room import (
58+
ConnectError,
59+
DataPacket,
60+
Room,
61+
RoomOptions,
62+
RtcConfiguration,
63+
SipDTMF,
64+
RtcStats,
65+
)
5866
from .track import (
5967
AudioTrack,
6068
LocalAudioTrack,
@@ -127,6 +135,7 @@
127135
"RoomOptions",
128136
"RtcConfiguration",
129137
"SipDTMF",
138+
"RtcStats",
130139
"DataPacket",
131140
"LocalAudioTrack",
132141
"LocalVideoTrack",

livekit-rtc/livekit/rtc/room.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
from ._proto import ffi_pb2 as proto_ffi
2525
from ._proto import participant_pb2 as proto_participant
2626
from ._proto import room_pb2 as proto_room
27+
from ._proto import stats_pb2 as proto_stats
2728
from ._proto.room_pb2 import ConnectionState
2829
from ._proto.track_pb2 import TrackKind
2930
from ._proto.rpc_pb2 import RpcMethodInvocationEvent
@@ -120,6 +121,12 @@ class SipDTMF:
120121
"""Participant who sent the DTMF digit. None when sent by a server SDK."""
121122

122123

124+
@dataclass
125+
class RtcStats:
126+
publisher_stats: list[proto_stats.RtcStats]
127+
subscriber_stats: list[proto_stats.RtcStats]
128+
129+
123130
class ConnectError(Exception):
124131
def __init__(self, message: str):
125132
self.message = message
@@ -408,6 +415,30 @@ def on_participant_connected(participant):
408415
# start listening to room events
409416
self._task = self._loop.create_task(self._listen_task())
410417

418+
async def get_rtc_stats(self) -> RtcStats:
419+
if not self.isconnected():
420+
raise RuntimeError("the room isn't connected")
421+
422+
req = proto_ffi.FfiRequest()
423+
req.get_session_stats.room_handle = self._ffi_handle.handle # type: ignore
424+
425+
queue = FfiClient.instance.queue.subscribe()
426+
try:
427+
resp = FfiClient.instance.request(req)
428+
cb: proto_ffi.FfiEvent = await queue.wait_for(
429+
lambda e: e.get_session_stats.async_id == resp.get_session_stats.async_id
430+
)
431+
finally:
432+
FfiClient.instance.queue.unsubscribe(queue)
433+
434+
if cb.get_session_stats.error:
435+
raise RuntimeError(cb.get_session_stats.error)
436+
437+
publisher_stats = list(cb.get_session_stats.result.publisher_stats)
438+
subscriber_stats = list(cb.get_session_stats.result.subscriber_stats)
439+
440+
return RtcStats(publisher_stats=publisher_stats, subscriber_stats=subscriber_stats)
441+
411442
def register_byte_stream_handler(self, topic: str, handler: ByteStreamHandler):
412443
existing_handler = self._byte_stream_handlers.get(topic)
413444
if existing_handler is None:
@@ -446,6 +477,7 @@ async def disconnect(self) -> None:
446477
await queue.wait_for(lambda e: e.disconnect.async_id == resp.disconnect.async_id)
447478
finally:
448479
FfiClient.instance.queue.unsubscribe(queue)
480+
449481
await self._task
450482
FfiClient.instance.queue.unsubscribe(self._ffi_queue)
451483

0 commit comments

Comments
 (0)