From 7c334096248cb32c2727feb119247365fd6f0035 Mon Sep 17 00:00:00 2001 From: lafay <2021211506@stu.hit.edu.cn> Date: Sat, 28 Mar 2026 01:06:51 +0800 Subject: [PATCH] feat(wsService, WebRTCManager): enhance call handling with media type support and negotiation improvements - Added optional media_type to WSCallIncomingMessage for better call type differentiation. - Updated call_type assignment in WebSocketService to prioritize media_type if available. - Removed initialOfferCreated flag in WebRTCManager to simplify negotiation logic. - Improved negotiation handling by releasing the negotiation lock after offer creation, ensuring smoother call setup. --- src/services/webrtc/WebRTCManager.ts | 22 ++++++++++++---------- src/services/wsService.ts | 3 ++- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/services/webrtc/WebRTCManager.ts b/src/services/webrtc/WebRTCManager.ts index c812df0..4d5fa72 100644 --- a/src/services/webrtc/WebRTCManager.ts +++ b/src/services/webrtc/WebRTCManager.ts @@ -38,7 +38,6 @@ class WebRTCManager { private isInitiator = false; private callType: CallType = 'voice'; private isNegotiating = false; - private initialOfferCreated = false; // Flag to prevent duplicate offer creation async initialize(iceServers: ICEServer[] = []): Promise { if (this.peerConnection) { @@ -103,19 +102,17 @@ class WebRTCManager { // @ts-ignore pc.onnegotiationneeded = async () => { console.log('[WebRTC] Negotiation needed, signalingState:', pc.signalingState, 'isNegotiating:', this.isNegotiating); - + // Check if peer connection is still valid if (!this.peerConnection || this.peerConnection !== pc) { console.log('[WebRTC] PeerConnection changed or disposed, skipping negotiation'); return; } - + // Only start negotiation if: // 1. We're in stable state // 2. Not already negotiating - // 3. We are the initiator - // 4. Initial offer has NOT been created yet (prevent duplicate during startCall) - if (pc.signalingState === 'stable' && !this.isNegotiating && this.isInitiator && !this.initialOfferCreated) { + if (pc.signalingState === 'stable' && !this.isNegotiating) { try { this.isNegotiating = true; const offer = await this.createOffer(); @@ -132,7 +129,7 @@ class WebRTCManager { }, 500); } } else { - console.log('[WebRTC] Skipping negotiation: state=', pc.signalingState, 'isNegotiating=', this.isNegotiating, 'isInitiator=', this.isInitiator, 'initialOfferCreated=', this.initialOfferCreated); + console.log('[WebRTC] Skipping negotiation: state=', pc.signalingState, 'isNegotiating=', this.isNegotiating); } }; @@ -199,7 +196,7 @@ class WebRTCManager { this.isInitiator = isInitiator; this.callType = callType; - this.initialOfferCreated = true; // Set flag BEFORE creating connection to prevent onnegotiationneeded + this.isNegotiating = true; // Prevent onnegotiationneeded from firing during setup this.peerConnection = this.createPeerConnection(); // Setup transceivers FIRST - this ensures consistent m-line order @@ -207,7 +204,7 @@ class WebRTCManager { // Now add local tracks to transceivers const transceivers = this.peerConnection.getTransceivers(); - + // Add audio track to audio transceiver const audioTrack = this.localStream.getAudioTracks()[0]; const audioTransceiver = transceivers.find(t => t.receiver.track?.kind === 'audio'); @@ -227,8 +224,14 @@ class WebRTCManager { if (isInitiator) { // For initiator, create offer directly here const offer = await this.createOffer(); + // Release negotiation lock after a delay to allow state to settle + setTimeout(() => { + this.isNegotiating = false; + }, 500); return offer; } + // For non-initiator, release lock immediately since no offer is created + this.isNegotiating = false; return null; } @@ -547,7 +550,6 @@ class WebRTCManager { this.eventHandlers.clear(); this.pendingCandidates = []; this.isNegotiating = false; - this.initialOfferCreated = false; if (this.localStream) { this.localStream.getTracks().forEach((track) => track.stop()); diff --git a/src/services/wsService.ts b/src/services/wsService.ts index 4c68dac..e19bcbf 100644 --- a/src/services/wsService.ts +++ b/src/services/wsService.ts @@ -48,6 +48,7 @@ export interface WSCallIncomingMessage { conversation_id: string; caller_id: string; call_type: string; + media_type?: string; created_at: number; lifetime?: number; ice_servers?: ICEServerConfig[]; @@ -621,7 +622,7 @@ class WebSocketService { call_id: payload.call_id, conversation_id: payload.conversation_id, caller_id: payload.caller_id, - call_type: payload.call_type, + call_type: payload.media_type || payload.call_type, created_at: payload.created_at, lifetime: payload.lifetime, ice_servers: payload.ice_servers,