add SFU#248
Conversation
The v5 API changes RelayAddressGenerator to accept config structs instead of (network, port) params, adds AllocateListener, and changes AuthHandler to (*RequestAttributes) returning (userID, key, ok). Eliminates the duplicate pion/turn/v4+v5 and pion/transport/v3+v4 pairs that would otherwise coexist once pion/webrtc/v4 is added.
Signals to the browser whether to use SFU or P2P signalling for this session. Old clients that ignore unknown JSON fields are unaffected.
Introduce SFUHost struct (per-sharer server-side WebRTC state) and a SFUHosts map on Room keyed by sharer user ID, enabling multiple simultaneous sharers in SFU mode. Add ViewerPC to RoomSession for the server-side sendonly PC used when forwarding a sharer's stream to a viewer. Add helper methods sfuHostBySession, closeSFUHost, and closeAllSFUHosts for lifecycle management. Extend Rooms with a webrtcAPI field initialised once at startup when SCREEGO_SFU_MODE=true, shared across all peer connections so codec negotiation state is consistent. Call closeAllSFUHosts when a room is torn down.
Add sfu.go with createHostPC/createViewerPC for the server-side WebRTC PeerConnections. createHostPC opens a recvonly PC to receive the sharer's stream; createViewerPC opens a sendonly PC per viewer and forwards the shared track. PLI requests from viewers are forwarded to the sharer via the main event loop to stay single-threaded. Add event_sfu_internal.go with the four internal event types that pion goroutines post into rooms.Incoming: SFUHostTrack — track arrived from sharer; starts RTP forward SFUIceCandidate — routes server ICE candidates to browser peers SFUSendPLI — requests a keyframe from the sharer SFUConnectionFailed — tears down a host or viewer PC on failure
Wire SCREEGO_SFU_MODE into all eight signaling events:
share — creates SFUHost entry + pending list, calls createHostPC
stopshare — closes the SFUHost and its viewer sessions
join — late-joiner gets a ViewerPC if track is ready, otherwise
added to the sharer's pending list
hostoffer — ignored in SFU mode (server originates all offers)
hostice — routes sharer browser ICE to the server host PC
clientanswer — routes sharer answer to host PC; viewer answer to ViewerPC
clientice — routes viewer browser ICE to the server ViewerPC
disconnected — closes SFUHost when a streaming user disconnects
P2P behaviour (SFUMode=false) is unchanged in every handler.
The server sets mode: "sfu" on hostsession messages when SCREEGO_SFU_MODE=true so the browser can switch to upload-only peer connection logic. Absent means p2p (existing behaviour).
When the server sends mode: "sfu" on a hostsession event, create an upload-only RTCPeerConnection instead of calling hostSession(). Track the session ID in hostSID so the hostoffer handler can identify the sharer's PC and set the remote description (server's recvonly offer) rather than routing through the viewer path. Codec preference is applied after setRemoteDescription so the correct transceiver direction is known. Viewer hostoffer handling is unchanged. stopShare cleans up only the upload PC in SFU mode; in P2P mode it closes all host PCs as before.
Standalone HTML page (no build step) that joins a room as a viewer, logs every WebSocket message and ICE event, and displays the forwarded stream. Useful for isolating server-side SFU issues from the main UI. Placed in ui/public/ so vite copies it to build/ unchanged. Registered in serve.go so it is reachable at /test-client.html in production too.
/test-client.html is now only registered when SCREEGO_TEST_CLIENT=true. Defaults to false so the debug endpoint is off in production deployments.
Eye button in the control bar hides/shows the thumbnail strip. When hidden with no stream selected nothing renders, saving GPU. X button overlaid top-right deselects the current main stream. An explicitDeselect ref prevents the auto-select effect from immediately re-selecting after an explicit deselect.
Clients can subscribe to individual sharers on demand and unsubscribe to release the connection and stop receiving RTP. - Subscribe event: creates viewer PC (SFU) or P2P session on demand; defers to Pending if the SFU track has not arrived yet - Unsubscribe event: closes viewer PC (SFU) or notifies sharer (P2P); removes from Pending if not yet connected - sessionByPeers helper added to Room for session lookup by (host, client)
Eye off: unsubscribes all non-selected thumbnail streams and closes their PCs. Eye on: re-subscribes any streaming users not yet present in clientStreams. A useEffect auto-unsubscribes streams that arrive while the strip is hidden. X button also unsubscribes the main stream when the strip is off. message.ts: add Subscribe and Unsubscribe outgoing message types. useRoom.ts: add subscribeStream/unsubscribeStream; track session→peer_id in clientPeerID ref so unsubscribe sends the correct sharer user ID.
Previously auth_mode=all only blocked room creation for unauthenticated users; joining (and thus watching) was open to anyone. Now guests are rejected on join with the same error as on create.
|
Sorry for the delay, and thanks for the PR. Given you've state this is vibecoded and you are unsure if it works correctly. I won't be reviewing this PR, as the feedback I'm writing is likely just passed to the agent, and then I could do this myself as the feedback loop is shorter this way. |
|
Do you consider to provide something similar? Overall it works pretty good I have just some trouble in flakey networks with reconnecting clients. One thing I would drop is the closing of the room when the owner leaves. It becomes pretty complicated when reconnecting to the room. Will he still be owner? What happens when he re-enters when all others have been kicked? Will that be the same or a different room. And another thing that I found strange is how the permissions are formulated. I get it that it is for the access and that all. Is like you need auth for everything. But someone what to access and roles are mixed up. And I wonder how this should could be used in a company setup. Overall the SFU setup on our own servers was more stable than what I have experienced on the test server. We had sessions over several days without breaking. |
|
I'm not sure yet, I'll probably wait for more community feedback if this feature is really necessary. I try to keep screego simple and only include features that the majority of users need. |
Hi,
I had the need for SFU and vibe coded a bit. It seems to be working fine, but that might be an illusion. Maybe we can use this as a base to come forward with a PR that can eventually land on master.