Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions src/lib/ClientMetrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,11 +148,11 @@ export const createRTCStatsReport = (

inboundVideo.forEach((report) => {
const videoData = {
framesReceived: report.framesReceived || 'unknown',
framesDropped: report.framesDropped || 'unknown',
framesPerSecond: report.framesPerSecond || 'unknown',
packetsReceived: report.packetsReceived || 'unknown',
packetsLost: report.packetsLost || 'unknown',
framesReceived: report.framesReceived ?? 'unknown',
framesDropped: report.framesDropped ?? 'unknown',
framesPerSecond: report.framesPerSecond ?? 'unknown',
packetsReceived: report.packetsReceived ?? 'unknown',
packetsLost: report.packetsLost ?? 'unknown',
resolution:
report.frameWidth && report.frameHeight
? `${report.frameWidth}x${report.frameHeight}`
Expand All @@ -172,9 +172,9 @@ export const createRTCStatsReport = (

inboundAudio.forEach((report) => {
const audioData = {
packetsReceived: report.packetsReceived || 'unknown',
packetsLost: report.packetsLost || 'unknown',
audioLevel: report.audioLevel || 'unknown',
packetsReceived: report.packetsReceived ?? 'unknown',
packetsLost: report.packetsLost ?? 'unknown',
audioLevel: report.audioLevel ?? 'unknown',
jitter: report.jitter !== undefined ? report.jitter : undefined,
totalAudioEnergy:
report.totalAudioEnergy !== undefined
Expand All @@ -194,8 +194,8 @@ export const createRTCStatsReport = (

outboundAudio.forEach((report) => {
const userAudioData = {
packetsSent: report.packetsSent || 'unknown',
retransmittedPackets: report.retransmittedPacketsSent || undefined,
packetsSent: report.packetsSent ?? 'unknown',
retransmittedPackets: report.retransmittedPacketsSent ?? undefined,
avgPacketSendDelay:
report.totalPacketSendDelay !== undefined
? (report.totalPacketSendDelay / (report.packetsSent || 1)) * 1000
Expand Down
63 changes: 47 additions & 16 deletions src/modules/StreamingClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,23 +146,50 @@ export class StreamingClient {

try {
const stats = await this.peerConnection.getStats();

let videoDetected = false;
let detectionMethod = null;

stats.forEach((report) => {
// Find the report for inbound video
if (report.type === 'inbound-rtp' && report.kind === 'video') {
if (report.framesReceived > 0) {
this.successMetricFired = true;
sendClientMetric(
ClientMetricMeasurement.CLIENT_METRIC_MEASUREMENT_SESSION_SUCCESS,
'1',
);
if (this.successMetricPoller) {
clearInterval(this.successMetricPoller);
}
clearTimeout(timeoutId);
this.successMetricPoller = null;
// Method 1: Try framesDecoded (most reliable when available)
if (
report.framesDecoded !== undefined &&
report.framesDecoded > 0
) {
videoDetected = true;
detectionMethod = 'framesDecoded';
} else if (
report.framesReceived !== undefined &&
report.framesReceived > 0
) {
videoDetected = true;
detectionMethod = 'framesReceived';
} else if (
report.bytesReceived > 0 &&
report.packetsReceived > 0 &&
// Additional check: ensure we've received enough data for actual video
report.bytesReceived > 100000 // rough threshold
) {
videoDetected = true;
detectionMethod = 'bytesReceived';
}
}
});
if (videoDetected && !this.successMetricFired) {
this.successMetricFired = true;
sendClientMetric(
ClientMetricMeasurement.CLIENT_METRIC_MEASUREMENT_SESSION_SUCCESS,
'1',
detectionMethod ? { detectionMethod } : undefined,
);
if (this.successMetricPoller) {
clearInterval(this.successMetricPoller);
}
clearTimeout(timeoutId);
this.successMetricPoller = null;
}
} catch (error) {}
}, 500);
}
Expand Down Expand Up @@ -448,6 +475,14 @@ export class StreamingClient {
// unregister the callback after the first frame
this.videoElement?.cancelVideoFrameCallback(handle);
this.publicEventEmitter.emit(AnamEvent.VIDEO_PLAY_STARTED);
if (!this.successMetricFired) {
this.successMetricFired = true;
sendClientMetric(
ClientMetricMeasurement.CLIENT_METRIC_MEASUREMENT_SESSION_SUCCESS,
'1',
{ detectionMethod: 'videoElement' },
);
}
});
}
} else if (event.track.kind === 'audio') {
Expand Down Expand Up @@ -568,11 +603,7 @@ export class StreamingClient {
private async shutdown() {
if (this.showPeerConnectionStatsReport) {
const stats = await this.peerConnection?.getStats();
if (!stats) {
console.error(
'StreamingClient - shutdown: peer connection is unavailable. Unable to create RTC stats report.',
);
} else {
if (stats) {
const report = createRTCStatsReport(
stats,
this.peerConnectionStatsReportOutputFormat,
Expand Down