Streaming ROS camera topics to a web browser

Set up web_video_server on ROS 1 or ROS 2, pick a stream format, build the stream URL, embed the feed in your own page and fix the usual connection problems.

Want to see what your robot sees, from a laptop or a phone, without installing anything? The web_video_server package turns any ROS image topic into a video stream that a normal web browser can open. This is handy for remote monitoring, teleoperation dashboards and demos.

How it works

$$ \underbrace{\text{Camera driver}}_{\text{ROS node}} \;\rightarrow\; \underbrace{\texttt{/camera/image\_raw}}_{\text{ROS topic}} \;\rightarrow\; \underbrace{\texttt{web\_video\_server}}_{\text{HTTP server, port 8080}} \;\rightarrow\; \text{Browser} $$

The server subscribes to the image topic only while someone is watching, encodes the frames and sends them over HTTP.

What you need

  • ROS 1 Noetic or ROS 2 (Humble or newer)
  • A node that publishes images, for example a camera driver or a Gazebo camera
  • Any modern browser

1. Install

Use the package from your ROS distribution:

Shell
# ROS 2 (replace humble with your distribution, e.g. jazzy)
sudo apt install ros-humble-web-video-server

# ROS 1 Noetic
sudo apt install ros-noetic-web-video-server

If no package exists for your distribution, build it from source in your workspace:

Shell
cd ~/ros2_ws/src
git clone https://github.com/RobotWebTools/web_video_server.git
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -y
colcon build --packages-select web_video_server
source install/setup.bash

2. Start a camera and the server

Check that an image topic is being published:

Shell
ros2 topic list | grep image        # ROS 1: rostopic list | grep image
ros2 topic hz /camera/image_raw     # should show a steady rate

Then start the server:

Shell
ros2 run web_video_server web_video_server                         # ROS 2, port 8080
ros2 run web_video_server web_video_server --ros-args -p port:=8081 # another port
rosrun web_video_server web_video_server _port:=8081               # ROS 1

3. Open it in the browser

Go to http://localhost:8080 on the robot, or http://<robot-ip>:8080 from another device on the same network. The page lists every image topic; click one to watch it.

Building the stream URL yourself

Every stream has its own address, so you can put it in your own pages:

http://<robot-ip>:8080/stream?topic=/camera/image_raw&type=mjpeg&quality=60&width=640&height=480
Parameter Meaning
topic The ROS image topic (required)
type Stream format, see the table below (default mjpeg)
width, height Resize the image before sending; saves bandwidth
quality JPEG quality from 1 to 100 (for mjpeg)
bitrate Target bitrate (for vp8, vp9, h264)

Two more endpoints are useful: /snapshot?topic=... returns a single JPEG image, and /stream_viewer?topic=... shows the stream on a ready-made page.

Which format to choose

type Good for Note
mjpeg Most cases, lowest delay Works in every browser inside an <img> tag; uses more bandwidth
vp8, vp9 Slow networks Better compression, needs a <video> tag, a little more delay
h264 Slow networks Good compression; browser support varies
png Exact images Lossless, large
ros_compressed Cameras that already publish compressed images Passes the JPEG through without re-encoding

Embedding the stream in your own page

An MJPEG stream behaves like an image, so one line of HTML is enough:

html
<img src="http://192.168.1.20:8080/stream?topic=/camera/image_raw&type=mjpeg&quality=60"
     alt="Live view from the robot camera" width="640">

For a small dashboard, put several <img> tags side by side, one per camera, and add buttons that change the topic in the address with a line of JavaScript.

Troubleshooting

Problem Check
The page lists no topics Is the camera node running? ros2 topic list. Is the message type sensor_msgs/Image? ros2 topic info /your/topic
The page does not open Is the server running? ros2 node list. Is port 8080 already used, or blocked by a firewall (sudo ufw allow 8080)?
Works on the robot but not from a laptop Use the robot's IP, not localhost. Both devices must be on the same network. Make sure the address parameter is 0.0.0.0 (all interfaces)
Stream is slow or jerky Lower quality, add width and height, or switch to vp8 on weak Wi-Fi
Black or frozen image Check the camera itself: ros2 run rqt_image_view rqt_image_view

A note on security

web_video_server has no login. Anyone who can reach the port can watch the camera. On a shared or public network, keep it behind a VPN, or put a reverse proxy such as nginx with authentication and HTTPS in front of it.

Why it is worth setting up

Being able to open the robot's camera from any browser makes remote monitoring, debugging and demonstrations much easier, and it is the first building block of a web-based control panel for telepresence, inspection or teaching robots.

Basheer Al-Tawil is a PhD researcher in Robotics and AI at Otto von Guericke University. Found a mistake or have a question? Write to me.

Browse by topic