iOS端WebRTC接收视频呼叫时无视频ICE候选生成问题
iOS WebRTC 视频通话接收端无视频ICE候选问题
问题现象
发起视频呼叫流程正常,但接收端在设置本地描述后,didGenerate代理仅返回音频ICE候选(candidate.sdpMid=0),始终不生成视频ICE候选(candidate.sdpMid=1),导致doAcceptCall中的定时器因检测不到视频候选无法退出,呼叫应答流程卡壳。
已知前置条件
- 服务器返回的Remote SDP已包含完整的视频相关参数
- 代码中创建媒体发送者时,已尝试添加视频轨道
操作流程回顾
- 收到视频呼叫邀请后,处理含
m=video的Remote SDP,创建Offer类型RTCSessionDescription - 初始化媒体资源,向
peerConnection添加视频轨道 - 设置
peerConnection远程描述,在回调中创建OfferToReceiveAudio和OfferToReceiveVideo均为true的应答约束 - 调用
setLocalDescription设置本地SDP - WebRTC仅生成音频ICE候选,无视频候选输出
问题定位与修复方案
1. 修复startMode赋值逻辑错误
当前代码中defaultPeerConnectionConstraints依赖self.startMode判断是否接收视频,但接收呼叫场景下startMode未被同步为视频模式,导致约束中视频接收参数未生效。
修改acceptCall方法,同步startMode为当前应答的视频模式:
- (void) acceptCall:(ndCallMode)mode{ RLogInfo(@"tag = %@", self.localTag); if ([self isEnded]){ return; } if (!self.isInviteReceived) { self.isIncomingAcceptedBeforeInvite = YES; self.localModeIncomingAcceptedBeforeInvite = mode; return; } self.isAnswered = YES; self.localMode = mode; // 新增:同步startMode为当前应答的呼叫模式 self.startMode = mode; self.state = ndCallStateIncomingAnswer; [self.callManager showCallInterface:self]; [self.callViewDelegate didCallStateChanged]; [self prepare]; // ... 剩余原有代码保持不变 ... }
2. 调整视频轨道添加的判断条件
createMediaSenders中原本使用self.startMode判断是否添加视频轨道,但接收呼叫时startMode更新不及时,导致视频轨道未被正确添加到peerConnection。改用已在acceptCall中设置的self.localMode作为判断条件:
- (void) createMediaSenders{ self.stream = [self.factory mediaStreamWithStreamId:kMediaStreamId]; RTCMediaConstraints *constraints = [self defaultMediaAudioConstraints]; RTCAudioSource *audioSource = [self.factory audioSourceWithConstraints:constraints]; RTCAudioTrack *audioTrack = [self.factory audioTrackWithSource:audioSource trackId:kAudioTrackId]; NSMutableArray *streamIds = [@[kMediaStreamId] mutableCopy]; [self.stream addAudioTrack:audioTrack]; #if !TARGET_IPHONE_SIMULATOR // 修改判断条件为localMode,确保接收视频呼叫时添加视频轨道 if (self.localMode == ndCallModeVideo){ RTCVideoSource *videoSource = [self.factory videoSource]; self.videoCapturer = [[VideoCapturer alloc] init]; [self.videoCapturer startCaptureLocalVideoWithVideoSource:videoSource settings:[LocalVideoCaptureSetting createDefaultSetting]]; self.localVideoTrack = [self.factory videoTrackWithSource:videoSource trackId:kVideoTrackId]; [self.stream addVideoTrack:self.localVideoTrack]; [self.localVideoTrack addRenderer:[self.callViewDelegate getCameraPreviewView]]; [self.peerConnection addTrack:self.localVideoTrack streamIds:streamIds]; } #endif [self.peerConnection addTrack: audioTrack streamIds:streamIds]; }
3. 确保应答约束正确设置视频接收参数
检查defaultAnswerConstraints方法(如果未实现则补充),确保应答时根据当前呼叫模式设置正确的视频接收参数:
- (RTCMediaConstraints *)defaultAnswerConstraints { NSDictionary *mandatoryConstraints = @{ @"OfferToReceiveAudio" : @"true", @"OfferToReceiveVideo" : (self.localMode == ndCallModeVideo) ? @"true" : @"false" }; NSDictionary *optionalConstraints = @{ @"DtlsSrtpKeyAgreement" : @"true" }; return [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mandatoryConstraints optionalConstraints:optionalConstraints]; }
4. 排查SDP预处理是否破坏视频参数
prepareRemoteSdp方法中对Remote SDP进行了修改,需确认未移除m=video行或视频相关的关键属性。可临时注释掉SDP预处理代码,测试是否能生成视频ICE候选,逐步定位是否是SDP修改导致的问题。
内容的提问来源于stack exchange,提问作者Tilek
相关产品推荐
相关产品推荐

