In this article, I will explain how to quickly test WebRTC applications and server infrastructure without building client applications, spinning up signaling servers, or manually configuring dozens of settings.
While working on Slyber TURN Server, I realized that this solution alone wasn't enough to address the pain points developers face when testing WebRTC applications, so I created Slyber Inspector. It is a web based tool for testing WebRTC applications directly from the browser. This saves a massive amount of time and frustration because you don't need to write separate client scripts for testing and configuring those is a challenge in itself. Below, I will walk through the methodology for testing WebRTC connections in Slyber Inspector in detail.
You cannot test a TURN or SFU server with standard tools like Postman. When you simply open two tabs of your application on your laptop, the browsers connect directly over the local network. This rarely causes issues, leading the developer to believe everything works fine. In practice, however, around 20 percent of users sit behind NATs or firewalls that block direct connections, making it essential to test an external relay server to route traffic through. And if you need to run twenty simultaneous video calls through such a server or simulate on the fly network switching, you have to spend time writing custom client scripts.
What Needs to Be Tested in WebRTC Applications
To ensure your server configuration is production ready, you need to run through six core scenarios:
- Port availability and strict relay routing. Browsers on the same network usually connect directly, bypassing the server. During testing, you must forcibly disable direct connections and verify that the call routes strictly through your server via UDP, TCP, or secure TLS.
- Protection against unauthorized connections. Third party applications should not be able to route traffic through your server for free. You need to test both authentication methods: when the server statelessly verifies temporary passwords using a shared secret key without a database, and when it checks active users against a list in a Redis database.
- Video and audio quality. You need to verify with your own eyes and ears that the video doesn't freeze, the audio doesn't drop out, and call participants see and hear each other without any channel mix ups.
- Seamless network switching without dropping the call. When someone leaves their home during a call, their phone switches from home Wi Fi to 4G mobile data. You must verify that the server allocates a new pair of ports to the participants on the fly and the conversation continues uninterrupted.
- Instant participant disconnection. If the server operates in tandem with a Redis database and we delete a specific user's key mid call, the server must immediately terminate their session.
- Performance under load. It is important to launch several dozen parallel video calls at once to see what throughput the server delivers, whether packets are lost along the way, and how quickly the signal travels from one peer to another on your hosting plan.
Two Levels of Testing From Console to Browser
In the Slyber ecosystem, testing is divided into two stages. The first stage is executed directly in the server terminal via the doctor and bench utilities built into the Slyber TURN Server binary itself.
The slyber_turn doctor command checks the node configuration and HTTP API protection, verifies the external IP address via public STUN servers, and performs a test port allocation. The slyber_turn bench command spins up a thread pool and exchanges UDP packets between them using the binary SLYB protocol with nanosecond timestamps, calculating throughput, packet loss, and jitter according to RFC 3550.
While console utilities quickly verify the OS network core and socket settings, Slyber Inspector is used to test the full browser WebRTC stack, including codecs, encryption, and signaling.
On the main screen of Slyber Inspector, you can switch between three ecosystem modules:
- Slyber TURN Server module: Handles relay candidate verification, video stream throughput testing, on the fly route switching, and Redis key management.
- Slyber SFU Server module: Tests video conference routing, Simulcast layer switching, and cascaded rooms.
- Slyber Signaling Server module: Tests SDP message exchange speed, event delivery latency, and room state under concurrent load.
All interface operations happen within a single server. The web interface communicates with the inspector's internal backend to verify a specific server and prepare keys. When a test pair is launched, the built in WebSocket signaling node connects two independent RTCPeerConnection objects directly inside a single open browser tab. Both peers capture different video clips and audio tracks from a local pool and stream them to each other strictly through the external server, while the telemetry collector outputs the bitrate, volume of transferred data, and latency for each direction every second.
Installing Slyber Inspector in Docker
For this demonstration, let's deploy Slyber TURN Server and Slyber Inspector on a basic Ubuntu virtual machine with a single core CPU.
First, we pull the TURN server image, generate a random secret key, run the container with a port pool from 50,000 to 50,100, and immediately run the doctor check. There is no need for complicated setup simply enter the command below and everything will be installed automatically:
docker pull ghcr.io/slyber-app/slyber-turn-server:latest docker rm -f slyber_turn 2>/dev/null || true GEN_SECRET=$(head -c 16 /dev/urandom | od -An -tx1 | tr -d ' \n') docker run -d \ --name slyber_turn \ --restart unless-stopped \ -p 3478:3478/udp \ -p 3478:3478/tcp \ -p 8080:8080/tcp \ -p 50000-50100:50000-50100/udp \ -e PUBLIC_IP="auto" \ -e REALM="turn.local" \ -e AUTH_MODE="secret" \ -e TURN_SECRET="${GEN_SECRET}" \ -e RELAY_MIN_PORT=50000 \ -e RELAY_MAX_PORT=50100 \ ghcr.io/slyber-app/slyber-turn-server:latest && \ sleep 1 && \ docker exec slyber_turn slyber_turn doctor && \ HOST_IP=$([ -n "${SSH_CONNECTION:-}" ] && curl -fsSL4 --max-time 2 ifconfig.me 2>/dev/null || echo 127.0.0.1) && \ echo " TURN / STUN URI : turn:${HOST_IP}:3478 (UDP/TCP)" && \ echo " HTTP API URL : http://${HOST_IP}:8080" && \ echo " Realm : turn.local" && \ echo " Auth Mode : secret (TURN_SECRET=${GEN_SECRET})" && \ echo " Test Creds API : curl -s \"http://${HOST_IP}:8080/api/turn-credentials?user_id=dev\" && echo" && \ echo " Run Benchmark : docker exec slyber_turn slyber_turn bench -clients 20 -duration 5s" && \ echo " Live Logs : docker logs -f slyber_turn" && \ echo "--------------------------------------------------" After launching, the console outputs a summary with the server's external IP address, port 3478, and the generated TURN_SECRET key.
With the second command, we spin up the Slyber Inspector container:
docker pull ghcr.io/slyber-app/slyber-inspector:latest docker rm -f slyber_test 2>/dev/null || true PORT=8095; while (ss -ltn 2>/dev/null || lsof -iTCP -sTCP:LISTEN -P -n 2>/dev/null) | grep -q ":${PORT}\b"; do PORT=$((PORT+1)); done; \ docker run -d \ --name slyber_test \ --restart unless-stopped \ -p "${PORT}:8095" \ -e LISTEN_ADDR="0.0.0.0:8095" \ ghcr.io/slyber-app/slyber-inspector:latest && \ HOST_IP=$([ -n "${SSH_CONNECTION:-}" ] && curl -fsSL4 --max-time 2 ifconfig.me 2>/dev/null || echo 127.0.0.1) && \ echo "==> Open Slyber Inspector: http://${HOST_IP}:${PORT}" The script finds an available port starting from 8095, launches the container, and outputs the link to the web interface.
Configuring Test Parameters in Slyber Inspector
In the top right corner of the interface, there are four summary indicators that update every second.
- Active pairs: Displays the number of peer pair cards created in the current session.
- Relay sessions: Counts active relay connections that have completed candidate negotiation. Each pair yields two relay sessions.
- Total throughput: Shows the combined incoming bitrate of all active calls in kilobits or megabits per second.
- Relayed traffic: Tracks the total volume of media data in megabytes that has passed through the TURN server since the pairs were launched.
All entered settings and uploaded videos are saved in the browser's local storage. The Reset saved state button in the header lets you completely reset settings and clear the video database.
In the left panel, Turn server configuration, you configure the connection to the target node under test.
- Turn server address: Accepts the host and port of the target server (127.0.0.1:3478 by default). Enter the external IP of our virtual machine here.
- Realm domain: Sets the authorization domain on the server (turn.local).
- Transport protocol: Switches the transport between UDP, TCP, TLS, and mixed mode.
- Ice transport policy: Defaults to the "relay only" mode. It forcibly disables direct P2P connections and guarantees that all traffic flows exclusively through the TURN server.
- Credential ttl: Sets the lifetime of temporary keys in seconds (3600 by default).
The Authentication mode toggle switches the credential verification mode between "secret" and "redis".
In "secret" mode, a panel with a static key opens. Paste the TURN_SECRET variable from the terminal into the Shared secret key field. In the Credential provisioning dropdown, select the method for generating the temporary HMAC SHA1 password. The inspector can calculate it locally using the shared key or request it via HTTP from the TURN server's own /api/turn credentials endpoint, whose address is specified in the Turn http api url field.
Selecting "redis" mode opens a Redis connection form with fields for Redis address or url, Redis acl username, Redis password, and Redis db index. Whenever a new pair is created in this mode, Slyber Inspector automatically generates unique logins (such as p3_u1_da37e6 and p3_u2_da37e6), calculates their MD5 hash according to the RFC 5389 standard, and writes the keys directly to the Redis database with the specified TTL.
The Verify server connection button in the top right corner of the panel sends a test STUN Binding packet to the specified address, checks the availability of the key store, and outputs the server's response time in milliseconds.
Generating Media Streams and Spawning Pairs
The right panel, Media pool & pair generator, manages video sources and launches load testing pairs.
Using the Upload video files button, you can upload your own video clips from your disk, which will be saved into the browser's built in IndexedDB database. If you need to run a quick test without local files, the Add 4 demo streams button immediately creates four synthetic streams featuring animated Canvas graphics and audio tone generators ranging from 220 to 520 Hz. The Clear pool button empties the video pool.
The Pairs to spawn field specifies the number of pairs to launch simultaneously, from 1 to 50. When you click Spawn pairs, the algorithm randomly selects two different videos from the pool for each pair so that the peers transmit different streams to one another. Next to it are buttons for quickly adding one more pair (+1 pair), muting audio across all players (Mute all), and stopping all active calls (Terminate all).
Inspecting Active Connections and Live Stress Testing
Each launched pair is displayed at the bottom as a separate card with two symmetrical participant windows: Peer 1 on the left and Peer 2 on the right. Inside the card, all telemetry for that specific call is gathered.
- Session state indicator: The colored dot next to the pair number shows the session status. It lights up yellow during port allocation or session restart, green during active video and audio transmission, and red if the connection drops.
- Relay address badge: The green badge in the top right corner of each peer displays the actual external IP address of the TURN server and the UDP relay port assigned to that participant—for example, "relay 89.111.175.67:50012" for the first peer and "relay 89.111.175.67:50013" for the second.
- Channel verification: Above the players, the Sending to peer line indicates the name of the outgoing file, while Receiving on screen from peer displays the name of the incoming stream for visual channel verification.
- Real time metrics: Above the right side of the player, the current stream bitrate in kilobits per second, the volume of received data in megabytes, and the packet round trip time (RTT) in milliseconds update every second.
Below each participant's player are buttons for testing connection behavior on the fly:
- Unmute peer audio / Mute peer audio: Enables or disables listening to the selected peer's incoming audio track via the Web Audio API.
- Ice restart: Triggers candidate renegotiation by calling pc.createOffer({ iceRestart: true }) without dropping the call. The card's indicator turns yellow during the switch, the server allocates a new pair of UDP relay ports, the numbers on the green badges update, and the video continues streaming over the new route.
- Revoke redis key: Appears when testing in "redis" mode. With a single click, it deletes a specific participant's key from the Redis database, allowing you to immediately test how the server and client react to access revocation.
- Remove pair: Closes both WebRTC connections, stops stream capture, closes signaling sockets, and removes the pair card.
Even on a virtual machine with a single CPU core, the server effortlessly handles multiple parallel video call pairs with zero packet loss and minimal latency.




