webrtc

package module
v1.13.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 6, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

README

Forge WebRTC, a Go extension for WebRTC call rooms and server-side peer connections built on Pion

Forge WebRTC: WebRTC call rooms and peer connections for Go

Forge WebRTC is the WebRTC extension for Forge, the Go backend framework. It builds on Pion WebRTC v4 and the Forge Streaming extension to give you call rooms with mesh and SFU topologies, server-side peer connections with SDP offer and answer handling, ICE candidates, data channels, and STUN and TURN server configuration. It is early software. You can create rooms and negotiate real peer connections with it today, but the built-in signaling endpoint, SFU media forwarding and recording are unfinished, so read Status before you design a product around it.

Go CI Go Reference Apache 2.0

Documentation · Quick start · Features · Call rooms · Peer connections · Status · Configuration · FAQ

Quick start

You need Go 1.26 or later and a Go module:

go get github.com/xraph/forge@latest
go get github.com/xraph/forge/extensions/streaming@latest
go get github.com/xraph/forge/extensions/webrtc@latest

Save this as main.go. It creates a call room at startup and answers a browser's SDP offer over plain HTTP:

package main

import (
	"context"
	"log"
	"net/http"

	"github.com/xraph/forge"
	"github.com/xraph/forge/extensions/streaming"
	"github.com/xraph/forge/extensions/webrtc"
)

func main() {
	stream := streaming.NewExtension(streaming.WithLocalBackend())

	rtc, err := webrtc.New(stream, webrtc.DefaultConfig())
	if err != nil {
		log.Fatal(err)
	}

	app := forge.NewApp(forge.AppConfig{
		Name:        "calls",
		HTTPAddress: ":8080",
		Extensions:  []forge.Extension{stream, rtc},
	})

	err = forge.OnStarted(app, "create-call", func(ctx context.Context, _ forge.App) error {
		_, err := rtc.CreateCallRoom(ctx, "standup", streaming.RoomOptions{
			ID:   "standup",
			Name: "Daily standup",
		})

		return err
	})
	if err != nil {
		log.Fatal(err)
	}

	r := app.Router()

	// STUN and TURN servers, shaped for the browser's RTCPeerConnection.
	err = r.GET("/ice-servers", func(ctx forge.Context) error {
		cfg := rtc.GetConfig()

		servers := []map[string]any{}
		for _, s := range cfg.GetICEServers() {
			servers = append(servers, map[string]any{
				"urls":       s.URLs,
				"username":   s.Username,
				"credential": s.Credential,
			})
		}

		return ctx.JSON(http.StatusOK, servers)
	})
	if err != nil {
		log.Fatal(err)
	}

	// The browser posts its offer, the server joins the call and answers.
	err = r.POST("/calls/:room/join", func(ctx forge.Context) error {
		var offer webrtc.SessionDescription
		if err := ctx.Bind(&offer); err != nil {
			return err
		}

		peer, err := rtc.JoinCall(ctx.Context(), ctx.Param("room"), ctx.Query("user"), &webrtc.JoinOptions{})
		if err != nil {
			return err
		}

		if err := peer.SetRemoteDescription(ctx.Context(), &offer); err != nil {
			return err
		}

		answer, err := peer.CreateAnswer(ctx.Context())
		if err != nil {
			return err
		}

		return ctx.JSON(http.StatusOK, map[string]string{
			"type": string(answer.Type),
			"sdp":  answer.SDP,
		})
	})
	if err != nil {
		log.Fatal(err)
	}

	if err := app.Run(); err != nil {
		log.Fatal(err)
	}
}

Run it with go mod tidy && go run ., then curl http://localhost:8080/ice-servers shows the two Google STUN servers from DefaultConfig(). From a page served on the same origin, a browser can open a data channel to the server like this:

const pc = new RTCPeerConnection({ iceServers: await (await fetch("/ice-servers")).json() });
pc.createDataChannel("chat");
await pc.setLocalDescription(await pc.createOffer());

// There is no trickle ICE endpoint, so send the offer once gathering is done.
await new Promise((done) => {
  if (pc.iceGatheringState === "complete") return done();
  pc.onicegatheringstatechange = () => pc.iceGatheringState === "complete" && done();
});

const res = await fetch("/calls/standup/join?user=ada", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify(pc.localDescription),
});
await pc.setRemoteDescription(await res.json());

The server waits for its own ICE gathering (up to five seconds) before it returns the answer, so the answer already carries its candidates. Each user can join a room once. A second join with the same user fails until that user leaves with rtc.LeaveCall.

Features

You need Forge WebRTC gives you
Call rooms CreateCallRoom, GetCallRoom, GetCallRooms, DeleteCallRoom, each backed by a streaming room
Participants JoinCall and LeaveCall per user, GetPeers, GetParticipants, mute and unmute, video on and off
Server-side peers A Pion peer connection per participant with CreateOffer, CreateAnswer, SetRemoteDescription, AddICECandidate, tracks and stats
Events OnICECandidate, OnTrack, OnConnectionStateChange and OnDataChannel callbacks
NAT traversal STUN and TURN servers from config, returned by GetICEServers()
Topologies Mesh (the default) and SFU, picked with WithTopology or WithSFU
Signaling helpers A SignalingManager that sends webrtc.offer, webrtc.answer and webrtc.ice_candidate messages to a streaming room
Lifecycle Depends on the streaming extension, closes every room on stop, and reports unhealthy when streaming is

Call rooms

A call room pairs a streaming room with WebRTC peers. You need a room ID in the options, and the topology comes from the extension's config:

room, err := rtc.CreateCallRoom(ctx, "support-42", streaming.RoomOptions{
	ID:         "support-42",
	Name:       "Support call",
	MaxMembers: 4,
})

peer, err := room.JoinCall(ctx, "agent-7", &webrtc.JoinOptions{
	AudioEnabled: true,
	VideoEnabled: true,
	DisplayName:  "Agent 7",
})

err = room.MuteUser(ctx, "agent-7")

AudioEnabled and VideoEnabled add a local audio or video track to the server's peer for that user. rtc.JoinCall(ctx, roomID, userID, opts) and rtc.LeaveCall(ctx, roomID, userID) do the same through the extension and also update the webrtc.calls.* and webrtc.peers.active metrics. DeleteCallRoom closes every peer in the room.

Peer connections

JoinCall returns a webrtc.PeerConnection, a thin interface over a Pion *webrtc.PeerConnection created with your ICE servers:

peer.OnICECandidate(func(c *webrtc.ICECandidate) {
	// send c to the client over your signaling channel
})

peer.OnConnectionStateChange(func(state webrtc.ConnectionState) {
	log.Printf("peer %s is %s", peer.UserID(), state)
})

stats, err := peer.GetStats(ctx)

SessionDescription and ICECandidate have no JSON tags, so they marshal with Go field names (Type, SDP). Decoding is case-insensitive, which is why the quick start can bind a browser's lowercase {type, sdp} straight into a SessionDescription, but you should shape what you send back to a browser yourself, as the quick start does, because the browser expects lowercase keys.

Status

Here is what is unfinished today, so you can plan around it.

RegisterRoutes(router) mounts a WebSocket at /webrtc/signal/{roomID}, but its read loop drops every message it receives. The handler also asserts ctx.Get("user_id").(string), so put middleware on the route that sets user_id, or a connection panics. Even with a user it can only join a room that already exists, because the auto-create path never sets the room ID. Do your own signaling instead, over HTTP as in the quick start or over your own WebSocket handler.

The SFU topology creates an SFU router and SFU call rooms, but RTP packets are not forwarded between publishers and subscribers yet, so if you pick SFU expecting group calls you will get rooms where nobody hears anybody. Mesh rooms give every participant their own server-side peer. TopologyMCU is declared and rejected by CreateCallRoom.

StartScreenShare, StopScreenShare and GetQuality on a call room return webrtc.ErrNotImplemented. The extension never constructs a recorder or quality monitor, so GetRecorder() and GetQualityMonitor() return nil. NewQualityMonitor and NewRecorder exist if you want to wire them yourself.

Several config fields are stored and never read: MediaConfig (codecs, bitrates, resolution), SignalingEnabled, SignalingTimeout, RequireAuth, AllowGuests, RecordingEnabled, RecordingPath and MetricsEnabled. Pion negotiates codecs with its defaults.

Configuration

You configure the extension in code. It does not read extensions.webrtc from your config file. Start from webrtc.DefaultConfig() and pass options to webrtc.New:

rtc, err := webrtc.New(stream, webrtc.DefaultConfig(),
	webrtc.WithSTUNServers("stun:stun.example.com:3478"),
	webrtc.WithTURNServer(webrtc.TURNConfig{
		URLs:       []string{"turn:turn.example.com:3478"},
		Username:   "calls",
		Credential: os.Getenv("TURN_PASSWORD"),
	}),
)
Option Sets
WithTopology(webrtc.Topology) TopologyMesh (default) or TopologySFU
WithSFU(webrtc.SFUConfig) SFU topology plus its settings (workers, bandwidth, simulcast, quality layers)
WithSTUNServers(...string) Replaces the STUN list
WithTURNServer(webrtc.TURNConfig) Adds a TURN server with URLs and credentials
WithAudioCodecs(...string), WithVideoCodecs(...string) MediaConfig codec lists (not applied yet)
WithRecording(path) RecordingEnabled and RecordingPath (not applied yet)
WithQualityMonitoring(webrtc.QualityConfig) Quality thresholds (not applied yet)

New validates the result and returns an error when there are no STUN or TURN servers, when the topology is SFU without an SFUConfig, or when MaxVideoBitrate is below MinVideoBitrate. You also need the streaming extension registered in the same app, since WebRTC lists it as a dependency and sends its signaling through it.

Documentation

Topic Where
Overview WebRTC docs
Features and usage WebRTC features
Configuration reference WebRTC configuration
Function reference WebRTC functions
Go API pkg.go.dev
The streaming extension it builds on Forge Streaming
The WebRTC stack underneath Pion WebRTC

Examples

The basic example wires auth, streaming and WebRTC with an SFU config and REST routes for creating, joining and leaving calls. It compiles with the module, but it relies on RegisterRoutes and recording, so read Status before you copy from it.

FAQ

How do I build a WebRTC server in Go with Forge?

Register streaming.NewExtension() and webrtc.New(stream, webrtc.DefaultConfig()) in one Forge app, create a call room, and exchange SDP with the browser through JoinCall, SetRemoteDescription and CreateAnswer. The quick start does it over HTTP.

Does Forge WebRTC include a TURN server?

No. It passes the TURN servers you configure to Pion and to your clients through GetICEServers(). You run the TURN server yourself, coturn for example, or use a hosted one.

Is the SFU mode ready for group calls?

Not yet. SFU rooms and the router exist, but media is not forwarded between participants. For now each participant you add gets a peer connection to the server, and any forwarding is up to you.

Which WebRTC library does it use?

Pion WebRTC v4, a pure Go implementation, so you do not need cgo or a browser engine on the server.

Contributing

WebRTC is its own Go module inside the Forge repository. It replaces the root, streaming and auth modules with local paths. Build, vet and test it from its directory the way CI does:

cd extensions/webrtc
GOWORK=off go build ./...
GOWORK=off go vet ./...
GOWORK=off go test -short -count=1 ./...
golangci-lint run ./...

-short skips the integration tests, which nothing in CI runs. Forge's AGENTS.md has the pinned lint version and the rest of the repository conventions. Commits follow Conventional Commits, for example fix(webrtc): ....

License

Forge WebRTC is part of Forge and is available under the Apache License 2.0.

Documentation

Index

Constants

View Source
const (
	MessageTypeOffer        = "webrtc.offer"
	MessageTypeAnswer       = "webrtc.answer"
	MessageTypeICECandidate = "webrtc.ice_candidate"
)

Message types for signaling.

Variables

View Source
var (
	ErrInvalidConfig       = errors.New("webrtc: invalid configuration")
	ErrNoICEServers        = errors.New("webrtc: no ICE servers configured")
	ErrInvalidBitrateRange = errors.New("webrtc: invalid bitrate range")

	ErrPeerNotFound           = errors.New("webrtc: peer not found")
	ErrPeerAlreadyExists      = errors.New("webrtc: peer already exists")
	ErrConnectionFailed       = errors.New("webrtc: connection failed")
	ErrConnectionClosed       = errors.New("webrtc: connection closed")
	ErrInvalidConnectionState = errors.New("webrtc: invalid connection state")

	ErrSignalingFailed  = errors.New("webrtc: signaling failed")
	ErrInvalidSDP       = errors.New("webrtc: invalid SDP")
	ErrInvalidCandidate = errors.New("webrtc: invalid ICE candidate")
	ErrSignalingTimeout = errors.New("webrtc: signaling timeout")

	ErrTrackNotFound     = errors.New("webrtc: track not found")
	ErrInvalidTrackKind  = errors.New("webrtc: invalid track kind")
	ErrMediaNotSupported = errors.New("webrtc: media type not supported")
	ErrCodecNotSupported = errors.New("webrtc: codec not supported")

	ErrRoomNotFound  = errors.New("webrtc: room not found")
	ErrRoomFull      = errors.New("webrtc: room is full")
	ErrNotInRoom     = errors.New("webrtc: not in room")
	ErrAlreadyInRoom = errors.New("webrtc: already in room")

	ErrDataChannelClosed = errors.New("webrtc: data channel closed")
	ErrDataChannelFailed = errors.New("webrtc: data channel failed")

	ErrRecordingFailed  = errors.New("webrtc: recording failed")
	ErrNotRecording     = errors.New("webrtc: not recording")
	ErrAlreadyRecording = errors.New("webrtc: already recording")

	ErrSFUNotEnabled    = errors.New("webrtc: SFU not enabled")
	ErrRoutingFailed    = errors.New("webrtc: media routing failed")
	ErrReceiverNotFound = errors.New("webrtc: receiver not found")

	ErrUnauthorized = errors.New("webrtc: unauthorized")
	ErrForbidden    = errors.New("webrtc: forbidden")

	ErrNotImplemented = errors.New("webrtc: not implemented - requires additional setup")
)

Common errors.

Functions

This section is empty.

Types

type AnswerHandler

type AnswerHandler func(peerID string, answer *SessionDescription)

Callback handlers.

type CallQuality

type CallQuality struct {
	RoomID           string
	ParticipantCount int
	AverageQuality   float64 // 0-100
	PacketLoss       float64
	Jitter           time.Duration
	Latency          time.Duration
	Participants     map[string]*ConnectionQuality
}

CallQuality holds overall call quality metrics.

type CallRoom

type CallRoom interface {
	// ID returns room ID
	ID() string

	// Name returns room name
	Name() string

	// Join joins the call
	JoinCall(ctx context.Context, userID string, options *JoinOptions) (PeerConnection, error)

	// Leave leaves the call
	Leave(ctx context.Context, userID string) error

	// GetPeer returns peer connection for user
	GetPeer(userID string) (PeerConnection, error)

	// GetPeers returns all peer connections
	GetPeers() []PeerConnection

	// GetParticipants returns participant information
	GetParticipants() []Participant

	// MuteUser mutes a user's audio
	MuteUser(ctx context.Context, userID string) error

	// UnmuteUser unmutes a user's audio
	UnmuteUser(ctx context.Context, userID string) error

	// EnableVideo enables user's video
	EnableVideo(ctx context.Context, userID string) error

	// DisableVideo disables user's video
	DisableVideo(ctx context.Context, userID string) error

	// StartScreenShare starts screen sharing
	StartScreenShare(ctx context.Context, userID string, track MediaTrack) error

	// StopScreenShare stops screen sharing
	StopScreenShare(ctx context.Context, userID string) error

	// GetQuality returns call quality metrics
	GetQuality(ctx context.Context) (*CallQuality, error)

	// Close closes the call room
	Close(ctx context.Context) error
}

CallRoom represents a WebRTC call room.

func NewMeshCallRoom

func NewMeshCallRoom(
	streamingRoom streaming.Room,
	config Config,
	signaling SignalingManager,
	logger forge.Logger,
	metrics forge.Metrics,
) CallRoom

NewMeshCallRoom creates a call room with mesh topology.

func NewMeshCallRoomFromOptions

func NewMeshCallRoomFromOptions(
	opts streaming.RoomOptions,
	config Config,
	signaling SignalingManager,
	logger forge.Logger,
	metrics forge.Metrics,
) (CallRoom, error)

NewMeshCallRoomFromOptions creates a mesh call room from streaming room options.

func NewSFUCallRoomFromOptions

func NewSFUCallRoomFromOptions(
	opts streaming.RoomOptions,
	config Config,
	signaling SignalingManager,
	router SFURouter,
	logger forge.Logger,
	metrics forge.Metrics,
) (CallRoom, error)

NewSFUCallRoomFromOptions creates an SFU call room from streaming room options.

type Config

type Config struct {
	// Signaling
	SignalingEnabled bool
	SignalingTimeout time.Duration

	// Topology
	Topology Topology

	// STUN servers for NAT traversal
	STUNServers []string

	// TURN servers for relaying when P2P fails
	TURNServers []TURNConfig

	// Media configuration
	MediaConfig MediaConfig

	// SFU configuration (if topology is SFU)
	SFUConfig *SFUConfig

	// Quality settings
	QualityConfig QualityConfig

	// Recording
	RecordingEnabled bool
	RecordingPath    string

	// Metrics
	MetricsEnabled bool

	// Security
	RequireAuth bool
	AllowGuests bool
}

Config holds WebRTC extension configuration.

func DefaultConfig

func DefaultConfig() Config

DefaultConfig returns default WebRTC configuration.

func (*Config) GetICEServers

func (c *Config) GetICEServers() []ICEServer

GetICEServers returns all configured ICE servers.

func (*Config) Validate

func (c *Config) Validate() error

Validate validates the configuration.

type ConfigOption

type ConfigOption func(*Config)

ConfigOption is a functional option for Config.

func WithAudioCodecs

func WithAudioCodecs(codecs ...string) ConfigOption

WithAudioCodecs sets audio codecs.

func WithQualityMonitoring

func WithQualityMonitoring(config QualityConfig) ConfigOption

WithQualityMonitoring enables quality monitoring.

func WithRecording

func WithRecording(path string) ConfigOption

WithRecording enables recording.

func WithSFU

func WithSFU(config SFUConfig) ConfigOption

WithSFU enables SFU mode with configuration.

func WithSTUNServers

func WithSTUNServers(servers ...string) ConfigOption

WithSTUNServers sets STUN servers.

func WithTURNServer

func WithTURNServer(turn TURNConfig) ConfigOption

WithTURNServer adds a TURN server.

func WithTopology

func WithTopology(topology Topology) ConfigOption

WithTopology sets the connection topology.

func WithVideoCodecs

func WithVideoCodecs(codecs ...string) ConfigOption

WithVideoCodecs sets video codecs.

type ConnectionError

type ConnectionError struct {
	PeerID string
	State  ConnectionState
	Err    error
}

ConnectionError wraps connection errors with context.

func (*ConnectionError) Error

func (e *ConnectionError) Error() string

func (*ConnectionError) Unwrap

func (e *ConnectionError) Unwrap() error

type ConnectionQuality

type ConnectionQuality struct {
	Score       float64 // 0-100
	PacketLoss  float64 // Percentage
	Jitter      time.Duration
	Latency     time.Duration
	BitrateKbps int
	Warnings    []string
	LastUpdated time.Time
}

ConnectionQuality holds connection quality metrics.

type ConnectionState

type ConnectionState string

ConnectionState represents peer connection state.

const (
	ConnectionStateNew          ConnectionState = "new"
	ConnectionStateConnecting   ConnectionState = "connecting"
	ConnectionStateConnected    ConnectionState = "connected"
	ConnectionStateDisconnected ConnectionState = "disconnected"
	ConnectionStateFailed       ConnectionState = "failed"
	ConnectionStateClosed       ConnectionState = "closed"
)

type ConnectionStateHandler

type ConnectionStateHandler func(state ConnectionState)

Callback handlers.

type DataChannel

type DataChannel interface {
	// ID returns channel ID
	ID() string

	// Label returns channel label
	Label() string

	// State returns channel state
	State() DataChannelState

	// Send sends data
	Send(data []byte) error

	// SendText sends text
	SendText(text string) error

	// OnMessage sets message callback
	OnMessage(handler DataChannelMessageHandler)

	// OnOpen sets open callback
	OnOpen(handler DataChannelStateHandler)

	// OnClose sets close callback
	OnClose(handler DataChannelStateHandler)

	// Close closes the channel
	Close() error
}

DataChannel represents a WebRTC data channel.

func NewDataChannel

func NewDataChannel(pc *webrtc.PeerConnection, label string, ordered bool, logger forge.Logger) (DataChannel, error)

NewDataChannel creates a new data channel on a peer connection.

type DataChannelHandler

type DataChannelHandler func(channel DataChannel)

Callback handlers.

type DataChannelMessageHandler

type DataChannelMessageHandler func(data []byte)

Callback handlers.

type DataChannelState

type DataChannelState string

DataChannelState represents data channel state.

const (
	DataChannelStateConnecting DataChannelState = "connecting"
	DataChannelStateOpen       DataChannelState = "open"
	DataChannelStateClosing    DataChannelState = "closing"
	DataChannelStateClosed     DataChannelState = "closed"
)

type DataChannelStateHandler

type DataChannelStateHandler func()

Callback handlers.

type Extension

type Extension struct {
	// contains filtered or unexported fields
}

Extension is the WebRTC extension.

func New

func New(streamingExt *streaming.Extension, config Config, opts ...ConfigOption) (*Extension, error)

New creates a new WebRTC extension.

func (*Extension) CreateCallRoom

func (e *Extension) CreateCallRoom(ctx context.Context, roomID string, opts streaming.RoomOptions) (CallRoom, error)

CreateCallRoom creates a new call room.

func (*Extension) DeleteCallRoom

func (e *Extension) DeleteCallRoom(ctx context.Context, roomID string) error

DeleteCallRoom deletes a call room.

func (*Extension) Dependencies

func (e *Extension) Dependencies() []string

Dependencies returns the extensions this extension depends on.

func (*Extension) Description

func (e *Extension) Description() string

Description returns the extension description.

func (*Extension) GetCallRoom

func (e *Extension) GetCallRoom(roomID string) (CallRoom, error)

GetCallRoom retrieves a call room.

func (*Extension) GetCallRooms

func (e *Extension) GetCallRooms() []CallRoom

GetCallRooms returns all call rooms.

func (*Extension) GetConfig

func (e *Extension) GetConfig() Config

GetConfig returns the extension configuration.

func (*Extension) GetQualityMonitor

func (e *Extension) GetQualityMonitor() QualityMonitor

GetQualityMonitor returns the quality monitor.

func (*Extension) GetRecorder

func (e *Extension) GetRecorder() Recorder

GetRecorder returns the recorder.

func (*Extension) GetSFURouter

func (e *Extension) GetSFURouter() SFURouter

GetSFURouter returns the SFU router (if enabled).

func (*Extension) GetSignalingManager

func (e *Extension) GetSignalingManager() SignalingManager

GetSignalingManager returns the signaling manager.

func (*Extension) Health

func (e *Extension) Health(ctx context.Context) error

Health checks extension health.

func (*Extension) JoinCall

func (e *Extension) JoinCall(ctx context.Context, roomID, userID string, opts *JoinOptions) (PeerConnection, error)

JoinCall is a convenience method to join a call.

func (*Extension) LeaveCall

func (e *Extension) LeaveCall(ctx context.Context, roomID, userID string) error

LeaveCall is a convenience method to leave a call.

func (*Extension) Name

func (e *Extension) Name() string

Name returns the extension name.

func (*Extension) Register

func (e *Extension) Register(app forge.App) error

Register registers the extension with the app.

func (*Extension) RegisterRoutes

func (e *Extension) RegisterRoutes(router forge.Router) error

RegisterRoutes registers WebRTC HTTP routes.

func (*Extension) Start

func (e *Extension) Start(ctx context.Context) error

Start starts the extension.

func (*Extension) Stop

func (e *Extension) Stop(ctx context.Context) error

Stop stops the extension.

func (*Extension) Version

func (e *Extension) Version() string

Version returns the extension version.

type ICECandidate

type ICECandidate struct {
	Candidate        string
	SDPMid           string
	SDPMLineIndex    int
	UsernameFragment string
}

ICECandidate represents an ICE candidate.

type ICECandidateHandler

type ICECandidateHandler func(candidate *ICECandidate)

Callback handlers.

type ICECandidateReceivedHandler

type ICECandidateReceivedHandler func(peerID string, candidate *ICECandidate)

Callback handlers.

type ICEServer

type ICEServer struct {
	URLs       []string
	Username   string
	Credential string
}

ICEServer represents a STUN/TURN server.

type JoinOptions

type JoinOptions struct {
	AudioEnabled bool
	VideoEnabled bool
	DisplayName  string
	Metadata     map[string]any
}

JoinOptions holds options for joining a call.

type MediaConfig

type MediaConfig struct {
	// Audio
	AudioEnabled bool
	AudioCodecs  []string // ["opus", "pcmu", "pcma"]

	// Video
	VideoEnabled bool
	VideoCodecs  []string // ["VP8", "VP9", "H264", "AV1"]

	// Screen sharing
	ScreenShareEnabled bool

	// Data channels
	DataChannelsEnabled bool

	// Bitrate limits (kbps)
	MaxAudioBitrate int
	MaxVideoBitrate int
	MinVideoBitrate int

	// Resolution constraints
	MaxWidth  int
	MaxHeight int
	MaxFPS    int
}

MediaConfig holds media stream configuration.

type MediaError

type MediaError struct {
	TrackID string
	Kind    TrackKind
	Err     error
}

MediaError wraps media errors with context.

func (*MediaError) Error

func (e *MediaError) Error() string

func (*MediaError) Unwrap

func (e *MediaError) Unwrap() error

type MediaTrack

type MediaTrack interface {
	// ID returns the track ID
	ID() string

	// Kind returns track kind ("audio" or "video")
	Kind() TrackKind

	// Label returns track label
	Label() string

	// Enabled returns if track is enabled
	Enabled() bool

	// SetEnabled enables/disables track
	SetEnabled(enabled bool)

	// GetSettings returns track settings
	GetSettings() TrackSettings

	// GetStats returns track statistics
	GetStats(ctx context.Context) (*TrackStats, error)

	// Close stops the track
	Close() error
}

MediaTrack represents a media track (audio/video).

func NewLocalTrack

func NewLocalTrack(kind TrackKind, id, label string, logger forge.Logger) (MediaTrack, error)

NewLocalTrack creates a new local media track.

type MeshCallRoom

type MeshCallRoom struct {
	// contains filtered or unexported fields
}

MeshCallRoom implements CallRoom with mesh topology.

func (MeshCallRoom) Close

func (r MeshCallRoom) Close(ctx context.Context) error

Close closes the call room.

func (MeshCallRoom) DisableVideo

func (r MeshCallRoom) DisableVideo(ctx context.Context, userID string) error

DisableVideo disables user's video.

func (MeshCallRoom) EnableVideo

func (r MeshCallRoom) EnableVideo(ctx context.Context, userID string) error

EnableVideo enables user's video.

func (MeshCallRoom) GetParticipants

func (r MeshCallRoom) GetParticipants() []Participant

GetParticipants returns participant information.

func (MeshCallRoom) GetPeer

func (r MeshCallRoom) GetPeer(userID string) (PeerConnection, error)

GetPeer returns peer connection for user.

func (MeshCallRoom) GetPeers

func (r MeshCallRoom) GetPeers() []PeerConnection

GetPeers returns all peer connections.

func (MeshCallRoom) GetQuality

func (r MeshCallRoom) GetQuality(ctx context.Context) (*CallQuality, error)

GetQuality returns call quality metrics (stub implementation).

func (MeshCallRoom) ID

func (r MeshCallRoom) ID() string

ID returns room ID.

func (*MeshCallRoom) JoinCall

func (r *MeshCallRoom) JoinCall(ctx context.Context, userID string, opts *JoinOptions) (PeerConnection, error)

JoinCall joins the mesh call.

func (MeshCallRoom) Leave

func (r MeshCallRoom) Leave(ctx context.Context, userID string) error

Leave leaves the call.

func (MeshCallRoom) MuteUser

func (r MeshCallRoom) MuteUser(ctx context.Context, userID string) error

MuteUser mutes a user's audio.

func (MeshCallRoom) Name

func (r MeshCallRoom) Name() string

Name returns room name.

func (MeshCallRoom) StartScreenShare

func (r MeshCallRoom) StartScreenShare(ctx context.Context, userID string, track MediaTrack) error

StartScreenShare starts screen sharing (stub implementation).

func (MeshCallRoom) StopScreenShare

func (r MeshCallRoom) StopScreenShare(ctx context.Context, userID string) error

StopScreenShare stops screen sharing (stub implementation).

func (MeshCallRoom) UnmuteUser

func (r MeshCallRoom) UnmuteUser(ctx context.Context, userID string) error

UnmuteUser unmutes a user's audio.

type OfferHandler

type OfferHandler func(peerID string, offer *SessionDescription)

Callback handlers.

type Participant

type Participant struct {
	UserID        string
	DisplayName   string
	AudioEnabled  bool
	VideoEnabled  bool
	ScreenSharing bool
	Quality       *ConnectionQuality
	JoinedAt      time.Time
}

Participant represents a call participant.

type PeerConnection

type PeerConnection interface {
	// ID returns the peer connection ID
	ID() string

	// UserID returns the user ID associated with this peer
	UserID() string

	// State returns the current connection state
	State() ConnectionState

	// CreateOffer creates an SDP offer
	CreateOffer(ctx context.Context) (*SessionDescription, error)

	// CreateAnswer creates an SDP answer
	CreateAnswer(ctx context.Context) (*SessionDescription, error)

	// SetLocalDescription sets local SDP
	SetLocalDescription(ctx context.Context, sdp *SessionDescription) error

	// SetRemoteDescription sets remote SDP
	SetRemoteDescription(ctx context.Context, sdp *SessionDescription) error

	// AddICECandidate adds an ICE candidate
	AddICECandidate(ctx context.Context, candidate *ICECandidate) error

	// AddTrack adds a media track
	AddTrack(ctx context.Context, track MediaTrack) error

	// RemoveTrack removes a media track
	RemoveTrack(ctx context.Context, trackID string) error

	// GetTracks returns all media tracks
	GetTracks() []MediaTrack

	// GetStats returns connection statistics
	GetStats(ctx context.Context) (*PeerStats, error)

	// Close closes the peer connection
	Close(ctx context.Context) error

	// OnICECandidate sets ICE candidate callback
	OnICECandidate(handler ICECandidateHandler)

	// OnTrack sets track received callback
	OnTrack(handler TrackHandler)

	// OnConnectionStateChange sets state change callback
	OnConnectionStateChange(handler ConnectionStateHandler)

	// OnDataChannel sets data channel callback
	OnDataChannel(handler DataChannelHandler)
}

PeerConnection represents a WebRTC peer connection.

func NewPeerConnection

func NewPeerConnection(id, userID string, config Config, logger forge.Logger) (PeerConnection, error)

NewPeerConnection creates a new peer connection.

type PeerStats

type PeerStats struct {
	PeerID              string
	ConnectionState     ConnectionState
	LocalCandidateType  string
	RemoteCandidateType string
	BytesSent           uint64
	BytesReceived       uint64
	PacketsSent         uint64
	PacketsReceived     uint64
	PacketsLost         uint64
	Jitter              time.Duration
	RoundTripTime       time.Duration
	AvailableBitrate    int
}

PeerStats holds peer connection statistics.

type QualityChangeHandler

type QualityChangeHandler func(peerID string, quality *ConnectionQuality)

Callback handlers.

type QualityConfig

type QualityConfig struct {
	// Monitoring
	MonitorEnabled  bool
	MonitorInterval time.Duration

	// Thresholds for quality warnings
	MaxPacketLoss float64 // Percentage
	MaxJitter     time.Duration
	MinBitrate    int // kbps

	// Adaptive quality
	AdaptiveQuality      bool
	QualityCheckInterval time.Duration
}

QualityConfig holds quality monitoring configuration.

func DefaultQualityConfig

func DefaultQualityConfig() QualityConfig

DefaultQualityConfig returns default quality monitoring configuration.

type QualityLayer

type QualityLayer struct {
	RID       string // "f" (full), "h" (half), "q" (quarter)
	MaxWidth  int
	MaxHeight int
	MaxFPS    int
	Bitrate   int
}

QualityLayer represents a simulcast quality layer.

type QualityMonitor

type QualityMonitor interface {
	// Monitor starts monitoring peer connection
	Monitor(ctx context.Context, peer PeerConnection) error

	// Stop stops monitoring
	Stop(peerID string)

	// GetQuality returns current quality metrics
	GetQuality(peerID string) (*ConnectionQuality, error)

	// OnQualityChange sets quality change callback
	OnQualityChange(handler QualityChangeHandler)
}

QualityMonitor monitors connection quality.

func NewQualityMonitor

func NewQualityMonitor(peerID string, peer PeerConnection, config QualityConfig, logger forge.Logger, metrics forge.Metrics) QualityMonitor

NewQualityMonitor creates a new quality monitor.

type QualitySample

type QualitySample struct {
	Timestamp        time.Time
	PacketLoss       float64
	Jitter           time.Duration
	RTT              time.Duration
	Bitrate          uint64
	AvailableBitrate uint64
}

QualitySample represents a quality measurement at a point in time.

type RecordOptions

type RecordOptions struct {
	Format      string
	Quality     string
	AudioOnly   bool
	VideoOnly   bool
	MaxDuration time.Duration
}

RecordOptions holds recording configuration options.

type Recorder

type Recorder interface {
	// Start starts recording
	Start(ctx context.Context, roomID string, options *RecordingOptions) error

	// Stop stops recording
	Stop(ctx context.Context, roomID string) error

	// Pause pauses recording
	Pause(ctx context.Context, roomID string) error

	// Resume resumes recording
	Resume(ctx context.Context, roomID string) error

	// GetStatus returns recording status
	GetStatus(roomID string) (*RecordingStatus, error)
}

Recorder handles call recording.

func NewRecorder

func NewRecorder(roomID string, config RecorderConfig, logger forge.Logger, metrics forge.Metrics) (Recorder, error)

NewRecorder creates a new media recorder.

type RecorderConfig

type RecorderConfig struct {
	OutputDir      string
	AudioCodec     string // opus, pcm
	VideoCodec     string // vp8, h264
	EnableAudio    bool
	EnableVideo    bool
	MaxDuration    time.Duration
	FileNamePrefix string
}

RecorderConfig holds recording configuration.

func DefaultRecorderConfig

func DefaultRecorderConfig() RecorderConfig

DefaultRecorderConfig returns default recorder configuration.

type RecordingOptions

type RecordingOptions struct {
	Format      string // "webm", "mp4"
	VideoCodec  string
	AudioCodec  string
	OutputPath  string
	IncludeChat bool
}

RecordingOptions holds recording options.

type RecordingStats

type RecordingStats struct {
	Duration    time.Duration
	FileSize    uint64
	Bitrate     int
	FrameRate   int
	AudioTracks int
	VideoTracks int
	StartTime   time.Time
	EndTime     time.Time
}

RecordingStats holds recording statistics.

type RecordingStatus

type RecordingStatus struct {
	RoomID     string
	Recording  bool
	Paused     bool
	StartedAt  time.Time
	Duration   time.Duration
	FileSize   int64
	OutputPath string
}

RecordingStatus represents recording status.

type RouterStats

type RouterStats struct {
	TotalTracks        int
	ActiveReceivers    int
	TotalBytesSent     uint64
	TotalBytesReceived uint64
	AverageBitrate     int
}

RouterStats holds SFU router statistics.

type SFUCallRoom

type SFUCallRoom struct {
	// contains filtered or unexported fields
}

SFUCallRoom implements CallRoom with SFU topology.

func (SFUCallRoom) Close

func (r SFUCallRoom) Close(ctx context.Context) error

Close closes the call room.

func (SFUCallRoom) DisableVideo

func (r SFUCallRoom) DisableVideo(ctx context.Context, userID string) error

DisableVideo disables user's video.

func (SFUCallRoom) EnableVideo

func (r SFUCallRoom) EnableVideo(ctx context.Context, userID string) error

EnableVideo enables user's video.

func (SFUCallRoom) GetParticipants

func (r SFUCallRoom) GetParticipants() []Participant

GetParticipants returns participant information.

func (SFUCallRoom) GetPeer

func (r SFUCallRoom) GetPeer(userID string) (PeerConnection, error)

GetPeer returns peer connection for user.

func (SFUCallRoom) GetPeers

func (r SFUCallRoom) GetPeers() []PeerConnection

GetPeers returns all peer connections.

func (SFUCallRoom) GetQuality

func (r SFUCallRoom) GetQuality(ctx context.Context) (*CallQuality, error)

GetQuality returns call quality metrics (stub implementation).

func (SFUCallRoom) ID

func (r SFUCallRoom) ID() string

ID returns room ID.

func (*SFUCallRoom) JoinCall

func (r *SFUCallRoom) JoinCall(ctx context.Context, userID string, opts *JoinOptions) (PeerConnection, error)

JoinCall joins the SFU call.

func (SFUCallRoom) Leave

func (r SFUCallRoom) Leave(ctx context.Context, userID string) error

Leave leaves the call.

func (SFUCallRoom) MuteUser

func (r SFUCallRoom) MuteUser(ctx context.Context, userID string) error

MuteUser mutes a user's audio.

func (SFUCallRoom) Name

func (r SFUCallRoom) Name() string

Name returns room name.

func (SFUCallRoom) StartScreenShare

func (r SFUCallRoom) StartScreenShare(ctx context.Context, userID string, track MediaTrack) error

StartScreenShare starts screen sharing (stub implementation).

func (SFUCallRoom) StopScreenShare

func (r SFUCallRoom) StopScreenShare(ctx context.Context, userID string) error

StopScreenShare stops screen sharing (stub implementation).

func (SFUCallRoom) UnmuteUser

func (r SFUCallRoom) UnmuteUser(ctx context.Context, userID string) error

UnmuteUser unmutes a user's audio.

type SFUConfig

type SFUConfig struct {
	// Worker configuration
	WorkerCount int

	// Bandwidth management
	MaxBandwidthMbps int
	AdaptiveBitrate  bool
	SimulcastEnabled bool

	// Quality layers for simulcast
	QualityLayers []QualityLayer

	// Recording
	RecordingEnabled bool
	RecordingFormat  string // "webm", "mp4"
}

SFUConfig holds SFU-specific configuration.

type SFURouter

type SFURouter interface {
	// RouteTrack routes a track from sender to receivers
	RouteTrack(ctx context.Context, senderID string, track MediaTrack, receiverIDs []string) error

	// AddPublisher adds a publishing peer
	AddPublisher(ctx context.Context, userID string, peer PeerConnection) error

	// AddSubscriber adds a subscribing peer
	AddSubscriber(ctx context.Context, userID string, peer PeerConnection) error

	// RemovePublisher removes a publishing peer
	RemovePublisher(ctx context.Context, userID string) error

	// RemoveSubscriber removes a subscribing peer
	RemoveSubscriber(ctx context.Context, userID string) error

	// SubscribeToTrack subscribes a peer to a publisher's track
	SubscribeToTrack(ctx context.Context, subscriberID, publisherID, trackID string) error

	// UnsubscribeFromTrack unsubscribes a peer from a track
	UnsubscribeFromTrack(ctx context.Context, subscriberID, trackID string) error

	// AddReceiver adds a receiver for a track
	AddReceiver(ctx context.Context, trackID, receiverID string) error

	// RemoveReceiver removes a receiver
	RemoveReceiver(ctx context.Context, trackID, receiverID string) error

	// GetReceivers returns all receivers for a track
	GetReceivers(trackID string) []string

	// SetQuality sets quality layer for receiver
	SetQuality(ctx context.Context, trackID, receiverID, quality string) error

	// GetStats returns routing statistics
	GetStats(ctx context.Context) (*RouterStats, error)

	// GetAvailableTracks returns all available tracks
	GetAvailableTracks() []TrackInfo
}

SFURouter handles media routing in SFU mode.

func NewSFURouter

func NewSFURouter(roomID string, logger forge.Logger, metrics forge.Metrics) SFURouter

NewSFURouter creates a new SFU router.

type SFUStats

type SFUStats struct {
	TotalTracks        int
	ActiveReceivers    int
	TotalBytesSent     uint64
	TotalBytesReceived uint64
	AverageBitrate     int
	Timestamp          time.Time
}

SFUStats holds SFU router statistics.

type SessionDescription

type SessionDescription struct {
	Type SessionDescriptionType
	SDP  string
}

SessionDescription represents SDP.

type SessionDescriptionType

type SessionDescriptionType string

SessionDescriptionType is the type of SDP.

const (
	SessionDescriptionTypeOffer  SessionDescriptionType = "offer"
	SessionDescriptionTypeAnswer SessionDescriptionType = "answer"
)

type SignalingError

type SignalingError struct {
	Op     string // Operation that failed
	PeerID string
	RoomID string
	Err    error
}

SignalingError wraps signaling errors with context.

func (*SignalingError) Error

func (e *SignalingError) Error() string

func (*SignalingError) Unwrap

func (e *SignalingError) Unwrap() error

type SignalingManager

type SignalingManager interface {
	// SendOffer sends SDP offer to peer
	SendOffer(ctx context.Context, roomID, peerID string, offer *SessionDescription) error

	// SendAnswer sends SDP answer to peer
	SendAnswer(ctx context.Context, roomID, peerID string, answer *SessionDescription) error

	// SendICECandidate sends ICE candidate to peer
	SendICECandidate(ctx context.Context, roomID, peerID string, candidate *ICECandidate) error

	// OnOffer sets offer received callback
	OnOffer(handler OfferHandler)

	// OnAnswer sets answer received callback
	OnAnswer(handler AnswerHandler)

	// OnICECandidate sets ICE candidate received callback
	OnICECandidate(handler ICECandidateReceivedHandler)

	// Start begins listening for signaling messages
	Start(ctx context.Context) error

	// Stop stops listening
	Stop(ctx context.Context) error
}

SignalingManager handles WebRTC signaling via streaming.

func NewSignalingManager

func NewSignalingManager(streamingExt *streaming.Extension, logger forge.Logger) SignalingManager

NewSignalingManager creates a new signaling manager.

type SimulcastLayer

type SimulcastLayer struct {
	RID     string
	Active  bool
	Width   int
	Height  int
	Bitrate int
}

SimulcastLayer represents a simulcast layer.

type TURNConfig

type TURNConfig struct {
	URLs       []string
	Username   string
	Credential string

	// TLS configuration
	TLSEnabled  bool
	TLSCertFile string
	TLSKeyFile  string
}

TURNConfig holds TURN server configuration.

type Topology

type Topology string

Topology represents the WebRTC connection topology.

const (
	// TopologyMesh - Peer-to-peer mesh (each peer connects to all others).
	TopologyMesh Topology = "mesh"

	// TopologySFU - Selective Forwarding Unit (server routes media).
	TopologySFU Topology = "sfu"

	// TopologyMCU - Multipoint Control Unit (server mixes media).
	TopologyMCU Topology = "mcu"
)

type TrackHandler

type TrackHandler func(track MediaTrack, receiver *TrackReceiver)

Callback handlers.

type TrackInfo

type TrackInfo struct {
	TrackID     string
	PublisherID string
	Kind        TrackKind
}

TrackInfo describes a published track in SFU stats.

type TrackKind

type TrackKind string

TrackKind represents track type.

const (
	TrackKindAudio TrackKind = "audio"
	TrackKindVideo TrackKind = "video"
)

type TrackReceiver

type TrackReceiver struct {
	TrackID  string
	PeerID   string
	Kind     TrackKind
	Settings TrackSettings
}

TrackReceiver receives a track.

type TrackSettings

type TrackSettings struct {
	Width      int
	Height     int
	FrameRate  int
	Bitrate    int
	SampleRate int
	Channels   int
}

TrackSettings represents track settings.

type TrackStats

type TrackStats struct {
	TrackID         string
	Kind            TrackKind
	BytesSent       uint64
	BytesReceived   uint64
	PacketsSent     uint64
	PacketsReceived uint64
	PacketsLost     uint64
	Bitrate         int
	FrameRate       int
	Jitter          time.Duration
}

TrackStats holds media track statistics.

Directories

Path Synopsis
examples
basic command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL