import React from 'react' import { useAppSelector } from '@/app/hooks' import type { RTCInboundRtpStreamStats } from '@/types' function mediaStreamStatsReportFilter( statsReport: RTCStats[], mediaStream: MediaStream | null, type: 'video' | 'audio', ): RTCInboundRtpStreamStats | undefined { if (mediaStream === null) { return undefined } let trackIds: string[] = [] if (type === 'video') { trackIds = mediaStream.getVideoTracks().map((t) => { return t.id }) } else if (type === 'audio') { trackIds = mediaStream.getAudioTracks().map((t) => { return t.id }) } const targetStats = statsReport.find((stats) => { if (stats.type !== 'inbound-rtp') { return false } if (!('kind' in stats) || !('trackIdentifier' in stats)) { return false } const inboundRtpStats = stats as RTCInboundRtpStreamStats if (inboundRtpStats.kind !== type) { return false } if (!trackIds.includes(inboundRtpStats.trackIdentifier)) { return false } return true }) return targetStats as RTCInboundRtpStreamStats } type Props = { stream: MediaStream type: 'video' | 'audio' } export const JitterButter: React.FC = (props) => { const statsReport = useAppSelector((state) => state.soraContents.statsReport) const prevStatsReport = useAppSelector((state) => state.soraContents.prevStatsReport) const currentInboundRtpStreamStatsReport = mediaStreamStatsReportFilter( statsReport, props.stream, props.type, ) const prevInboundRtpStreamStatsReport = mediaStreamStatsReportFilter( prevStatsReport, props.stream, props.type, ) if (currentInboundRtpStreamStatsReport === undefined) { return null } if ( currentInboundRtpStreamStatsReport.jitterBufferDelay === undefined || currentInboundRtpStreamStatsReport.jitterBufferEmittedCount === undefined ) { return null } let jitterBufferDelay = currentInboundRtpStreamStatsReport.jitterBufferDelay let jitterBufferEmittedCount = currentInboundRtpStreamStatsReport.jitterBufferEmittedCount if ( prevInboundRtpStreamStatsReport !== undefined && prevInboundRtpStreamStatsReport.jitterBufferDelay !== undefined && prevInboundRtpStreamStatsReport.jitterBufferEmittedCount !== undefined ) { jitterBufferDelay = currentInboundRtpStreamStatsReport.jitterBufferDelay - prevInboundRtpStreamStatsReport.jitterBufferDelay jitterBufferEmittedCount = currentInboundRtpStreamStatsReport.jitterBufferEmittedCount - prevInboundRtpStreamStatsReport.jitterBufferEmittedCount } const currentJitterBufferDelay = Math.floor((jitterBufferDelay / jitterBufferEmittedCount) * 1000) let borderClassName = 'normal-jitter-buffer' if (500 < currentJitterBufferDelay) { borderClassName = 'critical-jitter-buffer' } else if (300 < currentJitterBufferDelay) { borderClassName = 'danger-jitter-buffer' } else if (100 < currentJitterBufferDelay) { borderClassName = 'warning-jitter-buffer' } return (
{props.type}: {currentJitterBufferDelay}
) }