Skip to content

Real-Time Communication


WebRTC Mesh Topology

For live video/audio calls, TalentSync uses a Mesh Topology for 1-on-1 interviews.

  • Every peer connects directly to every other peer
  • Low latency, no central media server
  • Suitable for 1-on-1 sessions (scales poorly beyond ~4-5 participants — acceptable for interview use case)

Signaling Flow

  1. Join: Client emits JOIN_ROOM via Socket.io
  2. Discovery: Server returns list of existing peers in the room
  3. Offer: Joining client creates a WebRTC Offer → Server → Target peer
  4. Answer: Target peer creates Answer → Server → Initiator
  5. ICE Candidates: Exchanged asynchronously to traverse NATs
  6. Connected: Direct P2P media stream established

Socket.io Events (Live Room)

Signaling events (existing)

EventDirectionPayload
JOIN_ROOMClient → Server{ roomId, userInfo }
OFFERClient → Server → Client{ sdp, targetId }
ANSWERClient → Server → Client{ sdp, targetId }
ICE_CANDIDATEClient → Server → Client{ candidate, targetId }
USER_JOINEDServer → Client{ userId, userInfo }
USER_LEFTServer → Client{ userId }

Question push (Phase 1B)

EventDirectionPayload
push_questionClient (interviewer) → Server → Client (candidate){ questionText: string }

The push_question event is emitted from the interviewer's "My Questions" panel. The server broadcasts it to all other participants in the room. The candidate's screen renders the question text in a visible card.

Security

The push_question event only carries questionText. The interviewerHints and expectedAnswerGuide fields from InterviewQuestion are never sent to or rendered on the candidate's browser.


Collaborative Code Editor

Uses Yjs for Conflict-free Replicated Data Types (CRDTs).

  • Binding: y-codemirror.next binds the Yjs document to the CodeMirror editor
  • Provider: Custom WebRTC provider (or y-webrtc) syncs document updates directly between peers via WebRTC Data Channels
  • Awareness: Cursor positions and selections synced via the awareness protocol
  • Persistence: Yjs state can be persisted server-side for session replay (future feature)

Whiteboard

Integration with Excalidraw.

  • State is serialized and broadcast to all peers in the room
  • Real-time sync ensures a shared canvas experience
  • Whiteboard visibility controlled by StageTypeConfig.toolsConfig.whiteboard — only rendered when true

Webcam Proctoring (Phase 3)

Used in technical_dsa stages when dsaConfig.proctoringEnabled: true.

  • Webcam stream captured but not transmitted to peers (no live video call for async stages)
  • Periodic snapshots taken and stored (implementation TBD — Phase 3)
  • Visible indicator shown to candidate so they know proctoring is active

DSA Session: Code Execution (Phase 3)

The DSA session sends code to a sandboxed execution service:

POST /v1/dsa/:token/run     — run against visible test cases (non-final)
POST /v1/dsa/:token/submit  — run against all test cases (final)

The execution service (Judge0 self-hosted or equivalent) returns:

typescript
{
  testCaseId: string;
  passed: boolean;
  executionTimeMs: number;
  memoryUsedKB: number;
  stdout?: string;
  stderr?: string;
}

The aggregate score (% test cases passed) is stored on Interview.stageData.dsaSubmissions[].score — recruiter-only. Candidates see per-test pass/fail but not the overall %.