Skip to content

Commit

Permalink
fix: Optimize stats display
Browse files Browse the repository at this point in the history
  • Loading branch information
cloudwebrtc committed Oct 8, 2024
1 parent c9a0560 commit 0b6bc74
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 33 deletions.
1 change: 1 addition & 0 deletions example/lib/widgets/controls.dart
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ class _ControlsWidgetState extends State<ControlsWidget> {
else
PopupMenuButton<MediaDevice>(
icon: const Icon(Icons.settings_voice),
offset: Offset(0, -90),
itemBuilder: (BuildContext context) {
return [
PopupMenuItem<MediaDevice>(
Expand Down
14 changes: 7 additions & 7 deletions example/lib/widgets/participant.dart
Original file line number Diff line number Diff line change
Expand Up @@ -148,13 +148,6 @@ abstract class _ParticipantWidgetState<T extends ParticipantWidget>
)
: const NoVideoWidget(),
),
if (widget.showStatsLayer)
Positioned(
top: 30,
right: 30,
child: ParticipantStatsWidget(
participant: widget.participant,
)),
// Bottom bar
Align(
alignment: Alignment.bottomCenter,
Expand All @@ -176,6 +169,13 @@ abstract class _ParticipantWidgetState<T extends ParticipantWidget>
],
),
),
if (widget.showStatsLayer)
Positioned(
top: 130,
right: 30,
child: ParticipantStatsWidget(
participant: widget.participant,
)),
],
),
);
Expand Down
80 changes: 54 additions & 26 deletions example/lib/widgets/participant_stats.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,17 @@ class ParticipantStatsWidget extends StatefulWidget {
class _ParticipantStatsWidgetState extends State<ParticipantStatsWidget> {
List<EventsListener<TrackEvent>> listeners = [];
StatsType statsType = StatsType.kUnknown;
Map<String, String> stats = {};
Map<String, Map<String, String>> stats = {'audio': {}, 'video': {}};

void _setUpListener(Track track) {
var listener = track.createListener();
listeners.add(listener);
if (track is LocalVideoTrack) {
statsType = StatsType.kLocalVideoSender;
listener.on<VideoSenderStatsEvent>((event) {
Map<String, String> stats = {};
setState(() {
stats['video tx'] = 'total sent ${event.currentBitrate.toInt()} kpbs';
stats['tx'] = 'total sent ${event.currentBitrate.toInt()} kpbs';
event.stats.forEach((key, value) {
stats['layer-$key'] =
'${value.frameWidth ?? 0}x${value.frameHeight ?? 0} ${value.framesPerSecond?.toDouble() ?? 0} fps, ${event.bitrateForLayers[key] ?? 0} kbps';
Expand All @@ -37,52 +38,74 @@ class _ParticipantStatsWidgetState extends State<ParticipantStatsWidget> {
event.stats['f'] ?? event.stats['h'] ?? event.stats['q'];
if (firstStats != null) {
stats['encoder'] = firstStats.encoderImplementation ?? '';
stats['video codec'] =
'${firstStats.mimeType}, ${firstStats.clockRate}hz, pt: ${firstStats.payloadType}';
if (firstStats.mimeType != null) {
stats['codec'] =
'${firstStats.mimeType!.split('/')[1]}/${firstStats.clockRate}';
}
stats['payload'] = '${firstStats.payloadType}';
stats['qualityLimitationReason'] =
firstStats.qualityLimitationReason ?? '';
}

this.stats['video']!.addEntries(stats.entries);
});
});
} else if (track is RemoteVideoTrack) {
statsType = StatsType.kRemoteVideoReceiver;
listener.on<VideoReceiverStatsEvent>((event) {
Map<String, String> stats = {};
setState(() {
stats['video rx'] = '${event.currentBitrate.toInt()} kpbs';
stats['video codec'] =
'${event.stats.mimeType}, ${event.stats.clockRate}hz, pt: ${event.stats.payloadType}';
stats['video size'] =
stats['rx'] = '${event.currentBitrate.toInt()} kpbs';
if (event.stats.mimeType != null) {
stats['codec'] =
'${event.stats.mimeType!.split('/')[1]}/${event.stats.clockRate}';
}
stats['payload'] = '${event.stats.payloadType}';
stats['size/fps'] =
'${event.stats.frameWidth}x${event.stats.frameHeight} ${event.stats.framesPerSecond?.toDouble()}fps';
stats['video jitter'] = '${event.stats.jitter} s';
stats['video decoder'] = '${event.stats.decoderImplementation}';
stats['jitter'] = '${event.stats.jitter} s';
stats['decoder'] = '${event.stats.decoderImplementation}';
//stats['video packets lost'] = '${event.stats.packetsLost}';
//stats['video packets received'] = '${event.stats.packetsReceived}';
stats['video frames received'] = '${event.stats.framesReceived}';
stats['video frames decoded'] = '${event.stats.framesDecoded}';
stats['video frames dropped'] = '${event.stats.framesDropped}';
stats['frames received'] = '${event.stats.framesReceived}';
stats['frames decoded'] = '${event.stats.framesDecoded}';
stats['frames dropped'] = '${event.stats.framesDropped}';

this.stats['video']!.addEntries(stats.entries);
});
});
} else if (track is LocalAudioTrack) {
statsType = StatsType.kLocalAudioSender;
listener.on<AudioSenderStatsEvent>((event) {
Map<String, String> stats = {};
setState(() {
stats['audio tx'] = '${event.currentBitrate.toInt()} kpbs';
stats['audio codec'] =
'${event.stats.mimeType}, ${event.stats.clockRate}hz, ${event.stats.channels}ch, pt: ${event.stats.payloadType}';
stats['tx'] = '${event.currentBitrate.toInt()} kpbs';
if (event.stats.mimeType != null) {
stats['codec'] =
'${event.stats.mimeType!.split('/')[1]}/${event.stats.clockRate}/${event.stats.channels}';
}
stats['payload'] = '${event.stats.payloadType}';
this.stats['audio']!.addEntries(stats.entries);
});
});
} else if (track is RemoteAudioTrack) {
statsType = StatsType.kRemoteAudioReceiver;
listener.on<AudioReceiverStatsEvent>((event) {
Map<String, String> stats = {};
setState(() {
stats['audio rx'] = '${event.currentBitrate.toInt()} kpbs';
stats['audio codec'] =
'${event.stats.mimeType}, ${event.stats.clockRate}hz, ${event.stats.channels}ch, pt: ${event.stats.payloadType}';
stats['audio jitter'] = '${event.stats.jitter} s';
//stats['audio concealed samples'] =
stats['rx'] = '${event.currentBitrate.toInt()} kpbs';
if (event.stats.mimeType != null) {
stats['codec'] =
'${event.stats.mimeType!.split('/')[1]}/${event.stats.clockRate}/${event.stats.channels}';
}
stats['payload'] = '${event.stats.payloadType}';
stats['jitter'] = '${event.stats.jitter} s';
//stats['concealed samples'] =
// '${event.stats.concealedSamples} / ${event.stats.concealmentEvents}';
stats['audio packets lost'] = '${event.stats.packetsLost}';
stats['audio packets received'] = '${event.stats.packetsReceived}';
stats['packets lost'] = '${event.stats.packetsLost}';
stats['packets received'] = '${event.stats.packetsReceived}';

this.stats['audio']!.addEntries(stats.entries);
});
});
}
Expand Down Expand Up @@ -130,9 +153,14 @@ class _ParticipantStatsWidgetState extends State<ParticipantStatsWidget> {
vertical: 8,
horizontal: 8,
),
child: Column(
children:
stats.entries.map((e) => Text('${e.key}: ${e.value}')).toList()),
child: Column(children: [
const Text('audio stats',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16)),
...stats['audio']!.entries.map((e) => Text('${e.key}: ${e.value}')),
const Text('video stats',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16)),
...stats['video']!.entries.map((e) => Text('${e.key}: ${e.value}')),
]),
);
}
}

0 comments on commit 0b6bc74

Please sign in to comment.