From 12a41da24178fb19a627b6cc12714a7db71a4c18 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 18 May 2026 00:26:14 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20feat(im):=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E6=91=84=E5=83=8F=E5=A4=B4=E5=85=B3=E9=97=AD=E5=90=8E=E7=94=BB?= =?UTF-8?q?=E9=9D=A2=E5=8D=A1=E5=9C=A8=E6=9C=80=E5=90=8E=E4=B8=80=E5=B8=A7?= =?UTF-8?q?=EF=BC=88pickStream=20=E7=9F=AD=E8=B7=AF=20mute=20=E7=8A=B6?= =?UTF-8?q?=E6=80=81=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/im/home/composables/useLiveKitRoom.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/views/im/home/composables/useLiveKitRoom.ts b/src/views/im/home/composables/useLiveKitRoom.ts index a4c1eb560..769e2f73b 100644 --- a/src/views/im/home/composables/useLiveKitRoom.ts +++ b/src/views/im/home/composables/useLiveKitRoom.ts @@ -98,6 +98,9 @@ export function useLiveKitRoom() { }) .on(RoomEvent.TrackSubscribed, () => syncRemotes(r)) .on(RoomEvent.TrackUnsubscribed, () => syncRemotes(r)) + // mute / unmute 让 pickStream 的 isMuted 短路重算,video 元素能解绑 srcObject 而不是卡最后一帧 + .on(RoomEvent.TrackMuted, () => syncRemotes(r)) + .on(RoomEvent.TrackUnmuted, () => syncRemotes(r)) .on(RoomEvent.ConnectionQualityChanged, (quality) => { connectionQuality.value = quality }) @@ -241,12 +244,16 @@ export function useLiveKitRoom() { /** * 取参与者指定来源的轨道并打包为 MediaStream; * 参与者走 unknown 是因为响应式系统会丢失 livekit-client 的类签名,函数内手动 cast 回参与者类型; - * 命中缓存返回同一 MediaStream 引用,下游 watch / srcObject 无需重挂 + * 命中缓存返回同一 MediaStream 引用,下游 watch / srcObject 无需重挂; + * 轨道被 mute(本端关摄像头 / 远端关摄像头)时返回 null,让 video 元素解绑 srcObject 而不是卡在最后一帧 */ function pickStream(participant: unknown, source: Track.Source): MediaStream | null { const p = participant as Participant const pub = p.getTrackPublication(source) - const track = pub?.track?.mediaStreamTrack + if (!pub || pub.isMuted) { + return null + } + const track = pub.track?.mediaStreamTrack if (!track) { return null }