rtsptoweb webrtc is an open-source gateway that converts RTSP camera streams into low-latency WebRTC feeds playable directly in modern browsers without plugins. It bridges traditional IP camera protocols to web-native real-time communication using a Go-based media server that handles signaling, ICE negotiation, and codec repackaging. For developers building surveillance dashboards or live video applications, it eliminates the need for Flash or heavyweight media players while keeping latency under one second.
Introduction
IP cameras output RTSP streams that browsers cannot play natively. For years, developers worked around this with Flash players, VLC plugins, or transcoding pipelines that added seconds of delay. The rtsptoweb project changes that equation by acting as a lightweight gateway that pulls RTSP feeds and serves them as WebRTC streams to any modern browser.
Whether you are building a home surveillance dashboard, a live-shopping kiosk, or a remote monitoring system for industrial equipment, getting camera video into the browser with sub-second latency is the core challenge. RTSPtoWeb solves this by handling the protocol translation, ICE candidate negotiation, and codec packaging on the server side, leaving the browser to do what it does best: render WebRTC media streams.
By the end of this guide, you will understand how rtsptoweb webrtc works, how to deploy it, how to configure streams for production, and when to consider a more comprehensive solution like VideoSDK for multi-participant video applications.
What Is RTSP and How Does WebRTC Differ?
RTSP (Real-Time Streaming Protocol) is a network protocol designed for controlling streaming media servers, commonly used by IP cameras, DVRs, and NVRs. It operates over TCP or UDP and typically delivers H.264 or H.265 video payloads via RTP (Real-time Transport Protocol). RTSP has been the de facto standard for surveillance camera output since the early 2000s, but it was never designed for browser playback.
WebRTC, by contrast, is a browser-native real-time communication framework that uses UDP-based transport with sub-second latency. It handles its own signaling, NAT traversal via ICE/STUN/TURN, and media encryption via SRTP. WebRTC is built into every modern browser, requires no plugins, and supports adaptive bitrate streaming to handle fluctuating network conditions.
The fundamental difference is latency and accessibility. RTSP streams typically arrive in a browser only after transcoding to HLS or MPEG-DASH, which adds 5 to 30 seconds of delay. WebRTC delivers the same camera feed with latency under one second, making it suitable for interactive monitoring, live commerce, and any scenario where real-time responsiveness matters.
How rtsptoweb webrtc Converts Streams
The rtsptoweb project acts as a protocol bridge between RTSP sources and WebRTC consumers, and understanding its architecture helps you diagnose issues and plan production deployments effectively.
When a browser requests a stream, rtsptoweb initiates an RTSP session with the camera, receives RTP packets containing H.264 video and optional audio, and repackages them into WebRTC-compatible RTP payloads. The server then participates in WebRTC signaling with the browser, exchanges SDP offers and answers, and establishes a peer connection that delivers the media stream directly to the browser's video element.
The key insight is that rtsptoweb does not transcode video by default. It repackages the H.264 NAL units from RTSP into WebRTC RTP packets, which is fast and CPU-efficient. This works because H.264 is supported by all major browsers' WebRTC implementations. If your camera outputs H.265 or AV1, additional considerations apply, which we cover in the performance section.
Here is how the data flows from camera to browser:
The signaling layer handles the browser's WebRTC negotiation, including SDP exchange and ICE candidate gathering. The STUN/TURN infrastructure is critical for deployments where the browser or the server sits behind a NAT or firewall. Without proper STUN/TURN configuration, the peer connection will fail to establish, and the browser will show no video.
For developers who need more than single-stream playback, such as multi-participant rooms, recording, or custom layouts, VideoSDK's video calling SDK provides a full rooms-based architecture that handles these capabilities out of the box.
Installation Options
RTSPtoWeb offers two primary deployment paths: building from source or running the official Docker container. Your choice depends on whether you need to customize the server or want a quick, reproducible deployment.
From Source
Building rtsptoweb from source requires a Go environment. You clone the official repository from GitHub, ensure your Go version matches the project's requirements, and build the binary using the standard Go toolchain. The resulting binary is a single executable that serves both the WebRTC gateway and a demo web UI for testing streams.
After building, you run the binary with a configuration file that defines your server settings and stream definitions. The binary listens on the HTTP and HTTPS ports you specify, and the demo UI is accessible at the server's address. This approach gives you full control over build flags, custom patches, and debugging output, but it requires maintaining your Go toolchain and rebuilding when updates are released.
Docker Container
The Docker approach is faster and more reproducible. You pull the official RTSPtoWeb image from Docker Hub, mount your configuration file and any TLS certificates into the container, and run it with host networking mode. Host networking is important because WebRTC uses dynamic UDP ports for media transport, and Docker's default bridge network can interfere with ICE candidate discovery.
With Docker, you can deploy rtsptoweb in minutes, update by pulling a new image tag, and manage configuration through environment variables or mounted files. This is the recommended path for production deployments where reproducibility and ease of updates matter.
Configuration Deep Dive
RTSPtoWeb uses a JSON configuration file that defines server-level settings and a hierarchy of streams and channels. Understanding this structure is essential for managing multiple cameras and tuning performance.
Server Settings
The server configuration block controls global behavior. Key settings include the debug flag, which enables verbose logging useful for diagnosing ICE and signaling issues. The HTTP and HTTPS ports define where the web UI and API endpoints listen. For production, HTTPS is mandatory because browsers require secure contexts for WebRTC features like camera and microphone access, and increasingly for media playback from cross-origin sources.
The STUN and TURN server list is the most critical server-level setting. STUN servers help the browser and the RTSPtoWeb server discover their public IP addresses for ICE candidate gathering. TURN servers relay media when direct peer connections fail due to restrictive NATs or firewalls. Without properly configured STUN/TURN, remote clients connecting from different networks will frequently fail to establish a WebRTC connection.
You should also configure the logging level to balance diagnostic visibility against disk usage. In production, a moderate logging level captures errors and connection failures without filling disk space with per-packet debug output.
Stream and Channel Settings
Streams in rtsptoweb are logical containers that hold one or more channels. Each channel represents a single RTSP source URL. This hierarchy lets you group related cameras or provide multiple quality levels under a single stream name.
Each channel configuration includes the RTSP URL, an audio flag that controls whether audio is forwarded, and a status flag that enables or disables the channel without removing it from the config. The on-demand setting determines whether the server maintains a persistent connection to the camera or only pulls the stream when a browser requests it.
Here is how the configuration hierarchy maps to the runtime architecture:

This hierarchy means you can manage dozens of cameras in a single configuration file, each with multiple quality levels, and the server handles connection pooling and stream lifecycle automatically.
Streaming Modes: On-Demand vs Static
RTSPtoWeb supports two streaming modes that fundamentally affect bandwidth consumption and camera load, and choosing the right one depends on your viewing patterns.
On-demand mode tells the server to connect to the RTSP source only when a browser requests the stream. When the last viewer disconnects, the server closes the RTSP session. This is the default and recommended mode for most deployments because it minimizes bandwidth usage, reduces camera load, and prevents unnecessary network traffic when nobody is watching.
Static mode maintains a persistent connection to the RTSP source regardless of viewer count. The server continuously pulls the stream and keeps it ready for immediate playback. This reduces the initial connection time for the first viewer because the stream is already established, but it consumes bandwidth continuously and puts constant load on the camera.
Choose on-demand mode when you have many cameras and intermittent viewing patterns, such as a surveillance dashboard where operators check cameras sporadically. Choose static mode when you need instant playback with zero buffering for a high-traffic stream, such as a live-shopping event where every second of initial delay costs engagement.
Performance Considerations
Several factors influence the performance of rtsptoweb webrtc streams, and understanding them helps you deliver a smooth viewing experience across different network conditions.
Latency in an RTSP-to-WebRTC pipeline comes from three primary sources. The RTSP pull introduces a small delay based on the camera's keyframe interval. The repackaging from RTSP RTP to WebRTC RTP adds minimal overhead since no transcoding occurs. The WebRTC transport adds jitter buffer delay in the browser, typically 100 to 300 milliseconds. Total end-to-end latency usually falls between 300 and 800 milliseconds, which is excellent for real-time monitoring.
Browser codec support is a critical consideration. H.264 is universally supported across all major browsers' WebRTC implementations, making it the safest codec choice for RTSP cameras. H.265 (HEVC) is not supported by WebRTC in most browsers as of 2026, so cameras outputting H.265 require transcoding, which adds CPU load and latency. AV1 support in WebRTC is growing but not yet universal, with Chrome and Firefox offering partial support while Safari lags behind.
ICE candidate selection affects connection reliability and latency. Host candidates work when the browser and server are on the same network. Server-reflexive candidates (STUN) work across most NAT configurations. Relay candidates (TURN) provide the highest reliability but add latency due to media relaying. Configuring all three candidate types ensures the best chance of a successful connection.
Bandwidth adaptation is handled by WebRTC's built-in congestion control, which adjusts the send bitrate based on available bandwidth. However, since rtsptoweb repackages rather than transcodes, the adaptation is limited to what the camera's stream bitrate allows. If your camera outputs 4 Mbps of H.264 video and the viewer's connection can only handle 2 Mbps, the browser will experience packet loss and freezing unless the camera itself supports substream switching.
For applications that need true adaptive bitrate streaming with multiple quality levels, VideoSDK's network-adaptive streaming automatically adjusts resolution and bitrate in real time, which is something a simple RTSP-to-WebRTC bridge cannot do without additional transcoding infrastructure.
Security and Authentication
Securing your rtsptoweb deployment involves protecting both the server and the stream endpoints from unauthorized access.
The demo web UI ships with basic authentication that you should change from the default credentials immediately. For production deployments, consider placing the UI behind a reverse proxy that handles authentication at the edge, such as nginx with OAuth or a dedicated API gateway.
Stream access can be protected using token-based authentication. RTSPtoWeb supports generating authentication tokens that are appended to stream URLs, ensuring that only authorized clients can view specific camera feeds. Tokens should be generated server-side and have appropriate expiration times to prevent unauthorized sharing.
HTTPS is mandatory for production WebRTC deployments. Browsers require secure contexts for WebRTC APIs, and mixed-content policies block WebRTC media on HTTP pages. RTSPtoWeb can serve HTTPS directly if you provide TLS certificates, or you can terminate TLS at a reverse proxy and forward plain HTTP to the container.
Firewall configuration is often overlooked. WebRTC uses UDP for media transport on a range of dynamic ports. Your firewall must allow outbound UDP traffic from the server to STUN/TURN servers and inbound UDP on the configured media port range. Restrictive firewalls that only allow TCP 80 and 443 will cause WebRTC connections to fail or fall back to TURN relaying.
Real-World Use Cases
RTSPtoWeb WebRTC bridges are deployed across several industries, each with distinct requirements that make this approach compelling compared to traditional transcoding pipelines.
Home surveillance dashboards are the most common use case. A homeowner with multiple IP cameras wants a single web page that displays all camera feeds in real time. RTSPtoWeb pulls each camera's RTSP stream on demand and serves them as WebRTC peers to the browser dashboard. The sub-second latency means the homeowner sees events as they happen, not seconds later. The on-demand mode ensures cameras are not stressed when nobody is viewing.
Live-shopping kiosks in retail environments use RTSP cameras to stream product demonstrations to in-store displays or online viewers. The low latency of WebRTC ensures that interactions between the presenter and remote viewers feel natural. RTSPtoWeb can serve the camera feed to a web-based live-shopping platform, and the platform can overlay product information, chat, and purchase buttons on top of the video element. For multi-host live shopping with audience interaction, VideoSDK's interactive live streaming provides the host, co-host, and viewer role management that a simple RTSP bridge cannot.
Remote drone telemetry feeds use RTSP cameras mounted on drones to stream live video to ground stations. The sub-second latency is critical for pilot control and navigation. RTSPtoWeb running on a ground station computer can serve the drone's video feed to multiple browser-based monitoring stations via WebRTC, allowing a team to watch the feed simultaneously. The bandwidth efficiency of WebRTC compared to transcoded HLS means the ground station's uplink is not saturated.
Troubleshooting Common Issues
Even a well-configured rtsptoweb deployment can encounter issues, and knowing how to diagnose them systematically saves hours of trial and error.
No video in the browser is usually caused by one of three things. First, check that the RTSP URL is correct and the camera is reachable from the server. Use a desktop RTSP client to verify the camera is streaming. Second, check the browser console for WebRTC errors, which often indicate ICE failure. Third, verify that the server is running and the demo UI loads without authentication errors.
ICE connection failures occur when the browser and server cannot establish a UDP path. Check your STUN/TURN configuration first. If the server is behind a NAT, ensure the TURN server is configured and reachable. Use the browser's built-in WebRTC diagnostics to see which ICE candidates are being gathered and whether any succeed. Firewall rules blocking UDP traffic are the most common cause of persistent ICE failures.
CORS errors appear when the web page serving the video player is on a different origin than the RTSPtoWeb server. Configure the server's CORS settings to allow your application's origin, or serve both the application and the stream from the same origin using a reverse proxy.
Token rejection happens when the authentication token is expired, malformed, or generated with the wrong secret. Regenerate the token with the correct server secret and ensure the token is passed correctly in the stream URL. Check the server logs for authentication failure messages to confirm the cause.
Definitions Glossary
RTSP (Real-Time Streaming Protocol): A network protocol for controlling streaming media servers, commonly used by IP cameras to deliver video feeds over TCP or UDP.
WebRTC: A browser-native real-time communication framework that enables sub-second latency audio and video streaming using UDP transport, ICE negotiation, and SRTP encryption.
ICE (Interactive Connectivity Establishment): A framework that allows WebRTC peers to discover possible network paths between them using host, server-reflexive, and relay candidates.
STUN Server: A server that helps a WebRTC peer discover its public IP address when behind a NAT, enabling direct peer-to-peer connections.
TURN Server: A relay server that forwards WebRTC media traffic when direct peer connections fail due to restrictive NATs or firewalls.
On-Demand Streaming: A streaming mode where the server connects to the RTSP source only when a viewer requests the stream, conserving bandwidth and camera resources.
SDP (Session Description Protocol): A format for describing streaming media initialization parameters, used during WebRTC signaling to negotiate codecs, ports, and media types.
Key Takeaways
- rtsptoweb webrtc bridges the gap between RTSP IP cameras and browser-native WebRTC playback, delivering sub-second latency without plugins or transcoding.
- The server repackages H.264 RTP payloads from RTSP into WebRTC-compatible RTP packets, which is CPU-efficient but requires browser codec compatibility.
- On-demand streaming mode is the recommended default for most deployments because it minimizes bandwidth usage and camera load when no viewers are active.
- Proper STUN and TURN configuration is essential for remote viewers, as WebRTC media transport relies on UDP paths that firewalls and NATs can block.
- For applications requiring multi-participant rooms, recording, adaptive bitrate streaming, or custom layouts, VideoSDK provides a more comprehensive real-time communication platform than a standalone RTSP-to-WebRTC bridge.
Conclusion
RTSPtoWeb gives developers a straightforward path from IP camera RTSP output to browser-playable WebRTC streams. The Go-based gateway handles protocol translation, ICE negotiation, and stream management without requiring you to build a media server from scratch. The Docker deployment path gets you running in minutes, and the on-demand streaming mode keeps bandwidth costs predictable.
If your use case is primarily one-way camera-to-browser streaming, rtsptoweb webrtc is an excellent choice. If you need multi-participant video rooms, server-side recording, real-time transcription, or network-adaptive streaming across many viewers, VideoSDK's video calling SDK handles those capabilities with a broader set of platform SDKs including React, Flutter, Android, and iOS. You can start building for free at app.videosdk.live/login.
What are you building with RTSP cameras and WebRTC? Drop a comment below, I would love to hear what kind of streaming use case you are working on.
Step 5: Implement Participant View
In this section, we will enhance the RTSPtoWeb WebRTC application by implementing a participant view. This will allow multiple viewers to join and watch the same stream concurrently, offering a more interactive and scalable streaming experience.
HTML Structure for Participant View
We will extend the existing HTML to support multiple participants. Modify your
index.html file to include a list of participants and a container for their streams:HTML
1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>RTSPtoWeb WebRTC</title>
7 <style>
8 body {
9 font-family: Arial, sans-serif;
10 text-align: center;
11 margin-top: 50px;
12 }
13 #join-screen {
14 margin: 20px;
15 }
16 #video-container {
17 display: none;
18 margin-top: 20px;
19 }
20 #controls {
21 margin-top: 10px;
22 }
23 button {
24 margin: 0 10px;
25 }
26 #participants {
27 display: flex;
28 flex-wrap: wrap;
29 justify-content: center;
30 margin-top: 20px;
31 }
32 .participant {
33 margin: 10px;
34 }
35 video {
36 max-width: 100%;
37 }
38 </style>
39</head>
40<body>
41 <h1>Join a Live Stream</h1>
42 <div id="join-screen">
43 <label for="stream-select">Select Stream:</label>
44 <select id="stream-select">
45 <option value="example_stream">Example Stream</option>
46 <!-- Add more options here based on available streams -->
47 </select>
48 <button id="join-button">Join</button>
49 </div>
50 <div id="video-container">
51 <video id="video" autoplay playsinline controls></video>
52 <div id="controls">
53 <button id="play-button">Play</button>
54 <button id="pause-button">Pause</button>
55 <button id="stop-button">Stop</button>
56 </div>
57 </div>
58 <div id="participants"></div>
59 <script src="webrtc.js"></script>
60</body>
61</html>In this structure, the
#participants div will hold individual video elements for each participant.JavaScript Code for Participant View
Now, we need to update our JavaScript to handle multiple participants. Modify your
webrtc.js file with the following code:JavaScript
1document.getElementById('join-button').addEventListener('click', function() {
2 const streamName = document.getElementById('stream-select').value;
3 joinStream(streamName);
4});
5
6document.getElementById('play-button').addEventListener('click', function() {
7 const videoElement = document.getElementById('video');
8 videoElement.play();
9});
10
11document.getElementById('pause-button').addEventListener('click', function() {
12 const videoElement = document.getElementById('video');
13 videoElement.pause();
14});
15
16document.getElementById('stop-button').addEventListener('click', function() {
17 const videoElement = document.getElementById('video');
18 videoElement.pause();
19 videoElement.currentTime = 0; // Reset the video to the beginning
20});
21
22function joinStream(streamName) {
23 const videoContainer = document.getElementById('video-container');
24 const videoElement = document.getElementById('video');
25 const participantsContainer = document.getElementById('participants');
26
27 // Show the video container
28 videoContainer.style.display = 'block';
29
30 // Replace with actual WebRTC setup code
31 const wsUrl = `wss://yourserver.com/ws/${streamName}`; // WebSocket URL for the WebRTC stream
32 const pc = new RTCPeerConnection();
33 const ws = new WebSocket(wsUrl);
34
35 ws.onmessage = (message) => {
36 const signal = JSON.parse(message.data);
37 if (signal.sdp) {
38 pc.setRemoteDescription(new RTCSessionDescription(signal.sdp)).then(() => {
39 if (signal.sdp.type === 'offer') {
40 pc.createAnswer().then(answer => {
41 pc.setLocalDescription(answer).then(() => {
42 ws.send(JSON.stringify({ 'sdp': pc.localDescription }));
43 });
44 });
45 }
46 });
47 } else if (signal.candidate) {
48 pc.addIceCandidate(new RTCIceCandidate(signal.candidate));
49 }
50 };
51
52 pc.onicecandidate = (event) => {
53 if (event.candidate) {
54 ws.send(JSON.stringify({ 'candidate': event.candidate }));
55 }
56 };
57
58 pc.ontrack = (event) => {
59 videoElement.srcObject = event.streams[0];
60 addParticipantView(event.streams[0]);
61 };
62
63 navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
64 stream.getTracks().forEach(track => pc.addTrack(track, stream));
65 }).catch(error => {
66 console.error('Error accessing media devices.', error);
67 });
68
69 // Start WebRTC negotiation
70 pc.createOffer().then(offer => {
71 pc.setLocalDescription(offer).then(() => {
72 ws.send(JSON.stringify({ 'sdp': pc.localDescription }));
73 });
74 });
75}
76
77function addParticipantView(stream) {
78 const participantsContainer = document.getElementById('participants');
79 const participantDiv = document.createElement('div');
80 participantDiv.className = 'participant';
81 const participantVideo = document.createElement('video');
82 participantVideo.autoplay = true;
83 participantVideo.playsinline = true;
84 participantVideo.srcObject = stream;
85 participantDiv.appendChild(participantVideo);
86 participantsContainer.appendChild(participantDiv);
87}Explanation of the JavaScript Code
Event Listeners for Control Buttons
- Play Button: Resumes the video playback by calling the
playmethod on the video element. - Pause Button: Pauses the video playback by calling the
pausemethod on the video element. - Stop Button: Pauses the video and resets the current time to the beginning, effectively stopping the video.
Join Stream Function
- The
joinStreamfunction displays the video container and sets up the WebRTC connection. - A WebSocket connection is established to the server using the URL for the selected stream.
- The WebRTC peer connection (
RTCPeerConnection) is created, and signaling messages are exchanged via WebSocket to establish the connection. - The video stream is set as the source for the video element, and the
addParticipantViewfunction is called to add the stream to the participant view.
Add Participant View Function
- This function creates a new
divfor each participant, including avideoelement to display their stream. - The participant view is appended to the
#participantscontainer, allowing multiple viewers to be displayed concurrently.
By implementing the participant view, you enable multiple viewers to join and watch the same stream, enhancing the interactivity and scalability of your RTSPtoWeb WebRTC application. In the next step, we will focus on running your code and troubleshooting any common issues.
Step 6: Run Your Code Now
Now that you have set up the RTSPtoWeb WebRTC application with a join screen, user controls, and participant view, it’s time to run your code and see everything in action. This section will guide you through the process of running the application and troubleshooting common issues.
Running the Application
Start the RTSPtoWeb Application
Ensure you have your Go environment set up and dependencies installed as mentioned in Part 2. Then, run the application with the following command:
bash
1 go run main.goYou should see output indicating that the RTSPtoWeb server is running and ready to accept connections.
Access the Web Interface
Open a web browser and navigate to
http://localhost:8083. You should see the join screen where you can select a stream and click the "Join" button to start watching the live stream.Interacting with the Stream
- Play: Click the "Play" button to resume playback if the video is paused.
- Pause: Click the "Pause" button to pause the video stream.
- Stop: Click the "Stop" button to stop the video and reset it to the beginning.
Troubleshooting Common Issues
Server Not Starting
If the server fails to start, check the following:
- Ensure Go is installed correctly and your environment variables are set up.
- Verify that you have installed all dependencies using
go mod tidy. - Check the
config.jsonfile for any syntax errors or incorrect configurations.
WebSocket Connection Issues
If you encounter WebSocket connection issues:
- Ensure that the WebSocket URL in the
webrtc.jsfile is correct and matches your server’s address. - Verify that your server is running and accessible from the browser.
No Video Stream
If the video stream is not appearing:
- Ensure your RTSP stream source is working correctly and accessible.
- Check the browser console for any errors related to WebRTC or media devices.
- Make sure the
addParticipantViewfunction is correctly adding the video elements to the DOM.
Cross-Origin Resource Sharing (CORS) Issues
If you encounter CORS issues:
- Make sure your server is configured to allow CORS requests from your web application’s domain.
Conclusion
Congratulations! You have successfully set up the RTSPtoWeb WebRTC application. By following the steps outlined in this guide, you now have a functional application that allows multiple users to join and watch live RTSP streams through their web browsers. This setup provides a robust and scalable solution for real-time streaming applications.
Free $20 Balance for AI Voice Agents & Video Calls
FAQ
