From e047c2d54ea0b942ffe7a2c7a8f5830b4fea745185e59a629d6ac7f90d7217b0 Mon Sep 17 00:00:00 2001 From: AidarKC Date: Tue, 11 Aug 2026 12:43:17 +0400 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=B4=D0=B3=D0=BE=D1=82=D0=BE?= =?UTF-8?q?=D0=B2=D0=B8=D1=82=D1=8C=20=D0=BE=D0=B1=D1=8B=D1=87=D0=BD=D1=8B?= =?UTF-8?q?=D0=B9=20=D0=B7=D0=B2=D0=BE=D0=BD=D0=BE=D0=BA=20=D0=BA=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=B7=D0=B4=D0=BD=D0=B5=D0=BC=D1=83=20=D0=B0=D0=BF=D0=B3?= =?UTF-8?q?=D1=80=D0=B5=D0=B9=D0=B4=D1=83=20=D0=B2=20=D0=B2=D0=B8=D0=B4?= =?UTF-8?q?=D0=B5=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- VERSION.properties | 2 +- shine-UI/js/services/call-service.js | 59 ++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/VERSION.properties b/VERSION.properties index f01ad52a..5bdfa0ed 100644 --- a/VERSION.properties +++ b/VERSION.properties @@ -1,2 +1,2 @@ -client.version=1.5.27 +client.version=1.5.28 server.version=1.4.10 diff --git a/shine-UI/js/services/call-service.js b/shine-UI/js/services/call-service.js index 4670a646..033e7cd3 100644 --- a/shine-UI/js/services/call-service.js +++ b/shine-UI/js/services/call-service.js @@ -57,6 +57,7 @@ const CALL_MODE_AUDIO = 'audio'; const CALL_MODE_VIDEO = 'video'; const CALL_MODE_INSTANT_VIDEO = 'instant_video'; const VIDEO_TRANSPORT_NONE = 'none'; +const VIDEO_TRANSPORT_RESERVED = 'reserved'; const VIDEO_TRANSPORT_SLOT = 'slot'; function nowMs() { @@ -116,7 +117,7 @@ function normalizeCallMode(mode) { } function getVideoTransportModeForCallMode(mode) { - return normalizeCallMode(mode) === CALL_MODE_AUDIO ? VIDEO_TRANSPORT_NONE : VIDEO_TRANSPORT_SLOT; + return normalizeCallMode(mode) === CALL_MODE_AUDIO ? VIDEO_TRANSPORT_RESERVED : VIDEO_TRANSPORT_SLOT; } function isInstantVideoMode(mode) { @@ -1756,6 +1757,8 @@ async function ensurePeerConnection(call) { } else { ensureReservedVideoTransceiver(call); } + } else if (call.videoTransportMode === VIDEO_TRANSPORT_RESERVED) { + ensureReservedVideoTransceiver(call); } } catch (e) { setStatus(call, `Нет доступа к микрофону: ${e?.message || 'unknown'}`, 'failed'); @@ -1857,7 +1860,7 @@ async function onAccept(call) { try { await notifyPeerSessionsAboutConnectStart(call); const pc = await ensurePeerConnection(call); - if (call.videoTransportMode === VIDEO_TRANSPORT_SLOT) { + if (call.videoTransportMode === VIDEO_TRANSPORT_SLOT || call.videoTransportMode === VIDEO_TRANSPORT_RESERVED) { ensureReservedVideoTransceiver(call); } if (call.autoEnableCameraOnConnect && call.cameraEnabled) { @@ -2176,6 +2179,7 @@ async function applyCameraState(call) { if (!call?.pc) return false; const pc = call.pc; const hadSlotBefore = call.videoTransportMode === VIDEO_TRANSPORT_SLOT; + const hadReservedBefore = call.videoTransportMode === VIDEO_TRANSPORT_RESERVED; let videoTransceiver = call.videoTransceiver || null; if (!videoTransceiver) { const transceivers = pc.getTransceivers?.() || []; @@ -2208,6 +2212,31 @@ async function applyCameraState(call) { await applyVideoSenderEncodingProfile(sender, 'camera'); } videoTrack.enabled = true; + } else if (hadReservedBefore) { + const videoTrack = await ensureCameraTrack(call); + if (!videoTransceiver) { + videoTransceiver = ensureReservedVideoTransceiver(call); + call.videoTransceiver = videoTransceiver; + call.videoSender = videoTransceiver?.sender || call.videoSender || null; + } + try { + if (videoTransceiver && videoTransceiver.direction !== 'sendrecv') { + videoTransceiver.direction = 'sendrecv'; + } + } catch {} + if (videoTransceiver?.sender) { + await videoTransceiver.sender.replaceTrack(videoTrack); + call.videoSender = videoTransceiver.sender; + bindVideoSenderStream(call, videoTransceiver.sender); + await applyVideoSenderEncodingProfile(videoTransceiver.sender, 'camera'); + } else { + const sender = pc.addTrack(videoTrack, call.localStream); + call.videoSender = sender; + bindVideoSenderStream(call, sender); + await applyVideoSenderEncodingProfile(sender, 'camera'); + } + call.videoTransportMode = VIDEO_TRANSPORT_SLOT; + videoTrack.enabled = true; } else { call.videoTransportMode = VIDEO_TRANSPORT_SLOT; const videoTrack = await ensureCameraTrack(call); @@ -2254,14 +2283,17 @@ async function applyCameraState(call) { videoTransceiver.direction = 'sendrecv'; } } catch {} - if (call.videoTransportMode === VIDEO_TRANSPORT_SLOT && blackTrack) { + if (hadReservedBefore && videoTransceiver?.sender) { + try { await videoTransceiver.sender.replaceTrack(null); } catch {} + call.videoSender = videoTransceiver.sender; + } else if (call.videoTransportMode === VIDEO_TRANSPORT_SLOT && blackTrack) { await ensureVideoSenderSlot(call, { sourceTrack: blackTrack, profile: 'placeholder' }); } } await disableCameraTrack(call); } notifyCallState(); - if (!hadSlotBefore && call.videoTransportMode === VIDEO_TRANSPORT_SLOT && !refreshVideoSlotReady(call)) { + if (!hadSlotBefore && !hadReservedBefore && call.videoTransportMode === VIDEO_TRANSPORT_SLOT && !refreshVideoSlotReady(call)) { await renegotiateCall(call, 'upgrade_to_video_slot'); } return true; @@ -2784,9 +2816,18 @@ export async function handleIncomingCallSignal(evt) { } await pc.setRemoteDescription(incomingOffer); if (hasVideoSectionInSdp(incomingOffer?.sdp || '')) { - call.videoTransportMode = VIDEO_TRANSPORT_SLOT; - ensureReservedVideoTransceiver(call); - if (!call.videoSender) { + if (call.videoTransportMode === VIDEO_TRANSPORT_SLOT) { + ensureReservedVideoTransceiver(call); + if (!call.videoSender) { + await ensureVideoSenderSlot(call, { sourceTrack: ensureBlackVideoTrack(call), profile: 'placeholder' }); + } + } else if (call.videoTransportMode === VIDEO_TRANSPORT_RESERVED) { + ensureReservedVideoTransceiver(call); + } else { + call.videoTransportMode = VIDEO_TRANSPORT_RESERVED; + ensureReservedVideoTransceiver(call); + } + if (call.videoTransportMode === VIDEO_TRANSPORT_SLOT && !call.videoSender) { await ensureVideoSenderSlot(call, { sourceTrack: ensureBlackVideoTrack(call), profile: 'placeholder' }); } if (call.autoEnableCameraOnConnect && call.cameraEnabled) { @@ -2833,7 +2874,9 @@ export async function handleIncomingCallSignal(evt) { } await pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(data))); if (hasVideoSectionInSdp(pc.remoteDescription?.sdp || '')) { - call.videoTransportMode = VIDEO_TRANSPORT_SLOT; + if (!call.videoTransportMode || call.videoTransportMode === VIDEO_TRANSPORT_NONE) { + call.videoTransportMode = VIDEO_TRANSPORT_RESERVED; + } ensureReservedVideoTransceiver(call); } syncRemoteReceiverVideoTracks(call);