diff --git a/components/room/StreamGrid.vue b/components/room/StreamGrid.vue index f4ff6f8..4d949fb 100644 --- a/components/room/StreamGrid.vue +++ b/components/room/StreamGrid.vue @@ -83,7 +83,7 @@ const gridClass = computed(() => { :viewer-names="viewerNamesByStream[card.streamId] || []" :volume="volumeMap[card.streamId] ?? 1" :muted="mutedMap[card.streamId] ?? false" - :focused="focusStreamId === card.streamId" + :focused="layoutMode === 'focus' ? index === 0 : focusStreamId === card.streamId" @update:volume="emit('update:volume', card.streamId, $event)" @update:muted="emit('update:muted', card.streamId, $event)" @stop="emit('stop', card.streamId)" diff --git a/components/room/VideoPlayerCard.vue b/components/room/VideoPlayerCard.vue index 65c2497..b00fbf4 100644 --- a/components/room/VideoPlayerCard.vue +++ b/components/room/VideoPlayerCard.vue @@ -20,13 +20,41 @@ const emit = defineEmits<{ const videoRef = ref(null) const { formatted } = useRoomTimer(() => props.startedAt) +const dvrEnabled = computed(() => Boolean(props.focused && props.mediaStream)) + +const { + delayLabel, + isLive, + canSeekBack, + canSeekForward, + bufferMs, + recording, + error: dvrError, + seekBack, + seekForward, + goLive, + SEEK_STEP_MS, +} = useStreamDvr({ + enabled: dvrEnabled, + stream: () => props.mediaStream, + videoRef, +}) + +const bufferReadySec = computed(() => Math.floor(bufferMs.value / 1000)) + +function attachLiveStream(stream: MediaStream | null) { + const el = videoRef.value + if (!el) return + el.srcObject = stream + if (stream) el.play().catch(() => {}) +} + watch( - () => props.mediaStream, - (stream) => { - const el = videoRef.value - if (!el) return - el.srcObject = stream - el.play().catch(() => {}) + () => [props.mediaStream, props.focused] as const, + ([stream, focused]) => { + // Focused card: DVR composable owns the