Docs/Stream/Quickstart & Setup
Interactive Live Video & WebSockets

Quickstart: Stream in under 5 minutes

Learn how to generate a secure stream key, ingest video from OBS or SRT, embed the sub-second WebRTC viewer, and connect to the real-time moderated chat system.

⚡ Sub-Second WebRTC

Ultra-low latency SFU delivery for interactive audiences, with automated AAC-to-Opus audio transcoding.

🛡️ Zero-Trust Security

JWT validation via JWKS, Redis token-binding against IP and browser fingerprints, plus stream-wide bans.

📼 Automated DVR

Lossless FFmpeg stream capture auto-uploaded to Amazon S3 or Google Drive with tenant isolation.

1Provision a Stream & Stream Key

Create a new live stream instance using your tenant admin API key. The response returns your stream ID, ingest URLs, and private Stream Key.


Provision Live StreamAuth

Provision a live stream channel with transcoding and recording options.

Payload Example

{
  "title": "Townhall Q3 2026",
  "auto_record": true,
  "geo_block_regions": ["KP", "IR"],
  "chat_enabled": true
}

Status Codes

  • Name
    201
    Type
    HTTP
    Description
    Stream channel provisioned successfully
  • Name
    401
    Type
    HTTP
    Description
    Unauthorized
Request
POST/v1/stream/channels
Response 201

2Configure OBS or Ingest Encoders

Open OBS Studio (or your hardware encoder like ATEM Mini, vMix, or Teradek) and configure the streaming destination:

ServiceCustom...
Server URLrtmp://stream.apis.vyntech.com.au:1935/live
Stream Keyvyn_live_4f89d3a7710c598a2119b76

Recommended Encoder Output Settings:

  • Video Codec: H.264 (AVC) — Baseline or Main profile
  • Keyframe Interval: 2 seconds (strictly enforced for sub-second WebRTC & HLS chunking)
  • Audio Codec: AAC (Transcoded in real-time to Opus for WebRTC viewers)
  • Rate Control: CBR (Constant Bitrate) with 2500–6000 kbps

3Embed Low-Latency WebRTC Viewer

Viewers authenticate using a Zero-Trust JWT signed by your tenant IDP (https://id.vyntech.com.au). The client exchanges an SDP Offer with the Vyntech WebRTC SFU to begin playback in under 350ms:

import { useEffect, useRef } from "react";

export function StreamPlayer({ streamId, viewerJwt, fingerprint }) {
  const videoRef = useRef(null);

  useEffect(() => {
    async function initWebRTC() {
      const pc = new RTCPeerConnection({
        iceServers: [{ urls: "stun:stun.l.google.com:19302" }]
      });

      pc.ontrack = (event) => {
        if (videoRef.current) {
          videoRef.current.srcObject = event.streams[0];
        }
      };

      pc.addTransceiver("video", { direction: "recvonly" });
      pc.addTransceiver("audio", { direction: "recvonly" });

      const offer = await pc.createOffer();
      await pc.setLocalDescription(offer);

      const response = await fetch(`https://stream.apis.vyntech.com.au/api/webrtc/${streamId}/play`, {
        method: "POST",
        headers: {
          "Content-Type": "application/sdp",
          "Authorization": `Bearer ${viewerJwt}`,
          "X-Device-Fingerprint": fingerprint,
        },
        body: offer.sdp,
      });

      const answerSdp = await response.text();
      await pc.setRemoteDescription({ type: "answer", sdp: answerSdp });
    }

    initWebRTC();
  }, [streamId, viewerJwt, fingerprint]);

  return <video ref={videoRef} autoPlay playsInline controls className="w-full rounded-xl bg-black" />;
}

4Connect to Real-Time Moderated Chat

Connect to the distributed chat gateway over secure WebSockets (wss://). The server enforces token binding, rate limits, duplicate filters, and AI toxicity screening:

const socket = new WebSocket(
  `wss://stream.apis.vyntech.com.au/ws/chat?stream_id=${streamId}&token=${viewerJwt}&fingerprint=${fingerprint}`
);

socket.onmessage = (event) => {
  const message = JSON.parse(event.data);
  switch (message.type) {
    case "chat_message":
      console.log(`[${message.author}]: ${message.text}`);
      break;
    case "message_deleted":
      console.log(`Message ${message.message_id} removed by moderator`);
      break;
    case "stream_banned":
      alert("You have been banned from this live stream.");
      break;
  }
};

// Send message
function sendMessage(text) {
  socket.send(JSON.stringify({
    action: "send_message",
    text: text
  }));
}

Explore Further

We use cookies and similar technologies to measure traffic and improve the site. You can choose which categories to allow. Manage Preferences.