rtmp_rs/stats/
metrics.rs

1//! Statistics and metrics for RTMP sessions
2
3use std::time::{Duration, Instant};
4
5/// Session-level statistics
6#[derive(Debug, Clone, Default)]
7pub struct SessionStats {
8    /// Total bytes received
9    pub bytes_received: u64,
10    /// Total bytes sent
11    pub bytes_sent: u64,
12    /// Connection duration
13    pub duration: Duration,
14    /// Number of video frames received
15    pub video_frames: u64,
16    /// Number of audio frames received
17    pub audio_frames: u64,
18    /// Number of keyframes received
19    pub keyframes: u64,
20    /// Dropped frames count
21    pub dropped_frames: u64,
22    /// Current bitrate estimate (bits/sec)
23    pub bitrate: u64,
24}
25
26impl SessionStats {
27    /// Create new stats tracker
28    pub fn new() -> Self {
29        Self::default()
30    }
31
32    /// Calculate bitrate from bytes and duration
33    pub fn calculate_bitrate(&mut self) {
34        let secs = self.duration.as_secs();
35        if secs > 0 {
36            self.bitrate = (self.bytes_received * 8) / secs;
37        }
38    }
39}
40
41/// Stream-level statistics
42#[derive(Debug, Clone)]
43pub struct StreamStats {
44    /// Stream key
45    pub stream_key: String,
46    /// Start time
47    pub started_at: Instant,
48    /// Total bytes received
49    pub bytes_received: u64,
50    /// Video frames received
51    pub video_frames: u64,
52    /// Audio frames received
53    pub audio_frames: u64,
54    /// Keyframes received
55    pub keyframes: u64,
56    /// Last video timestamp
57    pub last_video_ts: u32,
58    /// Last audio timestamp
59    pub last_audio_ts: u32,
60    /// Video codec info
61    pub video_codec: Option<String>,
62    /// Audio codec info
63    pub audio_codec: Option<String>,
64    /// Video width
65    pub width: Option<u32>,
66    /// Video height
67    pub height: Option<u32>,
68    /// Video framerate
69    pub framerate: Option<f64>,
70    /// Audio sample rate
71    pub audio_sample_rate: Option<u32>,
72    /// Audio channels
73    pub audio_channels: Option<u8>,
74}
75
76impl StreamStats {
77    pub fn new(stream_key: String) -> Self {
78        Self {
79            stream_key,
80            started_at: Instant::now(),
81            bytes_received: 0,
82            video_frames: 0,
83            audio_frames: 0,
84            keyframes: 0,
85            last_video_ts: 0,
86            last_audio_ts: 0,
87            video_codec: None,
88            audio_codec: None,
89            width: None,
90            height: None,
91            framerate: None,
92            audio_sample_rate: None,
93            audio_channels: None,
94        }
95    }
96
97    /// Get duration since stream started
98    pub fn duration(&self) -> Duration {
99        self.started_at.elapsed()
100    }
101
102    /// Calculate bitrate in bits per second
103    pub fn bitrate(&self) -> u64 {
104        let secs = self.duration().as_secs();
105        if secs > 0 {
106            (self.bytes_received * 8) / secs
107        } else {
108            0
109        }
110    }
111
112    /// Calculate video framerate
113    pub fn calculated_framerate(&self) -> f64 {
114        let secs = self.duration().as_secs_f64();
115        if secs > 0.0 {
116            self.video_frames as f64 / secs
117        } else {
118            0.0
119        }
120    }
121}
122
123/// Server-wide statistics
124#[derive(Debug, Clone, Default)]
125pub struct ServerStats {
126    /// Total connections ever
127    pub total_connections: u64,
128    /// Current active connections
129    pub active_connections: u64,
130    /// Total bytes received
131    pub total_bytes_received: u64,
132    /// Total bytes sent
133    pub total_bytes_sent: u64,
134    /// Active streams
135    pub active_streams: u64,
136    /// Uptime
137    pub uptime: Duration,
138}
139
140impl ServerStats {
141    pub fn new() -> Self {
142        Self::default()
143    }
144}