webrtc-issue-detector
Version:
WebRTC diagnostic tool that detects issues with network or user devices
426 lines (425 loc) • 12.4 kB
TypeScript
import PeriodicWebRTCStatsReporter from './parser/PeriodicWebRTCStatsReporter';
import { AddConnectionPayload } from './parser/CompositeRTCStatsParser';
import { WebRTCIssueEmitter } from './WebRTCIssueEmitter';
export interface WIDWindow {
wid: {
handleNewPeerConnection(pc: RTCPeerConnection, id?: string): void;
};
}
export declare type IssueDetectorResult = IssuePayload[];
export interface IssueDetector {
detect(data: WebRTCStatsParsed, networkScores?: NetworkScores): IssueDetectorResult;
}
export interface INetworkScoresCalculator {
calculate(data: WebRTCStatsParsed): NetworkScores;
}
export declare enum EventType {
Issue = "issue",
NetworkScoresUpdated = "network-scores-updated",
StatsParsingFinished = "stats-parsing-finished"
}
export declare type EventPayload = IssueDetectorResult;
export interface StatsReportItem {
id: string;
stats: WebRTCStatsParsed;
timeTaken: number;
}
export interface ConnectionInfo {
id: string;
pc: RTCPeerConnection;
}
export interface CompositeStatsParser {
addPeerConnection: (payload: AddConnectionPayload) => void;
parse: () => Promise<StatsReportItem[]>;
}
export interface StatsParser {
parse: (info: ConnectionInfo) => Promise<StatsReportItem | undefined>;
}
export declare type WebRTCIssueDetectorConstructorParams = {
issueEmitter?: WebRTCIssueEmitter;
networkScoresCalculator?: INetworkScoresCalculator;
detectors?: IssueDetector[];
compositeStatsParser?: CompositeStatsParser;
statsReporter?: PeriodicWebRTCStatsReporter;
logger?: Logger;
onIssues?: (payload: IssueDetectorResult) => void;
onNetworkScoresUpdated?: (payload: NetworkScores) => void;
onStats?: (payload: StatsReportItem[]) => void;
ignoreSSRCList?: number[];
getStatsInterval?: number;
autoAddPeerConnections?: boolean;
};
export declare enum IssueType {
Network = "network",
CPU = "cpu",
Server = "server",
Stream = "stream"
}
export declare enum IssueReason {
OutboundNetworkQuality = "outbound-network-quality",
InboundNetworkQuality = "inbound-network-quality",
OutboundNetworkMediaLatency = "outbound-network-media-latency",
InboundNetworkMediaLatency = "inbound-network-media-latency",
NetworkMediaSyncFailure = "network-media-sync-failure",
OutboundNetworkThroughput = "outbound-network-throughput",
InboundNetworkThroughput = "inbound-network-throughput",
EncoderCPUThrottling = "encoder-cpu-throttling",
DecoderCPUThrottling = "decoder-cpu-throttling",
ServerIssue = "server-issue",
UnknownVideoDecoderIssue = "unknown-video-decoder",
LowInboundMOS = "low-inbound-mean-opinion-score",
LowOutboundMOS = "low-outbound-mean-opinion-score",
FrozenVideoTrack = "frozen-video-track",
MissingVideoStreamData = "missing-video-stream-data",
MissingAudioStreamData = "missing-audio-stream-data"
}
export declare type IssuePayload = {
type: IssueType;
reason: IssueReason;
ssrc?: number;
iceCandidate?: string;
data?: number;
statsSample?: Record<string, unknown>;
trackIdentifier?: string;
};
export declare type DetectIssuesPayload = {
data: WebRTCStatsParsed;
};
export declare type NetworkScore = number;
export declare type NetworkQualityStatsSample = {
avgJitter: number;
rtt: number;
packetsLoss: number;
};
export declare type NetworkScores = {
outbound?: NetworkScore;
inbound?: NetworkScore;
connectionId?: string;
statsSamples: {
outboundStatsSample?: NetworkQualityStatsSample;
inboundStatsSample?: NetworkQualityStatsSample;
};
};
export declare type StatsParsingFinishedPayload = {
timeTaken: number;
ts: number;
};
export declare type ParsedInboundAudioStreamStats = {
audioLevel: number;
bitrate: number;
bytesReceived: number;
clockRate: number;
codecId: string;
concealedSamples: number;
concealmentEvents: number;
fecPacketsDiscarded: number;
fecPacketsReceived: number;
headerBytesReceived: number;
id: string;
insertedSamplesForDeceleration: number;
jitter: number;
jitterBufferDelay: number;
jitterBufferEmittedCount: number;
kind: 'audio';
lastPacketReceivedTimestamp: number;
mediaType: string;
mimeType: string;
packetRate: number;
packetsDiscarded: number;
packetsLost: number;
packetsReceived: number;
payloadType: number;
remoteId: string;
removedSamplesForAcceleration: number;
silentConcealedSamples: number;
ssrc: number;
timestamp: number;
totalAudioEnergy: number;
totalSamplesDuration: number;
totalSamplesReceived: number;
track: {
audioLevel: number;
concealedSamples: number;
concealmentEvents: number;
detached: boolean;
ended: boolean;
id: string;
insertedSamplesForDeceleration: number;
jitterBufferDelay: number;
jitterBufferEmittedCount: number;
kind: 'audio';
remoteSource: boolean;
removedSamplesForAcceleration: number;
silentConcealedSamples: number;
timestamp: number;
totalAudioEnergy: number;
totalSamplesDuration: number;
totalSamplesReceived: number;
trackIdentifier: string;
type: string;
};
trackId: string;
transportId: string;
trackIdentifier: string;
};
export declare type ParsedOutboundAudioStreamStats = {
bitrate: number;
bytesSent: number;
clockRate: number;
codecId: string;
headerBytesSent: number;
id: string;
kind: string;
mediaSourceId: string;
mediaType: string;
mimeType: string;
nackCount: number;
packetRate: number;
packetsSent: number;
payloadType: number;
remoteId: string;
retransmittedBytesSent: number;
retransmittedPacketsSent: number;
ssrc: number;
timestamp: number;
targetBitrate: number;
track: {
audioLevel: number;
echoReturnLoss: number;
echoReturnLossEnhancement: number;
id: string;
kind: string;
timestamp: number;
totalAudioEnergy: number;
totalSamplesDuration: number;
trackIdentifier: string;
type: string;
};
trackId: string;
transportId: string;
};
export declare type ParsedInboundVideoStreamStats = {
bitrate: number;
bytesReceived: number;
clockRate: number;
codecId: string;
decoderImplementation: string;
firCount: number;
frameHeight: number;
frameWidth: number;
framesDecoded: number;
framesDropped: number;
framesPerSecond: number;
framesReceived: number;
headerBytesReceived: number;
id: string;
jitter: number;
jitterBufferDelay: number;
jitterBufferEmittedCount: number;
keyFramesDecoded: number;
kind: 'video';
mediaType: string;
mimeType: string;
nackCount: number;
packetRate: number;
packetsLost: number;
packetsReceived: number;
payloadType: number;
pliCount: number;
ssrc: number;
timestamp: number;
totalDecodeTime: number;
totalInterFrameDelay: number;
totalSquaredInterFrameDelay: number;
freezeCount: number;
totalFreezesDuration: number;
track: {
detached: boolean;
ended: boolean;
frameHeight: number;
frameWidth: number;
framesDecoded: number;
framesDropped: number;
framesReceived: number;
id: string;
jitterBufferDelay: number;
jitterBufferEmittedCount: number;
kind: 'video';
remoteSource: boolean;
timestamp: number;
trackIdentifier: string;
type: string;
};
trackId: string;
transportId: string;
trackIdentifier: string;
};
export declare type ParsedOutboundVideoStreamStats = {
bitrate: number;
bytesSent: number;
clockRate: number;
codecId: string;
encoderImplementation: string;
firCount: number;
frameHeight: number;
frameWidth: number;
framesEncoded: number;
framesPerSecond: number;
framesSent: number;
headerBytesSent: number;
hugeFramesSent: number;
id: string;
keyFramesEncoded: number;
kind: string;
mediaSourceId: string;
mediaType: string;
mimeType: string;
nackCount: number;
packetRate: number;
packetsSent: number;
payloadType: number;
pliCount: number;
qpSum: number;
qualityLimitationDurations: {
other: number;
cpu: number;
bandwidth: number;
none: number;
};
qualityLimitationReason: 'none' | 'bandwidth' | 'cpu' | 'other';
qualityLimitationResolutionChanges: number;
remoteId: string;
retransmittedBytesSent: number;
retransmittedPacketsSent: number;
rid: string;
ssrc: number;
timestamp: number;
totalEncodeTime: number;
totalEncodedBytesTarget: number;
totalPacketSendDelay: number;
track: {
id: string;
frames: number;
framesPerSecond: number;
height: number;
timestamp: number;
type: string;
trackIdentifier: string;
kind: string;
width: number;
};
trackId: string;
transportId: string;
type: string;
};
export declare type ParsedConnectionStats = {
availableOutgoingBitrate: number;
bytesReceived: number;
bytesSent: number;
currentRoundTripTime: number;
id: string;
transportId: string;
packetsReceived: number;
packetsSent: number;
state: string;
totalRoundTripTime: number;
type: string;
local: IceCandidateConnectionStats;
remote: IceCandidateConnectionStats;
};
export declare type IceCandidateConnectionStats = {
address: string;
candidateType: string;
id: string;
ip: string;
isRemote: boolean;
networkType?: string;
port: number;
priority: number;
protocol: 'udp' | 'tcp';
timestamp: number;
transportId: string;
type: 'local-candidate' | 'remote-candidate';
};
export declare type ParsedRemoteInboundStreamStats = {
clockRate: number;
codecId: string;
fractionLost: number;
id: string;
jitter: number;
kind: string;
localId: string;
mimeType: string;
packetsLost: number;
payloadType: number;
roundTripTime: number;
roundTripTimeMeasurements: number;
ssrc: number;
timestamp: number;
totalRoundTripTime: number;
transportId: string;
type: string;
};
export declare type ParsedRemoteOutboundStreamStats = {
bytesSent: number;
clockRate: number;
codecId: string;
id: string;
kind: string;
localId: string;
mimeType: string;
packetsSent: number;
payloadType: number;
remoteTimestamp: number;
reportsSent: number;
roundTripTimeMeasurements: number;
ssrc: number;
timestamp: number;
totalRoundTripTime: number;
transportId: string;
type: string;
};
export declare type RemoteParsedStats = {
video: {
inbound: ParsedRemoteInboundStreamStats[];
outbound: ParsedRemoteOutboundStreamStats[];
};
audio: {
inbound: ParsedRemoteInboundStreamStats[];
outbound: ParsedRemoteOutboundStreamStats[];
};
};
export declare type WebRTCStatsParsed = {
audio: {
inbound: ParsedInboundAudioStreamStats[];
outbound: ParsedOutboundAudioStreamStats[];
};
video: {
inbound: ParsedInboundVideoStreamStats[];
outbound: ParsedOutboundVideoStreamStats[];
};
connection: ParsedConnectionStats;
remote: RemoteParsedStats;
};
export interface Logger {
debug: (msg: any, ...meta: any[]) => void;
info: (msg: any, ...meta: any[]) => void;
warn: (msg: any, ...meta: any[]) => void;
error: (msg: any, ...meta: any[]) => void;
}
export declare enum MosQuality {
BAD = 2.1,
POOR = 2.6,
FAIR = 3.1,
GOOD = 3.8,
EXCELLENT = 4.3
}
export declare type WebRTCStatsParsedWithNetworkScores = WebRTCStatsParsed & {
networkScores: NetworkScores;
};
declare type CommonKeys<T, U> = Extract<keyof T, keyof U>;
declare type CommonFields<T, U> = {
[K in CommonKeys<T, U>]: T[K] extends object ? U[K] extends object ? CommonFields<T[K], U[K]> : never : T[K];
};
export declare type CommonParsedInboundStreamStats = CommonFields<ParsedInboundVideoStreamStats, ParsedInboundAudioStreamStats>;
export {};