Cách hoạt động
Hai peer vào cùng một phòng thông qua một signaling server WebSocket nhỏ. Server chỉ chuyển tiếp các message điều khiển: SDP offer và answer, ICE candidate và key E2EE. Audio, video và chat đi thẳng giữa hai peer qua WebRTC. STUN server công khai của Google giúp mỗi peer biết địa chỉ public của mình.
Đó là chế độ mặc định: mỗi phòng chứa hai người. Cuộc gọi nhóm là một chế độ tùy chọn, trong đó mọi người kết nối tới một SFU server nhỏ.
Các thành phần
| Thành phần | Công nghệ | Bắt đầu đọc từ |
|---|---|---|
| Signaling server | Node.js, ws | server.js |
| SFU server (không bắt buộc) | Go, Pion | sfu-server/ |
| Web | Vue 3, TypeScript, Vite | useCall.ts |
| Android | Kotlin, Jetpack Compose, webrtc-sdk | PeerConnectionClient.kt |
| iOS | Swift, SwiftUI, webrtc-sdk | PeerConnectionClient.swift |
| macOS | Swift, SwiftUI + AppKit, dùng lại engine của iOS | WebRTCDemoMacApp.swift |
| Windows | C#, WinUI 3, libwebrtc qua một C shim | CallViewModel.cs |
- UI
- Vue 3, Tailwind CSS, shadcn-vue
- WebRTC
- RTCPeerConnection có sẵn của trình duyệt
- Socket signaling
- WebSocket
- Camera
- getUserMedia()
- Chia sẻ màn hình
- getDisplayMedia()
- Đổi nguồn video
- RTCRtpSender.replaceTrack()
- E2EE
- Insertable Streams hoặc RTCRtpScriptTransform, chạy trong worker
- Background và sticker
- MediaPipe ImageSegmenter + FaceLandmarker, canvas 2D
- Picture-in-picture
- Document Picture-in-Picture API, video PiP fallback
Quy tắc mọi client đều tuân theo
Chính vài quyết định này giúp năm app độc lập gọi được cho nhau. Mỗi quy tắc có trang riêng.
- Peer đã ở trong phòng là bên tạo offer. Peer vào sau sẽ answer. Không bao giờ có chuyện hai bên cùng offer một lúc. Signaling
- Channel chat được tạo trước offer đầu tiên, nên mở chat không bao giờ phải renegotiate. Chat
- Chuyển giữa camera, màn hình và file không bao giờ renegotiate. Video sender giữ nguyên, chỉ thay thứ cấp frame cho nó. Chuyển nguồn video
- Trạng thái camera được gửi thành message. Track bị disable vẫn gửi frame đen, nên mỗi bên báo cho bên kia bằng
media state, trước hoặc sau khi track thay đổi 300 ms. Trạng thái camera và micro - E2EE dùng một định dạng frame và một bộ tùy chọn key duy nhất, và VP8 được ưu tiên khi bật E2EE. Mã hóa đầu cuối
- Không tự kết nối lại. Socket signaling đóng thì cuộc gọi kết thúc. Signaling
Cấu trúc đầy đủ của repository, kèm từng file và công dụng của nó, có trong ARCHITECTURE.md.
