| 4560 | |
| 4561 | # Start stats monitoring |
| 4562 | async def monitor_stats(): |
| 4563 | while True: |
| 4564 | try: |
| 4565 | await asyncio.sleep(5) |
| 4566 | if pc.connectionState in ["closed", "failed"]: |
| 4567 | break |
| 4568 | |
| 4569 | stats = await pc.getStats() |
| 4570 | active_pair = None |
| 4571 | |
| 4572 | # Find the active candidate pair |
| 4573 | for report in stats.values(): |
| 4574 | if report.type == "transport": |
| 4575 | selected_pair_id = getattr(report, "selectedCandidatePairId", None) |
| 4576 | if selected_pair_id: |
| 4577 | active_pair = stats.get(selected_pair_id) |
| 4578 | break |
| 4579 | |
| 4580 | if active_pair: |
| 4581 | local_candidate = stats.get(active_pair.localCandidateId) |
| 4582 | remote_candidate = stats.get(active_pair.remoteCandidateId) |
| 4583 | |
| 4584 | if local_candidate and remote_candidate: |
| 4585 | local_type = getattr(local_candidate, "candidateType", "unknown") |
| 4586 | remote_type = getattr(remote_candidate, "candidateType", "unknown") |
| 4587 | protocol = getattr(local_candidate, "protocol", "unknown").upper() |
| 4588 | |
| 4589 | # Determine simplified connection type |
| 4590 | # relay = TURN |
| 4591 | # srflx = STUN (Server Reflexive) |
| 4592 | # prflx = STUN (Peer Reflexive) |
| 4593 | # host = Local/Direct |
| 4594 | |
| 4595 | conn_type = "UNKNOWN" |
| 4596 | if local_type == "relay" or remote_type == "relay": |
| 4597 | conn_type = "TURN (Relay)" |
| 4598 | elif local_type in ["srflx", "prflx"] or remote_type in ["srflx", "prflx"]: |
| 4599 | conn_type = "STUN (P2P)" |
| 4600 | elif local_type == "host" and remote_type == "host": |
| 4601 | conn_type = "Direct (Host)" |
| 4602 | |
| 4603 | streamer_instance._log( |
| 4604 | f"[STATS] Connected via {conn_type} " |
| 4605 | f"({local_type} <-> {remote_type} over {protocol})" |
| 4606 | ) |
| 4607 | except Exception as e: |
| 4608 | streamer_instance._log(f"[STATS] Error monitoring stats: {e}") |
| 4609 | # Don't crash the loop |
| 4610 | await asyncio.sleep(5) |
| 4611 | |
| 4612 | asyncio.create_task(monitor_stats()) |
| 4613 | |