diff --git a/app/components/Participant.tsx b/app/components/Participant.tsx
index 3a1db3e8..5a18793e 100644
--- a/app/components/Participant.tsx
+++ b/app/components/Participant.tsx
@@ -1,7 +1,7 @@
import { VisuallyHidden } from '@radix-ui/react-visually-hidden'
import { forwardRef, useEffect, useMemo } from 'react'
import { Flipped } from 'react-flip-toolkit'
-import { of } from 'rxjs'
+import { combineLatest, fromEvent, map, of, switchMap } from 'rxjs'
import { useSubscribedState } from '~/hooks/rxjsHooks'
import { useDeadPulledTrackMonitor } from '~/hooks/useDeadPulledTrackMonitor'
import { useRoomContext } from '~/hooks/useRoomContext'
@@ -26,18 +26,40 @@ import { OptionalLink } from './OptionalLink'
import { Tooltip } from './Tooltip'
import { VideoSrcObject } from './VideoSrcObject'
+function useMid(track?: MediaStreamTrack) {
+ const { peer } = useRoomContext()
+ const transceivers$ = useMemo(
+ () =>
+ combineLatest([
+ peer.peerConnection$,
+ peer.peerConnection$.pipe(
+ switchMap((peerConnection) => fromEvent(peerConnection, 'track'))
+ ),
+ ]).pipe(map(([pc]) => pc.getTransceivers())),
+ [peer.peerConnection$]
+ )
+ const transceivers = useSubscribedState(transceivers$, [])
+ if (!track) return null
+ return transceivers.find(
+ (t) => t.sender.track === track || t.receiver.track === track
+ )?.mid
+}
+
+interface Props {
+ flipId: string
+ isScreenShare?: boolean
+ showDebugInfo?: boolean
+ user: User
+ audioTrack?: MediaStreamTrack
+ videoTrack?: MediaStreamTrack
+ isSelf?: boolean
+ pinnedId?: string
+ setPinnedId: (id?: string) => void
+}
+
export const Participant = forwardRef<
HTMLDivElement,
- JSX.IntrinsicElements['div'] & {
- flipId: string
- isScreenShare?: boolean
- user: User
- audioTrack?: MediaStreamTrack
- videoTrack?: MediaStreamTrack
- isSelf?: boolean
- pinnedId?: string
- setPinnedId: (id?: string) => void
- }
+ JSX.IntrinsicElements['div'] & Props
>(
(
{
@@ -49,11 +71,13 @@ export const Participant = forwardRef<
audioTrack,
pinnedId,
setPinnedId,
+ showDebugInfo,
},
ref
) => {
const { data } = useUserMetadata(user.name)
const { traceLink, peer, dataSaverMode } = useRoomContext()
+ const peerConnection = useSubscribedState(peer.peerConnection$)
useDeadPulledTrackMonitor(
user.tracks.video,
@@ -90,6 +114,9 @@ export const Participant = forwardRef<
const packetLoss = useSubscribedState(packetLoss$, 0)
+ const audioMid = useMid(audioTrack)
+ const videoMid = useMid(videoTrack)
+
return (
{data.displayName}
+ {showDebugInfo && peerConnection && (
+
+ {' '}
+ {[
+ audioMid && `audio mid: ${audioMid}`,
+ videoMid && `video mid: ${videoMid}`,
+ ]
+ .filter(Boolean)
+ .join(' ')}
+
+ )}
)}
diff --git a/app/components/PullAudioTracks.tsx b/app/components/PullAudioTracks.tsx
index 9db4fbc5..fe75ec0a 100644
--- a/app/components/PullAudioTracks.tsx
+++ b/app/components/PullAudioTracks.tsx
@@ -22,12 +22,17 @@ export const PullAudioTracks: FC = ({
- setAudioTrackMap({ ...audioTrackMap, [id]: track })
+ setAudioTrackMap((previous) => ({
+ ...previous,
+ [id]: track,
+ }))
}
onTrackRemoved={(id) => {
- const update = { ...audioTrackMap }
- delete update[id]
- setAudioTrackMap(update)
+ setAudioTrackMap((previous) => {
+ const update = { ...previous }
+ delete update[id]
+ return update
+ })
}}
/>
{children}
diff --git a/app/routes/_room.$roomName.room.tsx b/app/routes/_room.$roomName.room.tsx
index 651c958d..4af2ae77 100644
--- a/app/routes/_room.$roomName.room.tsx
+++ b/app/routes/_room.$roomName.room.tsx
@@ -44,19 +44,8 @@ export const loader = async ({ request, context }: LoaderFunctionArgs) => {
})
}
-function useGridDebugControls(
- {
- initialCount,
- defaultEnabled,
- }: {
- initialCount: number
- defaultEnabled: boolean
- } = { initialCount: 0, defaultEnabled: false }
-) {
- const [enabled, setEnabled] = useState(defaultEnabled)
- const [fakeUsers, setFakeUsers] = useState(
- Array.from({ length: initialCount }).map(() => nanoid())
- )
+function useDebugEnabled() {
+ const [enabled, setEnabled] = useState(false)
useEffect(() => {
const handler = (e: KeyboardEvent) => {
@@ -72,6 +61,20 @@ function useGridDebugControls(
}
}, [enabled])
+ return enabled
+}
+
+function useGridDebugControls({
+ initialCount,
+ enabled,
+}: {
+ initialCount: number
+ enabled: boolean
+}) {
+ const [fakeUsers, setFakeUsers] = useState(
+ Array.from({ length: initialCount }).map(() => nanoid())
+ )
+
const GridDebugControls = useCallback(
() =>
enabled ? (
@@ -128,8 +131,9 @@ function JoinedRoom({ bugReportsEnabled }: { bugReportsEnabled: boolean }) {
room: { otherUsers, websocket, identity },
} = useRoomContext()
+ const debugEnabled = useDebugEnabled()
const { GridDebugControls, fakeUsers } = useGridDebugControls({
- defaultEnabled: false,
+ enabled: debugEnabled,
initialCount: 0,
})
@@ -224,6 +228,7 @@ function JoinedRoom({ bugReportsEnabled }: { bugReportsEnabled: boolean }) {
audioTrack={userMedia.audioStreamTrack}
pinnedId={pinnedId}
setPinnedId={setPinnedId}
+ showDebugInfo={debugEnabled}
/>
)}
@@ -238,6 +243,7 @@ function JoinedRoom({ bugReportsEnabled }: { bugReportsEnabled: boolean }) {
videoTrack={userMedia.screenShareVideoTrack}
pinnedId={pinnedId}
setPinnedId={setPinnedId}
+ showDebugInfo={debugEnabled}
/>
)}
{actorsOnStage.map((user) => (
@@ -254,6 +260,7 @@ function JoinedRoom({ bugReportsEnabled }: { bugReportsEnabled: boolean }) {
audioTrack={audioTrack}
pinnedId={pinnedId}
setPinnedId={setPinnedId}
+ showDebugInfo={debugEnabled}
>
)}
@@ -267,6 +274,7 @@ function JoinedRoom({ bugReportsEnabled }: { bugReportsEnabled: boolean }) {
isScreenShare
pinnedId={pinnedId}
setPinnedId={setPinnedId}
+ showDebugInfo={debugEnabled}
/>
)}
@@ -293,6 +301,7 @@ function JoinedRoom({ bugReportsEnabled }: { bugReportsEnabled: boolean }) {
flipId={uid.toString()}
pinnedId={pinnedId}
setPinnedId={setPinnedId}
+ showDebugInfo={debugEnabled}
>
)}