1
1
import {
2
+ CommonParsedInboundStreamStats ,
2
3
IssueDetectorResult ,
4
+ IssuePayload ,
3
5
IssueReason ,
4
6
IssueType ,
5
- ParsedInboundAudioStreamStats ,
6
- ParsedInboundVideoStreamStats ,
7
- WebRTCStatsParsed ,
7
+ WebRTCStatsParsed
8
8
} from '../types' ;
9
9
import BaseIssueDetector from './BaseIssueDetector' ;
10
10
@@ -18,7 +18,7 @@ export class MissingStreamDataDetector extends BaseIssueDetector {
18
18
19
19
constructor ( params : MissingStreamDetectorParams = { } ) {
20
20
super ( ) ;
21
- this . #timeoutMs = params . timeoutMs ?? 10_000 ;
21
+ this . #timeoutMs = params . timeoutMs ?? 5_000 ;
22
22
}
23
23
24
24
performDetection ( data : WebRTCStatsParsed ) : IssueDetectorResult {
@@ -29,108 +29,65 @@ export class MissingStreamDataDetector extends BaseIssueDetector {
29
29
}
30
30
31
31
private processData ( data : WebRTCStatsParsed ) : IssueDetectorResult {
32
- const { connection : { id : connectionId } } = data ;
33
- const previousStats = this . getLastProcessedStats ( connectionId ) ;
34
32
const issues : IssueDetectorResult = [ ] ;
35
33
36
- if ( ! previousStats ) {
37
- return issues ;
38
- }
39
-
40
34
const { video : { inbound : newVideoInbound } } = data ;
41
- const { video : { inbound : prevVideoInbound } } = previousStats ;
42
35
const { audio : { inbound : newAudioInbound } } = data ;
43
- const { audio : { inbound : prevAudioInbound } } = previousStats ;
44
-
45
- const mapVideoStatsByTrackId = ( items : ParsedInboundVideoStreamStats [ ] ) => new Map < string , ParsedInboundVideoStreamStats > (
46
- items . map ( ( item ) => [ item . track . trackIdentifier , item ] as const ) ,
47
- ) ;
48
- const mapAudioStatsByTrackId = ( items : ParsedInboundAudioStreamStats [ ] ) => new Map < string , ParsedInboundAudioStreamStats > (
49
- items . map ( ( item ) => [ item . track . trackIdentifier , item ] as const ) ,
50
- ) ;
51
-
52
- const newVideoInboundByTrackId = mapVideoStatsByTrackId ( newVideoInbound ) ;
53
- const prevVideoInboundByTrackId = mapVideoStatsByTrackId ( prevVideoInbound ) ;
54
- const newAudioInboundByTrackId = mapAudioStatsByTrackId ( newAudioInbound ) ;
55
- const prevAudioInboundByTrackId = mapAudioStatsByTrackId ( prevAudioInbound ) ;
56
- const unvisitedTrackIds = new Set ( this . #lastMarkedAt. keys ( ) ) ;
57
-
58
- Array . from ( newVideoInboundByTrackId . entries ( ) ) . forEach ( ( [ trackId , newInboundItem ] ) => {
59
- unvisitedTrackIds . delete ( trackId ) ;
60
36
61
- const prevInboundItem = prevVideoInboundByTrackId . get ( trackId ) ;
62
- if ( ! prevInboundItem ) {
63
- return ;
64
- }
65
-
66
- const deltaFramesReceived = newInboundItem . framesReceived - prevInboundItem . framesReceived ;
67
-
68
- if ( deltaFramesReceived === 0 && ! newInboundItem . track . detached && ! newInboundItem . track . ended ) {
69
- const hasIssue = this . markIssue ( trackId ) ;
37
+ issues . push ( ...this . detectMissingData (
38
+ newAudioInbound as unknown as CommonParsedInboundStreamStats [ ] ,
39
+ IssueType . Stream ,
40
+ IssueReason . MissingAudioStreamData ,
41
+ ) ) ;
42
+ issues . push ( ...this . detectMissingData (
43
+ newVideoInbound ,
44
+ IssueType . Stream ,
45
+ IssueReason . MissingVideoStreamData ,
46
+ ) ) ;
70
47
71
- if ( ! hasIssue ) {
72
- return ;
73
- }
74
-
75
- const statsSample = {
76
- framesReceived : newInboundItem . framesReceived ,
77
- framesDropped : newInboundItem . framesDropped ,
78
- trackDetached : newInboundItem . track . detached ,
79
- trackEnded : newInboundItem . track . ended ,
80
- } ;
48
+ const unvisitedTrackIds = new Set ( this . #lastMarkedAt. keys ( ) ) ;
81
49
82
- issues . push ( {
83
- type : IssueType . Stream ,
84
- reason : IssueReason . MissingVideoStreamData ,
85
- statsSample,
86
- } ) ;
87
- } else {
50
+ unvisitedTrackIds . forEach ( ( trackId ) => {
51
+ const lastMarkedAt = this . #lastMarkedAt. get ( trackId ) ;
52
+ if ( lastMarkedAt && Date . now ( ) - lastMarkedAt > this . #timeoutMs) {
88
53
this . removeMarkIssue ( trackId ) ;
89
54
}
90
55
} ) ;
91
56
92
- Array . from ( newAudioInboundByTrackId . entries ( ) ) . forEach ( ( [ trackId , newInboundItem ] ) => {
93
- unvisitedTrackIds . delete ( trackId ) ;
57
+ return issues ;
58
+ }
94
59
95
- const prevInboundItem = prevAudioInboundByTrackId . get ( trackId ) ;
96
- if ( ! prevInboundItem ) {
97
- return ;
98
- }
60
+ private detectMissingData ( commonStreamStats : CommonParsedInboundStreamStats [ ] , type : IssueType , reason : IssueReason ) : IssueDetectorResult {
61
+ const issues : IssuePayload [ ] = [ ] ;
99
62
100
- const deltaFramesReceived = newInboundItem . bytesReceived - prevInboundItem . bytesReceived ;
63
+ commonStreamStats . forEach ( ( inboundItem ) => {
64
+ const trackId = inboundItem . track . trackIdentifier
101
65
102
- if ( deltaFramesReceived === 0 && ! newInboundItem . track . detached && ! newInboundItem . track . ended ) {
66
+ if ( inboundItem . bytesReceived === 0 && ! inboundItem . track . detached && ! inboundItem . track . ended ) {
103
67
const hasIssue = this . markIssue ( trackId ) ;
104
68
105
69
if ( ! hasIssue ) {
106
70
return ;
107
71
}
108
72
109
73
const statsSample = {
110
- bytesReceived : newInboundItem . bytesReceived ,
111
- packetsDiscarded : newInboundItem . packetsDiscarded ,
112
- trackDetached : newInboundItem . track . detached ,
113
- trackEnded : newInboundItem . track . ended ,
74
+ bytesReceived : inboundItem . bytesReceived ,
75
+ trackDetached : inboundItem . track . detached ,
76
+ trackEnded : inboundItem . track . ended ,
114
77
} ;
115
78
116
79
issues . push ( {
117
- type : IssueType . Stream ,
118
- reason : IssueReason . MissingAudioStreamData ,
80
+ type,
81
+ reason,
119
82
statsSample,
83
+ trackIdentifier : trackId ,
120
84
} ) ;
121
85
} else {
122
86
this . removeMarkIssue ( trackId ) ;
123
87
}
124
88
} ) ;
125
89
126
- unvisitedTrackIds . forEach ( ( trackId ) => {
127
- const lastMarkedAt = this . #lastMarkedAt. get ( trackId ) ;
128
- if ( lastMarkedAt && Date . now ( ) - lastMarkedAt > this . #timeoutMs) {
129
- this . removeMarkIssue ( trackId ) ;
130
- }
131
- } ) ;
132
-
133
- return issues ;
90
+ return issues
134
91
}
135
92
136
93
private markIssue ( trackId : string ) : boolean {
0 commit comments