LiveKit Ingress
repository·main·Indexed 41 days ago
https://github.com/livekit/ingressA service that enables media ingestion from non-WebRTC sources, such as RTMP and WHIP (WebRTC-HTTP Ingestion Protocol), into LiveKit rooms by automatically transcoding them for WebRTC compatibility. It supports push and pull models, simulcast, and configurable video layers.
What's inside LiveKit Ingress
- LiveKit Ingress (Universal Ingress) is a service designed to bridge non-WebRTC media workflows into a LiveKit room. It allows you to ingest media from equipment or workflows that do not natively support WebRTC, making it a versatile tool for integrating existing media infrastructure with LiveKit's WebRTC-based delivery.
Supported Ingress Protocols
mainLiveKit Ingress supports both push and pull models for media ingestion. The currently supported protocols are:
- RTMP
- WHIP (WebRTC-HTTP Ingestion Protocol)
How the Ingress push workflow works
mainTo push media to LiveKit Ingress, follow these steps:
- Create an Ingress: Call the
CreateIngressAPI on the LiveKit server. - Get the URL: The API returns a unique URL for the session.
- Configure Encoder: Copy the returned URL into your streaming software (e.g., OBS) or workflow.
- Start Stream: Once the stream starts, the Ingress service receives the data.
- Publish to Room: The Ingress service joins the specified LiveKit room and publishes the transcoded media as a participant.
- Create an Ingress: Call the
Supported Output and Transcoding
mainThe Ingress service automatically transcodes source media to ensure full compatibility with WebRTC.
Key output features include:
- Simulcast Support: The service can publish multiple video layers to optimize delivery for different participants.
- Layer Configuration: The parameters for different video layers can be defined at the time the ingress is created.
Run Ingress service natively
mainThe Ingress service is built in Go and requires GStreamer.
Prerequisites
- Go >= 1.18
- GStreamer libraries:
gstreamer,gst-plugins-base,gst-plugins-good,gst-plugins-bad,gst-plugins-ugly,gst-libav.
Build and Run
- Build:
mage build - Run:
ingress --config=config.yaml
MacOS Note: If using Homebrew for GStreamer, you must set the library path:
export DYLD_LIBRARY_PATH=/opt/homebrew/libTroubleshooting: If you encounter GStreamer plugin errors (e.g.,
Failed to load libsoup library), clear the registry:rm -rf ~/.cache/gstreamer-1.0/# Build mage build # Run export DYLD_LIBRARY_PATH=/opt/homebrew/lib ingress --config=config.yamlHow RTMPHandler processes media
mainThe
RTMPHandleris the internal component responsible for handling individual RTMP connections. It implements thertmp.DefaultHandlerinterface and performs the following:- Publishing: When a client calls
publish, the handler triggers theonPublishcallback. This is where you define the stream's parameters and initialize statistics gathering. - FLV Encoding: The handler automatically initializes an FLV encoder (
flv.Encoder) upon receiving the first data frames. It uses aPrerollBufferto ensure that if a relay is attached later, the initial metadata (like video/audio init tags) can be replayed. - Media Handling:
OnAudioandOnVideoreceive raw payloads, decode them into FLV tags, and encode them into the FLV stream.- It tracks keyframes to ensure the stream starts correctly.
- It updates media statistics via the registered
trackStats.
- Lifecycle: When the connection closes,
OnCloseis called, which closes themediaBufferand triggers theonClosecallback.
- Publishing: When a client calls
Configure the Ingress service via YAML
mainThe Ingress service is configured using a YAML file. You can provide this file via the
INGRESS_CONFIG_FILEenvironment variable or pass the raw YAML content viaINGRESS_CONFIG_BODY.Required Fields
api_key: LiveKit server API key (or useLIVEKIT_API_KEYenv).api_secret: LiveKit server API secret (or useLIVEKIT_API_SECRETenv).ws_url: LiveKit server websocket URL (or useLIVEKIT_WS_URLenv).redis: Configuration for the Redis instance used for communication and state.address: Redis address.username: Redis username.password: Redis password.db: Redis database index.
Common Optional Fields
health_port: HTTP port for health checks.prometheus_port: Port for Prometheus metrics.log_level:debug,info,warn, orerror(default:info).rtmp_port: Port for RTMP connections (default:1935).whip_port: Port for WHIP calls (default:8080).http_relay_port: Port for data relay between main and handler processes (default:9090).rtc_config: RTC/ICE settings for WHIP.enable_udp_url_pull: Enables pulling fromudp://URLs (default:false).psrpc.compression.quality: Gzip level 1-9 (0 to disable, default: 0).
# Example minimal config api_key: livekit server api key api_secret: livekit server api secret ws_url: livekit server websocket url redis: address: redis address username: redis username password: redis password db: 0How the Ingress service handles shutdown
mainThe Ingress server responds to OS signals to manage the lifecycle of active media streams:
- SIGTERM / SIGQUIT: The server attempts a graceful shutdown by finishing all active ingresses before shutting down.
- SIGINT (Ctrl+C): The server performs an immediate shutdown, stopping all ingresses, the relay, the RTMP server, and the WHIP server.
This ensures that media streams are either allowed to complete or are terminated cleanly to prevent resource leaks.
Configure LiveKit Server for Ingress
mainFor the LiveKit server to successfully create Ingress sessions, you must add an
ingresssection to yourlivekit-serverconfiguration. This defines the base URLs that the server will use to construct the final publishing endpoints (by appending a stream key to these prefixes).Required keys:
rtmp_base_url: The RTMP URL prefix pointing to your Ingress external IP or load balancer.whip_base_url: The WHIP URL prefix pointing to your Ingress external IP or load balancer.
ingress: rtmp_base_url: rtmp://my.domain.com/x whip_base_url: http://my.domain.com/wRun the RTMP relay service
mainThe
rtmprelayservice is a CLI entrypoint used to start an RTMP server and a relay service. It listens for RTMP connections and relays them through the LiveKit Ingress system.By default, the service initializes with:
RTMPPort: 1935HTTPRelayPort: 9090
The service handles graceful shutdowns when receiving a
SIGINTsignal.// The service initializes an RTMP server and a relay service // using the following default configuration: conf := &config.Config{ RTMPPort: 1935, HTTPRelayPort: 9090, } rtmpServer := rtmp.NewRTMPServer() relay := service.NewRelay(rtmpServer) // Start the components rtmpServer.Start(conf, nil) relay.Start(conf)Run the LiveKit Ingress server
mainThe
ingressCLI is used to import streamed media to LiveKit. You can start the main service by providing a configuration file or a raw YAML configuration body.Configuration Options
--config: Path to a LiveKit Ingress YAML configuration file. Can be set via theINGRESS_CONFIG_FILEenvironment variable.--config-body: A raw YAML configuration string. Can be set via theINGRESS_CONFIG_BODYenvironment variable.
When running the service, it initializes components like the Redis message bus, RTMP server (if
RTMPPortis configured), and WHIP server (ifWHIPPortis configured).# Using a config file ./ingress --config /path/to/config.yaml # Using a config body ./ingress --config-body "redis: { address: 'localhost:6379' }"Initialize and start a WHIPServer
mainTo use the WHIP (WebRTC-HTTP Ingestion Protocol) server, you must first create it using
NewWHIPServerwith apsrpc.MessageBus. Then, callStartwith your configuration, anonPublishcallback, and optional health handlers. TheonPublishcallback is critical as it defines how new streams are provisioned.The
onPublishcallback signature: It takesstreamKeyandresourceId(strings) and returns:*params.Params: The parameters for the new stream.readyfunction: Called when the session is ready. It acceptsmimeTypesand anerror, and returns a*stats.LocalMediaStatsGathererand a cleanup function.endedfunction: A cleanup function called when the session ends.error: Any error encountered during provisioning.
// Initialize the server server, err := whip.NewWHIPServer(bus) if err != nil { return err } // Define the onPublish callback onPublish := func(streamKey, resourceId string) (*params.Params, func(mimeTypes map[types.StreamKind]string, err error) *stats.LocalMediaStatsGatherer, func(error), error) { // Logic to provision the stream return params, readyFunc, endedFunc, nil } // Start the server err = server.Start(conf, onPublish, healthHandlers)