# ksfu **Repository Path**: mkwchecking/ksfu ## Basic Information - **Project Name**: ksfu - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-01-11 - **Last Updated**: 2026-01-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # KSFU - Kurento Compatible SFU Server A WebRTC Selective Forwarding Unit (SFU) server built with Go and Pion, fully compatible with Kurento signaling protocol. ## Features - **Kurento Protocol Compatible**: Full Kurento JSON-RPC 2.0 protocol support - **MediaPipeline Management**: Create and manage media pipelines - **WebRtcEndpoint Support**: Full WebRTC endpoint implementation with Pion - **SFU Stream Forwarding**: Single-port stream forwarding with track management - **Session Management**: Automatic session and connection lifecycle management - **ICE/STUN/TURN**: Support for ICE, STUN, and TURN servers - **Event System**: Subscribe and unsubscribe to media element events - **Advanced Configuration**: Comprehensive configuration via environment variables ## Architecture ``` ksfu/ ├── cmd/ │ └── server/ # Main application entry point ├── internal/ │ ├── media/ # MediaPipeline and MediaElement management │ │ ├── pipeline.go # MediaPipeline and MediaElement core │ │ ├── webrtc_endpoint.go # WebRtcEndpoint with SFU forwarding │ │ └── config.go # WebRTC and media configuration │ ├── signaling/ # Kurento signaling protocol │ │ └── kurento.go # JSON-RPC 2.0 protocol handler │ └── server/ # Core service logic │ └── server.go # Service orchestration ├── pkg/ │ ├── buffer/ # Buffer factory for WebRTC │ │ └── buffer.go # Buffer implementation │ └── config/ # Configuration management │ └── config.go # HTTP and basic config └── bin/ └── ksfu # Compiled executable ``` ## SFU Stream Forwarding The server implements true SFU (Selective Forwarding Unit) functionality with single-port stream forwarding: ### Key Features 1. **Track Management**: Automatically manages incoming and outgoing tracks 2. **Subscriber Management**: Efficiently handles multiple subscribers per publisher 3. **Dynamic Subscription**: New tracks are automatically forwarded to existing subscribers 4. **Resource Cleanup**: Automatic cleanup of tracks and subscriptions when endpoints disconnect 5. **Single-Port Mode**: Optional single UDP port for all ICE connections ### How It Works ``` Publisher (WebRtcEndpoint) ↓ (publishes tracks) ↓ Track Manager (TrackInfo) ↓ (forwards to all subscribers) ↓ Subscriber 1 (WebRtcEndpoint) Subscriber 2 (WebRtcEndpoint) Subscriber 3 (WebRtcEndpoint) ... ``` ## Configuration All configuration is done via environment variables. See `.env.example` for a complete example. ### HTTP Configuration | Environment Variable | Default | Description | |-------------------|---------|-------------| | `HTTP_PORT` | 8080 | HTTP port to listen on | | `HTTPS_PORT` | 8443 | HTTPS port to listen on | | `ENABLE_METRICS` | false | Enable metrics collection | ### WebRTC Configuration | Environment Variable | Default | Description | |-------------------|---------|-------------| | `ICE_SINGLE_PORT` | 0 | Single UDP port for all ICE connections (0 = disabled) | | `ICE_PORT_RANGE` | - | ICE port range (format: start,end) | | `STUN_SERVERS` | stun:stun.l.google.com:19302 | STUN servers (comma separated) | | `TURN_SERVERS` | - | TURN servers (comma separated) | | `TURN_USERNAME` | - | TURN server username | | `TURN_PASSWORD` | - | TURN server password | ### ICE Candidate Configuration | Environment Variable | Default | Description | |-------------------|---------|-------------| | `ICE_LITE` | false | Enable ICE Lite mode | | `ICE_NAT_1TO1_IPS` | - | NAT 1:1 IP addresses (comma separated) | | `ICE_CANDIDATE_TYPE` | host | Candidate type (host/srflx) | ### SDP Semantics | Environment Variable | Default | Description | |-------------------|---------|-------------| | `SDP_SEMANTICS` | unified-plan | SDP semantics (unified-plan/unified-plan-with-fallback/plan-b) | ### mDNS Support | Environment Variable | Default | Description | |-------------------|---------|-------------| | `MDNS_ENABLED` | false | Enable mDNS support | ### ICE Timeouts | Environment Variable | Default | Description | |-------------------|---------|-------------| | `ICE_DISCONNECTED_TIMEOUT` | 15 | ICE disconnected timeout (seconds) | | `ICE_FAILED_TIMEOUT` | 15 | ICE failed timeout (seconds) | | `ICE_KEEPALIVE_INTERVAL` | 5 | ICE keepalive interval (seconds) | ### TURN Server Configuration | Environment Variable | Default | Description | |-------------------|---------|-------------| | `TURN_ENABLED` | false | Enable TURN server | | `TURN_REALM` | kurento.org | TURN realm | | `TURN_ADDRESS` | - | TURN server address | | `TURN_CERT` | - | TURN server certificate file | | `TURN_KEY` | - | TURN server key file | | `TURN_PORT_RANGE` | - | TURN port range (format: start,end) | | `TURN_CREDENTIALS` | - | TURN credentials file | | `TURN_SECRET` | - | TURN secret key | ### Router Configuration | Environment Variable | Default | Description | |-------------------|---------|-------------| | `ROUTER_WITH_STATS` | false | Enable router statistics | | `ROUTER_MAX_BANDWIDTH` | 0 | Maximum bandwidth (bps) | | `ROUTER_MAX_PACKET_TRACK` | 0 | Maximum packet track count | | `ROUTER_AUDIO_LEVEL_INTERVAL` | 0 | Audio level calculation interval (ms) | | `ROUTER_AUDIO_LEVEL_THRESHOLD` | 0 | Audio level threshold (0-127) | | `ROUTER_AUDIO_LEVEL_FILTER` | 0 | Audio level filter | ### Simulcast Configuration | Environment Variable | Default | Description | |-------------------|---------|-------------| | `SIMULCAST_BEST_QUALITY_FIRST` | false | Prioritize best quality first | | `SIMULCAST_ENABLE_TEMPORAL_LAYER` | false | Enable temporal layer | ## Installation ### Prerequisites - Go 1.21 or higher - STUN/TURN servers (optional but recommended) - Docker (optional, for containerized deployment) ### Build ```bash go mod download go build -o bin/ksfu cmd/server/main.go ``` ### Docker #### Build Docker Image ```bash docker build -t ksfu . ``` #### Run with Docker ```bash # Basic usage docker run -p 8080:8080 -p 8443:8443 ksfu # With custom port docker run -p 9000:8080 -p 9443:8443 -e HTTP_PORT=9000 ksfu # With single-port ICE docker run -p 8080:8080 -p 50000:50000/udp -e ICE_SINGLE_PORT=50000 ksfu # With STUN servers docker run -p 8080:8080 -e STUN_SERVERS=stun:stun.l.google.com:19302 ksfu # With TURN servers docker run -p 8080:8080 \ -e TURN_SERVERS=turn:your-turn-server:3478 \ -e TURN_USERNAME=user \ -e TURN_PASSWORD=pass \ ksfu # Full configuration docker run -p 8080:8080 -p 8443:8443 \ -e HTTP_PORT=8080 \ -e HTTPS_PORT=8443 \ -e STUN_SERVERS=stun:stun.l.google.com:19302 \ -e ICE_SINGLE_PORT=50000 \ ksfu ``` #### Docker Compose Create `docker-compose.yml`: ```yaml version: '3.8' services: ksfu: build: . ports: - "8080:8080" - "8443:8443" - "50000:50000/udp" environment: - HTTP_PORT=8080 - HTTPS_PORT=8443 - STUN_SERVERS=stun:stun.l.google.com:19302 - ICE_SINGLE_PORT=50000 - ICE_LITE=false - SDP_SEMANTICS=unified-plan - MDNS_ENABLED=false - ICE_DISCONNECTED_TIMEOUT=15 - ICE_FAILED_TIMEOUT=15 - ICE_KEEPALIVE_INTERVAL=5 - TURN_ENABLED=false - ROUTER_WITH_STATS=false - ROUTER_MAX_BANDWIDTH=0 - ROUTER_MAX_PACKET_TRACK=0 - ROUTER_AUDIO_LEVEL_INTERVAL=0 - ROUTER_AUDIO_LEVEL_THRESHOLD=0 - ROUTER_AUDIO_LEVEL_FILTER=0 - SIMULCAST_BEST_QUALITY_FIRST=false - SIMULCAST_ENABLE_TEMPORAL_LAYER=false ``` Run with Docker Compose: ```bash docker-compose up -d ``` ## Usage ### Basic Usage ```bash # Copy example environment file cp .env.example .env # Edit configuration vim .env # Run server ./bin/ksfu ``` ### With Custom Port ```bash HTTP_PORT=9000 ./bin/ksfu ``` ### With Single-Port ICE ```bash ICE_SINGLE_PORT=50000 ./bin/ksfu ``` ### With STUN/TURN Servers ```bash STUN_SERVERS=stun:stun.l.google.com:19302,stun:stun1.l.google.com:19302 \ TURN_SERVERS=turn:your-turn-server:3478 \ TURN_USERNAME=user \ TURN_PASSWORD=pass \ ./bin/ksfu ``` ## API Endpoints ### WebSocket Signaling Connect to `ws://localhost:8080/ws` for Kurento-compatible signaling. ### Health Check ```bash curl http://localhost:8080/health ``` ## Kurento Protocol Support ### Supported Methods The server implements the following Kurento JSON-RPC 2.0 methods: #### 1. Ping Keep-alive mechanism to maintain connection. ```json { "id": 1, "method": "ping", "params": {"interval": 240000}, "jsonrpc": "2.0" } ``` #### 2. Create Create media objects (MediaPipeline, WebRtcEndpoint). **Create MediaPipeline:** ```json { "id": 1, "method": "create", "params": { "type": "MediaPipeline", "constructorParams": {} }, "jsonrpc": "2.0" } ``` **Create WebRtcEndpoint:** ```json { "id": 2, "method": "create", "params": { "type": "WebRtcEndpoint", "constructorParams": { "mediaPipeline": "pipeline_id_here" } }, "jsonrpc": "2.0" } ``` #### 3. Invoke Call methods on media objects. **Process Offer:** ```json { "id": 3, "method": "invoke", "params": { "object": "pipeline_id/endpoint_id", "operation": "processOffer", "operationParams": { "offer": "v=0\r\no=- 123456..." } }, "jsonrpc": "2.0" } ``` **Add ICE Candidate:** ```json { "id": 4, "method": "invoke", "params": { "object": "pipeline_id/endpoint_id", "operation": "addIceCandidate", "operationParams": { "candidate": "candidate:...", "sdpMid": "0", "sdpMLineIndex": 0 } }, "jsonrpc": "2.0" } ``` **Connect Endpoints (SFU Forwarding):** ```json { "id": 5, "method": "invoke", "params": { "object": "publisher_endpoint_id", "operation": "connect", "operationParams": { "sink": "subscriber_endpoint_id" } }, "jsonrpc": "2.0" } ``` #### 4. Subscribe Subscribe to events from media elements. ```json { "id": 6, "method": "subscribe", "params": { "object": "endpoint_id", "type": "OnIceCandidate" }, "jsonrpc": "2.0" } ``` #### 5. Unsubscribe Cancel event subscriptions. ```json { "id": 7, "method": "unsubscribe", "params": { "subscription": "subscription_id" }, "jsonrpc": "2.0" } ``` #### 6. Release Release media objects and free resources. ```json { "id": 8, "method": "release", "params": { "object": "endpoint_id" }, "jsonrpc": "2.0" } ``` ### Server Events The server can push events to clients: **OnIceCandidate Event:** ```json { "jsonrpc": "2.0", "method": "onEvent", "params": { "type": "OnIceCandidate", "data": { "endpoint": "endpoint_id", "candidate": "candidate:..." } } } ``` ## Typical SFU Usage Flow 1. **Establish WebSocket Connection**: Connect to `/ws` endpoint 2. **Create MediaPipeline**: Create a media pipeline for the session 3. **Create Publisher WebRtcEndpoint**: Create endpoint for the publisher 4. **Create Subscriber WebRtcEndpoints**: Create endpoints for each subscriber 5. **Process Offer/Answer**: Exchange SDP offers and answers with all endpoints 6. **Connect Endpoints**: Connect subscriber endpoints to publisher endpoint for stream forwarding 7. **Handle ICE Candidates**: Exchange ICE candidates for NAT traversal 8. **Automatic Forwarding**: Publisher tracks are automatically forwarded to all subscribers 9. **Release Resources**: Clean up endpoints and pipeline when done ## SFU Example Scenario ### Multi-Participant Conference ```javascript // 1. Create pipeline const pipeline = await create('MediaPipeline'); // 2. Create publisher endpoint const publisher = await create('WebRtcEndpoint', { mediaPipeline: pipeline.value }); // 3. Create subscriber endpoints const subscriber1 = await create('WebRtcEndpoint', { mediaPipeline: pipeline.value }); const subscriber2 = await create('WebRtcEndpoint', { mediaPipeline: pipeline.value }); // 4. Process publisher offer const publisherAnswer = await invoke(publisher.value, 'processOffer', { offer: publisherSDP }); // 5. Process subscriber offers const subscriber1Answer = await invoke(subscriber1.value, 'processOffer', { offer: subscriber1SDP }); const subscriber2Answer = await invoke(subscriber2.value, 'processOffer', { offer: subscriber2SDP }); // 6. Connect subscribers to publisher (SFU forwarding) await invoke(publisher.value, 'connect', { sink: subscriber1.value }); await invoke(publisher.value, 'connect', { sink: subscriber2.value }); // Now publisher's tracks are automatically forwarded to both subscribers! ``` ## Development ### Project Structure - `internal/media/`: MediaPipeline and MediaElement management with SFU forwarding - `internal/signaling/`: Kurento JSON-RPC 2.0 protocol implementation - `internal/server/`: Core service orchestration - `pkg/buffer/`: Buffer factory for WebRTC - `pkg/config/`: Configuration management ### Dependencies - `github.com/pion/webrtc/v4`: WebRTC implementation - `github.com/pion/ice/v2`: ICE implementation - `github.com/gorilla/websocket`: WebSocket support - `github.com/google/uuid`: UUID generation - `github.com/go-logr/logr`: Logging interface ### Makefile Commands ```bash make build # Build project make run # Run as server make clean # Clean build artifacts make deps # Download dependencies make dev # Run in development mode ``` ## Performance Considerations - **Single-Port Forwarding**: All streams are forwarded through a single PeerConnection per endpoint - **Efficient Routing**: Tracks are directly forwarded without transcoding - **Scalable**: Supports multiple subscribers per publisher - **Resource Management**: Automatic cleanup prevents memory leaks - **Configurable**: Extensive configuration options for different deployment scenarios ## License MIT License