Skip to main content

LiveKit Portal for ROS configuration

Configure the LiveKit Portal for ROS topics, services, and video sources.

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 direction controls the flow: out publishes a local topic into the room, in subscribes to a remote topic and republishes it on the local graph, and bidirectional does 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_raw topic as JSON Schema.
  • Receive /remote/cmd_vel commands.
  • Expose a service for robot-a to navigate to a pose.
ros_portal:
version: "0.0.1"
topic_polling_period_ms: 500
topics:
- topic: "/test/.*"
direction: "bidirectional"
- topic: "/imu/data_raw"
direction: "out"
max_rate_hz: 10
encoding: "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.

FieldTypeRequiredDefaultDescription
versionstringyesMust be "0.0.1".
topic_polling_period_msinteger500ROS graph polling interval in milliseconds. Must be positive.
ros_threadsinteger0ROS executor thread count. The default 0 uses the number of available CPU cores.
room_optionsmap{}LiveKit room connection options.
serviceslist[]Service route declarations.
topicslist[]Topic route declarations.
video_sourceslist[]Capture sources published as LiveKit video tracks.

Topics

Each entry in the topics list declares a topic route with the following fields:

FieldTypeRequiredDefaultDescription
topicstringyesROS 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.
directionstringyesValid values are: in, out, or bidirectional.
preserve_idbooleanfalseInbound topics only. Prefix the republished ROS topic with the publishing participant's identity.
max_rate_hznumberOutbound 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.
latchedbooleanfalseTreat the topic as latched (see below). Literal topic names only.
encodingstringros2msgSelects how data is encoded on the DataTrack. Outbound topics only. Literal topic names only. Valid values are: ros2msg, ros2idl, or jsonschema.
video_optionsmapOptional 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:

FieldTypeRequiredDefaultDescription
servicestringyesROS service name. Must be non-empty.
directionstringyesValid value: out
participantstringyesLiveKit participant identity. Must be non-empty.
msg_typestringyesROS 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

Version requirement

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.

FieldTypeRequiredDefaultDescription
track_namestringyesNon-empty LiveKit video track name.
sourcemapyesSource configuration. Its type is gstreamer, device, or pattern.
simulcastbooleanfalseEnables simulcast for device and pattern sources. GStreamer sources ignore this field.
publish_optionsmapOptional 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=center
valignment=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=30
lag-in-frames=0 target-bitrate=2500000
! video/x-vp8
! appsink name=lk_appsink sync=false max-buffers=2 drop=true
codec: "vp8"
resolution:
width: 640
height: 480
rate_control:
element: "lk_encoder"
property: "target-bitrate"
unit: "bps"
publish_options:
max_bitrate_bps: 2500000
max_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: 1280
height: 720
framerate_fps: 30
publish_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: 1280
height: 720
framerate_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.