How to Convert RTSP IP Camera Stream to WebRTC for Browser Viewing

A complete guide to using Happytime Portable RTC to ingest an RTSP stream from any IP camera and convert it to WebRTC for real-time, plugin-free viewing in Chrome, Firefox, Edge, or Safari. No browser plugins required — just standard WebRTC.

Why RTSP-to-WebRTC?

RTSP (Real-Time Streaming Protocol) is the dominant video streaming protocol used by IP cameras worldwide. However, no modern browser supports RTSP natively — users must install plugins like VLC Web Plugin or Flash, both of which are deprecated or blocked.

WebRTC solves this by enabling direct browser-to-server real-time communication using standard APIs built into every modern browser. By converting RTSP to WebRTC with Portable RTC, you achieve:

  • Zero Browser Plugins: View camera feeds directly in Chrome, Firefox, Edge, or Safari using built-in WebRTC support.
  • Low Latency: Portable RTC's optimized C-based stack delivers sub-second glass-to-glass latency, far lower than HLS or DASH alternatives.
  • Secure Transport: DTLS-SRTP encrypts both signaling and media streams, ensuring camera feeds are protected end-to-end.
  • NAT Traversal: ICE/STUN protocols automatically handle NAT and firewall traversal, enabling remote camera access without complex port forwarding.
  • Bandwidth Efficiency: On-demand proxy mode connects to the RTSP source only when a browser is actively viewing, conserving camera and network resources.

Architecture Overview

Before configuration, it is important to understand how the components fit together:

  1. RTSP IP Camera — Any ONVIF-compliant or generic IP camera producing an RTSP stream (e.g., rtsp://192.168.1.64:554/Streaming/Channels/101).
  2. Portable RTC — The C-based media engine that ingests the RTSP stream, transcodes it if needed, and packages it into WebRTC-compatible RTP packets. It exposes streams via WebSocket to the signal server.
  3. Signal Server — A WebSocket-based server that handles signaling (SDP offer/answer exchange and ICE candidate negotiation) between Portable RTC and the browser. Portable RTC connects to the signal server as a client.
  4. Browser Client — A standard web page using the WebRTC API. The browser connects to the signal server via WebSocket, exchanges SDP with Portable RTC, and receives the media stream via peer-to-peer (or relayed) RTP.

The complete data flow: Camera (RTSP) → Portable RTC (ingest + transcode + WebRTC-pack) → Signal Server (signaling relay) → Browser (WebRTC playback).

Step 1: Deploy the Signal Server

The signal server (SignalServer.exe) is the communication hub that Portable RTC and browsers connect to. It runs an HTTP server for serving the WebRTC player page and handles WebSocket signaling (SDP offer/answer exchange and ICE candidate negotiation) between Portable RTC and the browser.

Place SignalServer.exe and its configuration file signalserver.cfg on a machine reachable by both Portable RTC and the browser client.

Signal Server Configuration

signalserver.cfg — Default Configuration
<http_enable>1</http_enable>
<http_server_ip></http_server_ip>
<http_port>8080</http_port>
<https_enable>1</https_enable>
<https_server_ip></https_server_ip>
<https_port>5443</https_port>
<cert_file>cert.pem</cert_file>
<key_file>key.pem</key_file>
<ipv6_enable>1</ipv6_enable>
<wan_ip></wan_ip>
<log_enable>1</log_enable>
<log_level>1</log_level>
<log_path></log_path>
<log_mode>loop</log_mode>

Start the signal server:

Start the Signal Server
# On Windows
SignalServer.exe

# On Linux
./SignalServer

Verify the signal server is running by checking the console output. It should display the HTTP port (default 8080) and HTTPS port (default 5443) it is listening on. Note these addresses — you will need them for both the Portable RTC configuration and the browser URL.

For detailed deployment guidance including STUN/TURN ICE server configuration (via the <ice_servers> section in signalserver.cfg) and LAN/WAN/cloud placement, refer to the How to deploy signal server guide.

Step 2: Configure Portable RTC for RTSP Proxy

The core configuration file is portablertc.cfg. RTSP streams are converted to WebRTC through the <proxy> mechanism within an <application> block.

Configuration Structure

Section Purpose
Global HTTP/HTTPS server, logging, signal server address, device name, authentication, data channel.
<application> Defines a streaming application. Multiple applications can serve different stream groups. Each application is identified by its <name>.
<output> Defines encoding parameters matched by stream URL. When the browser requests a stream whose URL matches a specific <url> pattern, the corresponding output settings are applied.
<proxy> Defines a proxied RTSP/RTMP/SRT source. Specifies the original stream URL, credentials, transfer protocol, on-demand mode, and per-proxy output parameters.

Global Configuration

portablertc.cfg — Global Settings
<http_enable>1</http_enable>
<http_server_ip></http_server_ip>
<http_port>80</http_port>
<https_enable>0</https_enable>
<need_auth>0</need_auth>
<ipv6_enable>1</ipv6_enable>
<data_channel>0</data_channel>
<ws_signal_server>ws://192.168.3.36:8080</ws_signal_server>
<wss_signal_server>wss://192.168.3.36:5443</wss_signal_server>
<device_name>MyPortableRTC</device_name>
<log_enable>1</log_enable>
<log_level>1</log_level>
<log_path></log_path>
<log_mode>loop</log_mode>
<log_max_size></log_max_size>
<log_max_index></log_max_index>

Key global parameters:

Parameter Description
<ws_signal_server> The WebSocket address of the signal server. Format: ws://signal-server-ip:port. Portable RTC registers itself with this server.
<wss_signal_server> The secure WebSocket address. Format: wss://signal-server-ip:port. Used when HTTPS/WSS transport is required.
<device_name> A human-readable name that Portable RTC sends to the signal server. The browser can use this name to identify and select the device.
<data_channel> Enable (1) or disable (0) the WebRTC data channel. Enable this if you need bidirectional data messaging alongside the video stream.
<need_auth> Enable (1) or disable (0) authentication. When enabled, the browser client must provide valid credentials from the <user> block to access streams.

Step 3: Define the RTSP Proxy

The <proxy> block tells Portable RTC where to pull the source RTSP stream from, how to authenticate, and what encoding parameters to use for the WebRTC output.

Single RTSP Camera Configuration

portablertc.cfg — RTSP Proxy for One Camera
<application>
    <name>myapp</name>

    <!-- Default output settings -->
    <output>
        <url></url>
        <video>
            <codec>H264</codec>
            <width></width>
            <height></height>
            <framerate></framerate>
            <bitrate></bitrate>
        </video>
        <audio>
            <codec>G711A</codec>
            <samplerate>8000</samplerate>
            <channels>1</channels>
            <bitrate></bitrate>
        </audio>
    </output>

    <!-- RTSP proxy for front entrance camera -->
    <proxy>
        <suffix>front-entrance</suffix>
        <url>rtsp://192.168.1.64:554/Streaming/Channels/101</url>
        <user>admin</user>
        <pass>mypassword</pass>
        <transfer>TCP</transfer>
        <ondemand>1</ondemand>
        <output>
            <video>
                <codec>H264</codec>
                <width></width>
                <height></height>
                <framerate></framerate>
                <bitrate></bitrate>
            </video>
            <audio>
                <codec>G711A</codec>
                <samplerate>8000</samplerate>
                <channels>1</channels>
                <bitrate></bitrate>
            </audio>
        </output>
    </proxy>
</application>

Proxy configuration parameters:

Parameter Description
<suffix> The unique stream identifier. Combined with the application name to form the streamid URL parameter ([app]/[suffix]). Each proxy must have a unique suffix within the same application.
<url> The full RTSP URL of the IP camera. Format: rtsp://[user:pass@]ip:port/path. Also supports rtmp://, srt://, and HTTP MJPEG URLs.
<user> Username for the source RTSP stream. Leave empty if the camera does not require authentication. This authenticates Portable RTC to the camera, not the browser client.
<pass> Password for the source RTSP stream.
<transfer> RTSP client transport protocol. TCP is recommended for reliability and firewall traversal. Also supports UDP and MULTICAST.
<ondemand> Bandwidth-saving feature. When 1, Portable RTC connects to the RTSP source only when a browser client is actively viewing the stream. When the browser disconnects, the RTSP connection is released. When 0, the RTSP connection is maintained continuously.

Step 4: Configure for Multiple Cameras

To serve multiple cameras from a single Portable RTC instance, add additional <proxy> blocks with unique suffixes. The demo version supports up to 4 concurrent streams; the release version supports up to 100.

portablertc.cfg — Multiple RTSP Proxies
<application>
    <name>myapp</name>

    <!-- Proxy 1: Front Entrance -->
    <proxy>
        <suffix>front-entrance</suffix>
        <url>rtsp://admin:pass1@192.168.1.64:554/Streaming/Channels/101</url>
        <transfer>TCP</transfer>
        <ondemand>1</ondemand>
    </proxy>

    <!-- Proxy 2: Parking Lot -->
    <proxy>
        <suffix>parking-lot</suffix>
        <url>rtsp://admin:pass2@192.168.1.65:554/Streaming/Channels/101</url>
        <transfer>TCP</transfer>
        <ondemand>1</ondemand>
    </proxy>

    <!-- Proxy 3: Warehouse -->
    <proxy>
        <suffix>warehouse</suffix>
        <url>rtsp://admin:pass3@192.168.1.66:554/Streaming/Channels/101</url>
        <transfer>TCP</transfer>
        <ondemand>1</ondemand>
    </proxy>
</application>

Each proxy's <suffix> combined with the application <name> forms the streamid parameter used in the browser URL. With the configuration above, the three cameras are accessible at:

  • http://192.168.3.36:8080/webrtc?streamid=myapp/front-entrance
  • http://192.168.3.36:8080/webrtc?streamid=myapp/parking-lot
  • http://192.168.3.36:8080/webrtc?streamid=myapp/warehouse

Step 5: Complete Configuration Example

Below is a complete portablertc.cfg with all global settings and a single RTSP proxy configured. This is a ready-to-use configuration — only change the signal server IP and the RTSP camera URL to match your environment.

portablertc.cfg — Complete Example
<?xml version="1.0" encoding="utf-8"?>
<config>
    <http_enable>1</http_enable>
    <http_server_ip></http_server_ip>
    <http_port>80</http_port>
    <https_enable>0</https_enable>
    <need_auth>0</need_auth>
    <ipv6_enable>1</ipv6_enable>
    <data_channel>0</data_channel>
    <ws_signal_server>ws://192.168.3.36:8080</ws_signal_server>
    <wss_signal_server>wss://192.168.3.36:5443</wss_signal_server>
    <device_name>MyPortableRTC</device_name>
    <loop_nums>-1</loop_nums>
    <log_enable>1</log_enable>
    <log_level>1</log_level>
    <log_path></log_path>
    <log_mode>loop</log_mode>
    <log_max_size></log_max_size>
    <log_max_index></log_max_index>

    <user>
        <username>admin</username>
        <password>admin</password>
    </user>

    <application>
        <name>myapp</name>

        <proxy>
            <suffix>front-entrance</suffix>
            <url>rtsp://admin:mypassword@192.168.1.64:554/Streaming/Channels/101</url>
            <transfer>TCP</transfer>
            <ondemand>1</ondemand>
        </proxy>
    </application>
</config>

Step 6: Launch Portable RTC and Verify

  1. Save the portablertc.cfg file in the Portable RTC working directory.
  2. Ensure the signal server (SignalServer.exe) is running and reachable at the address specified in <ws_signal_server>.
  3. Launch the Portable RTC executable. It will read the configuration, start its HTTP server, and connect to the signal server via WebSocket.
  4. Check the logs (with <log_enable>1</log_enable> and <log_level>1</log_level>) for:
    • A successful connection to the signal server at the WebSocket address.
    • Registration of the device with the signal server (using the <device_name>).
    • Successful registration of each proxy suffix with the signal server.

Step 7: Access the Camera Stream in a Browser

Once both the signal server and Portable RTC are running, you can view the camera feed in any modern browser.

The signal server's built-in HTTP server (port 8080, or HTTPS port 5443) serves the WebRTC player page. Access a stream using the following URL format:

WebRTC Stream URL
# HTTP (unencrypted)
http://SIGNAL_SERVER_IP:8080/webrtc?streamid=APP_NAME/STREAM_SUFFIX

# HTTPS (encrypted)
https://SIGNAL_SERVER_IP:5443/webrtc?streamid=APP_NAME/STREAM_SUFFIX

For the configuration in this guide, open the following URL in Chrome, Firefox, Edge, or Safari:

Example: View Front Entrance Camera
http://192.168.3.36:8080/webrtc?streamid=myapp/front-entrance

URL parameter breakdown:

Component Value Source
SIGNAL_SERVER_IP:8080 The host and port of the signal server signalserver.cfg<http_port>
/webrtc Fixed path for the built-in WebRTC player page Served by the signal server
streamid= Query parameter identifying which stream to play Format: [app]/[stream]
myapp The application name portablertc.cfg<application><name>
front-entrance The stream suffix portablertc.cfg<proxy><suffix>

The browser will load the WebRTC player page, establish a WebSocket connection to the signal server for signaling, and negotiate a peer connection with Portable RTC. The live RTSP camera feed will appear in the browser window within a few seconds. No plugins are required.

Output Encoding Parameters

Each <proxy> can specify its own <output> parameters to control the video and audio encoding for the WebRTC stream. If not specified, the proxy inherits the application-level default output settings.

Parameter Values Recommendation
<video><codec> H264 or H265 H264 for maximum browser compatibility. H.265 browser support is limited.
<video><width> Pixel width. Leave empty or 0 for original. Leave empty to preserve the camera's native resolution.
<video><height> Pixel height. Leave empty or 0 for original. Leave empty for native. Reduce for bandwidth-constrained links.
<video><framerate> Frames per second. Leave empty for original. 15 for surveillance, 25 for live events.
<video><bitrate> kb/s. 0 for auto-calculation. 2048 for 1080p, 4096 for high-detail content. Set 0 to let the engine auto-calculate.
<audio><codec> G711A, G711U, or OPUS OPUS for best quality and browser compatibility. Use G711A if the camera's original audio must be preserved without transcoding.
<audio><samplerate> Hz. 8000, 16000, 44100, 48000 48000 for OPUS; 8000 for G711.
<audio><channels> 1 (mono) or 2 (stereo) 1 for surveillance; 2 for music or multimedia.

Troubleshooting

Issue Possible Cause Resolution
Portable RTC fails to connect to signal server SignalServer.exe not running, wrong IP/port in <ws_signal_server>, or firewall blocking port 8080. Verify SignalServer.exe is running. Check the WebSocket address in <ws_signal_server> matches the signal server's IP and HTTP port. Ensure port 8080 is reachable from the Portable RTC host.
Browser shows blank page at /webrtc URL The signal server's HTTP server (port 8080) is not running or not reachable from the browser. Verify SignalServer.exe is running and its <http_enable> is 1. Test by opening http://signal-server-ip:8080 in the browser — the root page should respond. Ensure the browser can reach the signal server IP.
No video appears in browser RTSP URL is incorrect, camera requires authentication but credentials are missing, or the RTSP stream is not accessible. Test the RTSP URL with VLC Media Player first: Media > Open Network Stream. If VLC cannot play it, neither can Portable RTC. Verify camera IP, port, and credentials in the <proxy> config.
Video is choppy or freezes Network packet loss on the RTSP source, insufficient bandwidth, or aggressive encoding settings. Use <transfer> set to TCP for the RTSP transport. Reduce <bitrate> and <framerate> in the proxy output settings. Check for network congestion on the camera link.
Browser shows "ICE connection failed" The browser and Portable RTC cannot establish a direct peer connection due to NAT or firewall restrictions. Ensure both the browser client and the signal server are on the same network for initial testing. For WAN access, configure STUN/TURN servers in the <ice_servers> section of signalserver.cfg.
Stream works on local network but not remotely ICE cannot establish a connection because the browser is on a different network and the NAT type blocks direct connection. Configure a TURN server in signalserver.cfg under <ice_servers> to relay media when direct peer connection fails. Format: turn:user:pass@ip:port.
Camera stream times out after a few minutes The RTSP session has expired due to camera-side session timeout. Most cameras allow the RTSP session timeout to be configured. Increase the timeout on the camera side, or use <ondemand> mode so the session is re-established on each browser request.
Portable RTC log shows "RTSP 401 Unauthorized" RTSP credentials are incorrect or missing. Check <user> and <pass> in the proxy configuration. Verify that the credentials work by testing the RTSP URL directly in VLC using the rtsp://user:pass@ip/path format.

Best Practices

  • Use TCP for RTSP Transport: Set <transfer> to TCP for all RTSP proxies. TCP guarantees reliable delivery of video frames and avoids the packet loss and out-of-order issues common with UDP-based RTSP over congested networks.
  • Enable On-Demand Mode: Set <ondemand> to 1 for all proxies. This prevents Portable RTC from maintaining idle RTSP connections when no one is watching, saving camera resources and network bandwidth.
  • Use Descriptive Suffix Names: Choose meaningful <suffix> values like front-entrance or warehouse-east. These appear in the streamid URL parameter and are visible to users selecting streams.
  • Test RTSP URLs with VLC First: Before configuring a proxy in Portable RTC, validate the RTSP URL with VLC Media Player or ffplay. If a generic RTSP client cannot play the stream, Portable RTC will also fail.
  • Start with Default Output Settings: Begin with empty output parameters to use the camera's native encoding. Only override <width>, <height>, or <bitrate> when you need to reduce bandwidth or adjust for browser display constraints.
  • Deploy Signal Server Close to Portable RTC: For minimum signaling latency, run SignalServer.exe on the same machine or same LAN as Portable RTC. The browser client connects to the signal server independently and does not need direct network access to Portable RTC.
  • Configure ICE Servers for WAN Access: If browsers need to access streams from outside the local network, add STUN/TURN server URLs in the <ice_servers> section of signalserver.cfg. This enables NAT traversal for remote viewers.
  • Secure Production Deployments: In production, enable HTTPS on the signal server (<https_enable>1</https_enable>), configure certificates, and use https://ip:5443/webrtc?streamid=app/stream for browser access. Enable <need_auth> in portablertc.cfg and change default credentials.