Overview
The YAML configuration file defines how the LiveKit Portal for ROS bridges your ROS graph to and from a LiveKit room. It sets which topics and services to expose and how to stream video. LiveKit Portal for ROS loads the file when the node starts. Specify the file path with the node's config_path ROS parameter. Changes to the file are applied when the node restarts.
The configuration file is optional. Without one, the LiveKit Portal for ROS forwards all topics bidirectionally, which is convenient for development but not recommended for production: declare only the routes your app needs.
The file declares routes, along with the connection options for the room. There are two kinds of routes:
- Topic routes bridge ROS topics to LiveKit DataTracks. The
directioncontrols the flow:outpublishes a local topic into the room,insubscribes to a remote topic and republishes it on the local graph, andbidirectionaldoes both. - Service routes expose a local ROS service that forwards each call to a specific LiveKit participant. Service routes are always
out.
Declare only the topics and services you need, and only in the direction you need them: every route adds traffic to the LiveKit connection, so a narrow configuration keeps bandwidth and latency down. For outbound topics, max_rate_hz throttles how often samples are forwarded, and encoding selects how each message is serialized on the DataTrack.
Example configuration
This example configures three topic routes and one service route:
- Send and receive all topics in the
/test/namespace. - Send out a rate-limited
/imu/data_rawtopic as JSON Schema. - Receive
/remote/cmd_velcommands. - Expose a service for
robot-ato navigate to a pose.
ros_portal:version: "0.0.1"topic_polling_period_ms: 500topics:- topic: "/test/.*"direction: "bidirectional"- topic: "/imu/data_raw"direction: "out"max_rate_hz: 10encoding: "jsonschema"- topic: "/remote/cmd_vel"direction: "in"services:- service: "/navigate_to_pose"direction: "out"participant: "robot-a"msg_type: "nav2_msgs/srv/NavigateToPose"
Credentials
LiveKit credentials are not read from the configuration file. Set LIVEKIT_URL and LIVEKIT_TOKEN in the node environment. The LiveKit room name comes from the active room connection (via the token grant), not from this configuration.
Top-level fields
Every field below is nested under a single top-level ros_portal key, as shown in the example above.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
version | string | yes | Must be "0.0.1". | |
topic_polling_period_ms | integer | 500 | ROS graph polling interval in milliseconds. Must be positive. | |
ros_threads | integer | 0 | ROS executor thread count. The default 0 uses the number of available CPU cores. | |
room_options | map | {} | LiveKit room connection options. | |
services | list | [] | Service route declarations. | |
topics | list | [] | Topic route declarations. | |
video_sources | list | [] | Capture sources published as LiveKit video tracks. |
Topics
Each entry in the topics list declares a topic route with the following fields:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
topic | string | yes | ROS topic pattern. Must be non-empty. Treated as an ECMAScript regex for the DataTrack path; matched as a literal name for max_rate_hz, latched, and encoding. | |
direction | string | yes | Valid values are: in, out, or bidirectional. | |
preserve_id | boolean | false | Inbound topics only. Prefix the republished ROS topic with the publishing participant's identity. | |
max_rate_hz | number | Outbound topics only. Cap (in Hz) on the rate samples are forwarded to LiveKit; samples arriving within one period of the last forwarded one are dropped (like topic_tools throttle messages). Literal topic names only. | ||
latched | boolean | false | Treat the topic as latched (see below). Literal topic names only. | |
encoding | string | ros2msg | Selects how data is encoded on the DataTrack. Outbound topics only. Literal topic names only. Valid values are: ros2msg, ros2idl, or jsonschema. | |
video_options | map | Optional video publish settings. |
Topic patterns are ECMAScript regular expressions matched against the full topic name. Only forwarding the streams you actually need (and only in the required direction) keeps unnecessary traffic off the LiveKit connection.
Services
Each entry in the services list declares a service route with the following fields:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
service | string | yes | ROS service name. Must be non-empty. | |
direction | string | yes | Valid value: out | |
participant | string | yes | LiveKit participant identity. Must be non-empty. | |
msg_type | string | yes | ROS service type, such as std_srvs/srv/SetBool. Must be non-empty. |
Setting direction: "out" creates a local ROS service server that forwards calls to the configured LiveKit participant using msg_type. Services support only out: a service route always exposes a local ROS server that proxies calls to a remote participant, so unlike topics, there's no inbound or bidirectional direction.
Video sources
Video sources require v1.0.0-rc3 or later of LiveKit Portal for ROS.
Each entry in video_sources publishes one independent LiveKit video track. The source can use GStreamer, a camera device, or a built-in test pattern.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
track_name | string | yes | Non-empty LiveKit video track name. | |
source | map | yes | Source configuration. Its type is gstreamer, device, or pattern. | |
simulcast | boolean | false | Enables simulcast for device and pattern sources. GStreamer sources ignore this field. | |
publish_options | map | Optional max_bitrate_bps and max_framerate limits. Both values must be positive integers. |
GStreamer source
A GStreamer source publishes pre-encoded video. The pipeline must end in appsink name=lk_appsink or leave one encoded video source pad unlinked.
The optional rate_control block connects WebRTC bitrate targets to a writable encoder property. Set unit to bps or kbps to match that property.
ros_portal:version: "0.0.1"video_sources:- track_name: "demo_camera"source:type: "gstreamer"# videotestsrc pattern=smpte is the classic SMPTE 100% color bars with# the television-snow block in the bottom right — an instantly# recognizable reference for checking colors, scaling and tearing.# clockoverlay stamps wall-clock date + time on every frame so uplink# latency and frozen/stale video are obvious at a glance.pipeline: >-videotestsrc is-live=true do-timestamp=true pattern=smpte! video/x-raw,width=640,height=480,framerate=30/1! clockoverlay time-format="%Y-%m-%d %H:%M:%S" halignment=centervalignment=top shaded-background=true font-desc="Sans Bold 20"! videoconvert ! video/x-raw,format=I420! vp8enc name=lk_encoder deadline=1 cpu-used=8 keyframe-max-dist=30lag-in-frames=0 target-bitrate=2500000! video/x-vp8! appsink name=lk_appsink sync=false max-buffers=2 drop=truecodec: "vp8"resolution:width: 640height: 480rate_control:element: "lk_encoder"property: "target-bitrate"unit: "bps"publish_options:max_bitrate_bps: 2500000max_framerate: 30
Valid codecs are h264, h265, vp8, vp9, and av1. The LiveKit Portal for ROS infers the codec and resolution from negotiated caps when you omit them.
Device source
A device source uses AVFoundation on macOS or V4L2 on Linux. List available devices before you select an id or index:
ros2 run ros_portal capture_devices
Prefer id because device indexes can change. The id and index fields are mutually exclusive. On Linux, the identifier is the /dev/videoN node number.
ros_portal:version: "0.0.1"video_sources:- track_name: "front_camera"source:type: "device"device:id: "0x8020000005ac8514"format:strategy: "closest"resolution:width: 1280height: 720framerate_fps: 30publish_options:max_framerate: 30
Omit device.format to use the device default. The strategy value can be exact, closest, highest_framerate, or highest_resolution.
For exact and closest, specify both resolution and framerate_fps.
highest_framerate accepts an optional resolution constraint. highest_resolution accepts an optional frame-rate constraint.
Test pattern source
Use a pattern source to replace camera hardware during debugging or demonstrations. It's built in and works on any platform, requiring no capture backend such as GStreamer, V4L2, or AVFoundation. Reuse the track_name of the source you're replacing so subscribers don't need any configuration changes.
ros_portal:version: "0.0.1"video_sources:- track_name: "front_camera"source:type: "pattern"pattern:pattern: "logo"resolution:width: 1280height: 720framerate_fps: 30
Choose gradient for an animated color gradient or logo for a bouncing LiveKit logo. The defaults are gradient, 640x480, and 30 fps.
Additional resources
The following resource provides more information about configuration.
LiveKit Portal for ROS configuration guide
The complete configuration reference in the LiveKit Portal for ROS repository, covering every field, room options, and full example configs.