import { IStreamSender, ICandidate, PushType, ISenderMap, XYConnectState, XYStreamParameterConfig, XYRTCSessionDescriptionInit } from '../../type/index'; import { default as Client } from '../client'; import { default as Logger } from '../../tools/log/logger'; import { default as VideoAudioTrack } from '../track/videoAudioTrack'; import { default as ContentTrack } from '../track/contentTrack'; import { State } from './state'; /** * Peer模块,用于管理 P2P(媒体Server) 连接和内部事件 */ export default class Peer extends State { private connectTimer; private connectCount; client: Client; peerConnection: RTCPeerConnection | null; logger: Logger; connectState: XYConnectState; streamSenders: IStreamSender[]; senderMap: ISenderMap; private senderTimer; private videoCodecs; private audioCodecs; private qualityWorker; private localCandidateInfo; private remoteCandidateInfo; private peerLibStatus; private firstCallState; private peerCallState; private isReceivedTrackMsg; private isCreatedOffer; private isReceivedAnswer; private contentTrackSize; private detectTrackMsgTimer; private candidateList; private offerKey; constructor(client: Client, isRenew?: boolean); /** * 初始化质量统计WebWorker模块 */ private initQualityWorker; /** * 初始化Peer模块 * 1. 创建PeerConnection * 2. 初始化监听事件 */ private init; /** * 向Client发送消息 * * @param { XYClientEventKey } type - 消息Key * @param { string } code - 状态码 * @param { unknown } detail - 补充消息内容 */ private sendEmmit; /** * 获取Peer是否连接成功 * * @returns { boolean } - 是否连接成功 */ getPeerConnectionStatus(): boolean; /** * 停止状态检查定时器,重置重连状态 */ private stopConnectTimer; /** * 启动检测监听到Track回调消息检测器 * * 检测场景:当Peer连接成功,但是未收到Track消息,导致收音频/视频异常问题 * 检测次数:1次,如仍然失败,则直接退会 */ private startDetectTrackMsgTimer; /** * 清理Track回调检测器定时器 */ private stopDetectTrackMsgTimer; /** * 获取最终协商成功的候选地址对 */ private getCandidatePairs; /** * 监听PeerConnection连接状态 */ private initDetectTimer; /** * 检测是否连接媒体服务器 */ private isConnectionMediaServer; /** * 成功连接媒体服务器后的处理逻辑 */ private handleConnectionMediaServer; /** * 超时检测连接状态 * 用于区分连接中、异常退会状态 * * @param { boolean } disconnected - 是否是强制退会处理,设置为true代表强制退会 */ private handleConnectionWarning; /** * 处理各种与媒体协商失败报错异常 * 处理方式:上报结果&退会或者提示 * * @param { string } code - 错误码 * @param { boolean } disconnected - 是否强制退会,默认是false,代表不强制,设置为true会上报disconnected消息 * @param { unknown } detail - 可选,自定义消息详情数据 */ private handlePeerConnectError; /** * ice协商回调事件 */ private onHandleNegotiationNeeded; /** * 修改SDP内容 * * @param { string } sdp - offer sdp报文信息 * @returns { string } - 修改后的报文 */ private appendExtmap; /** * 创建offer,并针对stream设置初始带宽 * * @private * @param { RTCOfferOptions } options createOffer options * @param isSetBandwidth 是否设置初始带宽,180:100,360: 500, 720: 1000 */ private createBaseOfferConnection; /** * 通过client模块统一发送socket消息 * * @public * @param { string } type 消息key * @param { any } data 消息内容 */ sendSocketMessage(type: string, data: any): void; /** * 处理candidate消息 * * @public * @param { ICandidate } body - candidate消息内容 */ handleCandidate(body: ICandidate): Promise; /** * 缓存协商的Candidate节点信息 * * @param { string } candidate - ICE Candidate协商节点信息 */ private cacheCandidateData; /** * 响应Answer * * @public * @param { XYRTCSessionDescriptionInit } answer answerSDP内容,设置到peerConnection上 */ handleAnswer(answer: XYRTCSessionDescriptionInit): Promise; /** * 对Track轨道进行动态带宽调整、帧率调整 * * @public * @param { string } trackId Track轨道id * @param { Object } encodingParams 需要限定的带宽值、帧率值 * @param { boolean } isIncreaseBase 带宽是否需要✖️系数1000 */ setParameters(trackId: string, encodingParams: { bandwidth: number; frameRate?: number; } | undefined, isIncreaseBase: boolean | undefined, stream: MediaStream | null, config?: XYStreamParameterConfig): Promise; /** * ICE Connection status change * * @param { Event } e - ICE状态回调事件 */ private onHandleIceConnectionStateChange; /** * PeerConnection connect state change * * Only supports Chrome 72 or higher, Firefox 113 or higher * * @param { Event } e - ICE状态回调事件 */ private onHandleConnectionStateChange; /** * 统一处理WebRTC PeerConnection连接状态事件 */ private peerStateChange; /** * WebRTC ICE探测错误事件监听 * * @param { Event } e - 错误信息 */ onHandleIcecandidateerror(e: Event): void; /** * WebRTC ICE协商事件 * * @param { any } ice - ICE报文 */ private onHandleIcecandidate; /** * Peer已经连接成功 * * @returns { boolean } - True或者False */ get isPeerConnected(): boolean; /** * 重连PeerConnection * * @param { 'socket' | 'peer' } entry - 重连入口 */ restartIceConnection(entry: 'socket' | 'peer'): Promise; /** * 关闭PeerConnection连接、销毁状态 */ destroy(): void; /** * Push people and content tracks of stream * * @public * @param { Stream } stream - Stream Library * @param { PushType } pushType - 推送类型,All全推送、Video只推送video、Audio只推送audio、Content只推送content video流 */ publish(track: VideoAudioTrack | ContentTrack, pushType: PushType): void; /** * people and content sender status * * @public */ initSenderStatus(): void; /** * 计算发送/接收端internals统计数据,更新存储到到Layout结果数据中 * 自动每隔6s记录一次内容统计数据到数据库中 * * @param { boolean } init - 是否执行初始化操作 * @private */ private qualityProcess; /** * Reset content sender track * * @public */ closeContentStream(): void; /** * Get peerConnection status */ getPeerStatus(): boolean; /** * Worker回传的结果数据 * * @param { MessageEvent } event - Worker数据结构 */ private onMeetingStats; /** * 获取基础的视频&音频发送Stats统计数据,通过worker计算返回最终的结果 */ private sendSenderStats; /** * 获取基础的音频Audio接收Stats统计数据,通过worker返回最终的结果 */ private sendAudioReceiverStats; /** * 获取基础的视频Video接收Stats统计数据,通过worker计算返回最终的结果 */ private sendVideoReceiverStats; /** * 处理过滤后的StreamConfig数据 * 1、如果存在Sender,则使用replaceTrack方式替换Track * 2、如果不存在Sender,则使用addTransceiver方式协商流通道 * * @param { IStreamConfig[] } streamConfigList 媒体流/协商流列表 * @param { RTCRtpTransceiverDirection } direction 指定添加到peer上的方向 */ private streamConfigProcessor; /** * 计算一组StreamConfig中Track面积最小的尺寸信息 * * @param { IStreamConfig[] } streamConfigList - An array of `IStreamConfig` objects */ private calculateContentTrackSize; /** * 重置ContentTrack尺寸信息 */ resetContentTrackSize(): void; /** * 添加Track轨道数据 * * @private * @param { TCustomStream | MediaStreamTrack } track Track轨道数据 * @param { RTCRtpTransceiverDirection } direction 指定添加到peer上的方向 * @param { IStreamConfig } streamConfig 自定义Stream流配置 */ private addTrackProcessor; /** * 设置Content流默认带宽 */ private setDefaultBandwidth; /** * 设置编解码器 * 兼容:chrome:67+、edge:79、safari:13.1、firefox:不支持 * * @param { TCustomStream | MediaStreamTrack } track Track轨道数据 * @param { RTCRtpTransceiver } rtcRtpTransceiver 流的发送器,由向peer添加track生成 */ private setCodecPreferences; /** * 缓存浏览器支持所有可用的编解码器配置信息 */ private setSupportCodec; /** * 按照顺序排序 * 注意此处使用sort函数,会修改原函数 */ private sortCodecs; /** * 过滤不符合优先级规则的视频编解码器 * * packetization-mode解释: * packetization-mode=0 代表单一 NALU 传输模式,部分 WebRTC 设备可能不支持。 * packetization-mode=1 是 WebRTC 更推荐的模式,因为它支持分片并提高适应性。 * profile-level-id解释: * 42001f(Baseline Profile) * 42e01f(Constrained Baseline Profile) * 4d001f(Main Profile) * 640034(High Profile) * 建议优先 42e01f(Constrained Baseline),因为它适用于大多数移动设备和 WebRTC 兼容客户端 */ private filterVideoCodecs; /** * 替换Sender发送器中的Track数据 * * @param { MediaStreamTrack } track - MediaStreamTrack数据 * @param { IStreamConfig } streamConfig - 自定义流配置 * @param { RTCRtpTransceiverDirection } direction - 通道方向 */ private replaceTrackProcessor; /** * 重置sender发送器的编码器scaleResolutionDownBy参数 * * @param { MediaStreamTrack } track - MediaStreamTrack数据 * @param { RTCRtpSender } sender - 编码发送器 * @param { IStreamConfig } streamConfig - 自定义流配置 */ private resetEncodingsScale; /** * 向peer添加Track轨道数据 * * @private * @param { TCustomStream | MediaStreamTrack } track Track轨道数据 * @param { RTCRtpTransceiverDirection } direction 指定添加到peer上的方向 * @param { IStreamConfig } streamConfig 自定义Stream流对象 */ private addTransceiver; /** * 计算编码器分辨率裁剪比例 * * @param { MediaStreamTrack } track - MediaStream Track * @param { IStreamConfig } streamConfig - 自定义Stream流对象 * @returns { number } - 裁剪比例 */ private calculateScaleValue; /** * 关联自定义stream对象和Sender发送器数据 * * @private * @param { TCustomStream | MediaStreamTrack } track Track轨道数据 * @param { IStreamConfig } item 自定义Stream流对象 * @param { RTCRtpTransceiver } rtcRtpTransceiver 流的发送器,由向peer添加track生成 */ private setSenderMap; /** * 监听远端更新Track事件 * * @private * @event * @param { RTCTrackEvent } e peer回调track数据 */ private onTrack; }