Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion livekit-api/livekit/api/room_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,11 @@ async def forward_participant(self, forward: ForwardParticipantRequest) -> None:
SVC,
"ForwardParticipant",
forward,
self._auth_header(VideoGrants(room_admin=True, room=forward.room, destination_room=forward.destination_room)),
self._auth_header(
VideoGrants(
room_admin=True, room=forward.room, destination_room=forward.destination_room
)
),
ForwardParticipantResponse,
)

Expand Down
11 changes: 10 additions & 1 deletion livekit-rtc/livekit/rtc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,15 @@
Participant,
RemoteParticipant,
)
from .room import ConnectError, DataPacket, Room, RoomOptions, RtcConfiguration, SipDTMF
from .room import (
ConnectError,
DataPacket,
Room,
RoomOptions,
RtcConfiguration,
SipDTMF,
RtcStats,
)
from .track import (
AudioTrack,
LocalAudioTrack,
Expand Down Expand Up @@ -123,6 +131,7 @@
"RoomOptions",
"RtcConfiguration",
"SipDTMF",
"RtcStats",
"DataPacket",
"LocalAudioTrack",
"LocalVideoTrack",
Expand Down
32 changes: 32 additions & 0 deletions livekit-rtc/livekit/rtc/room.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
from ._proto import ffi_pb2 as proto_ffi
from ._proto import participant_pb2 as proto_participant
from ._proto import room_pb2 as proto_room
from ._proto import stats_pb2 as proto_stats
from ._proto.room_pb2 import ConnectionState
from ._proto.track_pb2 import TrackKind
from ._proto.rpc_pb2 import RpcMethodInvocationEvent
Expand Down Expand Up @@ -120,6 +121,12 @@ class SipDTMF:
"""Participant who sent the DTMF digit. None when sent by a server SDK."""


@dataclass
class RtcStats:
publisher_stats: list[proto_stats.RtcStats]
subscriber_stats: list[proto_stats.RtcStats]


class ConnectError(Exception):
def __init__(self, message: str):
self.message = message
Expand Down Expand Up @@ -408,6 +415,30 @@ def on_participant_connected(participant):
# start listening to room events
self._task = self._loop.create_task(self._listen_task())

async def get_rtc_stats(self) -> RtcStats:
if not self.isconnected():
raise RuntimeError("the room isn't connected")

req = proto_ffi.FfiRequest()
req.get_session_stats.room_handle = self._ffi_handle.handle # type: ignore

queue = FfiClient.instance.queue.subscribe()
try:
resp = FfiClient.instance.request(req)
cb: proto_ffi.FfiEvent = await queue.wait_for(
lambda e: e.get_session_stats.async_id == resp.get_session_stats.async_id
)
finally:
FfiClient.instance.queue.unsubscribe(queue)

if cb.get_session_stats.error:
raise RuntimeError(cb.get_session_stats.error)

publisher_stats = list(cb.get_session_stats.result.publisher_stats)
subscriber_stats = list(cb.get_session_stats.result.subscriber_stats)

return RtcStats(publisher_stats=publisher_stats, subscriber_stats=subscriber_stats)

def register_byte_stream_handler(self, topic: str, handler: ByteStreamHandler):
existing_handler = self._byte_stream_handlers.get(topic)
if existing_handler is None:
Expand Down Expand Up @@ -446,6 +477,7 @@ async def disconnect(self) -> None:
await queue.wait_for(lambda e: e.disconnect.async_id == resp.disconnect.async_id)
finally:
FfiClient.instance.queue.unsubscribe(queue)

await self._task
FfiClient.instance.queue.unsubscribe(self._ffi_queue)

Expand Down
Loading