Stop fighting with firewalls and NAT. Access your RTSP streams from anywhere with reliable cloud endpoints.
Traditional approaches are complex, unreliable, and insecure
Corporate firewalls block incoming RTSP connections. Port forwarding is often impossible or forbidden by IT policies.
Cameras behind NAT are unreachable from the internet. Dynamic IPs change constantly, breaking your integrations.
VPNs, reverse proxies, STUN/TURN servers - the traditional solutions are complex and fragile.
Everything you need to access RTSP streams programmatically
No transcoding, no protocol conversion. Pure RTSP passthrough with minimal latency. Works with OpenCV, FFmpeg, VLC, and any RTSP client.
From localhost to cloud in 30 seconds. Run our agent, and your cameras are instantly accessible from anywhere.
Token-based authentication, encrypted tunnels, and granular access controls. Your streams are protected end-to-end.
Organize cameras by location, purpose, or project. Manage hundreds of streams through a single dashboard.
Add object detection, motion alerts, and analytics without changing your code. Process streams with YOLO, TensorFlow, or custom models.
RESTful API for camera management. Provision new streams, update configurations, and monitor health programmatically.
Three simple steps to global camera access
Deploy our lightweight agent on your local machine or remote server. Available for both Windows and Linux.
Open the Web UI and simply paste your local RTSP URLs. The agent handles a secure outbound connection to TheRelay Cloud.
Use the provided cloud URLs in your applications. Standard RTSP protocol, no special libraries needed.
From download to live video in seconds—no hoops, no hassle.
Launch once and you’re done. The agent starts immediately, keeps running after reboot, and quietly looks after itself—so you can focus on your cameras, not your infrastructure.
Most setups complete in seconds; actual time depends on network speed and device performance.
The service registers to your organization, stays healthy in the background, and restarts automatically. No firewall juggling or static IPs required—the connection is secure and outbound-only.
Works across popular distros and architectures. Most installs finish in seconds.
Works with your existing tools and libraries
import os
import cv2
RELAY_TOKEN = os.getenv('RELAY_TOKEN')
RELAY_ORG_ID = os.getenv('RELAY_ORG_ID')
cam = 'entrance-cam'
# Your TheRelay stream URL (with your auth token)
stream_url = f"rtsp://stream.therelay.net/{RELAY_TOKEN}/{RELAY_ORG_ID}/{cam}"
# Open the stream exactly like a local camera
cap = cv2.VideoCapture(stream_url)
if not cap.isOpened():
raise RuntimeError("Failed to open stream")
while True:
ok, frame = cap.read()
if not ok:
break
# Your CV/AI processing here
results = detect_objects(frame)
cv2.imshow("TheRelay Stream", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cap.release()
import { useEffect, useRef } from "react";
type Props = { url: string };
export function SimpleWHEPPlayer({ url }: Props) {
const videoRef = useRef<HTMLVideoElement>(null);
useEffect(() => {
const pc = new RTCPeerConnection();
pc.addTransceiver("video", { direction: "recvonly" });
pc.ontrack = (e) => { if (videoRef.current) videoRef.current.srcObject = e.streams[0]; };
(async () => {
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
const res = await fetch(url, { method: "POST", headers: { "content-type": "application/sdp" }, body: offer.sdp });
const answer = await res.text();
await pc.setRemoteDescription({ type: "answer", sdp: answer });
})();
return () => pc.close();
}, [url]);
return <video ref={videoRef} autoPlay playsInline muted style={{ width: "100%", background: "#000" }} />;
}
// Usage:
// e.g., app/page.tsx
import { SimpleWHEPPlayer } from "./SimpleWHEPPlayer";
export default function Page() {
const token = process.env.RELAY_TOKEN!;
const org = process.env.RELAY_ORG_ID!;
const cam = "exit-cam-06";
const url = `https://webrtc.therelay.net/${token}%2F${org}%2F${cam}/whep`;
return <SimpleWHEPPlayer url={url} />;
}
package main
import (
"fmt"
"os"
"gocv.io/x/gocv"
)
func main() {
token := os.Getenv("RELAY_TOKEN")
org := os.Getenv("RELAY_ORG_ID")
cam := "warehouse-01"
url := fmt.Sprintf("rtsp://stream.therelay.net/%s/%s/%s", token, org, cam)
fmt.Println("Opening:", url)
webcam, err := gocv.OpenVideoCapture(url)
if err != nil { panic(err) }
defer webcam.Close()
window := gocv.NewWindow("TheRelay Stream")
defer window.Close()
img := gocv.NewMat()
defer img.Close()
for {
if ok := webcam.Read(&img); !ok || img.Empty() {
break
}
// Your CV/AI processing here
window.IMShow(img)
if window.WaitKey(1) == 'q' {
break
}
}
}
// src/main.rs
use opencv::{highgui, prelude::*, videoio, Result};
use std::env;
fn main() -> Result<()> {
let token = env::var("RELAY_TOKEN")?;
let org = env::var("RELAY_ORG_ID")?;
let cam = "exit-cam-02";
let url = format("rtsp://stream.therelay.net/{}/{}/{}", token, org, cam);
println!("Opening: {}", url);
let mut cap = videoio::VideoCapture::from_file(&url, videoio::CAP_FFMPEG)?;
if !videoio::VideoCapture::is_opened(&cap)? {
panic!("Failed to open stream");
}
highgui::named_window("TheRelay Stream", highgui::WINDOW_AUTOSIZE)?;
loop {
let mut frame = Mat::default();
if !cap.read(&mut frame)? || frame.empty() {
break;
}
// Your CV/AI processing here
highgui::imshow("TheRelay Stream", &frame)?;
if highgui::wait_key(1)? == 'q' as i32 {
break;
}
}
Ok(())
}
From security to AI, TheRelay powers critical applications
No credit card required. Full access to all features.
AI SPOT uses TheRelay to connect any camera to their web platform—securely and with low latency—no port forwarding or VPNs. Alerts are delivered directly on WhatsApp.