@@ -146,23 +146,50 @@ export class StreamingClient {
146146
147147 try {
148148 const stats = await this . peerConnection . getStats ( ) ;
149+
150+ let videoDetected = false ;
151+ let detectionMethod = null ;
152+
149153 stats . forEach ( ( report ) => {
150154 // Find the report for inbound video
151155 if ( report . type === 'inbound-rtp' && report . kind === 'video' ) {
152- if ( report . framesReceived > 0 ) {
153- this . successMetricFired = true ;
154- sendClientMetric (
155- ClientMetricMeasurement . CLIENT_METRIC_MEASUREMENT_SESSION_SUCCESS ,
156- '1' ,
157- ) ;
158- if ( this . successMetricPoller ) {
159- clearInterval ( this . successMetricPoller ) ;
160- }
161- clearTimeout ( timeoutId ) ;
162- this . successMetricPoller = null ;
156+ // Method 1: Try framesDecoded (most reliable when available)
157+ if (
158+ report . framesDecoded !== undefined &&
159+ report . framesDecoded > 0
160+ ) {
161+ videoDetected = true ;
162+ detectionMethod = 'framesDecoded' ;
163+ } else if (
164+ report . framesReceived !== undefined &&
165+ report . framesReceived > 0
166+ ) {
167+ videoDetected = true ;
168+ detectionMethod = 'framesReceived' ;
169+ } else if (
170+ report . bytesReceived > 0 &&
171+ report . packetsReceived > 0 &&
172+ // Additional check: ensure we've received enough data for actual video
173+ report . bytesReceived > 100000 // rough threshold
174+ ) {
175+ videoDetected = true ;
176+ detectionMethod = 'bytesReceived' ;
163177 }
164178 }
165179 } ) ;
180+ if ( videoDetected && ! this . successMetricFired ) {
181+ this . successMetricFired = true ;
182+ sendClientMetric (
183+ ClientMetricMeasurement . CLIENT_METRIC_MEASUREMENT_SESSION_SUCCESS ,
184+ '1' ,
185+ detectionMethod ? { detectionMethod } : undefined ,
186+ ) ;
187+ if ( this . successMetricPoller ) {
188+ clearInterval ( this . successMetricPoller ) ;
189+ }
190+ clearTimeout ( timeoutId ) ;
191+ this . successMetricPoller = null ;
192+ }
166193 } catch ( error ) { }
167194 } , 500 ) ;
168195 }
@@ -448,6 +475,14 @@ export class StreamingClient {
448475 // unregister the callback after the first frame
449476 this . videoElement ?. cancelVideoFrameCallback ( handle ) ;
450477 this . publicEventEmitter . emit ( AnamEvent . VIDEO_PLAY_STARTED ) ;
478+ if ( ! this . successMetricFired ) {
479+ this . successMetricFired = true ;
480+ sendClientMetric (
481+ ClientMetricMeasurement . CLIENT_METRIC_MEASUREMENT_SESSION_SUCCESS ,
482+ '1' ,
483+ { detectionMethod : 'videoElement' } ,
484+ ) ;
485+ }
451486 } ) ;
452487 }
453488 } else if ( event . track . kind === 'audio' ) {
@@ -568,11 +603,7 @@ export class StreamingClient {
568603 private async shutdown ( ) {
569604 if ( this . showPeerConnectionStatsReport ) {
570605 const stats = await this . peerConnection ?. getStats ( ) ;
571- if ( ! stats ) {
572- console . error (
573- 'StreamingClient - shutdown: peer connection is unavailable. Unable to create RTC stats report.' ,
574- ) ;
575- } else {
606+ if ( stats ) {
576607 const report = createRTCStatsReport (
577608 stats ,
578609 this . peerConnectionStatsReportOutputFormat ,
0 commit comments