<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[VideoSDK - Updates about video APIs]]></title><description><![CDATA[Get all the updates about SDK and APIs, latest release, news and many more.]]></description><link>https://www.videosdk.live/</link><image><url>https://www.videosdk.live/favicon.png</url><title>VideoSDK - Updates about video APIs</title><link>https://www.videosdk.live/</link></image><generator>VideoSDK Blog</generator><lastBuildDate>Thu, 08 Oct 2026 22:54:44 GMT</lastBuildDate><atom:link href="https://www.videosdk.live/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Product Updates - September 2026: New Session Details UI, Reliable Flutter PubSub, and JS SDK Improvements]]></title><description><![CDATA[September focuses on visibility and reliability: a redesigned Session Details experience for faster debugging, stronger Flutter PubSub behavior under real-world conditions, JS SDK runtime improvements, and new resources for building with VideoSDK.]]></description><link>https://www.videosdk.live/blog/product-updates-september-2026</link><guid isPermaLink="false">6ac63ae9b3240feb748ca21a</guid><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 08 Oct 2026 06:26:57 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/10/monthly-update-september-blog-banner.png" medium="image"/><content:encoded><![CDATA[
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Product Updates - September 2026: New Session Details UI, Reliable Flutter PubSub, and JS SDK Improvements</title>
  <style>
    :root {
      --primary: #A497D9;
      --bg: #050608;
      --card-bg: #111217;
      --text-main: #E0E0E0;
      --text-muted: #A0A0A0;
      --border: #22242C;
    }

    body {
      font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      line-height: 1.7;
      color: var(--text-main);
      background-color: var(--bg);
      margin: 0;
      padding: 0;
    }

    .container {
      max-width: 850px;
      margin: 0 auto;
      padding: 60px 20px;
    }

    header {
      text-align: left;
      margin-bottom: 60px;
    }

    h2 {
      font-size: 28px;
      color: #FFFFFF;
      margin-top: 40px;
      padding-bottom: 10px;
      border-bottom: 1px solid var(--border);
      margin-bottom: 20px;
    }

    h3 {
      font-size: 22px;
      color: #FFFFFF;
      margin-top: 35px;
    }

    p {
      margin-bottom: 16px;
    }

    strong,
    b {
      color: #FFFFFF;
    }

    ul,
    ol {
      margin-bottom: 20px;
      padding-left: 20px;
    }

    li {
      margin-bottom: 10px;
    }

    .highlight {
      color: var(--primary);
      font-weight: 600;
    }

    a {
      color: var(--primary);
      text-decoration: none;
    }

    a:hover {
      text-decoration: underline;
    }

    .ic {
      font-family: 'Fira Code', 'Cascadia Code', 'Consolas', monospace;
      font-size: 13.5px;
      color: #A497D9;
      font-weight: 700;
    }

    .card {
      background-color: var(--card-bg);
      border-radius: 12px;
      padding: 24px;
      margin: 24px 0;
    }

    .img-container {
      margin: 20px 0;
      text-align: center;
    }

    .img-container img {
      width: 100%;
      height: auto;
      border-radius: 8px;
    }

    .img-caption {
      margin-top: 8px;
      color: var(--text-muted);
      font-size: 13px;
      text-align: left;
    }

    .cta-button {
      background-color: var(--primary);
      color: #000000;
      padding: 6px 20px;
      border-radius: 6px;
      font-size: 15px;
      font-weight: bold;
      display: inline-block;
      text-decoration: none;
    }

    .cta-box {
      text-align: left;
      background: linear-gradient(135deg, #111217 0%, #1a1b23 100%);
      padding: 30px;
      border-radius: 12px;
      border: 1px solid var(--primary);
      margin: 60px 0;
    }

    hr {
      border: 0;
      border-top: 1px solid var(--border);
      margin: 40px 0;
    }

    @media (max-width: 600px) {
      .container {
        padding: 40px 15px;
      }
    }
  </style>
</meta></meta></head>

<body>
  <div class="container">

    <header>
      <img src="https://assets.videosdk.live/static-assets/ghost/2026/10/monthly-update-september-blog-banner.png" alt="Product Updates - September 2026: New Session Details UI, Reliable Flutter PubSub, and JS SDK Improvements"/><p style="font-size:18px;color:#A0A0A0;margin:0;">
        September 2026 Updates: Deeper session visibility, more predictable messaging, and practical improvements across the developer workflow.
      </p>
    </header>

    <p>
      September's updates focus on a practical part of running real-time applications in production:
      understanding what happened during a session and making application behavior more predictable when conditions are not ideal.
    </p>

    <p>
      The Dashboard now provides a richer <strong>Session Details</strong> experience for investigating participant activity,
      network conditions, and media quality. <strong>Flutter SDK v4.0.0 and v4.0.1</strong> strengthen PubSub delivery and
      failure handling, while <strong>JS SDK v1.2.0</strong> improves WebView behavior and runtime observability.
      We have also expanded our resources for AI-assisted development and added new implementation tutorials across multiple SDKs.
    </p>


    <h2>A New Session Details UI</h2>

    <p>
      When one participant reports poor video quality or a session behaves differently than expected, the first problem is often
      not fixing it. It is figuring out <strong>what actually happened</strong>.
    </p>

    <p>
      The redesigned <strong>Session Details UI</strong> gives developers a clearer way to inspect a session from start to finish.
      The updated experience brings session-level information, participant activity, network events, and media statistics into a
      more useful debugging workflow.
    </p>

    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/sept_session_overview_df12a95430.png" alt="Product Updates - September 2026: New Session Details UI, Reliable Flutter PubSub, and JS SDK Improvements">
      <p class="img-caption">
        Session Overview combines session metadata with participant-level activity across the call.
      </p>
    </img></div>

    <h3>Follow participant activity on the timeline</h3>

    <p>
      The improved participant timeline makes it easier to understand what each participant experienced throughout the session.
      Join and leave events sit alongside network and media-related activity so developers can correlate user-reported problems
      with changes occurring inside the call.
    </p>

    <p>
      Network events such as bandwidth limitations and congestion can also be inspected directly from the timeline.
      Tooltips provide additional context around these events, helping developers understand when an issue appeared and when the
      underlying condition recovered.
    </p>

    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/sept_participant_timeline_8423ae0149.png" alt="Product Updates - September 2026: New Session Details UI, Reliable Flutter PubSub, and JS SDK Improvements">
      <p class="img-caption">
        Timeline events expose participant activity and network conditions in the context of the session.
      </p>
    </img></div>

    <h3>Inspect sender and receiver statistics together</h3>

    <p>
      The updated <strong>Session Stats</strong> view provides deeper media-level visibility across audio, video,
      screen-share audio, and screen-share video.
    </p>

    <p>
      For video sessions, developers can inspect signals including:
    </p>

    <ul>
      <li><strong>Round-trip time (RTT)</strong></li>
      <li><strong>Sent and received bitrate</strong></li>
      <li><strong>Bitrate by simulcast layer</strong></li>
      <li><strong>Jitter</strong></li>
      <li><strong>Packet loss</strong></li>
      <li><strong>Frames per second</strong></li>
      <li><strong>Resolution</strong></li>
      <li><strong>Freezes and pauses</strong></li>
    </ul>

    <p>
      Graph interactions have also been improved. Hovering over a point now surfaces detailed sender and receiver information for
      that moment instead of requiring developers to interpret the lines in isolation.
    </p>

    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/sept_session_hover_a92884d3ad.png" alt="Product Updates - September 2026: New Session Details UI, Reliable Flutter PubSub, and JS SDK Improvements">
      <p class="img-caption">
        Hover states surface sender and receiver metrics at a specific point in the session.
      </p>
    </img></div>

    <p>
      Additional explanatory tooltips throughout the interface make the metrics easier to interpret without leaving the debugging
      workflow. The result is a more useful starting point when investigating intermittent network problems, media degradation,
      or participant-specific quality issues.
    </p>


    <h2>Flutter SDK v4.0.0 &amp; v4.0.1: More Reliable PubSub</h2>

    <p>
      PubSub is frequently used for chat, reactions, application state, control messages, and other events that accompany the
      media session. The difficult cases appear when message traffic increases, a subscriber falls behind, or the network briefly
      disconnects.
    </p>

    <p>
      <strong>Flutter SDK v4.0.0</strong> adds more predictable behavior for those conditions.
      Live messages can now be delivered in batches, historical messages can stream progressively, dropped messages are surfaced
      instead of disappearing silently, and subscriptions remain active across reconnects.
    </p>

    <p>
      Applications can configure the behavior per topic using the new
      <span class="ic">PubSubSubscribeOptions</span>.
    </p>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">
        dart
      </div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">room.pubSub.subscribe(
  "CHAT",
  onMessageReceived,
  options: const PubSubSubscribeOptions(
    oldMessageLimit: 100,
    realtimeOverflow: PubSubRealtimeOverflow.queue,
    maxQueue: 70,
  ),
  onOldMessagesReceived: (messages, isLast) {
    // Historical messages, oldest first
  },
  onBatchReceived: (messages) {
    // Batch of new messages
  },
  onMessageDrop: (count) {
    // Number of messages that could not be delivered
  },
);</pre>
    </div>

    <p>
      The overflow strategy can be selected based on the type of event being delivered.
      <span class="ic">queue</span> temporarily holds messages for a subscriber that falls behind, while
      <span class="ic">drop</span> is appropriate when stale data no longer has value, such as typing indicators.
    </p>

    <h3>Failures are explicit now, too</h3>

    <p>
      <strong>Flutter SDK v4.0.1</strong> extends the reliability work by making unsuccessful PubSub operations visible to
      application code.
    </p>

    <p>
      <span class="ic">publish()</span>, <span class="ic">subscribe()</span>, and
      <span class="ic">unsubscribe()</span> now throw a <span class="ic">PubSubException</span> when the requested operation
      does not take effect. This removes a particularly difficult failure mode where a rejected publish could previously appear
      indistinguishable from a successfully delivered message.
    </p>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">
        dart
      </div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">try {
  await room.pubSub.publish("CHAT", text);
} on PubSubException catch (e) {
  showToast(e.message);
}</pre>
    </div>

    <p>
      Invalid subscription configurations are also rejected before the request is sent. This includes negative message limits,
      invalid queue sizes, and combinations that cannot work together.
    </p>

    <div class="card" style="border-left:4px solid #E06C75;background-color:#16171e;padding:20px 24px;margin:24px 0;">
      <p style="margin:0;color:#E0E0E0;font-size:14px;">
        <strong style="color:#E06C75;">⚠️ Migration Note:</strong>
        Existing Flutter applications should review PubSub call sites and explicitly handle asynchronous failures.
        Unawaited calls such as direct <span class="ic">publish()</span> calls inside UI callbacks can otherwise surface as
        unhandled async errors at runtime.
        See the
        <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank" style="color:var(--primary);text-decoration:underline;">
          Flutter SDK release notes
        </a>
        for the complete version details.
      </p>
    </div>


    <h2>JS SDK v1.2.0: WebView and Runtime Improvements</h2>

    <p>
      <strong>JS SDK v1.2.0</strong> includes a set of practical fixes for browser and embedded WebView applications.
    </p>

    <p>
      <span class="ic">participant.captureImage()</span> now works correctly in WebView environments where media playback
      requires a user gesture. We also fixed an issue where <span class="ic">changeWebcam</span> could attempt to disable
      the webcam even when no webcam producer was active.
    </p>

    <p>
      The release also includes several internal runtime improvements:
    </p>

    <ul>
      <li>
        Webcam device enumeration is now cached and refreshed only when the operating system emits a
        <span class="ic">devicechange</span> event.
      </li>
      <li>
        Additional tracing has been added around <span class="ic">participant.captureImage()</span> to improve debugging
        and observability.
      </li>
      <li>
        Proactive pong handling helps keep the server aware that a client remains active when packets are already being received
        within the expected ping interval.
      </li>
    </ul>

    <p>
      Together, these changes improve behavior and observability in browser and embedded WebView environments.
    </p>

    <p>
      <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank">
        View JS SDK release notes →
      </a>
    </p>


    <h2>Build with VideoSDK Using AI-Assisted Development Tools</h2>

    <p>
      We have also expanded the documentation available for developers using AI coding tools as part of their VideoSDK workflow.
    </p>

    <p>
      The new resources cover four entry points:
    </p>

    <ul>
      <li>
        <a href="https://docs.videosdk.live/ai-tools/start-with-ai" target="_blank">
          <strong>Start with AI</strong>
        </a>
        — an introduction to building VideoSDK applications with AI-assisted workflows.
      </li>
      <li>
        <a href="https://docs.videosdk.live/ai-tools/cli/overview" target="_blank">
          <strong>CLI</strong>
        </a>
        — command-line tooling for development workflows.
      </li>
      <li>
        <a href="https://docs.videosdk.live/ai-tools/agent-skill" target="_blank">
          <strong>Skills</strong>
        </a>
        — structured VideoSDK knowledge that can be used by compatible coding agents.
      </li>
      <li>
        <a href="https://docs.videosdk.live/ai-tools/mcp-server" target="_blank">
          <strong>MCP Server</strong>
        </a>
        — VideoSDK context for MCP-compatible development environments.
      </li>
    </ul>

    <p>
      These resources complement the existing SDK documentation by making VideoSDK context easier to bring directly into the
      tools developers use while writing, exploring, and debugging code.
    </p>


    <h2>New Tutorials Across JavaScript, React, React Native, Flutter, Unity, iOS, and Android</h2>

<p>
  We have continued expanding our practical tutorial library around three common real-time application patterns:
  <strong>video calling, audio rooms, and live streaming</strong>.
</p>

<p>
  Here are two recent walkthroughs to get started. You can also explore the full tutorial library across JavaScript, React, React Native, Flutter, Unity, iOS, and Android.
</p>

<h3>Build a Video Calling App with JavaScript</h3>

<div class="img-container" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;">
  <iframe width="560" height="315" src="https://www.youtube.com/embed/98igsjRPg8A" title="Build a Video Calling App with JavaScript using VideoSDK" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0 !important;border-radius:8px;">
  </iframe>
</div>

<h3>Build a Video Calling App with Flutter</h3>

<div class="img-container" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;">
  <iframe width="560" height="315" src="https://www.youtube.com/embed/skF-Ne2HIqs" title="Build a Video Calling App with Flutter using VideoSDK" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" style="position:absolute;top:0;left:0;width:100%;height:100%;border:0 !important;border-radius:8px;">
  </iframe>
</div>

<p>
  The full tutorial set now covers <strong>JavaScript, React, React Native, Flutter, Unity, iOS, and Android</strong>,
  with walkthroughs for video calling, audio rooms, and live streaming across the supported platforms.
</p>

<p>
  Browse the platform playlists:
  <a href="https://www.youtube.com/playlist?list=PLL0ctn32TjoU" target="_blank">JavaScript</a>,
  <a href="https://www.youtube.com/playlist?list=PLRSOsgSEB9W4" target="_blank">React</a>,
  <a href="https://www.youtube.com/playlist?list=PLOOu1ji99lrQ" target="_blank">React Native</a>,
  <a href="https://www.youtube.com/playlist?list=PLI5qWDrssrC8" target="_blank">Flutter</a>,
  <a href="https://www.youtube.com/playlist?list=PLB7-i8h1NVy8" target="_blank">Unity</a>,
  <a href="https://www.youtube.com/playlist?list=PLNuBsOOGlAKQ" target="_blank">iOS</a>,
  and
  <a href="https://www.youtube.com/playlist?list=PLBfjEN-RwEyM" target="_blank">Android</a>.
</p>


    <h2>Other SDK Fixes and Improvements</h2>

    <p>
      Alongside the larger releases, we continued shipping smaller maintenance fixes and improvements across other SDK surfaces.
    </p>

    <p>
      For example, <strong>iOS SDK v3.2.1</strong> includes bug fixes and general improvements without introducing a new
      feature surface.
    </p>

    <p>
      Platform-specific changes can be followed through the individual SDK release notes as they ship.
    </p>


    <h2>✨ Community Spotlight</h2>

<div style="border-left: 3px solid var(--primary); padding-left: 20px; margin-top: 30px; margin-bottom: 30px;">
  <a href="https://videosdk.live/customers/coalasaude" style="font-size: 18px; line-height: 1.5;">
    Explore how Coala Saude reduced medical documentation time by 45% with VideoSDK
  </a>
</div>

<div class="img-container">
  <a href="https://videosdk.live/customers/coalasaude">
    <img src="https://strapi.videosdk.live/uploads/testimonial_sept_update_blog_31bae664ed.png" alt="Product Updates - September 2026: New Session Details UI, Reliable Flutter PubSub, and JS SDK Improvements" style="border: none; box-shadow: none;">
  </img></a>
</div>


<h2>SDK Sketches</h2>

<p>
  Real-time systems tend to look simple when everything is healthy.
  The interesting engineering starts when traffic spikes, networks fluctuate,
  or applications need to explain why an operation did not behave as expected.
</p>

<div class="img-container">
  <img src="https://strapi.videosdk.live/uploads/sdk_sketch_sept_update_blog_9e1d4f5b69.png" alt="Product Updates - September 2026: New Session Details UI, Reliable Flutter PubSub, and JS SDK Improvements">
</img></div>

<p>
  This month's SDK Sketch - How improved Session Details helps developer.
</p>


<h2>September in Review</h2>

<p>
  September's work improves both sides of operating real-time applications:
  understanding what happened during a session and making application behavior
  more predictable when conditions change.
</p>

<p>
  The new Session Details experience brings participant activity, network events,
  and media statistics into a clearer debugging workflow. Flutter PubSub is more
  resilient under load and now exposes unsuccessful operations directly to
  application code. JS SDK improvements address WebView and runtime edge cases,
  while the new AI development resources and implementation tutorials make the
  build side easier to navigate.
</p>


<div class="cta-box">
  <h3 style="margin-top:0;">Build with September's Updates</h3>

  <p>
    Explore the new Session Details experience, review the latest SDK changes,
    and try the updated developer resources.
  </p>

  <a href="https://app.videosdk.live" class="cta-button" style="margin-right:12px;">
    Dashboard
  </a>

  <a href="https://discord.com/invite/Gpmj6eCq5u" class="cta-button">
    Join our Discord
  </a>
</div>

<p style="text-align:center;margin-top:40px;margin-bottom:0;">
  Happy building!<br>
  <strong>Team VideoSDK</strong>
</br></p>

  </div>
</body>
</html>

<!--kg-card-end: html-->
]]></content:encoded></item><item><title><![CDATA[Product Updates - August 2026: React Native v1.0.0, Persistent Media Configuration, and Smarter AI Agent Turn-Taking]]></title><description><![CDATA[August 2026 brings React Native SDK v1.0.0, persistent media configuration across iOS, Android, and Flutter, clearer RTC error handling, smarter AI agent turn-taking, improved pre-call diagnostics, and new developer resources.]]></description><link>https://www.videosdk.live/blog/product-updates-august-2026</link><guid isPermaLink="false">6aa151c4b3240feb748c9c93</guid><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 10 Sep 2026 14:17:58 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/august-update-banner.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/09/august-update-banner.png" alt="Product Updates - August 2026: React Native v1.0.0, Persistent Media Configuration, and Smarter AI Agent Turn-Taking"/><p/>
<!--kg-card-begin: html-->
<!DOCTYPE html>

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>Product Updates - August 2026: React Native v1.0.0, Persistent Media Configuration, and Smarter AI Agent Turn-Taking</title>

  <style>
    :root {
      --primary: #A497D9;
      --bg: #050608;
      --card-bg: #111217;
      --text-main: #E0E0E0;
      --text-muted: #A0A0A0;
      --border: #22242C;
    }

    body {
      font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      line-height: 1.7;
      color: var(--text-main);
      background-color: var(--bg);
      margin: 0;
      padding: 0;
    }

    .container {
      max-width: 850px;
      margin: 0 auto;
      padding: 60px 20px;
    }

    header {
      text-align: left;
      margin-bottom: 60px;
    }

    h2 {
      font-size: 28px;
      color: #FFFFFF;
      margin-top: 40px;
      padding-bottom: 10px;
      border-bottom: 1px solid var(--border);
      margin-bottom: 20px;
    }

    h3 {
      font-size: 22px;
      color: #FFFFFF;
      margin-top: 35px;
    }

    p {
      margin-bottom: 16px;
    }

    strong,
    b {
      color: #FFFFFF;
    }

    ul,
    ol {
      margin-bottom: 20px;
      padding-left: 20px;
    }

    li {
      margin-bottom: 10px;
    }

    a {
      color: var(--primary);
      text-decoration: none;
    }

    a:hover {
      text-decoration: underline;
    }

    .ic {
      font-family: 'Fira Code', 'Cascadia Code', 'Consolas', monospace;
      font-size: 13.5px;
      color: #A497D9;
      font-weight: 700;
    }

    .card {
      background-color: var(--card-bg);
      border-radius: 12px;
      padding: 24px;
      margin: 24px 0;
    }

    .img-container {
      margin: 20px 0;
      text-align: center;
    }

    .img-container img {
      width: 100%;
      height: auto;
      border-radius: 8px;
    }

    .cta-button {
      background-color: var(--primary);
      color: #000000;
      padding: 6px 20px;
      border-radius: 6px;
      font-size: 15px;
      font-weight: bold;
      display: inline-block;
      text-decoration: none;
    }

    .cta-box {
      text-align: left;
      background: linear-gradient(135deg, #111217 0%, #1a1b23 100%);
      padding: 30px;
      border-radius: 12px;
      border: 1px solid var(--primary);
      margin: 60px 0;
    }

    hr {
      border: 0;
      border-top: 1px solid var(--border);
      margin: 40px 0;
    }

    @media (max-width: 600px) {
      .container {
        padding: 40px 15px;
      }
    }
  </style>

</meta></meta></head>

<body>
  <div class="container">

<header>
  <p style="font-size:18px;color:#A0A0A0;margin:0;">
    August 2026 Updates: more predictable media behavior, clearer RTC error handling, a major React Native SDK release, and better turn-taking for real-time AI voice agents.
  </p>
</header>

<p>
  August's releases focused on making real-time applications more predictable across media controls, reconnects, device changes, and AI voice conversations. We shipped <strong>React Native SDK v1.0.0</strong>, expanded persistent media configuration across iOS, Android, and Flutter, improved error handling across the RTC SDK stack, and added new capabilities to the <strong>VideoSDK Agents SDK</strong>.
</p>

<p>
  We also improved pre-call diagnostics, Android build compatibility, Python media support, IoT resources, developer tutorials, and enterprise procurement options through Microsoft and AWS Marketplace.
</p>


<h2>React Native SDK v1.0.0: A Major SDK Update</h2>

<p>
  <strong>React Native SDK v1.0.0</strong> is one of the biggest updates this month, bringing a new PubSub experience, Promise-based SDK methods, typed errors, more predictable media controls, and stronger reconnect handling.
</p>

<h3>More Control Over PubSub</h3>

<p>
  PubSub now gives applications more control when handling high-volume realtime messaging.
</p>

<ul>
  <li><strong>Batched message delivery</strong> with <span class="ic">onBatchReceived</span>.</li>
  <li><strong>Backpressure controls</strong> for applications that need to queue or drop messages under load.</li>
  <li><strong>Message-drop visibility</strong> through <span class="ic">onMessageDrop</span>.</li>
</ul>

<div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
  <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">
    javascript
  </div>
  <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">usePubsub("CHAT",
{
    onMessageReceived: (msg) => {},
    onBatchReceived: (msgs) => {},
    onOldMessagesReceived: (msgs) => {},
    onMessageDrop: (info) => {}
},
{
    realtimeOverflow: "queue",
    maxQueue: 500
}
);</pre> </div>


<h3>Promise-Based APIs and Typed Errors</h3>

<p>
  SDK methods now return Promises, making it easier to handle successful operations and failures directly where the action is triggered.
</p>

<p>
  Errors provide structured information such as <span class="ic">name</span>, <span class="ic">code</span>, and <span class="ic">message</span>, so applications can respond more clearly to invalid states, timeouts, or operations already in progress.
</p>

<div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
  <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">
    javascript
  </div>
  <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">const { enableWebcam } = useMeeting();
try { await enableWebcam(); } 
catch (err){
    console.error({
        name: err.name,
        code: err.code,
        message: err.message
    });
}</pre> </div>


<h3>More Predictable Media Operations</h3>

<p>
  Camera, microphone, and screen-share operations now provide clearer completion and failure behavior. The SDK also adds request timeouts so applications are not left waiting indefinitely when an operation cannot complete.
</p>

<div class="card" style="border-left:4px solid #E06C75;background-color:#16171e;">
  <p style="margin:0;color:#E0E0E0;font-size:14px;">
    <strong style="color:#E06C75;">⚠️ Breaking Change:</strong>
    React Native SDK v1.0.0 moves SDK methods to Promise-based APIs and removes the external video playback APIs
    <span class="ic">startVideo</span>,
    <span class="ic">stopVideo</span>,
    <span class="ic">pauseVideo</span>,
    <span class="ic">resumeVideo</span>, and
    <span class="ic">seekVideo</span>.
  </p>
</div>

<div class="card" style="border:1px solid var(--primary);">
  <h3 style="margin-top:0;color:var(--primary);">Migrating to React Native SDK v1.0.0</h3>
  <p>
    Existing applications should update SDK calls to use <span class="ic">await</span> where required, handle rejected operations with <span class="ic">try/catch</span>, and review any usage of the removed external video playback APIs.
  </p>
  <p style="margin-bottom:0;">
    <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/migration-guide" target="_blank">
      <strong>React Native SDK v1.0.0 Migration Guide →</strong>
    </a>
  </p>
  
</div>
<p>
  <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank">
    React Native SDK Release Notes →
  </a>
</p>

<h2>Configure Media Once, Keep It Across the Meeting</h2>

<p>
  One of the strongest themes across the August SDK releases is persistent media configuration. Camera and microphone preferences can now stay applied even when users toggle devices, reconnect to a meeting, or move between meeting modes.
</p>

<h3>iOS SDK v3.1.0</h3>

<p>
  <strong>iOS SDK v3.1.0</strong> now remembers custom camera and microphone
  settings for the lifetime of the meeting.
</p>

<p>Settings are preserved across:</p>

<ul>
  <li>Camera off and on.</li>
  <li>Microphone mute and unmute.</li>
  <li>Meeting mode changes.</li>
  <li>Automatic reconnects after network interruptions.</li>
  <li>Updated media configuration when the application provides new settings.</li>
</ul>

<p>
  This includes video quality, camera direction, multistream preferences,
  bitrate settings, and noise configuration.
</p>
<p>
  <a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank">
    iOS SDK Release Notes →
  </a>
</p>
<h3>Android SDK v2.1.0</h3>

<p>
  <strong>Android SDK v2.1.0</strong> now keeps camera and microphone
  configuration isolated to each meeting and restores those settings whenever
  media needs to be recreated.
</p>

<p>Media preferences are preserved across:</p>

<ul>
  <li>Camera off and on.</li>
  <li>Microphone mute and unmute.</li>
  <li>Reconnects after network interruptions.</li>
  <li>Meeting mode changes.</li>
  <li>Custom track replacements.</li>
</ul>

<p>
  Multistream preferences are also retained when the SDK falls back to VP8,
  helping applications preserve their intended simulcast behavior.
</p>
<p>
  <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank">
    Android SDK Release Notes →
  </a>
</p>

<h3>Flutter SDK v3.11.0</h3>

<p>
  <strong>Flutter SDK v3.11.0</strong> also keeps camera and microphone
  preferences applied throughout the meeting.
</p>

<p>Settings are preserved across:</p>

<ul>
  <li>Camera off and on.</li>
  <li>Microphone mute and unmute.</li>
  <li>Camera and microphone device changes.</li>
  <li>Automatic reconnects after network interruptions.</li>
  <li>Media recovery after a device becomes unavailable.</li>
  <li>Meeting mode changes.</li>
</ul>

<p>
  <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank">
    Flutter SDK Release Notes →
  </a>
</p>

<div class="card">
  <h3 style="margin-top:0;">Why this matters</h3>
  <p style="margin-bottom:0;">
    Applications can configure media once and rely on those preferences throughout the meeting instead of manually restoring camera quality, device selection, multistream settings, or microphone configuration after common meeting events.
  </p>
</div>


<h2>Clearer RTC Errors and Reconnect Behavior</h2>

<p>
  August also brings more explicit error handling across several RTC SDKs. Invalid operations now fail clearly, while reconnect and media-state behavior is easier for applications to respond to.
</p>

<h3>JS SDK v1.1.0 &amp; React SDK v1.1.0</h3>

<p>
  <strong>JS SDK v1.1.0</strong> and <strong>React SDK v1.1.0</strong> introduce signalling request timeouts so unanswered operations no longer wait indefinitely.
</p>

<p>
  Screen-share operations also prevent overlapping enable or disable requests, while stream events are emitted at a point where applications can safely trigger their next media action.
</p>

<p>
  The releases also include reliability fixes around media publishing, device switching, and stream lifecycle behavior.
</p>

<p>
  <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank">
    JavaScript SDK Release Notes →
  </a>
  <br>
  <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank">
    React SDK Release Notes →
  </a>
</br></p>

<h3>iOS SDK v3.1.1</h3>

<p>
  <strong>iOS SDK v3.1.1</strong> now reports errors when applications attempt meeting actions before joining or while the meeting is reconnecting.
</p>

<p>
  The release also fixes an issue where microphone mute or camera-off state could be lost during a reconnect.
</p>

<h3>iOS SDK v3.2.0</h3>

<p>
  <strong>iOS SDK v3.2.0</strong> adds bounded reconnect behavior so applications receive a clear meeting exit reason when signalling cannot be restored.
</p>

<p>
  Manual meeting exits are also reported separately, making it easier to distinguish a user-initiated leave from a connectivity failure.
</p>

<h3>Flutter SDK v3.12.0 &amp; v3.12.1</h3>

<p>
  <strong>Flutter SDK v3.12.0</strong> now reports an error when meeting actions are called before join or during reconnect. It also introduces <span class="ic">RoomState.failed</span> for meetings that cannot be established successfully.
</p>

<p>
  <strong>Flutter SDK v3.12.1</strong> improves Android build compatibility. Apps no longer need manual setup for the previously reported <span class="ic">compileSdkVersion</span> issue, and the SDK is prepared for upcoming Android Gradle Plugin changes.
</p>


<h2>Smarter Agent Turn-Taking, Audio, and Telephony</h2>

<p>
  The <strong>VideoSDK Agents SDK v1.0.26 and v1.0.27</strong> releases focus on making AI voice conversations more responsive while adding more flexibility for telephony and full speech-to-speech applications.
</p>

<h3>VideoSDK Agents SDK v1.0.26: Better Turn Handling</h3>

<p>
  <strong>VideoSDK Agents SDK v1.0.26</strong> improves speech-to-text turn handling, interruption behavior, voice activity handling, and agent wake-up behavior.
</p>

<p>
  Developers can also configure interrupt phrases such as "stop", "wait", or "hold on" to give users more natural control during an active conversation.
</p>

<h3>More Audio Codec Options</h3>

<p>
  Voice agents can now select from <strong>Opus, PCMU, PCMA, and G.722</strong> audio codecs through <span class="ic">RoomOptions</span>, making the SDK more flexible for telephony and audio-specific applications.
</p>

<div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
  <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">
    python
  </div>
  <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">room_options = RoomOptions(
    name="Telephony Agent",
    audio_codec="pcmu"
)</pre> </div>


<h3>VideoSDK Agents SDK v1.0.27: Local VAD for Full Speech-to-Speech</h3>

<p>
  <strong>VideoSDK Agents SDK v1.0.27</strong> adds optional local Silero VAD support for full speech-to-speech pipelines, giving applications more control over user speech detection and conversational timing.
</p>

<div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
  <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">
    python
  </div>
  <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">from videosdk.agents import Pipeline
from videosdk.agents.plugins import GeminiRealtime, GeminiLiveConfig, SileroVAD

pipeline = Pipeline(
    llm=GeminiRealtime(
    model="gemini-3.1-flash-live-preview",
    config=GeminiLiveConfig(
        voice="Puck",
        response_modalities=["AUDIO"]
        )
    ),
    vad=SileroVAD()
)</pre> </div>


<h3>Improved Warm Transfers</h3>

<p>
  Warm-transfer workflows now better support consultation calls and recordings. The primary call and consultation room can both remain available during the transfer flow, and applications can retrieve the recording information needed afterward.
</p>


<h2>Better Pre-Call Diagnostics and Developer Experience</h2>

<h3>Prebuilt SDK Example v0.3.46</h3>

<p>
  <strong>Prebuilt SDK Example v0.3.46</strong> updates SDK operations to async and await for clearer error handling and more predictable state updates.
</p>

<p>
  The join flow now includes <span class="ic">runPrecallTest</span>, allowing applications to validate network and device readiness before a participant joins a meeting.
</p>

<p>The release also includes:</p>

<ul>
  <li>Improved PubSub payload handling.</li>
  <li>A fix for duplicate screen-share prompts after a rejected request.</li>
  <li>Corrected quality-selection behavior during meetings.</li>
  <li>More camera, microphone, and screen-share configuration options.</li>
  <li>A <span class="ic">verbose</span> option for SDK logging.</li>
  <li>Improved theme support across the Prebuilt meeting UI.</li>
</ul>


<h2>More Updates Across the SDK Stack</h2>

<div class="card">
  <h3 style="margin-top:0;">Python SDK v0.3.8</h3>
  <ul style="margin-bottom:0;">
    <li>Support for multiple video tracks.</li>
    <li>Custom frame metadata support.</li>
  </ul>
</div>

<div class="card">
  <h3 style="margin-top:0;">React Native SDK v1.0.1</h3>
  <p style="margin-bottom:0;">
    Improved compatibility with older React Native, Expo, Android, and Gradle environments.
  </p>
</div>


<div class="card">
  <h3 style="margin-top:0;">IoT SDK v0.4.0</h3>

  <p>
    The IoT SDK updates its documentation and examples to use the latest room terminology.
  </p>

  <p style="margin-bottom:0;">
    <a href="https://docs.videosdk.live/iot/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank">
      IoT SDK Release Notes →
    </a>
  </p>
</div>


<h2>Developer Resources</h2>

<p>
  Alongside the SDK releases, we published tutorials, demos, implementation guides, and AI tooling resources to help developers build and test VideoSDK applications faster.
</p>

<h3>React Tutorial</h3>

<div class="img-container" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;">
  <iframe width="560" height="315" src="https://www.youtube.com/embed/Auxjhx0_T1s?si=sO3YWm8KMksUPxfm" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
</div>

<p>
  <a href="https://youtu.be/Auxjhx0_T1s" target="_blank">
    Watch the React Tutorial →
  </a>
</p>


<h3>Build an Online Classroom with React and VideoSDK</h3>

<p>
  The classroom example combines real-time video with an online whiteboard experience and is available as a live demo, open-source project, implementation guide, and video walkthrough.
</p>

<ul>
  <li>
    <a href="https://classroom-by-videosdk.vercel.app/" target="_blank">
      Try the Classroom Demo →
    </a>
  </li>

  <li>
    <a href="https://github.com/videosdk-community/classroom" target="_blank">
      Explore the Classroom Demo Repository →
    </a>
  </li>

  <li>
    <a href="https://www.videosdk.live/blog/react-whiteboard-online-classroom" target="_blank">
      Read the React Whiteboard Online Classroom Guide →
    </a>
  </li>

  <li>
    <a href="https://youtu.be/hVXLhWCC9oM" target="_blank">
      Watch the Classroom Demo Walkthrough →
    </a>
  </li>
</ul>

<div class="img-container" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;">
  <iframe width="560" height="315" src="https://www.youtube.com/embed/hVXLhWCC9oM?si=ERJGyrFLCvKI8fqS" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
</div>


<h3>Build Video Calling on IoT Devices</h3>

<p>
  For developers working with embedded devices, we have an IoT tutorial and an ESP32 implementation guide covering video calling with the VideoSDK IoT SDK.
</p>

<ul>
  <li>
    <a href="https://youtu.be/7uQtud6MNFI" target="_blank">
      Watch the IoT Tutorial →
    </a>
  </li>

  <li>
    <a href="https://www.videosdk.live/blog/esp32-video-calling-videosdk-iot-sdk" target="_blank">
      Read the ESP32 Video Calling with VideoSDK IoT SDK Guide →
    </a>
  </li>
</ul>

<div class="img-container" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;">
  <iframe width="560" height="315" src="https://www.youtube.com/embed/7uQtud6MNFI?si=VTewWmUwaZvg-xU1" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
</div>


<h3>AI Tools: MCP Server and Agent Skills</h3>

<p>
  Developers using AI coding tools can connect VideoSDK documentation and development workflows through the VideoSDK MCP Server and Agent Skills.
</p>

<ul>
  <li>
    <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/ai-tools/mcp-server" target="_blank">
      VideoSDK MCP Server Documentation →
    </a>
  </li>

  <li>
    <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/ai-tools/agent-skill" target="_blank">
      VideoSDK Agent Skills Documentation →
    </a>
  </li>
</ul>


<h2>VideoSDK Is Now Available on Microsoft and AWS Marketplace</h2>

<p>
  VideoSDK is now available through both <strong>Microsoft Marketplace</strong> and <strong>AWS Marketplace</strong>, giving teams additional procurement options when adopting VideoSDK within existing cloud and enterprise workflows.
</p>

<div class="card">
  <ul style="margin-bottom:0;">
    <li>
      <a href="https://marketplace.microsoft.com/en-us/product/videosdk.videosdk" target="_blank">
        VideoSDK on Microsoft Marketplace →
      </a>
    </li>

    <li>
      <a href="https://aws.amazon.com/marketplace/pp/prodview-dk5mmvkjkpi64?sr=0-12&amp;ref_=ucaf&amp;applicationId=AWSMPContessa" target="_blank">
        VideoSDK on AWS Marketplace →
      </a>
    </li>
  </ul>
</div>


<h2>✨ Community Spotlight</h2>

<div style="border-left:3px solid var(--primary);padding-left:20px;margin-top:30px;margin-bottom:30px;">
  <a href="https://videosdk.live/customers/curable" style="font-size:18px;line-height:1.5;">
    Explore how Curable Scaled High-Quality Telemedicine Consultations with VideoSDK
  </a>
</div>

<div class="img-container">
  <a href="https://videosdk.live/customers/curable">
    <img src="https://strapi.videosdk.live/uploads/curable_testimonial_august_update_dcc22ff801.png" alt="Product Updates - August 2026: React Native v1.0.0, Persistent Media Configuration, and Smarter AI Agent Turn-Taking" VideoSDK="" has="" been="" instrumental="" in="" helping="" us="" deliver="" seamless="" telemedicine="" consultations.="" The="" platform="" is="" reliable,="" developer-friendly,="" and="" backed="" by="" a="" highly="" responsive="" support="" team.="" It="" valuable="" technology="" partner="" for="" Curable."="" style="border:none;box-shadow:none;">
  </img></a>
</div>


<h2>SDK Sketches</h2>

<p>
  This month's SDK Sketches looks at a familiar media-state problem: configuring camera quality, multistream, and microphone settings, then expecting those choices to stay applied when media is toggled or the meeting reconnects.
</p>

<div class="img-container">
  <img src="https://strapi.videosdk.live/uploads/august_update_sdk_sketch_236a7036c4.png" alt="Product Updates - August 2026: React Native v1.0.0, Persistent Media Configuration, and Smarter AI Agent Turn-Taking">
</img></div>


<h2>Build with August's Updates</h2>

<p>
  If you are upgrading this month, start by reviewing the breaking changes in <strong>React Native SDK v1.0.0</strong>, then test your media controls, reconnect flows, and device-switching experience with the latest SDK versions.
</p>

<p>
  For AI voice applications, <strong>VideoSDK Agents SDK v1.0.26 and v1.0.27</strong> add more control over conversational timing, interruptions, audio formats, VAD, and warm-transfer workflows.
</p>

<p>
  And if you are improving the experience before users enter a call, the updated Prebuilt example and <span class="ic">runPrecallTest</span> provide a useful starting point for network and device readiness checks.
</p>

<div class="cta-box">
  <h3 style="margin-top:0;">Start Building with VideoSDK</h3>

  <p>
    Upgrade to the latest SDKs, explore the new resources, and put August's updates to work in your application.
  </p>

  <a href="https://app.videosdk.live" class="cta-button" style="margin-right:12px;">
    Dashboard
  </a>

  <a href="https://discord.com/invite/Gpmj6eCq5u" class="cta-button">
    Join our Discord
  </a>
</div>

<p style="text-align:center;margin-top:40px;margin-bottom:0;">
  Happy building!<br>
  <strong>Team VideoSDK</strong>
</br></p>


  </div>
</body>
</html>



<!--kg-card-end: html-->
]]></content:encoded></item><item><title><![CDATA[Product Updates - July 2026 : Major Core SDK Milestone, Rebuilt PubSub, and IoT Video Support]]></title><description><![CDATA[July brings our most significant milestone yet: v1.0.0 (JS/React) and v2.0.0 (Android) core SDKs, featuring a rebuilt Web Worker PubSub and Promise-based APIs. Plus, live video support for IoT!]]></description><link>https://www.videosdk.live/blog/product-updates-july-2026</link><guid isPermaLink="false">6a704d47b3240feb748c9185</guid><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 03 Aug 2026 12:08:23 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/july-2026-monthly-product-update-banner-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/08/july-2026-monthly-product-update-banner-1.png" alt="Product Updates - July 2026 : Major Core SDK Milestone, Rebuilt PubSub, and IoT Video Support"/><p/>
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Product Updates - July 2026: Major Core SDK Milestone, Rebuilt PubSub, and IoT Video Support</title>
  <style>
    .product-update-content {
  --primary: #A497D9;
  --bg: #050608;
  --card-bg: #111217;
  --text-main: #E0E0E0;
  --text-muted: #A0A0A0;
  --border: #22242C;

  font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  line-height: 1.7;
  color: var(--text-main);
  background-color: var(--bg);
}

.product-update-content .product-update-container {
  max-width: 850px;
  margin: 0 auto;
  padding: 60px 20px;
}

.product-update-content header {
  text-align: left;
  margin-bottom: 60px;
}

.product-update-content h2 {
  font-size: 28px;
  color: #FFFFFF;
  margin-top: 40px;
  padding-bottom: 10px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 20px;
}

.product-update-content h3 {
  font-size: 22px;
  color: #FFFFFF;
  margin-top: 35px;
}

.product-update-content p {
  margin-bottom: 16px;
}

.product-update-content strong {
  color: #FFFFFF;
}

.product-update-content ul,
.product-update-content ol {
  margin-bottom: 20px;
  padding-left: 20px;
}

.product-update-content li {
  margin-bottom: 10px;
}

.product-update-content .highlight {
  color: var(--primary);
  font-weight: 600;
}

.product-update-content a {
  color: var(--primary);
  text-decoration: none;
}

.product-update-content a:hover {
  text-decoration: underline;
}

.product-update-content .ic {
  font-family: 'Fira Code', 'Cascadia Code', 'Consolas', monospace;
  font-size: 13.5px;
  color: #A497D9;
  font-weight: 700;
}

.product-update-content .card {
  background-color: var(--card-bg);
  border-radius: 12px;
  padding: 24px;
  margin: 24px 0;
}

.product-update-content .img-container {
  margin: 20px 0;
  text-align: center;
}

.product-update-content .img-container img {
  width: 100%;
  height: auto;
  border-radius: 8px;
}

.product-update-content .cta-button {
  background-color: var(--primary);
  color: #000000;
  padding: 6px 20px;
  border-radius: 6px;
  font-size: 15px;
  font-weight: bold;
  display: inline-block;
  text-decoration: none;
}

.product-update-content .cta-box {
  text-align: left;
  background: linear-gradient(135deg, #111217 0%, #1a1b23 100%);
  padding: 30px;
  border-radius: 12px;
  border: 1px solid var(--primary);
  margin: 40px 0;
}

.product-update-content hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin: 40px 0;
}

@media (max-width: 600px) {
  .product-update-content .product-update-container {
    padding: 40px 15px;
  }
}
  </style>
</meta></meta></head>

<body>
  <div class="product-update-content">
    <div class="product-update-container">
    <header>
      <p style="font-size:18px;color:#A0A0A0;margin:0;">July 2026 Updates: Core SDK v1.0.0/v2.0.0 Milestones, Rebuilt PubSub Engine, and IoT Video Capabilities.</p>
    </header>
    
    <p>Welcome to the July edition of the VideoSDK Monthly Updates! This month represents one of the most critical milestones in our platform's history as we roll out complete, production-hardened architectural overhauls for our primary client libraries.</p>
    <p>We are introducing <span class="highlight">JS SDK v1.0.0</span>, <span class="highlight">React SDK v1.0.0</span>, and <span class="highlight">Android SDK v2.0.0</span>, packing a thread-isolated PubSub engine and a promise-based async API. On top of that, we've brought live <b>video streaming support to edge IoT devices</b>. Let’s explore the details!</p>

    <!-- THE CORE OVERHAUL -->
    <h2>The Core SDK Paradigm Shift (v1.0.0 &amp; v2.0.0)</h2>
    <p>Real-time collaborative applications handle extensive, high-frequency message streams. On web and mobile, running these operations on the main execution thread causes UI freezes and sluggish rendering. Our major July milestone isolates these complex background systems entirely.</p>

    <h3>Rebuilt Web-Worker Powered PubSub</h3>
    <p>Our completely redesigned PubSub system is now built on a dedicated WebSocket transport with Protobuf framing. By offloading message parsing and state management to a background <b>Web Worker</b> (on Web/React) or a <b>background thread</b> (on Android), message traffic never competes with your UI rendering thread.</p>
    <ul>
      <li><strong>Batched Delivery:</strong> Capture high-volume event bursts efficiently with the new <span class="ic">onBatchReceived</span> listener.</li>
      <li><strong>Backpressure Control:</strong> Manage message overflows dynamically with the <span class="ic">realtimeOverflow</span> parameter-choosing between <span class="ic">queue</span> (retaining messages up to a cap) or <span class="ic">drop</span>.</li>
      <li><strong>Resilient Reconnects:</strong> Capped exponential backoff with jitter, a robust ping/pong watchdog, and automatic subscription state replay.</li>
    </ul>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">javascript</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">await meeting.pubSub.subscribe(
  "CHAT",
  {
    onMessageReceived: (msg) => { console.log(msg); },
    onBatchReceived: (msgs) => { console.log("Received batch:", msgs); },
    onOldMessagesReceived: (msgs) => { console.log("History loaded:", msgs); },
    onMessageDrop: (info) => { console.warn("Dropped:", info.droppedCount); }
  },
  { realtimeOverflow: "queue", maxQueue: 500 }
);</pre>
    </div>

    <h3>Promise-Based Async APIs &amp; Typed Errors</h3>
    <p>Every asynchronous method across our JS, React, and Android libraries now returns a standard Promise and rejects with a structured, strongly-typed error class (<span class="ic">SdkError</span> / <span class="ic">VideoSDKError</span>). Operations now fail cleanly at the call-site with precise error codes rather than propagating silently to a global listener.</p>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">javascript</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">try {
  await meeting.enableWebcam();
} catch (err) {
  <span style="color:#5c6370;">// Catches operation errors (4xxx/5xxx) and caller-state blocks (3xxx)</span>
  console.error(`Error [${err.code} - ${err.name}]: ${err.message}`);
}</pre>
    </div>

    <h3>Consistent Track Persistence</h3>
    <p>Your custom track settings (like <span class="ic">encoderConfig</span>, <span class="ic">facingMode</span>, <span class="ic">noiseConfig</span>, and <span class="ic">multiStream</span>) are now saved for the entire lifetime of the meeting. Tracks automatically retain these custom parameters across reconnect retries, page remounts, and meeting mode changes.</p>

    <!-- NEW MIGRATION CARD -->
    <div class="card" style="border: 1px solid var(--primary);">
      <h3 style="margin-top: 0; color: var(--primary);">Migrating to v1.0.0 &amp; v2.0.0</h3>
      <p>These major releases contain critical improvements and breaking changes. To assist with your upgrade path, explore our platform-specific migration guides:</p>
      <ul style="margin-bottom: 0;">
        <li><a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/migration-guide" target="_blank"><strong>JavaScript Migration Guide</strong></a></li>
        <li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/migration-guide" target="_blank"><strong>React Migration Guide</strong></a></li>
        <li><a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/migration-guide" target="_blank"><strong>Android Migration Guide</strong></a></li>
        <li><a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/migration-guide" target="_blank"><strong>iOS Migration Guide</strong></a></li>
      </ul>
    </div>

    <hr>

    <!-- FEATURE SPOTLIGHT -->
    <h2>Feature Spotlight: Video Support for IoT Devices</h2>
    <p>Our IoT SDK has taken a massive step forward, evolving from audio-only capabilities to supporting full <strong>real-time video sending and receiving</strong> on low-power, embedded chipsets.</p>
    <ul>
      
      <li><strong><a href="https://docs.videosdk.live/iot/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank">IoT SDK (v0.3.0 - v0.3.2)</a></strong>: Capture and stream real-time video feeds on Linux and ARM64 embedded boards, with specialized, smooth rendering optimizations on the <b>Espressif Korvo-2</b> display.</li>
      <li><strong>Teardown Simplification:</strong> We have removed the need for separate, manual audio-stop calls. Embedded devices now handle complete resource teardown automatically simply by invoking <span class="ic">leave()</span>.</li>
    </ul>

    <hr>

    <!-- OPTIMIZATIONS & FIXES -->
    <h2>Client-Side Performance &amp; Fixes</h2>
    <ul>
      <li><strong><a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank">React Native (v0.12.0)</a></strong>: Integrates the new PubSub backpressure configurations (<span class="ic">maxMessages</span> and <span class="ic">bufferMessages</span>) and resolves state hydration bugs in the <span class="ic">useMeeting</span> hook.</li>
      
      <li><strong><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank">Flutter SDK (v3.10.0 - v3.10.1)</a></strong>: Added support for batched server signaling and cleaned up external dependencies to resolve framework conflicts.</li>
      
      <li><strong><a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank">Android SDK (v2.0.1)</a></strong>: We’ve overhauled the socket interaction layer. Internal thread-blocking calls inside Pub/Sub, `changeMode()`, and media toggles have been completely replaced with background asynchronous execution.</li>
    </ul>

    <!-- NEW RELEASE NOTES SECTION -->
    <h3 style="margin-top: 24px;">SDK Release Notes</h3>
    <p>For a detailed, platform-specific breakdown of all API adjustments, performance updates, and minor bug fixes in these versions, read our official release documentation:</p>
    <ul>
      <li><a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank"><strong>JavaScript SDK Release Notes</strong></a></li>
      <li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank"><strong>React SDK Release Notes</strong></a></li>
      <li><a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank"><strong>Android SDK Release Notes</strong></a></li>
      <li><a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank"><strong>iOS SDK Release Notes</strong></a></li>
    </ul>

    <hr>


    <!-- DASHBOARD -->
    <h2>Dashboard Upgrades</h2>
    <ul>
      
      <li><strong><a href="https://app.videosdk.live/voice-studio" target="_blank">Voice Studio</a></strong>: Explore, sample, and test custom voice configurations for your AI agents directly within the dashboard.
      <div class="img-container">
      <a href="https://app.videosdk.live/voice-studio">
        <img src="https://strapi.videosdk.live/uploads/voice_studio_july_d3f855a9f1.png" alt="Product Updates - July 2026 : Major Core SDK Milestone, Rebuilt PubSub, and IoT Video Support" style="border: none; box-shadow: none;">
      </img></a>
    </div>
      </li>

      <li><strong><a href="https://app.videosdk.live/agent-v2" target="_blank">Agent Runtime v2</a></strong>: Create, manage, and split traffic across agent versions.
      <div class="img-container">
      <a href="https://app.videosdk.live/agent-v2">
        <img src="https://strapi.videosdk.live/uploads/agents_v2_july_2cdf394e3f.png" alt="Product Updates - July 2026 : Major Core SDK Milestone, Rebuilt PubSub, and IoT Video Support" style="border: none; box-shadow: none;">
      </img></a>
    </div>
      </li>

      
      <li><strong><a href="https://app.videosdk.live/profile/general" target="_blank">Profile Customization</a></strong>: You can now upload and update your developer profile pictures directly in the settings panel.
      <div class="img-container">
      <a href="https://app.videosdk.live/profile/general">
        <img src="https://strapi.videosdk.live/uploads/change_profile_pic_july_e0c013537e.png" alt="Product Updates - July 2026 : Major Core SDK Milestone, Rebuilt PubSub, and IoT Video Support" style="border: none; box-shadow: none;">
      </img></a>
    </div>
      </li>
    </ul>

    <hr>

    <!-- RESOURCES -->
    <h2>📚 New Content & Resources</h2>
    <h3>New Guides and Documentation</h3>
    <ul>
      <li><strong>Dashboard Management Guides:</strong> Comprehensive walkthroughs covering <a href="https://docs.videosdk.live/help_docs/dashboard/api-keys" target="_blank">API Keys Settings</a>, <a href="https://docs.videosdk.live/help_docs/dashboard/billing/overview" target="_blank">Billing</a>, <a href="https://docs.videosdk.live/help_docs/dashboard/sessions" target="_blank">Sessions</a>, <a href="https://docs.videosdk.live/help_docs/dashboard/recordings" target="_blank">Recordings</a>, and <a href="https://docs.videosdk.live/help_docs/dashboard/streaming/hls" target="_blank">Streaming.</a></li>
      
      <li><strong>Build a Zoom Clone with Claude Code:</strong> <a href="https://www.videosdk.live/blog/zoom-clone" target="_blank">A complete step-by-step guide to deploying a customized video meeting in under 10 minutes.</a></li>
      
      <li><strong>Build a Google Meet Clone:</strong> <a href="https://www.videosdk.live/blog/google-meet-clone" target="_blank">How to design and customize your own real-time web layout.</a></li>
    </ul>

    <h3>Featured Videos</h3>
    <ul>
      
      <li>▶️ <a href="https://www.youtube.com/watch?v=zoom-clone-claude" target="_blank">Build a Zoom Clone with Claude Code in 10 Minutes</a>
      <div class="img-container" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;">
      <iframe width="560" height="315" src="https://www.youtube.com/embed/j_biymyP5iw?si=bL759a4GklEg3cRQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
    </div>
        </li>

      <li>▶️ <a href="https://www.youtube.com/watch?v=google-meet-custom" target="_blank">You Can't Change Google Meet. So Let's Build One You Can.</a>
      <div class="img-container" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;">
      <iframe width="560" height="315" src="https://www.youtube.com/embed/HpAa3eld-bc?si=xNCXznvCZfUENdZS" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
    </div>
        </li>
    </ul>

    <hr>

    <h2>✨ Community Spotlight</h2>  

    <div style="border-left: 3px solid var(--primary); padding-left: 20px; margin-top: 30px; margin-bottom: 30px;">
        <a href="https://www.videosdk.live/customers/nxtqube" style="font-size: 18px; line-height: 1.5;">Explore how NxtQube built a low-latency drone monitoring pipeline in under a week with VideoSDK.</a>
    </div>

    <div class="img-container">
      <a href="https://videosdk.live/customers/nxtqube">
        <img src="https://strapi.videosdk.live/uploads/testimonial_july_854199b5fa.png" alt="Product Updates - July 2026 : Major Core SDK Milestone, Rebuilt PubSub, and IoT Video Support" style="border: none; box-shadow: none;">
      </img></a>
    </div>
    
    <hr>

    <!-- SDK SKETCHES -->
    <h2>SDK Sketches</h2>
    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/july_sdk_sketch_d992242f7a.png" alt="Product Updates - July 2026 : Major Core SDK Milestone, Rebuilt PubSub, and IoT Video Support">
      <span class="img-caption">This month's sketch: Blocking the main UI thread with intensive PubSub message parsing (Before) vs. Seamless, parallel background worker threads in v1.0.0 (After).</span>
    </img></div>

    <div class="cta-box">
      <h3 style="margin-top:0;">Build with July's Milestones</h3>
      <p>Log in to configure Agent Runtime v2 and explore Voice Studio on the dashboard, or upgrade your client SDKs to take advantage of the completely re-engineered core.</p>
      <a href="https://app.videosdk.live" class="cta-button" style="margin-right:12px;">Dashboard</a>
      <a href="https://discord.com/invite/Gpmj6eCq5u" class="cta-button">Join our Discord</a>
    </div>

    <p style="text-align: center; margin-top: 40px; margin-bottom: 0;">
      Happy building!<br>
      <strong>Team VideoSDK</strong>
    </br></p>
    </hr></hr></hr></hr></hr></hr></div>
  </div>
</body>
</html>
<!--kg-card-end: html-->
]]></content:encoded></item><item><title><![CDATA[Product Updates - June 2026 : TurnV2 : Echo, Selectable Video Codecs, and Embedded Jetson Nano Support]]></title><description><![CDATA[June brings TurnV2 (Echo) exclusively via the Inference Gateway, native C++ support for NVIDIA Jetson Nano, selectable video codecs across SDKs, and batched signaling.]]></description><link>https://www.videosdk.live/blog/product-updates-june-2026</link><guid isPermaLink="false">6a44baa4b3240feb748c555e</guid><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 01 Jul 2026 13:09:26 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/07/monthly-update-banner-june.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/07/monthly-update-banner-june.png" alt="Product Updates - June 2026 : TurnV2 : Echo, Selectable Video Codecs, and Embedded Jetson Nano Support"/><p/>
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Product Updates - June 2026 : TurnV2 (Echo) Inference, NVIDIA Jetson Nano Support, and Advanced RTC Codecs</title>
  <style>
    :root {
      --primary: #A497D9;
      --bg: #050608;
      --card-bg: #111217;
      --text-main: #E0E0E0;
      --text-muted: #A0A0A0;
      --border: #22242C;
    }
    body {
      font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      line-height: 1.7;
      color: var(--text-main);
      background-color: var(--bg);
      margin: 0;
      padding: 0;
    }
    header { text-align: left; margin-bottom: 60px; }
    h2 { font-size: 28px; color: #FFFFFF; margin-top: 40px; padding-bottom: 10px; border-bottom: 1px solid var(--border); margin-bottom: 20px; }
    h3 { font-size: 22px; color: #FFFFFF; margin-top: 35px; }
    p { margin-bottom: 16px; }
    strong { color: #FFFFFF; }
    ul, ol { margin-bottom: 20px; padding-left: 20px; }
    li { margin-bottom: 10px; }
    .highlight { color: var(--primary); font-weight: 600; }
    a { color: var(--primary); text-decoration: none; }
    a:hover { text-decoration: underline; }
    .ic { font-family: 'Fira Code','Cascadia Code','Consolas',monospace; font-size: 13.5px; color: #A497D9; font-weight: 700; }
    .card { background-color: var(--card-bg); border-radius: 12px; padding: 24px; margin: 24px 0; }
    .img-container { margin: 20px 0; text-align: center; }
    .img-container img { width: 100%; height: auto; border-radius: 8px; }
    .cta-button { background-color: var(--primary); color: #000000; padding: 6px 20px; border-radius: 6px; font-size: 15px; font-weight: bold; display: inline-block; text-decoration: none; }
    .cta-box { text-align: left; background: linear-gradient(135deg, #111217 0%, #1a1b23 100%); padding: 30px; border-radius: 12px; border: 1px solid var(--primary); margin: 40px 0; }
    hr { border: 0; border-top: 1px solid var(--border); margin: 40px 0; }
    @media (max-width: 600px) { .container { padding: 40px 15px; } }
  </style>
</meta></meta></head>
<body>
  <div class="container">
    <header>
      <p style="font-size:18px;color:#A0A0A0;margin:0;">June 2026 Updates: TurnV2 (Echo) Inference, NVIDIA Jetson Nano Support, and Advanced RTC Codecs.</p>
    </header>
    
    <p>Welcome to the June edition of the VideoSDK Monthly Updates! This month, we have focused on making conversational AI interaction feel incredibly natural and expanding our native hardware capabilities.</p>
    <p>We are introducing <span class="highlight">TurnV2 (Echo)</span> low-latency models exclusively via our Inference Gateway, launching full native support for <b>NVIDIA Jetson Nano</b> in our C++ SDK, and rolling out <b>selectable video codecs</b> across our web and mobile platforms. Let's dive in!</p>

    <!-- AI AGENTS EVOLUTION -->
    <h2>AI Agents: Conversational Edge &amp; TurnV2 (Echo)</h2>
    <p>While turn detection has always been a key component of VideoSDK, handling the fine-grained nuances of human conversation remains one of the hardest challenges in real-time AI.</p>

    <h3>Introducing TurnV2 (Echo) Low-Latency Models</h3>
    <p>We are launching <strong>TurnV2</strong>, a brand-new turn detector available exclusively via the <strong><a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference#turn-detection-configuration" target="_blank">VideoSDK Inference Gateway</a></strong>. It introduces two custom models:</p>
    <ul>
      <li><span class="ic">echo-small</span> : optimized for ultra-low latency response.</li>
      <li><span class="ic">echo-large</span> : optimized for high-accuracy turn classification.</li>
    </ul>
    <p>Rather than simply checking for silence, the <a href="https://docs.videosdk.live/ai_agents/core-components/turn-detection" target="_blank">TurnV2</a> models classify speech into 4 complex conversational states, altering agent behavior dynamically:</p>
    <ul>
      <li><strong>Complete:</strong> The user has finished speaking. The agent responds immediately.</li>
      <li><strong>Incomplete:</strong> The user paused mid-sentence. The agent continues to listen.</li>
      <li><strong>Backchannel:</strong> The user makes brief acknowledging noises (like "uh-huh" or "yeah") while the agent is talking. The agent intelligently ignores this and keeps speaking.</li>
      <li><strong>Wait:</strong> The user explicitly commands the agent to stop. The agent interrupts its speech immediately and yields.</li>
    </ul>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">from videosdk.agents.inference import <span style="color:#A497D9;">TurnV2</span>

pipeline = Pipeline(
    stt=DeepgramSTT(),
    llm=GoogleLLM(),
    tts=CartesiaTTS(),
    vad=SileroVAD(),
    turn_detector=<span style="color:#A497D9;">TurnV2.echo_large()</span>  <span style="color:#5c6370;"># or TurnV2.echo_small()</span>
)</pre>
    </div>

    <h3>Unified Single-Line Imports</h3>
    <p>We have simplified developer workflows by introducing a unified component import style (v1.0.17). You can now import any provider plugin or inference gateway component from a single namespace, avoiding multi-line, verbose imports.</p>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;"><span style="color:#5c6370;"># Clean, unified imports for local plugins</span>
from videosdk.agents.plugins import <span style="color:#A497D9;">DeepgramSTT, GoogleLLM, CartesiaTTS</span>

<span style="color:#5c6370;"># Clean, unified imports for the Inference Gateway</span>
from videosdk.agents.inference import <span style="color:#A497D9;">SarvamAISTT, SarvamAITTS, NamoTurnDetectorV1</span></pre>
    </div>

    <h3>AWS Bedrock LLM Support</h3>
    <p>We have integrated support for <strong>AWS Bedrock</strong> via the ConverseStream API (v1.0.21). You can now leverage top-tier foundation models like Amazon Nova and Anthropic Claude within your pipeline, with enhanced fallback tool routing support.</p>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">from videosdk.agents.plugins import <span style="color:#A497D9;">AWSBedrockLLM</span>

pipeline = Pipeline(
    llm=<span style="color:#A497D9;">AWSBedrockLLM</span>(
        model="amazon.nova-lite-v1:0",
        region="us-east-1",
    )
)</pre>
    </div>

    <hr>

    <!-- CORE RTC UPGRADES -->
    <h2>Core RTC Upgrades: Codecs, DTX &amp; Batched Signaling</h2>
    <p>We’ve introduced high-end streaming optimizations to our core JS, React, React Native, and iOS SDKs to keep your sessions lightweight and efficient.</p>

    <h3>Selectable Video Codecs</h3>
    <p>You can now specify preferred video codecs dynamically on initialization. The <span class="ic">createCameraVideoTrack()</span> method now accepts a `codec` parameter, supporting <b>AV1, VP9, VP8, and H264</b>.</p>

    <h3>DTX (Discontinuous Transmission)</h3>
    <p>Bandwidth optimization is now built-in. By enabling <strong>DTX</strong> across all audio profiles, the SDK automatically suspends transmission of audio data during silent moments, cutting bandwidth overhead significantly.</p>

    <h3>Batched Server Signaling</h3>
    <p>To reduce network traffic and client-side CPU consumption in larger meetings, the server now bundles multiple participant events into batched payloads of up to 5 events at a time. This behavior is enabled by default and can be customized via your meeting configuration.</p>

    <h3>PubSub Memory Safeguards</h3>
    <p>Available in <strong>React SDK v0.13.0</strong>, the new <span class="ic">maxMessages</span> and <span class="ic">bufferMessages</span> parameters allow you to cap or disable message retention on high-throughput topics, preventing unbounded memory leaks during fast data transmissions.</p>

    <hr>

    <!-- EMBEDDED & EDGE DEVICES -->
    <h2>Embedded WebRTC: NVIDIA Jetson Nano Support</h2>
    <p>Our native C++ SDK continues to expand its target architectures, bringing WebRTC capabilities to rugged edge computers and IoT devices.</p>
    <ul>
      <li><strong>Jetson Nano Support (v0.0.1-beta.5):</strong> Official support has been added, making it straightforward to deploy real-time audio and video AI pipelines to Jetson Nano platforms.</li>
      <li><strong>VP8 Simulcast:</strong> Configure up to 3 outgoing video layers with customizable resolution, bitrate, and framerate properties before joining the meeting using <span class="ic">setSimulcastLayers()</span>.</li>
      <li><strong>Native Data Channels:</strong> Exchange binary or text payloads of up to 15 KiB directly with peers on edge devices using the new <span class="ic">sendData()</span> method.</li>
    </ul>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">bash</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">curl -fsSL https://raw.githubusercontent.com/videosdk-live/videosdk-rtc-cpp-sdk/main/install.sh | sudo sh</pre>
    </div>

    <ul>
      <li><a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank"><strong>JS SDK</strong> v0.10.0</a></li>
      <li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank"><strong>React SDK</strong> v0.12.0</a></li>
      <li><a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank"><strong>React Native SDK</strong> v0.11.0</a></li>
      <li><a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank"><strong>iOS SDK</strong> v2.8.1</a></li>
      <li><a href="https://docs.videosdk.live/cpp/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank"><strong>C++ SDK</strong> v0.0.1-beta.5</a></li>
    </ul>

    <hr>

    <!-- INFRASTRUCTURE -->
    <h2>Infrastructure &amp; Telephony Connectors</h2>
    <p>Our server architecture received significant upgrades to support raw socket ingestion and simplified multi-tenant cloud deployments.</p>
    <ul>
      <li><strong>WebSocket Telephony Ingestion:</strong> Connect your custom telephone lines and gateways directly to VideoSDK using our standardized socket ingestion connectors. <a href="https://docs.videosdk.live/telephony/connectors/connectors-overview" target="_blank">Explore the Architecture Guide</a>.</li>
      <li><strong>Agent Cloud Registry:</strong> Easily deploy customized, containerized agents directly to the VideoSDK Cloud using our streamlined registry pipelines. <a href="https://docs.videosdk.live/ai_agents/deployments/agent-cloud/deployment-guides/videosdk-registry-to-videosdk-cloud" target="_blank">Read the Deployment Guide</a>.</li>
    </ul>

    <hr>

    <!-- RESOURCES -->
    <h2>📚 New Content & Resources</h2>
    <h3>New Guides and Tutorials</h3>
    <ul>
      <li><strong>TurnV2 Configuration:</strong> <a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference#turn-detection-configuration" target="_blank">How to configure echo models via the Inference Gateway.</a></li>
      
      <li><strong>Turn Detection Core Guide:</strong> <a href="https://docs.videosdk.live/ai_agents/core-components/turn-detection" target="_blank">Mastering Complete, Incomplete, and Backchannel triggers.</a></li>

      <li><strong>Blog:</strong> <a href="https://dev.to/video-sdk/cross-platform-live-video-app-development-architecture-tech-stack-challenges-and-best-practices-29nj" target="_blank">Cross-Platform Live Video App Development: Architecture, Tech Stack, Challenges, and Best Practices</a></li>

      <li><strong>Blog:</strong> <a href="https://dev.to/nisha_goswami_/how-to-choose-a-real-time-communication-api-for-a-webrtc-app-2edp" target="_blank">How to Choose a Real-Time Communication API for a WebRTC App</a></li>
      
    </ul>

    <h3>Featured Videos</h3>
    <ul>
        <!--<li>▶️ <a href="https://www.linkedin.com/feed/update/urn:li:activity:7447592523981553664">VideoSDK Agents v1 Official Launch</a>
        <div class="img-container" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;">
      <iframe src="https://www.linkedin.com/embed/feed/update/urn:li:ugcPost:7447592366921871360?collapsed=1" height="550" width="504" frameborder="0" allowfullscreen="" title="Embedded post"></iframe>
    </div></li>-->

      

      <li>▶️ <a href="https://www.youtube.com/watch?v=62XOP_4GsWg">Echo Turn Detection Models: Linguistic Turn Detection for Voice Agents</a>
      <div class="img-container" style="position:relative;padding-bottom:40%;height:0;overflow:hidden;border-radius:8px;">
      <iframe width="560" height="315" src="https://www.youtube.com/embed/62XOP_4GsWg?si=4AXL5IqIyikTuFqa" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
    </div>
        </li>

        <li>▶️ <a href="https://youtu.be/8UurwYHtdNc?si=_-dcMwNgk66Xhpau">Introducing VideoSDK Fallback Adapter</a>
      <div class="img-container" style="position:relative;padding-bottom:40%;height:0;overflow:hidden;border-radius:8px;">
      <iframe width="560" height="315" src="https://www.youtube.com/embed/8UurwYHtdNc?si=cxenKu6Wum6VwRg0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
    </div>
        </li>

      <li>▶️ <a href="https://youtu.be/jE-GdIkSCm4?si=Ci1tEnFAZ-2jI9hx">Introducing VideoSDK Call Transfer</a>
      <div class="img-container" style="position:relative;padding-bottom:40%;height:0;overflow:hidden;border-radius:8px;">
      <iframe width="560" height="315" src="https://www.youtube.com/embed/jE-GdIkSCm4?si=Ci1tEnFAZ-2jI9hx" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
    </div>
        </li>

      <li>▶️ <a href="https://youtu.be/uIp0NS1Lb9s?si=SWeRaGgL6U6NxDE2">Introducing VideoSDK Warm Transfer</a>
      <div class="img-container" style="position:relative;padding-bottom:40%;height:0;overflow:hidden;border-radius:8px;">
      <iframe width="560" height="315" src="https://www.youtube.com/embed/uIp0NS1Lb9s?si=SWeRaGgL6U6NxDE2" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
    </div>
        </li>
    </ul>

    <hr>

    
    
<h2>✨ Community Spotlight</h2>  

    <div style="border-left: 3px solid var(--primary); padding-left: 20px; margin-top: 30px; margin-bottom: 30px;">
        <a href="https://videosdk.live/customers/amniltech" style="font-size: 18px; line-height: 1.5;">Explore how V-Connect Enabled Video KYC and Digital Banking at Scale with VideoSDK.</a>
    </div>

    <div class="img-container">
      <a href="https://videosdk.live/customers/amniltech">
        <img src="https://strapi.videosdk.live/uploads/testimonial_june_5f79008974.png" alt="Product Updates - June 2026 : TurnV2 : Echo, Selectable Video Codecs, and Embedded Jetson Nano Support" style="border: none; box-shadow: none;">
      </img></a>
    </div>
    
    <hr>

    <!-- SKETCHES -->
    <h2>SDK Sketches</h2>
    <div class="img-container">
      <!-- Image URL to be updated later -->
      <img src="https://strapi.videosdk.live/uploads/sdk_sketch_june_b622dffbf9.png" alt="Product Updates - June 2026 : TurnV2 : Echo, Selectable Video Codecs, and Embedded Jetson Nano Support">
      <span class="img-caption">This month's sketch: The difference between a simple VAD interrupting every single user breathe vs. TurnV2 Echo smoothly ignoring backchannels.</span>
    </img></div>

    <div class="cta-box">
      <h3 style="margin-top:1;">Build with June's Updates</h3>
      <p>Configure TurnV2 (Echo) on the Inference Gateway, deploy on Jetson Nano, or upgrade your client SDKs to implement batched signaling and selectable video codecs.</p>
      <a href="https://app.videosdk.live" class="cta-button" style="margin-right:12px;">Dashboard</a>
      <a href="https://discord.com/invite/Gpmj6eCq5u" class="cta-button">Join our Discord</a>
    </div>

    <p style="text-align: center; margin-top: 40px; margin-bottom: 0;">
      Happy building!<br>
      <strong>Team VideoSDK</strong>
    </br></p>
  </hr></hr></hr></hr></hr></hr></div>
</body>
</html>
<!--kg-card-end: html-->
]]></content:encoded></item><item><title><![CDATA[Product Updates - May 2026 : Agent Runtime v2, Encrypted Recordings, and the Next-Gen Voice Pipeline]]></title><description><![CDATA[May brings Agent Runtime v2, secure Encrypted Recordings for regulated compliance, and a massive Voice Pipeline Overhaul with xAI and warm SIP transfers. Plus, check out the new native C++ SDK!]]></description><link>https://www.videosdk.live/blog/product-updates-may-2026</link><guid isPermaLink="false">6a2036f255831517a5a9fdad</guid><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 03 Jun 2026 14:18:05 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/06/product-update-may-2026-4.png" medium="image"/><content:encoded><![CDATA[
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    :root {
      --primary: #A497D9;
      --bg: #050608;
      --card-bg: #111217;
      --text-main: #E0E0E0;
      --text-muted: #A0A0A0;
      --border: #22242C;
    }
    body {
      font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      line-height: 1.7; color: var(--text-main); background-color: var(--bg); margin: 0; padding: 0;
    }
    .container { max-width: 850px; margin: 0 auto; padding: 60px 20px; }
    header { text-align: left; margin-bottom: 60px; }
    h2 { font-size: 28px; color: #FFFFFF; margin-top: 50px; padding-bottom: 10px; border-bottom: 1px solid var(--border); }
    h3 { font-size: 22px; color: #FFFFFF; margin-top: 35px; }
    p { margin-bottom: 20px; }
    strong { color: #FFFFFF; }
    ul, ol { margin-bottom: 20px; padding-left: 20px; }
    li { margin-bottom: 10px; }
    .highlight { color: var(--primary); font-weight: 600; }
    a { color: var(--primary); text-decoration: none; }
    a:hover { text-decoration: underline; }
    .ic { font-family: 'Fira Code','Cascadia Code','Consolas',monospace; font-size: 13.5px; color: #A497D9; font-weight: 700; }
    .card { background-color: var(--card-bg); border-radius: 12px; padding: 30px; margin: 30px 0; }
    .img-container { margin: 40px 0; text-align: center; position: relative;}
    .img-container img { width: 100%; height: auto; border-radius: 8px; }
    .cta-box { text-align: left; background: linear-gradient(135deg, #111217 0%, #1a1b23 100%); padding: 40px; border-radius: 12px; border: 1px solid var(--primary); margin: 60px 0; }
    @media (max-width: 600px) { .container { padding: 40px 15px; } }
  </style>
</meta></meta></head>
<body>
  <div class="container">
    <header>
      <img src="https://assets.videosdk.live/static-assets/ghost/2026/06/product-update-may-2026-4.png" alt="Product Updates - May 2026 : Agent Runtime v2, Encrypted Recordings, and the Next-Gen Voice Pipeline"/><p style="font-size:18px;color:#A0A0A0;margin:0;">May 2026 Updates: Dashboard Agent Runtime v2, Encrypted Recordings, and Next-Gen Voice Architectures.</p>
    </header>
    
    <p>Welcome to the May edition of the VideoSDK Monthly Updates! This month, we have focused on bringing <strong>production maturity, security compliance, and lower latency</strong> to your real-time video and AI applications.</p>
    <p>We are introducing <span class="highlight">Agent Runtime v2</span> on the dashboard, <span class="highlight">Encrypted Recordings</span> for sensitive compliance workflows, an expanded voice pipeline supporting <b>xAI Grok</b>, and a native C++ SDK for embedded Linux architectures like Raspberry Pi and NVIDIA Jetson. Let's explore the updates!</p>

    <!-- DASHBOARD EVOLUTION -->
    <h2>Dashboard Evolution: Agent Runtime v2 & Security</h2>
    <p>As developer requirements expand, our dashboard tools must scale to support complex user management, compliance, and direct system access.</p>
    <!-- <a href=" target="_blank">▶️ Watch Introduction Video</a> -->
    
    <h3>Agent Runtime v2</h3>
    <p><a href="https://app.videosdk.live/agent-v1" target="_blank">The no-code/low-code Agent Runtime</a> has received a major visual and feature upgrade (v2). While maintaining the core setup you are familiar with, v2 introduces key features designed for production-level management:</p>
    
    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/agent_runtime_templates_may_7bdea15d1b.png" alt="Product Updates - May 2026 : Agent Runtime v2, Encrypted Recordings, and the Next-Gen Voice Pipeline">
    </img></div>
    
    <ul>
      <li><strong>Fallback Model Support:</strong> Configure a secondary model to automatically take over if your primary model experiences issues or latency.</li>
    </ul>
    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/fallback_may_d1c972eaef.png" alt="Product Updates - May 2026 : Agent Runtime v2, Encrypted Recordings, and the Next-Gen Voice Pipeline">
    </img></div>
    
    <ul>
      <li><strong>Branching Logic:</strong> Manage agent versions securely by branching your configurations.</li>
    </ul>
    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/branching_may_a6b9f00c22.png" alt="Product Updates - May 2026 : Agent Runtime v2, Encrypted Recordings, and the Next-Gen Voice Pipeline">
    </img></div>
    
    <ul>
      <li><strong>Traffic Splitting:</strong> Safely deploy updates by splitting incoming call traffic among different branches for live A/B testing and gradual rollouts.</li>
    </ul>
    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/traffic_split_may_7825a84611.png" alt="Product Updates - May 2026 : Agent Runtime v2, Encrypted Recordings, and the Next-Gen Voice Pipeline">
    </img></div>

    <h3>Secure, Encrypted Recordings</h3>
    <p>Previously, session recordings saved in the cloud could be played back directly as standard MP4 files.</p>
    <p>Starting this month, you can configure <strong>Recording Encryption</strong>. Files are encrypted and only users possessing the private key can decrypt and play them back, ensuring zero unauthorized access.</p>

    <p><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/recording/recording-encryption" target="_blank">📄 Read The Recording Encryption Docs</a></p>
    

    <h3>Dashboard Telephony & Feedback Loop</h3>
    <ul>
      <li><strong><a href="https://app.videosdk.live/phonenumberv3" target="_blank">Consolidated Phone Numbers UI</a>:</strong> We have completely redesigned the Telephony interface to provide maximum flexibility, consolidating gateways directly into the Phone Numbers tab. It is now split into two clean views:
        <ul>
          <li><em>Phone Numbers:</em> Buy, import, or SIP configure your numbers along with gateway settings (includes 2 free demo numbers to start testing instantly).</li>
          <div class="img-container">
            <img src="https://strapi.videosdk.live/uploads/gateways_may_2997826656.png" alt="Product Updates - May 2026 : Agent Runtime v2, Encrypted Recordings, and the Next-Gen Voice Pipeline">
          </img></div>
          <div class="img-container">
            <img src="https://strapi.videosdk.live/uploads/phone_number_may_8c400fa374.png" alt="Product Updates - May 2026 : Agent Runtime v2, Encrypted Recordings, and the Next-Gen Voice Pipeline">
          </img></div>
          <li><em>Routing Rules:</em> Define precisely where incoming calls are directed, with the flexibility to map multiple phone numbers to a single routing rule.</li>
        </ul>
      </li>
      <li><strong>Native Feedback Tool:</strong> We want to hear from you! A new feedback button on the dashboard allows you to report bugs, suggest features, request improvements, or send a compliment directly to the VideoSDK team.</li>
    </ul>

    <hr>

    <!-- NEXT-GEN VOICE PIPELINE -->
    <h2>AI Agents: Next-Gen Voice Pipeline</h2>
    <p>Our voice framework received its most extensive optimizations yet to deliver ultra-low Time-To-First-Byte (TTFB) latencies and a more human-like flow.</p>

    <h3>Major Performance Overhaul (Agents SDK v1.0.13)</h3>
    <p>We rebuilt key components of the streaming voice pipeline to minimize delays and prevent stutter:</p>
    <ul>
      <li><strong>Websocket Prewarm & Reuse:</strong> Persistent connections are pre-warmed and recycled to eliminate connection handshakes.</li>
      <li><strong>Streaming-Safe Tokenizer:</strong> Text is passed through a new flow: <span class="ic">LLM</span> &rarr; <span class="ic">text-filter</span> &rarr; <span class="ic">chunker</span> &rarr; <span class="ic">TTS</span> to prevent pauses mid-sentence.</li>
      <li><strong>Multilingual Normalization:</strong> Added script-aware segmentation, currency verbalization, and an expanded Indic-language tokenizer.</li>
    </ul>

    <h3>Ecosystem Expansion: xAI Grok Support (v1.0.12)</h3>
    <p>You can now use xAI's Grok directly in your pipeline. We've introduced <span class="ic">XAISTT</span> (WebSocket-based streaming STT) and <span class="ic">XAITTS</span> (WebSocket-based expressive synthesis with support for inline tag formatting).</p>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">from videosdk.agents import Pipeline
from videosdk.plugins.xai import <span style="color:#A497D9;">XAILLM, XAISTT, XAITTS</span>

pipeline = <span style="color:#A497D9;">Pipeline</span>(
    stt=<span style="color:#A497D9;">XAISTT</span>(),
    llm=<span style="color:#A497D9;">XAILLM</span>(),
    tts=<span style="color:#A497D9;">XAITTS</span>()
)</pre>
    </div>

    <h3>Conversational Nuance: TTS Caching & Interruption Fading</h3>
    <ul>
      <li><strong>Audio Caching (v1.0.15):</strong> Pass an optional <span class="ic">audio_data</span> parameter to bypass the TTS engine entirely for static, predictable phrases (like welcomes or goodbyes), dropping latency to near zero.</li>
      <li><strong>Interruption Fade-out:</strong> Instead of cutting audio mid-sample when a user speaks over the agent, the buffered TTS audio is ducked down with an exponential fade-out to sound natural.</li>
    </ul>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;"><span style="color:#5c6370;"># Play a pre-rendered PCM file for zero-latency greeting</span>
await session.say(
    "Thanks for calling. How can I help?",
    audio_data=load_audio_file("greeting.ogg")
)</pre>
    </div>

    <hr>

    <!-- TELEPHONY & FAILOVER -->
    <h2>Telephony, Observability & Failover</h2>

    <h3>Warm Handoffs: SIP-to-SIP Transfers</h3>
    <p>Agents SDK v1.0.13 adds native support for <strong>attended SIP transfers</strong>. Your voice agent can now place a caller on hold, dial a human supervisor, brief them using an AI-generated summary of the conversation history, and gracefully execute a warm transfer without dropping the call.</p>

    <h3>Latency-Based Provider Fallback (v1.0.16)</h3>
    <p>Failover is no longer binary. You can now configure fallback providers to trigger not just when a service is completely down, but when its observed latency (over consecutive turns) crosses your budget threshold.</p>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">stt = FallbackSTT(
    [DeepgramSTT(), OpenAI_STT()],
    latency_threshold_ms=1200,      <span style="color:#5c6370;"># Failover if STT takes > 1.2s</span>
    consecutive_latency_hits=3      <span style="color:#5c6370;"># Trigger on 3 slow responses</span>
)</pre>
    </div>

    <h3>Realtime Mode Hooks Parity (v1.0.12)</h3>
    <p>You can now use `@pipeline.on` turn and LLM hooks in the Realtime (S2S) pipeline. This brings complete code parity between Cascade and Realtime pipelines. The same hooks run unchanged across both architectures.</p>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;"><span style="color:#A497D9;">@pipeline.on("user_turn_start")</span>
async def on_user_turn_start(transcript: str):
    logging.info(f"[USER] {transcript}")

<span style="color:#A497D9;">@pipeline.on("llm")</span>
async def on_llm(data: dict):
    logging.info(f"[AGENT] {data['text']}")</pre>
    </div>

    <p><a href="https://github.com/videosdk-live/agents/releases" target="_blank">Read full release notes on GitHub</a></p>

    <hr>

    <!-- CORE SDK UPDATES -->
    <h2>Core SDK updates</h2>

    <h3>JS &amp; React: Pre-Call Testing &amp; Node 22</h3>
    <p>We have introduced <span class="ic">runPreCallTest()</span> to JS v0.8.0 and React v0.10.0. This allows developers to check a user's network stability and hardware capabilities before they join the session, replacing the deprecated network stats API.</p>
    <p>Additionally, our dependency update to mediasoup brings official support for <strong>Node 22</strong> across JS and React SDKs.</p>

    <h3>iOS SDK (v2.8.0): AV1 &amp; VP9 Support</h3>
    <p>iOS developers can now leverage high-efficiency video codecs. Native support for <strong>AV1 and VP9</strong> has been added. If the hardware does not support the requested codec, the SDK handles graceful fallback to VP8 and throws a clear exception (<span class="ic">ERROR_VIDEO_CODEC_NOT_SUPPORTED</span>).</p>

    <h3>VideoSDK C++ SDK (v0.0.1-beta.3)</h3>
    <p>We are launching our <a href="https://github.com/videosdk-live/videosdk-rtc-cpp-sdk" target="_blank&quot;">official C++ SDK</a> bringing native WebRTC video and audio capabilities to Linux ARM64 (aarch64) platforms. Perfect for embedded hardware like Raspberry Pi or NVIDIA Jetson boards.</p>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">bash</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">curl -fsSL https://raw.githubusercontent.com/videosdk-live/videosdk-rtc-cpp-sdk/main/install.sh | sudo sh</pre>
    </div>

    <ul>
      <li><a href="https://docs.videosdk.live/js/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank"><strong>JS SDK</strong> v0.8.0</a></li>
      <li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank"><strong>React SDK</strong> v0.10.0</a></li>
      <li><a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank"><strong>iOS SDK</strong> v2.8.0</a></li>
      <li><a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/release-notes" target="_blank"><strong>Android SDK</strong> 1.2.1</a></li>
      <li><a href="https://github.com/videosdk-live/videosdk-rtc-cpp-sdk/releases/tag/v0.0.1-beta.3" target="_blank"><strong>C++ SDK</strong> v0.0.1-beta.3</a></li>
    </ul>

    <hr>

    <!-- RESOURCES -->
    <h2>📚 New Content & Resources</h2>
    <ul>
      <li><strong>React Starter App:</strong> <a href="https://youtu.be/FuKM9Y1qtuQ?si=nmWn8o-hJFBWn4bl" target="_blank">How to Add a Voice AI Agent to Your React App with VideoSDK</a></li>

      <li><strong>Starter App Blogs:</strong> <a href="https://www.videosdk.live/blog/page/2" target="_blank">Checkout new guides to add ai voice agent to your react and android apps</a></li>
      <!--
      <li><strong>Implementing Encryption:</strong> <a href="[LINK-TO-ENCRYPTION-GUIDE]" target="_blank">How to set up end-to-end encrypted recordings for sensitive compliance requirements.</a></li>
      <li><strong>Warm Handoff Tutorials:</strong> <a href="[LINK-TO-TELEPHONY-GUIDE]" target="_blank">Handling warm SIP transfers and agent huddle patterns.</a></li>
      -->
    </ul>
      
    <hr>

    <!-- SKETCHES -->
    <h2>SDK Sketches</h2>
    <div class="img-container">
      <img src="https://assets.videosdk.live/images/may-sdk-sketch.png" alt="Product Updates - May 2026 : Agent Runtime v2, Encrypted Recordings, and the Next-Gen Voice Pipeline">
      <span class="img-caption">This month's sketch: Downloading an unencrypted recording vs. Private-key encrypted security.</span>
    </img></div>

    <div class="cta-box">
      <h3 style="margin-top:0;">Build with May's Updates</h3>
      <p>Log in to access Agent Runtime v2 or upgrade to the latest SDK versions to implement encryption and high-efficiency codecs.</p>
      <a href="https://app.videosdk.live" class="cta-button" style="margin-right:12px;">Dashboard</a>
      <a href="https://discord.com/invite/Gpmj6eCq5u" class="cta-button">Join our Discord</a>
    </div>

    <p style="text-align: center; margin-top: 40px; margin-bottom: 0;">
      Happy building!<br>
      <strong>Team VideoSDK</strong>
    </br></p>
  </hr></hr></hr></hr></hr></div>
</body>
</html>
<!--kg-card-end: html-->
]]></content:encoded></item><item><title><![CDATA[Product Updates - April 2026 : RTC Alerts, Conversational Graphs, Batch Calling, Native Agent Metrics and more]]></title><description><![CDATA[April shipments are live: Introducing proactive RTC Alerts, deterministic Conversational Graphs, and Batch Calling for massive voice automation. Plus, connect VideoSDK Agents docs context to Claude/Cursor via our new Agents Docs MCP.
]]></description><link>https://www.videosdk.live/blog/product-updates-april-2026</link><guid isPermaLink="false">69ef20cc55831517a5a8a7ea</guid><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 01 May 2026 07:35:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/04/April-2026-monthly-update-1.png" medium="image"/><content:encoded><![CDATA[
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    :root {
      --primary: #A497D9;
      --bg: #050608;
      --card-bg: #111217;
      --text-main: #E0E0E0;
      --text-muted: #A0A0A0;
      --border: #22242C;
    }
    body {
      font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      line-height: 1.7; color: var(--text-main); background-color: var(--bg); margin: 0; padding: 0;
    }
    .container { max-width: 850px; margin: 0 auto; padding: 60px 20px; }
    header { text-align: left; margin-bottom: 60px; }
    h2 { font-size: 28px; color: #FFFFFF; margin-top: 50px; padding-bottom: 10px; border-bottom: 1px solid var(--border); }
    h3 { font-size: 22px; color: #FFFFFF; margin-top: 35px; }
    p { margin-bottom: 20px; }
    strong { color: #FFFFFF; }
    ul, ol { margin-bottom: 20px; padding-left: 20px; }
    li { margin-bottom: 10px; }
    .highlight { color: var(--primary); font-weight: 600; }
    a { color: var(--primary); text-decoration: none; }
    a:hover { text-decoration: underline; }
    .ic { font-family: 'Fira Code','Cascadia Code','Consolas',monospace; font-size: 13.5px; color: #A497D9; font-weight: 700; }
    .card { background-color: var(--card-bg); border-radius: 12px; padding: 30px; margin: 30px 0; }
    .img-container { margin: 40px 0; text-align: center; }
    .img-container img { width: 100%; height: auto; border-radius: 8px; }
    .cta-box { text-align: left; background: linear-gradient(135deg, #111217 0%, #1a1b23 100%); padding: 40px; border-radius: 12px; border: 1px solid var(--primary); margin: 60px 0; }
    @media (max-width: 600px) { .container { padding: 40px 15px; } }
  </style>
</meta></meta></head>
<body>
  <div class="container">
    <header>
      <img src="https://assets.videosdk.live/static-assets/ghost/2026/04/April-2026-monthly-update-1.png" alt="Product Updates - April 2026 : RTC Alerts, Conversational Graphs, Batch Calling, Native Agent Metrics and more"/><p style="font-size:18px;color:#A0A0A0;">April 2026 Roundup: Proactive RTC Alerts, Deterministic Conversational Graphs, and Intelligent Context Management.</p>
    </header>
    <p>Welcome to the April edition of the VideoSDK Monthly Updates! This month, we have focused on moving from reactive monitoring to <strong>proactive reliability</strong> and giving AI agents a structured "brain" for complex business logic.</p>
    <p>From the launch of <span class="highlight">RTC Alerts</span> to the new <span class="highlight">Conversational Graph</span> support and the <span class="highlight">ContextWindow</span> for smarter memory, April marks a significant leap in our AI and infrastructure capabilities. Let's dive into what we shipped!</p>

    <!-- RTC ALERTS -->
    <h2>Proactive RTC Alerts</h2>
    <p>In any real-time application, quality is the product. Unlike traditional systems, RTC failures are often subtle degradations - choppy video, breaking audio, or lagging screenshare. To solve this, we are introducing <strong>VideoSDK Alerts</strong>.</p>
    <p>RTC Alerts shift monitoring from passive observation to active detection. Instead of waiting for user complaints, you can now define metric-driven thresholds that trigger instant notifications.</p>
    
    <h3>Core Capabilities of RTC Alerts:</h3>
    <ul>
      <li><strong>Metric-Driven Monitoring:</strong> Build alerts based on Jitter, Latency, and Packet Loss across Camera or Screen Share streams.</li>
      <li><strong>Dimensional Filtering:</strong> Scope alerts by <strong>Region</strong> (e.g., APAC, US-East), <strong>OS</strong>, <strong>Browser</strong>, or <strong>SDK</strong> to isolate specific environmental issues.</li>
      <li><strong>Aggregation Logic:</strong> Use <strong>Max</strong> (worst-case), <strong>Average</strong>, or <strong>Percentiles</strong> to define what constitutes a failure.</li>
      <li><strong>Noise Reduction:</strong> Configure <strong>Minimum Session Impact</strong> (to ignore single-user outliers) and <strong>Time-Based Validation</strong> (to ignore transient spikes).</li>
      <li><strong>Historical Validation:</strong> Test your alert logic against past data before deployment to ensure accuracy.</li>
      <li><strong>Multi-Channel Delivery:</strong> Direct integration with <strong>Slack</strong>, <strong>PagerDuty</strong>, and <strong>Webhooks</strong>.</li>
    </ul>

    <!--<p><a href="https://www.videosdk.live/blog/introducing-rtc-alerts" target="_blank">Read the full RTC Alerts blog post</a> -->

    <p>▶️ <a href="https://youtu.be/sOhOw7R9dCM">Overview Video</a>
    <!--    <div class="img-container" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;">-->
      <!-- <iframe src="https://www.linkedin.com/embed/feed/update/urn:li:ugcPost:7447592366921871360?collapsed=1" height="550" width="504" frameborder="0" allowfullscreen="" title="Embedded post"></iframe> -->
    <!--</div></p>-->

    <hr>

    <!-- CONVERSATIONAL GRAPHS -->
    <h2>AI Agents: Rigid Control & Large-Scale Automation</h2>
    
    <h3>Conversational Graphs: Deterministic Workflows</h3>
    <p>Agents SDK v1.0.6 introduces directed graph support. This allows you to build multi-turn agents where you define the exact transitions between states (e.g., "Greeting" → "Booking" → "Payment"). The engine follows your routing exactly - the LLM handles the conversation, but never makes unauthorized routing decisions.</p>
    
    <p><a href="https://docs.videosdk.live/conversational_graph/introduction" target="_blank">📄 Read the Conversational Graphs docs</a></p>
    
<!--<p><a href="https://www.videosdk.live/blog/introducing-conversational-graphs" target="_blank">Read the Conversational Graphs blog post</a></p> -->

<p><a href="https://youtu.be/Oc2dluKb86I" target="_blank">▶️ Watch Introduction Video</a></p>
    
    
    
    <h3>Batch Calling: Voice Outreach at Scale</h3>
    <p>Our new <a href="https://app.videosdk.live/batch-calling" target="_blank">Batch Calling</a> infrastructure allows you to trigger hundreds of AI-powered voice calls simultaneously from the dashboard. This is designed for high-concurrency outbound use cases like automated reminders and large-scale customer surveys.</p>
    <div class="img-container">
      <img src="https://assets.videosdk.live/images/batch-calling.png" alt="Product Updates - April 2026 : RTC Alerts, Conversational Graphs, Batch Calling, Native Agent Metrics and more">
    </img></div>

    <hr>


    <!-- AI-Native Development: Agents MCP Server -->
<h2>AI-Native Development: Agents MCP Server</h2>
<p>We've launched the official <strong>Agents MCP Server</strong>. This allows you to provide the full, real-time context of our Agents documentation to AI coding assistants like Claude, Cursor, and VS Code. By connecting your AI to our docs, you can generate implementation code that follows our latest v1 standards and patterns automatically.</p>
<p>👉 <a href="https://docs.videosdk.live/ai_agents/docs-mcp-server" target="_blank">View the Agents MCP Server Setup Guide</a></p>
    
    <hr>

    <!-- CONTEXT WINDOW & AGENT INTELLIGENCE -->
    <h2>Agent Intelligence: Smarter Memory & Gated Speech</h2>

    <h3>ContextWindow: Intelligent Memory</h3>
    <p>Agents SDK v1.0.3 introduces the <a href="https://docs.videosdk.live/ai_agents/core-components/context-window" target="_blank">ContextWindow</a>. Instead of "blindly" truncating the oldest messages when token limits are reached, this feature uses history compression and summarization. It preserves the last <i>N</i> turns raw to maintain conversation quality while summarizing older history.</p>
    
    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">from videosdk.agents import <span style="color:#A497D9;">ContextWindow</span>

pipeline = <span style="color:#A497D9;">Pipeline</span>(
    ....
    context_window=<span style="color:#A497D9;">ContextWindow</span>(
        max_tokens=4000,
        max_context_items=20,
        keep_recent_turns=3,          <span style="color:#5c6370;"># Keep last 3 turns raw</span>
        max_tool_calls_per_turn=10,   <span style="color:#5c6370;"># Prevent infinite loops</span>
    ),
)</pre>
    </div>

    <h3>Startup Speech Gating</h3>
    <p>To prevent the user from interrupting an agent's initial greeting, we have implemented <strong>Early Speech Gating</strong> (v1.0.7). User audio is now gated until the agent has initiated its first <span class="ic">say()</span> or <span class="ic">reply()</span>, ensuring a professional and clear start to every interaction.</p>

<p><a href="https://github.com/videosdk-live/agents/releases" target="_blank">Read full release notes on GitHub</a></p>
    <hr>

    <!-- OBSERVABILITY & METRICS -->
    <h2>Observability & Metrics</h2>

    <h3>Unified Observability Configuration</h3>
    <p>You can now pass all observability settings - recording, traces, metrics, and logs - directly at session startup (v1.0.9).</p>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">await session.start(
   wait_for_participant=True,
   observability=<span style="color:#A497D9;">ObservabilityOptions</span>(
       recording=<span style="color:#A497D9;">RecordingOptions</span>(video=True),        
       traces=<span style="color:#A497D9;">TracesOptions</span>(export_url="https://otlp-endpoint"),
       logs=<span style="color:#A497D9;">LoggingOptions</span>(level=["INFO", "DEBUG"]),  
   ),
)</pre>
    </div>

    <h3>Pipeline & Metrics Hooks</h3>
    <p>Agents SDK v1.0.7 adds deep visibility hooks. Use <span class="ic">@pipeline.metrics.on("stt")</span> or <span class="ic">@pipeline.metrics.on("realtime")</span> to capture latency and token usage. You can also now use <span class="ic">session.get_context_history</span> to access session data for debugging or post-processing.</p>

    <h3>Native SDK Agent Metrics</h3>
    <p>Real-time agent performance data is now exposed directly in the client-side SDKs. Monitor latency, tokens, and component health via:</p>
    
    
    <ul>
      <li><a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/release-notes#v072" target="_blank"><strong>JS SDK v0.7.2</strong></a> - <span class="ic">agent-metrics</span> event on <span class="ic">AgentParticipant</span></li>
      <li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/release-notes#v091" target="_blank"><strong>React SDK v0.9.1</strong></a> - <span class="ic">onAgentMetrics()</span> callback</li>
      <li><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/release-notes#v390" target="_blank"><strong>Flutter SDK v3.9.0</strong></a> - <span class="ic">Events.agentMetrics</span> event</li>
    </ul>

    <h3>Hardware-Silence Detection</h3>
    <p>Available in <strong>JS SDK v0.7.2</strong> and <strong>React SDK v0.9.1</strong>, the <span class="ic">audio-input-silence</span> event triggers when a microphone is publishing but no audio signal is detected. This allows you to alert users to hardware mutes or Bluetooth issues immediately.</p>

    <hr>

    <!-- INTERACTIVE TRANSCRIPTS -->
    <h2>Interactive Transcripts & Ecosystem</h2>

    <h3>Word-level Timestamps & Interim Transcripts</h3>
    <p>Agents SDK v1.0.9 adds support for streaming agent transcripts with word-level timestamps (for <strong>Cartesia</strong> and <strong>ElevenLabs</strong>). Additionally, you can now enable interim user results to show text on the UI as the user is still speaking.</p>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;"><span style="color:#5c6370;"># Opt-in to word-level sync</span>
tts = CartesiaTTS(word_timestamps=True)
<span style="color:#5c6370;"># Opt-in to interim user results (v1.0.10)</span>
stt = DeepgramSTT(forward_interim_transcripts=True)</pre>
    </div>

    <h3>Core SDK Stability & Performance</h3>
    

    <ul>
      <li><a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/release-notes#v271" target="_blank"><strong>iOS SDK v2.7.1</strong></a> - Resolved rare crashes in screenshare/PubSub and optimized stats collection for large meetings.</li>
      <li><a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/release-notes#v120" target="_blank"><strong>Android SDK v1.2.0</strong></a> - Rewritten audioManager logic to resolve complex Bluetooth handoff issues.</li>
      <li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/release-notes#v091" target="_blank"><strong>React SDK v0.9.1</strong></a> and <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/release-notes#v0101" target="_blank"><strong>React Native SDK v0.10.1</strong></a> - Fixed unnecessary re-render issues and improved webcam toggle state handling.</li>
    </ul>


    <hr>

    <!-- DASHBOARD -->
    <h2>Dashboard Power-ups</h2>
    <ul>
      <li><strong>Agent Logs:</strong> A dedicated tab in <a href="https://app.videosdk.live/agents/sessions">session details</a> to view raw execution logs for debugging.</li>
      <li><strong>Composite Recording:</strong> Download a unified view of agent-user interactions in a single MP4.</li>
      <li><strong>Batch Calling & Alerts:</strong> Centralized UI to manage large-scale campaigns and configure proactive quality alerts.</li>
    </ul>

    <hr>

    <!-- RESOURCES -->
    <h2>📚 New Content & Resources</h2>
    <ul>
      <li><strong>Introducing VideoSDK AI Voice Agents v1:</strong> <a href="https://www.videosdk.live/blog/introducing-videosdk-ai-voice-agents-v1">The official v1 breakdown.</a></li>
      
<!--      <li><strong>Introducing VideoSDK RTC Alerts:</strong> Read <a href="https://gitmcp.io/videosdk-live/videosdk-docs">launch blog</a> here.</li>-->

<!--<li><strong>Blog:</strong> <a href="https://www.videosdk.live/blog/introducing-conversational-graphs">Building Deterministic Agents with Conversational Graphs</a></li>-->
<li><strong>Video:</strong> <a href="https://youtu.be/sOhOw7R9dCM">Proactive monitoring with RTC Alerts</a></li>
<li><strong>Video:</strong> <a href="https://youtu.be/Oc2dluKb86I">Deterministic Agent Workflows with Graphs</a></li>
      
    </ul>

    <h3>Featured Videos</h3>
    <ul>
        <!--<li>▶️ <a href="https://www.linkedin.com/feed/update/urn:li:activity:7447592523981553664">VideoSDK Agents v1 Official Launch</a>
        <div class="img-container" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;">
      <iframe src="https://www.linkedin.com/embed/feed/update/urn:li:ugcPost:7447592366921871360?collapsed=1" height="550" width="504" frameborder="0" allowfullscreen="" title="Embedded post"></iframe>
    </div></li>-->

        <li>▶️ <a href="https://youtu.be/_ufjI8nravE?si=Kgo2NTLCb-Sf4lon">Building with Agents MCP server</a>
      <div class="img-container" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;">
      <iframe width="560" height="315" src="https://www.youtube.com/embed/_ufjI8nravE?si=gAkTv4Rw6pe0AAwU" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
    </div>
        </li>
    </ul>

    <hr>

    
    
<h2>✨ Community Spotlight</h2>  

    <div class="img-container">
      <a href="https://www.videosdk.live/customers/refrens">
        <img src="https://assets.videosdk.live/images/founder-refrens.png" alt="Product Updates - April 2026 : RTC Alerts, Conversational Graphs, Batch Calling, Native Agent Metrics and more" style="border: none; box-shadow: none;">
      </img></a>
    </div>

    <div style="border-left: 3px solid var(--primary); padding-left: 20px; margin-top: 30px; margin-bottom: 30px;">
        <a href="https://www.videosdk.live/customers/refrens" style="font-size: 18px; line-height: 1.5;">Explore How Refrens Automated Lead Qualification at Scale with 10x Coverage Using VideoSDK Agents.</a>
    </div>

    <div class="img-container">
      <a href="https://www.videosdk.live/customers/refrens">
        <img src="https://assets.videosdk.live/images/vaidik-refrens.png" alt="Product Updates - April 2026 : RTC Alerts, Conversational Graphs, Batch Calling, Native Agent Metrics and more" style="border: none; box-shadow: none;">
      </img></a>
    </div>

    
    <!-- SDK SKETCHES -->
    <h2>SDK Sketches</h2>
    <div class="img-container">
      <img src="https://assets.videosdk.live/images/april-sdk-sketch.png" alt="Product Updates - April 2026 : RTC Alerts, Conversational Graphs, Batch Calling, Native Agent Metrics and more" style="max-width:620px;">
      <span class="img-caption">This month's sketch: Mass calling leads and getting only 3-4% of them qualified?....save your time for the important clients by giving the boring calls to agent with batch-calling</span>
    </img></div>

    <div class="cta-box">
      <h3 style="margin-top:0;">Build with April's Updates</h3>
      <p>Configure RTC Alerts and Batch Calling via the dashboard, or upgrade to Agents SDK v1.0.10 today.</p>
      <a href="https://app.videosdk.live" style="background-color:#A497D9;color:#000000;padding:8px 22px;border-radius:6px;font-size:14px;font-weight:700;display:inline-block;text-decoration:none;margin-right:12px;">Dashboard</a>
      <a href="https://discord.com/invite/Gpmj6eCq5u" style="background-color:#A497D9;color:#000000;padding:8px 22px;border-radius:6px;font-size:14px;font-weight:700;display:inline-block;text-decoration:none;">Join our Discord</a>
    </div>

    <p style="text-align: center; margin-top: 60px;">
      Happy building!<br>
      <strong>Team VideoSDK</strong>
    </br></p>
  </hr></hr></hr></hr></hr></hr></hr></hr></p></div>
</body>
</html>
<!--kg-card-end: html-->
]]></content:encoded></item><item><title><![CDATA[Introducing Prism - VideoSDK Agents V1.0.0]]></title><description><![CDATA[Learn more about Prism - VideoSDK Agent V1.0.0 , a complete rethink of the VideoSDK AI voice pipeline, built for full control, flexibility, and production-scale reliability.]]></description><link>https://www.videosdk.live/blog/introducing-videosdk-ai-voice-agents-v1</link><guid isPermaLink="false">69d3404055831517a5a8a61a</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 07 Apr 2026 13:07:03 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/04/Agent-V1---6.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/04/Agent-V1---6.png" alt="Introducing Prism - VideoSDK Agents V1.0.0"/><p><em>A complete rearchitecture of the VideoSDK AI voice pipeline.</em></p><p>We've been building AI voice agents for a while now. And the more we built, the more we ran into the same wall: the pipeline was in the way.</p><p>You couldn't swap a voice. You couldn't intercept what the LLM sees. You couldn't mix a custom STT with a realtime model. And when something broke in production, there was nothing to look at - no traces, no metrics, no logs.</p><p>So we rebuilt everything.</p><p>Today we're releasing <strong>Prism: Agents V1.0.0</strong>, a stable, production-ready rearchitecture of the VideoSDK Agents framework. It is not backward compatible with v0.x.</p><blockquote><a href="https://github.com/videosdk-live/videosdk-agents/releases/tag/v1.0.0">Full release notes and migration guide →</a></blockquote><h2 id="what-was-broken-in-v0x">What was broken in v0.x</h2><p>The old framework had two pipeline classes: <code>CascadingPipeline</code> for STT → LLM → TTS chains, and <code>RealtimePipeline</code> for speech-to-speech models. Every new capability we wanted to add was fighting the architecture.</p><p>Hybrid mode : running a custom STT into a realtime LLM  was impossible. The two pipelines had no way to talk to each other. If you didn't like the voice of your realtime model, you were stuck with it. If you wanted to clean or normalize a transcript before inference, there was no hook to do it. And observability was completely absent.</p><p>Adding features meant breaking things. So instead of patching it, we redesigned from scratch.</p><h2 id="agent-v1-architecture">Agent V1 architecture</h2><p>The <a href="https://docs.videosdk.live/ai_agents/core-components/overview" rel="noreferrer">Agent Session</a> orchestrates the entire workflow, combining the Agent with a Pipeline for real-time communication. The unified Pipeline automatically detects the best mode based on the components you provide whether that's a full cascade STT-LLM-TTS setup, a realtime speech-to-speech model, or a hybrid of both.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/agent_v1_architecture.jpg" class="kg-image" alt="Introducing Prism - VideoSDK Agents V1.0.0" loading="lazy" width="2208" height="1234"/></figure><ol><li><strong>Agent</strong>&nbsp;- This is the base class for defining your agent's identity and behavior. Here, you can configure custom instructions, manage its state, and register function tools.</li><li><a href="https://docs.videosdk.live/ai_agents/core-components/pipeline" rel="noreferrer"><strong>Pipeline</strong>&nbsp;</a>- This unified component manages the real-time flow of audio and data between the user and the AI models. It auto-detects the optimal mode based on the components you provide:<ul><li><strong>Cascade Mode</strong>&nbsp;- Provide STT, LLM, TTS, VAD, and Turn Detector for maximum flexibility and control over each processing stage.</li><li><strong>Realtime Mode</strong>&nbsp;- Provide a realtime model (e.g., OpenAI Realtime, Google Gemini Live, AWS Nova Sonic) for lowest-latency speech-to-speech processing.</li><li><strong>Hybrid Mode</strong>&nbsp;- Combine a realtime model with an external STT (for knowledge base support) or external TTS (for custom voice support).</li></ul></li><li><a href="https://docs.videosdk.live/ai_agents/core-components/agent-session" rel="noreferrer"><strong>Agent Session</strong></a>&nbsp;- This component brings together the agent and pipeline to manage the agent's lifecycle within a VideoSDK meeting.</li><li><a href="https://docs.videosdk.live/ai_agents/core-components/pipeline-hooks" rel="noreferrer"><strong>Pipeline Hooks</strong></a>&nbsp;- A middleware system for intercepting and processing data at any stage of the pipeline. Use hooks for custom STT/TTS processing, observing or modifying LLM output, lifecycle events, and more.</li></ol><h2 id="one-pipeline-class">One Pipeline Class</h2><p>The core change in V1 is the replacement of <code>CascadingPipeline</code> and <code>RealtimePipeline</code> with a single <code>Pipeline</code> class.</p><p>#Before</p><pre><code class="language-python">from videosdk.agents import CascadingPipeline, RealtimePipeline

pipeline = CascadingPipeline(stt=..., llm=..., tts=..., vad=..., turn_detector=...)
pipeline = RealtimePipeline(llm=OpenAIRealtime(...))
</code></pre><p>#After</p><pre><code class="language-python">from videosdk.agents import Pipeline

pipeline = Pipeline(stt=..., llm=..., tts=..., vad=..., turn_detector=...)
pipeline = Pipeline(llm=OpenAIRealtime(...))</code></pre><p>Pass any combination of components. The <code>PipelineOrchestrator</code> analyzes what you've given it and automatically selects the correct execution mode : cascade, realtime, or hybrid. You never configure it directly. You just pass components.</p><h2 id="three-modes-one-interface">Three Modes, One Interface</h2><p><strong>Cascade</strong> Mode -  full control over every stage.</p><pre><code class="language-python">pipeline = Pipeline(
    stt=DeepgramSTT(),
    llm=GoogleLLM(),
    tts=CartesiaTTS(),
    vad=SileroVAD(),
    turn_detector=TurnDetector(),
)
</code></pre><p><strong>Realtime</strong> Mode -  lowest latency, single model for the full voice pipeline.</p><pre><code class="language-python">pipeline = Pipeline(
    llm=GeminiRealtime(
        model="gemini-3.1-flash-live-preview",
        config=GeminiLiveConfig(voice="Leda", response_modalities=["AUDIO"]),
    )
)
</code></pre><p>Supported realtime models: <code>OpenAIRealtime</code>, <code>GeminiRealtime</code>, <code>AWSNovaSonic</code>, <code>AzureVoiceLive</code></p><p><strong>Hybrid</strong> : this is what was impossible before.</p><pre><code class="language-python"># Bring your own STT, use a realtime LLM
pipeline = Pipeline(stt=DeepgramSTT(), llm=OpenAIRealtime(...))

# Use a realtime LLM, bring your own voice
pipeline = Pipeline(llm=OpenAIRealtime(...), tts=ElevenLabsTTS(...))
</code></pre><p>You are no longer bounded by what the model provider gives you. Don't like the default voice? Swap it. Want your own transcription layer feeding a realtime model? Done.</p><h2 id="flexible-agent-composition">Flexible Agent Composition</h2><p>V1 also unlocks the ability to run partial pipelines for specific use cases.</p><pre><code class="language-python">Pipeline(stt=...)                     # Transcription agent
Pipeline(llm=...)                     # Text chatbot
Pipeline(stt=..., llm=..., tts=...)   # Voice + chat
Pipeline(stt=..., llm=..., tts=..., vad=..., turn_detector=...)      # Full voice agent
Pipeline(llm=OpenAIRealtime(...))     # Realtime voice agent
</code></pre><p>Same class, same structure, different capabilities depending on what you pass in.</p><h2 id="pipeline-hooks">Pipeline Hooks</h2><p><code>ConversationalFlow</code> is removed. In its place is <code>@pipeline.on(...)</code> : a decorator-based hooks system that lets you intercept and transform data at any stage, without subclassing anything.</p><pre><code class="language-python">@pipeline.on("stt")
async def on_transcript(text: str) -&gt; str:
    return text.strip()                        # normalize before LLM

@pipeline.on("tts")
async def on_tts(text: str) -&gt; str:
    return text.replace("SDK", "S D K")       # fix pronunciation

@pipeline.on("llm")
async def on_llm(messages):
    yield "Transferring you now."              # bypass LLM entirely
</code></pre><p>Hooks are available at every stage: <code>stt</code>, <code>tts</code>, <code>llm</code>, <code>vision_frame</code>, <code>user_turn_start</code>, <code>user_turn_end</code>, <code>agent_turn_start</code>, <code>agent_turn_end</code>. You can intercept raw audio streams at the <code>stt</code> and <code>tts</code> hooks — this is audio-level control, not just text.</p><blockquote><a href="https://github.com/videosdk-live/videosdk-agents/blob/main/examples/voice_pipeline_hooks.py">Hooks walkthrough →</a></blockquote><h2 id="observability-built-in">Observability, Built In</h2><p>Every V1 pipeline ships with per-component metrics, structured logging, and OpenTelemetry tracing across cascade, realtime, and hybrid modes. No extra setup. Configure custom endpoints via <code>RoomOptions</code>.</p><p>This was the biggest missing piece in v0.x. When something breaks in production, you now have something to look at.</p><h2 id="docs-mcp-server">Docs MCP Server</h2><p>Query VideoSDK documentation directly from your AI agent. The MCP server gives instant access to SDK references, implementation guides, and even source-level details inside your workflow. No manual searching, no context switching. Built for MCP-compatible agents like Claude, Cursor, or your own.</p><pre><code class="language- python">{
    "mcpServers": {
        "videosdkAgentDocs": {
            "serverUrl": "https://mcp.videosdk.live/mcp"
        }
    }
}</code></pre><blockquote>Explore the <a href="https://docs.videosdk.live/ai_agents/docs-mcp-server" rel="noreferrer">mcp-server docs -&gt;</a></blockquote><h2 id="agent-skills">Agent Skills</h2><p>Extend your agent with reusable capabilities. Define tools, actions, and behaviors once, and plug them into any pipeline. From API calls to complex workflows, Agent Skills let your agents do more than just respond - they can act, integrate, and automate.</p><blockquote>Explore the <a href="https://github.com/videosdk-live/agents/blob/main/examples/SKILLS.md" rel="noreferrer">agents-skills -&gt;</a></blockquote><h2 id="latency">Latency</h2><p>The pipeline stages in V1 run concurrently. STT, LLM, and TTS never block each other. TTS audio streams to the room as soon as the first chunk is generated not after full synthesis. In realtime mode, raw audio is routed directly to the model with zero transcription overhead.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/01_e2e_latency--1-.png" class="kg-image" alt="Introducing Prism - VideoSDK Agents V1.0.0" loading="lazy" width="3138" height="1590"/></figure><p>Interruptions are detected at the earliest possible point in the pipeline. In-flight LLM and TTS generation is cancelled immediately on user speech. Avatar audio flushes cleanly on interrupt with no residual artifacts.</p><p>We benchmarked V1 against the fastest pipelines in the industry. The numbers are in the release notes.</p><h2 id="22-production-ready-templates">22 Production Ready Templates</h2><p>We've shipped 22 production-ready agent templates covering the most common real-world use cases. Your logic. Your pipeline. These are the starting points.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/Screenshot-2026-04-08-at-4.29.50-PM.png" class="kg-image" alt="Introducing Prism - VideoSDK Agents V1.0.0" loading="lazy" width="3400" height="1682"/></figure><blockquote><a href="https://github.com/videosdk-live/videosdk-agents/tree/main/use_case_examples">Browse all examples →</a></blockquote><h2 id="breaking-changes">Breaking Changes</h2>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>v0.x</th>
<th>V1.0.0</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>CascadingPipeline</code></td>
<td><code>Pipeline</code></td>
</tr>
<tr>
<td><code>RealtimePipeline</code></td>
<td><code>Pipeline</code></td>
</tr>
<tr>
<td><code>ConversationalFlow</code></td>
<td><code>@pipeline.on(...)</code> hooks</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Function tools, agent lifecycle, <code>AgentSession</code>, <code>WorkerJob</code>, fallback providers, MCP tools, knowledge base, VAD, and turn detection all continue to work as before.</p><blockquote><a href="https://github.com/videosdk-live/videosdk-agents/releases/tag/v1.0.0#migration-guide">Full migration guide →</a></blockquote><h2 id="resources">Resources</h2><ul><li>Learn how to <a href="https://docs.videosdk.live/ai_agents/deployments/agent-cloud/cli/deploy" rel="noreferrer">deploy your agents</a>.</li><li>Follow the docs to start building your <a href="https://docs.videosdk.live/ai_agents/introduction" rel="noreferrer"> AI Voice Agents today</a></li><li>Contact our <a href="https://www.videosdk.live/contact" rel="noreferrer">sales team</a> to explore solutions tailored to your needs.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[Product Updates - March 2026 : Agents SDK v1.0.0, Unified Pipeline & Agent Participants Across All SDKs]]></title><description><![CDATA[One pipeline. Three modes. Five SDKs updated. March brings the stable release of Agents SDK v1.0.0 - a ground-up rebuild with a unified Pipeline class, real-time agent state tracking, and native Agent Participant support across JS, React, React Native, Flutter, and iOS.]]></description><link>https://www.videosdk.live/blog/product-updates-march-2026</link><guid isPermaLink="false">69ce013255831517a5a8a5cb</guid><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 03 Apr 2026 06:45:47 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/04/March-2026.jpg" medium="image"/><content:encoded><![CDATA[
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    :root {
      --primary: #A497D9;
      --bg: #050608;
      --card-bg: #111217;
      --text-main: #E0E0E0;
      --text-muted: #A0A0A0;
      --border: #22242C;
    }
    body {
      font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      line-height: 1.7;
      color: var(--text-main);
      background-color: var(--bg);
      margin: 0;
      padding: 0;
    }
    .container { max-width: 850px; margin: 0 auto; padding: 60px 20px; }
    header { text-align: left; margin-bottom: 60px; }
    h2 { font-size: 28px; color: #FFFFFF; margin-top: 50px; padding-bottom: 10px; border-bottom: 1px solid var(--border); }
    h3 { font-size: 22px; color: #FFFFFF; margin-top: 35px; }
    p { margin-bottom: 20px; }
    strong { color: #FFFFFF; }
    ul, ol { margin-bottom: 20px; padding-left: 20px; }
    li { margin-bottom: 10px; }
    .highlight { color: var(--primary); font-weight: 600; }
    a { color: var(--primary); text-decoration: none; }
    a:hover { text-decoration: underline; }
    .ic { font-family: 'Fira Code','Cascadia Code','Consolas',monospace; font-size: 13.5px; color: #A497D9; font-weight: 700; }
    .card { background-color: var(--card-bg); border-radius: 12px; padding: 30px; margin: 30px 0; }
    .img-container { margin: 40px 0; text-align: center; }
    .img-container img { width: 100%; height: auto; border-radius: 8px; }
    .img-caption { font-size: 13px; color: var(--text-muted); margin-top: 10px; display: block; }
    .cta-button { background-color: var(--primary); color: #000000; padding: 6px 20px; border-radius: 6px; font-size: 15px; font-weight: bold; display: inline-block; text-decoration: none; }
    .cta-box { text-align: left; background: linear-gradient(135deg, #111217 0%, #1a1b23 100%); padding: 40px; border-radius: 12px; border: 1px solid var(--primary); margin: 60px 0; }
    @media (max-width: 600px) { .container { padding: 40px 15px; } }
  </style>
</meta></meta></head>
<body>
  <div class="container">
    <header>
      <img src="https://assets.videosdk.live/static-assets/ghost/2026/04/March-2026.jpg" alt="Product Updates - March 2026 : Agents SDK v1.0.0, Unified Pipeline & Agent Participants Across All SDKs"/><p style="font-size:18px;color:#A0A0A0;">A complete recap of everything we shipped in March 2026: Agents SDK v1.0.0, unified pipeline, and Agent Participant support across all RTC SDKs.</p>
    </header>
    <p>Welcome to the March edition of the VideoSDK Monthly Updates! This month marks one of the biggest milestones for our AI stack — the official launch of <span class="highlight">Agents v1.0.0</span>.</p>
    <p>We have reimagined how developers build AI agents with a unified pipeline architecture, introduced hooks for deep customization, expanded our plugin ecosystem, and rolled out agent support across every SDK. This is a huge one, let's get started!</p>

    <h2>Agents v1.0.0: A New Foundation for AI Voice Agents</h2>
    <p>This release is more than just an upgrade. It is a complete architectural shift. With Agents v1.0.0, we have unified multiple execution models into a single, flexible system that adapts to your use case automatically.</p>
    <div class="img-container">
      <img src="https://assets.videosdk.live/images/image%20%2860%29.png" alt="Product Updates - March 2026 : Agents SDK v1.0.0, Unified Pipeline & Agent Participants Across All SDKs">
    </img></div>
    <p><a href="https://github.com/videosdk-live/agents/releases/tag/v1.0.0" target="_blank">Read full release notes on GitHub</a></p>

    <h3>Unified Pipeline Architecture</h3>
    <p><span class="ic">CascadingPipeline</span> and <span class="ic">RealtimePipeline</span> have been replaced with a single <strong>Pipeline</strong> class. Configure one pipeline and the SDK automatically determines the execution mode based on the components you provide.</p>

    <h3>Cascade Mode: STT to LLM to TTS</h3>
    <p>Compose any provider chain for complete control over each stage.</p>
    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">pipeline = <span style="color:#A497D9;">Pipeline</span>(
    stt=DeepgramSTT(),
    llm=GoogleLLM(),
    tts=CartesiaTTS(),
    vad=SileroVAD(),
    turn_detector=TurnDetector(),
)
session = AgentSession(agent=MyAgent(), pipeline=pipeline)
await session.start(wait_for_participant=True, run_until_shutdown=True)</pre>
    </div>

    <h3>Realtime Mode: Lowest Latency with Unified Models</h3>
    <p>Use a single realtime model for the full voice pipeline.</p>
    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">pipeline = <span style="color:#A497D9;">Pipeline</span>(
    llm=GeminiRealtime(
        model=<span style="color:#98c379;">"gemini-3.1-flash-live-preview"</span>,
        config=GeminiLiveConfig(voice=<span style="color:#98c379;">"Leda"</span>, response_modalities=[<span style="color:#98c379;">"AUDIO"</span>]),
    )
)
session = AgentSession(agent=MyAgent(), pipeline=pipeline)
await session.start(wait_for_participant=True, run_until_shutdown=True)</pre>
    </div>
    <p>Other supported realtime models: <a href="https://docs.videosdk.live/ai_agents/plugins/realtime/openai" target="_blank"><span class="ic">OpenAIRealtime</span></a>, <a href="https://docs.videosdk.live/ai_agents/plugins/realtime/aws-nova-sonic" target="_blank"><span class="ic">AWSNovaSonic</span></a>, <a href="https://docs.videosdk.live/ai_agents/plugins/realtime/azure-voice-live" target="_blank"><span class="ic">AzureVoiceLive</span></a>, <a href="https://docs.videosdk.live/ai_agents/plugins/realtime/xai-grok" target="_blank"><span class="ic">xAI Grok</span></a>, <a href="https://docs.videosdk.live/ai_agents/plugins/realtime/ultravox" target="_blank"><span class="ic">Ultravox</span></a>.</p>

    <h3>Hybrid Mode: Mix Cascade and Realtime Components</h3>
    <p>Read the full <a href="https://docs.videosdk.live/ai_agents/core-components/pipeline#hybrid-mode" target="_blank">Hybrid Mode docs</a>.</p>
    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;"><span style="color:#5c6370;"># Custom STT + Realtime LLM (bring your own transcription)</span>
pipeline = <span style="color:#A497D9;">Pipeline</span>(stt=DeepgramSTT(), llm=OpenAIRealtime(...))
<span style="color:#5c6370;"># Realtime LLM + Custom TTS (bring your own voice)</span>
pipeline = <span style="color:#A497D9;">Pipeline</span>(llm=OpenAIRealtime(...), tts=ElevenLabsTTS(...))</pre>
    </div>

    <h3>Flexible Agent Composition</h3>
    <p>Just pass the components you need. The pipeline handles the rest.</p>
    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;"><span style="color:#A497D9;">Pipeline</span>(stt=...)                                         <span style="color:#5c6370;"># Transcription only</span>
<span style="color:#A497D9;">Pipeline</span>(llm=...)                                         <span style="color:#5c6370;"># Text chatbot</span>
<span style="color:#A497D9;">Pipeline</span>(stt=..., llm=..., tts=...)                       <span style="color:#5c6370;"># Voice + Chat</span>
<span style="color:#A497D9;">Pipeline</span>(stt=..., llm=..., tts=..., vad=..., turn_detector=...)  <span style="color:#5c6370;"># Full voice agent</span>
<span style="color:#A497D9;">Pipeline</span>(llm=OpenAIRealtime(...))                         <span style="color:#5c6370;"># Realtime voice agent</span></pre>
    </div>

    <h3>Pipeline Hooks System</h3>
    <p><span class="ic">ConversationalFlow</span> has been removed in favour of <span class="ic">@pipeline.on(...)</span> — a lightweight hooks engine that lets you intercept and transform data at any stage without subclassing. See the full <a href="https://docs.videosdk.live/ai_agents/core-components/pipeline-hooks" target="_blank">Pipeline Hooks docs</a>.</p>

    <!-- Hooks table — fully inline styled so Ghost can't override -->
    <table style="width:100%;border-collapse:collapse;margin:20px 0 28px;font-size:14px;background:transparent !important;">
      <thead>
        <tr>
          <th style="background:#16171e !important;color:#A497D9;padding:12px 16px;text-align:left;font-weight:700;border-bottom:1px solid #22242C;font-family:'Inter',sans-serif;">HOOK</th>
          <th style="background:#16171e !important;color:#A497D9;padding:12px 16px;text-align:left;font-weight:700;border-bottom:1px solid #22242C;font-family:'Inter',sans-serif;">WHAT YOU CAN INTERCEPT / MODIFY</th>
        </tr>
      </thead>
      <tbody>
        <tr>
          <td style="background:#111217 !important;padding:12px 16px;border-bottom:1px solid #22242C;color:#E0E0E0;vertical-align:top;"><span style="font-family:'Fira Code',monospace;color:#A497D9;font-weight:700;font-size:13px;background:none !important;padding:0;border:none !important;box-shadow:none !important;">stt</span></td>
          <td style="background:#111217 !important;padding:12px 16px;border-bottom:1px solid #22242C;color:#E0E0E0;vertical-align:top;">Incoming audio stream and transcript text. Clean, redact, or replace before LLM.</td>
        </tr>
        <tr>
          <td style="background:#111217 !important;padding:12px 16px;border-bottom:1px solid #22242C;color:#E0E0E0;vertical-align:top;"><span style="font-family:'Fira Code',monospace;color:#A497D9;font-weight:700;font-size:13px;background:none !important;padding:0;border:none !important;box-shadow:none !important;">tts</span></td>
          <td style="background:#111217 !important;padding:12px 16px;border-bottom:1px solid #22242C;color:#E0E0E0;vertical-align:top;">Outgoing text and synthesized audio stream. Adjust pronunciation, filter, or re-route.</td>
        </tr>
        <tr>
          <td style="background:#111217 !important;padding:12px 16px;border-bottom:1px solid #22242C;color:#E0E0E0;vertical-align:top;"><span style="font-family:'Fira Code',monospace;color:#A497D9;font-weight:700;font-size:13px;background:none !important;padding:0;border:none !important;box-shadow:none !important;">llm</span></td>
          <td style="background:#111217 !important;padding:12px 16px;border-bottom:1px solid #22242C;color:#E0E0E0;vertical-align:top;">Message list. Bypass the model entirely with a yield, or modify before inference.</td>
        </tr>
        <tr>
          <td style="background:#111217 !important;padding:12px 16px;border-bottom:1px solid #22242C;color:#E0E0E0;vertical-align:top;"><span style="font-family:'Fira Code',monospace;color:#A497D9;font-weight:700;font-size:13px;background:none !important;padding:0;border:none !important;box-shadow:none !important;">vision_frame</span></td>
          <td style="background:#111217 !important;padding:12px 16px;border-bottom:1px solid #22242C;color:#E0E0E0;vertical-align:top;">Raw video frames from participants</td>
        </tr>
        <tr>
          <td style="background:#111217 !important;padding:12px 16px;border-bottom:1px solid #22242C;color:#E0E0E0;vertical-align:top;"><span style="font-family:'Fira Code',monospace;color:#A497D9;font-weight:700;font-size:13px;background:none !important;padding:0;border:none !important;box-shadow:none !important;">user_turn_start</span> / <span style="font-family:'Fira Code',monospace;color:#A497D9;font-weight:700;font-size:13px;background:none !important;padding:0;border:none !important;box-shadow:none !important;">user_turn_end</span></td>
          <td style="background:#111217 !important;padding:12px 16px;border-bottom:1px solid #22242C;color:#E0E0E0;vertical-align:top;">User speaking lifecycle</td>
        </tr>
        <tr>
          <td style="background:#111217 !important;padding:12px 16px;border-bottom:none;color:#E0E0E0;vertical-align:top;"><span style="font-family:'Fira Code',monospace;color:#A497D9;font-weight:700;font-size:13px;background:none !important;padding:0;border:none !important;box-shadow:none !important;">agent_turn_start</span> / <span style="font-family:'Fira Code',monospace;color:#A497D9;font-weight:700;font-size:13px;background:none !important;padding:0;border:none !important;box-shadow:none !important;">agent_turn_end</span></td>
          <td style="background:#111217 !important;padding:12px 16px;border-bottom:none;color:#E0E0E0;vertical-align:top;">Agent response lifecycle</td>
        </tr>
      </tbody>
    </table>

    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;"><span style="color:#A497D9;">@pipeline.on("stt")</span>
async def on_transcript(text: str) -> str:
    return text.strip()          <span style="color:#5c6370;"># normalize before LLM</span>
<span style="color:#A497D9;">@pipeline.on("tts")</span>
async def on_tts(text: str) -> str:
    return text.replace(<span style="color:#98c379;">"SDK"</span>, <span style="color:#98c379;">"S D K"</span>)   <span style="color:#5c6370;"># fix pronunciation</span>
<span style="color:#A497D9;">@pipeline.on("llm")</span>
async def on_llm(messages):
    yield <span style="color:#98c379;">"Transferring you now."</span>  <span style="color:#5c6370;"># bypass LLM entirely</span></pre>
    </div>

    <h3>Observability</h3>
    <p>Per-component metrics, structured logging, and OpenTelemetry tracing are built in across all pipeline modes. Custom endpoints configurable via <span class="ic">RoomOptions</span>.</p>

    <h3>Anam AI Avatar Plugin</h3>
    <p>Bring your agents to life with the <strong>Anam AI</strong> avatar plugin. Attach it to your pipeline with <span class="ic">avatar=AnamAI(...)</span> and the framework handles WebRTC data channel audio routing, interrupts, and teardown automatically. Read the <a href="https://docs.videosdk.live/ai_agents/plugins/avatar/anam-ai" target="_blank">Anam AI plugin docs</a> or <a href="https://www.videosdk.live/blog/how-to-build-ai-virtual-avatars-using-anam-ai-and-videosdk-ai-voice-agents" target="_blank">read this blog for full setup</a>.</p>
    <div class="img-container">
      <img src="https://assets.videosdk.live/images/image%20%2859%29.png" alt="Product Updates - March 2026 : Agents SDK v1.0.0, Unified Pipeline & Agent Participants Across All SDKs">
    </img></div>

    <h3>LangChain and LangGraph Support</h3>
    <p>Drop in any LangChain <span class="ic">BaseChatModel</span> or LangGraph <span class="ic">StateGraph</span> as your pipeline LLM. See the full <a href="https://docs.videosdk.live/ai_agents/plugins/llm/langchain-llm" target="_blank">LangChain plugin docs</a>.</p>
    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">from videosdk.plugins.langchain import <span style="color:#A497D9;">LangChainLLM</span>, <span style="color:#A497D9;">LangGraphLLM</span>
<span style="color:#5c6370;"># Use any LangChain BaseChatModel</span>
pipeline = <span style="color:#A497D9;">Pipeline</span>(llm=LangChainLLM(model=ChatOpenAI(...)))
<span style="color:#5c6370;"># Use a LangGraph StateGraph</span>
pipeline = <span style="color:#A497D9;">Pipeline</span>(llm=LangGraphLLM(graph=my_graph))</pre>
    </div>

    <h3>Structured Recording</h3>
    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">from videosdk.agents import <span style="color:#A497D9;">RoomOptions</span>, <span style="color:#A497D9;">RecordingOptions</span>
room_options = <span style="color:#A497D9;">RoomOptions</span>(
    recording=True,  <span style="color:#5c6370;"># audio-only by default</span>
    recording_options=RecordingOptions(
        video=True,         <span style="color:#5c6370;"># opt-in to camera recording</span>
        screen_share=True,  <span style="color:#5c6370;"># opt-in to screen share recording</span>
    )
)</pre>
    </div>

    <div class="card" style="background-color:#111217;border-radius:12px;padding:30px;margin:30px 0;">
      <h3 style="margin-top:0;">Migrating from v0.x</h3>
      <p>Replace <span class="ic">CascadingPipeline</span> and <span class="ic">RealtimePipeline</span> with <span class="ic">Pipeline</span>. Replace any <span class="ic">ConversationalFlow</span> subclass with <span class="ic">@pipeline.on(...)</span> hooks. Constructor arguments stay the same. Everything else (AgentSession, WorkerJob, VAD, fallback providers, MCP tools) works as before.</p>
      <a href="https://github.com/videosdk-live/agents/releases/tag/v1.0.0" style="background-color:#A497D9;color:#000000;padding:8px 22px;border-radius:6px;font-size:14px;font-weight:700;display:inline-block;text-decoration:none;">Full Release Notes on GitHub</a>
    </div>

    <h2>Agent Participant Support Across All RTC SDKs</h2>
    <p>AI agents are now first-class citizens across every VideoSDK platform. All five RTC SDKs shipped native <strong>Agent Participant</strong> support this month. Your app can now detect, track, and react to AI agents in a room including live state changes and real-time transcription.</p>
    <ul>
      <li><strong>JS SDK</strong> v0.7.0</li>
      <li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/release-notes#v080" target="_blank"><strong>React SDK</strong> v0.8.0</a></li>
      <li><a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/release-notes#v090" target="_blank"><strong>React Native SDK</strong> v0.9.0</a></li>
      <li><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/release-notes#380" target="_blank"><strong>Flutter SDK</strong> v3.8.0</a></li>
      <li><a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/release-notes#v270" target="_blank"><strong>iOS SDK</strong> v2.7.0</a></li>
    </ul>

    <h3>What Every SDK Now Supports</h3>
    <ul>
      <li><strong>AgentParticipant / isAgent:</strong> When an agent joins a room, it is automatically identified as a distinct participant type. No manual detection needed.</li>
      <li><strong>AgentState enum:</strong> Track lifecycle with <span class="ic">IDLE</span>, <span class="ic">LISTENING</span>, <span class="ic">THINKING</span>, and <span class="ic">SPEAKING</span>. Know exactly what your agent is doing at any moment.</li>
      <li><strong>State change events:</strong> React and React Native expose <span class="ic">onAgentStateChange</span>; JS fires <span class="ic">agent-state-change</span>; iOS uses <span class="ic">onAgentStateChanged</span>; Flutter uses <span class="ic">Events.agentStateChanged</span>.</li>
      <li><strong>Live transcription:</strong> Receive real-time agent transcription with the speaking participant and a timestamped text segment, available across all five SDKs.</li>
    </ul>

    <h2>Google Gemini 3.1 Support</h2>
    <p>VideoSDK now supports <strong>Google Gemini 3.1</strong> in the realtime pipeline. Drop in <span class="ic">GeminiRealtime</span> with the latest model and get ultra-low-latency voice responses powered by Gemini's newest architecture.</p>
    <div style="background:#0d0e13 !important;border-radius:10px;overflow:hidden;margin:20px 0 28px;border:none !important;box-shadow:none !important;outline:none !important;">
      <div style="background:#16171e !important;padding:8px 18px;font-size:11px;font-weight:600;color:#6e7685;letter-spacing:0.08em;text-transform:uppercase;font-family:'Fira Code',monospace;">python</div>
      <pre style="padding:16px 18px;overflow-x:auto;font-family:'Fira Code','Cascadia Code','Consolas',monospace;font-size:13px;line-height:1.8;color:#c9d1d9;margin:0;background:#0d0e13 !important;border:none !important;box-shadow:none !important;outline:none !important;">pipeline = <span style="color:#A497D9;">Pipeline</span>(
    llm=GeminiRealtime(
        model=<span style="color:#98c379;">"gemini-3.1-flash-live-preview"</span>,
        config=GeminiLiveConfig(voice=<span style="color:#98c379;">"Leda"</span>, response_modalities=[<span style="color:#98c379;">"AUDIO"</span>]),
    )
)</pre>
    </div>
    <div class="img-container" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;">
      <iframe style="position:absolute;top:0;left:0;width:100%;height:100%;border:0 !important;border-radius:8px;" src="https://www.youtube.com/embed/J9Wqdqpqjx4?si=QX_W6MY0E-9NnJJ3" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
    </div>

    <h2>AI Voice Agent Starter Apps</h2>
    <p>Get up and running in minutes with our ready-to-use starter apps. Each one is pre-wired with Agent Participant support, live transcription, and AgentState UI out of the box.</p>
    <ul>
      <li><a href="https://docs.videosdk.live/ai_agents/agent-runtime/connect-agent/web-integrations/agent-starter-react" target="_blank"><strong>React Starter App</strong></a>: Web integration with full agent UI</li>
      <li><a href="https://docs.videosdk.live/ai_agents/agent-runtime/connect-agent/mobile-integrations/agent-starter-flutter" target="_blank"><strong>Flutter Starter App</strong></a>: Cross-platform mobile agent integration</li>
      <li><a href="https://docs.videosdk.live/ai_agents/agent-runtime/connect-agent/mobile-integrations/agent-starter-ios" target="_blank"><strong>iOS Starter App</strong></a>: Native iOS agent integration</li>
    </ul>

    <h2>New Content and Resources</h2>
    <p>New guides cover the unified Pipeline, hooks deep dive, agent lifecycle and events, and SDK-specific agent integration.</p>
    <h3>New Guides and Tutorials</h3>
    <ul>
      <li><strong>Deploy your AI Voice Agent:</strong> <a href="https://www.videosdk.live/blog/how-to-deploy-your-ai-voice-agents-in-videosdk" target="_blank">A step-by-step guide to deploying production-ready voice agents on VideoSDK.</a></li>
      <li><strong>Build AI Virtual Avatars with Anam AI:</strong> <a href="https://www.videosdk.live/blog/how-to-build-ai-virtual-avatars-using-anam-ai-and-videosdk-ai-voice-agents" target="_blank">How to build interactive AI avatars using the Anam AI plugin.</a></li>
      <li><strong>Pipeline hooks deep dive:</strong> <a href="https://docs.videosdk.live/ai_agents/core-components/pipeline-hooks" target="_blank">How to intercept and transform data at every pipeline stage.</a></li>
      <li><strong>LangChain and LangGraph integration:</strong> <a href="https://docs.videosdk.live/ai_agents/plugins/llm/langchain-llm" target="_blank">Connect agents to external tools and multi-step reasoning workflows.</a></li>
    </ul>
    <h3>Featured Videos</h3>
    <ul>
      <li>▶️ <a href="https://youtu.be/J9Wqdqpqjx4" target="_blank">Building with Google Gemini 3.1 on VideoSDK</a></li>
    </ul>

    <h2>SDK Sketches</h2>
    <div class="img-container">
      <img src="https://assets.videosdk.live/images/penguin1.png" alt="Product Updates - March 2026 : Agents SDK v1.0.0, Unified Pipeline & Agent Participants Across All SDKs" style="border-radius:8px;max-width:620px;">
      <span class="img-caption">This month's sketch: CascadingPipeline and RealtimePipeline walk into v1.0.0... and they're the same picture.</span>
    </img></div>

    <h2>What's Next?</h2>
    <p>As we move through 2026, our focus remains on pushing the boundaries of what's possible with real-time communication and AI. Expect even more powerful tools, deeper platform integrations, and a relentless focus on the developer experience.</p>

    <div class="cta-box">
      <h3 style="margin-top:0;">Ready to Build?</h3>
      <p>Upgrade to Agents SDK v1.0.0 and the latest RTC SDKs to get everything in this release.</p>
      <a href="https://github.com/videosdk-live/agents" style="background-color:#A497D9;color:#000000;padding:8px 22px;border-radius:6px;font-size:14px;font-weight:700;display:inline-block;text-decoration:none;margin-right:12px;">GitHub</a>
      <a href="https://discord.com/invite/Gpmj6eCq5u" style="background-color:#A497D9;color:#000000;padding:8px 22px;border-radius:6px;font-size:14px;font-weight:700;display:inline-block;text-decoration:none;">Join our Discord</a>
    </div>
  </div>
</body>
</html>
<!--kg-card-end: html-->
]]></content:encoded></item><item><title><![CDATA[VideoSDK is now available on Microsoft Marketplace]]></title><description><![CDATA[Build real-time video, live streaming and AI communication into your app. Pay per minute through your Microsoft invoice, with no contract and no minimum spend.]]></description><link>https://www.videosdk.live/blog/videosdk-microsoft-marketplace</link><guid isPermaLink="false">6abe3b16b3240feb748ca195</guid><category><![CDATA[ANNOUNCEMENT]]></category><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 08 Oct 2026 13:13:14 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/10/videosdk-microsoft-marketplace.webp" medium="image"/><content:encoded><![CDATA[<blockquote><em>Build real-time video, live streaming and AI communication into your app. Pay per minute through your Microsoft invoice, with no contract and no minimum spend.</em></blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/10/videosdk-microsoft-marketplace.webp" alt="VideoSDK is now available on Microsoft Marketplace"/><p>VideoSDK gives developers the SDKs and infrastructure to add real-time video, voice, live streaming and AI voice agents to an app. It is now listed on <a href="https://marketplace.microsoft.com/en-us/product/videosdk.videosdk">Microsoft Marketplace</a>, the single place that brings Azure Marketplace and AppSource together.</p><p>There is one plan, Pay as you go. You pay for the minutes you use.</p><h2 id="what-you-gain-by-buying-through-microsoft">What you gain by buying through Microsoft</h2><ul><li>VideoSDK usage is billed through the Microsoft invoice you already get.</li><li>There is no commitment, no minimum spend and no base platform fee.</li><li>You manage the subscription from the Azure portal.</li><li>If you need custom terms, the listing has a <strong>Request private offer</strong> button.</li></ul><h2 id="what-the-pay-as-you-go-plan-includes">What the Pay as you go plan includes</h2><ul><li>Audio and video calling on web, mobile and desktop</li><li>Interactive live streaming</li><li>Cloud recording in SD, HD and Full-HD</li><li>RTMP simulcast to YouTube, Facebook or any RTMP destination</li><li>Session quality analytics on every session, at no extra cost</li><li>SDKs for JavaScript, React, React Native, Android, iOS, Flutter, Python and Unity, plus REST APIs and webhooks</li></ul><p>Compliance add-ons are available on this plan too: HIPAA with a Business Associate Agreement, SOC 2, ISO 27001, GDPR and CERT-In.</p><h2 id="what-it-costs">What it costs</h2><p>Every rate is per minute, and the charges come through your Microsoft invoice.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>What you use</th>
<th>Rate</th>
</tr>
</thead>
<tbody>
<tr>
<td>Audio call</td>
<td>$0.001 per participant per minute</td>
</tr>
<tr>
<td>HD video call</td>
<td>$0.004 per participant per minute</td>
</tr>
<tr>
<td>Live stream viewers</td>
<td>from $0.0005 per viewer minute</td>
</tr>
<tr>
<td>HD cloud recording</td>
<td>$0.015 per minute</td>
</tr>
<tr>
<td>Recording storage</td>
<td>$0.003 per minute</td>
</tr>
<tr>
<td>RTMP simulcast</td>
<td>$0.03 per minute</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>A one-hour HD video call with four people is 240 participant-minutes, which comes to $0.96.</p><p>Each resolution has its own rate, so you pay more only when you go to Full-HD or above. The full list is under Plans + Pricing on the listing.</p><h2 id="three-ways-to-run-videosdk-with-azure">Three ways to run VideoSDK with Azure</h2>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Option</th>
<th>How it works</th>
<th>Pricing</th>
</tr>
</thead>
<tbody>
<tr>
<td>Fully managed</td>
<td>VideoSDK manages the infrastructure, deployment, scaling and operations.</td>
<td>Usage-based</td>
</tr>
<tr>
<td>Hybrid</td>
<td>VideoSDK runs the real-time infrastructure. Recordings and data are stored in your own Azure Blob Storage.</td>
<td>Usage-based</td>
</tr>
<tr>
<td>Customer-hosted</td>
<td>VideoSDK is deployed inside your own Azure subscription. You control deployment, networking, security and data.</td>
<td>Fixed license fee, unlimited usage</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>You can connect your own Azure Blob Storage for recordings from the <a href="https://docs.videosdk.live/help_docs/dashboard/api-keys/cloud-storage-configuration">VideoSDK dashboard</a>. For customer-hosted, <a href="https://www.videosdk.live/contact">contact us</a> first.</p><h2 id="what-you-can-build">What you can build</h2><p>Calling and live streaming are the base. On top of them you can add:</p><ul><li>Live transcription and captions, plus transcripts and summaries after the call</li><li>SIP Connect, which brings phone calls into your VideoSDK meetings</li><li>AI voice agents with turn detection, interruption handling and memory. They can run on Azure OpenAI models through our <a href="https://docs.videosdk.live/ai_agents/plugins/llm/azureopenai">Azure OpenAI plugin</a>.</li></ul><h2 id="what-customers-have-built">What customers have built</h2><p><a href="https://www.videosdk.live/customers/groww">Groww</a>, a leading investment platform in India, runs Video KYC on VideoSDK with a success rate of about 90%. It went live within a month.</p><p><a href="https://www.videosdk.live/customers/coderschool">Coderschool</a> teaches coding in Vietnam. After it moved its online sessions to VideoSDK, session hours went up 140%.</p><p>Call failures on <a href="https://www.videosdk.live/customers/examedi">Examedi</a>'s telehealth platform went down by 50%, according to the Latin American healthcare startup.</p><h2 id="how-to-buy-videosdk-through-microsoft-marketplace">How to Buy VideoSDK Through Microsoft Marketplace</h2><p>Buy VideoSDK directly through <strong>Microsoft Marketplace</strong> on the Pay as you go plan. Microsoft handles the billing, while VideoSDK helps you with setup and onboarding.</p><h3 id="the-process-at-a-glance">The process at a glance</h3><p><strong>Get It Now → Choose Plan and Subscription → Complete Purchase → Configure Your VideoSDK Account → Start Using VideoSDK</strong></p><h2 id="step-1-open-the-videosdk-listing">Step 1: Open the VideoSDK Listing</h2><p>On the <a href="https://marketplace.microsoft.com/en-us/product/videosdk.videosdk">VideoSDK Microsoft Marketplace listing</a>, select <strong>Get it now</strong> and sign in with your Azure account. Need custom terms? Select <strong>Request private offer</strong> instead.</p><h2 id="step-2-choose-your-plan-and-azure-subscription">Step 2: Choose Your Plan and Azure Subscription</h2><p>Review or choose:</p><ul><li>The Pay as you go plan</li><li>The Azure subscription that will be billed</li><li>A resource group</li><li>A name for the SaaS subscription (you can't change it after purchase)</li></ul><h2 id="step-3-review-and-complete-the-purchase">Step 3: Review and Complete the Purchase</h2><p>Review your contact details, which are shared with VideoSDK, and the terms of use, then select <strong>Complete purchase</strong>. The purchase can take up to a minute, so keep the window open.</p><h3 id="important-required-azure-permissions">Important: Required Azure Permissions</h3><p>You need the <strong>Owner</strong> or <strong>Contributor</strong> role on the Azure subscription. The subscription must have a valid payment method. Student, Visual Studio Enterprise and free credit subscriptions can't purchase SaaS products.</p><h2 id="step-4-configure-your-videosdk-account">Step 4: Configure Your VideoSDK Account</h2><p>After the purchase, continue to the VideoSDK site to set up or sign in to your <strong>VideoSDK account</strong>. Do this promptly: if a plan waits for account setup before it activates, Microsoft deletes the subscription after 30 days.</p><h2 id="step-5-start-using-videosdk">Step 5: Start Using VideoSDK</h2><p>Once your account is set up, you can integrate our real-time communication infrastructure into your application. Our team can also help you with onboarding and technical requirements.</p><h2 id="step-6-billing-is-handled-by-microsoft">Step 6: Billing Is Handled by Microsoft</h2><p>Your usage is billed per minute through your <strong>Microsoft invoice</strong>. You can manage, change or cancel the subscription from the SaaS page in the Azure portal.</p><h2 id="what-you-need-before-you-start">What You Need Before You Start</h2><p>Make sure you have:</p><ul><li>An Azure account</li><li>An Azure subscription with a valid payment method</li><li>The Owner or Contributor role on that subscription</li><li>Your VideoSDK usage and technical requirements</li><li>A VideoSDK account or the ability to register for one</li></ul><h2 id="having-trouble-completing-the-purchase">Having Trouble Completing the Purchase?</h2><p>If you can't complete the purchase:</p><ol><li>Make sure you're signed in with the correct Azure account.</li><li>Confirm that you have the Owner or Contributor role on the subscription.</li><li>Check that the subscription has a valid payment method and isn't a free or student subscription.</li><li>Contact your organization's Azure administrator if you don't have access.</li><li>Contact the VideoSDK team if you need help with your purchase or setup.</li></ol><h2 id="ready-to-get-started">Ready to Get Started?</h2><p><a href="https://marketplace.microsoft.com/en-us/product/videosdk.videosdk"><strong>Get VideoSDK on Microsoft Marketplace</strong></a></p><p>For higher concurrency or private cloud deployment, <a href="https://www.videosdk.live/contact">ask us</a> about the Enterprise plan.</p>]]></content:encoded></item><item><title><![CDATA[VideoSDK is now available on Google Cloud Marketplace]]></title><description><![CDATA[Build real-time voice, video, telephony and AI-powered communication into your app. Buy it through a private offer, with Google handling the billing.]]></description><link>https://www.videosdk.live/blog/videosdk-google-cloud-marketplace</link><guid isPermaLink="false">6abe3afdb3240feb748ca18d</guid><category><![CDATA[ANNOUNCEMENT]]></category><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 08 Oct 2026 13:12:51 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/10/videosdk-google-cloud-marketplace.webp" medium="image"/><content:encoded><![CDATA[<blockquote><em>Build real-time voice, video, telephony and AI-powered communication into your app. Buy it through a private offer, with Google handling the billing.</em></blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/10/videosdk-google-cloud-marketplace.webp" alt="VideoSDK is now available on Google Cloud Marketplace"/><p>VideoSDK gives developers SDKs and APIs for voice, video, live streaming, SIP telephony and AI voice agents. It is now listed on <a href="https://console.cloud.google.com/marketplace/product/videosdk-public/videosdk">Google Cloud Marketplace</a>.</p><p>We sell it there through private offers. You agree on a price with us, accept the offer in the Marketplace, and Google Cloud bills you.</p><h2 id="what-you-gain-by-buying-through-google-cloud">What you gain by buying through Google Cloud</h2><ul><li>The charge goes to the Google Cloud billing account you already have.</li><li>You pay the price and term written into your private offer.</li><li>VideoSDK hosts and supports the service. Google Cloud handles the billing.</li></ul><h2 id="what-you-can-build-and-who-it-is-for">What you can build, and who it is for</h2><p>With VideoSDK you can build AI voice agents, live video conferencing, interactive streaming and SIP telephony workflows. There are SDKs for Web, iOS, Android, Flutter and React Native, and you can integrate from your server too.</p><p>It is built for <strong>healthcare, finance, customer support and education products.</strong></p><h2 id="how-videosdk-works-with-google-cloud">How VideoSDK works with Google Cloud</h2><p>Voice agents can run on Gemini. Our <a href="https://docs.videosdk.live/ai_agents/plugins/realtime/google-live-api">Gemini Live API plugin</a> lets an agent use Google's Gemini models for real-time conversations. You can connect with a Gemini API key or through Vertex AI.</p><p>To choose each part of the pipeline yourself, use the separate Google <a href="https://docs.videosdk.live/ai_agents/plugins/stt/google">speech-to-text</a> and <a href="https://docs.videosdk.live/ai_agents/plugins/tts/google-tts">text-to-speech</a> plugins.</p><p>Recordings can go to <a href="https://docs.videosdk.live/help_docs/dashboard/api-keys/cloud-storage-configuration">your own Google Cloud Storage bucket</a>.</p><h2 id="what-customers-have-built">What customers have built</h2><p><a href="https://www.videosdk.live/customers/refrens">Refrens</a>, a B2B SaaS platform from India, built voice agents on VideoSDK with Gemini as the LLM. The agents call new signups right away, and Refrens qualified 10x more leads without growing the team.</p><p><a href="https://www.videosdk.live/customers/coalasaude">Coala Saúde</a> is a telehealth platform in Brazil. It records consultations on VideoSDK and exports the raw audio directly to its Google Cloud storage. That starts Coala's own AI pipeline, which writes the medical record. Doctors now spend 45% less time on documentation after a consultation.</p><h2 id="what-your-team-gets">What your team gets</h2><p>Every session can be recorded, transcribed and monitored, and analytics are built in.</p><p><a href="https://www.videosdk.live/customers/groww">Groww</a>, a leading investment platform in India, gets Video KYC recordings in its own cloud storage in under 10 seconds. Its auditors can review a session within minutes.</p><p>Compliance add-ons are available when you need them.</p><h2 id="how-to-buy-videosdk-through-google-cloud-marketplace">How to Buy VideoSDK Through Google Cloud Marketplace</h2><p>Buy VideoSDK directly through <strong>Google Cloud Marketplace</strong> using a private offer. Google Cloud handles the billing, while VideoSDK helps you with pricing, setup, and onboarding.</p><h3 id="the-process-at-a-glance">The process at a glance</h3><p><strong>Contact Sales → Receive Private Offer → Accept Offer → Register with VideoSDK → Start Using VideoSDK</strong></p><h2 id="step-1-contact-videosdk-sales">Step 1: Contact VideoSDK Sales</h2><p>Visit the <a href="https://console.cloud.google.com/marketplace/product/videosdk-public/videosdk">VideoSDK Google Cloud Marketplace listing</a> and select <strong>Contact Sales</strong>.</p><p>Share your requirements with our team, including:</p><ul><li>Expected usage</li><li>Plan or features required</li><li>Contract duration</li><li>Any specific technical or business requirements</li></ul><p>Our team will work with you to finalize the <strong>pricing and contract terms</strong>.</p><h2 id="step-2-receive-your-private-offer">Step 2: Receive Your Private Offer</h2><p>Once the pricing and terms are agreed, VideoSDK will create a <strong>private offer</strong> for your Google Cloud Billing Account.</p><p>You will receive a private offer link that allows you to review and purchase the agreed VideoSDK plan through Google Cloud Marketplace.</p><h2 id="step-3-review-and-accept-the-offer">Step 3: Review and Accept the Offer</h2><p>Open the private offer link and review the:</p><ul><li>Pricing</li><li>Contract term</li><li>Billing details</li><li>Offer terms</li></ul><p>If everything looks correct, select <strong>Subscribe</strong> to accept the offer.</p><h3 id="important-required-google-cloud-permissions">Important: Required Google Cloud Permissions</h3><p>The person accepting the offer must have one of the following permission setups on the Google Cloud Billing Account:</p><ul><li><strong>Billing Account Administrator</strong>, or</li><li><strong>Billing Account User</strong> + <strong>Consumer Procurement Order Administrator</strong></li></ul><p>If you don't have the required permissions, contact your organization's Google Cloud billing administrator.</p><h2 id="step-4-register-with-videosdk">Step 4: Register with VideoSDK</h2><p>After accepting the private offer, register or sign in to your <strong>VideoSDK account</strong> and complete the required account setup.</p><p>This connects your VideoSDK account with your Google Cloud Marketplace purchase.</p><h2 id="step-5-start-using-videosdk">Step 5: Start Using VideoSDK</h2><p>Once your account is set up, you can start using VideoSDK and integrate our real-time communication infrastructure into your application.</p><p>Our team can also help you with onboarding and technical requirements.</p><h2 id="step-6-billing-is-handled-by-google-cloud">Step 6: Billing Is Handled by Google Cloud</h2><p>Your VideoSDK purchase through the private offer is billed through your <strong>Google Cloud Billing Account</strong>.</p><p>You don't need to set up a separate payment process with VideoSDK for the Marketplace purchase.</p><h2 id="what-you-need-before-you-start">What You Need Before You Start</h2><p>Make sure you have:</p><ul><li>An active Google Cloud account</li><li>An active Google Cloud Billing Account</li><li>The required billing permissions</li><li>Your VideoSDK usage and technical requirements</li><li>A VideoSDK account or the ability to register for one</li></ul><h2 id="having-trouble-accepting-the-offer">Having Trouble Accepting the Offer?</h2><p>If you can't accept the private offer:</p><ol><li>Make sure you're signed in to the correct Google Cloud account.</li><li>Confirm that you have the required Billing Account permissions.</li><li>Contact your organization's Google Cloud billing administrator if you don't have access.</li><li>Contact the VideoSDK team if you need help with the private offer or VideoSDK setup.</li></ol><h2 id="ready-to-get-started">Ready to Get Started?</h2><p><a href="https://console.cloud.google.com/marketplace/product/videosdk-public/videosdk?utm_source=chatgpt.com">Contact Sales on Google Cloud Marketplace</a> to discuss your requirements and receive a VideoSDK private offer.</p>]]></content:encoded></item><item><title><![CDATA[VideoSDK is now available on AWS Marketplace]]></title><description><![CDATA[Add video calling, live streaming and recording to your app, and pay for it on your AWS bill.]]></description><link>https://www.videosdk.live/blog/videosdk-aws-marketplace</link><guid isPermaLink="false">6abe3b0db3240feb748ca191</guid><category><![CDATA[ANNOUNCEMENT]]></category><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 08 Oct 2026 13:11:51 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/10/videosdk-aws-marketplace.webp" medium="image"/><content:encoded><![CDATA[<blockquote><em>Add video calling, live streaming and recording to your app, and pay for it on your AWS bill.</em></blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/10/videosdk-aws-marketplace.webp" alt="VideoSDK is now available on AWS Marketplace"/><p>VideoSDK is a WebRTC audio and video SDK for putting calls, live streams and recordings inside your own app. It is now listed on <a href="https://aws.amazon.com/marketplace/pp/prodview-dk5mmvkjkpi64">AWS Marketplace</a>.</p><p>This is for teams that already run on AWS and would rather not add one more vendor bill.</p><h2 id="what-you-gain-by-buying-through-aws">What you gain by buying through AWS</h2><ul><li>You subscribe with the AWS account you already have.</li><li>You pay per minute for what you use, billed monthly on your AWS bill.</li><li>The subscription has no end date, and you can cancel it any time.</li></ul><h2 id="what-you-can-build">What you can build</h2><p>You can build 1:1 calls, large group meetings, live streams, telehealth consultations, virtual classrooms and fintech onboarding flows. The SDK comes with:</p><ul><li>Video conferencing with signaling and chat built in</li><li>Screen sharing, cloud recording and a whiteboard</li><li>Polls, quizzes, emoji reactions and hand raise</li><li>Transcription after the call, with AI-generated summaries</li><li>APIs to control rooms, participants, recordings and live streams</li></ul><p>SDKs are available for Android, iOS, React, React Native and Flutter.</p><h2 id="keep-recordings-in-your-own-aws-account">Keep recordings in your own AWS account</h2><p>You can keep recordings on VideoSDK's storage, or <a href="https://docs.videosdk.live/help_docs/dashboard/api-keys/cloud-storage-configuration">connect your own Amazon S3 bucket</a> and have them saved there.</p><p>Amnil Technologies in Nepal uses VideoSDK in <a href="https://www.videosdk.live/customers/amniltech">V-Connect</a>, its digital banking platform. V-Connect records sessions and exports the data directly to each bank's private storage, on Amazon S3 or MinIO. The team built a proof of concept in one week.</p><h2 id="what-customers-have-built">What customers have built</h2><p><a href="https://www.videosdk.live/customers/nxtqube">NxtQube</a>, an India-based company, builds drone docking stations. Its operators make time-critical decisions from live drone and docking station feeds, so near-zero latency is a must. With VideoSDK, the team had a working proof of concept in under five hours. Within a week, live feeds were streaming into its React web app, and NxtQube did not need to build or maintain its own WebRTC stack.</p><p><a href="https://www.videosdk.live/customers/felicity">Felicity</a> runs online counselling in India. When its video provider was shutting down, Felicity moved to VideoSDK and added video, audio and cloud recording within a few days. Its case study reports 70% fewer technical issues in sessions.</p><p><a href="https://www.videosdk.live/customers/immigo">Immigo</a>, based in the US, runs peer-to-peer English classes for learners in 120+ countries. With limited engineering resources, it went live on VideoSDK in under a week.</p><h2 id="what-it-costs">What it costs</h2><p>Pricing is per minute. Three rates cover a basic call:</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>What you use</th>
<th>Rate</th>
</tr>
</thead>
<tbody>
<tr>
<td>Audio call</td>
<td>$0.001 per participant per minute</td>
</tr>
<tr>
<td>HD video call (720p)</td>
<td>$0.004 per participant per minute</td>
</tr>
<tr>
<td>HD cloud recording</td>
<td>$0.015 per recorded minute</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Two people on a 30-minute HD video call use 60 participant-minutes, which comes to $0.24. Recording that call in HD adds $0.45, plus $0.003 per stored minute if you keep the file on VideoSDK's storage.</p><p>The listing has every rate, including Full-HD, live streaming and transcription.</p><h2 id="security-and-compliance">Security and compliance</h2><p>Geo-fencing, a cloud proxy and the compliance packages are add-ons, so you pay only for the ones you need. Each has a monthly price on the listing:</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Add-on</th>
<th>Price per month</th>
</tr>
</thead>
<tbody>
<tr>
<td>HIPAA</td>
<td>$500</td>
</tr>
<tr>
<td>CERT-In</td>
<td>$500</td>
</tr>
<tr>
<td>Geo-fencing</td>
<td>$500</td>
</tr>
<tr>
<td>Cloud proxy, for restricted networks</td>
<td>$200</td>
</tr>
<tr>
<td>GDPR</td>
<td>$100</td>
</tr>
<tr>
<td>SOC 2 Type 2</td>
<td>$100</td>
</tr>
<tr>
<td>ISO 27001</td>
<td>$100</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>You can also pay for any of them annually.</p><h2 id="how-to-buy-videosdk-through-aws-marketplace">How to Buy VideoSDK Through AWS Marketplace</h2><p>Subscribe to VideoSDK directly through <strong>AWS Marketplace</strong>. AWS handles the billing on a pay-as-you-go basis, while VideoSDK helps you with setup and onboarding.</p><h3 id="the-process-at-a-glance">The process at a glance</h3><p><strong>View Purchase Options → Review Pricing and Terms → Accept → Set Up Your VideoSDK Account → Start Using VideoSDK</strong></p><h2 id="step-1-open-the-videosdk-listing">Step 1: Open the VideoSDK Listing</h2><p>Visit the <a href="https://aws.amazon.com/marketplace/pp/prodview-dk5mmvkjkpi64">VideoSDK AWS Marketplace listing</a> and select <strong>View purchase options</strong>.</p><h2 id="step-2-review-pricing-and-terms">Step 2: Review Pricing and Terms</h2><p>On the purchase page, review the:</p><ul><li>Pricing dimensions and the per-minute rate for each</li><li>Add-ons you may need, such as HIPAA or geo-fencing</li><li>End User License Agreement (select <strong>Download EULA</strong>)</li></ul><h2 id="step-3-accept-the-subscription">Step 3: Accept the Subscription</h2><p>If everything looks correct, select <strong>Accept</strong> to create an active subscription. The subscription has no end date, and you can cancel it any time.</p><h3 id="important-required-aws-permissions">Important: Required AWS Permissions</h3><p>The person subscribing needs one of these AWS managed policies in your AWS account:</p><ul><li><strong>AWSMarketplaceManageSubscriptions</strong>, to subscribe and unsubscribe, or</li><li><strong>AWSMarketplaceFullAccess</strong>, for complete control of subscriptions</li></ul><p>If you don't have them, contact your AWS account administrator.</p><h2 id="step-4-set-up-your-videosdk-account">Step 4: Set Up Your VideoSDK Account</h2><p>After you accept, register or sign in to your <strong>VideoSDK account</strong>, get your API key and add the SDK for your platform. This connects your VideoSDK account with your AWS Marketplace subscription.</p><h2 id="step-5-start-using-videosdk">Step 5: Start Using VideoSDK</h2><p>Once your account is set up, you can integrate our real-time communication infrastructure into your application. Our team can also help you with onboarding and technical requirements.</p><h2 id="step-6-billing-is-handled-by-aws">Step 6: Billing Is Handled by AWS</h2><p>You pay per minute for what you use, billed monthly on your <strong>AWS bill</strong>. You don't need to set up a separate payment process with VideoSDK. You can cancel any time from the AWS Marketplace console.</p><h2 id="what-you-need-before-you-start">What You Need Before You Start</h2><p>Make sure you have:</p><ul><li>An active AWS account with a valid payment method</li><li>The required AWS Marketplace permissions</li><li>Your VideoSDK usage and technical requirements</li><li>A VideoSDK account or the ability to register for one</li></ul><h2 id="having-trouble-subscribing">Having Trouble Subscribing?</h2><p>If you can't complete the subscription:</p><ol><li>Make sure you're signed in to the correct AWS account.</li><li>Confirm that you have the required AWS Marketplace permissions.</li><li>Contact your AWS account administrator if you don't have access.</li><li>Contact the VideoSDK team if you need help with your subscription or setup.</li></ol><h2 id="ready-to-get-started">Ready to Get Started?</h2><p><a href="https://aws.amazon.com/marketplace/pp/prodview-dk5mmvkjkpi64"><strong>Subscribe to VideoSDK on AWS Marketplace</strong></a></p><p>Have questions before you subscribe? <a href="https://www.videosdk.live/contact">Talk to our team</a>.</p>]]></content:encoded></item><item><title><![CDATA[Live Streaming SDK for Fitness Apps: Build Interactive Classes]]></title><description><![CDATA[How to add live workout classes to your own app: what a class needs from the video layer, when to use a real-time room or HLS, React quickstart code where the instructor hosts and the class watches, and a cost formula for one class.]]></description><link>https://www.videosdk.live/blog/live-streaming-sdk-fitness-app</link><guid isPermaLink="false">6abca451b3240feb748ca0ad</guid><category><![CDATA[live-streaming]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 08 Oct 2026 12:46:55 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/10/26.png" medium="image"/><content:encoded><![CDATA[<blockquote>To add live classes to a fitness app, run each class as a real-time video room. The instructor joins as a host who sends audio and video, members join as viewers who only receive, and one viewer can be promoted on stage for a form check. Record the class so members can replay it later.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/10/26.png" alt="Live Streaming SDK for Fitness Apps: Build Interactive Classes"/><p>This guide is for developers choosing a live streaming SDK for fitness apps and building classes into their own product. If you want a ready-made fitness live streaming platform for a studio, most results for that phrase are studio software; this page is about building one. It covers class requirements, when a real-time room beats an HTTP Live Streaming (HLS) broadcast, React code, the promotion step the sample leaves open, and a cost formula.</p><h2 id="what-live-workout-streaming-asks-of-the-video-layer">What live workout streaming asks of the video layer</h2><p>Live workout streaming differs from a webinar: the instructor reacts to members, one member sometimes needs to be seen, and audio mixes voice with music. The table maps each requirement to the build.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Class requirement</th>
<th>Why it matters</th>
<th>What it implies</th>
</tr>
</thead>
<tbody>
<tr>
<td>Instructor reacts to members</td>
<td>Correcting form needs a short round trip</td>
<td>A real-time path for anyone who talks back</td>
</tr>
<tr>
<td>Form check on one member</td>
<td>The instructor needs one camera, not everyone's</td>
<td>Receive-only members, plus a way to promote one</td>
</tr>
<tr>
<td>Voice over music</td>
<td>Browser audio processing is set per microphone track</td>
<td>Test audio settings with class music playing</td>
</tr>
<tr>
<td>Class size varies</td>
<td>Small and large classes have different cost curves</td>
<td>Choose real-time or HLS delivery per class</td>
</tr>
<tr>
<td>Replay after class</td>
<td>Members miss live slots</td>
<td>Record the room</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The form check row changes the architecture most: it turns a broadcast into a room with roles. The audio row is a test item: browsers expose <code>echoCancellation</code>, <code>noiseSuppression</code> and <code>autoGainControl</code> as audio constraints (<a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints">MDN, MediaTrackConstraints</a>). In VideoSDK's React SDK, <code>createMicrophoneAudioTrack()</code> sets all three in its <code>noiseConfig</code> and offers a <code>music_standard</code> encoder profile for sessions where music matters, per the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/custom-media-sources/custom-audio-sources">custom audio track docs</a>. Neither page says how each setting treats an instructor's voice over class music, so run a test class with music playing and compare the settings before you pick defaults.</p><h2 id="interactive-room-or-hls-broadcast-for-a-live-class">Interactive room or HLS broadcast for a live class</h2><p>A live class runs as a real-time room or an HLS broadcast. In a real-time room, every participant connects over WebRTC (Web Real-Time Communication), the browser technology for exchanging audio and video (<a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API">MDN, WebRTC API</a>). In an HLS broadcast, players download encoded segments over HTTP, which scales for watch-only audiences but adds delay.</p><p><a href="https://www.rfc-editor.org/rfc/rfc8216.html#section-6.3.3">RFC 8216, section 6.3.3</a>, says a player SHOULD NOT start less than three target durations from the end of a live playlist, and the <a href="https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices">Apple HLS Authoring Specification</a> says target durations SHOULD be 6 seconds. A player following both starts at least three segments behind live: fine for watching, too late for a form check.</p><p>The decision rule: use a real-time room when members talk back or appear on camera. Use HLS when the class is watch-only and large enough that per-viewer cost dominates. Combine them when a small group interacts on stage while a larger audience watches HLS. See the <a href="https://www.videosdk.live/blog/hls-vs-webrtc">delay, scale and cost trade-off between HLS and WebRTC</a>.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/live-streaming-sdk-fitness-apps-class-architecture.png" class="kg-image" alt="Live Streaming SDK for Fitness Apps: Build Interactive Classes" loading="lazy" width="3200" height="1800"/></figure><p><em>Members only receive; promoting one to sender puts them on stage. Recording and HLS output are optional branches from the same room.</em></p><p>VideoSDK implements the room pattern as <a href="https://www.videosdk.live/blog/interactive-live-streaming">interactive live streaming (ILS)</a>: hosts join in <code>SEND_AND_RECV</code> mode and the audience in <code>RECV_ONLY</code> mode, per the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/concept-and-architecture">ILS concept and architecture docs</a>.</p><h2 id="build-the-class-in-react-instructor-as-host-members-as-viewers">Build the class in React: instructor as host, members as viewers</h2><p>The React interactive live streaming quickstart maps onto a class: the instructor hosts, and members join as receive-only viewers. React SDK, checked 29 Sep 2026: the blocks are copied verbatim from VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-react-ils">React ILS quickstart docs</a>, whose complete example is the <a href="https://github.com/videosdk-live/quickstart/tree/54b8421/interactive-live-streaming/react-ils">react-ils folder of VideoSDK's quickstart repository</a> (commit 54b8421). It depends on <code>@videosdk.live/react-sdk</code> ^1.1.1, the version npm tagged <code>latest</code> on 29 September 2026. Comments and defects stay as published.</p><p>Not using React? The <a href="https://github.com/videosdk-live/quickstart/tree/main/interactive-live-streaming">samples folder</a> has other platforms.</p><h3 id="set-up-the-project">Set up the project</h3><p>Create a new React App using the below command.</p><pre><code class="language-bash">npm create vite@latest videosdk-ils-react-app -- --template react
cd videosdk-ils-react-app</code></pre><p>Install the VideoSDK using the below-mentioned npm command. Make sure you are in your react app directory before you run this command.</p><pre><code class="language-bash">npm install "@videosdk.live/react-sdk"</code></pre><pre><code class="language-bash">yarn add "@videosdk.live/react-sdk"</code></pre><p>Your project structure should look like this.</p><pre><code class="language-plaintext">   root
   ├── node_modules
   ├── public
   ├── src
   │    ├── API.js
   │    ├── App.jsx
   │    ├── App.css
   │    ├── main.jsx
   ├── package.json
   .    .</code></pre><p>You are going to use functional components to leverage react's reusable component architecture. There will be components for users, videos, and controls (mic, camera, leave) over the video.</p><p>You will be working on these files:</p><ul><li>API.js: Responsible for handling API calls such as generating unique streamId and token</li><li>App.jsx: Responsible for rendering container and joining the Live Stream.</li></ul><h3 id="create-the-class-room">Create the class room</h3><p><code>createStream</code> posts to the rooms endpoint and returns the room ID, which the sample calls a stream ID.</p><pre><code class="language-javascript">// Generate your token at https://app.videosdk.live/api-keys and paste it below.
export const authToken = "";

// API call to create stream
export const createStream = async ({ token }) =&gt; {
  try {
    const res = await fetch(`https://api.videosdk.live/v2/rooms`, {
      method: "POST",
      headers: {
        authorization: `${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({}),
    });

    if (!res.ok) {
      throw new Error(`Failed to create stream: ${res.status}`);
    }

    const { roomId } = await res.json();
    return roomId;
  } catch (error) {
    console.error("createStream failed", error);
    throw error;
  }
};
</code></pre><p>The sample pastes a temporary dashboard token into <code>authToken</code>. The <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-react-ils">React ILS quickstart docs</a> (updated 14 September 2026) call this development only: in production the client gets its token from your backend server. Per the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/authentication-and-token">authentication and token docs</a> (updated 10 July 2026), your server signs that token with your API key and secret, so the secret stays off the client.</p><h3 id="join-as-the-instructor-or-as-a-class-member">Join as the instructor or as a class member</h3><p><code>JoinView</code> renders three buttons: the instructor uses <code>Constants.modes.SEND_AND_RECV</code>, a member uses <code>Constants.modes.RECV_ONLY</code>.</p><pre><code class="language-jsx">import "./App.css";
import React, { useEffect, useRef, useState } from "react";
import {
  MeetingProvider,
  useMeeting,
  useParticipant,
  Constants,
} from "@videosdk.live/react-sdk";
import { authToken, createStream } from "./API";

// Join Screen - Handles joining or creating a stream
function JoinView({ initializeStream, setMode }) {
  const [streamId, setStreamId] = useState("");

  const handleAction = async (mode) =&gt; {
    // Sets the mode (Host or Audience) and initializes the stream
    setMode(mode);
    await initializeStream(streamId);
  };

  return (
    &lt;div className="container"&gt;
      {/* Button to create a new stream */}
      &lt;button onClick={() =&gt; handleAction(Constants.modes.SEND_AND_RECV)}&gt;
        Create Live Stream as Host
      &lt;/button&gt;
      {/* Input field for entering an existing Stream ID */}
      &lt;input
        type="text"
        placeholder="Enter Stream Id"
        onChange={(e) =&gt; setStreamId(e.target.value)}
      /&gt;
      {/* Button to join as a host */}
      &lt;button onClick={() =&gt; handleAction(Constants.modes.SEND_AND_RECV)}&gt;
        Join as Host
      &lt;/button&gt;
      {/* Button to join as an audience member */}
      &lt;button onClick={() =&gt; handleAction(Constants.modes.RECV_ONLY)}&gt;
        Join as Audience
      &lt;/button&gt;
    &lt;/div&gt;
  );
}

// Live Stream Container - Placeholder for the live stream container
function LSContainer(props) {
  return null;
}

// Main App Component - Handles the app flow and live stream lifecycle
function App() {
  const [streamId, setStreamId] = useState(null); // Holds the current stream ID
  const [mode, setMode] = useState(Constants.modes.SEND_AND_RECV); // Holds the current user mode (Host or Audience)

  const initializeStream = async (id) =&gt; {
    if (!authToken) {
      console.error("PLEASE PROVIDE TOKEN IN API.js FROM app.videosdk.live");
      return;
    }
    // Creates a new stream if no ID is provided or uses the given stream ID
    const newStreamId = id || (await createStream({ token: authToken }));
    setStreamId(newStreamId);
  };

  const onStreamLeave = () =&gt; setStreamId(null); // Resets the stream state on leave

  return authToken &amp;&amp; streamId ? (
    // Provides the stream context to the application
    &lt;MeetingProvider
      config={{
        meetingId: streamId,
        micEnabled: true, // Enables microphone by default
        webcamEnabled: true, // Enables webcam by default
        name: "John Doe", // Default participant name
        mode,
      }}
      token={authToken}
    &gt;
      {/* Renders the live stream container if a stream is active */}
      &lt;LSContainer streamId={streamId} onLeave={onStreamLeave} /&gt;
    &lt;/MeetingProvider&gt;
  ) : (
    // Renders the join view if no stream is active
    &lt;JoinView initializeStream={initializeStream} setMode={setMode} /&gt;
  );
}

export default App;</code></pre><p>LSContainer is a placeholder that returns nothing, so the app compiles at this step. The next step replaces it with the full component.</p><p>Two sample quirks: "Create Live Stream as Host" joins any ID typed in the field, and either join button with an empty field creates a new room.</p><p><code>App</code> passes the chosen mode into <code>MeetingProvider</code>. The <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/setup-livestream/initialize-livestream">initialize-livestream docs</a> mark <code>micEnabled</code> and <code>webcamEnabled</code> as ignored for the audience, so members stay off camera. Replace the <code>"John Doe"</code> placeholder. The quickstart docs also warn that a token cannot restrict mode, so any client with a valid token can join as <code>SEND_AND_RECV</code>: your server must decide who is the instructor.</p><h3 id="set-up-the-live-stream-view-and-container">Set up the live stream view and container</h3><p>This step implements the Live Stream View and Container components to manage and display HOST participants:</p><ul><li>StreamView Component: Displays participants in <code>SEND_AND_RECV</code> mode using the Participant component. Includes LSControls for managing the session.</li><li>LSContainer Component: Manages joining the stream via join from useMeeting. Shows the StreamView after joining or a <code>Join Stream</code> button otherwise.</li></ul><pre><code class="language-jsx">// Component to manage live stream container and session joining
function LSContainer({ streamId, onLeave }) {
  const [joined, setJoined] = useState(false); // Track if the user has joined the stream

  const { join } = useMeeting({
    onMeetingJoined: () =&gt; setJoined(true), // Set `joined` to true when successfully joined
    onMeetingLeft: onLeave, // Handle the leave stream event
    onError: (error) =&gt; alert(error.message), // Display an alert on encountering an error
  });

  const handleJoin = async () =&gt; {
    try {
      await join();
    } catch (error) {
      console.error("Failed to join stream", error);
    }
  };

  return (
    &lt;div className="container"&gt;
      &lt;h3&gt;Stream Id: {streamId}&lt;/h3&gt;
      {/* Show the stream view if joined, otherwise display the "Join Stream" button */}
      {joined ? (
        &lt;StreamView /&gt;
      ) : (
        &lt;button onClick={handleJoin}&gt;Join Stream&lt;/button&gt;
      )}
    &lt;/div&gt;
  );
}

// Component to display the live stream view
function StreamView() {
  const { participants } = useMeeting(); // Access participants using the VideoSDK useMeeting hook

  return (
    &lt;div&gt;
      &lt;LSControls /&gt; {/* Render live stream controls */}
      {[...participants.values()]
        .filter((p) =&gt; p.mode === Constants.modes.SEND_AND_RECV) // Filter participants in SEND_AND_RECV mode
        .map((p) =&gt; (
          &lt;Participant participantId={p.id} key={p.id} /&gt; // Render each participant's view
        ))}
    &lt;/div&gt;
  );
}

function Participant() {
  return null;
}

function LSControls() {
  return null;
}</code></pre><p>Participant and LSControls are placeholders at this step. Replace each one with the full version from the next two steps rather than adding a second function with the same name.</p><h3 id="render-each-participants-view">Render each participant's view</h3><p>This step component displays an individual participant's audio and video streams. It uses the <code>useParticipant</code> hook to retrieve the participant's data (e.g., webcam and mic status) and dynamically sets up the streams with <code>useEffect</code>. Audio and video elements are rendered based on the availability of the streams.</p><pre><code class="language-jsx">// Component to render audio and video streams for a participant
function Participant({ participantId }) {
  const { webcamStream, micStream, webcamOn, micOn, isLocal, displayName } =
    useParticipant(participantId);

  const audioRef = useRef(null); // Reference for audio element
  const videoRef = useRef(null); // Reference for video element

  // Function to attach or clear the stream
  const setupStream = (stream, ref, condition) =&gt; {
    if (ref.current &amp;&amp; stream) {
      ref.current.srcObject = condition
        ? new MediaStream([stream.track])
        : null;
      condition &amp;&amp; ref.current.play().catch(console.error);
    }
  };

  useEffect(() =&gt; setupStream(micStream, audioRef, micOn), [micStream, micOn]); // Handle mic stream
  useEffect(
    () =&gt; setupStream(webcamStream, videoRef, webcamOn),
    [webcamStream, webcamOn]
  ); // Handle webcam stream

  return (
    &lt;div&gt;
      &lt;p&gt;
        {displayName} | Webcam: {webcamOn ? "ON" : "OFF"} | Mic:{" "}
        {micOn ? "ON" : "OFF"}
      &lt;/p&gt;
      &lt;audio ref={audioRef} autoPlay muted={isLocal} /&gt; {/* Play mic stream */}
      {webcamOn &amp;&amp; (
        &lt;video
          ref={videoRef}
          autoPlay
          muted={isLocal}
          height="200"
          width="300"
        /&gt; /* Display webcam stream */
      )}
    &lt;/div&gt;
  );
}</code></pre><h3 id="implement-live-stream-controls">Implement live stream controls</h3><p>This step provides buttons to leave the stream, toggle the microphone and camera, and switch between <code>Host Mode</code> (send/receive streams) and <code>Audience Mode</code> (receive streams only). It uses <code>useMeeting</code> to access these functionalities.</p><p>From v1.0.0, all these methods are asynchronous and return a Promise, so <code>await</code> them and handle failures with <code>try</code> / <code>catch</code>. For details, see the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/migration-guide">Migration Guide</a>.</p><pre><code class="language-jsx">// Component for managing stream controls
function LSControls() {
  const { leave, toggleMic, toggleWebcam, changeMode, meeting } = useMeeting(); // Access methods
  const currentMode = meeting.localParticipant.mode; // Get the current participant's mode

  const handleLeave = async () =&gt; {
    try {
      await leave();
    } catch (error) {
      console.error("Failed to leave stream", error);
    }
  };

  const handleToggleMic = async () =&gt; {
    try {
      await toggleMic();
    } catch (error) {
      console.error("Failed to toggle mic", error);
    }
  };

  const handleToggleWebcam = async () =&gt; {
    try {
      await toggleWebcam();
    } catch (error) {
      console.error("Failed to toggle webcam", error);
    }
  };

  const handleChangeMode = async () =&gt; {
    const nextMode =
      currentMode === Constants.modes.SEND_AND_RECV
        ? Constants.modes.RECV_ONLY
        : Constants.modes.SEND_AND_RECV;
    try {
      await changeMode(nextMode);
    } catch (error) {
      console.error("Failed to change mode", error);
    }
  };

  return (
    &lt;div className="controls"&gt;
      {/* Button to leave the stream */}
      &lt;button onClick={handleLeave}&gt;Leave&lt;/button&gt;

      {/* Show mic and webcam toggles if in SEND_AND_RECV mode */}
      {currentMode === Constants.modes.SEND_AND_RECV &amp;&amp; (
        &lt;&gt;
          &lt;button onClick={handleToggleMic}&gt;Toggle Mic&lt;/button&gt;{" "}
          {/* Mute/unmute mic */}
          &lt;button onClick={handleToggleWebcam}&gt;Toggle Camera&lt;/button&gt;{" "}
          {/* Enable/disable Camera */}
        &lt;/&gt;
      )}

      {/* Button to switch between Host Mode and Viewer Mode */}
      &lt;button onClick={handleChangeMode}&gt;
        {currentMode === Constants.modes.SEND_AND_RECV
          ? "Switch to Audience Mode"
          : "Switch to Host Mode"}
      &lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><h3 id="add-the-styles">Add the styles</h3><p>The Vite template creates its own App.css, which the app runs with. To match the quickstart's layout, replace the contents of src/App.css with the quickstart's <a href="https://github.com/videosdk-live/quickstart/blob/54b8421/interactive-live-streaming/react-ils/src/App.css">App.css from the react-ils folder</a>.</p><pre><code class="language-css">/* App.css */
body {
  margin: 0;
  font-family: Arial, sans-serif;
  background-color: #f9f9f9;
}

.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  height: 100vh;
  gap: 20px;
  padding: 20px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

button {
  background: #007bff;
  color: #fff;
  border: none;
  padding: 10px 16px;
  border-radius: 5px;
  cursor: pointer;
  transition: 0.3s;
}

button:hover {
  background: #0056b3;
}

input {
  width: 60%;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 5px;
}

.controls {
  display: flex;
  gap: 10px;
}

video,
audio {
  margin: 10px 0;
  border-radius: 8px;
}</code></pre><h3 id="run-the-app">Run the app</h3><p>Start the development server with npm run dev, the command used in <a href="https://vite.dev/guide/">Vite's getting started guide</a>, then open the local address it prints. Create the stream as the instructor in one browser tab and join it as a member in a second tab with the same stream ID.</p><pre><code class="language-bash">npm run dev</code></pre><h3 id="bring-a-member-on-stage-for-a-form-check">Bring a member on stage for a form check</h3><p>Promotion needs code on both sides. VideoSDK's <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/audience-management/change-mode">change-mode docs</a> (updated 13 September 2026) state that <code>changeMode()</code> changes only the caller's own mode. The instructor publishes an invite over PubSub (publish-subscribe messaging) on a per-member topic, and the member's client calls <code>changeMode()</code> with <code>SEND_AND_RECV</code> on accepting. Every client must handle <code>onParticipantModeChanged</code> and rebuild both its stage list and its audience list.</p><p>The <code>LSControls</code> block above gives every audience member a "Switch to Host Mode" button with no instructor approval. Replace it with the invite flow.</p><h2 id="how-many-members-fit-in-a-live-class-and-what-it-costs">How many members fit in a live class, and what it costs</h2><p>VideoSDK limits concurrent usage per organization and per room. Its <a href="https://docs.videosdk.live/help_docs/quotas-and-limit">quotas and limits page</a> sets default per-room limits of 15 active speakers, 100 participants, 1,000 interactive live streaming viewers and 200 HTTP Live Streaming viewers. Across the organization, Pay-As-You-Go defaults to up to 500 concurrent hosts and 200 concurrent viewers. Extra capacity is sold in packs at $20 per pack per month, for example 200 more viewers per pack.</p><p>As of 1 October 2026, <a href="https://www.videosdk.live/pricing">VideoSDK pricing</a> bills ILS and HLS separately. ILS charges $0.002 per viewer minute at 720p. HLS charges $0.001 per viewer minute at 720p, per VideoSDK's <a href="https://docs.videosdk.live/help_docs/pricing">pricing FAQ</a>, plus $0.04 per livestream minute of 720p encoding.</p><ol><li>ILS viewer cost per class minute is 0.002 × N, for N viewers.</li><li>HLS cost per class minute is (0.001 × N) + 0.04.</li><li>HLS costs less once N exceeds 0.04 ÷ (0.002 - 0.001), which is 40 viewers.</li></ol><h2 id="adapting-the-pattern-for-creator-apps">Adapting the pattern for creator apps</h2><p>For creator app live video, the roles stay the same: the creator hosts, followers receive, and a guest comes on stage through the same invite flow. The <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/relay-media">relay media docs</a> describe <code>requestMediaRelay()</code>, which relays a host's media into one or more other live streams for cross-stream formats such as PK battles; a host in the destination stream accepts or rejects each request. For the full creator build, see <a href="https://www.videosdk.live/blog/build-social-live-streaming-app-like-tiktok-live">how to build a social live streaming app like TikTok Live</a>.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Participant mode (SEND_AND_RECV, RECV_ONLY):</strong> The role a participant joins with. VideoSDK's <code>MeetingProvider</code> also lists <code>SIGNALLING_ONLY</code>, which joins without media.</blockquote><blockquote><strong>HTTP Live Streaming (HLS):</strong> A protocol, specified in RFC 8216, that serves video as short segments listed in a playlist. See <a href="https://www.videosdk.live/blog/what-is-http-live-streaming">what HTTP Live Streaming is</a>.</blockquote><blockquote><strong>Target duration:</strong> The maximum segment duration an HLS playlist declares in its <code>EXT-X-TARGETDURATION</code> tag.</blockquote><blockquote><strong>PubSub (publish-subscribe):</strong> Topic-based messaging inside a VideoSDK room; <code>usePubSub</code> returns <code>publish</code> and <code>messages</code>.</blockquote><blockquote><strong>WHIP (WebRTC-HTTP Ingestion Protocol):</strong> An IETF Standards Track protocol, <a href="https://www.rfc-editor.org/rfc/rfc9725.html">RFC 9725</a>, that uses an HTTP exchange to set up a WebRTC session for sending media into a streaming service.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>A live streaming SDK for fitness apps should model the instructor as a host who sends media and members as receive-only viewers, with a way to promote one member.</li><li>Use a real-time room when members talk back or appear on camera, and HLS when a large class only watches.</li><li>A token cannot restrict mode, so your server issues tokens and decides who joins as instructor.</li><li>Promotion takes a PubSub invite, a <code>changeMode()</code> call by the member, and a mode-changed listener on every client.</li></ul><p>Start from the React quickstart, move tokens and mode decisions to your server, then add the invite flow. The <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/introduction">VideoSDK interactive live streaming docs</a> cover each step, and a new account comes with a $20 credit.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-the-best-streaming-infrastructure-for-fitness-and-creator-apps">What is the best streaming infrastructure for fitness and creator apps?</h3><p>No single setup is best for every class; match it to how much members interact. Look for host and receive-only roles, a documented promotion flow, server-issued tokens, recording, and an HLS path for large watch-only audiences. Then compare per-viewer-minute prices on the day.</p><h3 id="what-should-a-real-time-video-sdk-for-fitness-and-coaching-apps-include">What should a real-time video SDK for fitness and coaching apps include?</h3><p>A real-time video SDK for fitness and coaching apps should include roles set at join time, a promotion flow, and a data channel for cues, timers and chat. Coaching adds one-to-one sessions, which a room with two senders handles. Check that the docs show each piece in code.</p><h3 id="can-an-instructor-stream-a-class-from-obs-instead-of-a-browser">Can an instructor stream a class from OBS instead of a browser?</h3><p>Yes, through WHIP. VideoSDK's <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/whip-whep-ils">WHIP and WHEP docs</a> set up OBS Studio (Open Broadcaster Software) with a custom service: the server is the WHIP URL with the room ID, and the stream key is a VideoSDK token. The stream appears as a participant in the room.</p><h3 id="can-members-replay-a-class-after-it-ends">Can members replay a class after it ends?</h3><p>Yes. Call <code>startRecording()</code> from <code>useMeeting</code> during the class. The <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/recording/recording">ILS recording docs</a> and the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/recording/recording-storage-config">recording storage docs</a> cover storing files on VideoSDK's storage or in your own AWS S3, Azure Blob or GCP bucket. For a replay library you control, keep the recording in your own bucket.</p>]]></content:encoded></item><item><title><![CDATA[Hls.js VS Video.js: Choosing a Player for HLS Live Streams]]></title><description><![CDATA[hls.js is an HLS engine; Video.js is a player with its own engine. This comparison covers low-latency HLS, live-edge controls, Safari and iPhone behaviour and bundle sizes, with each project's version checked on 29 September 2026.]]></description><link>https://www.videosdk.live/blog/hls-js-vs-video-js</link><guid isPermaLink="false">6abca3c7b3240feb748ca095</guid><category><![CDATA[live-streaming]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 08 Oct 2026 12:45:36 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/28.png" medium="image"/><content:encoded><![CDATA[<blockquote>Use hls.js when you want only an HLS streaming engine, you will supply your own controls, and you need documented low-latency HLS support. Use Video.js 8 when you want a complete player with live-edge controls and standard-latency HLS through its bundled VHS engine. You rarely need both, because Video.js 8 does not use hls.js by default.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/28.png" alt="Hls.js VS Video.js: Choosing a Player for HLS Live Streams"/><p>The hls.js vs Video.js question comes up whenever a team has a live HLS URL and needs a live stream player for the web. This guide, for front-end developers working on live streams rather than video on demand, compares hls.js 1.7.3 and Video.js 8.24.1, current as of 29 September 2026; every feature claim comes from each project's own documentation or published code. If you need the protocol first, read <a href="https://www.videosdk.live/blog/what-is-http-live-streaming">how HTTP Live Streaming works</a>; for the broader checklist, see <a href="https://www.videosdk.live/developer-hub/hls/hls-video-player">the requirements every HLS video player has to meet</a>.</p><h2 id="hlsjs-vs-videojs-a-streaming-engine-and-a-player-framework">hls.js vs Video.js: a streaming engine and a player framework</h2><p>hls.js and Video.js sit at different layers, which is why the comparison confuses people. hls.js is a JavaScript library that implements an HTTP Live Streaming (HLS) client: it loads playlists and segments and feeds them to the browser through Media Source Extensions (MSE), according to the <a href="https://github.com/video-dev/hls.js">hls.js README</a>. It draws no buttons. You control playback through the standard <code>&lt;video&gt;</code> element, and the README points to Media Chrome for a custom interface.</p><p>Video.js is a player: controls, skins and plugins around the <code>&lt;video&gt;</code> element, plus an HLS engine. In Video.js 8 that engine is videojs-http-streaming (VHS), which the <a href="https://github.com/videojs/http-streaming">VHS README</a> says has shipped in the default Video.js build since version 7. VHS also plays MPEG-DASH; hls.js plays HLS only.</p><p>So the real choice is between two engines, hls.js or VHS, and whether you want the Video.js interface on top. The <a href="https://videojs.org/blog/videojs-v10-release-candidate">Video.js 10 release candidate</a>, published 9 September 2026 and not yet a stable release, has two HLS elements: <code>&lt;hls-video&gt;</code>, which runs on Video.js's own engine, and <a href="https://videojs.org/docs/framework/html/reference/components/hlsjs-video"><code>&lt;hlsjs-video&gt;</code></a>, which is powered by hls.js.</p><h2 id="live-hls-feature-comparison">Live HLS feature comparison </h2><p>The table compares the two stable stacks on what matters for a live stream. Each cell comes from that project's README, docs or npm entry, read on 29 September 2026, except the size row, which is measured as described below the table.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Criterion</th>
<th>hls.js 1.7.3</th>
<th>Video.js 8.24.1 with VHS 3.17.5</th>
</tr>
</thead>
<tbody>
<tr>
<td>Published on npm</td>
<td>11 Sep 2026</td>
<td>10 Sep 2026 (VHS: 19 Jun 2026)</td>
</tr>
<tr>
<td>Role</td>
<td>HLS engine, no interface</td>
<td>Player with interface and bundled engine</td>
</tr>
<tr>
<td>Formats</td>
<td>HLS</td>
<td>HLS and MPEG-DASH</td>
</tr>
<tr>
<td>Low-latency HLS</td>
<td>Documented: partial segments, blocking playlist reload, delta updates, rendition reports</td>
<td>Docs conflict: the supported-features page says on the roadmap; the changelog says on by default since VHS 3.0.0</td>
</tr>
<tr>
<td>Live controls</td>
<td>None; use <code>&lt;video controls&gt;</code> or your own interface</td>
<td>Live label by default; seek bar and SeekToLive button with <code>liveui: true</code></td>
</tr>
<tr>
<td>Safari and iPhone</td>
<td>MSE on macOS Safari 10+; iOS 17.1+ through ManagedMediaSource</td>
<td>Native HLS on Safari by default</td>
</tr>
<tr>
<td>Content protection</td>
<td>Encrypted Media Extensions (EME) digital rights management (DRM) with FairPlay, PlayReady and Widevine on fragmented MP4</td>
<td>Through the videojs-contrib-eme plugin</td>
</tr>
<tr>
<td>Captions</td>
<td>CEA-608/708 closed captions, WebVTT, IMSC1 text profile</td>
<td>CEA-608 and CEA-708 captions (708 parsing on by default); in-manifest WebVTT</td>
</tr>
<tr>
<td>Minified JS, gzip</td>
<td>188 kB full build, 119 kB light build</td>
<td>201 kB including VHS, plus 12 kB of CSS</td>
</tr>
<tr>
<td>Licence</td>
<td>Apache 2.0</td>
<td>Apache 2.0</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Sizes are the jsDelivr files for these versions, compressed with <code>gzip -9</code> on 29 September 2026. For a live project, read the low-latency HLS (LL-HLS) row first: if your packager emits LL-HLS, hls.js lists support in its README, while VHS's supported-features page and changelog disagree.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/hls-js-vs-video-js-playback-stacks.png" class="kg-image" alt="Hls.js VS Video.js: Choosing a Player for HLS Live Streams" loading="lazy" width="3200" height="1800"/></figure><p><em>hls.js stops at the engine; Video.js 8 wraps its own VHS engine and the video element in a player interface.</em></p><h2 id="playing-a-live-stream-with-hlsjs">Playing a live stream with hls.js</h2><p>An hls.js player is two parts: the hls.js engine and the controls you add yourself. The embed block below is copied verbatim from the <a href="https://github.com/video-dev/hls.js#embedding-hlsjs">hls.js README</a>, section "Embedding HLS.js".</p><pre><code class="language-html">&lt;script src="https://cdn.jsdelivr.net/npm/hls.js@1"&gt;&lt;/script&gt;
&lt;!-- Or if you want the latest version from the main branch --&gt;
&lt;!-- &lt;script src="https://cdn.jsdelivr.net/npm/hls.js@canary"&gt;&lt;/script&gt; --&gt;
&lt;video id="video"&gt;&lt;/video&gt;
&lt;script&gt;
  var video = document.getElementById('video');
  var videoSrc = 'https://test-streams.mux.dev/x36xhzz/x36xhzz.m3u8';
  if (Hls.isSupported()) {
    var hls = new Hls();
    hls.loadSource(videoSrc);
    hls.attachMedia(video);
  }
  // HLS.js is not supported on platforms that do not have Media Source
  // Extensions (MSE) enabled.
  //
  // When the browser has built-in HLS support (check using `canPlayType`),
  // we can provide an HLS manifest (i.e. .m3u8 URL) directly to the video
  // element through the `src` property. This is using the built-in support
  // of the plain video element, without using HLS.js.
  else if (video.canPlayType('application/vnd.apple.mpegurl')) {
    video.src = videoSrc;
  }
&lt;/script&gt;
</code></pre><p>For a live page, pin a version (<code>hls.js@1.7.3</code>) instead of <code>@1</code>, replace the on-demand test URL with your live <code>.m3u8</code>, and add the <code>controls</code> attribute, which the README's <code>&lt;video&gt;</code> element lacks. The README checks <code>Hls.isSupported()</code> first because Chrome 147 reports native HLS support yet can fail on some streams.</p><p>The live defaults come from the <a href="https://github.com/video-dev/hls.js/blob/master/docs/API.md">hls.js API documentation</a>. <code>liveSyncDurationCount</code> is 3, so on a playlist that declares no hold-back, playback starts three target durations behind the live edge, in line with section 6.3.3 of <a href="https://www.rfc-editor.org/rfc/rfc8216.html#section-6.3.3">RFC 8216</a>, and the docs warn that lowering it "is likely to cause playback stalls". <code>lowLatencyMode</code> defaults to <code>true</code>, which starts LL-HLS streams at the playlist's PART-HOLD-BACK instead, and <code>maxLiveSyncPlaybackRate</code> is 1, which disables catching up by speeding playback. Worker, buffer and event settings are in <a href="https://www.videosdk.live/developer-hub/hls/hls-js">configuring hls.js for production</a>.</p><h2 id="videojs-live-stream-playback-with-vhs">Video.js live stream playback with VHS</h2><p>A Video.js live stream plays through VHS in version 8, with the Video.js controls around it. The first block is the "Source" example from the <a href="https://github.com/videojs/http-streaming#source">VHS README</a>; the second is from the Video.js <a href="https://legacy.videojs.org/guides/live/">Live Support guide</a>. Both were copied verbatim on 29 September 2026.</p><pre><code class="language-javascript">var player = videojs('some-video-id');

player.src({
  src: 'https://d2zihajmogu5jn.cloudfront.net/bipbop-advanced/bipbop_16x9_variant.m3u8',
  type: 'application/x-mpegURL',
  withCredentials: true
});
</code></pre><pre><code class="language-javascript">var player = videojs('some-player-id', {liveui: true});
</code></pre><p>Both assume Video.js 8 is loaded on the page with a player element carrying the ID they name, as the <a href="https://legacy.videojs.org/getting-started/">Video.js getting started page</a> shows. That page's CDN links load 8.23.8, so change the version in them to 8.24.1. In the first block, swap the sample stream for your live playlist and drop <code>withCredentials</code> unless your CDN needs cookies. The VHS README recommends <code>player.src()</code> or a <code>&lt;video-js&gt;</code> element so the browser does not play the HLS natively.</p><p>The <code>liveui</code> option is <code>false</code> in the default options of Video.js 8.24.1, so the stock live interface hides the seek bar and shows a live label. With <code>liveui: true</code>, viewers get a seek bar across the live window and a SeekToLive button whose dot turns red at the live edge; <code>player.liveTracker</code> exposes the edge to your code.</p><h2 id="where-each-option-breaks-on-a-live-stream">Where each option breaks on a live stream</h2><p>hls.js breaks when delivery is not ready for it. The README requires cross-origin resource sharing (CORS) headers permitting <code>GET</code> on every HLS resource, so a playlist that plays natively in Safari can still fail through hls.js in Chrome. The ES module (ESM) builds do not bundle the transmuxer Web Worker, so transmuxing runs on the main thread unless you set <code>workerPath</code>. On iPhone, hls.js needs iOS 17.1 or later; older devices take the native fallback in the embed block.</p><p>Video.js 8's main gap on a live stream is low-latency HLS. The <a href="https://github.com/videojs/http-streaming/blob/main/docs/supported-features.md">VHS supported-features page</a> lists LL-HLS as on the roadmap and not available, yet the <a href="https://github.com/videojs/http-streaming/releases/tag/v3.0.0">VHS 3.0.0 release notes</a> say LL-HLS support is on by default, and the VHS 3.17.5 source still turns the <code>llhls</code> option on unless you pass <code>llhls: false</code>. With the project's own pages in conflict, test your LL-HLS stream in Video.js 8 before relying on it. The live guide says the <code>liveui</code> interface does not work with Android's native HLS, which lacks seekable ranges during live streams; VHS avoids that by default, because its <code>overrideNative</code> option is on everywhere except Safari, according to the VHS README. VHS's <code>experimentalUseMMS</code> option, which uses ManagedMediaSource on iPhone when <code>overrideNative</code> is on, currently disables AirPlay.</p><p>Both break when viewers need sub-second delay: HLS players start behind the live edge by design, so use a <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-player">WebRTC player for sub-second playback</a>. A digital video recorder (DVR) window, the rewindable part of a live playlist, only reaches back as far as the playlist does; for watching a stream after it ends, see <a href="https://www.videosdk.live/blog/what-is-video-on-demand">how video on demand works</a>.</p><h2 id="which-video-player-should-you-use-for-live-streams">Which video player should you use for live streams?</h2><p>The right video player for live streams depends on low-latency HLS, the interface you want and the formats you serve. Apply these rules in order:</p><ol><li>If your packager emits LL-HLS, use hls.js, because its README lists LL-HLS support, while VHS's own pages disagree on whether it has it.</li><li>If you are building a custom interface, use hls.js and ship only the engine.</li><li>If you want finished controls and plugins at standard latency on a stable release, use Video.js 8 with <code>liveui: true</code>.</li><li>If you also serve MPEG-DASH, Video.js 8 plays both through VHS; read <a href="https://www.videosdk.live/blog/hls-vs-mpeg-dash">HLS vs MPEG-DASH</a> before settling on the protocol.</li></ol><p>These rules are an opinion based on the documented features, not a benchmark. If you need a React video player for live HLS, both libraries run inside a component, and the wrappers are compared in <a href="https://www.videosdk.live/developer-hub/hls/react-hls-player">React HLS player libraries</a>.</p><h2 id="playing-a-videosdk-hls-stream-in-the-browser">Playing a VideoSDK HLS stream in the browser</h2><p>A media server publishes the live playlist URL; the player does the rest. In VideoSDK, <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/integrate-hls/start-hls"><code>startHls()</code></a> starts an HLS livestream of a meeting, and when <code>onHlsStateChanged</code> reports <code>HLS_PLAYABLE</code>, <code>hlsUrls.playbackHlsUrl</code> carries a live URL with playback support. The <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/integrate-hls/setup-hls-player">VideoSDK HLS player setup guide</a> (last updated 4 September 2026) plays it with hls.js and falls back to the native <code>&lt;video&gt;</code> source when <code>Hls.isSupported()</code> is false; it names no other player. Its example sets <code>liveSyncDurationCount</code> to 1, below the hls.js default of 3, and sets <code>maxBufferLength</code> to 0 and <code>maxMaxBufferLength</code> to 1, against hls.js defaults of 30 and 600 seconds. The <a href="https://github.com/video-dev/hls.js/blob/master/docs/API.md">hls.js API documentation</a> describes <code>maxBufferLength</code> as the buffer length hls.js tries to reach and warns that lowering <code>liveSyncDurationCount</code> "is likely to cause playback stalls", so test these values against your own stream before copying them. VideoSDK's docs do not cover Video.js, so test that path yourself before relying on it.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Media Source Extensions (MSE):</strong> The browser API that lets JavaScript append media segments to a <code>&lt;video&gt;</code> element.</blockquote><blockquote><strong>ManagedMediaSource (MMS):</strong> The MSE variant that shipped in Safari 17 on Mac and iPad and reached iPhone in Safari 17.1, according to <a href="https://webkit.org/blog/14735/webkit-features-in-safari-17-1/">WebKit</a>. hls.js has used it on iPhone since version 1.5.0.</blockquote><blockquote><strong>Low-Latency HLS (LL-HLS):</strong> The HLS extension that adds partial segments and blocking playlist reloads to cut delay; see <a href="https://www.videosdk.live/developer-hub/hls/hls-vs-ll-hls">how LL-HLS differs from standard HLS</a>.</blockquote><blockquote><strong>VHS (videojs-http-streaming):</strong> The HLS and MPEG-DASH engine bundled with Video.js 7 and 8.</blockquote><blockquote><strong>Live edge:</strong> The newest playable point in a live playlist, which players stay a few target durations behind.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>The hls.js vs Video.js choice is really an engine choice, hls.js or VHS, plus whether you want the Video.js interface on top.</li><li>hls.js 1.7.3 lists LL-HLS support in its README; for the VHS engine inside Video.js 8, the supported-features page says it is on the roadmap, while the changelog says it has been on by default since VHS 3.0.0.</li><li>Choose hls.js for LL-HLS or a custom interface, and Video.js 8 with <code>liveui: true</code> for finished live controls at standard latency.</li><li>Neither library makes HLS a real-time channel; for sub-second delay, viewers need a WebRTC player.</li></ul><p>Pin the version you test and read the changelog before upgrading. If you are producing the live stream as well as playing it, start with the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/integrate-hls/overview">VideoSDK HLS documentation</a>; a new account comes with a <a href="https://www.videosdk.live/pricing">$20 credit</a>.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="does-videojs-use-hlsjs">Does Video.js use hls.js?</h3><p>Video.js 8, the current stable release, does not use hls.js by default; its HLS engine is VHS, maintained in the Video.js GitHub organisation. The hls.js README lists three community plugins, videojs-hlsjs, videojs-hls.js and videojs-contrib-hls.js, that run hls.js inside Video.js. Check each plugin's latest release against Video.js 8 before adopting one.</p><h3 id="can-videojs-play-low-latency-hls">Can Video.js play low-latency HLS?</h3><p>Its documentation disagrees. The <a href="https://github.com/videojs/http-streaming/blob/main/docs/supported-features.md">VHS supported-features page</a>, read on 29 September 2026, says the low-latency features from the second edition of the HLS specification are on the roadmap but not available, while the <a href="https://github.com/videojs/http-streaming/releases/tag/v3.0.0">VHS 3.0.0 release notes</a> say LL-HLS support was enabled by default, and the 3.17.5 source still turns it on. Test your own LL-HLS stream before relying on Video.js 8 for it.</p><h3 id="do-you-need-hlsjs-on-safari-and-iphone">Do you need hls.js on Safari and iPhone?</h3><p>No. Safari on macOS, iPadOS and iOS plays HLS natively through the plain <code>&lt;video&gt;</code> element, and VHS uses that native player on Safari by default. hls.js is optional there; it supports macOS Safari 10 and later, iPadOS 13 and later, and iOS 17.1 and later through ManagedMediaSource. Use it there when you want one engine and one configuration in every browser.</p>]]></content:encoded></item><item><title><![CDATA[Watch Party API: How to Build Co-Watching in Your App]]></title><description><![CDATA[A watch party needs three parts: a video room for the group, a shared player and a sync channel. This guide compares three co-watching architectures, explains drift correction, and builds the room with the VideoSDK React quickstart.]]></description><link>https://www.videosdk.live/blog/watch-party-api</link><guid isPermaLink="false">6abca432b3240feb748ca0a7</guid><category><![CDATA[live-streaming]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 06 Oct 2026 12:49:52 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/10/25.png" medium="image"/><content:encoded><![CDATA[<blockquote>A watch party API combines three parts: a real-time room that carries everyone's camera and microphone, a shared video source, and a signalling channel that broadcasts play, pause and seek events with a timestamp. Each viewer's player applies those events and corrects its own drift, so the group sees the same moment together.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/10/25.png" alt="Watch Party API: How to Build Co-Watching in Your App"/><p>This guide is for developers adding co-watching to their own product with a watch party API, not for anyone choosing a consumer watch together app to install. It compares three architectures, sets out the sync arithmetic (clock offset, drift correction, late joiners and browser autoplay rules), and builds the room with the VideoSDK React software development kit (SDK).</p><h2 id="what-is-a-watch-party-api">What is a watch party API?</h2><p>A watch party API is the set of calls that lets a group watch one video at the same moment while they see and hear each other. The room carries faces and voices over Web Real-Time Communication (WebRTC). The player shows the video; in the design this guide builds, every viewer's player fetches the file itself from a content delivery network (CDN). The sync channel carries small control messages, so a pause on one screen becomes a pause on every screen.</p><p>Other platforms use a similar model: <a href="https://developers.google.com/workspace/meet/add-ons/guides/use-CoWatchingAPI">Google Meet's Co-Watching API guide</a> has apps call <code>notifyPauseState()</code> and <code>notifySeekToTimestamp()</code> when a user changes playback, though Google offered that API only through an Early Access Program that is now closed to new signups.</p><h2 id="three-ways-to-architect-co-watching">Three ways to architect co-watching</h2><p>The three co-watching architectures differ in where the video is decoded, and that decides how sync works.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Architecture</th>
<th>Who plays the video</th>
<th>How sync works</th>
<th>Best for</th>
<th>Main limit</th>
</tr>
</thead>
<tbody>
<tr>
<td>Local playback plus sync</td>
<td>Every viewer's own player</td>
<td>Control messages plus per-client drift correction</td>
<td>Small groups, licensed files</td>
<td>You write and tune the sync logic</td>
</tr>
<tr>
<td>Host screen share</td>
<td>Only the host</td>
<td>Everyone sees the host's shared frames</td>
<td>Quick demos, content with no API</td>
<td>Viewers watch a re-encoded capture of the host's screen</td>
</tr>
<tr>
<td>Broadcast</td>
<td>A server-side mix, sent as a stream</td>
<td>Viewers share the stream's delay</td>
<td>Large audiences</td>
<td>Viewers watch after the stream's delivery delay</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Local playback gives each viewer full-quality video while the room carries only faces, voices and small control messages, which is why this guide builds it. Screen share needs no sync code; the <a href="https://www.videosdk.live/blog/integrate-screen-share-in-react-js">screen share tutorial for React video calls</a> covers it. Broadcast suits a host talking over a film to a crowd: see <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/introduction">how to build a host-and-audience live stream in React</a>, and <a href="https://www.videosdk.live/blog/hls-vs-webrtc">how WebRTC and HTTP Live Streaming (HLS) differ on latency and scale</a>.</p><p>Whichever design you pick, showing a title to a group is also a licensing question for whoever manages your content agreements.</p><h2 id="how-do-you-keep-video-playback-in-sync-across-viewers">How do you keep video playback in sync across viewers?</h2><p>You keep playback in sync by making one client the leader and having every other client follow its messages. The leader sends an action (play, pause or seek), the video position in seconds read from <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/currentTime"><code>currentTime</code> on the HTML media element (MDN)</a>, and the time it sent the message.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/watch-party-api-playback-sync-architecture.png" class="kg-image" alt="Watch Party API: How to Build Co-Watching in Your App" loading="lazy" width="3200" height="1800"/></figure><p><em>Each player streams the video file itself; the room carries faces, voices and small control messages, and a shared store holds the last state for late joiners.</em></p><p>When the leader is playing, a follower's target is the sent position plus the time elapsed since sending. For example, if the message says "play from 754.2 seconds" and the follower's corrected clock reads 0.35 seconds after the sent-at time, the follower plays from 754.55 seconds.</p><p>The follower's clock must be corrected first, because the sent-at time comes from the leader's clock, which can differ from the follower's. <a href="https://datatracker.ietf.org/doc/html/rfc5905">RFC 5905 (Network Time Protocol, NTP)</a> estimates the offset from four timestamps as ((T2 - T1) + (T3 - T4)) / 2; run the same ping and reply over your sync channel when a viewer joins.</p><p>Players then drift apart during playback. Close a small gap by setting <code>playbackRate</code> slightly above or below 1.0; the <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/playbackRate">MDN <code>playbackRate</code> reference</a> notes that browsers correct audio pitch by default. Close a large gap with a seek by writing <code>currentTime</code>, and wait for the <code>seeked</code> event before measuring again. Base each measurement on several readings, because the <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/currentTime">MDN <code>currentTime</code> reference</a> describes the value as an approximation whose update frequency depends on the browser.</p><p>Late joiners read the last known state before their first play. Browsers also block audible playback until the user interacts with the page: the <a href="https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Autoplay">MDN autoplay guide</a> says <code>play()</code> then rejects with <code>NotAllowedError</code>, and <a href="https://developer.chrome.com/blog/autoplay">Chrome's autoplay policy</a> allows sound after a click or tap on the site. Start the player from the join click, or show a "tap to sync" button.</p><h2 id="how-to-build-a-watch-party-app-with-the-react-sdk">How to build a watch party app with the React SDK</h2><p>The watch party build in this section uses the React SDK, checked 29 Sep 2026, with code copied verbatim from VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">Quick Start for Conference in React</a>, whose complete example is the <code>react-rtc</code> folder of the <a href="https://github.com/videosdk-live/quickstart/tree/54b8421/react-rtc">VideoSDK quickstart repository</a> (commit <code>54b8421</code>). Its <code>package.json</code> requires <code>@videosdk.live/react-sdk</code> <code>^1.1.1</code>, the version npm tagged <code>latest</code> on 29 Sep 2026.</p><h3 id="set-up-the-project">Set up the project</h3><p>Create a new React App using the below command.</p><pre><code class="language-bash">npm create vite@latest videosdk-rtc-react-app -- --template react</code></pre><p>Install the VideoSDK using the below-mentioned npm command. Make sure you are in your react app directory before you run this command.</p><pre><code class="language-bash">npm install "@videosdk.live/react-sdk"</code></pre><pre><code class="language-bash">yarn add "@videosdk.live/react-sdk"</code></pre><p>Your project structure should look like this.</p><pre><code class="language-plaintext">   root
   ├── node_modules
   ├── public
   ├── src
   │    ├── API.js
   │    ├── App.jsx
   │    ├── main.jsx
   .    .</code></pre><p>You are going to use functional components to leverage react's reusable component architecture. There will be components for users, videos and controls (mic, camera, leave) over the video.</p><h3 id="create-a-room">Create a room</h3><p>Rooms come from a POST request with an auth token:</p><pre><code class="language-javascript">// Generate your token at https://app.videosdk.live/api-keys and paste it below.
export const authToken = "";

// API call to create meeting
export const createMeeting = async ({ token }) =&gt; {
  try {
    const res = await fetch(`https://api.videosdk.live/v2/rooms`, {
      method: "POST",
      headers: {
        authorization: `${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({}),
    });

    if (!res.ok) {
      throw new Error(`Failed to create meeting: ${res.status}`);
    }

    //Destructuring the roomId from the response
    const { roomId } = await res.json();
    return roomId;
  } catch (error) {
    console.error("createMeeting failed", error);
    throw error;
  }
};</code></pre><p>The sample pastes a temporary dashboard token into client code, which suits development only. In production, per the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token">authentication and token guide</a>, your backend generates the token from your API key and secret and the client fetches it; the secret never ships to the browser.</p><h3 id="join-the-room-and-render-the-group">Join the room and render the group</h3><p>To build up wireframe of App.jsx, you need to use VideoSDK Hooks and Context Providers. VideoSDK provides MeetingProvider, MeetingConsumer, useMeeting and useParticipant hooks.</p><p>First you need to understand Context Provider and Consumer. Context is primarily used when some data needs to be accessible by many components at different nesting levels.</p><ul><li><strong>MeetingProvider</strong>: This is the Context Provider. It accepts value <code>config</code> and <code>token</code> as props. The Provider component accepts a value prop to be passed to consuming components that are descendants of this Provider. One Provider can be connected to many consumers. Providers can be nested to override values deeper within the tree.</li><li><strong>MeetingConsumer</strong>: This is the Context Consumer. All consumers that are descendants of a Provider will re-render whenever the Provider's value prop changes.</li><li><strong>useMeeting</strong>: This is the meeting hook API. It includes all the information related to meeting such as join, leave, enable/disable mic or webcam etc.</li><li><strong>useParticipant</strong>: This is the participant hook API. It is responsible for handling all the events and props related to one particular participant such as name, webcamStream, micStream etc.</li></ul><p>The Meeting Context provides a way to listen for any changes that occur when a participant joins the meeting or makes modifications to their microphone, camera, and other settings. Begin by making a few changes to the code in the App.jsx file.</p><pre><code class="language-jsx">import "./App.css";
import React, { useEffect, useRef, useState } from "react";
import {
  MeetingProvider,
  MeetingConsumer,
  useMeeting,
  useParticipant,
  VideoPlayer,
} from "@videosdk.live/react-sdk";
import { authToken, createMeeting } from "./API";

function JoinScreen({ getMeetingAndToken }) {
  return null;
}

function ParticipantView(props) {
  return null;
}

function Controls(props) {
  return null;
}

function MeetingView(props) {
  return null;
}

function App() {
  const [meetingId, setMeetingId] = useState(null);

  //Getting the meeting id by calling the api we just wrote
  const getMeetingAndToken = async (id) =&gt; {
    if (!authToken) {
      console.error("PLEASE PROVIDE TOKEN IN API.js FROM app.videosdk.live");
      return;
    }
    const meetingId =
      id == null ? await createMeeting({ token: authToken }) : id;
    setMeetingId(meetingId);
  };

  //This will set Meeting Id to null when meeting is left or ended
  const onMeetingLeave = () =&gt; {
    setMeetingId(null);
  };

  return authToken &amp;&amp; meetingId ? (
    &lt;MeetingProvider
      config={{
        meetingId,
        micEnabled: true,
        webcamEnabled: true,
        name: "C.V. Raman",
      }}
      token={authToken}
    &gt;
      &lt;MeetingConsumer&gt;
        {() =&gt; (
          &lt;MeetingView meetingId={meetingId} onMeetingLeave={onMeetingLeave} /&gt;
        )}
      &lt;/MeetingConsumer&gt;
    &lt;/MeetingProvider&gt;
  ) : (
    &lt;JoinScreen getMeetingAndToken={getMeetingAndToken} /&gt;
  );
}

export default App;</code></pre><p><code>App</code> creates a room when the ID field is left untouched and wraps the view in <code>MeetingProvider</code> with the mic and webcam on.</p><p>JoinScreen, ParticipantView, Controls and MeetingView are placeholders that return nothing at this step, so the app compiles. The next steps replace each one with its full version; replace the placeholder rather than adding a second function with the same name.</p><p>Join screen will serve as a medium to either schedule a new meeting or join an existing one.</p><pre><code class="language-jsx">function JoinScreen({ getMeetingAndToken }) {
  const [meetingId, setMeetingId] = useState(null);
  const onClick = async () =&gt; {
    await getMeetingAndToken(meetingId);
  };
  return (
    &lt;div&gt;
      &lt;input
        type="text"
        placeholder="Enter Meeting Id"
        onChange={(e) =&gt; {
          setMeetingId(e.target.value);
        }}
      /&gt;
      &lt;button onClick={onClick}&gt;Join&lt;/button&gt;
      {" or "}
      &lt;button onClick={onClick}&gt;Create Meeting&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><p><code>MeetingView</code> joins on a button click (the user gesture autoplay rules need) and renders one tile per participant:</p><pre><code class="language-jsx">function MeetingView(props) {
  const [joined, setJoined] = useState(null);
  //Get the method which will be used to join the meeting.
  //We will also get the participants list to display all participants
  const { join, participants } = useMeeting({
    //callback for when meeting is joined successfully
    onMeetingJoined: () =&gt; {
      setJoined("JOINED");
    },
    //callback for when meeting is left
    onMeetingLeft: () =&gt; {
      props.onMeetingLeave();
    },
  });
  const joinMeeting = async () =&gt; {
    setJoined("JOINING");
    try {
      await join();
    } catch (error) {
      console.error("Failed to join meeting", error);
      setJoined(null);
    }
  };

  return (
    &lt;div className="container"&gt;
      &lt;h3&gt;Meeting Id: {props.meetingId}&lt;/h3&gt;
      {joined &amp;&amp; joined == "JOINED" ? (
        &lt;div&gt;
          &lt;Controls /&gt;
          //For rendering all the participants in the meeting
          {[...participants.keys()].map((participantId) =&gt; (
            &lt;ParticipantView
              participantId={participantId}
              key={participantId}
            /&gt;
          ))}
        &lt;/div&gt;
      ) : joined &amp;&amp; joined == "JOINING" ? (
        &lt;p&gt;Joining the meeting...&lt;/p&gt;
      ) : (
        &lt;button onClick={joinMeeting}&gt;Join&lt;/button&gt;
      )}
    &lt;/div&gt;
  );
}</code></pre><p>Next step is to create <code>MeetingView</code> and <code>Controls</code> components to manage features such as join, leave, mute and unmute.</p><p>From v1.0.0, all these methods are asynchronous and return a Promise, so <code>await</code> them and handle failures with <code>try</code> / <code>catch</code>. For details, see the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/migration-guide">Migration Guide</a>.</p><pre><code class="language-jsx">function Controls() {
  const { leave, toggleMic, toggleWebcam } = useMeeting();

  const handleLeave = async () =&gt; {
    try {
      await leave();
    } catch (error) {
      console.error("Failed to leave meeting", error);
    }
  };

  const handleToggleMic = async () =&gt; {
    try {
      await toggleMic();
    } catch (error) {
      console.error("Failed to toggle mic", error);
    }
  };

  const handleToggleWebcam = async () =&gt; {
    try {
      await toggleWebcam();
    } catch (error) {
      console.error("Failed to toggle webcam", error);
    }
  };

  return (
    &lt;div&gt;
      &lt;button onClick={handleLeave}&gt;Leave&lt;/button&gt;
      &lt;button onClick={handleToggleMic}&gt;toggleMic&lt;/button&gt;
      &lt;button onClick={handleToggleWebcam}&gt;toggleWebcam&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><p>Before implementing the participant view, you need to understand a couple of concepts.</p><p><strong>1. Forwarding Ref for mic.</strong> The <code>useRef</code> hook is responsible for referencing the audio component. It will be used to play and stop the audio of the participant.</p><pre><code class="language-jsx">const micRef = useRef(null);</code></pre><p><strong>2. useParticipant Hook.</strong> The <code>useParticipant</code> hook is responsible for handling all the properties and events of one particular participant joined in the meeting. It will take participantId as argument.</p><pre><code class="language-jsx">const { micStream, webcamOn, micOn } = useParticipant(props.participantId);</code></pre><p><strong>3. MediaStream API.</strong> The MediaStream API is beneficial for adding a MediaTrack to the audio tag, enabling the playback of audio.</p><pre><code class="language-jsx">const micRef = useRef(null);
const mediaStream = new MediaStream();
mediaStream.addTrack(micStream.track);

micRef.current.srcObject = mediaStream;
micRef.current
  .play()
  .catch((error) =&gt; console.error("micElem.current.play() failed", error));</code></pre><p>Only use the MediaStream API for microphone access. The VideoPlayer component in VideoSDK automatically handles the video stream.</p><p>Now you can use both of the hooks and the API to create <code>ParticipantView</code>.</p><pre><code class="language-jsx">function ParticipantView(props) {
  const micRef = useRef(null);
  const { micStream, webcamOn, micOn, isLocal, displayName } = useParticipant(
    props.participantId
  );

  useEffect(() =&gt; {
    if (micRef.current) {
      if (micOn &amp;&amp; micStream) {
        const mediaStream = new MediaStream();
        mediaStream.addTrack(micStream.track);

        micRef.current.srcObject = mediaStream;
        micRef.current
          .play()
          .catch((error) =&gt;
            console.error("micElem.current.play() failed", error)
          );
      } else {
        micRef.current.srcObject = null;
      }
    }
  }, [micStream, micOn]);

  return (
    &lt;div&gt;
      &lt;p&gt;
        Participant: {displayName} | Webcam: {webcamOn ? "ON" : "OFF"} | Mic:{" "}
        {micOn ? "ON" : "OFF"}
      &lt;/p&gt;
      &lt;audio ref={micRef} autoPlay muted={isLocal} /&gt;
      {webcamOn &amp;&amp; (
        &lt;VideoPlayer
          participantId={props.participantId} // Required
          type="video" // "video" or "share"
          containerStyle={{
            height: "200px",
            width: "300px",
          }}
          className="h-full"
          classNameVideo="h-full"
          videoStyle={{}}
        /&gt;
      )}
    &lt;/div&gt;
  );
}</code></pre><h3 id="add-the-styles">Add the styles</h3><p>The Vite template creates its own App.css, which the app runs with. To match the quickstart's layout, replace the contents of src/App.css with the quickstart's <a href="https://github.com/videosdk-live/quickstart/blob/54b8421/react-rtc/src/App.css">App.css from the react-rtc folder</a>.</p><pre><code class="language-css">.App {
  text-align: center;
}

.App-logo {
  height: 40vmin;
  pointer-events: none;
}

@media (prefers-reduced-motion: no-preference) {
  .App-logo {
    animation: App-logo-spin infinite 20s linear;
  }
}

.App-header {
  background-color: #282c34;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  font-size: calc(10px + 2vmin);
  color: white;
}

.App-link {
  color: #61dafb;
}

@keyframes App-logo-spin {
  from {
    transform: rotate(0deg);
  }
  to {
    transform: rotate(360deg);
  }
}</code></pre><p>To run the complete example, clone the repository, open <code>react-rtc</code>, paste a token into <code>API.js</code>, and run <code>npm install</code> then <code>npm run dev</code>.</p><h3 id="add-the-playback-sync-channel">Add the playback sync channel</h3><p>The quickstart has no sync code; three documented primitives supply it. The <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/pubsub">PubSub guide</a> covers <code>usePubSub(topic)</code> and <code>publish(message, options, payload)</code>: the message must be a string, structured fields such as action and position go in <code>payload</code>, and <code>persist: true</code> delivers earlier messages to late joiners through <code>onOldMessagesReceived</code>. <code>publish()</code> throws if it runs before the meeting is joined.</p><p>The <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/realtimestore">Realtime Store guide</a> fits the "current state" key: <code>setValue</code> stores and <code>getValue</code> returns string values of up to 1 KB per key, with 100 keys per session, last write wins, and <code>onValueChanged</code> reports each update. The <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/datastream">DataStream guide</a> suits frequent position heartbeats: <code>send()</code> has "reliable" and "unreliable" modes, a 15 KiB message limit, and <code>onData</code> returns a millisecond timestamp; only participants in <code>SEND_AND_RECV</code> mode can send. The <a href="https://www.videosdk.live/blog/integrate-chat-feature-in-react-js">React chat tutorial</a> uses <code>usePubSub</code> for group chat.</p><h2 id="scale-and-cost-when-choosing-a-co-watching-sdk">Scale and cost when choosing a co-watching SDK</h2><p>Watch party scale is bounded by concurrency, which the <a href="https://docs.videosdk.live/help_docs/quotas-and-limit">quotas page</a> counts across your organisation: 50 concurrent hosts before you add billing details and 500 on Pay-As-You-Go. For a larger audience, the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/concept-and-architecture">interactive live streaming (ILS) concept guide</a> has hosts join as <code>SEND_AND_RECV</code> and the audience as <code>RECV_ONLY</code>. If you broadcast over HLS, <a href="https://datatracker.ietf.org/doc/html/rfc8216#section-4.3.2.6">RFC 8216 section 4.3.2.6</a> defines <code>EXT-X-PROGRAM-DATE-TIME</code>, which maps the first sample of a segment to an absolute date and time. The tag is optional for servers, and VideoSDK's docs do not say whether its HLS playlists include it, so fetch your stream's playlist and check before you build alignment on it.</p><p>On <a href="https://www.videosdk.live/pricing">the pricing page</a>, 720p video costs $0.004 per participant minute on Pay-As-You-Go, and a new account starts with a $20 credit. As a hypothetical, six friends in a two-hour 720p watch party use 720 participant minutes, or $2.88. The film comes from your own CDN, so its delivery sits on that bill.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Leader client (host):</strong> The one participant whose player state the others copy; if the leader leaves, another participant must take the role.</blockquote><blockquote><strong>Playback drift:</strong> The growing gap between two players that started at the same position.</blockquote><blockquote><strong>Clock offset (clock skew):</strong> The difference between two devices' clocks at the same instant.</blockquote><blockquote><strong>Realtime Store:</strong> A per-session key-value store in the VideoSDK React SDK that every participant can read and observe.</blockquote><blockquote><strong>EXT-X-PROGRAM-DATE-TIME:</strong> An HLS playlist tag that maps the first sample of a segment to an absolute date and time.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>A watch party API is three parts: a room for faces and voices, a player per viewer, and a sync channel for play, pause and seek.</li><li>Use local playback plus sync for small groups, screen share when the content offers no API, and broadcast for large audiences.</li><li>Stamp every control message with a position and a sent-at time, correct for clock offset, then nudge <code>playbackRate</code> for small gaps and seek for large ones.</li></ul><p>Start with the <code>react-rtc</code> sample, add a leader and one playback topic, and measure drift between two browsers before tuning thresholds. For host and audience modes and HLS broadcast, read the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/introduction">VideoSDK interactive live streaming docs</a>.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="how-do-you-build-a-watch-party-or-co-watching-app">How do you build a watch party or co-watching app?</h3><p>You build one in four steps. Create a video room and join each viewer to it. Load the same video in every viewer's player. Choose a leader whose play, pause and seek actions are published with a position and timestamp. Have followers apply each message, correct drift, and read stored state when they join late.</p><h3 id="can-you-screen-share-a-streaming-service-in-a-watch-party">Can you screen share a streaming service in a watch party?</h3><p>You can share a browser tab, but results depend on the service and the browser. VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/handling-media/screen-share">React screen share guide</a> says screen sharing works in desktop browsers only, and tab audio only when sharing a Chrome tab in a Chromium-based browser. Services that protect video with digital rights management (DRM) can keep their frames out of a capture: Apple's <a href="https://developer.apple.com/library/archive/qa/qa1970/_index.html">Technical Q&amp;A QA1970</a> says FairPlay Streaming video in an iOS app is blacked out in screen recordings. Test the specific service and browser before you rely on screen share, and check the licensing terms too.</p><h3 id="how-many-people-can-join-a-watch-party">How many people can join a watch party?</h3><p>On VideoSDK, a room holds up to 100 participants and 15 active speakers by default, according to the quotas page (read 29 September 2026). Audience-only viewers have separate per-room limits: 1,000 for interactive live streaming and 200 for HLS. Organisation-wide concurrency limits apply on top, including 100 concurrent viewers before you add billing details and 200 on Pay-As-You-Go, which add-on packs can raise.</p>]]></content:encoded></item><item><title><![CDATA[RTMP vs SRT vs WHIP: Live Ingest Protocols Compared]]></title><description><![CDATA[RTMP, SRT and WHIP all carry live video from an encoder to an ingest server, but they fail differently on bad networks and suit different sources. This guide compares them against their specs and gives a rule for choosing one.]]></description><link>https://www.videosdk.live/blog/rtmp-vs-srt-vs-whip</link><guid isPermaLink="false">6abca2f6b3240feb748ca08e</guid><category><![CDATA[live-streaming]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 06 Oct 2026 12:49:20 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/24.png" medium="image"/><content:encoded><![CDATA[<blockquote>Choose RTMP (Real-Time Messaging Protocol) when a platform or content delivery network ingests RTMP and your uplink is stable. Choose SRT (Secure Reliable Transport) when a hardware encoder must cross a lossy public network. Choose WHIP (WebRTC-HTTP Ingestion Protocol) when a browser or OBS Studio feeds a WebRTC session. Put a gateway between them when sources differ.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/24.png" alt="RTMP vs SRT vs WHIP: Live Ingest Protocols Compared"/><p>RTMP vs SRT frames the first-mile question: which protocol carries a live stream from the encoder to the server that receives it. WHIP now belongs in the same comparison, because it lets a browser or OBS Studio push WebRTC (Web Real-Time Communication) media with one HTTP request. This guide, for developers choosing what an ingest endpoint accepts or an encoder sends, compares the three against their defining documents and ends with a decision rule. It covers ingest only; delivery to viewers, for example over HLS (HTTP Live Streaming), is a separate choice.</p><h2 id="rtmp-vs-srt-vs-whip-at-a-glance">RTMP vs SRT vs WHIP at a glance</h2><p>The table compares RTMP vs SRT vs WHIP as each ingest protocol's defining document describes it.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Attribute</th>
<th>RTMP</th>
<th>SRT</th>
<th>WHIP</th>
</tr>
</thead>
<tbody>
<tr>
<td>Defining document</td>
<td>Adobe memo (December 2012) plus Enhanced RTMP v2 (January 2026 revision)</td>
<td>Expired individual IETF (Internet Engineering Task Force) Internet-Draft, never an RFC</td>
<td>RFC 9725, IETF Standards Track, March 2025</td>
</tr>
<tr>
<td>Transport</td>
<td>TCP</td>
<td>UDP (User Datagram Protocol)</td>
<td>HTTP for setup, then ICE and DTLS-SRTP for media</td>
</tr>
<tr>
<td>Loss handling</td>
<td>TCP retransmits; later data waits</td>
<td>Retransmits within a latency window, drops late packets</td>
<td>Left to the WebRTC media stack</td>
</tr>
<tr>
<td>Encryption</td>
<td>RTMPS (RTMP over TLS) where the server offers it</td>
<td>Passphrase-based, off unless a passphrase is set</td>
<td>Always on (DTLS-SRTP)</td>
</tr>
<tr>
<td>Sender examples</td>
<td>OBS Studio, FFmpeg</td>
<td>OBS Studio 25.0 and later, FFmpeg with libsrt</td>
<td>Browsers, OBS Studio 30.0 and later, FFmpeg 8.0 and later</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The reading that matters: only WHIP has a finished IETF standard and a browser path, and SRT is built around a retransmission window you configure. RTMP's advantage sits outside the table: platforms already accept it.</p><h2 id="where-rtmp-ingest-still-wins-and-where-it-stops">Where RTMP ingest still wins, and where it stops</h2><p>RTMP ingest wins on reach. <a href="https://raw.githubusercontent.com/veovera/enhanced-rtmp/main/docs/legacy/rtmp-v1-0-spec.pdf">Adobe's RTMP specification</a> defines an application-level protocol that multiplexes audio, video and data over a reliable transport such as TCP (Transmission Control Protocol), and the <a href="https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=1935">IANA (Internet Assigned Numbers Authority) port registry</a> lists port 1935 as macromedia-fcs. <a href="https://support.google.com/youtube/answer/10364924?hl=en">YouTube's help centre</a> accepts RTMPS, which it describes as RTMP over a TLS (Transport Layer Security) connection.</p><p>RTMP ingest stops at packet loss. <a href="https://www.rfc-editor.org/rfc/rfc9293.html">RFC 9293</a> defines TCP as a reliable, in-order byte stream, so one lost segment holds back every byte behind it until the retransmission arrives.</p><p>The codec limit is changing. The <a href="https://veovera.org/docs/enhanced/enhanced-rtmp-v2">Enhanced RTMP v2 specification</a> says legacy RTMP and FLV (Flash Video) lack VP8, VP9, HEVC (High Efficiency Video Coding), VVC (Versatile Video Coding), AV1, Opus and FLAC, and adds them plus multitrack streams. The client declares its codecs in the connect command, so HEVC or AV1 over RTMP works only when the server supports Enhanced RTMP too. See <a href="https://www.videosdk.live/blog/what-is-rtmp">what the RTMP protocol is and how its handshake works</a> and <a href="https://www.videosdk.live/developer-hub/rtmp">the developer hub's RTMP guides</a>.</p><h2 id="how-does-the-srt-protocol-for-streaming-recover-lost-packets">How does the SRT protocol for streaming recover lost packets?</h2><p>The SRT protocol for streaming recovers lost packets by retransmitting them inside a fixed latency window and dropping any packet that still cannot arrive in time. The <a href="https://datatracker.ietf.org/doc/html/draft-sharabayko-srt">SRT Internet-Draft</a> describes the loop: the receiver sends a NAK (negative acknowledgement) when it sees a gap in sequence numbers, the sender puts the retransmission ahead of new packets, and the receiver releases each packet only after the configured latency has passed. Too-Late Packet Drop discards what misses its play time, keeping delay fixed at the cost of a glitch. The draft also allows FEC (forward error correction) alongside ARQ (automatic repeat request).</p><p>In libsrt, the reference implementation, the <a href="https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md">SRTO LATENCY socket option</a> defaults to 120 ms in live mode. A retransmission needs at least one round trip, so a longer or more jittery path needs a larger window; set it from the link's measured round-trip time.</p><p>SRT connects as caller, listener or rendezvous, and encrypts with AES (Advanced Encryption Standard) keys derived from a shared passphrase. The <a href="https://datatracker.ietf.org/doc/draft-sharabayko-srt/">IETF datatracker</a> lists its specification as an expired individual draft with no formal standing. The developer hub has <a href="https://www.videosdk.live/developer-hub/rtmp/rtmp-vs-srt">a Node.js RTMP server and an FFmpeg relay from RTMP to SRT</a>.</p><h2 id="how-whip-turns-webrtc-into-an-ingest-protocol">How WHIP turns WebRTC into an ingest protocol</h2><p>WHIP ingest sets up a WebRTC session with one HTTP exchange. In <a href="https://www.rfc-editor.org/rfc/rfc9725.html">RFC 9725</a>, the client POSTs an SDP (Session Description Protocol) offer, the server replies 201 Created with its SDP answer and a Location header naming the session, and the client completes ICE (Interactive Connectivity Establishment) and DTLS (Datagram Transport Layer Security) before sending media over SRTP (Secure Real-time Transport Protocol). An HTTP DELETE ends the session. PATCH carries trickle ICE candidates.</p><p>Encryption is mandatory. A browser can publish through the built-in <a href="https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection">RTCPeerConnection API</a>. And the destination must be a WebRTC media server, so WHIP suits streams that join a real-time room. For <a href="https://www.videosdk.live/developer-hub/webrtc/srt-vs-webrtc">how SRT and WebRTC compare once the stream reaches viewers</a>, see that comparison.</p><p>Authentication is where interoperability breaks. RFC 9725 section 4.7.1 has clients send a bearer token as defined in <a href="https://www.rfc-editor.org/rfc/rfc6750.html">RFC 6750</a>. OBS Studio, which added WHIP output in <a href="https://github.com/obsproject/obs-studio/releases/tag/30.0.0">version 30.0 on 12 November 2023</a>, and FFmpeg both send the literal prefix "Bearer". An endpoint that expects a raw token rejects them, so check what your endpoint accepts before choosing an encoder.</p><h2 id="which-ingest-protocol-should-you-choose">Which ingest protocol should you choose?</h2><p>Choose the ingest protocol by the source you must support and the network it crosses, not by a latency figure: none of the three specifications states one.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Source</th>
<th>Network</th>
<th>Send</th>
<th>Why</th>
</tr>
</thead>
<tbody>
<tr>
<td>Browser (webcam or screen)</td>
<td>Any</td>
<td>WHIP</td>
<td>The only one of the three a browser sends natively</td>
</tr>
<tr>
<td>OBS Studio to a social platform</td>
<td>Stable wired uplink</td>
<td>RTMP or RTMPS</td>
<td>Platforms document RTMP ingest; RTMPS adds TLS</td>
</tr>
<tr>
<td>OBS Studio into a WebRTC room</td>
<td>Any</td>
<td>WHIP (OBS 30.0 and later)</td>
<td>Lands in the room with no conversion</td>
</tr>
<tr>
<td>Hardware or field encoder</td>
<td>Lossy public internet or cellular</td>
<td>SRT</td>
<td>A retransmission window tuned to the path</td>
</tr>
<tr>
<td>IP camera</td>
<td>Local network</td>
<td>RTSP, pulled by a gateway</td>
<td>The gateway re-sends it as WHIP, RTMP or SRT</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The reading: if one row covers all your sources, accept one protocol. If your sources span rows, accept the protocol your destination speaks and convert the rest at a gateway.</p><h2 id="bridging-rtmp-srt-and-rtsp-sources-into-a-webrtc-room">Bridging RTMP, SRT and RTSP sources into a WebRTC room</h2><p>A protocol gateway receives RTMP, SRT or RTSP (Real-Time Streaming Protocol) and republishes each stream to a WebRTC room's WHIP endpoint, transcoding only when the codec does not fit WebRTC. IP cameras are one reason to run a gateway, because they serve <a href="https://www.videosdk.live/blog/what-is-rtsp-protocol">RTSP streams from the camera</a>.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/rtmp-vs-srt-vs-whip-ingest-paths.png" class="kg-image" alt="RTMP vs SRT vs WHIP: Live Ingest Protocols Compared" loading="lazy" width="3200" height="1800"/></figure><p><em>A browser reaches the room over WHIP directly; RTMP, SRT and RTSP sources reach it through an ingest server or gateway that re-sends them as WHIP.</em></p><p>FFmpeg can be that gateway. Its <a href="https://ffmpeg.org/ffmpeg-formats.html#whip">whip muxer</a>, added in <a href="https://ffmpeg.org/index.html#news">FFmpeg 8.0</a> on 22 August 2025, is marked experimental, expects H.264 without B-frames and Opus audio, and sends its optional authorization value as a Bearer token. A gateway built on it re-encodes the input to fit those limits and writes the whip format to the room's endpoint URL.</p><h2 id="how-videosdk-handles-ingest-and-output">How VideoSDK handles ingest and output</h2><p>In a WebRTC-based live platform, the room is the hub: streams arrive over WebRTC, and larger audiences get HLS or an RTMP restream. VideoSDK documents WHIP ingest and RTMP output, and does not document RTMP or SRT ingest. The <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/whip-whep-ils">WHIP/WHEP guide</a> says a stream sent to the WHIP endpoint appears as a participant in the room, and the <a href="https://docs.videosdk.live/api-reference/realtime-communication/whip/create-whip">Create WHIP Session API</a> returns the SDP answer with a Location header. That reference asks for the token without a prefix, while OBS and FFmpeg send "Bearer". </p><p>For output, <code>startLivestream()</code> pushes the room to RTMP destinations such as YouTube, Twitch and Facebook, taking an array of URL and stream key pairs, per the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/rtmp-livestream">RTMP livestream guide</a>. The room can also reach viewers as HLS; see <a href="https://www.videosdk.live/blog/what-is-http-live-streaming">how HLS packages the stream for viewers</a> and <a href="https://www.videosdk.live/blog/what-is-rtmp-in-and-rtmp-out">the difference between RTMP in and RTMP out</a>. Until the docs say otherwise, an RTMP or SRT source reaches a VideoSDK room through a gateway that republishes it over WHIP.</p><h2 id="scale-and-cost-of-live-ingest">Scale and cost of live ingest</h2><p>Ingest cost grows with the number of streams arriving at once, because each protocol keeps state for every stream: each RTMP publisher holds a TCP connection (<a href="https://www.rfc-editor.org/rfc/rfc9293.html">RFC 9293</a>), an SRT receiver buffers every stream for its latency window, which <a href="https://github.com/Haivision/srt/blob/master/docs/API/API-socket-options.md">libsrt sets to 120 ms by default</a> in live mode, and a WHIP endpoint keeps ICE and DTLS state for each session (<a href="https://www.rfc-editor.org/rfc/rfc9725.html">RFC 9725</a>).</p><p>A gateway adds compute for every stream it converts. FFmpeg's <a href="https://ffmpeg.org/ffmpeg-formats.html#whip">whip muxer</a> expects H.264 without B-frames and Opus audio, so a source in any other codec has to be re-encoded before it can be sent over WHIP.</p><p>On VideoSDK, as of 6 October 2026, the <a href="https://docs.videosdk.live/help_docs/pricing">pricing FAQ</a> charges RTMP Out at $0.03 per re-streamed minute and bills each RTMP output stream separately. The <a href="https://www.videosdk.live/pricing">pricing page</a> lists WHIP and WHEP among the live streaming features without a separate rate, and caps simultaneous RTMP out streams per plan, with packs of 10 more streams for $20 a month.</p><p>Worked example, with hypothetical inputs: restreaming a 2-hour event to YouTube and Twitch is two RTMP output streams of 120 minutes each, so 2 × 120 × $0.03 = $7.20 at that rate. Hosts and viewers in the room are billed separately as speaker and viewer minutes, and the <a href="https://docs.videosdk.live/help_docs/pricing">pricing FAQ</a> works through an example of those.</p><h2 id="glossary">Glossary</h2><blockquote><strong>RTMPS (RTMP over TLS):</strong> RTMP carried inside a TLS connection, so the stream key and media are encrypted in transit.</blockquote><blockquote><strong>Enhanced RTMP (E-RTMP):</strong> An extension of RTMP and FLV, maintained by the Veovera Software Organization, that adds modern codec signalling and multitrack media.</blockquote><blockquote><strong>ARQ (automatic repeat request):</strong> Loss recovery by asking the sender to retransmit missing packets. SRT triggers it with NAK reports.</blockquote><blockquote><strong>SDP offer and answer:</strong> The text descriptions of codecs, transports and connection details that two WebRTC endpoints exchange.</blockquote><blockquote><strong>WHEP (WebRTC-HTTP Egress Protocol):</strong> The playback counterpart of WHIP, which lets a player pull WebRTC media with the same HTTP pattern. The <a href="https://datatracker.ietf.org/doc/draft-ietf-wish-whep/">IETF datatracker</a> lists it as a working-group draft.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>RTMP vs SRT is a choice between reach and resilience: RTMP reaches platforms that document RTMP ingest, and SRT recovers loss over UDP inside a latency window you set.</li><li>WHIP, published as RFC 9725 in March 2025, is the only IETF standard of the three and the only one a browser sends without a plugin.</li><li>Decide by source and network: browsers and WebRTC rooms take WHIP, social platforms take RTMP or RTMPS, and field encoders on lossy links send SRT.</li><li>RTMP carries HEVC or AV1 only when both ends support Enhanced RTMP.</li><li>Ingest cost grows with simultaneous streams; on VideoSDK, RTMP Out costs $0.03 per re-streamed minute for each destination, as of 6 October 2026.</li></ul><p>If your sources span rows of the decision table, put a gateway in front of your destination. To see a WHIP stream join a room as a participant, work through the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/whip-whep-ils">VideoSDK WHIP/WHEP guide for interactive live streaming</a>; a new account includes a <a href="https://www.videosdk.live/pricing" rel="noreferrer">$20 credit</a>.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-the-rtmp-full-form">What is the RTMP full form?</h3><p>RTMP stands for Real-Time Messaging Protocol; Adobe's specification spells it without the hyphen. According to the Enhanced RTMP specification, RTMP and the FLV file format were introduced in 2002, and Adobe published the protocol as a memo in December 2012.</p><h3 id="how-do-you-use-the-srt-protocol-in-obs">How do you use the SRT protocol in OBS?</h3><p>OBS Studio sends SRT from version 25.0, according to the <a href="https://github.com/obsproject/obs-studio/wiki/Streaming-With-SRT-Or-RIST-Protocols">OBS wiki page on SRT streaming</a>. You enter an srt:// URL as the stream server, with options such as latency and passphrase that must match the receiver. The same page, last edited in July 2023, says the main streaming services did not accept SRT ingest. </p><h3 id="is-srt-encrypted-by-default">Is SRT encrypted by default?</h3><p>No. SRT supports AES encryption with 128, 192 or 256-bit keys, but it switches on only when a passphrase is set. In libsrt, SRTO_PASSPHRASE defaults to an empty string, which disables encryption. A passphrase must be 10 to 80 characters, and a peer with a different passphrase is rejected unless enforced encryption is turned off.</p><h3 id="is-whip-an-ietf-standard-or-still-a-draft">Is WHIP an IETF standard or still a draft?</h3><p>WHIP is a published IETF standard: RFC 9725, issued in March 2025 on the Standards Track, updating RFCs 8840 and 8842. The RFC requires WHIP clients to implement bearer token authentication, though an endpoint may choose not to require a token.</p>]]></content:encoded></item><item><title><![CDATA[Video Transcoding Explained: Why Live Streams Need It]]></title><description><![CDATA[Video transcoding turns one encoded stream into the versions your viewers can play. This guide covers transcoding vs encoding, how a live transcoder builds an aligned ABR ladder, a worked compute estimate for the ladder, and where the transcode can run.]]></description><link>https://www.videosdk.live/blog/video-transcoding-live-streaming</link><guid isPermaLink="false">6abca2d8b3240feb748ca088</guid><category><![CDATA[live-streaming]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 05 Oct 2026 12:35:53 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/20.png" medium="image"/><content:encoded><![CDATA[<blockquote>Video transcoding is decoding an already encoded video and encoding it again with different settings, such as another codec, resolution or bitrate. Live streams need it because one incoming feed must become a ladder of versions while the event runs, so each viewer's player can pick the version its screen and network can handle.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/20.png" alt="Video Transcoding Explained: Why Live Streams Need It"/><p>This guide is for developers building live video. It covers transcoding for streaming, not video editing: how it differs from encoding and transmuxing, how a live transcoder builds an aligned HTTP Live Streaming (HLS) ladder, what each rung costs in compute, and where the work runs.</p><h2 id="what-is-video-transcoding">What is video transcoding?</h2><p>Video transcoding is the process of decoding a stream and then encoding it again, as the <a href="https://ffmpeg.org/ffmpeg.html">FFmpeg manual</a> defines it in section 3.2. In streaming, it turns the stream you have into one a given device, network or player can use.</p><p>A transcoding workflow has three steps:</p><ol><li><strong>Decode</strong> the compressed video into raw frames.</li><li><strong>Process</strong> the frames: scale, change the frame rate, deinterlace or overlay.</li><li><strong>Encode</strong> the frames again with the target codec, resolution and bitrate.</li></ol><p>The types of transcoding are named by what changes. <a href="https://aws.amazon.com/what-is/video-transcoding/">AWS's guide to video transcoding</a> calls a bitrate-only change transrating and a resolution or aspect-ratio change transizing. A codec change, such as <a href="https://www.videosdk.live/developer-hub/social/av1-vs-h264">H.264 to AV1</a>, swaps the encoder. The FFmpeg manual advises transcoding only when you need to, because encoding is computationally expensive and in most cases lossy.</p><h2 id="transcoding-vs-encoding-what-is-the-difference">Transcoding vs encoding: what is the difference?</h2><p>Transcoding vs encoding comes down to the input. Encoding compresses raw frames from a camera or screen; transcoding starts from compressed video, so it must decode first. That difference between encoding and transcoding explains the quality cost: a transcoder never sees the original picture. For codecs, containers and encoder settings, see <a href="https://www.videosdk.live/blog/video-encoding">how video encoding works</a>.</p><p>The table adds transmuxing, a third process often confused with both.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Process</th>
<th>Input</th>
<th>Output</th>
<th>Quality cost</th>
<th>Typical place in a live pipeline</th>
</tr>
</thead>
<tbody>
<tr>
<td>Encoding</td>
<td>Raw frames</td>
<td>Compressed stream</td>
<td>Lossy with streaming codecs</td>
<td>The broadcaster's app or hardware encoder</td>
</tr>
<tr>
<td>Transcoding</td>
<td>Compressed stream</td>
<td>New codec, size or bitrate</td>
<td>A second round of loss</td>
<td>The server that builds the ladder</td>
</tr>
<tr>
<td>Transmuxing</td>
<td>Compressed stream</td>
<td>Same stream in a new container</td>
<td>None, nothing is re-encoded</td>
<td>The packager that writes HLS segments</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Read it by the Input column: encoding vs transcoding is a question of where your video comes from.</p><h3 id="transmuxing-vs-transcoding">Transmuxing vs transcoding</h3><p>Transmuxing vs transcoding is repackaging vs re-encoding. Transmuxing, or remuxing, moves encoded video and audio into a new container without decoding them. The FFmpeg manual calls this streamcopy and notes that, with no decoding or encoding, it is very fast and loses no quality. It cannot resize the picture or change the bitrate. One live example: an H.264 feed arriving over the <a href="https://www.videosdk.live/developer-hub/rtmp/rtmp-vs-srt" rel="noreferrer">Real-Time Messaging Protocol (RTMP)</a> is cut into HLS segments unchanged.</p><h2 id="what-is-video-transcoding-for-live-streaming">What is video transcoding for live streaming?</h2><p>Video transcoding for live streaming, or live transcoding, turns one incoming stream into several versions of the same content while the event is still running. The broadcaster sends one high-quality stream, and a transcoder produces lower resolutions and bitrates in real time for viewers on smaller screens and slower connections.</p><p>In <a href="https://www.videosdk.live/blog/what-is-http-live-streaming">HLS (HTTP Live Streaming)</a>, each version is a variant stream. <a href="https://www.rfc-editor.org/rfc/rfc8216">RFC 8216</a>, the HLS specification, describes a master playlist that lists the variant streams, each at its own bitrate, format and resolution, and says clients should switch between them to adapt to network conditions. That set is the <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">adaptive bitrate (ABR)</a> ladder; the transcoder builds it, and how players choose a rung is the player's half.</p><p>Sending the source to everyone fails three ways: it stalls slower connections, wastes pixels on phones, and may use a codec some devices cannot decode.</p><h2 id="how-live-transcoding-builds-an-abr-ladder">How live transcoding builds an ABR ladder</h2><p>Live transcoding builds the ladder by decoding the incoming stream once and encoding it several times.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/video-transcoding-live-abr-ladder.png" class="kg-image" alt="Video Transcoding Explained: Why Live Streams Need It" loading="lazy" width="3200" height="1800"/></figure><p><em>One decode feeds every rung (the top one can pass through), and keyframes and segment boundaries share timestamps, so players can switch cleanly.</em></p><p>The decoded frames are split into one copy per rung, and each copy is scaled and encoded at its own bitrate. FFmpeg's <a href="https://ffmpeg.org/ffmpeg-filters.html">split filter</a> makes the copies; four separate transcodes would decode the same frames four times.</p><p>The rungs must also line up, or players cannot switch cleanly:</p><ul><li>RFC 8216, section 6.2.4, requires the same content with matching timestamps in every variant stream, and the same target duration in every media playlist.</li><li>Apple's <a href="https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices">HLS Authoring Specification</a> recommends keyframes, or instantaneous decoder refresh (IDR) frames, every two seconds (item 1.13), 6-second target durations (item 7.5) and segment boundaries at the same times in every variant (item 8.22).</li></ul><p>Alignment is a keyframe problem. The <a href="https://ffmpeg.org/ffmpeg-formats.html">FFmpeg formats documentation</a> says its HLS muxer cuts a segment at the next keyframe after <code>hls_time</code> has passed, so every rung needs keyframes at the same timestamps, forced by time. For the encoder side, see <a href="https://www.videosdk.live/blog/what-is-a-keyframe">what a keyframe interval controls</a>.</p><h2 id="code-quickstart-build-a-live-abr-ladder-with-ffmpeg">Code quickstart: build a live ABR ladder with FFmpeg</h2><p>This FFmpeg command builds the four rungs used in the cost table below from one input: it decodes once, splits the frames into four copies, and writes an HLS ladder whose rungs share keyframe times and segment boundaries.</p><pre><code class="language-bash">ffmpeg -re -i input.mp4 \
  -filter_complex "[0:v]split=4[v1][v2][v3][v4];[v1]scale=w=1920:h=1080[v1out];[v2]scale=w=1280:h=720[v2out];[v3]scale=w=960:h=540[v3out];[v4]scale=w=640:h=360[v4out]" \
  -map "[v1out]" -c:v:0 libx264 -b:v:0 6000k \
  -map "[v2out]" -c:v:1 libx264 -b:v:1 3000k \
  -map "[v3out]" -c:v:2 libx264 -b:v:2 2000k \
  -map "[v4out]" -c:v:3 libx264 -b:v:3 365k \
  -map a:0 -map a:0 -map a:0 -map a:0 -c:a aac -b:a 128k \
  -force_key_frames "expr:gte(t,n_forced*2)" -sc_threshold 0 \
  -f hls -hls_time 6 -hls_playlist_type event \
  -hls_segment_filename "stream_%v/segment_%03d.ts" \
  -master_pl_name master.m3u8 \
  -var_stream_map "v:0,a:0 v:1,a:1 v:2,a:2 v:3,a:3" \
  stream_%v/index.m3u8</code></pre><p>What each part of the command does:</p><ul><li><code>-re</code> reads the input at its native frame rate, so a file behaves like a live feed. Replace <code>input.mp4</code> with your live source.</li><li><code>split=4</code> makes four copies of the decoded frames, and each <code>scale</code> filter sizes one copy, so the input is decoded only once.</li><li><code>-b:v:0</code> to <code>-b:v:3</code> set each rung's bitrate, taken from Apple's example ladder.</li><li><code>-force_key_frames "expr:gte(t,n_forced*2)"</code> puts a keyframe every 2 seconds in every rung, and <code>-sc_threshold 0</code> stops libx264 from adding extra keyframes at scene changes.</li><li><code>-hls_time 6</code> asks for 6-second segments, <code>-var_stream_map</code> pairs each video rung with a copy of the audio, and <code>-master_pl_name</code> writes the multivariant playlist that lists the four rungs.</li></ul><p>We ran this command with FFmpeg 9.0.1 on a 20-second 1080p, 30 fps test file on 5 October 2026. It wrote a master playlist listing the four renditions, every rung's segments were 6, 6, 6 and 2 seconds long, and keyframes landed every 2 seconds at the same timestamps in the 1080p and 360p rungs.</p><h2 id="live-transcoding-scale-and-cost-a-worked-ladder-calculation">Live transcoding scale and cost: a worked ladder calculation</h2><p>Live transcoding cost is mostly compute, and pixel rate (width times height times frames per second) gives a first estimate. The table applies it to four rungs of Apple's example H.264 ladder (item 1.25), for a hypothetical 30 fps source. It is a proxy: real encode time also depends on codec, preset and hardware.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Rung</th>
<th>Resolution</th>
<th>Bitrate (Apple example)</th>
<th>Pixels per second at 30 fps</th>
<th>Share of encode work</th>
</tr>
</thead>
<tbody>
<tr>
<td>1080p</td>
<td>1920 x 1080</td>
<td>6,000 kbps</td>
<td>62.2 million</td>
<td>55%</td>
</tr>
<tr>
<td>720p</td>
<td>1280 x 720</td>
<td>3,000 kbps</td>
<td>27.6 million</td>
<td>25%</td>
</tr>
<tr>
<td>540p</td>
<td>960 x 540</td>
<td>2,000 kbps</td>
<td>15.6 million</td>
<td>14%</td>
</tr>
<tr>
<td>360p</td>
<td>640 x 360</td>
<td>365 kbps</td>
<td>6.9 million</td>
<td>6%</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The top rung is more than half the encode work, so it is the first place to save: when the source's codec, bitrate and keyframe cadence already fit, pass it through with streamcopy and encode only the lower rungs. How tightly each rung holds its bitrate is a choice between <a href="https://www.videosdk.live/blog/cbr-vs-vbr">constant and variable bitrate</a>. </p><p>The compute runs for every live minute, whatever the audience size, because the ladder is made once for everyone. A decision rule follows:</p><ol><li><strong>Transmux</strong> when the source already plays on your viewers' devices and one bitrate is enough.</li><li><strong>Transcode the lower rungs</strong> when viewers differ in screen and network, as in a broadcast.</li><li><strong>Move the work to the sender</strong> with simulcast when the audience is small and interactive, as in a video call.</li></ol><h3 id="how-live-transcoding-cost-scales">How live transcoding cost scales</h3><p>Live transcoding cost scales with channels and minutes, while delivery cost scales with viewers. Each live channel needs its own ladder for as long as it runs, so 10 simultaneous events need about 10 times the encode compute of one, however many people watch each. Sending the renditions to viewers is the part that grows with the audience.</p><p>For a sense of the compute, the FFmpeg command above kept pace with real time on an Apple M2 laptop using about 2.5 CPU cores: 49 CPU-seconds for 20 seconds of 1080p, 30 fps video, with libx264 at its default preset, on 5 October 2026. A synthetic test pattern is not your content, so measure with your own footage before sizing servers.</p><p>On a managed service the same split shows up in the bill. Worked example, with hypothetical inputs, at VideoSDK's rates as of 5 October 2026: a 2-hour event encoded at 1080p costs 120 minutes × $0.08 = $9.60 of HLS encoding. If 200 viewers watch the whole event at 1080p, viewing adds 200 × 120 × $0.001 = $24.00, for $33.60 in total. Doubling the audience doubles only the viewing line.</p><p>Concurrent viewers and simultaneous HLS encodings are capped per plan, with packs to add more, on the <a href="https://docs.videosdk.live/help_docs/quotas-and-limit">VideoSDK quotas and limits page</a>.</p><h2 id="where-live-transcoding-runs-and-how-videosdk-handles-it">Where live transcoding runs, and how VideoSDK handles it</h2><p>Live transcoding can run in three places. At the source, the sender encodes several versions itself: <a href="https://www.rfc-editor.org/rfc/rfc8853">RFC 8853</a> defines simulcast as sending multiple encoded streams of the same media source, so a selective forwarding unit (SFU) picks one per receiver. On your own server, FFmpeg or a media server runs the pipeline above. In a cloud service, the provider runs it, and AWS notes that local transcoding means maintaining the infrastructure yourself.</p><p>VideoSDK's HLS output is the cloud case. Its <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/integrate-hls/overview">HLS overview</a> says the platform uses a default theme or your template to compose and encode the live stream, delivered as an M3U8 playlist that adapts to viewers' bandwidth. You choose a quality setting rather than building the ladder: the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/integrate-hls/start-hls">React start-HLS guide</a> lists low, med and high (SD, HD and FHD), and the <a href="https://docs.videosdk.live/server-sdk/reference/hls">Server SDK HLS reference</a> says there is no resolution option. </p><p>As of 5 October 2026, VideoSDK's <a href="https://www.videosdk.live/pricing">pricing page</a> bills HLS encoding per livestream minute: $0.04 at 720p and $0.08 at 1080p. The Server SDK's <a href="https://docs.videosdk.live/server-sdk/reference/transcodings">Transcodings resource</a> handles finished recordings and HLS streams (merging, HLS to MP4), not live feeds.</p><h3 id="start-a-transcoded-hls-stream-with-videosdk">Start a transcoded HLS stream with VideoSDK</h3><p>In the React SDK, a host who has joined the room starts HLS with startHls() from the useMeeting hook. This example from the start-HLS guide asks for the high (FHD) quality:</p><pre><code class="language-jsx">import { useMeeting } from "@videosdk.live/react-sdk";

const MeetingView = () =&gt; {
  const { startHls, stopHls } = useMeeting();

  const handleStartHls = async () =&gt; {
    // Start Hls
    try {
      await startHls({
        layout: {
          type: "GRID",
          priority: "SPEAKER",
          gridSize: 4,
        },
        theme: "DARK",
        mode: "video-and-audio",
        quality: "high",
        orientation: "landscape",
      });
    } catch (err) {
      console.error("startHls failed:", err);
    }
  };

  return (
    &lt;&gt;
      &lt;button onClick={handleStartHls}&gt;Start Hls&lt;/button&gt;
    &lt;/&gt;
  );
};</code></pre><p>When onHlsStateChanged reports HLS_PLAYABLE, the event carries playbackHlsUrl and livestreamUrl for your viewers' player. The guide also lists the layout, theme, mode and orientation options.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Variant stream (rendition):</strong> One version of the content in an HLS ladder, with its own bitrate, resolution and media playlist.</blockquote><blockquote><strong>Multivariant playlist (master playlist):</strong> The top-level HLS playlist that lists every variant stream with its bandwidth and resolution.</blockquote><blockquote><strong>IDR frame (keyframe):</strong> A frame a decoder can start from without earlier frames, which is why segments and rung switches begin on one.</blockquote><blockquote><strong>Transrating:</strong> Transcoding that changes only the bitrate, keeping the codec and resolution.</blockquote><blockquote><strong>Transizing (transsizing):</strong> Transcoding that changes the resolution or aspect ratio without changing the codec.</blockquote><blockquote><strong>Passthrough rung:</strong> A ladder rung that carries the source stream as it arrived, by streamcopy, instead of re-encoding it.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>Video transcoding decodes an already encoded stream and encodes it again with a different codec, resolution or bitrate, and each pass costs compute and some quality.</li><li>Transcode only when the output must differ; transmux when only the container changes, and use sender-side simulcast for small interactive audiences.</li><li>Live transcoding decodes the feed once and encodes a ladder whose rungs share timestamps, target duration and keyframe times, with keyframes every 2 seconds as Apple recommends.</li><li>In a four-rung ladder the 1080p rung is about 55% of the encode work, so passing a suitable source through is the first saving.</li><li>Transcoding cost grows with live channels and minutes, and delivery cost with viewers: at VideoSDK's rates as of 5 October 2026, a hypothetical 2-hour 1080p event for 200 viewers costs $9.60 of encoding and $24.00 of viewing.</li></ul><p>Check whether your source already fits your top rung, then size the lower rungs from your viewers' devices and networks. To see how VideoSDK delivers a live stream over HLS, read the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/introduction">interactive live streaming documentation</a>; there is a $20 credit on a new account.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="does-transcoding-reduce-video-quality">Does transcoding reduce video quality?</h3><p>Yes, in most cases. A transcode is a second lossy encode of an already degraded picture, so detail lost the first time cannot come back, and a higher output bitrate limits further loss without restoring any. When only the container must change, transmux instead and keep the original quality.</p><h3 id="does-live-transcoding-add-latency">Does live transcoding add latency?</h3><p>Yes, some. NVIDIA's <a href="https://docs.nvidia.com/video-technologies/video-codec-sdk/13.0/ffmpeg-with-nvidia-gpu/index.html">FFmpeg guide for its GPUs</a> keeps B-frames and look-ahead for latency-tolerant work and disables B-frames for low-latency uses, where it says latency can be as low as 16 ms. HLS delivery adds far more: RFC 8216 requires a listed segment to be downloadable at once, and tells players not to start within three target durations of the live edge, 18 seconds at 6-second segments.</p><h3 id="do-webrtc-video-calls-use-transcoding">Do WebRTC video calls use transcoding?</h3><p>They can avoid it. For Web Real-Time Communication (WebRTC) media, RFC 8853 describes simulcast as a trade-off: the sender encodes a few differently configured streams and a forwarding server picks one per receiver, instead of a mixer creating individual transcodings for each participant. The work moves to the sender's device, which suits small rooms where every participant is also a viewer.</p><h3 id="can-a-gpu-transcode-a-live-stream">Can a GPU transcode a live stream?</h3><p>Yes. NVIDIA's FFmpeg guide shows its hardware decoder and encoder (NVDEC and NVENC) transcoding one input into several resolutions and bitrates, scaling on the GPU so frames stay in video memory. Its low-latency mode lowers encoding quality, NVIDIA warns, so compare quality at your target bitrates first.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Live Auction Streaming App in React]]></title><description><![CDATA[How a live auction streaming app fits together, verbatim React code from VideoSDK's interactive live streaming quickstart, a rule for keeping bids server-authoritative, and a worked per-viewer cost example.]]></description><link>https://videosdk.live/blog/live-auction-streaming-app</link><guid isPermaLink="false">6abca413b3240feb748ca0a1</guid><category><![CDATA[live-streaming]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 05 Oct 2026 12:35:11 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/21.png" medium="image"/><content:encoded><![CDATA[<blockquote>A live auction streaming app pairs a Web Real-Time Communication (WebRTC) video room with a bid service you control. The auctioneer publishes video, bidders join as receive-only viewers, every bid goes to your backend to be validated and ordered, and each accepted bid is broadcast to all viewers over a real-time message channel while a timer closes the lot.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/21.png" alt="How to Build a Live Auction Streaming App in React"/><p>This guide is for developers adding live video bidding to an auction product. Auction houses that want a ready-made product can buy live auction software instead; this page is about building one. It covers the components, how bid timing decides whether bidders can use standard HTTP Live Streaming (HLS), verbatim React code from VideoSDK's interactive live streaming quickstart, server-authoritative bids and a worked cost example.</p><h2 id="how-a-live-auction-streaming-app-works">How a live auction streaming app works</h2><p>A live auction streaming app runs two separate paths: a media path for the auctioneer's video and a data path for bids. The video layer should never decide who is winning.</p><p>The table compares the four components by job and trade-off.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Component</th>
<th>Job</th>
<th>What you build</th>
<th>Trade-off</th>
</tr>
</thead>
<tbody>
<tr>
<td>Auctioneer video path</td>
<td>Publishes camera and mic into a room</td>
<td>Host client</td>
<td>Needs a stable uplink</td>
</tr>
<tr>
<td>Bidder viewing path</td>
<td>Plays the auctioneer's feed</td>
<td>Receive-only viewer client</td>
<td>Close to live, billed per viewer minute</td>
</tr>
<tr>
<td>Bid service</td>
<td>Accepts or rejects bids; runs the lot timer</td>
<td>Your backend and database</td>
<td>Must order concurrent bids</td>
</tr>
<tr>
<td>Message channel</td>
<td>Tells every screen the new high bid</td>
<td>A publish-subscribe topic per lot</td>
<td>Fast fan-out, not a ledger</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The key reading: only the bid service decides a winner; the other three display its decision.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/live-auction-streaming-app-architecture.png" class="kg-image" alt="How to Build a Live Auction Streaming App in React" loading="lazy" width="3200" height="1800"/></figure><p><em>Video and bids travel separately: the room carries media, and the bid service decides the winner before anyone announces it.</em></p><p>In VideoSDK, this pattern is <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/concept-and-architecture">interactive live streaming (ILS)</a>: hosts join a room in <code>SEND_AND_RECV</code> mode, the audience joins in <code>RECV_ONLY</code> mode, and PubSub topics can carry bid messages.</p><h2 id="why-bid-timing-decides-between-webrtc-and-hls">Why bid timing decides between WebRTC and HLS</h2><p>Bid timing decides the viewer protocol because a bidder whose video runs seconds behind the auctioneer is bidding on the past.</p><p>Standard HLS builds in delay. <a href="https://www.rfc-editor.org/rfc/rfc8216#section-6.3.3">RFC 8216, section 6.3.3</a>, says a live client SHOULD NOT start less than three target durations from the end of the playlist, and <a href="https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices">Apple's HLS authoring specification</a>, item 7.5, says target durations SHOULD be 6 seconds. A player following both starts about 18 seconds or more behind the end of the playlist, before encoding and delivery delay.</p><p>The decision rule: if a lot's bid window is shorter than the viewer delay, bidders need the WebRTC path, and HLS suits a watch-only audience. The full trade-off is in <a href="https://www.videosdk.live/blog/hls-vs-webrtc">how WebRTC and HLS differ on latency, scale and cost</a>.</p><h2 id="react-quickstart-stream-room-roles-and-viewers">React quickstart: stream room, roles and viewers</h2><p>The React quickstart code uses VideoSDK's React SDK, checked 29 Sep 2026: the example requests <code>@videosdk.live/react-sdk</code> ^1.1.1, the version npm tagged <code>latest</code> that day.</p><h3 id="set-up-the-project">Set up the project</h3><p>Create a new React App using the below command.</p><pre><code class="language-bash">npm create vite@latest videosdk-ils-react-app -- --template react
cd videosdk-ils-react-app</code></pre><p>Install the VideoSDK using the below-mentioned npm command. Make sure you are in your react app directory before you run this command.</p><pre><code class="language-bash">npm install "@videosdk.live/react-sdk"</code></pre><pre><code class="language-bash">yarn add "@videosdk.live/react-sdk"</code></pre><p>Your project structure should look like this.</p><pre><code class="language-plaintext">   root
   ├── node_modules
   ├── public
   ├── src
   │    ├── API.js
   │    ├── App.jsx
   │    ├── App.css
   │    ├── main.jsx
   ├── package.json
   .    .</code></pre><p>You are going to use functional components to leverage react's reusable component architecture. There will be components for users, videos, and controls (mic, camera, leave) over the video.</p><p>You will be working on these files:</p><ul><li>API.js: Responsible for handling API calls such as generating unique streamId and token</li><li>App.jsx: Responsible for rendering container and joining the Live Stream.</li></ul><h3 id="get-started-with-apijs">Get started with API.js</h3><p>Each participant needs a JSON Web Token (JWT). Dashboard tokens are for testing; in production, <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/authentication-and-token">generate the token on your server</a> so the API secret never reaches a browser.</p><p><code>createStream</code> posts to the rooms endpoint and returns a <code>roomId</code>, which the quickstart calls a stream ID. Use one room per auction session.</p><pre><code class="language-javascript">// Generate your token at https://app.videosdk.live/api-keys and paste it below.
export const authToken = "";

// API call to create stream
export const createStream = async ({ token }) =&gt; {
  try {
    const res = await fetch(`https://api.videosdk.live/v2/rooms`, {
      method: "POST",
      headers: {
        authorization: `${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({}),
    });

    if (!res.ok) {
      throw new Error(`Failed to create stream: ${res.status}`);
    }

    const { roomId } = await res.json();
    return roomId;
  } catch (error) {
    console.error("createStream failed", error);
    throw error;
  }
};
</code></pre><h3 id="initialize-and-join-the-live-stream">Initialize and join the live stream</h3><p>The <code>App</code> component passes <code>meetingId</code>, <code>mode</code>, <code>name</code>, <code>micEnabled</code>, <code>webcamEnabled</code> and the token to <code>MeetingProvider</code>. The auctioneer joins in <code>SEND_AND_RECV</code> and bidders in <code>RECV_ONLY</code>; the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/setup-livestream/initialize-livestream">initialize live stream guide</a> says mic and webcam settings are ignored for audience participants.</p><pre><code class="language-jsx">import "./App.css";
import React, { useEffect, useRef, useState } from "react";
import {
  MeetingProvider,
  useMeeting,
  useParticipant,
  Constants,
} from "@videosdk.live/react-sdk";
import { authToken, createStream } from "./API";

// Join Screen - Handles joining or creating a stream
function JoinView({ initializeStream, setMode }) {
  const [streamId, setStreamId] = useState("");

  const handleAction = async (mode) =&gt; {
    // Sets the mode (Host or Audience) and initializes the stream
    setMode(mode);
    await initializeStream(streamId);
  };

  return (
    &lt;div className="container"&gt;
      {/* Button to create a new stream */}
      &lt;button onClick={() =&gt; handleAction(Constants.modes.SEND_AND_RECV)}&gt;
        Create Live Stream as Host
      &lt;/button&gt;
      {/* Input field for entering an existing Stream ID */}
      &lt;input
        type="text"
        placeholder="Enter Stream Id"
        onChange={(e) =&gt; setStreamId(e.target.value)}
      /&gt;
      {/* Button to join as a host */}
      &lt;button onClick={() =&gt; handleAction(Constants.modes.SEND_AND_RECV)}&gt;
        Join as Host
      &lt;/button&gt;
      {/* Button to join as an audience member */}
      &lt;button onClick={() =&gt; handleAction(Constants.modes.RECV_ONLY)}&gt;
        Join as Audience
      &lt;/button&gt;
    &lt;/div&gt;
  );
}

// Live Stream Container - Placeholder for the live stream container
function LSContainer(props) {
  return null;
}

// Main App Component - Handles the app flow and live stream lifecycle
function App() {
  const [streamId, setStreamId] = useState(null); // Holds the current stream ID
  const [mode, setMode] = useState(Constants.modes.SEND_AND_RECV); // Holds the current user mode (Host or Audience)

  const initializeStream = async (id) =&gt; {
    if (!authToken) {
      console.error("PLEASE PROVIDE TOKEN IN API.js FROM app.videosdk.live");
      return;
    }
    // Creates a new stream if no ID is provided or uses the given stream ID
    const newStreamId = id || (await createStream({ token: authToken }));
    setStreamId(newStreamId);
  };

  const onStreamLeave = () =&gt; setStreamId(null); // Resets the stream state on leave

  return authToken &amp;&amp; streamId ? (
    // Provides the stream context to the application
    &lt;MeetingProvider
      config={{
        meetingId: streamId,
        micEnabled: true, // Enables microphone by default
        webcamEnabled: true, // Enables webcam by default
        name: "John Doe", // Default participant name
        mode,
      }}
      token={authToken}
    &gt;
      {/* Renders the live stream container if a stream is active */}
      &lt;LSContainer streamId={streamId} onLeave={onStreamLeave} /&gt;
    &lt;/MeetingProvider&gt;
  ) : (
    // Renders the join view if no stream is active
    &lt;JoinView initializeStream={initializeStream} setMode={setMode} /&gt;
  );
}

export default App;</code></pre><p>LSContainer is a placeholder that returns nothing, so the app compiles at this step. The next step replaces it with the full component.</p><h3 id="set-up-the-live-stream-view-and-container">Set up the live stream view and container</h3><p>This step implements the Live Stream View and Container components to manage and display HOST participants:</p><ul><li>StreamView Component: Displays participants in <code>SEND_AND_RECV</code> mode using the Participant component. Includes LSControls for managing the session.</li><li>LSContainer Component: Manages joining the stream via join from useMeeting. Shows the StreamView after joining or a <code>Join Stream</code> button otherwise.</li></ul><pre><code class="language-jsx">// Component to manage live stream container and session joining
function LSContainer({ streamId, onLeave }) {
  const [joined, setJoined] = useState(false); // Track if the user has joined the stream

  const { join } = useMeeting({
    onMeetingJoined: () =&gt; setJoined(true), // Set `joined` to true when successfully joined
    onMeetingLeft: onLeave, // Handle the leave stream event
    onError: (error) =&gt; alert(error.message), // Display an alert on encountering an error
  });

  const handleJoin = async () =&gt; {
    try {
      await join();
    } catch (error) {
      console.error("Failed to join stream", error);
    }
  };

  return (
    &lt;div className="container"&gt;
      &lt;h3&gt;Stream Id: {streamId}&lt;/h3&gt;
      {/* Show the stream view if joined, otherwise display the "Join Stream" button */}
      {joined ? (
        &lt;StreamView /&gt;
      ) : (
        &lt;button onClick={handleJoin}&gt;Join Stream&lt;/button&gt;
      )}
    &lt;/div&gt;
  );
}

// Component to display the live stream view
function StreamView() {
  const { participants } = useMeeting(); // Access participants using the VideoSDK useMeeting hook

  return (
    &lt;div&gt;
      &lt;LSControls /&gt; {/* Render live stream controls */}
      {[...participants.values()]
        .filter((p) =&gt; p.mode === Constants.modes.SEND_AND_RECV) // Filter participants in SEND_AND_RECV mode
        .map((p) =&gt; (
          &lt;Participant participantId={p.id} key={p.id} /&gt; // Render each participant's view
        ))}
    &lt;/div&gt;
  );
}

function Participant() {
  return null;
}

function LSControls() {
  return null;
}</code></pre><p>Participant and LSControls are placeholders at this step. Replace each one with the full version from the next two steps rather than adding a second function with the same name.</p><p><code>StreamView</code> renders only <code>SEND_AND_RECV</code> participants, so bidders see the auctioneer, never each other.</p><h3 id="render-each-participants-view">Render each participant's view</h3><p>This step component displays an individual participant's audio and video streams. It uses the <code>useParticipant</code> hook to retrieve the participant's data (e.g., webcam and mic status) and dynamically sets up the streams with <code>useEffect</code>. Audio and video elements are rendered based on the availability of the streams.</p><pre><code class="language-jsx">// Component to render audio and video streams for a participant
function Participant({ participantId }) {
  const { webcamStream, micStream, webcamOn, micOn, isLocal, displayName } =
    useParticipant(participantId);

  const audioRef = useRef(null); // Reference for audio element
  const videoRef = useRef(null); // Reference for video element

  // Function to attach or clear the stream
  const setupStream = (stream, ref, condition) =&gt; {
    if (ref.current &amp;&amp; stream) {
      ref.current.srcObject = condition
        ? new MediaStream([stream.track])
        : null;
      condition &amp;&amp; ref.current.play().catch(console.error);
    }
  };

  useEffect(() =&gt; setupStream(micStream, audioRef, micOn), [micStream, micOn]); // Handle mic stream
  useEffect(
    () =&gt; setupStream(webcamStream, videoRef, webcamOn),
    [webcamStream, webcamOn]
  ); // Handle webcam stream

  return (
    &lt;div&gt;
      &lt;p&gt;
        {displayName} | Webcam: {webcamOn ? "ON" : "OFF"} | Mic:{" "}
        {micOn ? "ON" : "OFF"}
      &lt;/p&gt;
      &lt;audio ref={audioRef} autoPlay muted={isLocal} /&gt; {/* Play mic stream */}
      {webcamOn &amp;&amp; (
        &lt;video
          ref={videoRef}
          autoPlay
          muted={isLocal}
          height="200"
          width="300"
        /&gt; /* Display webcam stream */
      )}
    &lt;/div&gt;
  );
}</code></pre><h3 id="implement-live-stream-controls">Implement live stream controls</h3><p><code>LSControls</code> adds mic and camera toggles for hosts, plus leave and mode-switch buttons for everyone.</p><pre><code class="language-jsx">// Component for managing stream controls
function LSControls() {
  const { leave, toggleMic, toggleWebcam, changeMode, meeting } = useMeeting(); // Access methods
  const currentMode = meeting.localParticipant.mode; // Get the current participant's mode

  const handleLeave = async () =&gt; {
    try {
      await leave();
    } catch (error) {
      console.error("Failed to leave stream", error);
    }
  };

  const handleToggleMic = async () =&gt; {
    try {
      await toggleMic();
    } catch (error) {
      console.error("Failed to toggle mic", error);
    }
  };

  const handleToggleWebcam = async () =&gt; {
    try {
      await toggleWebcam();
    } catch (error) {
      console.error("Failed to toggle webcam", error);
    }
  };

  const handleChangeMode = async () =&gt; {
    const nextMode =
      currentMode === Constants.modes.SEND_AND_RECV
        ? Constants.modes.RECV_ONLY
        : Constants.modes.SEND_AND_RECV;
    try {
      await changeMode(nextMode);
    } catch (error) {
      console.error("Failed to change mode", error);
    }
  };

  return (
    &lt;div className="controls"&gt;
      {/* Button to leave the stream */}
      &lt;button onClick={handleLeave}&gt;Leave&lt;/button&gt;

      {/* Show mic and webcam toggles if in SEND_AND_RECV mode */}
      {currentMode === Constants.modes.SEND_AND_RECV &amp;&amp; (
        &lt;&gt;
          &lt;button onClick={handleToggleMic}&gt;Toggle Mic&lt;/button&gt;{" "}
          {/* Mute/unmute mic */}
          &lt;button onClick={handleToggleWebcam}&gt;Toggle Camera&lt;/button&gt;{" "}
          {/* Enable/disable Camera */}
        &lt;/&gt;
      )}

      {/* Button to switch between Host Mode and Viewer Mode */}
      &lt;button onClick={handleChangeMode}&gt;
        {currentMode === Constants.modes.SEND_AND_RECV
          ? "Switch to Audience Mode"
          : "Switch to Host Mode"}
      &lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><h3 id="add-the-styles">Add the styles</h3><p>The Vite template creates its own App.css, which the app runs with. To match the quickstart's layout, replace the contents of src/App.css with the quickstart's styles.</p><pre><code class="language-css">/* App.css */
body {
  margin: 0;
  font-family: Arial, sans-serif;
  background-color: #f9f9f9;
}

.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  height: 100vh;
  gap: 20px;
  padding: 20px;
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

button {
  background: #007bff;
  color: #fff;
  border: none;
  padding: 10px 16px;
  border-radius: 5px;
  cursor: pointer;
  transition: 0.3s;
}

button:hover {
  background: #0056b3;
}

input {
  width: 60%;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 5px;
}

.controls {
  display: flex;
  gap: 10px;
}

video,
audio {
  margin: 10px 0;
  border-radius: 8px;
}</code></pre><h3 id="run-the-app">Run the app</h3><p>Start the development server with the dev script from the Vite template, then open the local address it prints. Create the stream as host in one browser tab and join it as audience in a second tab with the same stream ID.</p><pre><code class="language-bash">npm run dev</code></pre><p>Fix three things before production. The token sits in client code (<code>API.js</code>, line 2). Joining from <code>JoinView</code> with an empty ID creates a new stream. Most important for an auction, each client picks its own mode: "Join as Host" and "Switch to Host Mode" both let any bidder go on camera without host approval. The quickstart says your server must decide who joins as a host, and VideoSDK's authentication docs state that no token permission restricts publishing media or PubSub, so enforce that rule in your own app and server.</p><p>The full example is in the <a href="https://github.com/videosdk-live/quickstart/tree/main/interactive-live-streaming/react-ils">react-ils folder on GitHub</a>, explained in <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-react-ils">VideoSDK's React interactive live streaming quickstart</a>. Not using React? Use the <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start-js-ils">JavaScript interactive live streaming quickstart</a>.</p><h2 id="how-to-handle-real-time-bids-without-a-wrong-winner">How to handle real-time bids without a wrong winner</h2><p>Real-time bids stay correct only when one component decides them. Each bid goes to your bid service over HTTPS. The service checks identity, that the lot is open and that the amount clears the increment, then writes the bid with an atomic compare-and-set on the current high bid, so two equal bids cannot both win. An idempotency key stops a retried request from counting twice. The lot timer runs here, never in a browser.</p><p>Only an accepted bid gets announced. VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/pubsub">PubSub guide</a> documents <code>usePubSub(topic)</code>, which returns <code>publish</code>. <code>publish()</code> takes a string message, an options object and an optional <code>payload</code> object for structured data such as lot ID and amount. With <code>persist: true</code>, a bidder who joins mid-lot receives earlier bids through <code>onOldMessagesReceived</code>.</p><p>The <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/sending-virtual-gifts">virtual gifts guide</a> documents the same order: the client calls your backend, the backend authenticates the user and processes the transaction (the guide recommends storing it), and only on success does the client publish. Engineering reasoning from that pattern, not a VideoSDK statement: a client-published message is only as trustworthy as its client, so treat it as a display hint and read the current high bid from your service before showing "you are winning".</p><h2 id="what-a-live-auction-costs-to-stream-at-scale">What a live auction costs to stream at scale</h2><p>Streaming cost for bidders in an ILS room is viewers × minutes × rate. <a href="https://www.videosdk.live/pricing">VideoSDK's pricing page</a> lists ILS viewer minutes at 720p at $0.002 per viewer minute on Pay-As-You-Go, as of 29 Sep 2026.</p><p>Worked example, with hypothetical inputs: 150 bidders watching a 90-minute sale at 720p use 150 × 90 = 13,500 ILS viewer minutes, or $27.00 at $0.002 per viewer minute, as of 1 Oct 2026. That excludes the auctioneer's own minutes.</p><p>A watch-only HLS audience instead costs HLS viewer minutes  plus 720p HLS encoding at $0.04 per livestream minute, or $2.40 an hour, as of 29 Sep 2026.</p><p>The <a href="https://docs.videosdk.live/help_docs/quotas-and-limit">VideoSDK quotas and limits page</a> caps concurrent viewers per organization and per room, and sells extra viewer packs of 200 viewers at $20 per pack per month, as of 1 Oct 2026.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Interactive live streaming (ILS):</strong> Live streaming in which the audience joins the same room as the hosts, so a viewer can be brought on stage: a host sends an invitation and the viewer's client switches its own mode.</blockquote><blockquote><strong>Room ID (stream ID):</strong> The room identifier, in the format xxx-yyy-zzz, that the quickstart names <code>streamId</code> and passes to <code>MeetingProvider</code> as <code>meetingId</code>.</blockquote><blockquote><strong>SEND_AND_RECV and RECV_ONLY:</strong> The two participant modes VideoSDK's ILS guides use: hosts publish and receive media, and audience members only receive it. The SDK also has a third mode, <code>SIGNALLING_ONLY</code>, which neither sends nor receives media.</blockquote><blockquote><strong>PubSub (publish-subscribe):</strong> Messaging in which clients publish to named topics and subscribers to a topic receive the messages. In VideoSDK, <code>sendOnly</code> can limit a message to listed participants, and <code>onMessageDrop</code> reports messages a client could not receive.</blockquote><blockquote><strong>HTTP Live Streaming (HLS):</strong> A segment-based delivery protocol defined in RFC 8216. See <a href="https://www.videosdk.live/blog/what-is-http-live-streaming">what HTTP Live Streaming is</a>.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>A live auction streaming app runs a WebRTC video room for the auctioneer and a bid service that alone accepts bids; broadcast messages only display its decisions.</li><li>Put bidders on WebRTC whenever a lot's bid window is shorter than the viewer delay; HLS suits a watch-only audience.</li><li>The quickstart's client-side token and its self-service host buttons ("Join as Host" and "Switch to Host Mode") must change before production.</li><li>Budget streaming as viewers × minutes × rate, and confirm your viewer ceiling before a large sale.</li></ul><p>Start from the quickstart, move token generation to your server, then build the bid service. For the ILS modes and guides used here, read <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/introduction">VideoSDK's React interactive live streaming docs</a>; a new account comes with a $20 credit.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-are-the-tools-for-hosting-live-auctions-online">What are the tools for hosting live auctions online?</h3><p>Hosting live auctions online takes four kinds of tools: a video layer that streams the auctioneer, a bid service that accepts bids and runs lot timers, payments and identity checks, and the bidder apps. Auction houses that prefer not to build can buy live auction software; teams that build can take the video layer from a video API and write the bid service themselves.</p><h3 id="how-do-you-stop-bid-sniping-at-the-end-of-a-lot">How do you stop bid sniping at the end of a lot?</h3><p>Use a soft close, also called extended bidding: the bid service pushes the lot's closing time back whenever a bid lands near the end. <a href="https://support.auctionninja.com/knowledge/what-is-extended-bidding">AuctionNinja's help center</a>, for example, extends a lot when a bid arrives in its last five minutes. Run the timer on the server and broadcast each new closing time.</p><h3 id="can-a-bidder-be-brought-on-camera-during-a-live-auction">Can a bidder be brought on camera during a live auction?</h3><p>Yes, with code on both sides. VideoSDK's <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/audience-management/change-mode">change mode guide</a> says <code>changeMode()</code> only changes the mode of the participant who calls it. The host publishes an invitation on a PubSub topic addressed to the bidder, whose client subscribes and calls <code>changeMode("SEND_AND_RECV")</code> itself. Validate invitations on your server so a bidder cannot forge one. A token cannot restrict mode, so a modified client can still call <code>changeMode()</code> on its own; every client receives a mode-changed event, and the auctioneer's app can <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/audience-management/remove-participant">remove</a> anyone who switches without an invitation.</p>]]></content:encoded></item><item><title><![CDATA[What is AAC? Advanced Audio Coding for Streaming Explained]]></title><description><![CDATA[How advanced audio coding compresses sound, which AAC profile and bitrate suit a live stream, what an .aac or .m4a file holds, and why HLS and RTMP carry AAC while WebRTC uses Opus.]]></description><link>https://www.videosdk.live/blog/advanced-audio-coding</link><guid isPermaLink="false">6abca287b3240feb748ca07c</guid><category><![CDATA[live-streaming]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 01 Oct 2026 12:29:40 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/11-1.png" medium="image"/><content:encoded><![CDATA[<blockquote>Advanced audio coding (AAC) is a lossy audio codec standardized by the Moving Picture Experts Group (MPEG) for MPEG-2 and MPEG-4. Its encoder uses a psychoacoustic model to discard sound a listener is unlikely to hear. In live streaming, AAC is the usual audio codec for broadcast delivery, while real-time calls use Opus.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/11-1.png" alt="What is AAC? Advanced Audio Coding for Streaming Explained"/><p>This guide is for developers who meet AAC in an encoder, an HTTP Live Streaming (HLS) playlist or a Real-Time Messaging Protocol (RTMP) ingest spec. It covers how the codec works, its profiles and codec strings, what an .aac file holds, which protocols carry AAC, and how to choose an encoder and bitrate.</p><h2 id="how-does-advanced-audio-coding-work">How does advanced audio coding work?</h2><p>Advanced audio coding is a perceptual codec: it splits the signal into frequency bands, estimates what the ear will notice, and quantizes the rest coarsely or drops it. According to the Open University's <a href="https://www.open.edu/openlearn/digital-computing/exploring-communications-technology/content-section-3.7">OpenLearn section on MPEG-4 AAC</a>, AAC uses either 2048 or 256 sub-bands, against 32 for MP3 (MPEG-1 Audio Layer III), which gives the psychoacoustic model finer frequency resolution.</p><p>OpenLearn names the deciding step perceptual masking: a louder sound hides quieter ones close to it in frequency, so the encoder codes the hidden parts with fewer bits, or none. Three coding tools extend this at low bitrates: perceptual noise substitution (PNS), spectral band replication (SBR) and parametric stereo (PS).</p><p>Because AAC is lossy, each decode and re-encode step loses more quality. AAC also adds delay. Fraunhofer IIS notes on its <a href="https://www.iis.fraunhofer.de/en/ff/amm/communication/aaceld.html">AAC-ELD family page</a> that conventional AAC's encoder and decoder chain exceeds 100 ms of algorithmic delay, which it calls not acceptable for two-way communication. That is one reason real-time calls use a different codec.</p><h2 id="what-is-the-aac-audio-format">What is the AAC audio format?</h2><p>The AAC audio format is a codec, not a file layout. The short answer to what is AAC format, or what is AAC music format, is that the name describes the compression; a container decides how the compressed frames are stored (see <a href="https://www.videosdk.live/blog/video-encoding">the difference between a codec and a container</a>). MDN's <a href="https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Audio_codecs">web audio codec guide</a> lists three containers for AAC, MP4, ADTS (Audio Data Transport Stream) and 3GP, with bitrates up to 512 kbps and sample rates of 8 to 96 kHz.</p><p>Inside a playlist or a media type, AAC is identified by a codec string. <a href="https://datatracker.ietf.org/doc/html/rfc6381">RFC 6381</a> defines the syntax: in <code>mp4a.40.2</code>, <code>40</code> means MPEG-4 audio and <code>2</code> is the audio object type for AAC-LC (Low Complexity). An HLS player reads this string from the <code>CODECS</code> attribute, and <a href="https://datatracker.ietf.org/doc/html/rfc8216">RFC 8216</a>, section 4.3.4.2, requires that attribute to list every sample format in the variant, for example <code>ac-3,mp4a.40.2</code>.</p><h2 id="aac-formats-compared-aac-lc-he-aac-and-xhe-aac">AAC formats compared: AAC-LC, HE-AAC and xHE-AAC</h2><p>AAC formats, more precisely profiles or object types, add coding tools to the core codec for lower bitrates or lower delay. The table compares five.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Profile</th>
<th>Codec string</th>
<th>What it adds</th>
<th>Where it fits</th>
<th>Source</th>
</tr>
</thead>
<tbody>
<tr>
<td>AAC-LC</td>
<td><code>mp4a.40.2</code></td>
<td>The core codec: up to 256 kbit/s per channel, 8 to 96 kHz</td>
<td>FFmpeg's default and most compatible profile</td>
<td><a href="https://www.iis.fraunhofer.de/en/ff/amm/broadcast-streaming/aaclc.html">Fraunhofer AAC-LC page</a>; RFC 6381</td>
</tr>
<tr>
<td>HE-AAC v1 (High Efficiency)</td>
<td><code>mp4a.40.5</code></td>
<td>SBR, a bandwidth extension for high frequencies</td>
<td>Low-bitrate stereo</td>
<td><a href="https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/codecs_parameter">MDN codecs parameter guide</a>; <a href="https://www.via-la.com/licensing-programs/aac/">Via LA</a></td>
</tr>
<tr>
<td>HE-AAC v2</td>
<td><code>mp4a.40.29</code></td>
<td>PS on top of SBR</td>
<td>Very low-bitrate stereo</td>
<td>MDN; Via LA</td>
</tr>
<tr>
<td>xHE-AAC (Extended HE-AAC)</td>
<td>Not in MDN's object-type table</td>
<td>Speech coding plus mandatory MPEG-D loudness and dynamic range control</td>
<td>Mixed speech and music at low rates; fragmented MP4 (fMP4) only, in Apple HLS</td>
<td>Via LA; Apple rule 2.25</td>
</tr>
<tr>
<td>AAC-LD and AAC-ELD (Low Delay, Enhanced Low Delay)</td>
<td><code>mp4a.40.23</code>, <code>mp4a.40.39</code></td>
<td>Low delay; ELD reaches 7.5 ms at 48 kHz in delay-reduced mode</td>
<td>Two-way calls, such as FaceTime</td>
<td>Fraunhofer AAC-ELD page; MDN</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The key reading is the bitrate boundary. Apple's <a href="https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices">HLS authoring specification for Apple devices</a> says you should not use HE-AAC above 64 kbit/s (rule 2.4), and rule 2.3 requires stereo audio in AAC, HE-AAC v1 or HE-AAC v2. Above 64 kbit/s, AAC-LC is the profile to use.</p><h2 id="what-is-an-aac-file">What is an AAC file?</h2><p>An AAC file is a .aac file holding an ADTS stream. MDN's <a href="https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Containers">media container guide</a> describes ADTS as an almost bare stream of AAC data, made of frames with a minimal header, served as <code>audio/aac</code> and intended for streamed audio such as internet radio.</p><p>The same MDN guide lists .m4a and .mp4 under the MP4 container, <code>audio/mp4</code>. So the answer to what is an AAC audio file depends on the extension: raw ADTS in a .aac file, AAC inside MP4 in an .m4a file.</p><p>The distinction matters in HLS. RFC 8216, section 3.4, defines packed audio segments of AAC with ADTS framing, each starting with an ID3 tag that holds its timestamp. HLS can also carry AAC inside MPEG transport stream (TS) or fMP4 segments (sections 3.2 and 3.3).</p><h2 id="where-aac-audio-fits-in-hls-rtmp-and-webrtc">Where AAC audio fits in HLS, RTMP and WebRTC</h2><p>AAC audio is the codec both broadcast protocols name, and one that Web Real-Time Communication (WebRTC) does not require. The table lists the audio codecs each specification or ingest guide names.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Protocol</th>
<th>Audio codecs named</th>
<th>Carries AAC?</th>
<th>Source</th>
</tr>
</thead>
<tbody>
<tr>
<td>HLS</td>
<td>AAC, MP3, AC-3, E-AC-3 as packed audio; Apple requires stereo AAC or HE-AAC</td>
<td>Yes, required by Apple</td>
<td>RFC 8216 section 3.4; Apple rule 2.3</td>
</tr>
<tr>
<td>RTMP, YouTube ingest</td>
<td>AAC or MP3; 5.1 surround only as AAC</td>
<td>Yes</td>
<td><a href="https://support.google.com/youtube/answer/2853702">YouTube live encoder settings</a>, as of 29 Sep 2026</td>
</tr>
<tr>
<td>Enhanced RTMP v2</td>
<td>Adds AC-3, E-AC-3, Opus and FLAC to legacy RTMP</td>
<td>Yes</td>
<td><a href="https://github.com/veovera/enhanced-rtmp">Enhanced RTMP repository</a></td>
</tr>
<tr>
<td>WebRTC</td>
<td>Endpoints must implement Opus and G.711</td>
<td>Not required</td>
<td><a href="https://datatracker.ietf.org/doc/html/rfc7874">RFC 7874</a> section 3</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The reading: an app with a live call and a broadcast audience runs two audio paths, and the bridge between them is where Opus becomes AAC. For the protocols themselves, see <a href="https://www.videosdk.live/blog/what-is-http-live-streaming">how HLS segments and playlists work</a> and <a href="https://www.videosdk.live/blog/what-is-rtmp">how RTMP carries audio and video to an ingest server</a>. The video track is a separate choice; see <a href="https://www.videosdk.live/developer-hub/social/av1-vs-h264">how AV1 and H.264 compare for the video track</a>.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/advanced-audio-coding-live-audio-paths.png" class="kg-image" alt="What is AAC? Advanced Audio Coding for Streaming Explained" loading="lazy" width="3200" height="1800"/></figure><p><em>A room carries Opus end to end; the HLS rendition needs stereo AAC for Apple devices, so the bridge from room to HLS re-encodes the audio once.</em></p><h2 id="how-to-choose-an-aac-encoder-and-bitrate-for-a-live-stream">How to choose an AAC encoder and bitrate for a live stream</h2><p>An AAC encoder choice depends on the profiles you need and what your build can include. FFmpeg's <a href="https://ffmpeg.org/ffmpeg-codecs.html">codec documentation</a> (development version, page dated 28 September 2026) describes two options:</p><ul><li><strong>The native <code>aac</code> encoder</strong> is FFmpeg's default AAC codec. Setting a bitrate with <code>-b:a</code> switches it to constant bit rate (CBR), and without one it uses 128 kbps. Its profiles, <code>aac_low</code> (the default and most compatible), <code>mpeg2_aac_low</code> and <code>aac_ltp</code>, include no HE-AAC.</li><li><code><strong>libfdk_aac</strong></code> wraps the Fraunhofer FDK library and adds <code>aac_he</code>, <code>aac_he_v2</code>, <code>aac_ld</code> and <code>aac_eld</code>. The build must be configured with <code>--enable-libfdk-aac</code>, and because the library is incompatible with the GNU General Public License (GPL), a GPL build also needs <code>--enable-nonfree</code>.</li></ul><p>For bitrate, Apple's HLS specification gives 32 to 160 kbit/s for stereo AAC. YouTube recommends 128 kbps stereo at 44.1 kHz. MDN gives 96 kbps at 48 kHz as the recommended minimum for stereo AAC. For rate-control modes, see <a href="https://www.videosdk.live/blog/cbr-vs-vbr">constant vs variable bitrate modes</a>.</p><p>A decision rule that follows from these sources:</p><ol><li>Opus on the real-time leg, because RFC 7874 requires it in every WebRTC endpoint.</li><li>AAC-LC stereo at 96 to 160 kbit/s for HLS and RTMP delivery: MDN's minimum up to Apple's upper bound.</li><li>HE-AAC only for renditions at 64 kbit/s or below, such as an audio-only fallback (Apple rule 2.4).</li><li>AAC-ELD only for two-way calling, the use Fraunhofer describes.</li></ol><h2 id="handling-aac-and-opus-when-you-build-on-a-live-streaming-sdk">Handling AAC and Opus when you build on a live streaming SDK</h2><p>A platform serving an interactive room and an HLS audience runs both paths in the diagram. Hosts talk over WebRTC, where Opus is mandatory, and the platform must produce AAC for the HLS rendition, because Apple's rule 2.3 requires stereo AAC. The HLS playlist's codec string shows what the platform chose.</p><p>VideoSDK splits the same job into interactive live streaming (ILS) and HLS. In an ILS room, hosts join with <code>SEND_AND_RECV</code> and the audience with <code>RECV_ONLY</code>. To reach an HLS audience, a participant calls <code>startHls</code> from <code>useMeeting</code>, whose <code>mode</code> option is <code>"video-and-audio"</code> or <code>"audio"</code>, per the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/integrate-hls/start-hls">Start HLS guide</a>. The docs do not state the audio codec, profile or bitrate of that HLS output </p><p>WHIP (WebRTC-HTTP Ingestion Protocol) lets an encoder such as OBS push a stream into a room, where it appears as a participant, per the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/whip-whep-ils">WHIP ingest guide</a>. Because WHIP carries a WebRTC session, the encoder offers WebRTC audio codecs, not the AAC it would send over RTMP. RTMP out pushes the room to platforms such as YouTube, which accepts AAC or MP3.</p><h2 id="glossary">Glossary</h2><blockquote><strong>ADTS (Audio Data Transport Stream):</strong> The frame-by-frame AAC stream format used by .aac files and HLS packed audio. RFC 8216 cites ISO/IEC 13818-7, the MPEG-2 AAC standard, for its definition.</blockquote><blockquote><strong>SBR (spectral band replication):</strong> A bandwidth extension tool that codes the high frequencies of a signal with little data. It is the tool HE-AAC v1 adds to AAC-LC.</blockquote><blockquote><strong>Parametric stereo (PS):</strong> A tool that analyzes the spatial relationship between the left and right channels and exploits what they share. HE-AAC v2 adds it to SBR.</blockquote><blockquote><strong>Perceptual noise substitution (PNS):</strong> A tool that replaces noise-like high-frequency bands with generated noise at the decoder. FFmpeg's native encoder enables it by default.</blockquote><blockquote><strong>Opus:</strong> An open audio codec standardized by the Internet Engineering Task Force (IETF) as RFC 6716 and required in every WebRTC endpoint. See <a href="https://www.videosdk.live/blog/video-codecs">why Opus is the default codec for real-time audio</a>.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>Advanced audio coding is MPEG's lossy perceptual audio codec, and AAC-LC (<code>mp4a.40.2</code>) is its most compatible profile.</li><li>AAC is a codec, not a container: a .aac file holds raw ADTS frames, while .m4a and .mp4 files hold AAC inside MP4.</li><li>HLS and RTMP ingest name AAC for audio, while WebRTC requires Opus, so a room re-broadcast over HLS is re-encoded once at the bridge.</li><li>Use AAC-LC stereo at 96 to 160 kbit/s for delivery, and HE-AAC only at 64 kbit/s or below, per Apple's HLS rules.</li></ul><p>Next, check the <code>CODECS</code> strings your pipeline produces and your encoder's audio settings against these rules. To build a live stream with an interactive room and an HLS audience, start with the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/introduction">VideoSDK interactive live streaming docs</a>; a new account comes with a $20 credit.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-advanced-audio-coding">What is advanced audio coding?</h3><p>Advanced audio coding is a family of lossy audio compression formats defined in ISO/IEC 13818-7 (MPEG-2) and ISO/IEC 14496-3 (MPEG-4). It codes what the ear is likely to notice and discards much of the rest. Its profiles range from AAC-LC for general delivery to HE-AAC for low bitrates and AAC-ELD for calls.</p><h3 id="is-aac-better-than-mp3">Is AAC better than MP3?</h3><p>Generally yes, at the same bitrate. OpenLearn reports a broad consensus that AAC gives better subjective quality than MP3 at the same bit rate, and MDN notes that AAC was designed to give more compression with higher fidelity than MP3. At low bitrates, OpenLearn says HE-AAC delivers near-CD quality at 64 kbit/s.</p><h3 id="do-you-need-a-license-to-stream-aac-audio">Do you need a license to stream AAC audio?</h3><p>No patent license fee is due for streaming AAC content. The Via LA AAC program's FAQ states that fees apply to the sale of encoders and decoders only, not to distributing AAC bitstreams by broadcast, network streaming or physical media. MDN agrees, adding that codec developers license through Via.</p>]]></content:encoded></item><item><title><![CDATA[What is Buffering? Why Live Streams Stall & How to Stop It]]></title><description><![CDATA[Buffering keeps a video playing through network dips until the buffer runs dry. This guide explains what the player is doing, why live streams rebuffer, and which encoder, CDN and player settings reduce stalls.]]></description><link>https://www.videosdk.live/blog/what-is-buffering</link><guid isPermaLink="false">6abca2b7b3240feb748ca082</guid><category><![CDATA[live-streaming]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 01 Oct 2026 12:29:25 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/13-1.png" medium="image"/><content:encoded><![CDATA[<blockquote>Buffering is a video player downloading media ahead of the playhead and holding it in memory, so playback survives short network slowdowns. When media arrives slower than it plays, the buffer empties and playback pauses to refill: that pause is rebuffering. Live streams stall more easily because a player can only buffer up to the newest published segment.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/13-1.png" alt="What is Buffering? Why Live Streams Stall & How to Stop It"/><p>This guide is for developers and streaming engineers whose viewers see the spinner. When viewers ask what does buffering mean, they usually mean that pause. The everyday buffering meaning and the technical one are the same thing seen from two sides: the viewer sees a wait, the player sees an empty buffer. This page covers the playback buffer in HTTP streaming players, not the jitter buffer inside video calls. It adds what viewer-focused explainers skip: the spec rules behind stalls, player settings, and how to measure rebuffering.</p><h2 id="what-does-buffering-do-inside-a-video-player">What does buffering do inside a video player?</h2><p>Buffering does one job: it keeps media ready before the playhead needs it. A streaming player downloads segments, appends them to the media element, and plays from the front of that store. Players buffer video ahead of the playhead because network throughput varies from second to second, while playback consumes exactly one second of media per second.</p><p>The browser exposes this store directly. The <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/buffered"><code>buffered</code> property on HTMLMediaElement, documented by MDN</a>, returns the time ranges the browser holds. The forward buffer is the distance from the current playback position to the end of the range that contains it.</p><p>Three phases decide what the viewer sees. At startup, the player waits until enough media arrives to cross a start threshold. In steady state, each downloaded segment adds its duration and playback drains the store continuously. When downloads fall behind for long enough, the buffer reaches zero, playback pauses, and the player waits until it crosses the threshold again.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/what-is-buffering-buffer-level-over-time.png" class="kg-image" alt="What is Buffering? Why Live Streams Stall & How to Stop It" loading="lazy" width="3200" height="1800"/></figure><p><em>Illustrative, not measured: each 6-second segment adds one target duration, the playhead drains one second per second, and the stall lasts until the buffer refills past the resume threshold.</em></p><h2 id="why-live-streams-buffer-more-than-recorded-video">Why live streams buffer more than recorded video</h2><p>Live streams buffer more than recorded video because the player cannot download what has not been encoded yet. A video on demand (VOD) player can fill minutes ahead. A live player's buffer is capped by the live edge, the newest segment listed in the playlist.</p><p>HTTP Live Streaming (HLS) sets that cap in its spec. <a href="https://datatracker.ietf.org/doc/html/rfc8216">RFC 8216, the HLS specification</a>, says in section 6.3.3 that a client should not start playback less than three target durations from the end of a live playlist, because doing so can trigger playback stalls. <a href="https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices">Apple's HLS Authoring Specification</a> recommends 6-second target durations (requirement 7.5), so three target durations is about 18 seconds of cushion.</p><p>Every second of that cushion is also a second of delay behind the live edge. Low-Latency HLS (LL-HLS) shrinks it with partial segments: Apple recommends a one-second part target (14.2c) and a hold-back of at least three parts (14.3). A smaller cushion means less delay and less room to absorb a slow download.</p><p>Real-time streams avoid segments altogether. WebRTC (Web Real-Time Communication) receivers hold incoming frames in a jitter buffer, and MDN documents the <a href="https://developer.mozilla.org/en-US/docs/Web/API/RTCInboundRtpStreamStats/jitterBufferDelay"><code>jitterBufferDelay</code> statistic</a> that measures time spent there. See <a href="https://www.videosdk.live/blog/hls-vs-webrtc">how HLS and WebRTC trade delay for scale</a>.</p><h2 id="what-causes-rebuffering-on-a-live-stream">What causes rebuffering on a live stream</h2><p>Rebuffering on a live stream happens when the next segment is not in the buffer when the playhead reaches it. The table maps each common cause to where it starts, what viewers see, and the rule it breaks. An IDR (instantaneous decoder refresh) frame is the keyframe a decoder can start from.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Cause</th>
<th>Where it starts</th>
<th>What viewers see</th>
<th>Rule or source</th>
</tr>
</thead>
<tbody>
<tr>
<td>Throughput below the lowest rendition's bitrate</td>
<td>Viewer network</td>
<td>Stalls even at the lowest quality</td>
<td>Apple 9.9: provide multiple bit rates</td>
</tr>
<tr>
<td>Encoder peaks above the declared <code>BANDWIDTH</code></td>
<td>Encoder</td>
<td>Stalls on high-motion scenes</td>
<td>Apple 1.29: live peak under 125% of <code>BANDWIDTH</code></td>
</tr>
<tr>
<td>Segments longer than the target duration</td>
<td>Encoder or packager</td>
<td>Stalls near segment boundaries</td>
<td>RFC 8216, 4.3.3.1</td>
</tr>
<tr>
<td>Segments that do not start on an IDR frame</td>
<td>Encoder</td>
<td>Rendition switches that cannot start cleanly</td>
<td>Apple 7.4</td>
</tr>
<tr>
<td>Playlist updates published late</td>
<td>Origin or content delivery network (CDN)</td>
<td>Waiting at the live edge</td>
<td>Apple 8.24: stale after three target durations</td>
</tr>
<tr>
<td>Player starts too close to the live edge</td>
<td>Player settings</td>
<td>A stall soon after joining</td>
<td>RFC 8216, 6.3.3</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Five of the six causes start on the publisher side, so the fix usually sits in the pipeline, not on the viewer's device. RFC 8216 section 4.3.3.1 states that segments longer than the target duration "can trigger playback stalls or other errors."</p><p>Viewers can still check their own side: a congested Wi-Fi network or other large downloads on the same connection both cut the throughput the player gets.</p><h2 id="how-to-stop-buffering-on-a-live-stream">How to stop buffering on a live stream</h2><p>To stop buffering on a live stream, give the player a lower rung to fall to, keep the encoder inside its declared bitrate, and give the buffer enough cushion. In order:</p><ol><li><strong>Offer an adaptive bitrate (ABR) ladder with a low rung.</strong> Apple requirement 9.9 makes multiple variants mandatory. The player can then drop quality instead of stalling; this is <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming">how adaptive bitrate streaming picks a rendition</a>.</li><li><strong>Cap peak bitrate.</strong> For live content, Apple 1.29 requires the measured peak to stay under 125% of the declared <code>BANDWIDTH</code>. Capped rate control keeps it there; see <a href="https://www.videosdk.live/blog/cbr-vs-vbr">constant vs variable bitrate for live streaming</a>.</li><li><strong>Fix the keyframe interval to the segment length.</strong> Apple 7.4 requires every segment to start with an IDR frame; see <a href="https://www.videosdk.live/blog/what-is-a-keyframe">what a keyframe is and why segments start on one</a>.</li><li><strong>Serve playlists and segments from a CDN.</strong> A CDN serves cached copies from servers placed close to viewers; see <a href="https://www.videosdk.live/developer-hub/rtmp/cdn-live-streaming">using a CDN for live streaming</a>.</li><li><strong>Give the player hold-back.</strong> In <a href="https://github.com/video-dev/hls.js/blob/v1.7.3/docs/API.md">the hls.js API documentation (v1.7.3)</a>, <code>liveSyncDurationCount</code> defaults to 3 target durations, and the docs warn that decreasing it "is likely to cause playback stalls."</li><li><strong>Measure before and after.</strong> Change one setting at a time and compare stall counts.</li></ol><p>Raise hold-back first when stalls cluster right after viewers join, and fix the ladder first when they cluster on weak networks.</p><h2 id="how-to-measure-rebuffering">How to measure rebuffering?</h2><p>Rebuffering is measured from player events. In the browser, the <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/waiting_event"><code>waiting</code> event, documented by MDN</a>, fires when playback stops because of a temporary lack of data, and the <code>playing</code> event fires when it resumes. The <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/stalled_event"><code>stalled</code> event</a> is different: it fires when the browser is fetching data that unexpectedly does not arrive. hls.js adds a <code>BUFFER_STALLED_ERROR</code> when playback is stuck because the buffer ran out.</p><p>Two numbers cover most of the picture. Rebuffer ratio is total stall time divided by watch time: 36 seconds of stalls in a 60-minute session is 36 / 3,600, or 1%. Startup time is the gap between pressing play and the first frame.</p><p>Both matter to viewers. In a <a href="https://people.cs.umass.edu/~ramesh/Site/HOME_files/imc208-krishnan.pdf">2012 study of 23 million views on Akamai's network by Krishnan and Sitaraman</a>, a viewer whose rebuffer delay equalled 1% of the video's duration played 5% less of it than a similar viewer with no rebuffering. Viewers began abandoning after 2 seconds of startup delay, and each extra second raised abandonment by 5.8%. The data is from 2012; treat it as direction, not a current benchmark. For the wider metric set, see <a href="https://www.videosdk.live/blog/qoe-quality-of-experience">quality of experience (QoE) metrics</a>.</p><h2 id="what-is-the-video-buffer-window">What is the video buffer window?</h2><p>The video buffer window means one of two things, depending on who uses the phrase. In a player, it is how far ahead the player may buffer: in hls.js, <code>maxBufferLength</code> (default 30 seconds) is the length it tries to reach, and <code>maxMaxBufferLength</code> (default 600 seconds) is a limit it never exceeds.</p><p>In a live playlist, it is the sliding window of segments the server lists. Apple requirement 8.11 calls for at least six segments in a live playlist, so with 6-second targets the window spans at least 36 seconds. That window limits how far back a viewer can seek, not how far ahead the player can buffer.</p><h2 id="buffer-settings-in-a-videosdk-hls-player">Buffer settings in a VideoSDK HLS player</h2><p>HLS buffer settings belong to the viewer app: in a browser without native HLS playback, the app plays the stream through a JavaScript library such as hls.js and passes it a buffer configuration. VideoSDK's React guide, <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/integrate-hls/setup-hls-player">Setup HLS Player</a>, plays <code>hlsUrls.playbackHlsUrl</code> with hls.js once <code>hlsState</code> is <code>HLS_PLAYABLE</code>.</p><p>The guide's example config sets <code>maxBufferLength: 0</code>, <code>maxMaxBufferLength: 1</code>, <code>liveSyncDurationCount: 1</code>, <code>maxStarvationDelay: 1</code> and <code>startLevel: 0</code>. Against the hls.js defaults (30, 600, 3 and 4), that keeps the player close to the live edge with almost no forward buffer: it favours a short delay over stall resistance. <code>startLevel: 0</code> starts on the lowest rendition, which shortens startup.</p><p>If your viewers rebuffer, raise <code>liveSyncDurationCount</code> toward 3 first, then <code>maxBufferLength</code>. </p><h2 id="glossary">Glossary</h2><blockquote><strong>Playhead (playback position):</strong> the point in the media timeline that is on screen now. The forward buffer is measured from it.</blockquote><blockquote><strong>Forward buffer (buffer length):</strong> seconds of downloaded media ahead of the playhead. It is what the player spends during a slow download.</blockquote><blockquote><strong>Rebuffering (stall):</strong> a pause in playback because the forward buffer reached zero. Browsers signal it with the <code>waiting</code> event.</blockquote><blockquote><strong>Target duration (EXT-X-TARGETDURATION):</strong> the maximum segment duration an HLS media playlist declares, in whole seconds.</blockquote><blockquote><strong>Live edge (hold-back):</strong> the newest media a live playlist lists. Hold-back is how far behind it the player starts.</blockquote><blockquote><a href="https://www.videosdk.live/blog/what-is-jitter-buffer"><strong>Jitter buffer</strong></a><strong>:</strong> a short queue in real-time receivers that evens out packet arrival times. It is a different mechanism from the playback buffer.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>Buffering is a player storing media ahead of the playhead; rebuffering is the pause when that store runs dry.</li><li>Live streams are more exposed than recorded video because the buffer can never extend past the live edge.</li><li>Five of the six common causes start with the publisher: bitrate peaks, long segments, missing IDR frames, late playlists or too little hold-back.</li><li>Decision rule: if stalls cluster right after joining, raise hold-back; if they cluster on weak networks, add a lower rung.</li></ul><p>Start by logging <code>waiting</code> events and computing the rebuffer ratio for a week, so every change has a baseline. To build an HLS stream with its own player, start with the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/integrate-hls/overview">VideoSDK HLS guide</a>; a new account includes a <a href="https://www.videosdk.live/pricing" rel="noreferrer">$20 credit</a>.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-buffering">What is buffering?</h3><p>Buffering is when a video player loads media before it is needed and keeps it in memory, so short drops in network speed do not interrupt playback. In computing, a <a href="https://en.wikipedia.org/wiki/Data_buffer">data buffer</a> is memory that holds data temporarily while it moves from one place to another, and a player's buffer is one example. If downloads fall behind for long enough, the stored media runs out and playback pauses until more arrives.</p><h3 id="what-is-the-purpose-of-buffering">What is the purpose of buffering?</h3><p>The purpose of buffering is to absorb the gap between how fast media arrives and how fast it plays. Throughput changes from moment to moment and downloads land in segment-sized bursts, so without stored media the player would pause at every dip. The buffer also guides quality choices: hls.js's adaptive logic picks renditions it predicts will not drain the buffer before the next segment arrives.</p><h3 id="is-buffering-the-same-as-latency">Is buffering the same as latency?</h3><p>No. Latency is the delay between an event being captured and being shown; buffering is media held ahead of the playhead. The two meet on live streams, where a deeper buffer can only come from sitting further behind the live edge. Stalls add latency as well: by default, hls.js adds one second to its target delay after each stall (<code>liveSyncOnStallIncrease</code>), so a stream that stalls often drifts further behind.</p>]]></content:encoded></item><item><title><![CDATA[HLS vs MPEG-DASH: Which Live Streaming Protocol to Use?]]></title><description><![CDATA[How HLS and MPEG-DASH differ on native playback, codecs, content protection and latency, where each one breaks, how one set of fMP4 segments can serve both, and which to use for a live streaming product.]]></description><link>https://www.videosdk.live/blog/hls-vs-mpeg-dash</link><guid isPermaLink="false">6ab656beb3240feb748ca04c</guid><category><![CDATA[live-streaming]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 25 Sep 2026 13:17:36 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/23.png" medium="image"/><content:encoded><![CDATA[<blockquote>HLS vs MPEG-DASH is a choice between reach and control. Use HLS (HTTP Live Streaming) when your viewers include iPhones and Safari, because Apple devices play it natively. Use MPEG-DASH (Dynamic Adaptive Streaming over HTTP) when you control every player, as in Android and smart TV apps. To serve both, package one set of segments with two manifests.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/23.png" alt="HLS vs MPEG-DASH: Which Live Streaming Protocol to Use?"/><p>This guide is for developers choosing a delivery format for a live or on-demand streaming product. It compares the two protocols on the points that decide a build: native playback, codecs, content protection and latency. It also covers details that change the answer today: native HLS in desktop Chrome, how iPhones handle DASH, the playlist rule that sets standard HLS latency, and what it takes for one set of segments to serve both manifests. For how HLS itself works, see <a href="https://www.videosdk.live/blog/what-is-http-live-streaming">what HTTP Live Streaming is and how it works</a>.</p><p>HLS and MPEG-DASH are both HTTP-based adaptive streaming protocols. The server cuts video into short segments at several bitrates, a manifest lists them, and the player downloads segments over ordinary HTTP and switches bitrate as the network changes. That shared model is how&nbsp;<a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">adaptive bitrate streaming picks a rendition</a>. The protocols differ in who defines them, what the manifest looks like and which devices play them without extra code.</p><h2 id="what-is-hls">What is HLS?</h2><p>HLS is Apple's HTTP-based adaptive streaming protocol. Apple released it in May 2009, according to&nbsp;<a href="https://en.wikipedia.org/wiki/HTTP_Live_Streaming" rel="noreferrer">Wikipedia's HLS entry</a>, and it is documented in&nbsp;<a href="https://www.rfc-editor.org/rfc/rfc8216" rel="noreferrer">RFC 8216</a>, published by the Internet Engineering Task Force (IETF) in 2017. Its manifests are M3U8 text playlists: a multivariant playlist that lists the renditions, and a media playlist for each rendition that lists its segments. Segments are MPEG-2 transport stream (TS) files or fragmented MP4 (fMP4) files. Apple's&nbsp;<a href="https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices" rel="noreferrer">HLS Authoring Specification</a>&nbsp;adds the stricter rules that Apple devices expect.</p><h2 id="what-is-mpeg-dash">What is MPEG-DASH?</h2><p>MPEG-DASH is an international standard for HTTP-based adaptive streaming. It was developed by the Moving Picture Experts Group (MPEG) and published as ISO/IEC 23009-1 in April 2012, according to&nbsp;<a href="https://en.wikipedia.org/wiki/Dynamic_Adaptive_Streaming_over_HTTP" rel="noreferrer">Wikipedia's DASH entry</a>. The&nbsp;<a href="https://www.mpeg.org/standards/MPEG-DASH/" rel="noreferrer">MPEG-DASH standard page</a>&nbsp;describes it as a suite of standards for streaming over existing HTTP infrastructure such as servers and content delivery networks (CDNs). Its manifest is the Media Presentation Description (MPD), an XML document, and the same Wikipedia entry notes that DASH is codec-agnostic.</p><h2 id="hls-vs-dash-compared">HLS vs DASH compared</h2><p>The table compares HLS vs DASH on the criteria that usually decide a streaming build, as of 25 September 2026.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Criterion</th>
<th>HLS</th>
<th>MPEG-DASH</th>
</tr>
</thead>
<tbody>
<tr>
<td>Defined by</td>
<td>Apple; RFC 8216, plus Apple's HLS Authoring Specification</td>
<td>MPEG; ISO/IEC 23009-1</td>
</tr>
<tr>
<td>Manifest</td>
<td>M3U8 text playlists</td>
<td>MPD, an XML document</td>
</tr>
<tr>
<td>Segment format</td>
<td>MPEG-2 TS or fMP4</td>
<td>fMP4 or WebM, among others</td>
</tr>
<tr>
<td>Video codecs</td>
<td>On Apple devices: H.264, HEVC, Dolby Vision or AV1</td>
<td>Codec-agnostic; the device's decoders set the limit</td>
</tr>
<tr>
<td>Native browser playback</td>
<td>Safari, iPhone Safari, Chrome 142 and later, Chrome for Android</td>
<td>None; needs a JavaScript player</td>
</tr>
<tr>
<td>Content protection</td>
<td>FairPlay Streaming on Apple devices; Common Encryption in fMP4</td>
<td>Encrypted segments, played through the browser's Encrypted Media Extensions (EME)</td>
</tr>
<tr>
<td>Low-latency mode</td>
<td>Low-Latency HLS (LL-HLS) with partial segments</td>
<td>Low-latency DASH with Common Media Application Format (CMAF) chunks</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Sources for each row are linked in the sections below. Most DASH vs HLS decisions turn on the native playback row, because it decides whether an Apple viewer needs any extra code.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/hls-vs-mpeg-dash-one-segment-set.png" class="kg-image" alt="HLS vs MPEG-DASH: Which Live Streaming Protocol to Use?" loading="lazy" width="3200" height="1800"/></figure><p><em>One encode, two manifests: the same fMP4 segments can be listed in an M3U8 playlist for HLS players and in an MPD for DASH players.</em></p><h2 id="which-browsers-and-devices-play-hls-and-dash-natively">Which browsers and devices play HLS and DASH natively?</h2><p>Native HLS playback now reaches beyond Apple. According to <a href="https://caniuse.com/http-live-streaming">caniuse's HLS table</a>, read 25 September 2026, Safari on macOS and iOS, desktop Chrome from version 142 and Chrome for Android play an M3U8 URL set directly on a video element. Firefox and Edge do not. Everywhere else, HLS plays through a JavaScript library built on Media Source Extensions (MSE), the browser API that lets a script feed media segments to a video element.</p><p>Native support is not the same as reliable support. The <a href="https://github.com/video-dev/hls.js">hls.js documentation</a> notes that Chrome 147 reports HLS support but may fail to play certain streams natively, so it recommends trying hls.js first and falling back to native playback.</p><p>No browser plays an MPD from a plain video tag. MPEG-DASH on the web always runs through an MSE player such as <a href="https://github.com/Dash-Industry-Forum/dash.js">dash.js</a>, maintained by the DASH Industry Forum (DASH-IF). For Android apps, Wikipedia's DASH entry notes that DASH is available through ExoPlayer.</p><p>iPhones are the hard case for DASH. <a href="https://caniuse.com/mediasource">caniuse's MSE table</a> lists full MSE support only on iPadOS 13 and later, not on iPhone. Safari offers ManagedMediaSource instead, which <a href="https://developer.mozilla.org/en-US/docs/Web/API/ManagedMediaSource">MDN</a> marks as limited availability and experimental. hls.js documents support for Safari on iOS 17.1 and later through it. A DASH player on an iPhone depends on that same API, while HLS needs no library there at all.</p><h2 id="dash-vs-hls-where-each-one-breaks">DASH vs HLS: Where each one breaks?</h2><p>DASH vs HLS failures show up in different places: HLS breaks on latency at default settings, and DASH breaks on Apple devices.</p><p><strong>HLS: latency at standard settings.</strong> Apple's authoring specification says target durations SHOULD be 6 seconds (requirement 7.5). RFC 8216, section 6.3.3, says a live client SHOULD NOT start playback less than three target durations from the end of the playlist. With 6-second segments, a standard HLS player therefore starts at least 18 seconds behind the newest segment, before encoding and delivery delay. LL-HLS shortens this with partial segments. The current HLS draft, <a href="https://www.ietf.org/archive/id/draft-pantos-hls-rfc8216bis-22.txt">draft-pantos-hls-rfc8216bis-22</a>, says the low-latency hold-back SHOULD be at least three part durations, so 1-second parts give a hold-back of at least 3 seconds. For the setup differences, see <a href="https://www.videosdk.live/developer-hub/hls/hls-vs-ll-hls">HLS vs LL-HLS</a>.</p><p><strong>HLS: container rules on Apple devices.</strong> Apple's specification allows TS or fMP4 for H.264 but requires fMP4 for HEVC and AV1 (requirements 1.2, 1.5 and 1.39). A TS-only pipeline cannot use the newer codecs on Apple devices.</p><p><strong>DASH: Apple devices and player code.</strong> Every DASH viewer on the web needs a JavaScript player, and on iPhones that player depends on ManagedMediaSource. A product that ships DASH therefore still needs HLS for Apple devices.</p><p><strong>DASH: latency is the same arithmetic.</strong> DASH has no lower latency by design. The <a href="https://dashif.org/dash.js/pages/usage/low-latency.html">dash.js low-latency guide</a> works through 8-second segments: a player that joins 3 seconds into a new segment and starts from the last complete one ends up 11 seconds behind live. With 1-second CMAF chunks, it can start inside the segment still being written and sit about 3 seconds behind. dash.js has supported CMAF low-latency streaming since version 2.6.8.</p><p><strong>DASH: codec freedom stops at the decoder.</strong> A codec-agnostic manifest does not make a device decode VP9 or AV1. The player can only choose among renditions the device supports.</p><h2 id="mpeg-dash-vs-hls-which-should-you-use">MPEG-DASH vs HLS: Which should you use?</h2><p>MPEG-DASH vs HLS comes down to who your viewers are and who controls the player. Use this rule by use case:</p><ol><li><strong>Audience includes iPhones, iPads or Safari, and you want one format:</strong> use HLS. It plays natively on Apple devices and, with hls.js, in every browser that has MSE.</li><li><strong>You ship your own apps on Android, smart TVs or set-top boxes, or need a codec outside Apple's HLS list, such as VP9:</strong> use DASH for those players, and keep HLS for Apple devices.</li><li><strong>You need both:</strong> package once as fMP4 and write two manifests (see the packaging section below).</li><li><strong>Viewers must talk back in under a second, such as co-hosts or live bidding:</strong> neither protocol fits at standard settings; use Web Real-Time Communication (WebRTC) for those participants, as covered in <a href="https://www.videosdk.live/blog/hls-vs-webrtc">WebRTC vs HLS for live streaming</a>.</li></ol><p>Both are delivery protocols. Ingest protocols such as the Real-Time Messaging Protocol (RTMP), Secure Reliable Transport (SRT) and the WebRTC-HTTP Ingestion Protocol (WHIP) carry the stream from the encoder to the server; HLS and DASH carry it from the server to viewers.</p><h2 id="how-one-set-of-segments-serves-both-hls-and-mpeg-dash">How one set of segments serves both HLS and MPEG-DASH</h2><p>The DASH video format has two parts, an MPD and the media segments it lists, and HLS has the same shape with M3U8 playlists. HLS accepts fMP4 segments (<a href="https://www.rfc-editor.org/rfc/rfc8216">RFC 8216</a>, section 3.3), and fMP4 is also a DASH segment format, so one set of fMP4 files can sit behind both manifests. MPEG's <a href="https://www.mpeg.org/standards/MPEG-A/19/">Common Media Application Format standard</a> (ISO/IEC 23000-19) was written for this case. Its 2017 white paper says CMAF fragments are encoded independently of the delivery protocol, so segments can be delivered once to CDN edge servers and served from cache to many players.</p><p>For the shared segments to also play on Apple devices, these rules from Apple's authoring specification apply to every rendition:</p><ul><li><strong>Segment length:</strong> target durations SHOULD be 6 seconds (requirement 7.5), and a segment MUST NOT exceed the target duration by more than 0.5 seconds (7.7).</li><li><strong>Keyframes:</strong> key frames SHOULD be present every 2 seconds (1.13), so each 6-second segment can start on one.</li><li><strong>Audio and video in step:</strong> audio and video playlists MUST use the same target duration and contain the same duration of content (8.2 and 8.3).</li><li><strong>Encryption:</strong> video encrypted with Common Encryption MUST use a 1:9 encrypt:skip pattern (13.7). The CMAF white paper describes Common Encryption as letting one encrypted presentation be protected by different DRM systems, so check that each DRM system your DASH players use accepts that pattern.</li></ul><p>The packaging tool or media server then writes an M3U8 playlist set and an MPD that point at the same files, as the diagram above shows.</p><h2 id="choosing-an-hls-player-and-a-dash-player-for-the-web">Choosing an HLS player and a DASH player for the web</h2><p>A web page needs an HLS player for browsers without native support and a DASH player for every browser. The two examples below adapt the official quick starts.</p><p>HLS with <a href="https://github.com/video-dev/hls.js">hls.js</a>, trying the library first and falling back to native playback, as its documentation recommends:</p><pre><code class="language-html">&lt;video id="video" controls&gt;&lt;/video&gt;
&lt;script src="https://cdn.jsdelivr.net/npm/hls.js@1"&gt;&lt;/script&gt;
&lt;script&gt;
  const video = document.getElementById("video");
  const src = "https://example.com/live/master.m3u8";
  if (Hls.isSupported()) {
    const hls = new Hls();
    hls.loadSource(src);
    hls.attachMedia(video);
  } else if (video.canPlayType("application/vnd.apple.mpegurl")) {
    video.src = src;
  }
&lt;/script&gt;
</code></pre><p>DASH with <a href="https://github.com/Dash-Industry-Forum/dash.js">dash.js</a>:</p><pre><code class="language-html">&lt;video id="player" controls&gt;&lt;/video&gt;
&lt;script src="https://cdn.dashjs.org/latest/modern/umd/dash.all.min.js"&gt;&lt;/script&gt;
&lt;script&gt;
  const player = dashjs.MediaPlayer().create();
  player.initialize(document.getElementById("player"),
    "https://example.com/live/manifest.mpd", true);
&lt;/script&gt;
</code></pre><p>The third argument to <code>initialize()</code> is <code>autoPlay</code>, per the dash.js type definitions. Pin a specific release in production instead of <code>latest</code> or <code>@1</code>, so a new version cannot change playback without a test.</p><h2 id="where-hls-and-dash-sit-in-an-interactive-live-streaming-build">Where HLS and DASH sit in an interactive live streaming build</h2><p>An interactive live app usually has two paths. Hosts and co-hosts talk over WebRTC. A server then composites the room into one stream and packages it for the large audience, and that packaging step is where HLS or DASH is chosen. The viewer's player has to match that output.</p><p>In VideoSDK, the audience path is HLS. The <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/integrate-hls/start-hls">Start HLS guide</a> (updated 4 September 2026) calls <code>startHls()</code> with a <code>config</code> that sets the layout, theme, mode and a <code>quality</code> of <code>"low"</code> (SD), <code>"med"</code> (HD, the default) or <code>"high"</code> (FHD). The <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/integrate-hls/overview">interactive livestream overview</a> says the stream is delivered as an M3U8 playlist that adapts resolution to the viewer's network. The docs do not describe a DASH output. </p><p>For playback, the <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/integrate-hls/setup-hls-player">Setup HLS Player guide</a> listens for the <code>hls-state-changed</code> event, waits for <code>HLS_PLAYABLE</code>, and passes <code>playbackHlsUrl</code> to hls.js, with the same <code>Hls.isSupported()</code> check and native fallback shown above.</p><p>The hosts' WebRTC codec is a separate choice from the HLS output. The JavaScript SDK's <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track">custom video track guide</a> (updated 11 September 2026) supports VP8 (the default), H264, VP9 and AV1, and says <code>multiStream</code>, its simulcast setting, is not supported for VP9 and AV1. </p><h2 id="glossary">Glossary</h2><blockquote><strong>Multivariant playlist (master playlist):</strong> The top-level HLS playlist that lists each rendition's bitrate, resolution and codecs, and points to one media playlist per rendition.</blockquote><blockquote><strong>MPD (Media Presentation Description):</strong> The XML manifest of an MPEG-DASH stream, describing its periods, adaptation sets and segments.</blockquote><blockquote><strong>fMP4 (fragmented MP4):</strong> An MP4 file split into movie fragments, each with its own index, so a player can fetch and play it piece by piece.</blockquote><blockquote><strong>CMAF (Common Media Application Format):</strong> An MPEG format for fMP4 segments and chunks that both HLS and DASH manifests can reference.</blockquote><blockquote><strong>Target duration:</strong> The maximum segment length an HLS media playlist declares, in whole seconds, which players use to decide how far behind live to start.</blockquote><blockquote><strong>MSE (Media Source Extensions):</strong> The browser API that lets JavaScript players such as hls.js and dash.js append media segments to a video element.</blockquote><blockquote><strong>ManagedMediaSource:</strong> A variant of MSE in which the browser can evict buffered media; Safari supports it, and web players use it on iPhones.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>HLS vs MPEG-DASH is a reach-versus-control choice: HLS plays natively on Apple devices and, as of 25 September 2026, in desktop Chrome 142 and later, while MPEG-DASH needs a player library in every browser.</li><li>On Apple devices, HLS accepts H.264, HEVC, Dolby Vision and AV1, so codec support alone rarely forces DASH.</li><li>Latency comes from segment duration and hold-back, not the protocol name: 6-second HLS segments put a standard player at least 18 seconds behind the newest segment, and both protocols have chunked low-latency modes.</li><li>Packaging once as fMP4 lets the same segments serve an M3U8 playlist and an MPD.</li></ul><p>If your audience includes Apple devices, start with HLS and add DASH only for players you control. To see how an interactive live stream becomes HLS output in VideoSDK, start with the <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/integrate-hls/overview">interactive livestream HLS guide</a>.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="which-mpeg-dash-player-should-you-use-in-a-browser">Which MPEG-DASH player should you use in a browser?</h3><p>Use dash.js, the open-source player maintained by the DASH Industry Forum, unless you already license a commercial player. It plays MPEG-DASH in any browser that supports Media Source Extensions and plays protected content through Encrypted Media Extensions. Load it, create a player with <code>dashjs.MediaPlayer().create()</code>, and call <code>initialize()</code> with your video element and MPD URL.</p><h3 id="does-the-mpeg-dash-protocol-work-on-iphone">Does the MPEG-DASH protocol work on iPhone?</h3><p>Not natively. iPhone Safari cannot play an MPD from a video tag, and caniuse lists full Media Source Extensions support only on iPadOS, not iPhone. A web DASH player on iPhone depends on Safari's ManagedMediaSource, which MDN marks as limited availability. HLS plays natively on iPhone, which makes it the practical format for iPhone viewers.</p><h3 id="is-dash-lower-latency-than-hls">Is DASH lower latency than HLS?</h3><p>Not by design. Both protocols deliver segments over HTTP, and latency depends on segment duration and how far behind live the player starts. With 6-second segments, a standard HLS player starts at least 18 seconds behind the newest segment, and DASH follows the same arithmetic. Both have low-latency modes: LL-HLS partial segments and low-latency DASH with CMAF chunks.</p>]]></content:encoded></item><item><title><![CDATA[CBR vs VBR: Constant vs Variable Bitrate for Live Streaming]]></title><description><![CDATA[Constant or variable bitrate? What each rate-control mode does inside the encoder, the peak limits HLS and YouTube set, capped VBR and two-pass VBR, and where the choice sits in a video SDK.]]></description><link>https://www.videosdk.live/blog/cbr-vs-vbr</link><guid isPermaLink="false">6ab6177cb3240feb748ca02b</guid><category><![CDATA[live-streaming]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 25 Sep 2026 13:17:16 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/ChatGPT-Image-Sep-25--2026--03_15_00-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>CBR vs VBR is a choice between a predictable rate and efficient quality. Use CBR (constant bit rate) for live contribution feeds, where the receiving service or network expects a steady rate. Use VBR (variable bit rate) for recordings and on-demand files, where quality per byte matters more. For live streaming renditions, capped VBR sits between the two.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/ChatGPT-Image-Sep-25--2026--03_15_00-PM.png" alt="CBR vs VBR: Constant vs Variable Bitrate for Live Streaming"/><p>This guide is for developers who have to pick a rate-control mode in an encoder or streaming pipeline. It covers what each mode does, the peak limits in <a href="https://www.videosdk.live/live-streaming" rel="noreferrer">HTTP Live Streaming (HLS)</a>, and where the choice sits when you build on a video SDK. For the definition of bitrate itself, see <a href="https://www.videosdk.live/blog/what-is-bitrate">what bitrate is and how it behaves in a WebRTC call</a>.</p><h2 id="how-constant-bit-rate-cbr-encoding-works">How Constant Bit Rate (CBR) encoding works</h2><p>Constant bit rate (CBR) encoding holds the encoder's output at one target rate, second after second, whatever the picture contains. The encoder gives a static slide the same budget as a crowd scene and changes how coarsely it quantizes each frame to stay on that budget. When a scene needs fewer bits than the target, a strict CBR stream adds stuffing packets to keep the rate up, as the <a href="https://en.wikipedia.org/wiki/Constant_bitrate">Wikipedia entry on constant bitrate</a> describes.</p><p>The payoff is predictability. A 2,500 kbps CBR stream needs 2,500 kbps of uplink at every moment, so you can size a connection or a content delivery network (CDN) ingest once and trust the number. At 30 frames per second that budget averages about 83 kilobits per frame (2,500 / 30), which is why <a href="https://www.videosdk.live/blog/frames-per-second">frame rate</a> matters as much as bitrate when you set one.</p><p>The cost is quality in the hard parts: the same Wikipedia entry notes that CBR may not allocate enough data to complex sections and wastes data on simple ones.</p><p>Because the rate never changes, CBR also makes size and bandwidth arithmetic exact:</p><pre><code class="language-text">file size (bytes) = bitrate (bits per second) x duration (seconds) / 8
</code></pre><p>A one-hour video stream at 2,500 kbps is 2,500,000 x 3,600 / 8 = 1,125,000,000 bytes, about 1.13 GB before audio and container overhead. Uncompressed pulse-code modulation (PCM) audio is constant by nature: 48,000 samples per second x 16 bits x 2 channels is 1,536,000 bits per second, or 1,536 kbps.</p><h2 id="how-variable-bit-rate-vbr-encoding-works">How variable bit rate (VBR) encoding works</h2><p>Variable bit rate (VBR) encoding lets the output rate rise and fall with the content: more bits for complex or fast-moving scenes, fewer for static ones. According to the <a href="https://en.wikipedia.org/wiki/Variable_bitrate">Wikipedia entry on variable bitrate</a>, VBR gives a better quality-to-space ratio than a CBR file of the same data, at the price of a more complex encode that can take longer.</p><p>VBR comes in three common forms:</p><ol><li><strong>Quality-targeted VBR.</strong> The encoder aims for a steady quality instead of a rate. In FFmpeg's libx264 encoder this is <code>-crf</code>, the constant rate factor (CRF), which the <a href="https://ffmpeg.org/ffmpeg-codecs.html">FFmpeg codec documentation</a> describes as the quality setting for constant quality mode. The file size is unknown until the encode ends.</li><li><strong>Average-bitrate VBR, usually two-pass.</strong> The encoder hits a target average across the whole file. A first pass analyses the content and a second pass spends the bits. The same Wikipedia entry notes that multi-pass encoding cannot be used for live streaming, because each pass reads the whole input.</li><li><strong>Capped VBR (constrained VBR).</strong> This is VBR with a ceiling. FFmpeg's <code>-maxrate</code> sets the maximum and requires <code>-bufsize</code>, the rate-control buffer the encoder measures itself against. It keeps most of VBR's efficiency while bounding the peaks a network or player has to absorb.</li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/cbr-vs-vbr-bitrate-over-time.png" class="kg-image" alt="CBR vs VBR: Constant vs Variable Bitrate for Live Streaming" loading="lazy" width="3200" height="1800"/></figure><p><em>Illustrative, not measured: capped VBR tracks scene complexity until it meets the ceiling that maxrate and bufsize set.</em></p><h2 id="cbr-vs-vbr-compared">CBR vs VBR Compared</h2><p>The table compares CBR vs VBR, with capped VBR as the middle option, on the attributes that decide a streaming setup.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Attribute</th>
<th>CBR</th>
<th>Uncapped VBR</th>
<th>Capped VBR</th>
</tr>
</thead>
<tbody>
<tr>
<td>Bitrate over time</td>
<td>Flat at the target</td>
<td>Follows scene complexity</td>
<td>Varies below a set maximum</td>
</tr>
<tr>
<td>Quality over time</td>
<td>Drops in complex scenes</td>
<td>Most even</td>
<td>Even until a scene hits the cap</td>
</tr>
<tr>
<td>Bandwidth planning</td>
<td>Exact</td>
<td>Peaks unknown in advance</td>
<td>Peak bounded by maxrate</td>
</tr>
<tr>
<td>Encoding passes</td>
<td>One, real time</td>
<td>One (quality mode) or two (files only)</td>
<td>One, real time</td>
</tr>
<tr>
<td>Typical use</td>
<td>Live contribution feeds</td>
<td>Recordings, uploads, archives</td>
<td>HLS renditions, live or on demand</td>
</tr>
<tr>
<td>Fit with adaptive bitrate (ABR) ladders</td>
<td>Works, but spends bits on simple scenes</td>
<td>Peaks can overshoot the rate the playlist declares</td>
<td>Peaks stay near the declared rate</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The row that decides most setups is bandwidth planning: CBR and capped VBR give you a number to plan a network around, and uncapped VBR does not.</p><h2 id="cbr-or-vbr-for-live-streaming">CBR or VBR for live streaming?</h2><p>For a live contribution feed, the stream you push from an encoder to a platform or media server, use CBR unless the receiving service asks for something else. YouTube's <a href="https://support.google.com/youtube/answer/2853702?hl=en">live encoder settings</a> list "Bitrate encoding: CBR", as of 25 September 2026. A steady input also means your uplink never sees a spike your encoder chose. Hardware and desktop encoders expose the same modes under their own setting names, so check which label maps to CBR before you go live. For the bitrate each platform accepts, see <a href="https://www.videosdk.live/developer-hub/hls/streaming-bitrate">streaming bitrate settings for Twitch, YouTube and OBS</a>.</p><p>For live HLS renditions that you encode and package yourself, capped VBR is allowed, within limits. <a href="https://www.rfc-editor.org/rfc/rfc8216">RFC 8216</a>, section 4.3.4.2, defines the playlist's BANDWIDTH attribute as the peak segment bit rate and AVERAGE-BANDWIDTH as the average segment bit rate, and warns that an inaccurate value can cause playback stalls. Apple's <a href="https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices">HLS Authoring Specification</a> adds numbers for live (linear) content: the measured peak bit rate must be less than 125% of BANDWIDTH, and the average over about an hour must be less than 110% of AVERAGE-BANDWIDTH (requirements 1.28 and 1.29). Players pick renditions from those declared rates, which is how <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming">adaptive bitrate streaming switches between renditions</a>, so each rung's maxrate should sit inside what its playlist line promises.</p><p>WebRTC calls and interactive streams fit neither label. The sender's congestion controller keeps recomputing a target bitrate from network feedback, as the Internet Engineering Task Force (IETF) <a href="https://datatracker.ietf.org/doc/html/draft-ietf-rmcat-gcc-02">Google Congestion Control draft</a> describes, so the rate moves with the network rather than with the scene.</p><h2 id="vbr-vs-cbr-for-recordings-and-on-demand-video">VBR vs CBR for recordings and on-demand video</h2><p>For files watched on demand, VBR vs CBR usually favours VBR, because a player can buffer ahead and absorb short peaks. HLS still bounds it. For video on demand (VOD), Apple's specification requires the measured peak bit rate to be within 10% of BANDWIDTH and the average segment bit rate to be within 10% of AVERAGE-BANDWIDTH (requirements 1.26 and 1.27). It also says the peak SHOULD be no more than 200% of the average (requirement 1.30).</p><p>That gives a simple rule for on-demand work:</p><ol><li>For an archive master that nobody streams directly, use quality-targeted VBR with no cap.</li><li>For a file you will upload to a platform that re-encodes it, use quality-targeted or two-pass VBR at a generous rate.</li><li>For HLS renditions you serve yourself, use capped VBR or two-pass VBR, with the peak no more than twice the average.</li></ol><h2 id="where-the-rate-control-choice-sits-when-you-build-on-a-video-sdk">Where the rate-control choice sits when you build on a video SDK</h2><p>An app built on a real-time video SDK usually involves three encoders, and you control a different amount of each:</p><ol><li><strong>Encoders you run yourself</strong> (OBS Studio, FFmpeg, hardware): you pick the rate mode, and CBR is the safe default for a live feed.</li><li><strong>The SDK's in-app encoder</strong> for camera and screen share: it follows congestion control, so you pick a resolution and a quality profile.</li><li><strong>The platform's server-side encoder</strong> for HLS and recordings: the platform picks the mode, and you pick a quality tier.</li></ol><p>In VideoSDK, those three map to documented settings. The JavaScript SDK's <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track">custom video track guide</a> (updated 11 September 2026) passes an <code>encoderConfig</code> such as <code>"h720p_w1280p"</code> and a <code>bitrateMode</code> of <code>BANDWIDTH_OPTIMIZED</code>, <code>BALANCED</code> (the default) or <code>HIGH_QUALITY</code> to <code>createCameraVideoTrack()</code>. Its table lists 1,000, 1,500 and 2,000 kbps for those three modes at 1280x720 and 30 fps. The guide describes these as quality profiles and does not document a CBR or VBR switch.</p><p>For your own encoders, VideoSDK documents <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/whip-whep-ils">WebRTC-HTTP Ingestion Protocol (WHIP) ingest from OBS Studio into a room</a> (updated 10 July 2026). The rate mode is set in OBS, and the guide does not recommend one. For HLS output, the <a href="https://docs.videosdk.live/api-reference/realtime-communication/start-hlsStream">start HLS API</a> takes a <code>quality</code> of <code>"low"</code>, <code>"med"</code> or <code>"high"</code> rather than a rate mode.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Rate control (bitrate mode):</strong> The encoder logic that decides how many bits each frame gets to meet a target rate, quality or ceiling.</blockquote><blockquote><strong>VBV buffer (video buffering verifier, bufsize):</strong> The model buffer an encoder measures its output against, set in FFmpeg with <code>-bufsize</code>.</blockquote><blockquote><strong>CRF (constant rate factor):</strong> The libx264 quality-targeted mode, set with <code>-crf</code>, which aims for a quality level instead of a bitrate.</blockquote><blockquote><strong>Capped VBR (constrained VBR):</strong> Variable bit rate with a maximum rate and buffer, so peaks stay bounded while simple scenes still save bits.</blockquote><blockquote><strong>Two-pass encoding (multi-pass):</strong> An encode that analyses the whole file before spending bits, so it suits files but not live streams.</blockquote><blockquote><strong>BANDWIDTH and AVERAGE-BANDWIDTH:</strong> HLS playlist attributes that declare a rendition's peak and average segment bit rates.</blockquote><h3 id="key-takeaways">Key takeaways</h3><ul><li>CBR vs VBR comes down to predictability against efficiency: CBR holds one rate, and VBR moves the rate to hold quality.</li><li>Use CBR for live contribution feeds; YouTube's live encoder settings list CBR as of 25 September 2026.</li><li>Use capped VBR for HLS renditions, and for live content on Apple devices keep the measured peak under 125% of the declared BANDWIDTH.</li><li>Use quality-targeted or two-pass VBR for recordings and on-demand files, where the whole file can be analysed and buffered.</li></ul><p>Set the rate mode where each encoder sits: your own encoder for ingest, the SDK's quality profile for in-app video, and the platform's tier for HLS. To see how an interactive stream becomes HLS output in VideoSDK, start with the <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/integrate-hls/overview">interactive livestream HLS guide</a>.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-cbr">What is CBR?</h3><p>CBR stands for constant bit rate, an encoding mode that keeps the output at one fixed number of bits per second whatever the scene contains. It makes bandwidth and file size predictable, which suits live contribution feeds, at the cost of lower quality in complex scenes and wasted bits in simple ones. Outside media encoding, the same three letters also name unrelated things, such as a comic-book archive format.</p><h3 id="what-is-vbr">What is VBR?</h3><p>VBR stands for variable bit rate, an encoding mode that raises the bitrate for complex or fast scenes and lowers it for simple ones to keep quality steady. It gives better quality per byte than CBR at the same average rate, but its peaks are less predictable. Capped VBR adds a maximum rate and buffer so those peaks stay bounded for streaming.</p><h3 id="does-vbr-use-less-bandwidth-than-cbr">Does VBR use less bandwidth than CBR?</h3><p>On average, often yes: at the same visual quality, VBR usually needs a lower average bitrate because it saves bits on simple scenes. Its peaks can be higher than a CBR stream's, though, so the bandwidth a viewer needs at the worst moment may rise. That is why HLS playlists declare both a peak BANDWIDTH and an AVERAGE-BANDWIDTH for each rendition.</p>]]></content:encoded></item><item><title><![CDATA[Frame Rate (FPS) Explained: What Frames Per Second Means & Which Frame Rate to Use?]]></title><description><![CDATA[Frames per second is the count of images in each second of video, and the rate you choose decides how motion looks, how much bitrate you need and how long your GOP runs. Here are the standard rates, what Apple, YouTube and Amazon IVS ask for, and what variable frame rate does to an encoder.]]></description><link>https://www.videosdk.live/blog/frames-per-second</link><guid isPermaLink="false">6ab278c1b3240feb748c9fd8</guid><category><![CDATA[live-streaming]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 22 Sep 2026 13:20:27 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/04-1.png" medium="image"/><content:encoded><![CDATA[<blockquote>Frames per second (fps) is the number of still images a video shows each second. It is also called frame rate. Film runs at 24 fps, most streaming and broadcast video at 30, and sport, gaming and screen capture at 60. Higher frame rates look smoother and cost more bandwidth.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/04-1.png" alt="Frame Rate (FPS) Explained: What Frames Per Second Means & Which Frame Rate to Use?"/><p>This page is for anyone choosing a number in an encoder, a camera menu or a stream settings screen. It has the standard frame rates explained one by one, says which industry settled on each of those fps standards, and covers what to set for a live stream, what variable frame rate does to an encoder, and what the eye actually does with frames. Every figure below comes from a specification or a platform's own documentation, dated.</p><h2 id="common-frame-rates-what-each-one-is-for">Common frame rates &amp; What each one is for?</h2><p>The typical video frame rates cluster around five values: 24, 25, 30, 50 and 60 frames per second. Encoder menus write the setting as frame rate, framerate or fps and broadcast documents call it frame frequency, but the frame rate meaning does not change between them. Which value is standard where is a question of broadcast history, not of which one looks best.</p><p>This frame rate comparison covers those five standard frame rates per second, the standard each belongs to, what it suits and what it costs.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Frame rate</th>
<th>Where it is the standard</th>
<th>Best for</th>
<th>The catch</th>
</tr>
</thead>
<tbody>
<tr>
<td>24 fps</td>
<td>Digital cinema. The DCI specification requires 24.000 Hz</td>
<td>Film and cinematic video</td>
<td>Motion judder on fast pans, and 3:2 pull-down to reach 30 fps</td>
</tr>
<tr>
<td>25 fps</td>
<td>PAL regions. A listed ITU-R BT.709 picture rate</td>
<td>European broadcast and archive material</td>
<td>Apple asks for 50 fps, not 25, from a live PAL source</td>
</tr>
<tr>
<td>30 fps</td>
<td>The starting point on YouTube Live and Amazon IVS</td>
<td>Talking heads, webinars, most live video</td>
<td>Not enough for fast sport or 60 Hz screen capture</td>
</tr>
<tr>
<td>50 fps</td>
<td>The PAL high frame rate</td>
<td>European sport and fast motion</td>
<td>Doubles the frames a 25 fps bitrate budget was built for</td>
</tr>
<tr>
<td>60 fps</td>
<td>The ceiling for HLS delivery</td>
<td>Sport, gaming, screen capture</td>
<td>Amazon IVS recommends it only at 720p and above</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The reading that matters in that frames per second comparison: different frame rates suit different destinations, so choose from the destination rather than from the camera. The frame rate differences above are resolved by conversion, and conversions cost quality no bitrate increase recovers.</p><p>Two of those values are specified rather than conventional. The <a href="https://dcss.dcimovies.com/latest/dcss.html">DCI Digital Cinema System Specification</a> states at item 3.1.4.2 that a digital cinema master must support 24.000 Hz, with 48.000 Hz allowed for 2K content only, which is why the frame rate of film is 24 and movie frames per second have not moved. Broadcast standards define frame rate in hertz rather than fps: <a href="https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.709-6-201506-I!!PDF-E.pdf">ITU-R BT.709-6</a>, the HDTV parameter recommendation, lists picture rate in section 5.5 as 60, 60/1.001, 30, 30/1.001, 50, 25, 24 and 24/1.001 Hz. Television frames per second are therefore regional: 25 and 50 where PAL was the standard, 30 and 60 where NTSC was.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/frame-rate-24-30-60-one-second.png" class="kg-image" alt="Frame Rate (FPS) Explained: What Frames Per Second Means & Which Frame Rate to Use?" loading="lazy" width="2400" height="1040"/></figure><p><em>The same second of video at three frame rates. The frame duration, not the frame count, is what an encoder and a display work with.</em></p><h3 id="24-fps-vs-30-fps">24 fps vs 30 fps</h3><p>The 24 frame rate vs 30 question is settled by the destination, not by quality. 24 fps is the film frame rate and carries the motion character an audience reads as cinema. 30 fps is the normal frame rate for streaming, conferencing and North American broadcast, and holds up better on fast movement. Converting between them is the real cost: ITU-R BT.709 describes 3:2 pull-down to make a 30 Hz copy from a 24 frame per second original, and that cadence survives into whatever encodes the result.</p><h3 id="why-some-frame-rates-have-a-97-or-a-94">Why some frame rates have a .97 or a .94</h3><p>The fractional rates are that same ITU-R list divided by 1.001: 29.97, 59.94 and 23.976. Apple's HLS authoring specification, linked in the next section, lists all three alongside the whole numbers as supported rates, so a file marked 29.97 is normal rather than broken. The consequence is arithmetic. A timeline counted in whole 30 fps frames runs about 0.1% fast against a clock, so long-form projects track the fractional rate rather than rounding it.</p><h2 id="frame-rate-for-live-streaming">Frame rate for live streaming</h2><p>Live streaming uses a 30fps frame rate by default and a 60 fps frame rate for fast motion, and the choice changes both the bitrate you need and the length of your GOP, the group of pictures between two key frames. A live stream is encoded, segmented and delivered in one pass, so its frame rate is bound to other settings in the encoder.</p><p>The table lists the fps rates three platforms publish, read on 22 September 2026.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Platform</th>
<th>Frame rates accepted</th>
<th>What it asks for on a live stream</th>
<th>Stated in</th>
</tr>
</thead>
<tbody>
<tr>
<td>Apple HLS authoring spec</td>
<td>23.976, 24, 25, 29.97, 30, 50, 59.94, 60. Nothing above 60</td>
<td>60 or 59.94 from an NTSC or ATSC source, 50 from a PAL source</td>
<td><a href="https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices">Items 1.16 to 1.19</a></td>
</tr>
<tr>
<td>YouTube Live</td>
<td>Up to 60 fps</td>
<td>30 or 60, with a separate bitrate row for each</td>
<td><a href="https://support.google.com/youtube/answer/2853702">Live encoder settings</a></td>
</tr>
<tr>
<td>Amazon IVS</td>
<td>Up to 60, including the PAL 25 and 50 rates</td>
<td>30 at 480p, 30 or 60 at 720p and 1080p</td>
<td><a href="https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/streaming-config.html">Streaming configuration</a></td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Two lines in that table are worth more than the rest. Apple's item 1.19 states that frame rates above 60 fps shall not be used, so 60 is a hard ceiling for anything delivered to Apple devices over HLS, or HTTP Live Streaming. Items 1.16 and 1.17 then ask for 59.94 or 60 from NTSC and ATSC sources and 50 from PAL, which is higher than the 30 fps most streaming guides suggest.</p><p>Doubling the frame rate does not double the bitrate. YouTube's live encoder table gives the H.264 recommendation for 1080p at 30 fps as 10 Mbps and for 1080p at 60 fps as 12 Mbps, a 20% increase for twice the frames, and moves 720p from 4 Mbps to 6 Mbps. The extra frames are cheap because each sits closer in time to its neighbour, so the difference an encoder stores is smaller. What 60 fps costs is headroom: on a connection already marginal at 30 fps, the encoder fits twice as many frames under the same ceiling and degrades something to do it.</p><h3 id="frame-rate-and-keyframe-alignment">Frame rate and keyframe alignment</h3><p>Frame rate decides how many frames sit inside a GOP, because most encoders express the keyframe interval in seconds and convert. At a two second interval, 30 fps produces a 60 frame GOP and 60 fps a 120 frame GOP. Apple's authoring specification asks at item 1.13 for key frames every two seconds, and Amazon IVS gives two seconds at every resolution tier above.</p><p>The trap is an encoder whose keyframe field counts frames rather than seconds. Set it to 60 while running 30 fps and the interval is two seconds; change the frame rate to 60 and the same 60 silently becomes one second. Re-check that field after every frame rate change, and if the stream goes out over HTTP, read how <a href="https://www.videosdk.live/blog/what-is-http-live-streaming">HLS cuts a stream into media segments</a> first, because segment length is built on both numbers.</p><h3 id="frame-rate-on-a-real-time-path">Frame rate on a real-time path</h3><p>A WebRTC sender treats frame rate as a request rather than a setting. The W3C <a href="https://www.w3.org/TR/mediacapture-streams/">Media Capture and Streams specification</a> defines <code>frameRate</code> as a constrainable property on a video track, so an application asks the source for a rate and the user agent supplies what the hardware and conditions allow.</p><p>That matters when bandwidth drops, because an encoder under pressure gives up either frames or pixels and cannot keep both. Moving content suffers most from lost frames, text and shared screens from lost detail. VideoSDK exposes that as an optimization mode on a video track, where the motion setting will "degrade resolution in order to maintain frame rate" and the text and detail settings do the opposite, as its <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track">optimize video track guide</a> documents.</p><h2 id="what-is-variable-frame-rate">What is variable frame rate?</h2><p>Variable frame rate, or VFR, means each frame carries its own timestamp and the gap between frames is allowed to change. Constant frame rate, or CFR, spaces every frame evenly. A screen recorder that emits a frame only when the picture changes produces VFR, and so does a phone camera that lengthens its exposure in low light.</p><p>VFR is efficient at capture and awkward everywhere after it. Any tool that assumes a constant rate reads the file as evenly spaced, so picture and sound drift apart further the longer the recording runs. Cinema rules it out at the master: the DCI specification requires a digital cinema master's frame rate to remain constant.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/constant-vs-variable-frame-rate-1.png" class="kg-image" alt="Frame Rate (FPS) Explained: What Frames Per Second Means & Which Frame Rate to Use?" loading="lazy" width="2400" height="1020"/></figure><p><em>CFR spaces frames evenly, so a segmenter can cut on a predictable boundary. VFR does not, and the gap moves with the scene.</em></p><p>Streaming is stricter still. Apple's authoring specification requires at item 8.14 that a frame rate change be marked as a discontinuity with an <code>EXT-X-DISCONTINUITY</code> tag, and warns at item 9.23 that nonsimilar frame rates may cause playback issues. A VFR source in a live encoder forces a choice between rewriting timestamps and emitting discontinuities some players handle badly.</p><p>Force CFR at the first encode. In FFmpeg that is <code>-fps_mode cfr</code>, which the <a href="https://ffmpeg.org/ffmpeg.html">FFmpeg documentation</a> describes as duplicating and dropping frames to reach exactly the requested constant frame rate, paired with <code>-r</code>. In OBS and most broadcast encoders the output is already CFR, so the setting to check is the capture device.</p><h2 id="how-many-frames-per-second-can-the-human-eye-see">How many frames per second can the human eye see?</h2><p>The human eye does not work in frames, so the question has no number as an answer. Vision is continuous, and what changes with frame rate is not whether you see the image but which artefacts you notice: judder on a pan, strobing on a wheel, flicker on an edge.</p><p>The measurement usually quoted is the critical flicker fusion rate, the point where modulated light stops looking like flicker, reported somewhere between 50 and 90 Hz. That figure understates what the eye can resolve. In <a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC4314649/">Humans perceive flicker artifacts at 500 Hz</a>, published in Scientific Reports in February 2015, Davis, Hsieh and Lee showed that when a display contains a high frequency spatial edge, "flicker artifacts disappear only over 500 Hz" for the median viewer, and several participants saw them above 800 Hz.</p><p>None of that argues for 500 fps video, because flicker is how a display refreshes its light while frame rate is how often the content changes. It does mean that anyone capping the eye at 30 or 60 is describing a display convention, not a limit of vision.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li>Frames per second counts the still images a video shows each second, and frame rate is the same measurement under a different name.</li><li>The standard frame rates are 24 for cinema, 25 and 50 in PAL regions, 30 and 60 for streaming, and the fractional variants are those divided by 1.001.</li><li>Apple's HLS authoring specification forbids anything above 60 fps, which makes 60 the working ceiling for delivery to Apple devices.</li><li>Doubling the frame rate raises YouTube's recommended bitrate by 20 to 50%, not by 100%, because consecutive frames are more alike.</li><li>Variable frame rate is fine at capture and a problem afterwards, so force constant frame rate before a file reaches an encoder.</li></ul><h2 id="conclusion">Conclusion</h2><p>Frame rate is one of the few encoder settings that changes three things at once: how motion looks, how much bitrate the stream needs, and how many frames sit inside each group of pictures. Decide it from the destination, keep it constant, and re-check the keyframe field whenever you change it. If you are building a live product where hosts stream in real time and an audience watches over <a href="https://www.videosdk.live/live-streaming" rel="noreferrer">HLS</a>, the <a href="https://www.videosdk.live/interactive-live-streaming">interactive live streaming</a> pattern carries both paths, and each one handles frame rate differently.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-does-frame-rate-mean-in-video">What does frame rate mean in video?</h3><p>Frame rate means how many individual images a video contains for each second of running time, written as frames per second or fps. One frame per second means one still image a second, so a 30 fps clip holds thirty. That is the whole frame rate definition, and the meaning of frame rate is identical in a camera, an editor and an encoder. It is independent of resolution.</p><h3 id="how-many-frames-per-second-should-a-video-be">How many frames per second should a video be?</h3><p>Match the frame rate to where the video will play. Use 24 fps for film and cinematic work, 25 or 50 in PAL regions, 30 fps for most streaming and conferencing, and 60 fps for sport, gaming and screen capture. Anything above 60 is wasted on an HLS path, which does not accept it.</p><h3 id="what-is-a-good-frame-rate-for-live-streaming">What is a good frame rate for live streaming?</h3><p>30 fps is a good frame rate for most live streams and 60 fps is the right choice for fast motion. Amazon IVS recommends 30 at 480p and 30 or 60 at 720p and 1080p, and YouTube accepts up to 60 fps. Whatever fps rate you pick, keep it constant. Lower rates such as 15 fps or 5 frames per second stay valid for low-motion sources: Amazon IVS gives a security camera as its example.</p><h3 id="what-fps-is-real-life">What fps is real life?</h3><p>Real life has no fps, because nothing samples it. People asking how many fps is real life are usually reaching for the refresh rate of the screen in front of them, which is a property of that display rather than of vision. Frame rate only becomes visible when a recording samples motion coarsely enough that your eye can tell one frame from the next.</p><h3 id="what-is-frame-time">What is frame time?</h3><p>Frame time is the same measurement expressed in milliseconds instead of frames per second, and the two are reciprocals. 24 fps is 41.7 ms per frame, 30 fps is 33.3 ms and 60 fps is 16.7 ms. Frame time is the more useful figure when you are budgeting a capture and encode path, because every stage has to finish inside it. Over a minute, 30 fps is 1,800 frames per minute.</p>]]></content:encoded></item><item><title><![CDATA[What is a Keyframe? Keyframe Intervals and GOPs Explained]]></title><description><![CDATA[A keyframe is the complete picture a decoder can start from, and the keyframe interval decides how fast a viewer can join, seek or switch quality. Here are the frame types, the GOP, the intervals Apple, YouTube, Amazon IVS and Cloudflare ask for, and what OBS auto really sets.]]></description><link>https://www.videosdk.live/blog/what-is-a-keyframe</link><guid isPermaLink="false">6ab25ac5b3240feb748c9f91</guid><category><![CDATA[live-streaming]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 22 Sep 2026 12:33:58 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/03.png" medium="image"/><content:encoded><![CDATA[<blockquote>A keyframe, or I-frame, is a video frame stored as a complete picture that a decoder can render without reference to any other frame. The P and B frames around it store only what changed. The keyframe interval is how often an encoder emits one, and it sets how fast a player can start, seek or switch quality.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/03.png" alt="What is a Keyframe? Keyframe Intervals and GOPs Explained"/><p>If you searched what is a keyframe and landed on animation tutorials, this is the other keyframe: the one in video encoding and live streaming. Most of the material under that phrase describes After Effects and CSS, where a keyframe is a marker you place on a timeline. This page is about the frame an encoder writes: the frame types inside a group of pictures, the interval streaming platforms ask you to set, and what the OBS 0 value actually does. </p><h2 id="i-p-and-b-frames-and-the-gop">I, P and B frames and the GOP</h2><p>A keyframe is one of three frame types a video encoder produces, and the only one that stands on its own. The&nbsp;<a href="https://www.w3.org/TR/webcodecs/">W3C WebCodecs specification</a>&nbsp;defines a key chunk as “an encoded chunk that does not depend on any other frames for decoding”, and notes it is commonly called a key frame.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Frame type</th>
<th>What it stores</th>
<th>Decodes on its own</th>
<th>Typical size</th>
</tr>
</thead>
<tbody>
<tr>
<td>I-frame (keyframe)</td>
<td>A complete picture</td>
<td>Yes</td>
<td>Largest</td>
</tr>
<tr>
<td>P-frame</td>
<td>Differences from earlier frames</td>
<td>No</td>
<td>Smaller</td>
</tr>
<tr>
<td>B-frame</td>
<td>Differences from earlier and later frames</td>
<td>No</td>
<td>Smallest</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Keyframes are the only frames a decoder can enter a stream at, which turns their spacing into a configuration decision rather than an encoder detail.</p><p>In H.264 the precise term is IDR, for instantaneous decoding refresh.&nbsp;<a href="https://www.rfc-editor.org/rfc/rfc6184.html">RFC 6184</a>&nbsp;defines an IDR picture as one that resets the decoding process, so that every picture after it in decoding order decodes without inter prediction from anything before it. An ordinary I-frame is coded without reference to other frames, but later frames may still reference pictures from before it. Only an IDR guarantees a clean entry point, which is why streaming specifications ask for IDRs rather than I-frames.</p><p>B-frames are the reason decode order and display order differ. A B-frame references a frame that comes after it on screen, so the decoder has to receive that later frame first. Cutting B-frames is a standard step when a pipeline is tuned for the lowest possible delay.</p><p>A group of pictures, or GOP, is the run of frames from one keyframe up to the frame before the next. Cloudflare’s Stream documentation, cited below, treats the two terms as interchangeable, writing of a “GOP duration (keyframe interval)”. GOP length is the number most encoder settings screens expose, whether they label it GOP size, keyframe interval or keyframe frequency.</p><p><a href="https://app.slack.com/client/TEADZSVH8/gop-structure-keyframes.png" rel="noopener noreferrer"/></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/gop-structure-keyframes.png" class="kg-image" alt="What is a Keyframe? Keyframe Intervals and GOPs Explained" loading="lazy" width="2400" height="1320"/></figure><p><em>Each GOP opens with a keyframe. A player can only begin decoding, seek, or switch rendition at one of those openings, so GOP length sets the granularity of all three.</em></p><p>GOP length is a single trade. Keyframes are the expensive frames, so a longer GOP leaves more of a fixed bit budget for the P and B frames that carry detail, while a shorter one softens the picture under motion but lets a decoder start more often. Every recommendation below is a position on that trade.</p><h2 id="keyframe-interval-for-live-streaming">Keyframe interval for live streaming</h2><p>The keyframe interval is the longest an encoder will go before emitting another keyframe, and for a live stream it is usually two seconds. The reason is segment alignment rather than picture quality. HLS cuts a stream into short media segments requested one at a time over HTTP, and each segment has to be independently decodable.</p><p><a href="https://www.rfc-editor.org/rfc/rfc8216.html">RFC 8216</a>, the HLS specification, states in section 3 that a media segment carrying H.264 should contain an IDR. Apple’s HLS Authoring Specification, linked in the table below, turns that into a requirement at item 7.4: “Video segments MUST start with an IDR frame.” A segment therefore cannot be shorter than the keyframe interval, because it would have no keyframe to start with.</p><p>Two further items explain the two-second convention. Item 1.13 states that key frames should be present every two seconds; item 7.5 states that target durations should be six seconds. A six-second segment built from three two-second GOPs satisfies both and leaves the packager free to cut at any of the three keyframes.</p><p>Rendition switching depends on the same boundaries. The&nbsp;<code>EXT-X-INDEPENDENT-SEGMENTS</code>&nbsp;tag in RFC 8216 section 4.3.5.1 signals that every media segment decodes on its own, and Apple’s item 9.11 tells authors to set it when segments start with an IDR. An adaptive player changes quality at a segment boundary, so a viewer on a fluctuating connection gets a quality change only as often as a new keyframe arrives, and a viewer joining mid-stream waits for the next one before anything decodes.</p><p>When the interval runs long that machinery stops working: Amazon IVS documents that above five seconds it can no longer guarantee every playback segment begins with a keyframe. Going shorter is not free either. AWS’s IVS streaming configuration guide puts stream-start latency at six to seven seconds with a two-second interval against three to four at one second, but warns that one-second segments make an adaptive player switch rendition more often.</p><p>Low-latency HLS attacks the same delay from the other end, splitting each segment into parts of 200 to 500 milliseconds so a player can fetch the front of a segment before the rest exists; the&nbsp;<a href="https://www.videosdk.live/developer-hub/hls/hls-low-latency">LL-HLS guide</a>&nbsp;covers that path. The interval itself stays at two seconds because it sits between those two failure modes, not because it is optimal for either.</p><h3 id="what-the-platforms-ask-for">What the platforms ask for</h3><p>These are current published requirements, read on 22 September 2026. Each links to its source.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Platform</th>
<th>Keyframe interval</th>
<th>Stated in</th>
</tr>
</thead>
<tbody>
<tr>
<td>Apple HLS authoring spec</td>
<td>Every 2 seconds (SHOULD)</td>
<td><a href="https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices">Item 1.13</a></td>
</tr>
<tr>
<td>YouTube Live</td>
<td>2 seconds recommended, do not exceed 4</td>
<td><a href="https://support.google.com/youtube/answer/2853702">Live encoder settings</a></td>
</tr>
<tr>
<td>Amazon IVS</td>
<td>2 seconds, or 1 for lower latency; avoid above 5</td>
<td><a href="https://docs.aws.amazon.com/ivs/latest/LowLatencyUserGuide/streaming-config.html">Streaming configuration</a></td>
</tr>
<tr>
<td>Cloudflare Stream Live</td>
<td>2 to 8 seconds; 2 to 4 for Low-Latency HLS</td>
<td><a href="https://developers.cloudflare.com/stream/stream-live/start-stream-live/">Start a live stream</a></td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Two seconds satisfies all four, and only Cloudflare’s standard tier is comfortable above four. If one encoder feeds several destinations, two seconds is the setting that never needs revisiting per destination.</p><h3 id="keyframes-on-a-real-time-path">Keyframes on a real-time path</h3><p>A WebRTC stream has no fixed keyframe interval, because nothing is being cut into segments. The receiver asks for a keyframe when it needs one:&nbsp;<a href="https://www.rfc-editor.org/rfc/rfc4585.html">RFC 4585</a>&nbsp;defines the Picture Loss Indication message, which a decoder sends to tell the encoder it has lost “an undefined amount of coded video data”, and the sender may respond with an intra-picture subject to congestion control.</p><p>So on a WebRTC path keyframe cadence follows joins and packet loss and the stack handles it, while on an HLS path it follows the segmenter and it is yours to configure. Both can run from one session: VideoSDK’s&nbsp;<a href="https://docs.videosdk.live/react/api/sdk-reference/use-meeting/introduction"><code>useMeeting</code>&nbsp;reference</a>&nbsp;exposes&nbsp;<code>startHls</code>&nbsp;and&nbsp;<code>stopHls</code>&nbsp;on a live meeting, and only the HLS output of that session takes a keyframe interval.</p><h2 id="obs-keyframe-interval-setting">OBS keyframe interval setting</h2><p>The keyframe interval in OBS Studio is a single field labelled&nbsp;<strong>Keyframe Interval (0=auto)</strong>, expressed in seconds, in the encoder settings for the software x264 encoder. It is the upper bound OBS passes to the encoder, and it is the one value every platform in the table above asks you to set.</p><h3 id="what-the-0-auto-value-actually-does">What the 0 (auto) value actually does</h3><p>Auto does not mean what most streamers assume. OBS ships the field defaulting to 0, and when it is 0 OBS does not pass a keyframe interval to x264 at all. x264 then applies its own default, which&nbsp;<a href="https://github.com/mirror/x264/blob/master/common/base.c"><code>x264_param_default</code>&nbsp;sets to 250 frames</a>.</p><p>250 is a frame count, not a duration, so what it means in seconds depends on frame rate:</p><ul><li>At 30 fps: 250 / 30 = about 8.3 seconds</li><li>At 60 fps: 250 / 60 = about 4.2 seconds</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/obs-keyframe-interval-0-vs-2-1.png" class="kg-image" alt="What is a Keyframe? Keyframe Intervals and GOPs Explained" loading="lazy" width="2400" height="896"/></figure><p><em>Auto is a frame count, not a duration, so what it means moves with frame rate.</em></p><p>Both exceed what every platform in the table above asks for. Entering 2 makes the interval explicit and independent of frame rate.</p><p>Two caveats. The 250-frame default belongs to x264, so a hardware encoder such as NVENC or QuickSync has its own field and its own default, and this number does not transfer. And scene-cut detection stays on unless you disable it, so a stream set to two seconds will still contain keyframes closer together whenever the picture changes sharply.</p><h2 id="the-other-keyframe">The other keyframe</h2><p>In animation and video editing software, a keyframe is a marker on a timeline rather than a compressed frame:&nbsp;<a href="https://www.adobe.com/creativecloud/video/discover/keyframing.html">Adobe’s guide for Creative Cloud users</a>&nbsp;describes it as choosing how elements of a graphic “will move or change over time”. The two senses share a name and nothing else, because that keyframe is an instruction you place while an encoding keyframe is a frame the encoder writes.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li>A keyframe, or I-frame, is a complete picture a decoder can start from, while the P and B frames around it store only differences.</li><li>In H.264 the exact term is IDR, and only an IDR guarantees that nothing after it references a picture from before it.</li><li>Keyframe interval sets GOP length, which decides how often a player can start, seek or change quality, and trades compression efficiency against all three.</li><li>Two seconds satisfies Apple, YouTube, Amazon IVS and Cloudflare Stream at once, which is why it has become the default recommendation.</li><li>OBS auto is not two seconds: 0 hands the setting to x264's 250-frame default, about 8.3 seconds at 30 fps.</li></ul><h2 id="conclusion">Conclusion</h2><p>Keyframes are the only frames a decoder can start from, so the interval you set decides how a stream behaves the moment someone joins, seeks or changes quality. Two seconds is the value that satisfies every platform in the table above, and OBS auto is not two seconds. Set the number explicitly, re-check it after any frame rate change, and confirm it against the documentation of whichever platform you ingest to. If you are weighing a real-time path against an HLS path, the <a href="https://www.videosdk.live/interactive-live-streaming">interactive live streaming</a> pattern runs both, and only the HLS side needs this number.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="should-the-obs-keyframe-interval-be-0-or-2">Should the OBS keyframe interval be 0 or 2?</h3><p>Set it to 2. The 0 value hands the decision to x264, which uses a 250-frame default: about 8.3 seconds at 30 fps and 4.2 seconds at 60 fps. Both exceed the two seconds recommended by Apple, YouTube and Amazon IVS, and the 30 fps figure is long enough to break segment alignment on some platforms. Entering 2 fixes the interval in seconds regardless of frame rate.</p><h3 id="what-happens-if-the-keyframe-interval-is-too-high">What happens if the keyframe interval is too high?</h3><p>The visible symptom is usually a frozen or smeared picture at a quality switch, which reads as a network fault and is not one. Amazon IVS documents the cause: segments that do not begin with a keyframe "may result in decode errors or visual distortions" when a viewer starts playback or changes rendition. Viewers also wait longer before playback starts. Set the interval to 2 and turn scene change detection off before investigating bandwidth.</p><h3 id="does-a-shorter-keyframe-interval-reduce-video-quality">Does a shorter keyframe interval reduce video quality?</h3><p>At a fixed bitrate, yes, slightly. Keyframes are the largest frames, so emitting them more often leaves fewer bits for everything else and the picture softens under motion. The effect is small between two and four seconds and grows below one second. Amazon IVS also notes that one-second intervals can increase buffering, because smaller segments make an adaptive player switch rendition more often.</p><h3 id="why-does-my-encoder-produce-keyframes-i-did-not-ask-for">Why does my encoder produce keyframes I did not ask for?</h3><p>Scene-cut detection. Most encoders insert an unscheduled keyframe when the picture changes sharply, so a configured interval is an upper bound rather than a fixed cadence. In x264 the <code>scenecut</code> threshold defaults to 40 and the behaviour is on by default. Amazon IVS asks broadcasters to set scene change detection off, because irregular keyframes disturb the segment pattern its packager relies on.</p>]]></content:encoded></item><item><title><![CDATA[Poor Call Quality: How to Test VoIP & WebRTC Call Quality?]]></title><description><![CDATA[Poor call quality has a cause you can measure. A five-step VoIP and WebRTC call quality test, the thresholds to compare against, a symptom-to-cause table, and fixes for the network, QoS, app settings, and SIP-connected AI voice agents.]]></description><link>https://www.videosdk.live/blog/call-quality-troubleshooting</link><guid isPermaLink="false">6aaba8e5b3240feb748c9efc</guid><category><![CDATA[WebRTC]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 17 Sep 2026 12:13:45 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/17.png" medium="image"/><content:encoded><![CDATA[<blockquote>VoIP call quality is how clearly voice travels over an IP network, and it depends mostly on delay, jitter and packet loss. To fix poor call quality, test the network, read the call's stats against thresholds, and change one variable at a time. VideoSDK's analytics dashboard sets thresholds of 30 ms jitter, 300 ms RTT and 5% packet loss.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/17.png" alt="Poor Call Quality: How to Test VoIP & WebRTC Call Quality?"/><p>A connection can pass a speed test and still carry a robotic-sounding call. Speed tests measure how much data a link moves, but calls suffer when packets arrive late or unevenly.</p><p>This guide gives a five-step test method for VoIP and WebRTC calls and a symptom-to-cause table. It then covers fixes for the network, the app, and SIP-connected AI voice agents.</p><h2 id="what-affects-voip-call-quality">What affects VoIP call quality?</h2><p>VoIP call quality depends on a few network measurements, plus the devices and codecs at each end of the call.</p><p>VoIP call quality is defined as how clearly, completely and promptly speech reaches the listener over an IP network. It works by sending audio in small RTP packets, so any delay, variation or loss between those packets changes what the listener hears.</p><ul><li><strong>Latency and round trip time (RTT).</strong> Latency is the delay from sender to receiver. RTT is the time data takes to reach the server and come back.</li><li><strong>Jitter.</strong> Jitter is the variation in packet arrival times. <a href="https://www.rfc-editor.org/rfc/rfc3550">RFC 3550</a> section 6.4.1 defines how RTP calculates it. Read more in <a href="https://www.videosdk.live/blog/what-is-jitter">what is jitter</a> and <a href="https://www.videosdk.live/blog/what-is-jitter-buffer">what is a jitter buffer</a>.</li><li><strong>Packet loss.</strong> Lost packets leave gaps. The receiver fills small gaps with locally synthesised audio, which the <a href="https://www.w3.org/TR/webrtc-stats/">W3C WebRTC statistics spec</a> counts as concealed samples.</li><li><strong>Bandwidth and CPU.</strong> VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/render-media/understanding-call-quality">call quality guide</a> says low bandwidth causes frozen video and robotic voice. A heavily loaded CPU can also make audio choppy or robotic.</li></ul><p>Together these numbers describe VoIP performance, and every call quality VoIP checklist starts with them. WebRTC calls use the same measures. The table lists the thresholds this guide compares against.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Metric</th>
<th>Threshold</th>
<th>Source</th>
</tr>
</thead>
<tbody>
<tr>
<td>Jitter</td>
<td>30 ms or less</td>
<td><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/render-media/understanding-analytics-dashboard">VideoSDK analytics dashboard</a></td>
</tr>
<tr>
<td>Round trip time (RTT)</td>
<td>300 ms or less</td>
<td>VideoSDK analytics dashboard</td>
</tr>
<tr>
<td>Packet loss</td>
<td>5% or less</td>
<td>VideoSDK analytics dashboard</td>
</tr>
<tr>
<td>One-way, mouth-to-ear delay</td>
<td>Under 150 ms feels transparent; 400 ms is the planning limit</td>
<td><a href="https://www.itu.int/rec/T-REC-G.114">ITU-T G.114 (05/2003)</a></td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>RTT and one-way delay are different measures, and many guides mix them up. RTT covers the trip to the server and back, while G.114 describes the delay a speaker's words take to reach a listener.</p><p>For a single score, mean opinion score (MOS) rates quality from 1 to 5. Our <a href="https://www.videosdk.live/blog/qoe-quality-of-experience">QoE guide</a> explains how MOS relates to these network numbers.</p><h2 id="how-to-test-call-quality">How to test call quality</h2><p>A reliable VoIP call quality test measures the network first, then a real call, and changes only one thing at a time.</p><ol><li><strong>Baseline the network.</strong> Run a speed test and a bufferbloat test on the calling device, once on Wi-Fi and once on Ethernet. Note latency, jitter and upload speed.</li><li><strong>Run a pre-call test or a test call.</strong> In a VideoSDK React app, <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/setup-call/precall"><code>runPreCallTest()</code></a> checks the camera and microphone, then measures audio and video in both directions. It samples for 15 seconds by default.</li><li><strong>Read the call's stats.</strong> In a browser, <a href="https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/getStats"><code>RTCPeerConnection.getStats()</code></a> returns jitter, packets lost, round trip time, concealed samples and <code>qualityLimitationReason</code>. Chrome shows the same data live at chrome://webrtc-internals.</li><li><strong>Compare with the thresholds.</strong> Check each number against the table above. Then compare the sender's graphs with each receiver's graphs to see which side of the call degrades.</li><li><strong>Change one variable and retest.</strong> Swap Wi-Fi for Ethernet or mobile data, then try another device, browser or headset. When the numbers move with one change, you have found the cause.</li></ol><p>The pre-call test returns a score from 1 (bad) to 5 (excellent) for uplink and downlink. It also lists the factors behind the score, such as RTT, packet loss, jitter, frozen video and concealed audio.</p><p>During a call, VideoSDK's <code>getAudioStats()</code> and <code>getVideoStats()</code> return bitrate, jitter, RTT and packet loss for each participant. The dashboard's Session Stats tab graphs those metrics for any sender and receiver, which is how step 4 works in practice.</p><p>A phone call quality test for SIP calls follows the same steps, using the SIP provider's call records instead of browser stats. Tools that check VoIP quality, such as a voice over IP quality test from a phone provider, usually cover only step 1.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/call-quality-troubleshooting-path.png" class="kg-image" alt="Poor Call Quality: How to Test VoIP & WebRTC Call Quality?" loading="lazy" width="2400" height="1400"/></figure><h2 id="symptom-to-cause">Symptom to cause</h2><p>Most call quality complaints match one of a few symptoms, and each symptom points to a short list of causes.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Symptom</th>
<th>Likely cause</th>
<th>What to check</th>
<th>First fix</th>
</tr>
</thead>
<tbody>
<tr>
<td>Robotic, choppy or cutting-out voice</td>
<td>Jitter, packet loss or a busy CPU</td>
<td>Jitter over 30 ms, loss over 5%, rising concealed samples, a <code>cpu</code> limitation</td>
<td>Move to Ethernet, close heavy apps, lower video resolution</td>
</tr>
<tr>
<td>You hear your own voice echo</td>
<td>No echo cancellation, or loud speakers, on the other person's device</td>
<td>The far end's audio settings and headset</td>
<td>Turn on <code>echoCancellation</code>, use headphones</td>
</tr>
<tr>
<td>One-way audio</td>
<td>NAT or firewall blocking media in one direction, or a blocked microphone</td>
<td>Firewall rules, relay use, microphone permission errors</td>
<td>Open the media and TURN ports; for SIP, use symmetric RTP or TURN</td>
</tr>
<tr>
<td>Frozen or blurry video while audio holds</td>
<td>Low bandwidth or a CPU limit on the sender</td>
<td><code>onQualityLimitation</code> type, freezes, bitrate</td>
<td>Keep <code>multiStream</code> on, lower <code>encoderConfig</code>, offer audio-only</td>
</tr>
<tr>
<td>Long pauses, people talking over each other</td>
<td>High RTT from a distant server, a VPN or bufferbloat</td>
<td>RTT over 300 ms, bufferbloat result, region</td>
<td>Use the nearest region, drop the VPN, fix router queueing</td>
</tr>
<tr>
<td>Can't join, or can't rejoin later</td>
<td>Expired or invalid token</td>
<td>Error 4002, <code>INVALID_TOKEN</code></td>
<td>Issue a fresh token before each join</td>
</tr>
<tr>
<td>SIP call drops after about 32 seconds</td>
<td>The caller's final ACK never arrived</td>
<td>A SIP trace with no ACK</td>
<td>Fix NAT handling on the signalling path</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The timing-related failures need more context:</p><ul><li><strong>Token expiry.</strong> VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token">token guide</a> says a token is validated only at join. A token that expires mid-call does not end that call, so a drop at the same minute every time has another cause.</li><li><strong>The 32-second SIP drop.</strong> <a href="https://www.rfc-editor.org/rfc/rfc3261">RFC 3261</a> says the answering side should end the session with a BYE if no ACK arrives within 64 × T1. With T1 at its 500 ms default, that is 32 seconds.</li><li><strong>Drops at a longer fixed interval.</strong> SIP session timers in <a href="https://www.rfc-editor.org/rfc/rfc4028">RFC 4028</a> end a call when a refresh fails. RFC 4028 recommends 1,800 seconds, so check the Session-Expires value.</li></ul><h2 id="is-your-network-causing-poor-call-quality">Is your network causing poor call quality?</h2><p>Your network is causing poor call quality when jitter, RTT or packet loss cross their thresholds while the device's CPU is not the limit.</p><p>The exact warning "Your network is causing poor call quality" appears in Microsoft's Dynamics 365 voice channel. <a href="https://learn.microsoft.com/en-us/troubleshoot/dynamics-365/customer-service/omnichannel-for-customer-service/use-diagnostic-messages-in-call-issues">Microsoft's docs</a> say it shows when incoming or outgoing stream quality is poor, or when the call reconnects.</p><p>To confirm it on your own network, work through these checks:</p><ul><li><strong>Wi-Fi vs wired.</strong> Repeat the test on Ethernet. If jitter and loss drop, the wireless link is the cause, so move closer to the access point or stay wired.</li><li><strong>Bufferbloat.</strong> A router that queues too many packets adds delay whenever the link is busy. Run a <a href="https://www.waveform.com/tools/bufferbloat">bufferbloat test</a> while a large upload runs. Routers that support FQ-CoDel, which <a href="https://www.rfc-editor.org/rfc/rfc8290">RFC 8290</a> describes as a tool for fighting bufferbloat, keep call packets moving.</li><li><strong>Competing traffic.</strong> Cloud backups, uploads and video streams on the same link compete with the call.</li><li><strong>Firewalls and VPNs.</strong> VideoSDK's <a href="https://docs.videosdk.live/help_docs/firewall-setup">firewall guide</a> lists UDP 40000 to 60000 for media with a TCP fallback on those ports. TURN uses UDP and TCP 3478, with TCP 443 as a fallback.</li><li><strong>Network or device?</strong> VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/call-quality/network-quality-monitoring"><code>onQualityLimitation</code></a> event reports <code>bandwidth</code>, <code>congestion</code> or <code>cpu</code>. The first two point to the network, while <code>cpu</code> points to the device.</li></ul><h2 id="quality-of-service-for-voice-over-ip">Quality of service for voice over IP</h2><p>Quality of service (QoS) for voice over IP means marking voice packets so routers forward them ahead of bulk traffic.</p><p><a href="https://www.rfc-editor.org/rfc/rfc8837">RFC 8837</a> says browsers should mark WebRTC audio as Expedited Forwarding (EF, DSCP 46) at medium and high priority. Interactive video gets AF41 to AF43 values. Your router then needs a rule that serves EF packets first on the uplink.</p><p>Wi-Fi needs its own mapping. <a href="https://www.rfc-editor.org/rfc/rfc8325">RFC 8325</a> recommends mapping EF to IEEE 802.11 User Priority 6, which places it in the Voice access category.</p><p>QoS has limits. RFC 8837 notes that networks do not trust endpoint markings and may rewrite them anywhere along the path. Marking still helps on the first hops you control, such as your office LAN and uplink.</p><h2 id="fixes-on-the-application-side">Fixes on the application side</h2><p>When the network checks out and calls still sound poor, the fix usually sits in the app's media settings.</p><ul><li><strong>Run a pre-call test.</strong> Check devices and the network before users join. See <a href="https://www.videosdk.live/blog/precall-integration-in-react-native">pre-call checks in React Native</a> for a mobile example.</li><li><strong>Pick the right codec.</strong> VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/call-quality/video-codecs">video codec guide</a> makes VP8 the default and the fallback. VP9 and AV1 compress better but need more processing and don't support <code>multiStream</code>. Compare them in <a href="https://www.videosdk.live/blog/video-codecs">video codecs explained</a>.</li><li><strong>Cap bitrate to the connection.</strong> Video <code>encoderConfig</code> presets run from 90p to 2160p, each with optimized, balanced and high-quality bitrates. Audio presets run from 16 kbps speech to 192 kbps stereo. See <a href="https://www.videosdk.live/blog/what-is-bitrate">what is bitrate</a>.</li><li><strong>Clean up the audio.</strong> The <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/render-media/optimize-audio-track">speech audio presets</a> turn on echo cancellation, noise suppression and gain control. For more, read <a href="https://www.videosdk.live/blog/noise-suppression">how noise suppression works</a>.</li><li><strong>Use the nearest region.</strong> VideoSDK connects participants to the nearest available server by default. Its <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/geo-fencing-and-proxy-controls/geo-fencing">geo-fencing guide</a> warns that pinning a distant region can hurt quality, so use it only when compliance requires.</li><li><strong>React during the call.</strong> Show a warning when <code>onQualityLimitation</code> fires, and use <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/call-quality/monitoring-transport-stats"><code>getTransportStats()</code></a> for a connection indicator. The docs suggest offering audio-only when a participant's connection weakens.</li></ul><p>These fixes add up. Examedi, a Latin American healthcare company, reports 50% fewer call failures after moving to VideoSDK, according to a <a href="https://www.videosdk.live/customers/examedi">VideoSDK-published case study</a>.</p><p>Want to improve call quality in your own app? <a href="https://app.videosdk.live/login">Create a free VideoSDK account</a>, follow the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a>, then add the pre-call test.</p><h2 id="call-quality-for-sip-and-ai-voice-agents">Call quality for SIP and AI voice agents</h2><p>A SIP call to an AI voice agent has more legs than a browser call, and each leg adds its own delay and failure points.</p><p>The path runs from the caller's phone and carrier to a SIP provider, then to VideoSDK's SIP gateway and room. From there, the AI agent turns speech into text, generates a reply and speaks it.</p><ul><li><strong>Codec on the phone leg.</strong> VoIP quality on this leg depends on the codec. For outbound calls, VideoSDK's <a href="https://docs.videosdk.live/telephony/managing-calls/hd-voice">HD Voice guide</a> says it offers PCMA and PCMU (G.711) first, then Opus. Wideband HD Voice needs the SIP provider to negotiate Opus.</li><li><strong>Measure each leg.</strong> Use the SIP provider's call records for the carrier leg. For the agent, <a href="https://docs.videosdk.live/ai_agents/core-components/pipeline-observability">pipeline metrics hooks</a> report speech-to-text, LLM, text-to-speech and end-of-utterance timings for every turn.</li><li><strong>Watch the agent dashboard.</strong> The <a href="https://docs.videosdk.live/ai_agents/tracing-observability/session-analytics">session analytics view</a> shows time to first word plus P50, P90 and P95 response times.</li><li><strong>Check NAT on the SIP side.</strong> <a href="https://www.rfc-editor.org/rfc/rfc6314">RFC 6314</a> shows how some NATs drop media after a STUN lookup, which leads to one-way audio. TURN relays solve it.</li><li><strong>Denoise before transcription.</strong> Background noise lowers speech-to-text accuracy, so add the <a href="https://docs.videosdk.live/ai_agents/plugins/denoise">denoise plugin</a> at the front of the pipeline.</li></ul><p>To connect a phone number, follow the <a href="https://docs.videosdk.live/react-native/guide/sip-connect/quick-start">SIP connect quick start</a> or the <a href="https://docs.videosdk.live/telephony/introduction">telephony overview</a>.</p><h2 id="definitions-glossary">Definitions glossary</h2><blockquote><strong>Jitter:</strong> The variation in packet arrival times, calculated as defined in RFC 3550. VideoSDK's analytics dashboard uses 30 ms as its threshold.</blockquote><blockquote><strong>Round trip time (RTT):</strong> The time data takes to reach the server and come back. VideoSDK returns it from <code>getAudioStats()</code> and <code>getVideoStats()</code>.</blockquote><blockquote><strong>Packet loss concealment:</strong> Synthesised audio a receiver plays in place of lost packets. The W3C stats API reports it as concealed samples.</blockquote><blockquote><strong>Bufferbloat:</strong> Excess packet queueing in routers that adds delay when a link is busy. FQ-CoDel, described in RFC 8290, is one fix.</blockquote><blockquote><strong>DSCP:</strong> A field in the IP header that marks a packet's traffic class. RFC 8837 recommends EF (46) for WebRTC audio.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>Poor call quality usually comes down to jitter, RTT, packet loss, bandwidth or CPU, not raw download speed.</li><li>Test in five steps: baseline the network, run a test call, read stats, compare with thresholds, change one variable.</li><li>VideoSDK's dashboard thresholds are 30 ms jitter, 300 ms RTT and 5% packet loss.</li><li>QoS markings help on links you control, but networks may rewrite them further along.</li><li>SIP and AI voice agent calls add carrier, codec and pipeline legs that need measuring separately.</li></ul><h2 id="conclusion">Conclusion</h2><p>Poor call quality has a cause you can measure. Baseline the network, read the call's stats, compare them with thresholds, and change one variable at a time until the numbers move. Then fix the network, the app settings, or the SIP leg that caused it.</p><p>To add pre-call tests and live quality alerts to your app, start with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a>. <a href="https://app.videosdk.live/login">Sign up for VideoSDK</a> with <a href="https://www.videosdk.live/pricing">$20 free credit</a>.</p><p>Which call quality problem is hardest to track down in your app? Tell us in the comments.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="how-do-you-test-voip-call-quality">How do you test VoIP call quality?</h3><p>To test VoIP call quality, run a speed and bufferbloat test, then place a real test call and read its jitter, RTT and packet loss. Compare them with thresholds, such as 30 ms jitter, 300 ms RTT and 5% loss. Change one variable at a time to find the cause.</p><h3 id="what-are-good-jitter-latency-and-packet-loss-numbers-for-voip">What are good jitter, latency and packet loss numbers for VoIP?</h3><p>Good VoIP numbers stay within 30 ms of jitter, 300 ms of RTT and 5% packet loss, the thresholds in VideoSDK's analytics dashboard. ITU-T G.114 adds that one-way, mouth-to-ear delay under 150 ms feels transparent for most calls.</p><h3 id="why-does-my-voip-call-sound-robotic">Why does my VoIP call sound robotic?</h3><p>A VoIP call sounds robotic when packets arrive late or go missing, so the receiver fills the gaps with synthesised audio. High jitter, packet loss, low bandwidth and a busy CPU are the usual causes. Try a wired connection and close heavy apps.</p><h3 id="why-can-only-one-person-hear-on-a-call">Why can only one person hear on a call?</h3><p>One-way audio usually means media is blocked in one direction by a NAT or firewall, or a microphone is muted or blocked. Check firewall rules for media and TURN ports, check microphone permissions, and for SIP calls use symmetric RTP or TURN.</p><h3 id="what-does-your-network-is-causing-poor-call-quality-mean">What does "your network is causing poor call quality" mean?</h3><p>"Your network is causing poor call quality" is a Microsoft Dynamics 365 warning shown when incoming or outgoing stream quality is poor, or when the call reconnects. It means the problem is the connection, not the app, so try a better network.</p><h3 id="does-qos-improve-voip-call-quality">Does QoS improve VoIP call quality?</h3><p>Yes, QoS improves VoIP call quality on links that honour it, by forwarding voice packets ahead of bulk traffic. RFC 8837 recommends marking WebRTC audio as EF (46). Networks may rewrite markings, so QoS helps most on your own LAN and uplink.</p><h3 id="how-can-i-improve-call-quality-in-a-voice-or-video-app">How can I improve call quality in a voice or video app?</h3><p>To improve call quality in a voice or video app, run a pre-call test, pick a suitable codec, and cap bitrate to the connection. Also turn on echo cancellation and noise suppression, connect users to the nearest region, and warn them when quality drops.</p>]]></content:encoded></item><item><title><![CDATA[Noise Suppression for Voice & Video Calls]]></title><description><![CDATA[Noise suppression removes background sound from a microphone signal while keeping the voice. How classic and AI denoisers work, how they differ from noise reduction, echo cancellation and gain control, and how to add noise suppression in the browser, in mobile apps and with VideoSDK.]]></description><link>https://www.videosdk.live/blog/noise-suppression</link><guid isPermaLink="false">6aab97b9b3240feb748c9ef1</guid><category><![CDATA[WebRTC]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 17 Sep 2026 12:13:09 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/16.png" medium="image"/><content:encoded><![CDATA[<blockquote>Noise suppression is audio processing that removes background sound, such as fans, traffic and keyboard clicks, from a microphone signal while keeping the speech. Browsers offer a basic version through the WebRTC noiseSuppression constraint. VideoSDK adds an AI noise suppressor (BETA) for web and Flutter calling apps.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/16.png" alt="Noise Suppression for Voice & Video Calls"/><p>A fan or a busy street can make a speaker hard to follow on a call. The listener cannot fix it, because the noise arrives inside the audio.</p><p>This guide explains what noise suppression means, how it compares with echo cancellation and gain control, and how classic and AI denoisers work. It then shows how to add it in the browser, with VideoSDK's AI noise suppressor for React, and in mobile calling apps.</p><h2 id="what-is-noise-suppression">What is noise suppression?</h2><p>Noise suppression is defined as the real-time removal of unwanted background sound from a speech signal, so the other people on a call hear mainly the voice.</p><p>Noise suppression works by splitting the microphone signal into short frames, estimating how much of each frequency is noise, and turning those parts down while leaving speech mostly intact.</p><p>So the plain noise suppression meaning is: keep the voice, lower everything else. What does noise suppression do on a call? It cleans the audio you send, so other participants hear less of your room. It does not change the audio you receive from them.</p><p>The <a href="https://www.w3.org/TR/mediacapture-streams/">W3C Media Capture and Streams specification</a> treats audio noise suppression as a microphone setting that apps can switch on or off, since some cases need unaltered audio. Searchers also spell it "noise supression" or "noise suppresion".</p><h3 id="stationary-and-non-stationary-noise">Stationary and Non-stationary noise</h3><p>Stationary noise sounds roughly the same over time, like an air conditioner or electrical hum. Non-stationary noise changes quickly, like keyboard clicks, a barking dog or other people talking.</p><p>Classic algorithms handle stationary noise well because they learn its profile during pauses. Non-stationary noise is where AI models help most, because it changes faster than a simple running estimate.</p><h3 id="noise-suppression-vs-noise-cancellation">Noise suppression vs noise cancellation</h3><p>Noise suppression cleans the audio a microphone sends, which helps your listeners. Active noise cancellation in headphones plays inverted sound into your ears, which helps you.</p><h3 id="what-does-denoise-mean">What does denoise mean?</h3><p>To denoise audio is to run noise suppression on it. Research papers and audio libraries often call the component that does this a denoiser.</p><h2 id="noise-suppression-vs-noise-reduction-vs-echo-cancellation-vs-gain-control">Noise suppression vs Noise reduction vs Echo cancellation vs Gain control</h2><p>Noise suppression, noise reduction, echo cancellation and automatic gain control are separate jobs that often run together on one microphone signal.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Process</th>
<th>What it removes or changes</th>
<th>Where it runs in a call</th>
<th>WebRTC constraint</th>
</tr>
</thead>
<tbody>
<tr>
<td>Noise suppression</td>
<td>Background noise such as fans, hum, traffic and typing</td>
<td>On the sender's microphone signal, before encoding</td>
<td><code>noiseSuppression</code></td>
</tr>
<tr>
<td>Noise reduction</td>
<td>Any unwanted noise; the umbrella term for software, filter and hardware methods</td>
<td>Microphones, headsets, and sender or receiver software</td>
<td>None of its own; browsers expose <code>noiseSuppression</code></td>
</tr>
<tr>
<td>Echo cancellation</td>
<td>Far-end voices that leak from your speaker back into your microphone</td>
<td>On the sender, using the audio being played out as a reference</td>
<td><code>echoCancellation</code></td>
</tr>
<tr>
<td>Automatic gain control</td>
<td>Volume swings; it brings speech to a steady level</td>
<td>On the sender, after echo cancellation and noise suppression</td>
<td><code>autoGainControl</code></td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>What does noise reduction do that noise suppression does not? It is the broader term, covering every way of lowering noise, from microphone design to software. Product copy also says noise filtering or noise removal.</p><p>In the open-source WebRTC engine, these steps live in one audio processing module. Its <a href="https://webrtc.googlesource.com/src/+/refs/heads/main/api/audio/audio_processing.h">public header</a> says the module takes audio in chunks of about 10 ms. It offers four suppression levels, from low to very high, with moderate as the default. Its adaptive digital gain controller runs after echo cancellation and noise suppression, so it does not boost the noise along with the voice.</p><h2 id="how-noise-suppression-works">How noise suppression works</h2><p>Every noise suppressor runs the same loop on each short frame of audio: estimate the noise, decide how far to turn each frequency down, and rebuild the frame.</p><ol><li><strong>Frame the signal.</strong> Audio is cut into short frames, about 10 ms each in WebRTC's audio module, and converted to the frequency domain.</li><li><strong>Estimate the noise.</strong> The suppressor judges which parts of the spectrum are noise, often by tracking the signal during pauses in speech.</li><li><strong>Compute gains.</strong> Each frequency bin or band gets a gain between zero and one. Bins dominated by noise get low gains.</li><li><strong>Apply and rebuild.</strong> The gains are applied, and the frame is converted back to a waveform for the encoder.</li></ol><p>Classic and AI noise reduction techniques differ mainly in steps 2 and 3. The diagram below compares the two pipelines and shows where VideoSDK's web suppressor fits.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/noise-suppression-pipeline-1.png" class="kg-image" alt="Noise Suppression for Voice & Video Calls" loading="lazy" width="2400" height="1320"/></figure><h3 id="classic-noise-suppression-spectral-subtraction-and-wiener-filtering">Classic noise suppression: Spectral subtraction and Wiener filtering</h3><p>Classic noise suppression uses hand-designed statistics to estimate noise and compute gains, with no training data. These are the three noise reduction methods most later work builds on.</p><ul><li><strong>Spectral subtraction.</strong> Steven Boll's <a href="https://doi.org/10.1109/TASSP.1979.1163209">1979 paper</a> estimates the noise spectrum during non-speech periods and subtracts it from the noisy spectrum. It is cheap, but aggressive subtraction leaves short tonal blips, often called musical noise.</li><li><strong>Wiener filtering.</strong> A Wiener filter scales each frequency by an estimate of how much of it is speech rather than noise. Lim and Oppenheim's <a href="https://doi.org/10.1109/PROC.1979.11540">1979 review</a> covers it among the main speech enhancement methods.</li><li><strong>MMSE amplitude estimation.</strong> Ephraim and Malah's <a href="https://doi.org/10.1109/TASSP.1984.1164453">1984 estimator</a> predicts the clean speech amplitude in each frequency. It remains a standard baseline for newer methods.</li></ul><p>This family still ships today. WebRTC's open-source noise suppressor includes a <a href="https://webrtc.googlesource.com/src/+/refs/heads/main/modules/audio_processing/ns/wiener_filter.h">Wiener filter</a>, alongside a quantile-based noise estimator and a speech probability estimator.</p><p>The weakness is the assumption that noise changes slowly. Classic suppressors struggle with clicks, barks and background voices, and pushing them harder damages the speech.</p><h3 id="ai-noise-suppression-rnnoise-and-deep-learning">AI noise suppression: RNNoise and Deep Learning</h3><p>AI noise suppression replaces hand-tuned estimates with a neural network trained on pairs of noisy and clean speech.</p><p>RNNoise is an open-source example built for real-time calls. Jean-Marc Valin describes it in a <a href="https://arxiv.org/abs/1709.08243">2017 paper</a>, presented at MMSP 2018, as a hybrid of signal processing and deep learning. His <a href="https://jmvalin.ca/demo/rnnoise/">RNNoise demo page</a> explains the design:</p><ul><li>The network works on 22 bands on the Bark scale instead of 480 spectral values, much like a 22-band equaliser.</li><li>It takes 42 input features, and most of the work happens in three GRU layers. A GRU is a recurrent layer that carries memory from frame to frame.</li><li>It outputs a gain for each band plus a voice activity probability.</li><li>A pitch filter removes noise between the harmonics of the voice, which the coarse bands cannot resolve.</li><li>Look-ahead is limited to 10 ms to suit real-time communication.</li></ul><p>The paper reports clearly higher quality than a traditional MMSE spectral estimator while running in real time at 48 kHz on a low-power processor.</p><p>To compare AI denoisers, Microsoft ran the Deep Noise Suppression (DNS) Challenge. The <a href="https://arxiv.org/abs/2303.11510">ICASSP 2023 edition</a>, its fifth, used fullband 48 kHz audio, headset and speakerphone tracks, and listening tests. The organisers found that improving speech quality was hard when noise and interfering talkers appeared together. For automated scoring, Microsoft also published <a href="https://arxiv.org/abs/2010.15258">DNSMOS</a> in 2020, a metric that predicts listener ratings without a clean reference.</p><p>For a longer look at neural models, read <a href="https://www.videosdk.live/developer-hub/ai/ai-noise-cancellation">AI noise cancellation for real-time apps</a>.</p><h3 id="trade-offs-to-test-before-shipping">Trade-offs to test before shipping</h3><p>Stronger noise suppression is not always better. Check these before you ship:</p><ul><li><strong>Over-suppression.</strong> Aggressive settings can clip soft word endings or make voices sound thin.</li><li><strong>Music.</strong> A speech-tuned suppressor may treat instruments as noise.</li><li><strong>Overlapping talkers.</strong> A second voice is speech too, and DNS 2023 shows this case is still hard.</li><li><strong>Device load.</strong> Client-side models use CPU on every participant's device.</li><li><strong>Stacking.</strong> Browser and AI suppressors can both process one track, so compare the result with each on and off.</li></ul><h2 id="adding-noise-suppression-in-the-browser">Adding noise suppression in the browser</h2><p>Browsers that support it expose noise suppression as an audio constraint on <code>getUserMedia()</code>, so a web app can request it without extra libraries. This short snippet asks for all three voice processing steps and then logs whether noise suppression was applied.</p><pre><code class="language-javascript">const stream = await navigator.mediaDevices.getUserMedia({
  audio: {
    noiseSuppression: true,
    echoCancellation: true,
    autoGainControl: true,
  },
});

const [track] = stream.getAudioTracks();
console.log(track.getSettings().noiseSuppression);
</code></pre><p>Three rules from <a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints/noiseSuppression">MDN's constraint reference</a> shape how this behaves:</p><ul><li><strong><code>true</code> is a request, not a demand.</strong> The browser tries to apply it, and the call still succeeds if it cannot. Use <code>{ exact: true }</code> if you would rather the request fail.</li><li><strong>Check what you got.</strong> <a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackSettings/noiseSuppression"><code>getSettings()</code></a> reports what was applied, and <a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getSupportedConstraints"><code>getSupportedConstraints()</code></a> shows whether the browser knows the constraint.</li><li><strong>Support is uneven.</strong> MDN marks <code>noiseSuppression</code> as limited availability, not Baseline, because it does not work in some widely used browsers.</li></ul><p>The constraint is also on or off only. You cannot pick a strength or an algorithm, and results differ between browsers. Treat built-in background noise suppression as a basic first layer.</p><p>VideoSDK's React SDK exposes the same three settings through <a href="https://docs.videosdk.live/react/api/sdk-reference/custom-tracks"><code>createMicrophoneAudioTrack()</code></a>. Its default <code>speech_standard</code> preset turns all three on, while <code>music_standard</code> and the higher-bitrate presets turn them off. A <code>noiseConfig</code> object sets each one directly.</p><h2 id="adding-ai-noise-suppression-with-videosdk">Adding AI noise suppression with VideoSDK</h2><p>VideoSDK's AI noise suppressor is a separate web package, labelled BETA in the docs, that cleans a microphone stream before your app publishes it. The <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/plugins/noise-suppresion">React noise suppression guide</a> covers it in three steps.</p><p>You need a working VideoSDK meeting first. <a href="https://app.videosdk.live/login">Sign up for VideoSDK</a> and follow the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a>, then add the steps below.</p><p><strong>1. Install the package.</strong></p><pre><code class="language-bash">npm install --save "@videosdk.live/videosdk-noise-suppressor-web"
</code></pre><p>The guide notes that the older <code>@videosdk.live/videosdk-media-processor-web</code> package will get no new versions, so use this one.</p><p><strong>2. Import and create the suppressor.</strong> Import <code>VideoSDKNoiseSuppressor</code> from the new package, and <code>useMeeting</code> and <code>createMicrophoneAudioTrack</code> from <code>@videosdk.live/react-sdk</code>. The suppressor is created inside your meeting component.</p><p><strong>3. Process the mic stream and swap it in.</strong> This block is the guide's example:</p><pre><code class="language-jsx">const MeetingView = () =&gt;{
  // Instantiate VideoSDKNoiseSuppressor Class
  const noiseProcessor = new VideoSDKNoiseSuppressor();
  const { changeMic } = useMeeting({});
  const handleStartNoiseSuppression = async () =&gt; {
    // Getting stream from mic
    const stream = await createMicrophoneAudioTrack({});
    const processedStream = await noiseProcessor.getNoiseSuppressedAudioStream(
      stream
    );
    try {
      await changeMic(processedStream);
    } catch (err) {
      console.error("changeMic failed:", err);
    }
  };
  const handleStopNoiseSuppression = () =&gt; {};
  return &lt;&gt;...&lt;/&gt;;
}
</code></pre><p><code>createMicrophoneAudioTrack({})</code> captures the microphone, and <code>getNoiseSuppressedAudioStream()</code> returns a noise-suppressed copy of that stream. <code>changeMic()</code> publishes it, and the guide says <code>enableMic()</code> and <code>toggleMic()</code> accept it too. <code>return &lt;&gt;...&lt;/&gt;</code> stands in for your own buttons.</p><p>To stop noise suppression, call <code>changeMic()</code> again with a fresh stream from <code>createMicrophoneAudioTrack({})</code>. To join with clean audio from the start, pass the processed stream as <code>customMicrophoneAudioTrack</code> in the <code>MeetingProvider</code> config, as the guide's Extras section shows.</p><p>As of September 2026, the <a href="https://www.npmjs.com/package/@videosdk.live/videosdk-noise-suppressor-web">npm package</a> is at version 0.1.0. It lists one dependency, <a href="https://github.com/shiguredo/rnnoise-wasm"><code>@shiguredo/rnnoise-wasm</code></a>, a WebAssembly build of RNNoise.</p><p>Not using React? The <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/plugins/noise-suppresion">JavaScript</a> and <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/plugin/noise-suppresion">Flutter</a> SDKs have their own guides. For live streams, see <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/ai-noise-suppression">AI noise suppression for interactive live streaming</a>. VideoSDK Prebuilt has an <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/features/noise-removal">AI Noise Removal (BETA)</a> option in its microphone settings from version 0.3.21.</p><h2 id="adding-noise-suppression-in-mobile-calling-apps">Adding noise suppression in mobile calling apps</h2><p>Mobile operating systems ship their own voice processing, so check it before adding another suppressor.</p><ul><li><strong>Android.</strong> The <a href="https://developer.android.com/reference/android/media/audiofx/NoiseSuppressor"><code>NoiseSuppressor</code></a> class attaches the platform's suppressor to an <code>AudioRecord</code> session. Android's reference names voice chat, video conferencing and SIP calls as its main uses. Some devices insert it by default, so call <code>getEnable()</code> to check.</li><li><strong>iPhone, iPad and Mac.</strong> From iOS 15 and macOS 12, users pick a <a href="https://developer.apple.com/documentation/avfoundation/avcapturedevice/microphonemode">microphone mode</a> in Control Center. <code>voiceIsolation</code> isolates the voice and turns down other sounds, while <code>wideSpectrum</code> keeps every sound. An app cannot set the mode, but it can read <code>preferredMicrophoneMode</code> and open the panel with <code>showSystemUserInterface(_:)</code>.</li></ul><p>VideoSDK's <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/render-media/optimize-audio-track">Android</a>, <a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/render-media/optimize-audio-track">iOS</a>, <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/render-media/optimize-audio-track">React Native</a> and <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/render-media/optimize-audio-track">Flutter</a> SDKs use the same encoder presets as the web SDK. <code>speech_low_quality</code> and <code>speech_standard</code> turn noise suppression on, while <code>music_standard</code> and the higher presets turn it off.</p><h2 id="which-noise-suppression-option-should-you-use">Which noise suppression option should you use?</h2><p>The right noise suppression option depends on your platform and how much control you need. If you are deciding how to suppress noise in your product, start here.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Option</th>
<th>Good fit</th>
<th>Control</th>
<th>Where it runs</th>
</tr>
</thead>
<tbody>
<tr>
<td>Browser <code>noiseSuppression</code> constraint</td>
<td>Web calls that need a basic first layer</td>
<td>On or off only</td>
<td>The user's browser</td>
</tr>
<tr>
<td>VideoSDK noise suppressor (BETA)</td>
<td>Web and Flutter apps that want an AI suppressor</td>
<td>Start and stop from your app</td>
<td>Your app, before publishing</td>
</tr>
<tr>
<td>VideoSDK speech presets</td>
<td>Any VideoSDK calling app</td>
<td>On or off per track</td>
<td>The user's device</td>
</tr>
<tr>
<td>VideoSDK Prebuilt AI Noise Removal (BETA)</td>
<td>Teams using the Prebuilt UI</td>
<td>A user option in microphone settings</td>
<td>Prebuilt 0.3.21 and later</td>
</tr>
<tr>
<td>Android <code>NoiseSuppressor</code></td>
<td>Native Android apps using <code>AudioRecord</code></td>
<td>On or off per session</td>
<td>Android's audio framework</td>
</tr>
<tr>
<td>Apple microphone modes</td>
<td>Calls on iPhone, iPad and Mac</td>
<td>Set by the user</td>
<td>The operating system</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>If you are still choosing a voice SDK, compare options in our <a href="https://www.videosdk.live/blog/10-best-audio-calling-api">guide to voice call APIs</a>.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Noise suppression:</strong> Real-time removal of background sound from a speech signal. Browsers expose it as the <code>noiseSuppression</code> constraint, and VideoSDK web apps can add its AI noise suppressor (BETA).</blockquote><blockquote><strong>Spectral subtraction:</strong> A classic method that estimates the noise spectrum during pauses and subtracts it from each frame. Steven Boll published it in 1979.</blockquote><blockquote><strong>Wiener filter:</strong> A filter that scales each frequency by how likely it is to be speech. WebRTC's open-source noise suppressor includes one.</blockquote><blockquote><strong>RNNoise:</strong> An open-source noise suppressor that pairs signal processing with a small recurrent neural network. VideoSDK's web noise suppressor package depends on a WebAssembly build of it.</blockquote><blockquote><strong>Echo cancellation:</strong> Removal of far-end audio that loops from a speaker back into a microphone. Browsers expose it as the <code>echoCancellation</code> constraint.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>Noise suppression removes background sound from the speech you send, while noise reduction is the broader term.</li><li>Echo cancellation and automatic gain control are separate steps with their own WebRTC constraints.</li><li>Classic suppressors rely on statistics such as spectral subtraction and Wiener filters, while AI suppressors such as RNNoise learn the gains.</li><li>The browser constraint is basic, on or off only, and its support varies by browser.</li><li>VideoSDK offers an AI noise suppressor (BETA) for web and Flutter apps, and its speech presets turn on built-in noise suppression in every SDK.</li><li>On mobile, Android's <code>NoiseSuppressor</code> and Apple's microphone modes add platform-level options.</li></ul><h2 id="conclusion">Conclusion</h2><p>Noise suppression decides whether a call sounds like a quiet room or a busy street. Start with the browser's <code>noiseSuppression</code> constraint or your SDK's speech preset, and add an AI suppressor when the built-in result is not enough. On mobile, check the operating system's own processing first.</p><p>To try VideoSDK's AI noise suppressor, follow the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a> and add the three steps above. <a href="https://app.videosdk.live/login">Sign up for VideoSDK</a> with <a href="https://www.videosdk.live/pricing">$20 free credit</a>.</p><p>Which kind of noise causes the most trouble on your calls? Tell us in the comments.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-noise-suppression-1">What is noise suppression?</h3><p>Noise suppression is audio processing that removes background sound from a microphone signal in real time while keeping the voice. Calling apps apply it before the audio is sent, so other people hear less of your room. Browsers expose it as the WebRTC noiseSuppression constraint.</p><h3 id="what-does-noise-suppression-do">What does noise suppression do?</h3><p>Noise suppression lowers background sounds such as fans, hum, traffic and typing in the audio you send. It estimates which frequencies are noise and turns them down, frame by frame. It does not change the audio you receive, and it does not remove echo.</p><h3 id="what-is-the-difference-between-noise-suppression-and-noise-cancellation">What is the difference between noise suppression and noise cancellation?</h3><p>Noise suppression and active noise cancellation solve different problems. Suppression cleans your microphone audio so listeners hear less background sound. Active noise cancellation in headphones plays inverted sound so you hear less of your surroundings. Product names often use the two terms loosely.</p><h3 id="what-is-noise-reduction">What is noise reduction?</h3><p>Noise reduction is the umbrella term for any method that lowers unwanted sound, from microphone design to software filters. Noise suppression is the real-time software form used in calls. Noise control is broader still, covering noise at its source, along its path and at the listener.</p><h3 id="what-is-dynamic-noise-reduction">What is dynamic noise reduction?</h3><p>Dynamic noise reduction (DNR) is a playback technique for tape and FM audio, not a call feature. Texas Instruments' LM1894 DNR chip, for example, uses psychoacoustic masking and an adaptive bandwidth scheme, with no specially encoded source needed.</p><h3 id="how-do-you-suppress-noise-in-a-web-app">How do you suppress noise in a web app?</h3><p>To suppress noise in a web app, request <code>noiseSuppression: true</code> in <code>getUserMedia()</code> for the browser's built-in filter. For AI noise suppression, VideoSDK's React SDK can pass the mic stream through its noise suppressor (BETA) and publish it with <code>changeMic()</code>.</p><h3 id="should-noise-suppression-always-be-on">Should noise suppression always be on?</h3><p>No, noise suppression should not always be on. The W3C specification notes that some apps need unaltered audio, such as music. Strong settings can also clip soft speech. Let users switch it off, and check <code>getSettings()</code> to confirm what the browser applied.</p>]]></content:encoded></item><item><title><![CDATA[What Is QoE (Quality of Experience)? QoE vs QoS, MOS Explained]]></title><description><![CDATA[QoE, or quality of experience, is what the participant took away from a call, while QoS is what the network delivered. The ITU definition, a QoE vs QoS table, the metrics that matter for real-time video, and three ways to measure QoE in production.]]></description><link>https://www.videosdk.live/blog/qoe-quality-of-experience</link><guid isPermaLink="false">6aaa55b2b3240feb748c9e57</guid><category><![CDATA[WebRTC]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 16 Sep 2026 12:33:21 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/13.png" medium="image"/><content:encoded><![CDATA[<blockquote>QoE, or quality of experience, is defined by ITU-T P.10/G.100 as the degree of delight or annoyance of the user of an application or service. For a video call, QoE is the call as the participant actually felt it. VideoSDK reports the session metrics behind that feeling, including jitter, round trip time and packet loss.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/13.png" alt="What Is QoE (Quality of Experience)? QoE vs QoS, MOS Explained"/><p>Two people finish a call. One says it was fine. The other says the video kept stalling. The graphs for that session look almost identical, because both were on the same office wifi.</p><p>That gap is the problem QoE exists to describe. Packet counters tell you what the network did. They do not tell you whether anyone could hold a conversation. This guide covers the QoE definition, how it differs from QoS, the metrics that matter for calls, and the three ways teams measure it with VideoSDK.</p><h2 id="what-is-qoe-quality-of-experience">What is QoE (quality of experience)?</h2><p>QoE is defined as the degree of delight or annoyance of the user of an application or service.</p><p>That wording is the formal definition in <a href="https://www.itu.int/rec/T-REC-P.10">Recommendation ITU-T P.10/G.100</a>, clause 6.209. The Recommendation is the ITU vocabulary for performance, quality of service and quality of experience, and the edition in force is dated November 2017.</p><p>QoE works by combining what the system delivered with what the person expected. Clause 6.210 lists the influencing factors. They include the type of application, the context of use, whether the user's expectations were met, cultural background and emotional state.</p><p>A blurry frame during a family catch-up is a shrug. The same frame during a remote medical consultation is a failure. That is why QoE cannot be read off a router.</p><h3 id="where-the-quality-of-experience-definition-comes-from">Where the quality of experience definition comes from</h3><p>The ITU adopted the quality of experience definition from academic work rather than writing it fresh. Clause 6.209 credits the Qualinet White Paper on Definitions of Quality of Experience, produced at the fifth Qualinet meeting in Novi Sad in March 2013.</p><p>The Recommendation attaches a note to it. The definition is described as a working one, expected to keep evolving as research continues. Anyone citing a fixed, final QoE definition is overstating the standard.</p><p>Standards writers use both word orders. P.10/G.100 heads clause 6.209 with quality of experience QoE, and its abbreviations list reverses that to QoE quality of experience. Both point at the same entry.</p><h2 id="qoe-vs-qos-what-each-one-measures">QoE vs QoS: What each one measures?</h2><p>QoS describes what the network delivered. QoE describes what the person got out of it.</p><p><a href="https://www.itu.int/rec/T-REC-E.800">Recommendation ITU-T E.800</a> defines quality of service as the totality of characteristics of a telecommunications service that bear on its ability to satisfy stated and implied user needs. Clause 6.212 of P.10/G.100 repeats that definition and points back to E.800. The two terms live in one vocabulary because one feeds the other.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th/>
<th>QoE</th>
<th>QoS</th>
</tr>
</thead>
<tbody>
<tr>
<td>What is measured</td>
<td>How the call felt to the participant</td>
<td>How the network and service performed</td>
</tr>
<tr>
<td>Who reports it</td>
<td>The user, through a rating or an action</td>
<td>The network, the server and the client SDK</td>
</tr>
<tr>
<td>Example metrics</td>
<td>MOS, post-call rating, call abandoned, meeting rejoined</td>
<td>Jitter, round trip time, packet loss, bitrate, frame rate</td>
</tr>
<tr>
<td>Where it is collected</td>
<td>Surveys, in-app rating prompts, product analytics</td>
<td>Client stats APIs, media servers, session dashboards</td>
</tr>
<tr>
<td>Where it falls short</td>
<td>Small samples, late ratings, users rarely explain why</td>
<td>Green metrics on a call the user hated, no view of expectation</td>
</tr>
<tr>
<td>How they relate</td>
<td>QoE is the outcome</td>
<td>QoS is the strongest lever you control</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The fifth row is the one that costs teams time. Good QoS numbers do not guarantee good QoE, but bad QoS numbers almost always produce bad QoE. So instrument the technical side heavily, then use a small amount of user feedback to check whether the two pictures agree.</p><h3 id="network-quality-of-experience-is-only-half-the-picture">Network quality of experience is only half the picture</h3><p>The phrase network quality of experience is common, and slightly misleading. The network is one influencing factor among the several that clause 6.210 lists.</p><p>A call can be ruined by a saturated uplink. It can equally be ruined by a laptop pinned at 100% CPU, a cheap microphone, an echo, or a badly lit room. Network fixes only move the metrics they touch.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/qoe-measurement-layers.png" class="kg-image" alt="What Is QoE (Quality of Experience)? QoE vs QoS, MOS Explained" loading="lazy" width="2400" height="1560"/></figure><h2 id="qoe-metrics-for-real-time-video">QoE metrics for real-time video</h2><p>Every QoE metric for a call is either something the user reported or something the client measured while media was flowing.</p><p>The metric definitions below come from the W3C specification <a href="https://www.w3.org/TR/webrtc-stats/">Identifiers for WebRTC's Statistics API</a>, a Candidate Recommendation Draft dated 25 September 2025. It defers to <a href="https://www.rfc-editor.org/rfc/rfc3550">RFC 3550</a> for jitter and loss. The flag values come from VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/render-media/understanding-analytics-dashboard">analytics dashboard documentation</a>, updated 10 July 2026.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Metric</th>
<th>What it measures</th>
<th>Documented flag</th>
<th>Source of the flag</th>
</tr>
</thead>
<tbody>
<tr>
<td>MOS</td>
<td>Average of user ratings on a five-point scale</td>
<td>5 excellent, 4 good, 3 fair, 2 poor, 1 bad</td>
<td>ITU-T P.800, Annex B.4.5</td>
</tr>
<tr>
<td>Jitter</td>
<td>Variation in packet arrival, in seconds</td>
<td>30 ms or less</td>
<td>VideoSDK analytics docs</td>
</tr>
<tr>
<td>Round trip time</td>
<td>Time for data to reach the server and come back</td>
<td>300 ms or less</td>
<td>VideoSDK analytics docs</td>
</tr>
<tr>
<td>Packet loss</td>
<td>Share of RTP packets that never arrived</td>
<td>5% or less</td>
<td>VideoSDK analytics docs</td>
</tr>
<tr>
<td>Video freezes</td>
<td>Gap between two consecutively rendered frames</td>
<td>No published threshold, count them per session</td>
<td>W3C webrtc-stats defines the freeze</td>
</tr>
<tr>
<td>Resolution and frame rate</td>
<td>Sharpness and smoothness, video only</td>
<td>No published threshold, compare sender against receiver</td>
<td>VideoSDK analytics docs</td>
</tr>
<tr>
<td>Joining time</td>
<td>Time the participant took to establish the connection</td>
<td>No published threshold, watch the distribution</td>
<td>VideoSDK session overview</td>
</tr>
<tr>
<td>Session errors</td>
<td>Network issues and connection disruptions</td>
<td>Any error is worth reading</td>
<td>VideoSDK Errors tab</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Those three VideoSDK numbers are dashboard triage flags, not service guarantees.</p><h3 id="why-a-jitter-number-needs-context">Why a jitter number needs context?</h3><p>RFC 3550 is unusually direct about the limits of the jitter it defines. It describes the interarrival jitter field as a snapshot at the time of a report, and says it is not intended to be taken quantitatively.</p><p>It is meant for comparison, across reports from one receiver over time or across receivers at the same moment. A single jitter reading in isolation proves very little.</p><p>The same section gives jitter a job packet loss cannot do. Loss tracks persistent congestion, jitter tracks transient congestion, and jitter can show congestion before it turns into loss. Watching jitter is how you see trouble arriving.</p><h3 id="what-counts-as-a-video-freeze">What counts as a video freeze?</h3><p>Freezes are the one QoE metric with a precise published formula, and almost nobody quotes it.</p><p>The W3C webrtc-stats specification defines <code>freezeCount</code> for inbound video. A freeze is counted when the gap between two consecutively rendered frames reaches Max(3 x avg_frame_duration_ms, avg_frame_duration_ms + 150). That average is taken over the last 30 rendered frames.</p><p>The threshold is whichever of the two is larger. At 30 frames per second the average frame lasts about 33 ms, so a freeze starts at a gap of about 183 ms. The three-times rule only takes over below about 13 frames per second. The spec pairs the count with <code>totalFreezesDuration</code>, so you can report how often video stalled and for how long.</p><p>VideoSDK surfaces the same idea as an event. The <a href="https://docs.videosdk.live/react/api/sdk-reference/use-stream/events">onStreamStateChanged callback</a> fires for a remote participant's video or screen share, reporting <code>active</code>, <code>stuck</code>, <code>freeze-detected</code>, <code>freeze-resolved</code> or <code>ended</code>.</p><h2 id="how-to-measure-qoe-three-methods">How to measure QoE: three methods</h2><p>There are three practical ways to measure QoE, and production teams end up running all three.</p><h3 id="subjective-mos-from-user-ratings">Subjective: MOS from user ratings</h3><p>The mean opinion score is the oldest QoE measure still in daily use. <a href="https://www.itu.int/rec/T-REC-P.800">Recommendation ITU-T P.800</a>, dated August 1996, sets the listening-quality scale in Annex B.4.5. Excellent scores 5, Good 4, Fair 3, Poor 2 and Bad 1, and the arithmetic mean of those scores is the MOS.</p><p>Two limits matter before you ship a five-star widget. P.800 describes laboratory methods for speech, under controlled conditions, with screened subjects. Video has its own Recommendation, <a href="https://www.itu.int/rec/T-REC-P.910">ITU-T P.910</a>, whose current edition is dated July 2026.</p><p>A rating prompt after a call is therefore a MOS-like signal rather than a P.800 MOS. It is still the most direct read you will get on whether the call worked.</p><h3 id="objective-stats-from-the-session">Objective: stats from the session</h3><p>Objective measurement means reading what the client already knows. VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/render-media/understanding-call-quality">call quality guide</a> documents four participant methods: <code>getVideoStats()</code>, <code>getAudioStats()</code>, <code>getShareStats()</code> and <code>getShareAudioStats()</code>.</p><p>The video and screen share versions return resolution, frame rate, bitrate, jitter, round trip time and packet loss. The audio versions return bitrate, jitter, round trip time and packet loss. A separate <code>getTransportStats()</code> returns aggregate uplink and downlink bitrate in kbps.</p><h3 id="hybrid-ratings-joined-to-stats">Hybrid: ratings joined to stats</h3><p>The useful measurement is the join. A rating alone says a call was bad. A stats trace alone says the uplink was congested. Together they say that congested uplinks are what your users call bad.</p><p>VideoSDK gives you the key for that join. Every session has a <code>sessionId</code> and every participant an ID, both shown in the session overview. A rating captured in your own product can then be matched back to the measured session.</p><h2 id="monitoring-qoe-in-production-with-videosdk">Monitoring QoE in production with VideoSDK</h2><p>VideoSDK ships session analytics with the platform rather than as a paid add-on.</p><p>Sessions appear at <code>app.videosdk.live/sessions</code>, and each opens into four tabs: Session Overview, Session Stats, Traces and Errors. The <a href="https://www.videosdk.live/pricing">VideoSDK pricing page</a> lists session metrics and analytics among the free plan's feature highlights, and describes pay-as-you-go as everything in free plus usage charges. New accounts start with $20 free credit.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/image.png" class="kg-image" alt="What Is QoE (Quality of Experience)? QoE vs QoS, MOS Explained" loading="lazy" width="2564" height="1700"/></figure><p>Session Stats is a two-sided view with Audio, Video, ScreenShare Audio and ScreenShare Video sub-tabs. The left side graphs what a selected sender transmitted and the right side graphs what a selected receiver got. Comparing them is how you separate an uplink problem from a downlink problem. The graph captions grade jitter as good (&lt;15), average (15-30) and bad (&gt;30). RTT is good (&lt;150), average (150-300) and bad (&gt;300). The participant view adds a call health bar that scores audio, video and screen share separately in green, orange and red.</p><p>That dashboard is a post-call tool. For live reaction, the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/call-quality/network-quality-monitoring">onQualityLimitation event</a> fires when media quality is limited or recovers. It reports a <code>type</code> of <code>cpu</code>, <code>bandwidth</code> or <code>congestion</code>, plus a <code>state</code> of <code>detected</code> or <code>resolved</code>.</p><p>For an outcome example, the healthcare-at-home startup Examedi credits VideoSDK with a 50% reduction in call failures. The quote comes from Rafael Toro, Head of New Business, in the <a href="https://www.videosdk.live/customers/examedi">published case study</a>. Treat it as a vendor-published customer testimonial rather than a benchmark.</p><h2 id="how-do-you-improve-qoe-on-a-video-call">How do you improve QoE on a video call?</h2><p>You improve QoE by removing the specific impairment your metrics point at, one at a time.</p><ol><li><strong>Attack jitter before latency.</strong> Jitter is what makes audio robotic and video pixelated, and it moves first. Start with <a href="https://www.videosdk.live/blog/what-is-jitter">What jitter is</a> and how a <a href="https://www.videosdk.live/blog/what-is-jitter-buffer">jitter buffer</a> trades delay for smooth playout.</li><li><strong>Separate bandwidth problems from delay problems.</strong> They have different fixes and are routinely confused, which is the subject of <a href="https://www.videosdk.live/blog/bandwidth-vs-latency">bandwidth vs latency</a>.</li><li><strong>Set a bitrate that matches the resolution.</strong> Too low looks soft, too high heats phones and starves the uplink. See <a href="https://www.videosdk.live/blog/what-is-bitrate">What bitrate is</a>.</li><li><strong>Choose the codec deliberately.</strong> Codec choice changes how much quality survives a given bitrate, covered in <a href="https://www.videosdk.live/blog/video-encoding">video encoding</a> and <a href="https://www.videosdk.live/blog/h264-vs-h265">H.264 vs H.265</a>.</li><li><strong>Subscribe to onQualityLimitation.</strong> A <code>type</code> of <code>cpu</code> means drop the resolution. A <code>type</code> of <code>bandwidth</code> means offer audio only.</li><li><strong>Detect freezes instead of guessing.</strong> <code>onStreamStateChanged</code> reports <code>freeze-detected</code> and <code>freeze-resolved</code>, so you log stalls rather than wait for complaints.</li><li><strong>Test the network before the call.</strong> VideoSDK's <a href="https://docs.videosdk.live/react/api/sdk-reference/network-statistics">getNetworkStats() method</a> returns download and upload speed in Mb/s, enough to warn a user in advance.</li><li><strong>Show a connection indicator.</strong> <code>getTransportStats()</code> returns one snapshot per invocation, so poll it. Showing good, fair or poor per participant explains an invisible problem.</li></ol><p>Building this from scratch means writing your own stats collection and dashboards. The <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React quickstart</a> gets you a call with those stats methods already attached, and every new account gets $20 free credit.</p><h2 id="definitions-glossary">Definitions glossary</h2><blockquote><strong>Mean opinion score (MOS):</strong> The average of user ratings on the ITU-T P.800 five-point scale, from 5 for Excellent to 1 for Bad. In a VideoSDK app, you collect the rating in your own product and join it to the session.</blockquote><blockquote><strong>Jitter:</strong> Variation in packet arrival times, defined in RFC 3550 section 6.4.1. VideoSDK's analytics dashboard flags jitter above 30 ms.</blockquote><blockquote><strong>Round trip time (RTT):</strong> The time data takes to reach the server and come back. VideoSDK returns it from <code>getVideoStats()</code> and <code>getAudioStats()</code>, and its dashboard flags values above 300 ms.</blockquote><blockquote><strong>Video freeze:</strong> A gap between two rendered frames that reaches the threshold set in the W3C webrtc-stats specification. VideoSDK reports it as the <code>freeze-detected</code> state of <code>onStreamStateChanged</code>.</blockquote><blockquote><strong>Session Stats:</strong> The VideoSDK dashboard tab that graphs jitter, RTT, bitrate, packet loss, resolution and frame rate for a chosen sender and receiver. It is where you trace a bad call to an uplink or a downlink.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>QoE is defined by ITU-T P.10/G.100 as the degree of delight or annoyance of the user, and it is always estimated rather than read directly.</li><li>QoS is what the network delivered and QoE is what the participant took away, so green metrics on a call the user hated is the normal failure mode.</li><li>The metrics worth watching for calls are MOS, jitter, round trip time, packet loss, freezes, resolution, frame rate and joining time.</li><li>VideoSDK documents triage flags of 30 ms jitter, 300 ms round trip time and 5% packet loss.</li><li>Measuring QoE properly means joining a subjective rating to objective session stats, using the session ID as the key.</li></ul><h2 id="conclusion">Conclusion</h2><p>QoE is the only quality measure that matches what your users actually complain about. Start with the objective side, because VideoSDK already collects jitter, round trip time, packet loss, resolution and frame rate for every session. Add a short rating prompt once you can join it back to a session ID. <a href="https://app.videosdk.live/login" rel="noreferrer">Grab API keys</a> and <a href="https://www.videosdk.live/pricing" rel="noreferrer">$20 free credit</a> and read your first session's stats today.</p><p>What does quality of experience look like in your product? </p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-a-qoe">What is a QoE?</h3><p>A QoE, short for quality of experience, is a measure of how satisfying an application or service felt to the person using it. ITU-T P.10/G.100 defines it as the degree of delight or annoyance of the user. For a video call it covers the audio, the video, the join and the wait.</p><h3 id="what-is-the-difference-between-qoe-and-qos">What is the difference between QoE and QoS?</h3><p>The main difference is who is being measured. QoS measures the service and the network, using metrics like jitter, round trip time and packet loss. QoE measures the person, using ratings and behaviour. QoS is the lever you control, QoE is the result you are trying to move.</p><h3 id="how-is-qoe-measured">How is QoE measured?</h3><p>QoE is measured three ways. Subjective measurement collects user ratings and averages them into a MOS, following ITU-T P.800 for speech or ITU-T P.910 for video. Objective measurement reads session stats from the client. Hybrid measurement joins the rating to the stats for one session.</p><h3 id="what-is-a-good-mos-score">What is a good MOS score?</h3><p>MOS runs on the five-point scale in ITU-T P.800, where 5 is Excellent, 4 is Good, 3 is Fair, 2 is Poor and 1 is Bad. No single number counts as good across every product, because expectations differ by context. Track the trend in your own app rather than chasing an industry figure.</p><h3 id="is-network-quality-of-experience-the-same-as-network-quality">Is network quality of experience the same as network quality?</h3><p>No. Network quality is a QoS idea, covering throughput, delay, loss and stability. Network quality of experience describes how those conditions landed with the user, and it also picks up CPU load, device hardware and expectation. Two people on one network can report very different experiences.</p><h3 id="does-videosdk-show-qoe-metrics-for-past-calls">Does VideoSDK show QoE metrics for past calls?</h3><p>Yes. The VideoSDK session analytics dashboard keeps a per-session record with Session Overview, Session Stats, Traces and Errors tabs. Session Stats covers jitter, round trip time, bitrate, packet loss, resolution and frame rate, graphed for sender and receiver side by side.</p>]]></content:encoded></item><item><title><![CDATA[What is Video KYC (vKYC)?]]></title><description><![CDATA[VKYC, or video KYC, verifies a customer's identity over a live, recorded video call with a trained official. What RBI's 2025 KYC Directions require, the eight-step V-CIP process, VKYC vs eKYC vs physical KYC, why calls fail, and the video technology behind it.]]></description><link>https://www.videosdk.live/blog/what-is-vkyc</link><guid isPermaLink="false">6aaa7925b3240feb748c9eb3</guid><category><![CDATA[Video KYC]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 16 Sep 2026 12:32:39 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/14.png" medium="image"/><content:encoded><![CDATA[<blockquote>VKYC (video KYC) is identity verification over a live, recorded video call between a customer and a trained official of a bank or other regulated entity. RBI calls it V-CIP and treats a compliant call as equal to face-to-face identification. VideoSDK provides the video calling, recording and location controls that teams build VKYC flows on.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/14.png" alt="What is Video KYC (vKYC)?"/><p>On 28 November 2025, the Reserve Bank of India issued new KYC Directions by type of regulated entity. For commercial banks, they repeal the earlier KYC instructions, including the 2016 Master Direction most VKYC flows were built on. The video KYC rules now sit in paragraphs 26 and 27.</p><p>This guide explains what VKYC is, walks through the process, compares it with eKYC and physical KYC, and shows where VideoSDK fits.</p><h2 id="what-is-vkyc-video-kyc">What is VKYC (video KYC)?</h2><p>VKYC is defined as customer identification carried out over a live, consent-based audio and video call with an authorised official of a regulated entity.</p><p>VKYC works by pairing that call with identity data the entity has already fetched, such as an Aadhaar e-KYC response or a DigiLocker document. The official checks the person on camera against that data, and the whole interaction is recorded.</p><p>RBI's name for it is V-CIP, the Video based Customer Identification Process. The <a href="https://www.rbi.org.in/Scripts/BS_ViewMasDirections.aspx?id=13141">Commercial Banks KYC Directions, 2025</a> define it as an alternative method of identifying a customer using facial recognition and customer due diligence. A V-CIP that meets the prescribed standards counts the same as face-to-face identification.</p><p>Paragraph 26 allows V-CIP for three jobs:</p><ul><li>Onboarding new individual customers, including proprietors, authorised signatories and beneficial owners of business customers</li><li>Converting accounts opened through Aadhaar OTP based e-KYC</li><li>Updating KYC, including periodic updation</li></ul><p>For a developer, VKYC is a regulated video call with evidence attached: a recording, a live photo, GPS coordinates and a timestamp.</p><h3 id="video-kyc-under-sebi-and-irdai">Video KYC under SEBI and IRDAI</h3><p>SEBI's <a href="https://www.sebi.gov.in/legal/circulars/apr-2020/clarification-on-know-your-client-kyc-process-and-use-of-technology-for-kyc_46565.html">circular of 24 April 2020</a> lets registered intermediaries run KYC through their own app, including live video. For insurers, an <a href="https://irdai.gov.in/document-detail?documentId=395494">IRDAI circular dated 21 September 2020</a> permits a Video Based Identification Process (VBIP).</p><p>The mechanics look alike, but each regulator writes its own rules, so work from the one that governs your licence. VideoSDK's <a href="https://www.videosdk.live/blog/sebi-video-kyc-compliance-guide-for-stockbrokers">SEBI video KYC guide for stockbrokers</a> covers the securities side.</p><h2 id="vkyc-rules-under-rbis-2025-kyc-directions">VKYC rules under RBI's 2025 KYC Directions</h2><p>RBI's VKYC rules sit in paragraphs 26 and 27 of its KYC Directions, 2025, issued on 28 November 2025 as separate Directions by type of regulated entity.</p><p>RBI first added V-CIP to the <a href="https://www.rbi.org.in/Scripts/BS_ViewMasDirections.aspx?id=11566">2016 KYC Master Direction</a> through a circular dated 9 January 2020. Paragraph 80 of the new commercial bank Directions repeals the earlier KYC instructions for those banks. The NBFC version uses the same V-CIP paragraph numbers.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Requirement</th>
<th>Paragraph</th>
<th>What it means for the video layer</th>
</tr>
</thead>
<tbody>
<tr>
<td>Infrastructure in the entity's own premises and secured network, with any technology outsourcing following RBI guidelines</td>
<td>27(1)(i)</td>
<td>Review your video provider against RBI's outsourcing rules</td>
</tr>
<tr>
<td>All data, including the recording, moves to entity-owned servers once the call ends</td>
<td>27(1)(i)</td>
<td>Send recordings to your own bucket</td>
</tr>
<tr>
<td>End-to-end encryption of data between the customer's device and the V-CIP hosting point, with consent recorded in an alteration-proof way</td>
<td>27(1)(ii)</td>
<td>Check the full media and signalling path in your security review</td>
</tr>
<tr>
<td>Connections from IP addresses outside India, or spoofed IPs, can be blocked</td>
<td>27(1)(iii)</td>
<td>Needs geo-IP filtering</td>
</tr>
<tr>
<td>Recordings carry live GPS coordinates and a date and time stamp</td>
<td>27(1)(iv)</td>
<td>The app must write location into the recording</td>
</tr>
<tr>
<td>Video clear enough to identify the customer beyond doubt</td>
<td>27(1)(iv)</td>
<td>Bandwidth handling becomes a compliance issue</td>
</tr>
<tr>
<td>Face liveness or spoof detection, plus face matching</td>
<td>27(1)(v)</td>
<td>Usually a separate identity vendor</td>
</tr>
<tr>
<td>Security testing by CERT-In empanelled auditors</td>
<td>27(1)(viii)</td>
<td>The whole V-CIP stack is in scope</td>
</tr>
<tr>
<td>A dropped call means a fresh session, and pauses should not create multiple video files</td>
<td>27(2)(ii)</td>
<td>Reconnect logic must respect the one-file rule</td>
</tr>
<tr>
<td>Data and recordings stored in India, with an activity log that includes the official's credentials</td>
<td>27(3)</td>
<td>Use an Indian storage region and log agent actions</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>This table summarises the rules and is not legal advice, so read the full paragraph for your entity type.</p><p>Much of paragraph 27 lands on the video stack, not only on the identity checks.</p><h2 id="the-vkyc-process-step-by-step">The VKYC process step by step</h2><p>A compliant VKYC session runs in eight stages, and each stage maps to a clause in paragraph 27 of RBI's KYC Directions.</p><ol><li><strong>Consent and pre-checks.</strong> The customer agrees to the call, and the bank records that consent in an alteration-proof way. The app confirms camera, microphone and location access and an Indian IP address.</li><li><strong>Identity data fetched.</strong> The bank uses Aadhaar OTP e-KYC, offline Aadhaar verification, CKYCR records or an equivalent e-document such as a DigiLocker file. An Aadhaar XML file or Secure QR code must be no older than three working days.</li><li><strong>Live call with a trained official.</strong> A specially trained official joins and recording starts. The official captures a photograph of the customer.</li><li><strong>Geotag and timestamp.</strong> The recording carries the customer's live GPS coordinates and a date and time stamp.</li><li><strong>Liveness and face match.</strong> The application runs face liveness or spoof detection and face matching. Gestures such as blinking are not mandatory, and the check must not exclude people with special needs.</li><li><strong>PAN check.</strong> The official captures a clear image of the PAN card unless the customer provides an e-PAN. The bank verifies PAN with the issuing authority, and the ID photos must match the person on camera.</li><li><strong>Questions from the official.</strong> The official varies the order or type of questions to show the call is live, and confirms the current address and financial profile. If anyone is seen prompting the customer, the bank rejects the account opening.</li><li><strong>Audit trail and approval.</strong> Data and recordings are stored in India with the official's activity log. The account becomes operational only after a concurrent audit.</li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/vkyc-process-flow.png" class="kg-image" alt="What is Video KYC (vKYC)?" loading="lazy" width="2400" height="1560"/></figure><p>In rare cases where the process cannot finish in one go, the video step must happen within three working days of fetching the identity data.</p><p>The video layer carries stages 3 and 4 and supports stages 1, 6 and 8. Identity services connected to the call run stages 2, 5 and 6.</p><h2 id="vkyc-vs-ekyc-vs-physical-kyc">VKYC vs eKYC vs Physical KYC</h2><p>VKYC removes the branch visit without the account limits RBI places on accounts opened through Aadhaar OTP e-KYC.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th/>
<th>VKYC (V-CIP)</th>
<th>Aadhaar OTP eKYC, non-face-to-face</th>
<th>Physical KYC</th>
</tr>
</thead>
<tbody>
<tr>
<td>How identity is established</td>
<td>Recorded call with a trained official</td>
<td>OTP authentication against Aadhaar</td>
<td>In person, with original documents</td>
</tr>
<tr>
<td>What the customer needs</td>
<td>Camera device, stable connection, PAN card or e-PAN</td>
<td>Mobile number linked to Aadhaar</td>
<td>A branch visit or an official's visit</td>
</tr>
<tr>
<td>RBI standing</td>
<td>On par with face-to-face</td>
<td>Allowed, with paragraph 25 limits</td>
<td>Documents checked in person</td>
</tr>
<tr>
<td>Account limits</td>
<td>None specific to the method</td>
<td>Deposits up to ₹1 lakh, credits up to ₹2 lakh a financial year, term loans up to ₹60,000 a year, fuller identification within a year</td>
<td>None specific to the method</td>
</tr>
<tr>
<td>Main cost drivers</td>
<td>Official's time, video, recording, storage</td>
<td>Authentication fees</td>
<td>Staff time, travel, paperwork</td>
</tr>
<tr>
<td>Published success figures</td>
<td>About 90% call success at Groww, vendor-published</td>
<td>None set by RBI</td>
<td>None set by RBI</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The limits row decides most product designs. OTP eKYC suits low-limit products and fast sign-ups, VKYC suits products that need full KYC from day one, and physical KYC serves customers without a camera or usable connection.</p><p>For a use-case breakdown, see VideoSDK's <a href="https://www.videosdk.live/blog/video-kyc-ekyc-and-physical-kyc-comparison">video KYC vs eKYC vs physical KYC comparison</a>.</p><h2 id="why-vkyc-calls-fail">Why VKYC calls fail?</h2><p>Most VKYC failures fall into three groups: an RBI rule forces a restart or rejection, the device blocks access, or the network cannot carry clear video.</p><h3 id="restarts-and-rejections-written-into-rbis-rules">Restarts and rejections written into RBI's rules</h3><ul><li><strong>Call drop.</strong> A dropped or disconnected call means a fresh session.</li><li><strong>Prompting.</strong> Anyone seen prompting the customer ends the account opening.</li><li><strong>IP outside India.</strong> Connections from foreign or spoofed IP addresses can be blocked by design.</li><li><strong>Stale Aadhaar file.</strong> An offline Aadhaar XML file or QR code older than three working days is not accepted.</li><li><strong>Printed documents.</strong> A printed copy of an e-document, including an e-PAN, is not valid.</li><li><strong>Liveness or face mismatch.</strong> A failed liveness check, or an ID photo that does not match the person on camera, fails verification.</li></ul><h3 id="device-and-network-failures">Device and network failures</h3><ul><li><strong>Camera or microphone blocked.</strong> Browsers throw a NotAllowedError when the user or a policy denies access, according to <a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia">MDN's getUserMedia reference</a>.</li><li><strong>Location blocked.</strong> The Geolocation API returns <a href="https://developer.mozilla.org/en-US/docs/Web/API/GeolocationPositionError/code">PERMISSION_DENIED</a>, leaving the recording without the required GPS coordinates.</li><li><strong>Low bandwidth.</strong> Video must identify the customer beyond doubt, so a starved connection can sink a session even when audio holds.</li><li><strong>Restricted networks.</strong> Some corporate and bank firewalls block UDP media. VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/security/firewall-setup">firewall setup guide</a> lists the domains to allow.</li><li><strong>Waiting for an official.</strong> Customers who wait too long may leave. RBI sets no wait-time benchmark, so track your own queue abandonment.</li></ul><p>VideoSDK's <a href="https://www.videosdk.live/blog/video-kyc-success-rate-optimization-guide">video KYC success rate optimization guide</a> breaks this funnel down stage by stage.</p><h3 id="vkyc-success-rates-in-practice">VKYC success rates in practice</h3><p>RBI's Directions and the SEBI and IRDAI circulars set no success-rate figure, so published numbers come from companies describing their own flows.</p><p>Groww built Video KYC for its lending flow on VideoSDK. The <a href="https://www.videosdk.live/customers/groww">Groww case study</a> reports about 90% call success and credits adaptive bitrate for customers on low bandwidth.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-09-16-at-5.06.07-PM.png" class="kg-image" alt="What is Video KYC (vKYC)?" loading="lazy" width="1570" height="752"/></figure><p>The same case study reports recordings delivered in under 10 seconds and a 45-second VKYC completion time. These are vendor-published customer figures, not independent benchmarks, so track your own numbers.</p><p>Among insurers, ICICI Prudential Life Insurance is listed as a technology partner on VideoSDK's <a href="https://www.videosdk.live/partners/icici_pru">partners page</a>.</p><h2 id="the-video-technology-behind-vkyc">The video technology behind VKYC</h2><p>VideoSDK covers the video layer of VKYC: the live call, recording, geo-tagging, geo-IP controls and network handling.</p><h3 id="recording-encryption-and-storage-in-your-cloud">Recording, encryption and storage in your cloud</h3><p><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/recording/Overview">VideoSDK recording</a> can capture a whole meeting, one participant or one audio or video track. Track recording starts a new file whenever a track changes state, such as after a mute. Given RBI's one-file rule, whole-meeting recording is the simpler fit for VKYC.</p><p>Recordings can go to your own AWS S3, Azure Blob, Google Cloud Storage or S3-compatible bucket, set per API key in <a href="https://docs.videosdk.live/help_docs/dashboard/api-keys/cloud-storage-configuration">cloud storage configuration</a>. A bucket in an Indian region, such as AWS ap-south-1, keeps files in India.</p><p><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/recording/recording-encryption">Recording encryption</a> encrypts each recording with its own AES-256 key and wraps that key with your RSA public key before upload. VideoSDK stores only the public key. Encryption and transcription processing cannot both run on the same API key.</p><p>For the audit trail, <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/recording/webhook-and-events">recording webhooks</a> report recording state changes with the meeting and session IDs. VideoSDK's <a href="https://docs.videosdk.live/help_docs/security-and-privacy/cert-in">CERT-In page</a> states that transmissions are encrypted with TLS and SRTP, and no video or audio is stored unless you configure it.</p><h3 id="geotagging-and-location-controls">Geotagging and location controls</h3><p>VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/recording/geo-tag-recording">geo-tag recording guide</a> is written for vKYC. It uses a custom recording template, and your app publishes the customer's latitude and longitude over PubSub after reading them from the device.</p><p><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/geo-fencing-and-proxy-controls/geo-ip-restriction">Geo IP restriction</a> allows or denies a connection based on the user's IP address, and the docs suggest it for VPN or proxy restrictions. <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/geo-fencing-and-proxy-controls/geo-fencing">Geo-fencing</a> keeps connections on servers in a chosen region. Both list India as a region.</p><p>The <a href="https://www.videosdk.live/pricing">VideoSDK pricing page</a> lists geo-fencing, geo-restriction, and VPN detection and IP restriction as add-ons on Pay-As-You-Go, with custom pricing on Enterprise. <a href="https://www.videosdk.live/contact?formType=talk_to_sales">Contact sales</a> for a quote.</p><h3 id="handling-low-bandwidth-and-restricted-networks">Handling low bandwidth and restricted networks</h3><p>The <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/get-notified/network-events">onQualityLimitation event</a> fires when media quality is limited by CPU, bandwidth or congestion, and again when the limit clears. Your app can use it to ask the customer to switch networks before the official loses a clear view.</p><p>For locked-down networks, VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/geo-fencing-and-proxy-controls/cloud-proxy">cloud proxy</a> tries UDP first and falls back to TCP by default.</p><h3 id="photo-capture-and-agent-controls">Photo capture and agent controls</h3><p>The React SDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/handling-media/image-capturer">image capture feature</a> returns a camera frame as a base64 image. The docs name Video KYC as a use case, such as a customer holding up an ID document.</p><p>An official can also <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/control-remote-participant/switch-remote-participant-camera">switch the customer's camera</a> between front and back, which helps when showing the PAN card. For the operator side, see how to build a <a href="https://www.videosdk.live/blog/video-kyc-agent-dashboard">video KYC agent dashboard</a>.</p><h3 id="what-videosdk-does-not-do">What VideoSDK does not do</h3><p>VideoSDK does not perform liveness detection, face matching, Aadhaar or PAN verification, or the concurrent audit. Those belong to the bank or identity vendors, covered in <a href="https://www.videosdk.live/blog/liveness-detection-android-ios-video-kyc">liveness detection for Android and iOS video KYC</a>. The CERT-In audit of V-CIP infrastructure is also the bank's obligation.</p><p>To try the video layer, start with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a>. New accounts get $20 free credit, as the <a href="https://www.videosdk.live/pricing">VideoSDK pricing page</a> shows.</p><h2 id="definitions-glossary">Definitions glossary</h2><blockquote><strong>V-CIP:</strong> RBI's Video based Customer Identification Process, its formal name for VKYC. VideoSDK supplies the video, recording and location controls a V-CIP application runs on.</blockquote><blockquote><strong>Liveness check:</strong> A test that the person on camera is physically present, not a photo or replay. VideoSDK leaves this check to the bank or an identity vendor.</blockquote><blockquote><strong>CKYCR:</strong> The Central KYC Records Registry, which stores and returns customers' KYC records. A V-CIP can use CKYCR records fetched with the customer's KYC identifier.</blockquote><blockquote><strong>Equivalent e-document:</strong> A digitally signed electronic document from the issuing authority, including DigiLocker documents. RBI accepts it in V-CIP, but not as a printout.</blockquote><blockquote><strong>Geotagging:</strong> Adding the customer's live GPS coordinates and a timestamp to the V-CIP recording. VideoSDK's geo-tag recording guide does this with a custom template.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>VKYC is identity verification over a live, recorded video call, and RBI treats a compliant V-CIP as equal to face-to-face identification.</li><li>RBI's V-CIP rules now sit in paragraphs 26 and 27 of the KYC Directions, 2025, issued on 28 November 2025.</li><li>Much of paragraph 27 lands on the video stack: data location, IP blocking, geotagged recordings, clear video and the one-file rule.</li><li>Published VKYC success rates come from companies, not regulators, such as Groww's vendor-published 90%.</li><li>VideoSDK provides the video layer, while identity checks come from the bank or its vendors.</li></ul><h2 id="conclusion">Conclusion</h2><p>VKYC turns a branch visit into a regulated video call, and RBI's 2025 KYC Directions spell out what that call must prove. Much of the engineering sits in the video layer: where recordings go, how location is captured, which connections are refused and how calls survive weak networks.</p><p>VideoSDK handles that layer, so your team can focus on identity checks and the official's workflow. Read the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a>, then <a href="https://app.videosdk.live/login">sign up for VideoSDK</a> with $20 free credit to test a VKYC call.</p><p>What kind of VKYC flow are you building? </p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-vkyc">What is VKYC?</h3><p>VKYC is video KYC, a way to verify a customer's identity over a live, recorded video call with a trained official. In India, RBI calls it V-CIP and treats a compliant call as equal to face-to-face identification. Banks, NBFCs, insurers and stockbrokers use it to onboard customers remotely.</p><h3 id="is-vkyc-mandatory-for-opening-a-bank-account">Is VKYC mandatory for opening a bank account?</h3><p>No, VKYC is not mandatory. RBI's KYC Directions say a bank may undertake V-CIP, alongside routes such as Aadhaar-based e-KYC, digital KYC and in-person verification. VKYC avoids a branch visit without the limits placed on OTP e-KYC accounts.</p><h3 id="what-documents-do-you-need-for-vkyc">What documents do you need for VKYC?</h3><p>For VKYC, the bank needs identity data it can fetch digitally, such as Aadhaar e-KYC, an offline Aadhaar file, a CKYCR record or a DigiLocker document. You also need your PAN card or an e-PAN, plus a device with camera and location access.</p><h3 id="what-happens-if-a-vkyc-call-disconnects">What happens if a VKYC call disconnects?</h3><p>If a VKYC call drops or disconnects, RBI requires the bank to start a fresh session. Pauses that do not create multiple video files do not need a restart. VideoSDK's onQualityLimitation event helps apps spot bandwidth problems early.</p><h3 id="does-videosdk-provide-liveness-detection-for-vkyc">Does VideoSDK provide liveness detection for VKYC?</h3><p>No, VideoSDK provides the video layer of VKYC, not liveness detection. It covers the live call, recording to your own storage, recording encryption, geo-tagging and geo-IP restriction. Liveness detection and face matching come from the bank or an identity vendor.</p>]]></content:encoded></item><item><title><![CDATA[How to Build Live Audio Rooms: Voice Chat Architecture, Features & Example]]></title><description><![CDATA[Live audio rooms let a few speakers talk while a large audience listens and raises hands to join. How the architecture works, the features users expect, what a 500-listener room costs on VideoSDK, and how to build one in Flutter, React Native, or JavaScript.
]]></description><link>https://www.videosdk.live/blog/live-audio-rooms</link><guid isPermaLink="false">6aa8fea2b3240feb748c9de6</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 15 Sep 2026 12:51:59 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/09.png" medium="image"/><content:encoded><![CDATA[<blockquote>Live audio rooms are defined as real-time voice sessions where a few hosts and speakers talk, a larger audience listens, and listeners can raise a hand to be invited on stage. On VideoSDK, speakers join in SEND_AND_RECV mode and listeners in RECV_ONLY mode, and audio-only listener minutes are listed at $0.0005 each.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/09.png" alt="How to Build Live Audio Rooms: Voice Chat Architecture, Features & Example"/><p>A live audio room looks simple from the outside: a stage, an audience, and a raise-hand button. Behind it are three separate problems. Speakers need two-way, real-time audio. Hundreds of listeners need to hear them without each one adding load to every speaker's connection. And the app has to move a listener onto the stage without dropping the room.</p><p>This guide covers how live audio rooms work, the features users expect, and what a voice chat API costs per listener minute. It then shows how to build one on VideoSDK with Flutter, React Native, or JavaScript, and ends with the quotas that decide how large a room can grow.</p><h2 id="what-are-live-audio-rooms">What are live audio rooms?</h2><p>A live audio room is a voice-only broadcast with an open stage, where the audience can join the conversation instead of only hearing it.</p><p>Live audio rooms are defined as real-time voice sessions with two classes of participant: people on stage who publish audio, and listeners who only receive it. They work by routing each speaker's audio through a media server that forwards it to every listener, while a separate signalling channel carries requests such as raised hands.</p><p>Clubhouse made the format popular, and X Spaces, Discord Stage channels, and Facebook Live Audio Rooms followed. The same pattern now runs inside apps that are not audio products at all: a fitness class Q&amp;A, a live shopping stream with voice, or a community town hall.</p><p>It helps to separate three terms that often get mixed up:</p><ul><li>An <strong>audio call</strong> is symmetric. Everyone in a voice call application can speak, as in a phone call or a team huddle.</li><li><strong>Live audio streaming software</strong>, such as an internet radio or podcast broadcaster, is one-way. Listeners cannot talk back.</li><li>A <strong>live audio room</strong> sits between them. A small group speaks, a large group listens, and the line between them moves during the session.</li></ul><p>VideoSDK supports all three patterns on one SDK. Its <a href="https://www.videosdk.live/live-audio-rooms">live audio room product page</a> covers the commercial overview, and this guide covers the architecture and the build.</p><h2 id="how-live-audio-rooms-work">How live audio rooms work</h2><p>A live audio room runs on three layers: speakers publish audio, a media server forwards it, and a signalling channel handles who is allowed to speak.</p><p>The diagram below shows those layers in one room. Speakers send audio up to the media server, and the server forwards a copy to every listener. A raised hand travels as a message on the signalling channel rather than as audio.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/live-audio-rooms-architecture.png" class="kg-image" alt="How to Build Live Audio Rooms: Voice Chat Architecture, Features & Example" loading="lazy" width="2400" height="1420"/></figure><h3 id="speakers-publish-listeners-subscribe">Speakers publish, listeners subscribe</h3><p>Each person on stage captures their microphone and sends one audio stream to the media server. Browsers and WebRTC apps encode that stream with Opus, which <a href="https://www.rfc-editor.org/rfc/rfc7874">RFC 7874</a> makes mandatory for every WebRTC endpoint. <a href="https://www.rfc-editor.org/rfc/rfc6716">RFC 6716</a> defines Opus from 6 kb/s speech up to 510 kb/s stereo music, so one codec covers a quiet talk and a live DJ set.</p><p>Listeners send nothing. They open a receive-only connection and play whatever the server forwards. On VideoSDK, that is the difference between SEND_AND_RECV mode for the stage and RECV_ONLY mode for the audience, as the <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start-flutter-ils">Flutter interactive live streaming quickstart</a> sets out.</p><h3 id="why-the-media-server-forwards-instead-of-mixing">Why the media server forwards instead of mixing</h3><p>The media server is usually a <a href="https://www.videosdk.live/blog/sfu-vs-mcu-vs-mesh-webrtc" rel="noreferrer">Selective Forwarding Unit (SFU)</a>. <a href="https://www.rfc-editor.org/rfc/rfc7667#section-3.7">RFC 7667</a>, the IETF document on RTP topologies, calls it a Selective Forwarding Middlebox: it selects which incoming streams go to each endpoint. A mixer, by contrast, decodes the streams and generates a new combined one.</p><p>Forwarding keeps each speaker's upload constant however many people listen, because the speaker sends one stream and the server makes the copies. VideoSDK describes its media layer as an <a href="https://www.videosdk.live/developer-hub/ils/simulcast">SFU architecture</a>.</p><h3 id="the-hand-raise-to-speaker-flow">The hand-raise-to-speaker flow</h3><p>Moving a listener onto the stage is a short conversation over the signalling channel. On VideoSDK it runs in five steps:</p><ol><li><strong>The listener raises a hand.</strong> Their app publishes a message on the RAISE_HAND topic using <a href="https://docs.videosdk.live/flutter/guide/interactive-live-streaming/interaction-in-livestream/raise-hand">PubSub</a>.</li><li><strong>The host sees the request.</strong> The host's app subscribes to RAISE_HAND and shows the raised hand in a queue.</li><li><strong>The host sends an invitation.</strong> The host publishes to a topic addressed to that listener, as the <a href="https://docs.videosdk.live/flutter/guide/interactive-live-streaming/handling-participants/invite-guest-on-stage">invite-on-stage guide</a> shows.</li><li><strong>The listener's own app switches mode.</strong> It calls changeMode with SEND_AND_RECV. The <a href="https://docs.videosdk.live/flutter/guide/interactive-live-streaming/audiance-managment/change-mode">change-mode docs</a> note that changeMode only ever changes the mode of the participant who calls it, so the host cannot force it.</li><li><strong>The new speaker turns on the microphone.</strong> Everyone now hears them through the same forwarding path.</li></ol><p>Moving someone back off stage reverses the flow: the host asks, and the speaker's app switches to RECV_ONLY.</p><h2 id="features-users-expect-in-a-live-audio-room">Features users expect in a live audio room</h2><p>Users judge a live audio room on control and continuity: who can speak, who can be silenced, and whether the audio survives a locked phone.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Feature</th>
<th>Why users expect it</th>
<th>How VideoSDK provides it</th>
</tr>
</thead>
<tbody>
<tr>
<td>Hand raise</td>
<td>Listeners need a polite way to ask to speak</td>
<td>A message on the RAISE_HAND PubSub topic (<a href="https://docs.videosdk.live/flutter/guide/interactive-live-streaming/interaction-in-livestream/raise-hand">docs</a>)</td>
</tr>
<tr>
<td>Speaker promotion</td>
<td>The host decides who joins the stage</td>
<td>PubSub invitation, then changeMode on the listener's app (<a href="https://docs.videosdk.live/flutter/guide/interactive-live-streaming/handling-participants/invite-guest-on-stage">docs</a>)</td>
</tr>
<tr>
<td>Mute controls</td>
<td>Hosts must silence a speaker who drifts off topic</td>
<td>Remote muteMic, which needs the allow_mod permission in the host's token (<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/control-remote-participant/remote-participant-media">docs</a>)</td>
</tr>
<tr>
<td>Room chat</td>
<td>Listeners without a microphone still want to take part</td>
<td>Text messages over PubSub, which the docs describe as currently free (<a href="https://docs.videosdk.live/flutter/guide/interactive-live-streaming/interaction-in-livestream/chat-using-pubsub">docs</a>)</td>
</tr>
<tr>
<td>Active speaker indicator</td>
<td>Listeners need to know who is talking</td>
<td>A speakerChanged event that names the current dominant speaker (<a href="https://www.videosdk.live/blog/flutter-live-audio-room">tutorial</a>)</td>
</tr>
<tr>
<td>Recording</td>
<td>Rooms become podcasts and replays</td>
<td>Audio-only recording, $0.015 per recorded minute (<a href="https://docs.videosdk.live/flutter/guide/interactive-live-streaming/recording/recording">docs</a>)</td>
</tr>
<tr>
<td>Background audio on mobile</td>
<td>People lock their phones and keep listening</td>
<td>Background handling for iOS and Android (<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/handling-media/background-handling">docs</a>)</td>
</tr>
<tr>
<td>Noise suppression</td>
<td>Speakers join from kitchens, cars, and cafes</td>
<td>The media effects plugin (<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/plugin/noise-suppresion">docs</a>)</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The two features that most often break in production are mute controls and background audio. Mute controls fail when the host's token was minted without allow_mod, so give moderators that permission server-side and nobody else.</p><h3 id="keeping-audio-alive-when-the-phone-is-locked">Keeping audio alive when the phone is locked</h3><p>Background audio is an operating system rule, not an SDK setting, and each platform enforces it differently.</p><p>On iOS, the app must declare the audio <a href="https://developer.apple.com/documentation/xcode/configuring-background-execution-modes">background execution mode</a> and use an audio session category such as <a href="https://developer.apple.com/documentation/avfaudio/avaudiosession/category-swift.struct/playandrecord">playAndRecord</a>, which Apple describes as suited to VoIP apps. Without the background mode, audio stops when the screen locks.</p><p>On Android, a speaker's microphone has to run inside a foreground service. From Android 14 (API level 34), every foreground service must declare its <a href="https://developer.android.com/develop/background-work/services/fgs/service-types">service type</a>, so a speaker needs the microphone type and a listener needs mediaPlayback. Android also blocks creating a microphone foreground service while the app is already in the background, so start it when the user joins the stage.</p><h2 id="voice-chat-api-vs-voice-sdk">Voice Chat API vs Voice SDK</h2><p>A voice chat API runs on your server and manages rooms and tokens, while a voice SDK runs in the app and handles the microphone and speakers.</p><p>Every API voice call has both halves. The table shows which half owns each job.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th/>
<th>Voice chat API (server)</th>
<th>Voice SDK (client)</th>
</tr>
</thead>
<tbody>
<tr>
<td>Runs on</td>
<td>Your backend</td>
<td>The user's phone or browser</td>
</tr>
<tr>
<td>Creates rooms and tokens</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>Captures and plays audio</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Switches listener and speaker modes</td>
<td>No</td>
<td>Yes, with changeMode</td>
</tr>
<tr>
<td>Starts recording</td>
<td>Yes, over REST</td>
<td>Yes, from the host's app</td>
</tr>
<tr>
<td>Holds your API secret</td>
<td>Yes</td>
<td>Never</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h3 id="what-a-live-audio-room-costs">What a live audio room costs</h3><p>VideoSDK prices audio by the minute and bills people on stage and people in the audience at different rates.</p><p>As of September 15, 2026, VideoSDK's <a href="https://www.videosdk.live/pricing">pricing page</a> lists voice at $0.001 per participant minute for people in a real-time call. For interactive live streaming it lists voice streaming, meaning audio-only viewer minutes, at $0.0005 per viewer minute.</p><p>Here is a worked example: a one-hour room with one host, three speakers, and 500 listeners.</p><ul><li>Stage: 4 people x 60 minutes = 240 participant minutes x $0.001 = $0.24</li><li>Audience: 500 listeners x 60 minutes = 30,000 viewer minutes x $0.0005 = $15.00</li><li>Total for the session: $15.24</li></ul><p>The audience is 98% of the bill, so the viewer rate matters far more than the speaker rate when you compare any audio streaming solution. Recording the session adds $0.015 per recorded minute, or $0.90 for the hour.</p><h3 id="is-there-a-free-voice-call-api">Is there a free voice call API?</h3><p>VideoSDK gives new accounts a $20 free credit, which covers the first session above with room to spare. For more providers side by side, see the <a href="https://www.videosdk.live/blog/10-best-audio-calling-api">10 best audio calling APIs</a> and the <a href="https://www.videosdk.live/blog/voice-chat-sdk">top voice chat SDKs</a>.</p><h2 id="build-it-a-flutter-live-audio-room-example">Build it: a Flutter live audio room example</h2><p>The fastest way to a working live audio room is VideoSDK's step-by-step <a href="https://www.videosdk.live/blog/flutter-live-audio-room">Flutter live audio room tutorial</a>, which builds speakers, listeners, and raised hands from an empty project.</p><p>The tutorial follows six steps:</p><ol><li><strong>Install the SDK.</strong> Add the videosdk package and set the Android and iOS microphone permissions.</li><li><strong>Get a token and room ID.</strong> Your app fetches a token from your server, which also creates the room through the VideoSDK REST API.</li><li><strong>Join with the camera off.</strong> Speakers join with the microphone on, and listeners with it off.</li><li><strong>Add the raise-hand button.</strong> Listeners publish a RAISE_HAND message, and the host's screen lists them.</li><li><strong>Promote and demote speakers.</strong> The host unmutes an invited listener and mutes them again later, using the allow_mod permission.</li><li><strong>Highlight the active speaker and record.</strong> A speaker-changed event drives the highlight, and one call starts a recording.</li></ol><p>Two things to change when you follow it today. The tutorial was written against version 2 of the Flutter package, and the current release on <a href="https://pub.dev/packages/videosdk">pub.dev</a> is 4.0.1, published September 8, 2026. It also puts everyone in the same call mode, which caps a room at 100 participants. For a larger audience, join listeners in RECV_ONLY mode as the <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start-flutter-ils">Flutter quickstart</a> shows.</p><p>The same room on other platforms:</p><ul><li><strong>React Native:</strong> the <a href="https://www.videosdk.live/sdk/react-native/audio-rooms">React Native audio rooms tutorial</a> and the <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start-react-native-ils">React Native quickstart</a></li><li><strong>JavaScript:</strong> the <a href="https://www.videosdk.live/sdk/javascript/audio-rooms">JavaScript audio rooms tutorial</a> and the <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start-js-ils">JavaScript quickstart</a></li></ul><p><strong>Ready to try it?</strong> <a href="https://app.videosdk.live/login">Create a VideoSDK account</a>, use the $20 free credit, and run the Flutter quickstart with two phones in one room.</p><p>Prefer to watch first? This 4-minute VideoSDK walkthrough builds the simplest version of an audio room in plain JavaScript: the video calling quickstart with the camera removed, and two people talking in one room. Add listener mode and raise hand from the guides above to turn it into a live audio room.</p>
<!--kg-card-begin: html-->
<iframe width="700" height="415" src="https://www.youtube.com/embed/4JQrsZYDTKk?si=-UvoCQYA6NMJbeXv" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<h2 id="scaling-live-audio-rooms-quotas-and-audience-sizes">Scaling live audio rooms: quotas and audience sizes</h2><p>How large a live audio room can grow depends on two sets of limits: per room, and across your whole VideoSDK account at once.</p><p>VideoSDK's <a href="https://docs.videosdk.live/help_docs/quotas-and-limit">quota documentation</a> sets these defaults, read September 15, 2026:</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Limit</th>
<th>Free plan</th>
<th>Pay-as-you-go</th>
<th>Add-on</th>
</tr>
</thead>
<tbody>
<tr>
<td>Concurrent hosts, account-wide</td>
<td>50</td>
<td>500</td>
<td>100 more for $20 per month</td>
</tr>
<tr>
<td>Concurrent viewers, account-wide</td>
<td>100</td>
<td>200</td>
<td>200 more for $20 per month</td>
</tr>
<tr>
<td>Active speakers per room</td>
<td>15</td>
<td>15</td>
<td/>
</tr>
<tr>
<td>Participants per room</td>
<td>100</td>
<td>100</td>
<td/>
</tr>
<tr>
<td>Interactive live streaming viewers per room</td>
<td>1,000</td>
<td>1,000</td>
<td/>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The numbers that shape a live audio room are 15 active speakers and 1,000 listeners per room. A stage larger than 15 needs a rotation, and an audience larger than 1,000 needs a second room or HLS playback.</p><p>The account-wide viewer limit bites first. The 500-listener room from the pricing example fits inside one room, but on pay-as-you-go it exceeds the default 200 concurrent viewers. Two add-on packs lift that to 600 for $40 a month.</p><p>These are defaults rather than hard ceilings. Pay-as-you-go accounts raise them by buying add-on packs from the VideoSDK dashboard, so size the packs before a launch event rather than during it.</p><h2 id="definitions-glossary">Definitions glossary</h2><blockquote><strong>SFU (selective forwarding unit):</strong> A media server that forwards selected incoming streams to each participant instead of mixing them into one. It keeps a speaker's upload the same size however many people listen.</blockquote><blockquote><strong>Participant mode:</strong> The VideoSDK setting that decides what a participant sends. SEND_AND_RECV publishes and receives audio for hosts and speakers, while RECV_ONLY only receives it, for listeners.</blockquote><blockquote><strong>changeMode:</strong> The VideoSDK method a participant calls to switch between RECV_ONLY and SEND_AND_RECV. It only changes the caller's own mode, so the host invites and the listener's app makes the switch.</blockquote><blockquote><strong>PubSub:</strong> VideoSDK's publish-subscribe messaging inside a room, used here for raised hands, stage invitations and chat. VideoSDK's pricing FAQ lists PubSub messaging and signaling as currently free.</blockquote><blockquote><strong>Opus:</strong> The audio codec defined in RFC 6716, which RFC 7874 makes mandatory for every WebRTC endpoint. It runs from 6 kb/s speech up to 510 kb/s stereo music.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>Live audio rooms split participants into speakers who publish audio and listeners who only receive it, joined by an SFU that forwards each speaker's stream.</li><li>A raised hand is a signalling message, not audio, and the listener's own app switches into speaker mode when the host accepts.</li><li>On VideoSDK, the audience drives the cost: audio-only listener minutes are $0.0005 each, so a 500-listener hour costs about $15.</li><li>Background audio needs platform work: the iOS audio background mode and, on Android 14 and later, a typed foreground service.</li></ul><h2 id="conclusion">Conclusion</h2><p>Live audio rooms combine a small real-time stage with a large listening audience, and the engineering follows that split. Speakers publish, the SFU forwards, and hand raises travel as messages. Most of the product decisions come down to moderation, background audio, and the viewer quota.</p><p>VideoSDK covers the room, the modes, and the signalling on Flutter, React Native, and JavaScript. Start with the $20 free credit at <a href="https://app.videosdk.live/login" rel="noreferrer">VideoSDK</a> and the <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start-flutter-ils">Flutter quickstart</a>. What kind of live audio room are you building? Tell us in the comments.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-an-audio-stream">What is an audio stream?</h3><p>An audio stream is a continuous flow of encoded sound sent over a network and played as it arrives, rather than downloaded first. In a live audio room, each speaker produces one audio stream, usually Opus-encoded, and the media server forwards it to every listener.</p><h3 id="how-do-i-stream-my-voice-live-to-an-audience">How do I stream my voice live to an audience?</h3><p>Live streaming voice to an audience needs an app that captures your microphone and a service that forwards the audio to listeners. With VideoSDK, you join a room in SEND_AND_RECV mode as the host, and your audience joins in RECV_ONLY mode to listen.</p><h3 id="how-many-listeners-can-a-live-audio-room-have">How many listeners can a live audio room have?</h3><p>A single VideoSDK room supports up to 1,000 interactive live streaming listeners and 15 active speakers by default. On pay-as-you-go, the account-wide limit is 200 concurrent viewers, raised in packs of 200 for $20 a month.</p><h3 id="what-is-the-difference-between-an-audio-call-and-a-live-audio-room">What is the difference between an audio call and a live audio room?</h3><p>The difference is who can speak. In an audio call, every participant can talk at any time. In a live audio room, only people on stage talk, listeners join receive-only, and a listener speaks only after the host invites them.</p><h3 id="how-do-listeners-become-speakers">How do listeners become speakers?</h3><p>A listener raises a hand, which publishes a message the host sees. If the host accepts, the listener's own app switches from RECV_ONLY to SEND_AND_RECV mode and turns on the microphone, because VideoSDK only lets a participant change their own mode.</p><h3 id="is-there-a-free-voice-call-api-1">Is there a free voice call API?</h3><p>VideoSDK includes a one-time $20 free credit for new accounts, which covers about 40,000 listener minutes at the audio-only viewer rate. Open-source media servers are free to license but not to host.</p>]]></content:encoded></item><item><title><![CDATA[Video Encoding Explained: Encoding vs Transcoding vs Codecs]]></title><description><![CDATA[Video encoding compresses raw frames into a stream a network can carry, and transcoding converts one encoded stream into another. The main codecs and containers, hardware vs software encoders, and how real-time video calls encode differently, with VideoSDK's encoder presets.]]></description><link>https://www.videosdk.live/blog/video-encoding</link><guid isPermaLink="false">6aa9148bb3240feb748c9def</guid><category><![CDATA[WebRTC]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 15 Sep 2026 12:44:35 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/10.png" medium="image"/><content:encoded><![CDATA[<blockquote>Video encoding is defined as the process of compressing raw video frames into a smaller stream using a codec such as H.264, VP8, or AV1. Transcoding decodes an encoded stream and encodes it again in a different format or size.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/10.png" alt="Video Encoding Explained: Encoding vs Transcoding vs Codecs"/><p>One minute of raw 1080p video at 30 frames per second is about 5.6 GB. No phone connection carries that. Video encoding shrinks it, and the settings you give the encoder decide how sharp, smooth, and responsive the result looks.</p><p>This guide explains video encoding for developers who build apps with video. It separates encoding, transcoding, and codecs, compares the main video encoding formats, and weighs hardware against software encoders. It then shows what changes when video must be encoded in real time, using the presets in the VideoSDK JavaScript SDK.</p><h2 id="what-is-video-encoding">What is video encoding?</h2><p>Video encoding compresses raw frames into a stream a network can carry, mostly by storing what changes between frames instead of every pixel.</p><p>Video encoding is defined as converting uncompressed video frames into a compressed bitstream that follows a codec standard. It works by predicting each frame from frames already coded, then storing only the difference and discarding detail viewers are unlikely to notice. VideoSDK's <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/call-quality/video-codecs">video codecs guide</a> describes a codec as storing "each frame largely as the changes from the one before."</p><p>The savings are large. Uncompressed 1080p at 30 fps with 8-bit 4:2:0 color is 1920 x 1080 pixels x 12 bits x 30 frames, or about 746 Mbps. VideoSDK's balanced 1080p preset sends the same resolution at 2,200 kbps, roughly 340 times less data.</p><p>Encoders mix three kinds of frames:</p><ul><li><strong>I-frame (keyframe):</strong> coded on its own, so a decoder can start from it.</li><li><strong>P-frame:</strong> predicted from earlier frames.</li><li><strong>B-frame:</strong> predicted from earlier and later frames, which saves bits but forces the encoder to wait for a future frame.</li></ul><p>That is the video encoding definition in practice: a trade between size, picture quality, delay, and the computing power spent describing each frame.</p><h2 id="encoding-vs-transcoding-vs-codec">Encoding vs Transcoding vs Codec</h2><p>Encoding creates a compressed stream, transcoding converts one compressed stream into another, and a codec is the standard both follow.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Term</th>
<th>Input</th>
<th>Output</th>
<th>Where it happens</th>
<th>Example</th>
</tr>
</thead>
<tbody>
<tr>
<td>Encoding</td>
<td>Raw frames from a camera or screen</td>
<td>A compressed stream in one codec</td>
<td>On the sending device, or in a live encoder</td>
<td>A laptop browser encodes its webcam as VP8 for a video call</td>
</tr>
<tr>
<td>Transcoding</td>
<td>An already encoded stream or file</td>
<td>The same content in another codec, resolution, or bitrate</td>
<td>On a server or in a media pipeline</td>
<td>A 1080p H.264 upload becomes 720p and 360p versions for streaming</td>
</tr>
<tr>
<td>Codec</td>
<td>Not a process: a specification, plus the software or hardware that implements it</td>
<td>Rules for how to encode and decode</td>
<td>Inside every encoder and player</td>
<td>H.264, H.265, VP9, AV1</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Encoding vs transcoding comes down to the input. An encoder starts from raw pictures, while a transcoder must decode first, so every transcode costs compute and loses a little quality. AWS describes <a href="https://aws.amazon.com/what-is/video-transcoding/">video transcoding</a> as converting video from one format to another by adjusting resolution, encoding, and bitrate.</p><p>A codec is also not a container. A container such as MP4 or WebM is the wrapper that holds encoded video, audio, and timing data, while the codec decides how pictures are compressed. For workflows and pipeline examples, see VideoSDK's <a href="https://www.videosdk.live/developer-hub/media-server/transcoding-vs-encoding">transcoding vs encoding</a> guide.</p><h3 id="where-encoding-and-transcoding-happen-in-a-videosdk-app">Where encoding and transcoding happen in a VideoSDK app</h3><p>In a VideoSDK video call, encoding happens on each participant's device, and server-side processing enters only when you broadcast or export.</p><ul><li><strong>HLS:</strong> the <a href="https://docs.videosdk.live/server-sdk/reference/hls">Server SDK HLS reference</a> renders the room into a grid, spotlight, or sidebar layout for a large audience. You choose a quality of low, med, high, or ultra, and the docs state there is no separate resolution option.</li><li><strong>RTMP:</strong> the <a href="https://docs.videosdk.live/server-sdk/reference/rtmp">RTMP reference</a> pushes the composed room to destinations such as YouTube or Twitch.</li><li><strong>Finished files:</strong> the <a href="https://docs.videosdk.live/server-sdk/reference/transcodings">Transcodings reference</a> turns completed recordings and HLS streams into downloadable MP4 files.</li></ul><p>The docs do not describe a configurable rendition ladder or per-rendition bitrates for HLS output, so plan around the quality presets rather than custom encoder settings.</p><h2 id="video-encoding-formats-codecs-and-containers">Video encoding formats: Codecs and Containers</h2><p>A video encoding format pairs a codec, which compresses the pictures, with a container, which packages them for storage or delivery.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Codec</th>
<th>First published</th>
<th>Common containers</th>
<th>Where you meet it</th>
</tr>
</thead>
<tbody>
<tr>
<td>H.264 / AVC</td>
<td>ITU-T, May 2003</td>
<td>MP4, MPEG-TS</td>
<td>The broad-compatibility default, and mandatory in WebRTC browsers</td>
</tr>
<tr>
<td>H.265 / HEVC</td>
<td>ITU-T, April 2013</td>
<td>MP4</td>
<td>Streaming where bandwidth matters, since ITU said it needs about half the bitrate of H.264</td>
</tr>
<tr>
<td>VP9</td>
<td>Google, June 2013</td>
<td>WebM</td>
<td>Web browsers and WebRTC</td>
</tr>
<tr>
<td>AV1</td>
<td>AOMedia, June 2018</td>
<td>MP4</td>
<td>Browsers and streaming apps, and allowed in Apple's HLS authoring spec</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Container rules are stricter than people assume. The <a href="https://www.webmproject.org/docs/container/">WebM container guidelines</a> say WebM video should be VP8 or VP9 and audio should be Vorbis or Opus. For streaming, <a href="https://www.rfc-editor.org/rfc/rfc8216">RFC 8216</a> lets HLS carry segments as MPEG-2 transport streams or fragmented MP4.</p><p>The HEVC figure comes from ITU's <a href="https://www.itu.int/net/pressoffice/press_releases/2013/01.aspx">January 2013 announcement</a>, which said HEVC needs only half the bit rate of H.264. Real savings depend on content and encoder. The trade-offs between the two are covered in <a href="https://www.videosdk.live/blog/h264-vs-h265">H.264 vs H.265</a>, and containers get more space in <a href="https://www.videosdk.live/blog/video-quality-bandwidth-codecs-containers">video quality, bandwidth, codecs and containers</a>.</p><h2 id="hardware-vs-software-video-encoders">Hardware vs software video encoders</h2><p>A hardware video encoder is a dedicated block on a chip that compresses video without loading the CPU, while a software encoder runs on the CPU.</p><p>The common hardware encoders are NVIDIA NVENC on GPUs, Apple <a href="https://developer.apple.com/documentation/videotoolbox">VideoToolbox</a> on Apple devices, and Android <a href="https://developer.android.com/reference/android/media/MediaCodec">MediaCodec</a>, which gives apps access to the phone's codec components. The best-known software video encoder is x264 for H.264. Its <a href="https://github.com/mirror/x264/blob/master/x264.c">presets</a> run from ultrafast to placebo, with medium as the default, and slower presets spend more CPU time to find smaller encodings.</p><p>Hardware encoders have the same dial. NVIDIA's <a href="https://docs.nvidia.com/video-technologies/video-codec-sdk/13.0/nvenc-application-note/index.html">NVENC application note</a> for Video Codec SDK 13.0 gives H.264 speeds on Ada GPUs in constant-bitrate mode. One NVENC engine reaches 910 fps with the fastest P1 preset and 247 fps with the highest-quality P7 preset. The same note says offloading encoding leaves CPU cores free for other work.</p><p>Quality is harder to generalize. A <a href="https://chipsandcheese.com/p/gpu-hardware-video-encoders-how-good-are-they">March 2022 test by Chips and Cheese</a> scored encoders with Netflix's VMAF metric at 1080p and 4 to 10 Mbps. On a game clip, NVIDIA's Turing NVENC matched or beat x264's faster preset. AMD's encoder scored significantly worse. That is one test on one content type with 2022 hardware, so measure your own content.</p><p>In a video call app, you do not call NVENC or x264 directly. The browser or mobile OS supplies the encoder, and you control codec, resolution, and bitrate through the SDK. If you were looking for a video encoder to buy, such as a box that takes HDMI and streams to YouTube, that is a separate product category for broadcasters.</p><h2 id="how-real-time-encoding-differs-from-file-encoding">How real-time encoding differs from file encoding</h2><p>Real-time video encoding must finish every frame before the next one is due, so it gives up the look-ahead that file encoders use to save bits.</p><p>The diagram below puts the two pipelines side by side. In the top lane, a file is encoded once and a transcoder later turns it into HLS versions. In the bottom lane, a VideoSDK call encodes each frame on the device and sends three simulcast layers. The media server forwards one layer to each receiver, and a receiver can ask for a new keyframe.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/video-encoding-pipelines.png" class="kg-image" alt="Video Encoding Explained: Encoding vs Transcoding vs Codecs" loading="lazy" width="2400" height="1520"/></figure>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th/>
<th>File or on-demand encoding</th>
<th>Real-time encoding</th>
</tr>
</thead>
<tbody>
<tr>
<td>Time per frame</td>
<td>Can run slower than real time for better results</td>
<td>Must keep pace with the camera</td>
</tr>
<tr>
<td>B-frames</td>
<td>Common, because waiting for future frames costs nothing</td>
<td>Avoided, because waiting adds delay</td>
</tr>
<tr>
<td>Keyframes</td>
<td>Placed on a fixed schedule</td>
<td>Also sent when a receiver asks for one</td>
</tr>
<tr>
<td>Versions</td>
<td>Made later by transcoding</td>
<td>Often encoded at the same time (simulcast)</td>
</tr>
<tr>
<td>Bitrate</td>
<td>Planned for the whole file</td>
<td>Adjusted continuously to the network</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h3 id="no-waiting-for-future-frames">No waiting for future frames</h3><p><a href="https://www.rfc-editor.org/rfc/rfc7742">RFC 7742</a> requires WebRTC browsers to implement VP8 and H.264 Constrained Baseline. Constrained Baseline is built on the <a href="https://www.itu.int/rec/T-REC-H.264">H.264</a> Baseline profile, which allows only I and P slices, so the mandatory H.264 profile has no B-frames. Apple's VideoToolbox documentation explains the cost: to encode B-frames, an encoder must reorder frames, which means holding them back.</p><p>The same documentation notes that an offline encoder may work slower than real time to produce a better result. A live encoder has no such option, so it searches less and accepts slightly larger frames.</p><h3 id="keyframes-on-request-and-several-versions-at-once">Keyframes on request, and several versions at once</h3><p>A file encoder places keyframes on a schedule. In a call, receivers also ask for them. A Picture Loss Indication, defined in <a href="https://www.rfc-editor.org/rfc/rfc4585">RFC 4585</a>, reports lost pictures, and the sender may respond with an intra picture. A Full Intra Request in <a href="https://www.rfc-editor.org/rfc/rfc5104">RFC 5104</a> asks for a decoder refresh point at the earliest opportunity, such as when a new participant needs a starting frame.</p><p>Real-time senders also encode more than one version. <a href="https://www.rfc-editor.org/rfc/rfc8853">RFC 8853</a> calls sending several differently encoded versions of the same source simulcast. The media server forwards whichever version each receiver can handle, as explained in <a href="https://www.videosdk.live/blog/what-is-simulcast">what is simulcast</a>.</p><h3 id="how-videosdk-configures-the-video-encoder">How VideoSDK configures the video encoder</h3><p>In the VideoSDK JavaScript SDK, you choose encoder settings when you create a camera track, by passing a named preset as encoderConfig. The <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track">optimize video track guide</a> lists 18 presets. The common 16:9 ones are below.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Preset</th>
<th>Resolution</th>
<th>Frame rate</th>
<th>Bitrate: bandwidth optimized / balanced / high quality</th>
</tr>
</thead>
<tbody>
<tr>
<td>h180p_w320p</td>
<td>320 x 180</td>
<td>15 fps</td>
<td>100 / 150 / 250 kbps</td>
</tr>
<tr>
<td>h360p_w640p</td>
<td>640 x 360</td>
<td>20 fps</td>
<td>200 / 400 / 600 kbps</td>
</tr>
<tr>
<td>h540p_w960p</td>
<td>960 x 540</td>
<td>25 fps</td>
<td>350 / 550 / 800 kbps</td>
</tr>
<tr>
<td>h720p_w1280p (default)</td>
<td>1280 x 720</td>
<td>30 fps</td>
<td>1,000 / 1,500 / 2,000 kbps</td>
</tr>
<tr>
<td>h1080p_w1920p</td>
<td>1920 x 1080</td>
<td>30 fps</td>
<td>1,600 / 2,200 / 2,700 kbps</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Four more options decide how the encoder behaves when the network gets worse:</p><ul><li><strong>bitrateMode</strong> picks the bitrate column: bandwidth_optimized, balanced (the default), or high_quality.</li><li><strong>optimizationMode</strong> decides what to give up first. The default, motion, lowers resolution to protect frame rate. The text and detail modes lower frame rate to keep resolution sharp, which suits slides and code.</li><li><strong>multiStream</strong> turns simulcast on, and it is on by default for camera tracks. A 720p camera sends 720p, 360p, and 180p layers, and maxLayer set to 2 keeps only the highest and lowest.</li><li><strong>codec</strong> selects VP8 (the default), H.264, VP9, or AV1. VideoSDK does not support multiStream with VP9 or AV1, so those codecs send one layer.</li></ul><p>The SDK reference also notes that for calls of four people or fewer, turning multiStream off is regarded as best practice. If a receiver cannot decode the chosen codec, the video codecs guide says VideoSDK switches the stream to VP8.</p><h2 id="encoding-settings-that-affect-quality">Encoding settings that affect quality</h2><p>Six settings decide most of the quality any video encoder produces: bitrate, resolution, frame rate, GOP length, profile, and rate control.</p><ol><li><strong>Bitrate.</strong> The number of bits per second the encoder may spend. More bits keep more detail, with diminishing returns. See <a href="https://www.videosdk.live/blog/what-is-bitrate">what is bitrate</a>.</li><li><strong>Resolution.</strong> At a fixed bitrate, more pixels means fewer bits per pixel, so a lower resolution can look cleaner on a weak connection.</li><li><strong>Frame rate.</strong> Higher frame rates look smoother but need more bits. VideoSDK's presets use 15 fps at the smallest sizes and 30 fps from 720p up.</li><li><strong>GOP length (keyframe interval).</strong> The distance between keyframes. Apple's <a href="https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices">HLS authoring specification</a> says keyframes should appear every two seconds. Longer gaps save bits but slow recovery after loss.</li><li><strong>Profile.</strong> A profile limits which coding tools an encoder may use. H.264 Baseline allows only I and P slices, while Main adds B slices, which improve compression but add delay.</li><li><strong>Rate control.</strong> Constant bitrate (CBR) holds a steady rate, which suits live links. Variable bitrate (VBR) spends more on complex scenes. The x264 help text describes CRF as quality-based VBR, which targets a quality level instead of a size.</li></ol><p>For viewers on mixed networks, you encode several versions and let the player switch between them, which is <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming">adaptive bitrate streaming</a>.</p><h2 id="definitions-glossary">Definitions glossary</h2><blockquote><strong>Codec:</strong> The standard for compressing and decompressing video, such as H.264, VP8, VP9 or AV1, plus the encoders that implement it. VideoSDK's JavaScript SDK uses VP8 by default.</blockquote><blockquote><strong>Container:</strong> The format that wraps encoded video, audio and timing data, such as MP4 or WebM. It compresses nothing, so it cannot change picture quality.</blockquote><blockquote><strong>Transcoding:</strong> Decoding an encoded stream and encoding it again in another codec, resolution or bitrate. VideoSDK's Server SDK Transcodings API turns finished recordings and HLS streams into MP4 files.</blockquote><blockquote><strong>Keyframe (I-frame):</strong> A frame coded without reference to other frames, so a decoder can start from it. In a video call, a receiver can prompt one with a PLI or FIR message.</blockquote><blockquote><strong>Simulcast:</strong> Sending several differently encoded versions of one video at once, as RFC 8853 describes. VideoSDK's multiStream option sends 720p, 360p and 180p layers from a 720p camera.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>Video encoding turns raw frames into a compressed stream, and transcoding decodes and re-encodes an existing stream into another format or size.</li><li>A codec such as H.264, VP9, or AV1 compresses the pictures, while a container such as MP4 or WebM packages them.</li><li>Hardware encoders save CPU and software encoders offer finer control, but quality depends on the encoder, the preset, and the content.</li><li>Real-time encoding avoids B-frames, sends keyframes on request, and often encodes simulcast layers, which VideoSDK's JavaScript SDK controls through encoderConfig, bitrateMode, and multiStream.</li></ul><h2 id="conclusion">Conclusion</h2><p>Video encoding is a set of trade-offs between size, quality, delay, and compute, and the right trade depends on whether video is a file or a live conversation. File pipelines can look ahead and transcode later. Real-time apps must encode every frame as it arrives.</p><p>To try real-time encoding yourself, start with the <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start">JavaScript quickstart</a> and sign up at <a href="https://app.videosdk.live/login" rel="noreferrer">VideoSDK</a> with a $20 free credit. </p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-the-difference-between-encoding-and-transcoding">What is the difference between encoding and transcoding?</h3><p>The difference is the input. Encoding compresses raw frames from a camera or screen into a codec such as H.264. Transcoding takes a stream that is already encoded, decodes it, and encodes it again in another codec, resolution, or bitrate.</p><h3 id="is-mp4-a-codec-or-a-container">Is MP4 a codec or a container?</h3><p>MP4 is a container, not a codec. It wraps encoded video, audio, and timing data, and the video inside is usually H.264, H.265, or AV1. WebM is also a container, typically holding VP8 or VP9 video.</p><h3 id="what-is-the-difference-between-h264-and-h265">What is the difference between H.264 and H.265?</h3><p>H.265, also called HEVC, is the successor to H.264. ITU said at its 2013 launch that it needs about half the bitrate of H.264, though real savings depend on the content and the encoder. WebRTC browsers are only required to support H.264 and VP8.</p><h3 id="why-dont-video-calls-use-b-frames">Why don't video calls use B-frames?</h3><p>Video calls avoid B-frames because a B-frame depends on a later frame, so the encoder must wait before sending it. WebRTC's mandatory H.264 profile, Constrained Baseline, allows only I and P slices, which keeps delay down.</p><h3 id="does-video-encoding-reduce-quality">Does video encoding reduce quality?</h3><p>Yes, the lossy video encoding used for streaming and calls discards detail to save bits. At a sensible bitrate most viewers do not notice. Each transcode removes a little more, which is why pipelines try to encode as few times as possible.</p><h3 id="which-video-codec-does-videosdk-use">Which video codec does VideoSDK use?</h3><p>VideoSDK's JavaScript SDK uses VP8 by default and also supports H.264, VP9, and AV1 through the codec option. Simulcast works with VP8 and H.264. If a receiver cannot decode the chosen codec, VideoSDK switches the stream to VP8.</p>]]></content:encoded></item><item><title><![CDATA[What is a Video Chat API? Pricing and How to Add One]]></title><description><![CDATA[ A video chat API runs the rooms, tokens, signaling, TURN relays and media servers behind a live video call. What it is, how it differs from a video chat SDK, what VideoSDK, Twilio Video, Agora and Daily charge per participant minute, and the steps to add one to your app.]]></description><link>https://www.videosdk.live/blog/video-chat-api</link><guid isPermaLink="false">6aa3ad97b3240feb748c9d72</guid><category><![CDATA[video-conferencing]]></category><category><![CDATA[video calling]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 15 Sep 2026 06:48:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/07.png" medium="image"/><content:encoded><![CDATA[<blockquote>A video chat API is defined as a hosted service, such as VideoSDK, that creates video rooms, authenticates users with short-lived tokens, and routes audio and video over WebRTC. Your backend calls the API; a client SDK renders media.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/07.png" alt="What is a Video Chat API? Pricing and How to Add One"/><p>Adding a camera button to an app takes an afternoon. Keeping that call connected for a user on hotel Wi-Fi, behind a firewall that blocks direct connections, is the part that takes a team.</p><p>A hosted API is how most products skip that second part. You get the servers, relays, and signaling as a service, and you write the interface.</p><p>This guide covers what a video chat API is, how it differs from a video chat SDK, and what happens on the network during a call. It then lists the features worth checking and what four providers charge, and ends with the integration steps on VideoSDK.</p><h2 id="what-is-a-video-chat-api">What is a video chat API?</h2><p>A video chat API is the server side of live video, delivered as a service you call instead of infrastructure you run.</p><p>A video chat API is defined as a set of REST endpoints and client libraries that create rooms, admit authenticated participants, and move real-time audio and video between their devices. It works by placing a media server between participants, so each device uploads its stream once and the server forwards it to everyone else.</p><p>The category goes by several names. Video chat API, video chatting API, video calling API, and video conferencing API all describe the same product. That is why a search for video chat APIs returns calling and conferencing pages side by side.</p><p>What you are buying is the part of a call nobody sees. That includes a signaling service that reconnects dropped users and media servers close to your users. It also includes TURN relays for networks that block direct traffic, plus recording and streaming your server can trigger.</p><p>VideoSDK's <a href="https://www.videosdk.live/audio-video-conferencing">video conferencing API</a> is built around the Room. Your backend creates a room over REST and signs a token for each participant. The participant then joins from a client SDK for React, JavaScript, React Native, Android, iOS, Flutter, Unity, C++, IoT, or Python.</p><h2 id="video-chat-api-vs-video-chat-sdk">Video Chat API vs Video Chat SDK</h2><p>The API and the SDK are two halves of one product, and you need both. The API runs on your server; the SDK runs in your user's app.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th/>
<th>Video chat API</th>
<th>Video chat SDK</th>
</tr>
</thead>
<tbody>
<tr>
<td>Where it runs</td>
<td>Your backend, called with your secret</td>
<td>Inside the browser or mobile app</td>
</tr>
<tr>
<td>What it does</td>
<td>Creates rooms, issues tokens, starts and stops recording, sends webhooks</td>
<td>Captures camera and microphone, sends media, renders other participants</td>
</tr>
<tr>
<td>What it holds</td>
<td>Your API key and secret</td>
<td>A short-lived token only</td>
</tr>
<tr>
<td>Typical actions</td>
<td>Create a room, start recording, fetch recordings</td>
<td>Join, mute and unmute, turn the camera on and off, leave</td>
</tr>
<tr>
<td>When you touch it</td>
<td>Before and after the call, and for server-side control</td>
<td>Everything the user sees and hears during the call</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The token is the handoff between the two. Your server signs it with the secret, the app passes it to the SDK, and the secret never reaches the client.</p><p>In practice, teams integrate video chat API calls on the server and integrate video chat SDK components in the client, in that order. The confusion comes from marketing, where vendors headline whichever half their buyer searched for.</p><p>A useful test when comparing vendors is to ask where the media server runs. If the vendor runs it, you are buying an API and the SDK comes with it. If you run it, you are adopting a library, and the servers and relays are yours to build.</p><h2 id="how-a-video-chat-api-works">How a video chat API works</h2><p>Every video chat call passes through the same six components, and the first one runs on your server before the user sees a camera preview.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/video-call-session-sequence.png" class="kg-image" alt="What is a Video Chat API? Pricing and How to Add One" loading="lazy" width="2880" height="2050"/></figure><ol><li><strong>Your backend.</strong> Your server creates a room through the REST API and signs a <a href="https://datatracker.ietf.org/doc/html/rfc7519">JSON Web Token</a> (JWT) for the participant. The token carries your API key, a join permission, and an expiry.</li><li><strong>Signaling.</strong> The client SDK connects to the provider's signaling service and exchanges session descriptions with the media server. These list the codecs and media each side can send, in the offer and answer format that <a href="https://www.w3.org/TR/webrtc/">WebRTC</a> standardises.</li><li><strong>STUN.</strong> Each device asks a <a href="https://datatracker.ietf.org/doc/html/rfc8489">STUN</a> server for its public address, since most devices sit behind a router that hides it. That address becomes one of several <a href="https://datatracker.ietf.org/doc/html/rfc8445">ICE</a> candidates, and ICE picks the path that works.</li><li><strong>TURN.</strong> When no direct path works, the connection falls back to a <a href="https://datatracker.ietf.org/doc/html/rfc8656">TURN</a> server that relays the media. Relayed calls cost real bandwidth, which is why TURN is among the first things to break in a self-built stack.</li><li><strong>SFU.</strong> The selective forwarding unit is the media server. It receives one upload from each participant and forwards copies to everyone who subscribes, without re-encoding them.</li><li><strong>Media tracks.</strong> Each participant publishes an audio track and a video track. Your interface subscribes to tracks, not people, so a participant can appear a moment before their video does.</li></ol><p>WebRTC encrypts media in transit using DTLS-SRTP, as its <a href="https://datatracker.ietf.org/doc/html/rfc8827">security architecture</a> requires. In a standard SFU deployment the server terminates that encryption to forward packets, so encryption in transit is not the same as end-to-end encryption. Ask any provider which one they mean before it goes into a security review. For a privacy-sensitive worked example, see VideoSDK's guide to <a href="https://www.videosdk.live/blog/secure-video-chat-react-native-dating-app">secure video chat in a React Native dating app</a>.</p><p>The SFU is also why a group video chat API scales. In a peer-to-peer mesh, a five-person call means four uploads from every device. Through an SFU, each device uploads once however large the room gets. VideoSDK's <a href="https://www.videosdk.live/blog/webrtc">WebRTC explainer</a> covers the protocol layer underneath in more depth.</p><h2 id="video-chat-api-features-to-look-for">Video chat API features to look for</h2><p>Every provider handles a 1:1 call. The features below are where providers actually differ, and each one is cheaper to check now than to discover missing after launch.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Feature</th>
<th>Why it matters</th>
<th>VideoSDK documentation</th>
</tr>
</thead>
<tbody>
<tr>
<td>Group calls</td>
<td>Depends on the SFU and on account-wide concurrency. VideoSDK's quota page lists 50 concurrent hosts on the free plan and 500 on pay-as-you-go.</td>
<td><a href="https://docs.videosdk.live/help_docs/quotas-and-limit">Usage quotas</a></td>
</tr>
<tr>
<td>Screen share</td>
<td>Support, tutoring, and sales calls need it, and it publishes as a separate track.</td>
<td><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/handling-media/screen-share">Screen share</a></td>
</tr>
<tr>
<td>In-call chat</td>
<td>Text alongside video, for links and for users whose microphone fails. VideoSDK builds it on its PubSub messaging.</td>
<td><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/chat-using-pubsub">Chat using PubSub</a></td>
</tr>
<tr>
<td>Recording</td>
<td>Check composite versus per-participant files, and whether they can land in your own storage bucket.</td>
<td><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/recording/Overview">Recording overview</a></td>
</tr>
<tr>
<td>Noise suppression</td>
<td>Background noise is a common complaint on mobile calls. VideoSDK's plugin is labelled beta in its docs.</td>
<td><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/plugins/noise-suppresion">Noise suppression</a></td>
</tr>
<tr>
<td>HLS for large audiences</td>
<td>When a call becomes a broadcast, HLS carries far more viewers than an interactive room, with more delay.</td>
<td><a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/integrate-hls/overview">HLS overview</a></td>
</tr>
<tr>
<td>SIP dial-in</td>
<td>Lets someone join from a phone number when their data connection is poor.</td>
<td><a href="https://docs.videosdk.live/telephony/introduction">Telephony and SIP</a></td>
</tr>
<tr>
<td>Transcription</td>
<td>Captions during the call, or a transcript and summary after it.</td>
<td><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/transcription-and-summary/realtime-transcribe-meeting">Real-time transcription</a></td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Two more items rarely appear on feature pages. The first is platform coverage: list every client you will ship in the next two years and confirm an SDK exists for each. The second is the token model, because tokens with a short expiry stop a leaked room link from becoming an open door.</p><p>Read these video chat API features as a filter, not a scorecard. Most products need four or five on day one, and the rest decide which provider you can grow into.</p><h2 id="how-to-add-video-chat-to-your-app">How to add video chat to your app</h2><p>Adding video chat takes two pieces of work: a server route that issues tokens and creates rooms, and a client screen that joins a room and shows participants.</p><p>The steps below follow VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a> and its <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token">authentication and token guide</a>. The same order applies on every platform VideoSDK supports. Only the client library changes.</p><ol><li><strong>Get your API key and secret.</strong> Create a VideoSDK account and copy both from the dashboard. The secret belongs in your server's environment variables, never in an app bundle.</li><li><strong>Issue a token on your server.</strong> Your backend signs a JWT with the secret, carrying your API key, a join permission, and an expiry. VideoSDK's token guide uses 120 minutes in its example. The quickstart keeps a token in client code to shorten the demo, so move it server-side before you ship.</li><li><strong>Create a room.</strong> Your server calls the REST API's create-room endpoint with that token and gets back a room ID. Store the ID against your own record, such as the appointment, class, or support ticket, then send it to the client with a token.</li><li><strong>Join from the client SDK.</strong> In React, the call sits inside VideoSDK's meeting provider, configured with the room ID and token. A meeting hook exposes join, leave, and the microphone and camera toggles, and a participant hook gives you each person's streams.</li><li><strong>Render video and audio separately.</strong> VideoSDK's React video player renders video only. Each participant's audio needs its own audio element fed from their microphone stream, muted for the local user. Miss this and the call looks right, but nobody can hear anyone.</li><li><strong>Test on HTTPS.</strong> Browsers grant camera and microphone access only in a <a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia">secure context</a>, meaning HTTPS or localhost. A staging server on plain HTTP fails at the permission prompt, not in the SDK.</li></ol><p>Open the page in two browser tabs and join the same room from both, and you should see two participants. VideoSDK's <a href="https://docs.videosdk.live/code-sample">code samples</a> hold complete, runnable versions of this flow for each platform.</p><h3 id="embed-video-chat-without-building-the-ui">Embed video chat without building the UI</h3><p>To embed video chat API features without designing an interface, use VideoSDK's <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Prebuilt UI kit</a>. It drops a complete call screen into a page and uses the same room and token model, so you can move to a custom interface later.</p><h3 id="pick-the-quickstart-for-your-platform">Pick the quickstart for your platform</h3><p>Steps 1 to 3 stay identical on every platform, because they run on your server. For the client, start from the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a> or the <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start">JavaScript quickstart</a>, or go to <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start">Flutter</a>, <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/quick-start">Android</a>, or <a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start">iOS</a>.</p><p><strong>Try it on your own account:</strong> <a href="https://app.videosdk.live/login">sign up for VideoSDK</a> and use the $20 free credit to run a quickstart end to end.</p><p>Prefer to see it running? This 4-minute walkthrough builds the React group video call above, from an empty folder to two browser windows in the same room. It takes its token from the dashboard to keep the demo short, so switch to a server-issued token before you ship, as step 2 explains.</p>
<!--kg-card-begin: html-->
<iframe width="700" height="415" src="https://www.youtube.com/embed/Auxjhx0_T1s?si=IlH7CP0sWoeJ2qJp" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<h3 id="what-a-video-chat-api-costs">What a video chat API costs</h3><p>Video chat API pricing is per participant minute: one person connected for one minute. A three-person, 20-minute call is 60 participant minutes, and an empty room costs nothing.</p><p>Rates below were read from each vendor's pricing page on September 11, 2026. Watch the units, because Agora quotes per 1,000 minutes.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Provider</th>
<th>Video, per participant minute</th>
<th>Audio only, per participant minute</th>
<th>Free allowance</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td>$0.004 (HD 720p), $0.008 (Full HD)</td>
<td>$0.001</td>
<td>$20 free credit on signup, one time</td>
</tr>
<tr>
<td>Twilio Video</td>
<td>$0.004 (Group Rooms)</td>
<td>Not listed separately</td>
<td>No free minutes listed; first 10 GB of recording storage free</td>
</tr>
<tr>
<td>Agora</td>
<td>$0.00399 HD ($3.99 per 1,000 minutes), $0.00899 Full HD</td>
<td>$0.00099 ($0.99 per 1,000 minutes)</td>
<td>10,000 minutes per month</td>
</tr>
<tr>
<td>Daily</td>
<td>$0.004 from 10,001 to 100,000 minutes a month, falling in tiers to $0.0015 above 50 million</td>
<td>$0.00099, falling to $0.00036</td>
<td>10,000 minutes per month</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Three things stand out, and not all of them favour VideoSDK.</p><p>The entry rate is effectively identical. All four charge about $0.004 per participant minute for HD video at low volume, so the headline rate does not separate them.</p><p>The free allowances differ. Agora and Daily include 10,000 minutes every month. VideoSDK gives a one-time $20 credit, which covers 5,000 participant minutes of HD video. For a product that stays small, the recurring allowance is worth more.</p><p>Daily is the only one of the four that publishes volume discounts on its pricing page. Agora bills video by aggregate subscribed resolution, the combined pixels of every stream a user receives. A user watching several small tiles can therefore land in a higher tier than any single stream suggests. For a comparison beyond price, VideoSDK's <a href="https://www.videosdk.live/blog/10-best-video-calling-apis">video calling API roundup</a> covers ten providers.</p><h2 id="why-teams-switch-video-chat-providers">Why teams switch video chat providers</h2><p>When entry rates sit within a fraction of a cent of each other, teams rarely switch providers over price. They switch over support and product quality, or because their current provider is ending the service.</p><p>Felicity, an India-based teletherapy platform that runs counselling over video, audio, and chat. Its <a href="https://www.videosdk.live/customers/felicity">case study</a> says the team had to move because its previous video provider was shutting down. Felicity completed the migration in 48 hours and reports 70% fewer technical issues in counselling sessions. </p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-09-11-at-4.38.35-PM.png" class="kg-image" alt="What is a Video Chat API? Pricing and How to Add One" loading="lazy" width="1814" height="734"/></figure><h2 id="glossary">Glossary</h2><blockquote><strong>Room:</strong> The container a video chat happens in, identified by a room ID. Participants join a room, and server-side operations such as recording target that room ID.</blockquote><blockquote><strong>Meeting token:</strong> A JWT your server signs with your API secret that lets a participant join. VideoSDK tokens carry a join permission and an expiry.</blockquote><blockquote><strong>SFU (selective forwarding unit):</strong> The media server that receives one stream from each participant and forwards copies to the others without re-encoding them.</blockquote><blockquote><strong>Participant minute:</strong> The billing unit for almost every provider in this category. One person connected for one minute is one participant minute.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>A video chat API is the hosted server side of live video: rooms, tokens, signaling, TURN relays, and an SFU that forwards each participant's stream.</li><li>The API and the video chat SDK are two halves of one integration, joined by a token your server signs, so the API secret never reaches the client.</li><li>VideoSDK, Twilio Video, Agora, and Daily all charge about $0.004 per participant minute for HD video at entry volume, so features and free allowances decide the choice.</li><li>VideoSDK uses one room and token model across React, JavaScript, React Native, Android, iOS, Flutter, and more, so one backend serves every client you ship.</li></ul><h2 id="conclusion">Conclusion</h2><p>A hosted API trades a media engineering project for a per-minute bill. Signaling, STUN, TURN, and the <a href="https://www.videosdk.live/blog/sfu-vs-mcu-vs-mesh-webrtc" rel="noreferrer">SFU</a> become the provider's problem, and your work shrinks to a token route and a call screen.</p><p>Choose on features and free allowance rather than the headline rate, and price the recording and transcription you will use. To try VideoSDK's video chat API, start with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a>, check live rates on the <a href="https://www.videosdk.live/pricing">pricing page</a>, and <a href="https://app.videosdk.live/login">sign up</a> for $20 free credit.</p><p>What kind of video chat are you adding to your app? Drop a comment, or ask in the <a href="https://discord.gg/Gpmj6eCq5u">VideoSDK Discord</a>.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="how-to-create-a-video-chat-app">How to create a video chat app?</h3><p>To create a video chat app, choose a provider and add a server route that signs a token and creates a room. Then add a client component that joins the room and renders each participant. With VideoSDK, the server side stays the same on every platform, and the React, Flutter, Android, and iOS quickstarts cover the client.</p><h3 id="what-is-the-difference-between-a-video-chat-api-and-a-video-chat-sdk">What is the difference between a video chat API and a video chat SDK?</h3><p>The API is the server-side surface your backend calls with its secret to create rooms, issue tokens, and control recording. The video chat SDK is the client library inside your app that captures, sends, and renders media. A working integration uses both, with the token as the handoff.</p><h3 id="how-much-does-a-video-chat-api-cost">How much does a video chat API cost?</h3><p>A video chat API typically costs about $0.004 per participant minute for HD video. As of September 11, 2026, VideoSDK, Twilio Video, and Daily list $0.004 at entry volume, and Agora lists $3.99 per 1,000 minutes. Recording and transcription are billed separately and often cost more than the call.</p><h3 id="is-there-a-free-video-chat-api">Is there a free video chat API?</h3><p>There is no fully free hosted option for production, but each major provider has a free entry point. Agora and Daily include 10,000 minutes every month, and VideoSDK gives a one-time $20 free credit, enough for 5,000 participant minutes of HD video. Open-source media servers are free to license but move the server cost to you.</p><h3 id="can-i-embed-a-video-chat-sdk-without-building-the-ui">Can I embed a video chat SDK without building the UI?</h3><p>Yes. To embed video chat SDK features without writing an interface, use a prebuilt UI kit. VideoSDK's Prebuilt option drops a complete call screen into a page. It shares the room and token model with the custom SDK, so you can switch to a custom interface later.</p><h3 id="can-a-live-video-chat-api-handle-group-calls">Can a live video chat API handle group calls?</h3><p>Yes, a live video chat API handles group calls through an SFU, which takes one upload from each participant and forwards it to the others. The limit that usually matters is account-wide concurrency rather than room size. VideoSDK's quota documentation lists 50 concurrent hosts on the free plan and 500 on pay-as-you-go.</p><h3 id="is-webrtc-a-video-chat-api">Is WebRTC a video chat API?</h3><p>No. WebRTC is the open standard for capturing and sending real-time media in browsers and apps, and it has no servers of its own. An online video chat API is a hosted service built on WebRTC that adds signaling, TURN relays, an SFU, room management, and recording.</p>]]></content:encoded></item><item><title><![CDATA[What is SRTP?]]></title><description><![CDATA[SRTP encrypts every WebRTC call and most secure VoIP calls, but encrypted in transit is not end-to-end. How SRTP protects RTP packets, how DTLS-SRTP, SDES and ZRTP exchange keys, which ciphers and ports it uses, and what a media server can still see.]]></description><link>https://www.videosdk.live/blog/srtp</link><guid isPermaLink="false">6aa3cb03b3240feb748c9d8d</guid><category><![CDATA[WebRTC]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 15 Sep 2026 06:22:44 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/08.png" medium="image"/><content:encoded><![CDATA[<blockquote>SRTP (Secure Real-time Transport Protocol) is defined as the IETF profile of RTP, published as RFC 3711, that encrypts the payload of every voice and video packet, authenticates each packet, and rejects replayed ones. WebRTC requires it for all audio and video.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/08.png" alt="What is SRTP?"/><p>Every audio and video stream in a standards-compliant WebRTC call is encrypted with SRTP. You cannot turn it off, because the WebRTC security architecture forbids unencrypted media.</p><p>That makes SRTP the media encryption most developers rely on without ever configuring it. It is also widely misread. "Encrypted with SRTP" and "end-to-end encrypted" are different claims, and the difference decides who can see your users' video.</p><p>This guide covers what SRTP protects, how its keys are exchanged, and which ciphers and ports it uses in WebRTC, SIP, and VoIP. It ends with why a group call through a media server is encrypted hop by hop, not end to end.</p><h2 id="what-is-srtp">What is SRTP?</h2><p>SRTP (Secure Real-time Transport Protocol) is the encrypted form of RTP, the protocol that carries nearly every live voice and video packet on the internet.</p><p>SRTP is defined as a profile of the Real-time Transport Protocol (RTP, RFC 3550) that adds confidentiality, message authentication, and replay protection to RTP and to its control protocol, RTCP. The IETF published it as <a href="https://www.rfc-editor.org/rfc/rfc3711">RFC 3711</a> in March 2004. SRTP works by encrypting each packet's payload with a session key, then appending an authentication tag computed over the header and the encrypted payload.</p><p>You will see it called secure RTP, the secure real time transport protocol, or the shorter secure real time protocol. All three names point to the same RFC 3711 profile. Its protected control channel is SRTCP.</p><p>SRTP does not set up calls or exchange keys. Signalling, such as SIP or a WebRTC app's own messaging, sets up the call, and a separate key exchange gives both ends the same master key. SRTP protects the media once that key exists. For the unencrypted base protocol, its packet layout, and RTCP, see <a href="https://www.videosdk.live/blog/what-is-rtp-protocol">what RTP is and how WebRTC uses it</a>.</p><p>VideoSDK's <a href="https://docs.videosdk.live/help_docs/security-and-privacy/hipaa">HIPAA documentation</a> lists SRTP for media encryption and TLS for network traffic. Its <a href="https://docs.videosdk.live/help_docs/security-and-privacy/soc2">SOC 2</a> and <a href="https://docs.videosdk.live/help_docs/security-and-privacy/gdpr">GDPR</a> pages describe data in transit as protected by TLS and SRTP.</p><h2 id="how-srtp-works">How SRTP works</h2><p>SRTP encrypts the payload of every RTP packet and authenticates the whole packet, so an attacker on the path can neither read the media nor alter it unnoticed.</p><p>The diagram below lays out a single SRTP packet the way RFC 3711 draws it, 32 bits per row. The header rows at the top are sent in the clear, and the payload and padding, shaded blue, are encrypted with AES in counter mode. The bracket on the right shows that HMAC-SHA1 authenticates everything from the first header bit to the pad count, and the optional MKI and the authentication tag follow at the end.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/srtp-packet-diagram.png" class="kg-image" alt="What is SRTP?" loading="lazy" width="2800" height="1236"/></figure><h3 id="what-srtp-encrypts-and-what-it-authenticates">What SRTP encrypts and What it authenticates</h3><p>An SRTP packet keeps the normal 12-byte RTP header readable. The header carries the sequence number, timestamp, and synchronisation source (SSRC) that receivers and network equipment need, and RFC 3711 leaves it in the clear so header compression still works.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Part of the packet</th>
<th>Encrypted</th>
<th>Authenticated</th>
</tr>
</thead>
<tbody>
<tr>
<td>RTP header, including CSRCs and header extensions</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>Payload (the audio or video data, plus padding)</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Master key identifier (MKI), optional</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>Authentication tag, 80 bits by default</td>
<td>No</td>
<td>It is the tag</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>RFC 3711 does not encrypt header extensions. <a href="https://www.rfc-editor.org/rfc/rfc6904">RFC 6904</a> (April 2013) added selective encryption for them, and <a href="https://www.rfc-editor.org/rfc/rfc9335">RFC 9335</a> (January 2023), known as Cryptex, encrypts header extensions and CSRC lists completely.</p><h3 id="session-keys-the-rollover-counter-and-replay-protection">Session keys, the rollover counter, and replay protection</h3><p>Both ends start from a shared master key, 128 bits by default, and a 112-bit master salt. SRTP runs a key derivation function over them to produce separate session keys for encryption, authentication, and salting.</p><p>Each packet gets a 48-bit index made from the 16-bit RTP sequence number and a 32-bit rollover counter (ROC) that counts how many times the sequence number has wrapped. The index feeds the cipher, so packets in a stream never reuse the same keystream.</p><p>The receiver keeps a replay list, a sliding window of at least 64 packets, and drops any packet whose index it has already accepted. An attacker who records packets cannot inject them again later.</p><h3 id="srtcp-and-the-cost-of-encryption">SRTCP and the cost of encryption</h3><p>RTCP carries the loss, jitter, and round-trip reports that adaptive bitrate depends on. SRTCP protects it the same way, with two differences. Authentication is mandatory for SRTCP, where RFC 3711 only recommends it for SRTP. Each SRTCP packet also carries a 31-bit index and an E flag that marks whether it is encrypted.</p><p>The overhead is small and fixed. With the default suite, SRTP adds a 10-byte authentication tag to each packet, and counter-mode encryption does not change the payload length. The 32-bit tag variant adds 4 bytes, and AES-GCM adds a 16-byte tag.</p><h2 id="key-exchange-dtls-srtp-vs-sdes-vs-zrtp">Key exchange: DTLS-SRTP vs SDES vs ZRTP</h2><p>SRTP needs both ends to hold the same master key, and the three ways of delivering it differ mainly in who else can see that key.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th/>
<th>DTLS-SRTP</th>
<th>SDES</th>
<th>ZRTP</th>
</tr>
</thead>
<tbody>
<tr>
<td>Specification</td>
<td><a href="https://www.rfc-editor.org/rfc/rfc5764">RFC 5764</a> and <a href="https://www.rfc-editor.org/rfc/rfc5763">RFC 5763</a>, May 2010</td>
<td><a href="https://www.rfc-editor.org/rfc/rfc4568">RFC 4568</a>, July 2006</td>
<td><a href="https://www.rfc-editor.org/rfc/rfc6189">RFC 6189</a>, April 2011, Informational</td>
</tr>
<tr>
<td>Where the key travels</td>
<td>Derived from a DTLS handshake on the media path</td>
<td>Written into the SDP on the signalling path, in an a=crypto line</td>
<td>Diffie-Hellman exchange on the media path</td>
</tr>
<tr>
<td>Visible to the signalling server</td>
<td>No, signalling carries only a certificate fingerprint</td>
<td>Yes, any server that handles the SDP can read it</td>
<td>No</td>
</tr>
<tr>
<td>How the ends verify each other</td>
<td>The DTLS certificate must match the fingerprint in the SDP</td>
<td>Depends on the signalling channel being protected</td>
<td>Users compare a short authentication string (SAS)</td>
</tr>
<tr>
<td>Where you meet it</td>
<td>Mandatory in WebRTC</td>
<td>SIP phones, PBXs, and SIP trunks</td>
<td>Some secure SIP softphones</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>WebRTC chose DTLS-SRTP. <a href="https://www.rfc-editor.org/rfc/rfc8827">RFC 8827</a>, the WebRTC security architecture, requires DTLS-SRTP for every media channel and forbids offering or accepting SDES. The companion document, RFC 8826, gives the reason: a calling service that holds the keying material, as it does with SDES, can decrypt the call.</p><p>With DTLS-SRTP, the DTLS handshake runs on the same port as the media. Both ends then export the SRTP keys from it, and the signalling server never sees them.</p><p>SDES is simpler and still common in SIP. RFC 4568 requires the signalling that carries the key to be protected for confidentiality and integrity. For SIP it prefers SIPS or S/MIME, and calls relying on transport TLS alone not recommended, because SIP proxies along the path can still read the key.</p><h2 id="srtp-ciphers-and-key-lengths">SRTP ciphers and key lengths</h2><p>SRTP's default is AES-128 in counter mode with an 80-bit HMAC-SHA1 tag, and newer AES-GCM profiles replace the separate HMAC with authenticated encryption.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Suite (SDES name, DTLS-SRTP name)</th>
<th>Cipher and key</th>
<th>Master salt</th>
<th>Authentication tag</th>
<th>Defined in, and where it applies</th>
</tr>
</thead>
<tbody>
<tr>
<td>AES_CM_128_HMAC_SHA1_80, SRTP_AES128_CM_HMAC_SHA1_80</td>
<td>AES-128, counter mode</td>
<td>112 bits</td>
<td>HMAC-SHA1, 80 bits</td>
<td>RFC 3711 default; the one suite every WebRTC endpoint must support</td>
</tr>
<tr>
<td>AES_CM_128_HMAC_SHA1_32, SRTP_AES128_CM_HMAC_SHA1_32</td>
<td>AES-128, counter mode</td>
<td>112 bits</td>
<td>HMAC-SHA1, 32 bits on RTP, 80 on RTCP</td>
<td>RFC 5764; saves 6 bytes per packet with weaker integrity</td>
</tr>
<tr>
<td>AES_192_CM_HMAC_SHA1_80 and _32</td>
<td>AES-192, counter mode</td>
<td>112 bits</td>
<td>HMAC-SHA1, 80 or 32 bits</td>
<td><a href="https://www.rfc-editor.org/rfc/rfc6188">RFC 6188</a>; SDES only</td>
</tr>
<tr>
<td>AES_256_CM_HMAC_SHA1_80 and _32</td>
<td>AES-256, counter mode</td>
<td>112 bits</td>
<td>HMAC-SHA1, 80 or 32 bits</td>
<td>RFC 6188; SDES only</td>
</tr>
<tr>
<td>SRTP_AEAD_AES_128_GCM</td>
<td>AES-128, GCM</td>
<td>96 bits</td>
<td>16 bytes, built into GCM</td>
<td><a href="https://www.rfc-editor.org/rfc/rfc7714">RFC 7714</a>; DTLS-SRTP</td>
</tr>
<tr>
<td>SRTP_AEAD_AES_256_GCM</td>
<td>AES-256, GCM</td>
<td>96 bits</td>
<td>16 bytes, built into GCM</td>
<td>RFC 7714; DTLS-SRTP</td>
</tr>
<tr>
<td>SRTP_NULL_HMAC_SHA1_80 and _32</td>
<td>None</td>
<td>None</td>
<td>HMAC-SHA1, 80 or 32 bits</td>
<td>RFC 5764; integrity only, forbidden in WebRTC</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The DTLS-SRTP names and values come from the <a href="https://www.iana.org/assignments/srtp-protection">IANA SRTP protection profile registry</a>. RFC 3711 also defines AES in f8 mode as an optional alternative, but no DTLS-SRTP profile uses it.</p><p>In WebRTC you do not pick a suite by hand. The two ends negotiate one during the DTLS handshake, and RFC 8827 says they should favour the AEAD (GCM) profiles when both support them. On a SIP trunk, AES_CM_128_HMAC_SHA1_80 is the RFC 3711 default and the safest choice for interoperability.</p><h2 id="is-srtp-end-to-end-encryption">Is SRTP end-to-end encryption?</h2><p>No, not when media passes through a server that holds the keys, which is how most group calls and all server-side recording work.</p><p>SRTP protects each hop between two endpoints that share a key. In a one-to-one WebRTC call sent directly between two browsers, those endpoints are the two users, so the media is protected from end to end.</p><p>A group call is different. Each participant's SRTP session ends at a media server, usually a Selective Forwarding Unit (SFU). The server holds the keys for every leg, forwards the media, and re-encrypts it toward each receiver, so it can access the media in the clear.</p><p>That is not a defect. The server hop is what makes recording, transcription, and live streaming possible. It does mean that "encrypted with SRTP" describes encryption in transit, and the provider running the server sits inside your trust boundary.</p><h3 id="what-true-end-to-end-encryption-needs">What true end-to-end encryption needs</h3><p>End-to-end encryption in a group call needs a second layer of encryption on the media frames, applied before SRTP, with keys the server never holds.</p><ul><li><strong>SFrame</strong>, <a href="https://www.rfc-editor.org/rfc/rfc9605">RFC 9605</a> (August 2024), encrypts each media frame so an SFU can forward it without access to the media.</li><li><strong>WebRTC Encoded Transform</strong>, a <a href="https://www.w3.org/TR/webrtc-encoded-transform/">W3C Working Draft</a> as of June 2026, lets a browser app process encoded frames before they are packetised. That is where a frame-level encryption layer runs.</li><li><strong>PERC</strong>, <a href="https://www.rfc-editor.org/rfc/rfc8723">RFC 8723</a> (April 2020), defines double encryption: one hop-by-hop layer for the server and one end-to-end layer it cannot remove.</li></ul><p>The trade-off is direct. Once the server cannot read the media, server-side recording, transcription, and AI processing stop working unless a client does that work instead.</p><h3 id="what-videosdk-provides">What VideoSDK provides</h3><p>VideoSDK encrypts media in transit with SRTP and signalling with TLS. Media passes through VideoSDK's servers, which is what lets VideoSDK record, transcribe, and stream a call. A standard VideoSDK call is therefore encrypted hop by hop, in transit, and should not be described as end-to-end encrypted.</p><p>Recordings get their own layer at rest. With <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/recording/recording-encryption">recording encryption</a> turned on, each recording is encrypted with its own AES-256 key (GCM recommended, CTR supported). That key is wrapped with an RSA public key you upload before the file reaches your cloud storage. VideoSDK stores only the public key, so only the holder of your private key can decrypt the recording.</p><p>For how this maps to healthcare rules, see <a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api">HIPAA compliant video conferencing API requirements</a>.</p><p><strong>Building a call that needs this?</strong> VideoSDK applies SRTP and TLS to every room without configuration. Start with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a> and the $20 free credit.</p><h2 id="srtp-in-sip-and-voip">SRTP in SIP and VoIP</h2><p>In SIP and VoIP, a secure call needs two layers: TLS for the SIP signalling and SRTP for the media.</p><p><a href="https://www.rfc-editor.org/rfc/rfc3261">RFC 3261</a> sets port 5061 as the default for SIP over TLS and 5060 for UDP and TCP. The SDP inside the SIP message marks encrypted media with the RTP/SAVP profile and, when SDES is used, carries the key in an a=crypto line. That is why SRTP VoIP deployments using SDES should always run SIP over TLS: without it, the media key crosses the network readable.</p><p>When a WebRTC user calls a phone number, a gateway sits between the two worlds. It ends the DTLS-SRTP leg on the WebRTC side and speaks SIP to the carrier, using SRTP if the trunk supports it. Any call that reaches the public phone network leaves SRTP at the carrier boundary.</p><p>VideoSDK's inbound and outbound telephony gateways have a Media Encryption setting. With it on, VideoSDK uses <a href="https://docs.videosdk.live/telephony/managing-calls/secure-sip">TLS for SIP signalling and SRTP for media</a> and expects the carrier's signalling over TLS. The <a href="https://docs.videosdk.live/telephony/managing-calls/ip-whitelisting">IP whitelisting page</a> lists 5060 for TCP and UDP and 5061 for TLS. To connect a SIP trunk to a room, follow the <a href="https://docs.videosdk.live/react-native/guide/sip-connect/quick-start">SIP connect quickstart</a>.</p><h3 id="what-port-does-srtp-use">What port does SRTP use?</h3><p>There is no fixed SRTP port number. SRTP uses whichever ports RTP would, and those are usually negotiated dynamically in the SDP. <a href="https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml">IANA registers</a> 5004 and 5005 for RTP and RTCP, and RFC 3550 recommends an even port for RTP with RTCP on the next odd port.</p><p>WebRTC narrows this further. It multiplexes RTP and RTCP on one port (<a href="https://www.rfc-editor.org/rfc/rfc5761">RFC 5761</a>) and bundles audio, video, and data onto one transport (<a href="https://www.rfc-editor.org/rfc/rfc8843">RFC 8843</a>), so a call typically uses a single UDP port per connection.</p><p>SRTP does not change NAT traversal. ICE, STUN, and TURN find the network path, as explained in the <a href="https://www.videosdk.live/blog/webrtc">WebRTC guide</a>, and SRTP rides on whatever path they find. For VideoSDK firewall rules, the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/security/firewall-setup">firewall setup guide</a> lists UDP ports 40000 to 60000 for media, with TURN on port 3478 or TCP 443 as fallbacks.</p><h2 id="srtp-cyber-security-what-it-stops-and-what-it-leaves-exposed">SRTP cyber security: what it stops and what it leaves exposed</h2><p>In an SRTP cyber security review, the useful question is which attacks SRTP blocks and which it leaves to other layers.</p><p>SRTP stops three things on every network hop:</p><ul><li><strong>Eavesdropping.</strong> The audio and video content is unreadable without the session key.</li><li><strong>Tampering.</strong> A modified packet fails the authentication tag and is dropped.</li><li><strong>Replay.</strong> A recorded packet sent again is rejected by the replay list.</li></ul><p>SRTP leaves these to something else:</p><ul><li><strong>Headers and traffic patterns.</strong> Sequence numbers, timestamps, SSRCs, packet sizes, and timing stay visible, and so do header extensions unless RFC 6904 or Cryptex is in use.</li><li><strong>Signalling and chat.</strong> SRTP covers media only. Text in an SRTP chat or calling app travels over the signalling channel or a WebRTC data channel, protected by TLS or DTLS instead.</li><li><strong>The server hop.</strong> A media server that holds the keys can read the media, as explained above.</li><li><strong>The devices.</strong> Malware on a phone or laptop sees the media before it is encrypted.</li></ul><h2 id="key-takeaways">Key takeaways</h2><ul><li>SRTP encrypts RTP payloads with AES and authenticates each whole packet, blocking eavesdropping, tampering, and replay, while leaving headers readable.</li><li>The key exchange decides who can see the key: DTLS-SRTP keeps it off the signalling path, while SDES puts it in the SDP.</li><li>WebRTC mandates DTLS-SRTP and requires support for AES_CM_128_HMAC_SHA1_80, and should prefer AES-GCM when both ends support it.</li><li>SRTP through a media server is encryption in transit, not end-to-end encryption. VideoSDK uses SRTP and TLS in transit and offers encrypted recordings with a key only you hold.</li></ul><h2 id="conclusion">Conclusion</h2><p>SRTP is the reason live audio and video on the web is encrypted by default. It is also why "encrypted" needs a second question: encrypted between whom? Most group calls are protected on every network hop and readable at the server, which is what makes recording and transcription possible.</p><p>VideoSDK applies SRTP and TLS to every call and lets you encrypt recordings with your own key. Try it with the $20 free credit at <a href="https://app.videosdk.live/login" rel="noreferrer">VideoSDK</a>, or check <a href="https://www.videosdk.live/pricing">pricing</a>. What is your team's threat model for call media? </p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-srtp-protocol">What is SRTP protocol?</h3><p>SRTP protocol is the Secure Real-time Transport Protocol, defined in RFC 3711, which adds encryption, message authentication, and replay protection to RTP media. It protects the audio and video in WebRTC calls and in secure SIP and VoIP calls. The keys come from a separate exchange such as DTLS-SRTP or SDES.</p><h3 id="what-is-the-difference-between-rtp-and-srtp">What is the difference between RTP and SRTP?</h3><p>The difference is protection. RTP sends media payloads in the clear with no integrity check, while SRTP encrypts the payload and adds an authentication tag, 80 bits by default, over the header and payload. The RTP header stays readable in both.</p><h3 id="what-is-dtls-srtp">What is DTLS-SRTP?</h3><p>DTLS-SRTP is the key exchange defined in RFC 5764, in which the two endpoints run a DTLS handshake on the media path and derive SRTP keys from it. The signalling carries only a certificate fingerprint, so the signalling server never sees the key. WebRTC requires it.</p><h3 id="does-srtp-encrypt-chat-messages">Does SRTP encrypt chat messages?</h3><p>No. SRTP encrypts only RTP audio and video. In WebRTC, chat usually travels over a data channel, which is encrypted with DTLS, or through the app's signalling server over TLS.</p><h3 id="how-much-overhead-does-srtp-add">How much overhead does SRTP add?</h3><p>SRTP adds a 10-byte authentication tag per packet with the default suite, 4 bytes with the 32-bit tag, and 16 bytes with AES-GCM. Counter-mode encryption does not change the payload size. An optional master key identifier, whose length the key management sets, adds to that when used.</p><h3 id="does-videosdk-use-srtp">Does VideoSDK use SRTP?</h3><p>Yes. VideoSDK's compliance documentation lists SRTP for media and TLS for signalling, and its telephony gateways support TLS plus SRTP for SIP calls. Media passes through VideoSDK's servers, so calls are encrypted in transit rather than end to end, and recordings can be encrypted at rest with a key you hold.</p>]]></content:encoded></item><item><title><![CDATA[Video Codecs Explained: H.264 vs VP8 vs VP9 vs AV1]]></title><description><![CDATA[A video codec compresses raw 720p video about 221 times so a call fits through a network. This guide compares H.264, VP8, VP9, and AV1 on compression, CPU cost, simulcast, and battery, separates codec from container and encoder, and shows how VideoSDK sets the codec and falls back to VP8.]]></description><link>https://www.videosdk.live/blog/video-codecs</link><guid isPermaLink="false">6aa261c0b3240feb748c9cf5</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 10 Sep 2026 12:12:40 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/05.png" medium="image"/><content:encoded><![CDATA[<blockquote>A video codec is software or hardware that compresses video for sending and decompresses it for playback. H.264 and VP8 run almost everywhere at low CPU cost. VP9 and AV1 compress better but need more processing power. VideoSDK supports all four and falls back to VP8 automatically when a device cannot handle the codec you chose.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/05.png" alt="Video Codecs Explained: H.264 vs VP8 vs VP9 vs AV1"/><p>Before the first frame of a video call reaches your screen, the devices on each end have already agreed on a video codec. That agreement decides how much bandwidth the call uses, how warm the phone gets, and whether a group call can adapt when one participant drops to a weak connection.</p><p>Most codec explainers are written for files and streaming, where a server encodes once and viewers only decode. Real-time video breaks that model. Every participant encodes live on their own device and decodes everyone else, and one unsupported codec can turn a tile black.</p><p>This guide covers what a video codec is, how H.264, VP8, VP9, and AV1 compare in VideoSDK's own codec table, which one to pick for which job, and how to set it in code.</p><h2 id="what-is-a-video-codec">What is a video codec?</h2><p>A video codec shrinks raw camera frames roughly 160 to 330 times so they fit through a network, then rebuilds them on arrival.</p><p>A video codec is defined as software or hardware that encodes digital video into a compact bitstream and decodes that bitstream back into frames for display. The name is a contraction of coder-decoder. H.264, VP8, VP9, and AV1 are all video codecs, and each one defines its own rules for how the compression works.</p><p>In a video call, the codec runs on every participant's device: once to encode their own camera and once for every other feed they decode. VideoSDK exposes the codec as a per-track option on <code>createCameraVideoTrack()</code>, supports VP8, H.264, VP9, and AV1, and uses VP8 by default, a codec every WebRTC browser is required to implement.</p><p>A video codec works by discarding information your eyes will not miss and describing the rest as efficiently as possible. The two subsections below show why that matters and how it is done.</p><h3 id="why-video-needs-a-codec">Why video needs a codec</h3><p>Uncompressed video is far too large to send. A single raw 720p camera feed would overwhelm almost any home or mobile connection.<br><br>A codec shrinks that feed to a small fraction of its size. VideoSDK's default 720p profile, <code>h720p_w1280p</code>, sends it at about 1.5 Mbps, according to the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track" rel="noreferrer">encoder table in VideoSDK's docs</a>. That reduction is what makes a video call possible at all.</br></br></p><h3 id="how-a-video-codec-compresses-frames">How a video codec compresses frames</h3><p>Every modern video codec uses the same three techniques, in different proportions.</p><ol><li><strong>Intra-frame (spatial) compression.</strong> A keyframe is compressed on its own, like a photo, by predicting each block of pixels from its neighbours in the same frame. Keyframes are expensive, so encoders send them sparingly.</li><li><strong>Inter-frame (temporal) compression.</strong> Most frames are described as changes from an earlier frame. The encoder finds where each block moved (a motion vector) and sends the movement plus the small difference left over. A talking head on a still background compresses extremely well for this reason.</li><li><strong>Quantization.</strong> The encoder rounds away fine detail. This is the lossy step, and it is where the bitrate target is enforced: a lower bitrate means coarser rounding and a softer picture.</li></ol><p>Newer codecs win by giving the encoder more options for all three: more flexible block sizes, more prediction modes, better filtering. More options mean better compression and more work for the encoder, and that trade-off sits behind every row of the comparison table later in this guide.</p><p>In short, a video codec is the compression contract between sender and receiver, and every codec trades encoder effort for bitrate.</p><h2 id="codec-vs-container-vs-encoder">Codec vs Container vs Encoder</h2><p>A codec defines the compression, a container packages the result into a file, and an encoder is the software or chip that does the compressing.</p><p>The three terms get used interchangeably, which is why "Is MP4 a video codec?" appears in search results for this topic. It is not. MP4 is a container, and it can hold H.264, VP9, or AV1 video, according to <a href="https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/Video_codecs">MDN's web video codec guide</a>.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Term</th>
<th>What it is</th>
<th>Examples</th>
<th>What it decides</th>
</tr>
</thead>
<tbody>
<tr>
<td>Codec (video coding format)</td>
<td>The compression standard: the rules for turning frames into a bitstream and back</td>
<td>H.264, VP8, VP9, AV1</td>
<td>Bitrate at a given quality, CPU cost, and which devices can decode the stream</td>
</tr>
<tr>
<td>Container</td>
<td>The wrapper that stores encoded video, audio, and metadata together in one file</td>
<td>MP4, WebM, MKV</td>
<td>Which players and platforms accept the file, plus seeking, subtitles, and chapters</td>
</tr>
<tr>
<td>Encoder</td>
<td>One implementation of a codec, in software or dedicated hardware</td>
<td>x264 and Cisco's OpenH264 for H.264, libvpx for VP8 and VP9, the video blocks inside phone chips</td>
<td>Encoding speed, power draw, and how much quality it extracts from the same codec</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The formal name for the first row is a video coding format: the specification of the bitstream. H.264 is a video coding format, and x264 is an encoder that produces it. Two encoders for the same codec can give visibly different quality at the same bitrate, because the standard defines what a decoder must understand, not how hard the encoder searches for a good encoding.</p><p>Real-time calls add a twist. A WebRTC call has no container while it runs: encoded frames travel as RTP packets straight to the other side. The codec format video calls negotiate is the only one of the three that both ends must agree on. A container only enters the picture when you record the call to a file.</p><p>WebM is the container you will meet most often next to VP8, VP9, and AV1, and MP4 is H.264's usual home. If file packaging is your actual question, see <a href="https://www.videosdk.live/blog/mkv-vs-mp4">MKV vs MP4</a>. For how codec, container, and network each affect picture quality, see <a href="https://www.videosdk.live/blog/video-quality-bandwidth-codecs-containers">video quality explained: bandwidth, codecs, and containers</a>.</p><p>Keep the three apart and most codec confusion disappears: choose the codec for the network and devices, the container for the destination, and the encoder for speed and power.</p><h2 id="h264-vs-vp8-vs-vp9-vs-av1">H.264 vs VP8 vs VP9 vs AV1</h2><p>VP8 and H.264 trade compression for reach and low CPU cost, while VP9 and AV1 trade CPU and simulcast for better compression.</p><p>The table below reproduces the substance of the codec guidance in VideoSDK's documentation, which rates each codec on the same five criteria. It is the most useful single view of these four codecs for real-time video, because it includes the column most comparisons leave out: whether the codec supports simulcast.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Codec</th>
<th>Quality and compression</th>
<th>CPU cost</th>
<th>Device and browser support</th>
<th>Simulcast (<code>multiStream</code>)</th>
<th>Recommended use</th>
</tr>
</thead>
<tbody>
<tr>
<td>VP8</td>
<td>Good</td>
<td>Low</td>
<td>Very broad</td>
<td>Supported</td>
<td>Default choice for maximum compatibility</td>
</tr>
<tr>
<td>H.264</td>
<td>Good</td>
<td>Low</td>
<td>Broad</td>
<td>Supported on web, single-stream on iOS</td>
<td>Mobile and enterprise environments</td>
</tr>
<tr>
<td>VP9</td>
<td>Better</td>
<td>Medium to high</td>
<td>Modern browsers</td>
<td>Not supported</td>
<td>Improved quality on modern devices</td>
</tr>
<tr>
<td>AV1</td>
<td>Best</td>
<td>High, reduced by hardware acceleration</td>
<td>Growing</td>
<td>Not supported</td>
<td>Highest quality where supported</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p><em>Source: </em><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track" rel="noreferrer"><em>VideoSDK optimize video track guide</em></a><em> for the React SDK, read September 10, 2026. The </em><a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track"><em>iOS version of the guide</em></a><em> lists H.264 as single-stream.</em></p><p>The simulcast column is the one that bites in production. Pass VP9 or AV1 with <code>multiStream: true</code> and VideoSDK switches <code>multiStream</code> off and emits <code>ERROR_MULTISTREAM_NOT_SUPPORTED</code>, so every receiver gets the same single layer regardless of their connection.</p><h3 id="codec-origins-licensing-and-webrtc-status">Codec origins, licensing, and WebRTC status</h3>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Codec</th>
<th>First published</th>
<th>Developed by</th>
<th>Licensing</th>
<th>WebRTC status</th>
</tr>
</thead>
<tbody>
<tr>
<td>H.264 (AVC)</td>
<td>2003</td>
<td>ITU-T and MPEG</td>
<td>Patent-licensed through Via LA; Cisco does not pass royalties on for its OpenH264 binary</td>
<td>Mandatory in browsers (RFC 7742)</td>
</tr>
<tr>
<td>VP8</td>
<td>2010</td>
<td>Google, released through the WebM Project</td>
<td>Royalty-free</td>
<td>Mandatory in browsers (RFC 7742)</td>
</tr>
<tr>
<td>VP9</td>
<td>2013</td>
<td>Google</td>
<td>Royalty-free</td>
<td>Optional: Chrome 48+ and Firefox</td>
</tr>
<tr>
<td>AV1</td>
<td>2018</td>
<td>Alliance for Open Media</td>
<td>Royalty-free</td>
<td>Optional: Chrome 113+ and Firefox 136+</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p><em>Sources: publication years from the </em><a href="https://www.itu.int/rec/T-REC-H.264-200305-S/en"><em>ITU-T H.264 recommendation</em></a><em>, the </em><a href="http://blog.webmproject.org/2010/05/introducing-webm-open-web-media-project.html"><em>WebM Project announcement</em></a><em>, and the </em><a href="https://engineering.fb.com/wp-content/uploads/2025/09/Meta-AV1-White-Paper-FINAL.pdf"><em>Meta, Vodafone, and YouTube AV1 white paper</em></a><em>. Licensing from MDN and </em><a href="https://www.openh264.org/"><em>OpenH264</em></a><em>. WebRTC support from </em><a href="https://developer.mozilla.org/en-US/docs/Web/Media/Guides/Formats/WebRTC_codecs"><em>MDN's WebRTC codec guide</em></a><em> and </em><a href="https://www.rfc-editor.org/rfc/rfc7742.html"><em>RFC 7742</em></a><em>.</em></p><h3 id="h264-the-codec-every-device-already-has">H.264: the codec every device already has</h3><p>H.264, also called AVC, is the oldest codec in this comparison, supported in close to 100% of smartphones according to the 2025 white paper from Meta, Vodafone, and YouTube. RFC 7742 requires every WebRTC browser to implement its Constrained Baseline profile, so an H.264 call can always be negotiated.</p><p>Its advantage on mobile is hardware. MDN notes that on iOS and iPadOS, H.264 can be encoded and decoded in hardware. The catch is licensing: H.264 is patent-encumbered, although Cisco's OpenH264 binary removes the royalty question for most WebRTC apps.</p><h3 id="vp8-webrtcs-default-codec">VP8: WebRTC's default codec</h3><p>VP8 is Google's royalty-free codec, open-sourced in May 2010 through the WebM Project and, like H.264, mandatory in every WebRTC browser. VideoSDK uses VP8 as its default and as the fallback it switches to whenever another codec fails.</p><p>Its compression is on par with H.264, and VideoSDK's table rates both "Good." Its weakness is Apple hardware: MDN states VP8 has no hardware support on iOS, which increases processor load and reduces battery life.</p><h3 id="vp9-better-compression-single-stream-in-videosdk">VP9: better compression, single-stream in VideoSDK</h3><p>VP9 is VP8's successor, finalized by Google in 2013 and royalty-free. VideoSDK rates its compression "Better" than VP8 and H.264, at a medium-to-high CPU cost. WebRTC support covers Chrome 48 and later plus Firefox, per MDN.</p><p>In VideoSDK, VP9 runs single-stream, so it suits calls where every receiver has a similar connection: one-to-one calls, or small meetings on known networks.</p><h3 id="av1-the-best-compression-at-the-highest-cpu-cost">AV1: the best compression at the highest CPU cost</h3><p>AV1 is the Alliance for Open Media's royalty-free codec, first published in 2018. The Meta, Vodafone, and YouTube white paper puts its gain at up to 30% better compression than VP9, and MDN cites compression rates as much as 50% higher than H.264. For a longer look at that pairing, see <a href="https://www.videosdk.live/developer-hub/social/av1-vs-h264">AV1 vs H.264</a>.</p><p>That efficiency costs compute, which is why VideoSDK rates AV1's CPU cost as high. VideoSDK's docs also carry a warning from its own testing: AV1 failed on some versions of Safari on macOS and on mobile web on iPhone, in both Chrome and Safari. Test it on your target devices before shipping it.</p><h3 id="where-h265-fits">Where H.265 fits</h3><p>H.265 (HEVC) is missing from this comparison because VideoSDK's <code>codec</code> option does not offer it: the four choices are VP8, H.264, VP9, and AV1. For recorded and broadcast workflows where H.265 comes up, see <a href="https://www.videosdk.live/blog/h264-vs-h265">H.264 vs H.265</a>, which also covers its uneven WebRTC support.</p><p>On raw compression AV1 wins; on reach, CPU cost, and simulcast, VP8 and H.264 still win for most live calls.</p><h2 id="which-codec-should-you-use">Which codec should you use?</h2><p>Use VP8 or H.264 for most live calls, and save VP9 and AV1 for known devices where bandwidth is the binding constraint.</p><p>The right video codec depends less on which one compresses best and more on who is sending, who is receiving, and whether the call needs to adapt to different connections. Use this list as a starting point:</p><ul><li><strong>Use VP8 when you do not control the clients.</strong> It is VideoSDK's default, rated "Very broad" for support, keeps simulcast, and is the codec every other choice falls back to anyway.</li><li><strong>Use H.264 when your audience is mostly on iPhones or enterprise networks.</strong> Hardware encode and decode on iOS saves battery, per MDN, and VideoSDK's docs recommend it for mobile and enterprise environments. On VideoSDK's iOS SDK, H.264 runs single-stream, so plan group-call layouts around that.</li><li><strong>Use VP9 for one-to-one or small calls on modern desktop browsers.</strong> With one receiver, losing simulcast costs little, and you get better quality per bit.</li><li><strong>Use AV1 when you control the hardware and have tested it.</strong> Meeting-room devices, kiosks, or a desktop app on recent machines are good candidates. Mobile web is not, given the iPhone failures in VideoSDK's own testing.</li><li><strong>Use AV1 or VP9 for recorded and on-demand video.</strong> Encoding offline removes the real-time CPU limit. Over 75% of YouTube's catalog, weighted by watch time, is available in AV1, according to the Meta, Vodafone, and YouTube white paper.</li></ul><h3 id="the-mistake-av1-in-a-large-group-call">The mistake: AV1 in a large group call</h3><p>The most expensive codec mistake in real-time apps is choosing the best-compressing codec for a large group call. With <code>multiStream</code> on, VideoSDK sends 720p, 360p, and 180p layers from a 720p camera, so each viewer receives the layer their bandwidth can carry. VP9 and AV1 turn that off.</p><p>Without simulcast, one layer serves everyone. The participant on a weak mobile connection receives the same stream as the one on office fibre, and the more receivers a call has, the more likely one of them is on a poor connection. In practice, better compression per stream rarely makes up for losing adaptation across every receiver. For why raw bandwidth is not the whole story, see <a href="https://www.videosdk.live/blog/bandwidth-vs-latency">bandwidth vs latency</a>.</p><p>The short version: default to VP8 or H.264, and treat VP9 and AV1 as targeted upgrades for call types you have measured.</p><h2 id="setting-the-codec-in-a-real-time-sdk">Setting the codec in a real-time SDK</h2><p>In VideoSDK, the codec is one option on the camera track, and the SDK handles fallback when a device cannot use it.</p><p>The examples below use VideoSDK's JavaScript SDK, which added the <code>codec</code> option in version 0.10.2 on June 5, 2026. The npm registry listed version 1.1.1 as current on September 10, 2026. Load the SDK from its CDN script tag or with <code>npm install @videosdk.live/js-sdk</code>; the docs reference it as the global <code>VideoSDK</code>.</p><h3 id="choose-the-codec-on-the-camera-track">Choose the codec on the camera track</h3><p>Pass <code>codec</code> to <code>createCameraVideoTrack()</code>. This track asks for H.264 at 720p with three simulcast layers:</p><pre><code class="language-javascript">const cameraTrack = await VideoSDK.createCameraVideoTrack({
  encoderConfig: "h720p_w1280p",
  optimizationMode: "motion",
  bitrateMode: VideoSDK.Constants.BitrateMode.BALANCED,
  multiStream: true,
  maxLayer: 3,
  codec: VideoSDK.Constants.VideoCodec.H264,
});
</code></pre><p><code>codec</code> takes a value from <code>VideoSDK.Constants.VideoCodec</code>: <code>VP8</code> (the default), <code>H264</code>, <code>VP9</code>, or <code>AV1</code>. H.264 is used here because, in the JavaScript SDK, it keeps <code>multiStream</code> on. Swap in <code>VP9</code> or <code>AV1</code> and VideoSDK turns <code>multiStream</code> off and emits <code>ERROR_MULTISTREAM_NOT_SUPPORTED</code>, which also makes <code>maxLayer</code> irrelevant, since it only applies when <code>multiStream</code> is on.</p><h3 id="handle-the-codec-changed-event">Handle the codec-changed event</h3><p>Pass the track to <code>initMeeting()</code>, then register listeners before joining so no event is missed. The token comes from your server, never from the browser; see <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/authentication-and-token">VideoSDK authentication and tokens</a>. Run this inside an async function, as the quickstart does.</p><pre><code class="language-javascript">VideoSDK.config(TOKEN); // minted on your server

const meeting = VideoSDK.initMeeting({
  meetingId: MEETING_ID,
  name: "Ada",
  webcamEnabled: true,
  customCameraVideoTrack: cameraTrack,
  codecSwitchEnabled: true, // default: fall back to VP8 instead of a black tile
});

meeting.on("error", (error) =&gt; {
  if (error.code === "ERROR_VIDEO_PRODUCE_CODEC_NOT_SUPPORTED") {
    // This device can't encode the chosen codec; VideoSDK is sending VP8
  }
  if (error.code === "CODEC_NOT_SUPPORTED") {
    // This device can't decode the meeting's codec; a switch to VP8 follows
  }
});

meeting.on("codec-changed", (data) =&gt; {
  console.log("Current codec:", data.currentCodec);
  console.log("Previous codec:", data.previousCodec);
  console.log("Unsupported remote codec:", data.unsupportedRemoteCodec);
  console.log("Kind:", data.kind);
  console.log("Caused by participant:", data.causedBy);
});

await meeting.join();
</code></pre><p>Two fallbacks are at work here, and both end in VP8, the codec video calls in VideoSDK always return to:</p><ol><li><strong>Sending side.</strong> If this device cannot encode H.264, VideoSDK switches its track to VP8 and emits <code>ERROR_VIDEO_PRODUCE_CODEC_NOT_SUPPORTED</code>. The call continues.</li><li><strong>Receiving side.</strong> If a participant joins whose device cannot decode the meeting's codec, that participant gets <code>CODEC_NOT_SUPPORTED</code>. VideoSDK then moves every participant to VP8, and everyone receives <code>codec-changed</code> with the previous codec, the new one, the unsupported codec, the media kind, and the participant who caused the switch.</li></ol><p>The switch is controlled by <code>codecSwitchEnabled</code> in <code>initMeeting()</code>, which defaults to <code>true</code>. Set it to <code>false</code> and VideoSDK will not fall back, and the docs warn that affected participants may see a black screen instead of video. Leave it on unless you are testing codec support deliberately.</p><p>The practical value of <code>codec-changed</code> is visibility. Send it to your analytics along with <code>causedBy</code>, and you learn which devices in your user base cannot handle the codec you chose. That is better evidence for a codec decision than any compatibility table, including the ones above. The full payload is listed in the <a href="https://docs.videosdk.live/js-sdk-reference/types/MeetingEvent.html#codec-changed"><code>codec-changed</code> API reference</a>.</p><p><strong>Not using JavaScript?</strong> The React SDK exposes the same event as <code>onCodecChanged</code> on the <code>useMeeting</code> hook, and the iOS SDK as <code>onCodecChanged</code> on <code>MeetingEventListener</code>. See the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track">React</a> and <a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track">iOS</a> versions of the optimize video track guide. One platform difference to plan for: VideoSDK's iOS guide lists H.264 as single-stream, like VP9 and AV1.</p><h2 id="audio-codecs">Audio codecs</h2><p>Every WebRTC endpoint must implement two audio codecs, Opus and G.711, under <a href="https://www.rfc-editor.org/rfc/rfc7874.html">RFC 7874</a>, published by the IETF in May 2016.</p><p>Audio gets far less attention than video in codec discussions, because in a video call it rarely needs a decision. It does need one the moment a call touches the phone network.</p><h3 id="opus-the-default-for-real-time-audio">Opus: the default for real-time audio</h3><p>Opus was standardized as <a href="https://www.rfc-editor.org/rfc/rfc6716.html">RFC 6716</a> in September 2012. It scales from narrowband speech at 6 kbit/s to high-quality stereo music at 510 kbit/s, with frame sizes from 2.5 to 60 ms. MDN's WebRTC codec guide suggests 16 to 20 kbps for wideband speech and 28 to 40 kbps for fullband.</p><p>That range is why video calls rarely need an audio codec decision: Opus handles a quiet one-to-one and a live music lesson with the same codec. VideoSDK's <a href="https://docs.videosdk.live/telephony/integrations/telynx-sip-integration">Telnyx SIP integration guide</a> tells you to choose Opus and set it as the first priority.</p><h3 id="g711-the-codec-of-the-telephone-network">G.711: the codec of the telephone network</h3><p>G.711 is the pulse-code modulation format of the public telephone network: 8-bit samples at 8,000 Hz, which works out to 64 kbps. MDN describes its quality as generally poor by modern standards and treats it as a least-common-denominator fallback. It survives as the lowest common denominator across SIP trunks and PBXs.</p><p>At 64 kbps, G.711 uses 3 to 4 times the bitrate of wideband Opus to carry narrowband audio. When the phone leg of a call runs G.711, that leg is narrowband no matter what the WebRTC side uses, which is why phone callers sound like phone callers. VideoSDK's <a href="https://docs.videosdk.live/iot/guide/video-and-audio-calling-api-sdk/setup-call/init-room">IoT SDK</a> exposes both G.711 flavours, <code>AUDIO_CODEC_PCMA</code> (A-law) and <code>AUDIO_CODEC_PCMU</code> (u-law), alongside <code>AUDIO_CODEC_OPUS</code>. For bridging calls to phone numbers, see <a href="https://docs.videosdk.live/telephony/introduction">VideoSDK telephony</a>.</p><p>Use Opus everywhere you can, and expect G.711 only on legs that cross into telephony.</p><h2 id="hardware-acceleration-and-battery">Hardware acceleration and battery</h2><p>Hardware video decoders use less than 9% of the energy software decoders need, according to a 2024 review by Kr√§nzler, Herglotz, and Kaup.</p><p>That review, <a href="https://arxiv.org/abs/2402.09001">presented at the Picture Coding Symposium 2024</a>, compared the energy efficiency of software and hardware video decoders. The size of the gap explains a detail in VideoSDK's codec table: AV1 is rated high on CPU, with the qualification that hardware acceleration can significantly reduce CPU usage. The codec is the same either way. Whether a dedicated chip does the work decides the cost.</p><h3 id="which-devices-have-codec-hardware">Which devices have codec hardware</h3><ul><li><strong>H.264 on Apple devices.</strong> MDN notes that H.264 can be encoded and decoded in hardware on iOS and iPadOS. VP8 has no hardware support there, which increases processor load and reduces battery life.</li><li><strong>AV1 on phones.</strong> The Meta, Vodafone, and YouTube white paper (September 2025) reports AV1 hardware decode on most modern high-end phone chips, with limited support in mid and low tiers. Software decoding with the open-source dav1d decoder fills the gap at a modest cost in CPU use and battery.</li><li><strong>AV1 on iPhone.</strong> Apple added a dedicated AV1 decoder to the A17 Pro chip in the iPhone 15 Pro, <a href="https://www.apple.com/newsroom/2023/09/apple-unveils-iphone-15-pro-and-iphone-15-pro-max/">announced September 12, 2023</a>.</li></ul><h3 id="why-calls-are-harder-than-streaming">Why calls are harder than streaming</h3><p>Most published codec battery data is about playback, where a server encodes and the phone only decodes. A video call reverses half of that: the phone encodes its own camera live, for the whole call. Apple's A17 Pro announcement describes an AV1 <em>decoder</em>, and decode hardware helps a phone receive AV1, not send it.</p><p>Before you make AV1 the sending codec on mobile, check that the device can encode it efficiently, not just play it. Browsers can tell you: <a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaCapabilities/encodingInfo"><code>navigator.mediaCapabilities.encodingInfo()</code></a> accepts a configuration with <code>type: "webrtc"</code> and returns <code>supported</code>, <code>smooth</code>, and <code>powerEfficient</code> flags. A <code>powerEfficient</code> value of <code>false</code> is a hint that the device will encode that codec in software.</p><p>For battery-sensitive mobile audiences, H.264 on iOS and VP8 or H.264 elsewhere remain the safe sending codecs until you have tested AV1 encoding on the devices your users actually carry.</p><h2 id="video-codec-glossary">Video codec glossary</h2><blockquote><strong>Video codec:</strong> Software or hardware that compresses video into a bitstream and decompresses it for display. VideoSDK supports four codecs for video on its camera track: VP8, H.264, VP9, and AV1.</blockquote><blockquote><strong>Video coding format:</strong> The standardized bitstream a codec produces, independent of any implementation. H.264 is a coding format; x264 and OpenH264 are encoders for it.</blockquote><blockquote><strong>Simulcast:</strong> Sending the same video at several resolutions at once, so a media server can forward each receiver the layer their bandwidth supports. In VideoSDK this is <code>multiStream</code>, which sends 720p, 360p, and 180p layers from a 720p camera.</blockquote><blockquote><strong>Codec negotiation:</strong> The exchange in which WebRTC endpoints agree on a codec both support before media flows. RFC 7742 guarantees that VP8 and H.264 are always available to agree on in browsers.</blockquote><blockquote><strong>Codec fallback:</strong> Switching to a codec every participant supports when the chosen one fails. VideoSDK falls back to VP8 and reports the switch through the <code>codec-changed</code> event.</blockquote><h2 id="key-takeaways-on-video-codecs">Key takeaways on video codecs</h2><ul><li>A video codec compresses raw video by two orders of magnitude: 331.8 Mbit/s of raw 720p becomes 1,500 kbps at VideoSDK's default 720p profile, about 221:1.</li><li>A codec, a container, and an encoder are different things: H.264 is a codec, MP4 is a container, and x264 is an encoder.</li><li>VP8 and H.264 remain the right default for live group calls, because both are mandatory in WebRTC browsers and both keep simulcast in VideoSDK's JavaScript SDK.</li><li>VP9 and AV1 compress better, with AV1 up to 30% ahead of VP9, but VideoSDK runs them single-stream, and AV1 needs testing on Safari and iPhone.</li><li>VideoSDK falls back to VP8 automatically when a device cannot send or receive the chosen codec, and the <code>codec-changed</code> event tells you which participant caused the switch.</li></ul><h2 id="conclusion">Conclusion</h2><p>Choosing a video codec for a real-time app is less about which codec compresses best and more about which one every participant can encode, decode, and adapt. Start with VP8 or H.264, log <code>codec-changed</code> events in production, and move specific call types to VP9 or AV1 when your own data shows the devices can handle it.</p><p>To try the <code>codec</code> option, follow the <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK JavaScript quickstart</a> and sign up at <a href="https://app.videosdk.live/login" rel="noreferrer">VideoSDK</a> with $20 free credit. Questions are welcome in the <a href="https://discord.gg/Gpmj6eCq5u">VideoSDK Discord</a>.</p><p>Which codec are you running in production, and has a <code>codec-changed</code> event ever surprised you? Drop a comment.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-a-video-codec-1">What is a video codec?</h3><p>A video codec is software or hardware that compresses digital video into a compact bitstream for storage or transmission, and decompresses it for playback. The word combines coder and decoder. H.264, VP8, VP9, and AV1 are the video codecs used most in real-time communication, and VideoSDK supports all four on its camera track.</p><h3 id="what-is-the-codec">What is the codec?</h3><p>The codec of a video is the compression format its picture was encoded with, and you can check it directly. For a file, tools such as MediaInfo or FFmpeg's ffprobe report the codec of each stream. In a live VideoSDK call, the codec you set on <code>createCameraVideoTrack()</code> applies until a fallback occurs, and the <code>codec-changed</code> event reports the new codec when one does.</p><h3 id="which-video-codec-is-better-vp8-vp9-or-av1">Which video codec is better, VP8, VP9, or AV1?</h3><p>AV1 compresses best, VP9 comes second, and VP8 is the most compatible and the cheapest on CPU. For live group calls VP8 usually wins overall, because in VideoSDK both VP9 and AV1 disable simulcast. For recorded video, or one-to-one calls on known modern hardware, AV1 or VP9 is the better choice.</p><h3 id="does-videosdk-support-av1">Does VideoSDK support AV1?</h3><p>Yes, VideoSDK supports AV1 in its JavaScript, React, and iOS SDKs, set through the <code>codec</code> option on <code>createCameraVideoTrack()</code>. AV1 runs single-stream, without simulcast, and VideoSDK's documentation warns that it failed in testing on some Safari versions on macOS and on mobile web on iPhone. If a participant cannot decode AV1, VideoSDK moves the meeting to VP8 automatically.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Telehealth Video Platform: Architecture, Compliance, UX & Cost]]></title><description><![CDATA[A telehealth video platform is six layers, and the video call is one of them. This guide maps the architecture, shows what WebRTC does and does not give you, covers five telehealth UX patterns, summarizes the HIPAA controls, and prices 2,000 consults a month.]]></description><link>https://www.videosdk.live/blog/telehealth-video-platform</link><guid isPermaLink="false">6aa122adb3240feb748c9c53</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 10 Sep 2026 08:40:50 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/04.png" medium="image"/><content:encoded><![CDATA[<blockquote>A telehealth video platform is defined as the full stack behind a virtual consult: scheduling, identity, encrypted media, recording, storage, and an audit trail. The video call is one layer of six. </blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/04.png" alt="How to Build a Telehealth Video Platform: Architecture, Compliance, UX & Cost"/><p>Telehealth reached 5.51 percent of US medical claim lines in the first quarter of 2026, up 10.1 percent from the quarter before, according to FAIR Health's Quarterly Telehealth Regional Tracker.</p><p>That volume runs on software somebody had to assemble. Teams building it usually start at the video call, which is the part vendors sell, and meet the other five layers later: appointment-to-room binding, token minting, recording custody, EHR write-back, and audit logging. Then they meet the patient who cannot find the "allow camera" button.</p><p>This guide covers the architecture of a telehealth video platform, what WebRTC does and does not give you, five UX patterns that decide whether the patient connects at all, the compliance controls that gate a US launch, where AI fits, and a worked cost model for 2,000 consultations a month.</p><h2 id="what-is-a-telehealth-video-platform">What is a telehealth video platform?</h2><p>A <a href="https://www.videosdk.live/solutions/telehealth" rel="noreferrer">telehealth video</a> platform is the system that carries a clinical encounter from a booked appointment to a signed note, with video as the transport in the middle.</p><p>It is defined as a stack that authenticates a patient and a clinician, places them in a private session, encrypts the media between them, optionally records the encounter into storage the provider controls, and writes evidence of all of it into an audit log.</p><p>A telehealth video platform works by separating the parts that must stay under your control from the parts you can rent. Identity, scheduling, clinical records, and audit belong to you, because they are where protected health information lives and where regulators look. Media transport is infrastructure, and almost nobody builds it twice.</p><p>That split is the reason most healthcare teams do not write their own signaling servers. VideoSDK provides the media layer through its <a href="https://www.videosdk.live/audio-video-calling-api-sdk">video calling API and SDKs</a>, with recordings uploaded directly to your own cloud storage bucket rather than held on VideoSDK's side.</p><h3 id="telehealth-video-solutions-fall-into-two-groups">Telehealth video solutions fall into two groups</h3><p>Video solutions for telehealth split into finished platforms and embeddable APIs, and the choice is mostly about who owns the patient experience.</p><p>Finished platforms such as Doxy.me, SimplePractice, or Zoom for Healthcare ship a working consult room, a patient link, and a BAA on day one. You configure them. You do not change how they look, where they store recordings, or how they behave when the patient's connection drops.</p><p>Embeddable APIs, including VideoSDK, Daily, LiveKit, and Amazon Chime SDK, hand you the media layer and leave the rest of the product to you. You get control over the waiting room, the branding, the EHR write-back, and the storage bucket, and you take on the work of building them.</p><p>If you are choosing a vendor rather than designing a system, the ranked breakdown in <a href="https://www.videosdk.live/blog/video-conferencing-telemedicine-api">Top 10 Video Conferencing Telemedicine APIs</a> compares ten providers against healthcare-specific criteria. The rest of this article assumes you have decided to build.</p><h2 id="telehealth-video-platform-architecture-layer-by-layer">Telehealth video platform architecture, layer by layer</h2><p>A working telehealth video platform has six layers, and only one of them is the video call.</p><p>Teams that treat the SDK integration as the project ship a demo quickly and then spend two quarters on the other five. Mapping them first makes the build predictable, and makes it obvious which layers a vendor can absorb.</p><h3 id="layer-1-identity-and-scheduling">Layer 1: Identity and scheduling</h3><p>Every session starts with a booking, and the booking is what proves the patient belongs in the room.</p><p>Your scheduling system holds the appointment record: which patient, which clinician, what time, which service. Nothing about that belongs in the video vendor. The room is created because an appointment exists, not the other way around.</p><p>Practical rule: one room per appointment, created server side at booking time or shortly before the visit. Reusable room IDs are the most common way a stranger ends up in a consult.</p><h3 id="layer-2-server-side-token-minting">Layer 2: Server-side token minting</h3><p>Tokens are where access control actually happens, and they must be minted on your server.</p><p>A meeting token is a short-lived credential that says which room a participant may join and what they may do in it. Your API key and secret generate it, which is why neither can ever ship in a web bundle or a mobile binary.</p><p>Scope tokens by role. A clinician token may start a recording; a patient token may not. Give tokens the shortest lifetime the appointment allows, so a leaked link expires before it is useful. VideoSDK's <a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">REST API reference</a> covers room creation and token validation endpoints.</p><h3 id="layer-3-media-transport">Layer 3: Media transport</h3><p>The media layer routes encrypted audio and video between participants and adapts to whatever network the patient is on.</p><p>Nearly every production telehealth platform routes media through a Selective Forwarding Unit rather than connecting devices directly. An <a href="https://www.videosdk.live/blog/sfu-vs-mcu-vs-mesh-webrtc" rel="noreferrer">SFU</a> receives each participant's streams and forwards them, which keeps upload bandwidth flat as participants are added and makes server-side recording possible.</p><p>The tradeoff is that an SFU terminates encryption to forward media, so the call is encrypted hop by hop rather than end to end. That is a compliance decision, not just an architecture one, and the compliance section below returns to it.</p><h3 id="layer-4-recording-and-storage-custody">Layer 4: Recording and storage custody</h3><p>Recording is where a telehealth video platform stops being a video problem and becomes a records problem.</p><p>A recorded consult is a clinical record. It inherits retention schedules, access controls, patient access rights, and breach exposure. The single most important architectural decision here is whose bucket it lands in.</p><p>VideoSDK writes recordings directly to your cloud storage and documents that it holds write-only access and deletes its copy immediately. Keeping recordings in infrastructure you already have under a BAA removes an entire category of vendor risk, and it usually costs less than paying the platform to store them.</p><h3 id="layer-5-clinical-system-integration">Layer 5: Clinical system integration</h3><p>The consult has to leave the video platform and land in the chart, or clinicians will keep two systems open.</p><p>In practice this means writing an encounter record, the visit note, and any recording reference back to the EHR, usually over <a href="https://www.hl7.org/fhir/">HL7 FHIR</a> resources such as Encounter, DocumentReference, and Appointment. Build this as a server-side job triggered by session webhooks rather than anything the browser does.</p><h3 id="layer-6-audit-and-observability">Layer 6: Audit and observability</h3><p>An audit log that was assembled after an incident is not an audit log.</p><p>Subscribe to session webhooks and append every join, leave, recording start, recording stop, and permission change to storage that your application cannot rewrite. Keep the clinical audit trail separate from your application logs, because the two have different retention rules and very different readers.</p><p>One layer that is easy to skip: call quality telemetry. Without per-session stats you cannot tell a clinician complaining about "bad video" whether the cause was their Wi-Fi, the patient's phone, or your configuration.</p><h2 id="webrtc-for-telehealth-what-it-solves-and-what-it-does-not">WebRTC for telehealth: What it solves and What it does not</h2><p><a href="https://www.w3.org/TR/webrtc/" rel="noreferrer">WebRTC</a> gives you encrypted, plugin-free media in a browser, and nothing above the media layer.</p><p>That distinction matters because WebRTC telehealth projects are often scoped as if the standard were a product. It is a browser API and a set of IETF protocols. It solves transport. It has no opinion about patients, appointments, or HIPAA.</p><h3 id="what-webrtc-solves">What WebRTC solves</h3><p>WebRTC solves the four hardest problems in moving real-time media between two devices on the open internet.</p><p><strong>Capture and transport without an install.</strong> <a href="https://www.w3.org/TR/webrtc/">WebRTC 1.0</a> is a W3C Recommendation implemented in Chrome, Safari, Firefox, and Edge. A patient joins from the browser they already have, which is the single largest determinant of whether they connect at all.</p><p><strong>Connectivity through NAT and firewalls.</strong> ICE candidate gathering, with STUN for address discovery and <a href="https://www.rfc-editor.org/rfc/rfc8656">TURN relay</a> as fallback, is what makes a call work from a hospital guest network or a mobile carrier.</p><p><strong>Encryption that is not optional.</strong> WebRTC media is carried over <a href="https://www.rfc-editor.org/rfc/rfc3711">SRTP</a> with keys negotiated by DTLS. There is no unencrypted mode to misconfigure, which is a genuine advantage of WebRTC healthcare deployments over older video stacks.</p><p><strong>Adaptation to bad networks.</strong> Congestion control and simulcast let the sender drop resolution and bitrate instead of dropping the call, which matters when the patient is on rural LTE.</p><h3 id="what-webrtc-does-not-give-you">What WebRTC does not give you</h3><p>WebRTC deliberately leaves out everything that would make it a telehealth product.</p><p><strong>Signaling is undefined.</strong> The specification does not say how two peers exchange session descriptions. You build that, or your vendor does.</p><p><strong>There is no media server.</strong> Direct peer connections work for a two-person consult on good networks and degrade badly beyond that. Group consults, recording, and reliable relay all require an SFU and <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a> infrastructure that somebody has to run and scale.</p><p><strong>There is no identity layer.</strong> WebRTC has no concept of a patient, a clinician, or permission to join. Authorization is entirely yours.</p><p><strong>There is no recording.</strong> Capturing a consult means a server-side component that subscribes to streams, composites them, and writes a file.</p><p><strong>There is no compliance.</strong> The <a href="https://www.rfc-editor.org/rfc/rfc8827">WebRTC security architecture</a> covers protocol-level threats. It does not sign a BAA, retain audit logs, or restrict where media is processed.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Layer</th>
<th>WebRTC provides</th>
<th>You still need</th>
<th>Supplied by VideoSDK</th>
</tr>
</thead>
<tbody>
<tr>
<td>Media encryption</td>
<td>SRTP with DTLS key exchange</td>
<td>Nothing at protocol level</td>
<td>Yes, plus TLS on signaling</td>
</tr>
<tr>
<td>NAT traversal</td>
<td>ICE and STUN</td>
<td>TURN relay servers at scale</td>
<td>Yes, managed</td>
</tr>
<tr>
<td>Signaling</td>
<td>Nothing, undefined by spec</td>
<td>A signaling service</td>
<td>Yes, managed</td>
</tr>
<tr>
<td>Media routing</td>
<td>Peer to peer only</td>
<td>An SFU for groups and recording</td>
<td>Yes, managed</td>
</tr>
<tr>
<td>Recording</td>
<td>Nothing</td>
<td>Server-side capture and compositing</td>
<td>Yes, to your bucket</td>
</tr>
<tr>
<td>Identity and access</td>
<td>Nothing</td>
<td>Token minting, role scoping</td>
<td>Token API, you mint</td>
</tr>
<tr>
<td>Scheduling and rooms</td>
<td>Nothing</td>
<td>Appointment to room mapping</td>
<td>Room API, you map</td>
</tr>
<tr>
<td>Audit trail</td>
<td>Nothing</td>
<td>Append-only event log</td>
<td>Webhooks, you store</td>
</tr>
<tr>
<td>BAA and compliance</td>
<td>Nothing</td>
<td>Signed agreements, controls</td>
<td>HIPAA add-on and BAA</td>
</tr>
<tr>
<td>EHR write-back</td>
<td>Nothing</td>
<td>FHIR integration</td>
<td>No, you build</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>WebRTC telemedicine builds fail on the right-hand columns, not the left. The protocol work is finished and standardized; the product work is not.</p><p>WebRTC services for healthcare are sold precisely to close that gap, and the honest question when evaluating one is how many rows of that table it actually covers.</p><h2 id="telehealth-ux-patterns-that-decide-whether-the-patient-connects">Telehealth UX patterns that decide whether the patient connects</h2><p>UX for telehealth is not general video conferencing UX, because the user is often elderly, anxious, on a phone, and using the product once.</p><p>A patient in a Zoom meeting who cannot get their camera working asks a colleague. A patient waiting for a psychiatry appointment closes the tab. Telemedicine UX has to assume no second attempt and no IT support, which changes what you build.</p><p>These five patterns address the points where sessions actually fail. VideoSDK documents the underlying behaviour in its <a href="https://docs.videosdk.live/react/guide/best-practices/user-experience">user experience guidelines</a> and <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/setup-call/precall">pre-call setup guide</a>.</p><h3 id="pattern-1-browser-first-join-with-no-download">Pattern 1: Browser-first join with no download</h3><p>The patient should reach the consult from a link, in the browser they already have, with no account and no app.</p><p>Every install step is a place to lose a first-time patient, and mobile app stores are a hard stop for someone joining from a hospital waiting room five minutes before their appointment. WebRTC runs natively in current Safari, Chrome, Firefox, and Edge, so the download is not technically necessary.</p><p>Reserve the native app for patients in ongoing care programmes who benefit from notifications and background reconnection. Never make it the only door.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/pattern1-interim-rn-crossplatform-terminal-blurred.png" class="kg-image" alt="How to Build a Telehealth Video Platform: Architecture, Compliance, UX & Cost" loading="lazy" width="1920" height="1080"/></figure><h3 id="pattern-2-a-pre-call-check-that-tests-real-devices">Pattern 2: A pre-call check that tests real devices</h3><p>A pre-call screen that only asks for permission is not a test. It has to actually exercise the camera, microphone, and speaker.</p><p>The useful sequence is: request permissions, enumerate devices, show a live camera preview, record two seconds of microphone audio and play it back, play a test tone through the selected speaker, and check upstream bandwidth. Each step catches a distinct failure that would otherwise surface in front of a clinician.</p><p>VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/setup-call/precall" rel="noreferrer">precall guide</a> covers the permission check and device selection flow, including using <code>checkPermissions()</code> from the <code>useMediaDevice</code> hook to detect what has been granted before the patient is in the room.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/pre-call-setup.png" class="kg-image" alt="How to Build a Telehealth Video Platform: Architecture, Compliance, UX & Cost" loading="lazy" width="1920" height="1019"/></figure><h3 id="pattern-3-a-permission-denied-path-that-says-what-to-click">Pattern 3: A permission-denied path that says what to click</h3><p>Browsers show the camera permission prompt once, and a patient who dismisses it is stuck with no visible way back.</p><p>Detect the denied state explicitly and replace the video tile with instructions specific to that browser: where the padlock icon is, which toggle to flip, and that the page needs a reload afterwards. Generic text saying "please enable camera access" leaves the patient exactly where they were.</p><p>This is the highest-yield telehealth <a href="https://docs.videosdk.live/react/guide/best-practices/user-experience" rel="noreferrer">UX fix</a> available, because it converts an abandoned appointment into a completed one with no infrastructure change.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/manual_permission.png" class="kg-image" alt="How to Build a Telehealth Video Platform: Architecture, Compliance, UX & Cost" loading="lazy" width="1440" height="900"/></figure><h3 id="pattern-4-visible-connection-quality-and-a-deliberate-audio-only-fallback">Pattern 4: Visible connection quality and a deliberate audio-only fallback</h3><p>Show the patient their connection state before it fails, and give the clinician a one-tap way to drop video.</p><p>VideoSDK exposes per-stream statistics through <code>getVideoStats()</code>, <code>getAudioStats()</code>, and <code>getShareStats()</code>, which is enough to render a three-state indicator rather than leaving both sides guessing why the picture froze.</p><p>The fallback matters clinically as well as technically. HHS has published <a href="https://www.hhs.gov/hipaa/for-professionals/privacy/guidance/hipaa-audio-telehealth/index.html">guidance on audio-only telehealth</a> under the HIPAA Rules, and for many consult types finishing the appointment on voice is a better outcome than rescheduling. Voice costs $0.001 per participant minute against $0.004 for HD video, so the fallback is also cheaper.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-09-09-at-6.25.08-PM.png" class="kg-image" alt="How to Build a Telehealth Video Platform: Architecture, Compliance, UX & Cost" loading="lazy" width="1273" height="726"/></figure><h3 id="pattern-5-rejoin-that-returns-to-the-same-appointment">Pattern 5: Rejoin that returns to the same appointment</h3><p>A dropped patient should be able to return to the same consult from the same link, without a new invitation.</p><p>Because the room is bound to the appointment rather than to a session, a rejoin is just a fresh token against the existing room. Keep the clinician informed with join and leave events so they know whether to wait or to call.</p><p>Pair this with device switching mid-call. A patient whose Bluetooth headset disconnects needs to change audio output without leaving, and the SDK supports switching devices inside an active session.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/rejoin.png" class="kg-image" alt="How to Build a Telehealth Video Platform: Architecture, Compliance, UX & Cost" loading="lazy" width="2917" height="1758"/></figure><h2 id="compliance-controls-for-a-telehealth-video-platform">Compliance controls for a telehealth video platform</h2><p>A US telehealth video platform needs a signed BAA covering the exact features you use, and the BAA is a gate, not a checkbox.</p><p>This section is a summary. The full treatment, including the 45 CFR 164.312 safeguard mapping, what a BAA does and does not cover, recording rules, and GDPR alongside HIPAA, is in <a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api">HIPAA Compliant Video Conferencing API</a>.</p><p><strong>The controls that decide whether you can launch:</strong></p><ul><li><strong>A BAA with every vendor that touches PHI.</strong> That includes the video vendor, the storage provider, the transcription vendor, and any model provider in an AI pipeline. HHS ended its COVID-era telehealth enforcement discretion on May 11, 2023, with a 90-day transition period, so the pre-2023 flexibility no longer applies.</li><li><strong>Encryption in transit and at rest.</strong> VideoSDK documents TLS for signaling and SRTP for media, with encryption at rest where storage supports it.</li><li><strong>Recording custody in your own bucket.</strong> VideoSDK uploads recordings directly to customer storage and states it holds write-only access, which keeps the retained clinical record inside your existing controls.</li><li><strong>Role-scoped, short-lived tokens.</strong> Access control lives in the token, minted server side, never in the client.</li><li><strong>An append-only audit trail.</strong> Built from session webhooks, retained separately from application logs.</li><li><strong>Region pinning where residency applies.</strong> <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/geo-fencing-and-proxy-controls/geo-fencing">Geo-fencing</a> keeps media processing inside a chosen region.</li></ul><p>Two things are worth knowing before you design around them.</p><p><strong>Hop-by-hop is not end-to-end.</strong> An SFU decrypts and re-encrypts to forward media. That is normal, it is what makes recording and group consults possible, and HIPAA does not require end-to-end encryption. VideoSDK does offer <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/security/E2EE">E2EE</a>, but enabling it disables recording and transcription, so it is a real tradeoff rather than a free upgrade.</p><p><strong>HIPAA coverage is a paid add-on.</strong> VideoSDK sells HIPAA compliance and the BAA as an add-on to Enterprise and Pay-As-You-Go plans, enabled from the dashboard under Billing then Add-ons. Pricing is custom, so budget it as a line item you have to ask for rather than a rate you can read off the page.</p><h2 id="ai-in-telehealth-what-actually-runs-inside-the-call">AI in telehealth: what actually runs inside the call</h2><p>AI telehealth features today are mostly documentation, captions, and intake, and each one changes your compliance surface.</p><p>The clinically useful applications are narrow and real. Ambient documentation turns the consult audio into a draft note so the clinician is not typing through the appointment. Live captions make consults accessible to deaf and hard-of-hearing patients. Voice agents handle intake and triage before a clinician joins.</p><p>VideoSDK prices these as metered features: real-time transcription at $0.020 per minute, post-call transcription at $0.004 per minute, and prompt-based summaries at $0.005 per request. Its <a href="https://docs.videosdk.live/ai_agents/introduction">AI voice agent SDK</a> connects speech-to-text, an LLM, and text-to-speech into a room for the intake case.</p><h3 id="the-constraint-nobody-mentions-until-integration">The constraint nobody mentions until integration</h3><p>Enabling VideoSDK's HIPAA add-on turns off its own AI features.</p><p>The <a href="https://docs.videosdk.live/help_docs/security-and-privacy/hipaa">HIPAA compliance documentation</a> lists live transcription, closed captions, post-call transcription, AI-generated summaries, and live streaming over HLS and <a href="https://www.videosdk.live/developer-hub/rtmp/rtmp-vs-srt" rel="noreferrer">RTMP-out</a> as unavailable in HIPAA mode. Enabling end-to-end encryption removes recording and transcription for the same reason: a service that cannot read the media cannot transcribe it.</p><p>This is a coherent design rather than a gap. It does mean the architecture for a compliant AI telehealth workflow looks different from the demo:</p><ol><li>Record the consult to your own storage bucket, under your own BAA.</li><li>Run transcription and summarization in your own pipeline against that recording.</li><li>Hold a BAA with every model vendor in that pipeline, including the speech-to-text and LLM providers.</li><li>Write the draft note back to the EHR for clinician review, and keep it flagged as a draft until a human signs it.</li></ol><p>Budget for this properly. Real-time transcription across every consult costs 2.5 times the HD video itself in the model below, which is the kind of number that should be decided deliberately rather than discovered on an invoice.</p><h2 id="what-a-telehealth-call-costs">What a telehealth call costs</h2><p>A 30-minute two-party HD telehealth consult costs about $0.24 in media on VideoSDK, before recording, storage, or transcription.</p><p>The unit that matters is the participant minute. A 30-minute call with two people is 60 participant minutes, not 30. Recording is billed differently, per recorded minute of output, so it does not double with participant count.</p><h3 id="rate-card">Rate card</h3>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Item</th>
<th>Unit</th>
<th>Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>Voice</td>
<td>Per participant minute</td>
<td>$0.001</td>
</tr>
<tr>
<td>Video HD 720p</td>
<td>Per participant minute</td>
<td>$0.004</td>
</tr>
<tr>
<td>Video Full HD 1080p</td>
<td>Per participant minute</td>
<td>$0.008</td>
</tr>
<tr>
<td>Composite recording HD</td>
<td>Per recorded minute</td>
<td>$0.015</td>
</tr>
<tr>
<td>Composite recording Full HD</td>
<td>Per recorded minute</td>
<td>$0.030</td>
</tr>
<tr>
<td>Recording storage</td>
<td>Per minute per month</td>
<td>$0.003</td>
</tr>
<tr>
<td>Post-call transcription</td>
<td>Per minute</td>
<td>$0.004</td>
</tr>
<tr>
<td>Real-time transcription</td>
<td>Per minute</td>
<td>$0.020</td>
</tr>
<tr>
<td>Prompt-based summary</td>
<td>Per request</td>
<td>$0.005</td>
</tr>
<tr>
<td>HIPAA compliance and BAA</td>
<td>Add-on</td>
<td>Custom</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>New accounts start with $20 in free credit, which is enough for testing and includes all the required features.</p><h3 id="worked-example-2000-consultations-a-month">Worked example: 2,000 consultations a month</h3><p>Assume a behavioural health group running 2,000 telehealth appointments a month, 30 minutes each, one patient and one clinician, with 60 percent of sessions recorded for the record.</p><p>That is 120,000 participant minutes, 60,000 session minutes, and 36,000 recorded minutes.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Line item</th>
<th>Calculation</th>
<th>Monthly cost</th>
</tr>
</thead>
<tbody>
<tr>
<td>HD video</td>
<td>120,000 participant min at $0.004</td>
<td>$480.00</td>
</tr>
<tr>
<td>Composite recording, HD</td>
<td>36,000 recorded min at $0.015</td>
<td>$540.00</td>
</tr>
<tr>
<td>Recording storage, first month</td>
<td>36,000 min at $0.003</td>
<td>$108.00</td>
</tr>
<tr>
<td>Post-call transcription</td>
<td>36,000 min at $0.004</td>
<td>$144.00</td>
</tr>
<tr>
<td>Visit summaries</td>
<td>1,200 requests at $0.005</td>
<td>$6.00</td>
</tr>
<tr>
<td><strong>Total</strong></td>
<td/>
<td><strong>$1,278.00</strong></td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>That is $0.64 per completed consultation. Three things in that table are worth arguing about before you build.</p><p><strong>Recording costs more than the calls.</strong> At $540 against $480, capturing the consult is the larger line. Recording only what a retention policy actually requires is the fastest cost reduction available, and it reduces breach exposure at the same time.</p><p><strong>Storage compounds, and the rate card only shows month one.</strong> At 36,000 new minutes a month, the storage line reaches $1,296 a month by month twelve, twelve times the first month, and it keeps climbing for as long as your retention schedule runs. Writing recordings to your own bucket, which HIPAA mode requires anyway, moves this onto object storage you already negotiate.</p><p><strong>Resolution is the biggest single lever.</strong> Running the same month at Full HD costs $960 for video and $1,080 for recording, exactly double, at $1.02 per consult. Some specialties need the detail. A follow-up medication review does not.</p><h3 id="what-the-same-month-costs-in-hipaa-mode">What the same month costs in HIPAA mode</h3>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Line item</th>
<th>Monthly cost</th>
</tr>
</thead>
<tbody>
<tr>
<td>HD video</td>
<td>$480.00</td>
</tr>
<tr>
<td>Composite recording, HD</td>
<td>$540.00</td>
</tr>
<tr>
<td>Transcription and summaries</td>
<td>Not available in HIPAA mode</td>
</tr>
<tr>
<td>VideoSDK storage</td>
<td>Not applicable, recordings go to your bucket</td>
</tr>
<tr>
<td>HIPAA add-on and BAA</td>
<td>Custom pricing</td>
</tr>
<tr>
<td><strong>Media subtotal</strong></td>
<td><strong>$1,020.00</strong></td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Media works out at $0.51 per consult, plus the add-on, plus your own storage and your own AI pipeline. The comparison that matters is not $1,278 against $1,020, it is $1,278 against $1,020 plus the cost of building and holding BAAs for the pipeline you now run yourself.</p><h3 id="costs-that-are-not-on-the-rate-card">Costs that are not on the rate card</h3><ul><li><strong>Concurrency headroom.</strong> Free plans allow 50 concurrent hosts, Pay-As-You-Go 500, with capacity packs at $20 a month per 100 hosts. Concurrent recordings are capped at 1 on free and 10 on Pay-As-You-Go, which binds earlier than most teams expect for a clinic with overlapping appointment slots.</li><li><strong>Per-room limits.</strong> 100 participants and 15 active speakers per room, published in the <a href="https://docs.videosdk.live/help_docs/quotas-and-limit">usage quota documentation</a>. Fine for consults, relevant for group therapy or teaching rounds.</li><li><strong>The four layers the SDK does not build for you.</strong> Scheduling, EHR write-back, audit storage, and the patient-facing UX are engineering time, and they are most of the build.</li></ul><h2 id="healthcare-teams-building-on-videosdk">Healthcare teams building on VideoSDK</h2><p>Two published healthcare deployments show what changes after a migration, and both are vendor-published testimonials rather than independent benchmarks.</p><p>Coala Saude is a Brazil-based telehealth platform dedicated to bringing accessible healthcare to schools to support the well-being of the next generation.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-09-10-at-12.45.57-PM.png" class="kg-image" alt="How to Build a Telehealth Video Platform: Architecture, Compliance, UX & Cost" loading="lazy" width="1818" height="678"/></figure><p>After moving off Jitsi to <a href="https://www.videosdk.live/customers/coalasaude">VideoSDK</a>, Brazilian school-telehealth platform Coala Saúde built a working AI transcription prototype in 4–5 days, using automatic cloud recording and raw-audio export to Google Cloud to produce structured medical records in about 1 minute.</p><p>The results were 45% less documentation time for doctors (down from about 12.9 minutes per session), medical records with 50%+ more detail, and over 10,000 consultations handled in 2025 through a fully automated workflow.</p><p>Talk Your Heart Out, an online therapy platform, migrated from Twilio. </p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-09-08-at-4.11.26-PM-1.png" class="kg-image" alt="How to Build a Telehealth Video Platform: Architecture, Compliance, UX & Cost" loading="lazy" width="1820" height="656"/></figure><p>The <a href="https://www.videosdk.live/customers/tyho">TYHO case study</a> reports an 88 percent referral rate, 96 percent of clients finding the platform easy to use, and 70 percent repeat clients.</p><p>Read both as customer statements. The useful signal is not the percentages, it is that both teams cited support responsiveness and call reliability rather than features, which is consistent with where telehealth deployments actually break.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Room:</strong> A VideoSDK session that participants join and share media within, identified by a unique room ID. In telehealth, bind one room to one appointment rather than reusing IDs.</blockquote><blockquote><strong>Meeting token:</strong> A short-lived JWT, minted on your server from your API key and secret, that authorizes a participant to join a specific room with a specific role.</blockquote><blockquote><strong>SFU (Selective Forwarding Unit):</strong> A media server that receives each participant's streams and forwards them to others. It keeps upload bandwidth flat as participants are added and makes server-side recording possible, at the cost of terminating encryption to forward.</blockquote><blockquote><strong>TURN relay:</strong> A server that relays media when a direct peer connection cannot be established through NAT or a firewall, specified in RFC 8656. It is what makes calls work from hospital guest networks.</blockquote><blockquote><strong>BAA (Business Associate Agreement):</strong> The contract under which a vendor handling protected health information accepts HIPAA obligations. Without one covering the specific features you use, those features are not compliant regardless of their encryption.</blockquote><blockquote><strong>PHI (Protected Health Information):</strong> Individually identifiable health information covered by HIPAA. A recorded consult, its transcript, and the appointment metadata around it are all PHI.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>A telehealth video platform is six layers, and the video call is one of them; identity, tokens, recording custody, EHR integration, and audit are where the build time goes.</li><li>WebRTC solves encrypted transport, NAT traversal, and browser-native capture, and supplies no signaling, no media server, no identity, no recording, and no compliance.</li><li>Telehealth UX has to assume a first-time user with no IT support, which makes browser-first joining, a real device test, and a permission-denied recovery path higher value than any in-call feature.</li><li>Recording usually costs more than the calls themselves, and storage compounds every month against a retention schedule that healthcare sets, not you.</li><li>Enabling VideoSDK's HIPAA add-on disables its built-in transcription, captions, and summaries, so a compliant AI workflow runs in your own pipeline against recordings in your own bucket.</li></ul><h2 id="conclusion">Conclusion</h2><p>Building a telehealth video platform is mostly a records and access-control project wearing a video interface. Get the room-to-appointment binding, server-side tokens, and recording custody right, and the media layer is a vendor decision you can make on price and reliability. Get them wrong and no amount of video quality helps.</p><p>Start with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK quickstart</a> and $20 in free credit at <a href="https://app.videosdk.live/login" rel="noreferrer">VideoSDK</a>, and read the <a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api">HIPAA guide</a> before you scope the compliance work.</p><p>What is blocking your telehealth build right now, the compliance review or the patient onboarding flow? Drop a comment, the answer is rarely the video.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-a-telehealth-video-platform-1">What is a telehealth video platform?</h3><p>A telehealth video platform is the system that carries a clinical encounter from a booked appointment to a signed note. It authenticates the patient and clinician, places them in a private encrypted session, optionally records the consult into provider-controlled storage, and writes an audit trail. The video call is one layer of six.</p><h3 id="is-webrtc-hipaa-compliant">Is WebRTC HIPAA compliant?</h3><p>WebRTC is not compliant or non-compliant by itself, because HIPAA applies to organizations and their vendors, not to protocols. WebRTC mandates SRTP encryption for media, which satisfies the transmission security expectation, but compliance also requires a signed BAA, access controls, audit logging, and retention policies that the protocol does not provide.</p><h3 id="how-much-does-it-cost-to-build-a-telehealth-video-platform">How much does it cost to build a telehealth video platform?</h3><p>Media costs are predictable and small. On VideoSDK, 2,000 thirty-minute two-party consults a month cost $480 in HD video, $540 in composite recording, and $108 in first-month storage, about $0.64 per consult with transcription included. The larger cost is engineering time for scheduling, EHR integration, audit logging, and patient onboarding.</p><h3 id="do-patients-need-to-install-an-app-for-telehealth-video-calls">Do patients need to install an app for telehealth video calls?</h3><p>No. WebRTC runs natively in current versions of Chrome, Safari, Firefox, and Edge, so patients can join a consult from a link with no download and no account. Native apps are worth building for patients in ongoing care programmes who benefit from push notifications, but they should never be the only way in.</p><h3 id="can-i-record-telehealth-consultations">Can I record telehealth consultations?</h3><p>Yes, and a recorded consult becomes a clinical record subject to retention schedules and patient access rights. VideoSDK uploads recordings directly to your own cloud storage bucket and states that it holds write-only access and deletes its copy immediately, which keeps the retained record inside the controls you already operate.</p><h3 id="does-videosdk-sign-a-baa-for-telehealth">Does VideoSDK sign a BAA for telehealth?</h3><p>Yes. VideoSDK offers HIPAA compliance and a Business Associate Agreement as a paid add-on to Enterprise and Pay-As-You-Go plans, enabled from the dashboard under Billing then Add-ons. Pricing is custom rather than published, so treat it as a line item to request during procurement.</p><h3 id="can-i-use-ai-transcription-in-a-hipaa-compliant-telehealth-call">Can I use AI transcription in a HIPAA-compliant telehealth call?</h3><p>Not through VideoSDK's built-in features. VideoSDK's HIPAA documentation lists live transcription, closed captions, post-call transcription, and AI-generated summaries as unavailable in HIPAA mode. A compliant workflow records to your own bucket and runs transcription in your own pipeline, with a BAA held with every model vendor in that chain.</p><h3 id="what-is-the-difference-between-telehealth-and-telemedicine">What is the difference between telehealth and telemedicine?</h3><p>Telemedicine refers specifically to remote clinical services delivered by a licensed clinician, such as a diagnosis or a prescription. Telehealth is the broader category, covering clinical care plus remote monitoring, patient education, and administrative interactions. Most video platform requirements are identical across both.</p>]]></content:encoded></item><item><title><![CDATA[What is a Video Call API? How It Works, Cost & How to Choose One]]></title><description><![CDATA[A video call API runs the signaling, media servers, and TURN relays behind a live call so your app only builds the interface. What it is, how a call flows through it, what VideoSDK, Daily, Agora, Twilio, and Amazon Chime charge per participant minute, and a ten-point checklist for choosing one.

]]></description><link>https://www.videosdk.live/blog/video-call-api</link><guid isPermaLink="false">6a9fd02ab3240feb748c9b6e</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 09 Sep 2026 09:57:18 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/02.png" medium="image"/><content:encoded><![CDATA[<blockquote>A video call API is defined as a hosted service that runs the signaling, media servers, and global network behind a live video call, so your app only handles the interface. You reach it through REST endpoints on your server and client SDKs in your app. VideoSDK prices it at $0.004 per participant minute for HD video.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/02.png" alt="What is a Video Call API? How It Works, Cost & How to Choose One"/><p>Video calling looks like a solved problem until you price it out. Two engineers, three months, and a working demo, then the first 50-person call falls over because nobody budgeted for a media server.</p><p>A video call API removes that entire layer. What it does not remove is the decision: which one, at what cost, with which limits.</p><p>This guide covers what a video call API actually is, how a call flows through one, what five named providers charge per participant minute, and a ten-point checklist for picking one. Pricing is current as of September 8, 2026 and sourced per vendor.</p><h2 id="what-is-a-video-call-api">What is a video call API?</h2><p>A video call API is the infrastructure layer of a live call, delivered as a service you call rather than servers you run.</p><p>A video call API is defined as a set of server-side <a href="https://docs.videosdk.live/api-reference/realtime-communication/intro" rel="noreferrer">REST endpoints</a> and <a href="https://www.videosdk.live/sdk" rel="noreferrer">client SDKs</a> that create meeting rooms, authenticate participants, route audio and video between them, and expose recording, streaming, and transcription as programmable operations. It works by placing a media server between participants, so each device uploads its stream once and the server forwards it to everyone else.</p><p>The media server is the reason the category exists at all. Without a media server, every participant sends a separate copy of their video to every other participant, and upload bandwidth becomes the ceiling. With one, upload stays flat as the room grows.</p><p>An API for video calling gives you four things a from-scratch build does not: a signaling service that survives reconnection, a global network of media servers close to your users, <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a> relays for the networks that block direct connections, and a support contract when a call fails at 2am.</p><p>VideoSDK provides this as a rooms-based API. You create a Room over REST API, mint a Meeting Token scoped to that room, and join from a client SDK on React, JavaScript, React Native, Android, iOS, Flutter, Unity, C++, IoT, or Python. Recording, interactive live streaming, transcription, and SIP telephony run against the same room.</p><p>Every video call API in the market ships the same six capabilities, and a vendor missing one is a vendor you will outgrow:</p><ul><li><strong>Room and session management,</strong> to create, list, close, and audit calls from your server.</li><li><strong>Token-based authentication,</strong> so a participant is scoped to one room with a short-lived credential rather than a shared key.</li><li><strong>Media routing through an SFU,</strong> which is what makes rooms larger than four people practical.</li><li><strong>Client SDKs per platform,</strong> covering web and mobile so one backend serves every client you ship.</li><li><strong>Recording, streaming, and transcription,</strong> exposed as server-side operations rather than client buttons.</li><li><strong>A global edge network with TURN relays,</strong> so calls connect from restrictive networks and from users far from your servers.</li></ul><h2 id="video-call-api-vs-video-sdk-vs-webrtc">Video call API vs Video SDK vs WebRTC</h2><p>The three terms describe three different amounts of work, not three competing products. WebRTC is the protocol, a Video SDK is the client library, and a video call API is the hosted service behind both.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Layer</th>
<th>What you get</th>
<th>What you still build</th>
<th>When to choose it</th>
</tr>
</thead>
<tbody>
<tr>
<td>WebRTC</td>
<td>The browser and mobile APIs for capturing media, encrypting it, and connecting two peers directly. Free, standardised by the W3C and IETF, supported everywhere.</td>
<td>A signaling server, a media server for anything past a few participants, STUN and TURN infrastructure, reconnection logic, recording, and a support rota.</td>
<td>You have a media engineering team, a hard data residency rule that forbids third-party servers, or a research use case where the protocol itself is the product.</td>
</tr>
<tr>
<td>Video SDK</td>
<td>A client library for one or more platforms that wraps WebRTC, plus rendering helpers, device management, and events for participants and tracks.</td>
<td>The backend. Room lifecycle, token issuance, and the servers that route media, unless the SDK ships with a hosted service behind it.</td>
<td>You want control of the client but already have, or are buying, the server side. In practice a standalone video calling SDK is half of a product.</td>
</tr>
<tr>
<td>Video call API</td>
<td>The full hosted stack: signaling, a global SFU network, TURN relays, room and token management, recording, streaming, and transcription, reachable over REST plus client SDKs.</td>
<td>Your interface, your business rules, your auth, and the token route that connects them.</td>
<td>You are shipping a product where calling is a feature rather than the product, and you would rather spend the next quarter on your domain than on media servers.</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The middle row is the one that confuses buyers. Vendors market the client package as the headline, so "video SDK" and "video call API" often name the same product from two directions. The test is simple: ask where the media server runs. If the vendor runs it, you are buying an API and the SDK comes with it. If you run it, you are buying or adopting a library.</p><p>For the layer underneath, VideoSDK's explainers on <a href="https://www.videosdk.live/blog/webrtc">WebRTC</a> and on <a href="https://www.videosdk.live/blog/sfu-vs-mcu-vs-mesh-webrtc">SFU versus MCU architectures</a> cover why the media server choice sets both your cost curve and your maximum room size.</p><h2 id="how-a-video-call-api-works">How a video call API works</h2><p>Every call on a video call API follows the same six-step sequence, and the first two happen on your server before the user sees anything.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/ChatGPT-Image-Sep-8--2026--03_49_27-PM.png" class="kg-image" alt="What is a Video Call API? How It Works, Cost & How to Choose One" loading="lazy" width="1055" height="1491"/></figure><ol><li><strong>Create the room.</strong> Your backend posts to the rooms endpoint and receives a room ID. Store it against your own record, the appointment, the class, or the support ticket. Nothing about the room is public, and nothing has been billed yet.</li><li><strong>Issue the token.</strong> Your backend signs a JWT with your API secret, scoped to that room ID, that participant ID, and a short expiry. The secret never leaves your server. The token is the only credential the browser or app ever holds.</li><li><strong>Join.</strong> The client SDK sends the token and the room ID, the service validates the token, and the participant is admitted. This is the moment billing starts, because billing is per participant minute connected.</li><li><strong>Negotiate media through the SFU.</strong> The client and the selective forwarding unit exchange session descriptions and ICE candidates, then agree on codecs and a transport. If a direct path is blocked by a firewall or a symmetric NAT, the connection falls back to a TURN relay.</li><li><strong>Publish and subscribe to tracks.</strong> Each participant publishes one audio track and one video track upward to the SFU. The SFU forwards copies down to every other participant who subscribes. Your interface receives an event per track and attaches it to a video or audio element.</li><li><strong>Leave.</strong> The participant disconnects, their tracks stop, and billing for that participant stops. The room stays alive for whoever is still in it, and closes on its own once empty or on the schedule you configured.</li></ol><p>Steps 4 and 5 are the part teams underestimate. Media arrives on a separate track event, not with the participant, so a participant can be in the room for a second or two before their video exists. Interfaces that assume otherwise render a black tile.</p><p>The SFU is also why a live video call API scales differently from a peer-to-peer one. Adding the tenth participant adds one upload and nine downloads across the room, not nine uploads from every device.</p><h2 id="what-video-call-apis-cost">What video call APIs cost</h2><p><a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">Video call API</a> pricing is per participant minute almost everywhere, which means cost scales with people multiplied by time, not with how many rooms you create.</p><p>One participant connected for one minute is one participant minute. A four-person 30-minute call is 120 participant minutes, whether it runs in one room or four. Rooms are free to create, and an empty room bills nothing.</p><p>Rates below were read from each vendor's public pricing page on September 8, 2026. Compare the video column carefully, because the units differ: some vendors quote per minute and some per 1,000 minutes.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Provider</th>
<th>Video, per participant minute</th>
<th>Audio only, per participant minute</th>
<th>Recurring free tier</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td>$0.004 (HD 720p), $0.008 (Full HD)</td>
<td>$0.001</td>
<td>$20 free credit on signup, one time</td>
</tr>
<tr>
<td>Daily</td>
<td>$0.004</td>
<td>$0.00099</td>
<td>10,000 participant minutes per month</td>
</tr>
<tr>
<td>Agora</td>
<td>$0.00399 (HD, billed as $3.99 per 1,000 minutes), $0.00899 (Full HD)</td>
<td>$0.00099 ($0.99 per 1,000 minutes)</td>
<td>10,000 minutes per month</td>
</tr>
<tr>
<td>Twilio Video</td>
<td>$0.004 (Group Rooms)</td>
<td>Not listed separately</td>
<td>None listed</td>
</tr>
<tr>
<td>Amazon Chime SDK</td>
<td>$0.0017, any modality</td>
<td>$0.0017</td>
<td>None listed</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Two honest observations from that table.</p><p>First, the headline rate is near-identical across VideoSDK, Daily, Agora, and Twilio. At HD video, all four land within a hundredth of a cent of each other, so per-minute price is not the deciding factor between them. Amazon Chime SDK is the outlier at roughly 43% of that rate, and it charges one flat attendee-minute rate whether the session uses audio, video, or screen share.</p><p>Second, the free tiers are not comparable. Daily and Agora give recurring monthly minutes. VideoSDK gives a one-time $20 credit on signup, which is roughly 5,000 participant minutes of HD video. </p><h3 id="participant-minutes-are-not-subscriber-minutes">Participant minutes are not subscriber minutes</h3><p>Two vendors on that list bill something subtly different, and it changes the arithmetic.</p><p>Agora bills video by <strong>aggregate subscribed resolution</strong>, the combined pixel count of every stream a user is receiving. A participant watching four 360p tiles is subscribing to 921,600 pixels in total, which lands in the HD tier even though no individual stream is HD. In a grid layout, the tier a user pays for is set by how many people they can see, not by their own camera.</p><p>Amazon Chime SDK goes the other way and charges one flat attendee-minute rate for every modality, so an audio-only participant costs the same as a 1080p one. That is cheap for video-heavy products and expensive for audio-first ones, where $0.0017 is nearly double what VideoSDK, Daily, or Agora charge for voice.</p><p>Read the unit before the number. A vendor that looks 20% cheaper per minute can bill 60% more for your actual call shape.</p><h3 id="the-costs-that-are-not-on-the-rate-card">The costs that are not on the rate card</h3><p>Calling is the base. These land on top, using VideoSDK's published rates as the worked example:</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Add-on</th>
<th>VideoSDK rate</th>
<th>What it costs on a real workload</th>
</tr>
</thead>
<tbody>
<tr>
<td>Recording, HD</td>
<td>$0.015 per recorded minute</td>
<td>A recorded 30-minute 1:1 consult costs $0.45 to record and $0.24 to call</td>
</tr>
<tr>
<td>HLS encoding, HD</td>
<td>$0.04 per livestream minute</td>
<td>$2.40 per broadcast hour, before viewer costs</td>
</tr>
<tr>
<td>Interactive live streaming, HD</td>
<td>$0.002 per viewer minute</td>
<td>A 500-viewer webinar hour costs $60 on the viewer side alone</td>
</tr>
<tr>
<td>Real-time transcription</td>
<td>$0.020 per minute</td>
<td>Five times the HD calling rate per participant</td>
</tr>
<tr>
<td>Post-call transcription</td>
<td>$0.004 per minute</td>
<td>Same as one participant minute of HD video</td>
</tr>
<tr>
<td>Compliance add-ons</td>
<td>Custom, quoted per account</td>
<td>HIPAA and GDPR modes are priced per user, not per minute</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Four more line items appear on the invoice or the architecture diagram, and none of them are usually quoted upfront:</p><ul><li><strong>Recording storage and egress.</strong> VideoSDK stores nothing by default and writes recordings to your own S3, Azure, or GCP bucket with write-only access. That is good for data control and it means the storage bill is yours. A thousand 30-minute HD recordings a month is real object storage spend that no per-minute table shows.</li><li><strong>TURN relay.</strong> Some share of connections cannot establish a direct path and must be relayed, which is real bandwidth someone pays for. Vendors differ on whether relayed media is billed separately, so ask. Twilio's pricing page, for instance, states unlimited TURN relay is included.</li><li><strong>Resolution drift.</strong> Pricing tiers are set by resolution, and adaptive streaming moves participants between them during a call. Budget at the tier your good-network users hit, not the average.</li><li><strong>Minimum commits and SLA uplift.</strong> Enterprise tiers routinely trade a discount for an annual commitment, and an uptime SLA with financial remedies is usually a paid upgrade rather than the default.</li></ul><h3 id="build-versus-buy-with-the-assumptions-written-down">Build versus buy, with the assumptions written down</h3><p>Nobody on this topic publishes their arithmetic, so here is a model you can argue with rather than a number to trust.</p><p>Assume a two-engineer team takes six months to reach a production-grade SFU deployment with signaling, TURN, reconnection, and recording. Assume a fully loaded cost of $150,000 per engineer per year, three-year amortisation of the initial build, half an engineer on ongoing maintenance, and $3,000 a month in servers and egress at moderate scale.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Line</th>
<th>Annual cost</th>
</tr>
</thead>
<tbody>
<tr>
<td>Initial build, $150,000 amortised over three years</td>
<td>$50,000</td>
</tr>
<tr>
<td>Ongoing maintenance, 0.5 engineer</td>
<td>$75,000</td>
</tr>
<tr>
<td>Servers, bandwidth, and egress</td>
<td>$36,000</td>
</tr>
<tr>
<td><strong>Total to run it yourself</strong></td>
<td><strong>$161,000</strong></td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>At $0.004 per participant minute, $161,000 buys 40.25 million participant minutes a year, or roughly <strong>3.35 million participant minutes a month</strong>. Below that volume, buying is cheaper on cash alone, before counting the six months of shipped features you gave up. Above it, self-hosting starts to pay, which is why the companies that build their own media stacks are the ones running calls continuously at scale.</p><p>Change the salary number, the team size, or the egress assumption and the break-even moves. The point is the shape: the crossover sits in the millions of minutes per month, not the thousands, and most products never reach it.</p><h2 id="how-to-choose-a-video-call-api">How to choose a video call API</h2><p>Since the per-minute rates cluster, the decision comes down to what happens around the call. Work through these ten points in order, because the early ones eliminate vendors faster than the later ones.</p><ol><li><strong>Platform SDKs.</strong> List every client you will ship in the next two years, then check the vendor covers all of them. Web only is a short list. Web plus iOS plus Android plus Flutter plus React Native narrows the field fast. VideoSDK's documentation carries quickstarts for eleven surfaces: a prebuilt UI kit, JavaScript, React, React Native, Android, iOS, Flutter, Unity, IoT, C++, and Python, which is the broadest coverage in the category. Unity and IoT only matter if you are building into a game or a device, and almost nobody else offers them.</li><li><strong>Recording.</strong> Ask three questions, not one. <br>1. Does it record composite, per participant, or per track? <br>2. Where do the files land, vendor storage or your own bucket? <br>3. What does it cost per recorded minute? <br>A product that needs per-participant files for a transcription pipeline cannot use a vendor that only composites.</br></br></br></br></li><li><strong>Live streaming out.</strong> If any part of your product broadcasts to an audience, check for both <a href="https://www.videosdk.live/developer-hub/hls/video-streaming-protocols-guide" rel="noreferrer">HLS</a> and <a href="https://www.videosdk.live/developer-hub/rtmp/rtmp-vs-srt" rel="noreferrer">RTMP</a> output. HLS carries large viewer counts at higher latency. RTMP pushes the composed feed to YouTube, Twitch, or LinkedIn. Interactive live streaming sits between them, keeping latency low enough for viewers to be promoted to speakers.</li><li><strong>Compliance add-ons.</strong> HIPAA, GDPR, SOC 2 Type II, and ISO 27001 are not features you retrofit. Confirm the vendor signs a business associate agreement or a data processing agreement, what it costs, and which features get disabled in compliance mode. On <a href="https://www.videosdk.live/security" rel="noreferrer">VideoSDK</a>, HIPAA mode is a custom-priced add-on, and it turns off transcription, captions, AI summaries, and HLS and RTMP output.</li><li><strong>Concurrency quotas.</strong> Two separate limits apply, and the one that bites is not the one vendors advertise. Per room is the published number. Account-wide concurrency is the ceiling across every room at once, and it is what a school timetable or an evening rush actually hits. VideoSDK documents both: 15 active speakers and 100 participants per room, 1,000 viewers for interactive live streaming and 200 for HLS, against an organisation-wide ceiling of 50 concurrent hosts on the free plan and 500 on pay-as-you-go, extendable in packs. Ask every vendor for the account-level figure in writing, because most publish only the room figure.</li><li><strong>Region availability.</strong> Check which regions run media servers, and whether you can pin a room to one at creation time rather than letting the network choose. Data residency rules and plain latency both depend on it. VideoSDK exposes region pinning through a geo-fencing feature covering the United States, Europe, India, the UAE, and Singapore, set per room with a region code such as <code>us002</code>. Confirm the current region list and which plan includes it with sales, because the documentation is inconsistent on both points.</li><li><strong>Pricing model.</strong> Confirm the unit and the rounding. Per participant minute is standard, but Agora bills video by aggregate subscribed resolution, so a user watching four 360p tiles can land in a higher tier than the label suggests. Amazon Chime SDK bills one flat attendee minute rate for every modality. These differences change the bill more than the headline rate does.</li><li><strong>Support.</strong> Find out what the free and entry paid tiers actually include, what the response time commitment is, and whether there is a private channel. A public Discord is useful for questions and useless during an outage.</li><li><strong>Migration path.</strong> Assume you will move at least once. Check whether the vendor's room and token model maps cleanly onto another's, whether recordings export in a standard container, and whether the client SDK is wrapped behind your own interface rather than called from every component. Twilio is the cautionary tale here: it announced end of life for Programmable Video in late 2023, extended it to December 2026, then reversed the decision in October 2024. Teams that had already migrated did not get that time back.</li><li><strong>Sample apps.</strong> Clone the vendor's quickstart repository and get a two-person call running before you commit. The time it takes is a direct measure of the documentation quality you will live with, and it surfaces the gaps that the marketing page does not.</li></ol><p>The honest summary: points 1, 4, and 5 eliminate vendors. Points 2, 3, and 6 decide between the survivors. Point 7 decides the bill. The rest decide how much you enjoy the next two years.</p><h2 id="common-use-cases">Common use cases</h2><p>Five verticals drive most video call API adoption, and each one stresses a different part of the stack.</p><p><strong>Telehealth.</strong> A clinical consult is usually 1:1 and short, so calling cost is trivial and compliance cost is not. What matters is a signed business associate agreement, an audit trail of who joined which session, and recordings that land in storage you control. Features that touch protected health information, including transcription and AI summaries, are typically switched off in compliance mode. The requirement map is in the <a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api">HIPAA compliant video API guide</a>, and the vertical page is <a href="https://www.videosdk.live/solutions/telehealth">telehealth</a>.</p><p><strong>Video KYC.</strong> Identity verification calls are short, high volume, and evidentiary. The recording is the product, so per-participant recording, timestamps, and storage you control matter more than picture quality. Regional data residency is a regulatory requirement rather than a latency preference here, which makes geo-fencing a hard filter when choosing a vendor. See the <a href="https://www.videosdk.live/solutions/video-kyc">video KYC solution page</a> and the <a href="https://www.videosdk.live/blog/video-kyc-api">video KYC API guide</a>.</p><p><strong>Virtual classrooms.</strong> Education is the most feature-hungry vertical: breakout rooms, a shared whiteboard, polls, hand raising, attendance, and a recording every student expects to rewatch. Concurrency is spiky, because a school timetable puts every class on the hour, which makes account-level concurrency limits the constraint rather than room size. Recording usually costs more than calling, since sessions are long and every one is captured. See the <a href="https://www.videosdk.live/solutions/edtech">edtech solution page</a> and <a href="https://www.videosdk.live/blog/virtual-classroom-api">what a virtual classroom API is</a>.</p><p><strong>Dating.</strong> Video calls in dating products are short, unscheduled, and privacy-sensitive. Participants must never learn each other's identity or network address, which rules out peer-to-peer connections and makes an SFU mandatory rather than merely convenient. Volume is bursty around evenings, so the account-level concurrency ceiling matters more than the per-room one. See the <a href="https://www.videosdk.live/solutions/dating">dating solution page</a>.</p><p><strong>Marketplaces and on-demand services.</strong> A video call inside a marketplace is a transaction step: a property viewing, a remote inspection, a consultation before a booking. Calls are one-off and link-based, since neither side wants an account just to talk, so guest tokens with a short expiry and a browser-first path do most of the work. The closest published pattern is <a href="https://www.videosdk.live/solutions/live-shopping">live shopping</a>, which shares the same one-off, link-driven shape.</p><p>The pattern across all five: the call itself is rarely the expensive part. Compliance, recording, and concurrency are.</p><h2 id="teams-that-switched-and-what-moved-them">Teams that switched, and what moved them</h2><p>Two published customer accounts describe the switch away from a larger vendor, and neither cites price as the reason.</p><p><strong>Immigo,</strong> a US-based English learning platform, evaluated the field before choosing. </p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-09-08-at-4.10.53-PM.png" class="kg-image" alt="What is a Video Call API? How It Works, Cost & How to Choose One" loading="lazy" width="1820" height="798"/></figure><p><a href="https://www.videosdk.live/customers/immigo" rel="noreferrer">Immigo</a> reported that they went live in under a week and now runs sessions across 120 countries.</p><p><strong>Talk Your Heart Out,</strong> a Singapore-based therapy platform, moved from Twilio. </p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-09-08-at-4.11.26-PM.png" class="kg-image" alt="What is a Video Call API? How It Works, Cost & How to Choose One" loading="lazy" width="1820" height="656"/></figure><p><a href="https://www.videosdk.live/customers/tyho" rel="noreferrer">TYHO</a>, struggled with quality and support of twilio but with VideoSDK, maintained a smooth, hassle-free experience, ensuring optimal user interactions even in the face of network fluctuations.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Room:</strong> The container a video call happens in, identified by a room ID. Participants join a room, and server-side operations such as recording and streaming target that room ID.</blockquote><blockquote><strong>Meeting token:</strong> A JWT signed on your server with your API secret that authorises one participant to join one room. Scoping it to a room ID and a participant ID is what stops a leaked room ID from becoming an open door.</blockquote><blockquote><strong>SFU (selective forwarding unit):</strong> The media server that receives one upload from each participant and forwards copies to the others. It is why a 20-person call does not require 19 uploads from every device.</blockquote><blockquote><strong>Track:</strong> A single stream of audio or video published by one participant. Interfaces subscribe to tracks, not to participants, which is why media arrives on its own event.</blockquote><blockquote><strong>Participant minute:</strong> The billing unit used by almost every video call API. One participant connected for one minute equals one participant minute, so a 4-person 30-minute call is 120 participant minutes.</blockquote><blockquote><strong>Interactive live streaming:</strong> A streaming mode that keeps latency low enough for viewers to be promoted to active speakers, unlike standard HLS where the delay runs into tens of seconds.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>A video call API replaces the signaling service, media servers, and TURN relays behind a live call, and bills per participant minute rather than per room.</li><li>Per-minute rates cluster tightly: VideoSDK, Daily, Agora, and Twilio all sit at roughly $0.004 for HD video, while Amazon Chime SDK charges $0.0017 for any modality.</li><li>At 1,000 one-hour 1:1 calls per month, the gap between the four WebRTC-native vendors is about $41, so features and limits decide the choice, not price.</li><li>Recording, streaming, and transcription are usually the larger line items, and a product that records every session pays more for storage than for calling.</li><li>Platform coverage, compliance add-ons, and concurrency quotas eliminate vendors faster than anything else, so check those three before you compare rates.</li></ul><h2 id="conclusion">Conclusion</h2><p>Choosing a video call API is mostly a process of elimination. Start with the platforms you must ship on, then compliance, then the concurrency your busiest hour needs. Price the features you will actually enable, not the headline rate, because recording and streaming usually outweigh calling.</p><p>VideoSDK covers the ten points above with SDKs on ten platforms, per-participant and composite recording, interactive live streaming, and HIPAA and GDPR add-ons. Start with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a> or the <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start">JavaScript quickstart</a>, sign up at <a href="https://app.videosdk.live/login" rel="noreferrer">VideoSDK</a> for <strong>$20 free credit</strong>, and check live rates on the <a href="https://www.videosdk.live/pricing">pricing page</a>.</p><p>Which video call API are you evaluating, and what is the constraint that keeps ruling options out? Drop a comment, or bring the question to the <a href="https://discord.gg/Gpmj6eCq5u">VideoSDK Discord</a>.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="how-to-do-a-video-call">How to do a video call?</h3><p>To do a video call, open an app that supports video, select the person or group you want to reach, and tap the video camera icon. Both sides need an internet connection and a camera. Inside the app, that camera button is wired to a video call API or an equivalent in-house stack, which creates the session and routes the media.</p><h3 id="how-to-video-call-on-android-from-a-browser">How to video call on Android from a browser?</h3><p>Open Chrome on the Android device, go to the meeting link, and allow camera and microphone access when prompted. No install is required, because Android Chrome supports WebRTC natively. This browser path is exactly what a video call API for websites provides, and it is why link-based joining is the standard fallback when a participant will not download an app.</p><h3 id="how-to-video-call-someone-who-does-not-have-your-app">How to video call someone who does not have your app?</h3><p>Send them a join link rather than asking them to install anything. Products built on a video call SDK generate a room, mint a guest token, and hand back a URL that opens the call in the recipient's browser. Restrict the guest token to that one room with a short expiry, so the link stops working after the call.</p><h3 id="what-is-the-difference-between-a-video-call-api-and-a-video-call-sdk">What is the difference between a video call API and a video call SDK?</h3><p>The API is the server-side surface, called from your backend with your secret, used to create rooms, mint tokens, and control recording. The video call SDK is the client-side package inside your web or mobile app that holds the WebRTC connection and renders media. A working product uses both, with the token as the handoff between them.</p><h3 id="how-much-does-a-video-call-api-cost">How much does a video call API cost?</h3><p>Video call API pricing is per participant minute. As of September 8, 2026, VideoSDK charges $0.004 for HD video and $0.001 for audio only, Daily charges $0.004 and $0.00099, Agora charges $3.99 and $0.99 per 1,000 minutes, Twilio Video charges $0.004 for Group Rooms, and Amazon Chime SDK charges $0.0017 for any modality. Recording, streaming, and transcription bill separately and often exceed the calling cost.</p><h3 id="can-i-embed-a-video-call-sdk-into-an-existing-website">Can I embed a video call SDK into an existing website?</h3><p>Yes. To embed video call SDK components into a page you already have, install the JavaScript or React package, request a token from your own backend, and mount the call inside a component or a container element. If you would rather not build the interface, a prebuilt UI kit drops a complete call screen in with an iframe or a single component, and you can move to the custom SDK later without changing the room and token model.</p><h3 id="is-there-a-free-video-call-api">Is there a free video call API?</h3><p>There is no fully free production video call API, but every major vendor has a free entry point. Daily and Agora each include 10,000 free minutes per month on an ongoing basis. VideoSDK gives a one-time $20 free credit on signup, which covers roughly 5,000 participant minutes of HD video. Open-source options such as Jitsi and LiveKit are free to license and shift the cost to servers you run and operate.</p><h3 id="what-is-a-live-video-call-api">What is a live video call API?</h3><p>A live video call API is the same product described here, with the word live emphasising real-time two-way media rather than recorded or one-way playback. Latency is the distinguishing number: interactive calling runs in the hundreds of milliseconds, while VideoSDK's documentation puts standard HLS at around 5 to 6 seconds. If viewers need to speak, ask a question, or be promoted to the stage, you need the interactive path rather than the broadcast one.</p><h3 id="how-many-participants-can-a-video-call-api-support">How many participants can a video call API support?</h3><p>Two limits apply and vendors usually publish only one. VideoSDK documents a per-room default of 100 participants with 15 active speakers, 1,000 viewers for interactive live streaming, and 200 for HLS. Separately, an organisation-wide concurrency ceiling caps how many hosts can be connected across all rooms at once, at 50 on the free plan and 500 on pay-as-you-go, extendable with add-on packs. The account-level number is the one that constrains a product with a spiky schedule.</p>]]></content:encoded></item><item><title><![CDATA[How to Integrate a Video Conferencing API into Your Website or App]]></title><description><![CDATA[Integrate a video conferencing API in six steps with VideoSDK: create a room, mint a scoped JWT on your server, join from the client, render participant streams, wire mute and screen share, then clean up.]]></description><link>https://www.videosdk.live/blog/video-conferencing-api</link><guid isPermaLink="false">6a9faf7fb3240feb748c9b41</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 09 Sep 2026 09:49:21 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/01.png" medium="image"/><content:encoded><![CDATA[<blockquote>A video conferencing API is defined as a hosted service that handles WebRTC signaling, media routing, and recording so your application only handles the interface. You integrate it by creating a room on your server, minting a short-lived token, and joining that room from a client SDK. VideoSDK covers that path in four calls.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/01.png" alt="How to Integrate a Video Conferencing API into Your Website or App"/><p>The demo works on localhost. Then the first production call drops twenty minutes in, because the token was minted in the browser with a twenty minute expiry and the secret shipped inside the JavaScript bundle.</p><p>That failure is the norm, not the exception. The API surface is small. The work around it, token minting, room lifecycle, permission prompts, and reconnection, is where teams lose weeks.</p><p>This guide walks the whole path with VideoSDK: a room created from your server, a scoped <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token" rel="noreferrer">JWT</a>, a browser client that joins and renders streams, then recording, mobile, errors, and real cost math. </p><h2 id="what-is-a-video-conferencing-api">What is a video conferencing API?</h2><p>A <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">video conferencing API</a> is a hosted service that runs the parts of a real-time call your product should never own: signaling, media routing, and infrastructure.</p><p>A video conferencing API is defined as a set of REST endpoints and client SDKs that create meeting rooms, authenticate participants, route audio and video between them, and expose recording and streaming as server-side calls. It works by placing a selective forwarding unit between participants, so each device uploads its stream once and the server fans it out to everyone else.</p><p>That distinction matters for cost. In a mesh peer-to-peer call, every participant uploads a separate copy of their video to every other participant, so a five-person call means four uploads per device. A selective forwarding unit turns that into one upload per device regardless of room size.</p><p><a href="https://videosdk.live/" rel="noreferrer">VideoSDK</a> provides this through a rooms-based model. You create a Room, mint a Meeting Token scoped to that room, and join it from any of the client SDKs, currently React, JavaScript, React Native, Android, iOS, Flutter, Unity, C++, IoT, and Python. Recording, interactive live streaming, transcription, and SIP telephony run as server-side calls against the same room.</p><h3 id="api-or-sdk-which-one-are-you-integrating">API or SDK: Which one are you integrating?</h3><p>Both, and the split is worth naming because it decides where your code lives.</p><p>The <strong>API</strong> is the server surface. It is HTTP, you call it from your backend with your secret, and it handles room creation, token minting, recording control, and analytics. The <a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">REST API reference</a> documents these endpoints.</p><p>The <strong>SDK</strong> is the client surface. It is a package you install into your web or mobile app, it holds the WebRTC connection, and it never sees your secret. When people say they want to integrate a video conferencing SDK, this is the half they mean.</p><p>Your backend talks to the API. Your frontend talks to the SDK. The JWT is the handoff between them, and getting that handoff right is most of the integration.</p><h2 id="before-you-start-integrating-a-video-conferencing-api">Before you start integrating a video conferencing API</h2><p>Five things need to be in place before you integrate video conferencing API calls into a real product, and four of them fail silently if you skip them.</p><p><strong>1. An account and API credentials.</strong> Sign up at <a href="https://app.videosdk.live/login" rel="noreferrer">VideoSDK</a>, open the dashboard, and copy your API key and secret. A new account starts with <strong>$20 free credit</strong>, which is enough to run the full walkthrough below many times over. The dashboard also issues a temporary token you can paste into a terminal for the first REST call, before your own token endpoint exists.</p><p><strong>2. A token server.</strong> You need one backend route that signs a <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token" rel="noreferrer">JWT</a> with your secret. Node, Python, Go, or anything else works. This is not optional and not something to defer: the secret must never reach the browser, because anyone who reads your bundle can then mint tokens against your account.</p><p><strong>3. An HTTPS origin.</strong> Browsers only expose <code>getUserMedia</code> and <code>getDisplayMedia</code> in a secure context, per the <a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia">MDN MediaDevices reference</a>. <code>http://localhost</code> counts as secure, so development works. The moment you deploy to a plain HTTP host, camera access returns nothing and the failure looks like a permissions bug.</p><p><strong>4. Camera and microphone permission handling.</strong> The permission prompt fires on the first <code>getUserMedia</code> call, and users deny it often enough that you need a real path for it. Plan a pre-call device check screen rather than discovering the denial after the participant has already joined.</p><p><strong>5. A browser support decision.</strong> VideoSDK runs on Chrome, Edge, Firefox, and Safari on both desktop and mobile. Screen sharing is the exception.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Surface</th>
<th>Audio and video calling</th>
<th>Screen sharing</th>
</tr>
</thead>
<tbody>
<tr>
<td>Chrome, Edge, Firefox (desktop)</td>
<td>Supported</td>
<td>Supported</td>
</tr>
<tr>
<td>Safari (macOS)</td>
<td>Supported</td>
<td>Supported</td>
</tr>
<tr>
<td>Chrome, Firefox (Android)</td>
<td>Supported</td>
<td>Not supported in browser</td>
</tr>
<tr>
<td>Safari (iOS and iPadOS)</td>
<td>Supported</td>
<td>Not supported in browser</td>
</tr>
<tr>
<td>React Native and Flutter apps</td>
<td>Supported</td>
<td>Supported through native screen capture</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>VideoSDK supports screen sharing on desktop browsers. Mobile and tablet browsers don't allow it, that's a browser limitation, so if mobile screen share is part of your requirements, you'll need a native app rather than a web build.</p><h2 id="how-to-integrate-a-video-conferencing-api-in-six-steps">How to integrate a video conferencing API in six steps</h2><p>To integrate a video conferencing API, create a room on your server, mint a scoped token, join the room from the client, render the streams, wire the controls, then clean up on exit.</p><ol><li><strong>Create a room.</strong> Call the rooms endpoint from your backend and store the returned room ID against your own appointment, class, or ticket record.</li><li><strong>Generate a JWT.</strong> Sign a token server-side with your API secret, scoped to one room and one participant, with a short expiry.</li><li><strong>Join the room.</strong> Pass the token and room ID to the client SDK and call join from a user action.</li><li><strong>Render participants.</strong> Subscribe to participant and stream events, then attach each track to a media element.</li><li><strong>Add controls.</strong> Wire mute, camera toggle, and screen share to SDK methods rather than to raw browser APIs.</li><li><strong>Leave and clean up.</strong> Call leave, detach listeners, and stop local tracks so the camera light actually goes out.</li></ol><p>Teams that integrate video conferencing API endpoints for the first time usually underestimate steps 2 and 6.</p><p>Follow this <a href="https://www.videosdk.live/sdk/javascript/video-calling" rel="noreferrer">quickstart</a> to integrate video conferencing API yourself!</p><p>You can also watch this video to get a quick integration guide idea!</p>
<!--kg-card-begin: html-->
<iframe width="720" height="415" src="https://www.youtube.com/embed/Auxjhx0_T1s?si=zNJa5wpiorCIz1cj" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<h2 id="common-video-conferencing-api-integration-errors">Common video conferencing API integration errors</h2><p>Six failures account for most of the debugging time in a first integration, and five of them raise a specific error code rather than a generic connection failure.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Symptom</th>
<th>Code and name</th>
<th>Cause</th>
<th>Fix</th>
</tr>
</thead>
<tbody>
<tr>
<td>Join silently fails, no participants appear</td>
<td>4002 <code>INVALID_TOKEN</code></td>
<td>Token empty, malformed, or expired before join</td>
<td>Mint the token immediately before join, not at page load. Confirm the payload carries <code>apikey</code> and <code>permissions</code>.</td>
</tr>
<tr>
<td>Join rejected for a room that exists</td>
<td>4003 <code>INVALID_MEETING_ID</code></td>
<td>Room ID mistyped, or deactivated</td>
<td>Log the exact <code>roomId</code> you pass to <code>initMeeting</code>. A room closed by <code>autoCloseConfig</code> returns this too.</td>
</tr>
<tr>
<td>Token works for one room only</td>
<td>4022 <code>UNAUTHORIZED_MEETING_ID</code></td>
<td>Token was scoped to a different <code>roomId</code></td>
<td>Mint per room. A token with <code>roomId</code> set cannot join any other room.</td>
</tr>
<tr>
<td>Black tile, no video, no error dialog</td>
<td>3014 <code>ERROR_GET_VIDEO_MEDIA_PERMISSION_DENIED</code></td>
<td>Camera permission denied, or the page is not on HTTPS</td>
<td>Add a pre-call device check. Confirm the origin is HTTPS or localhost.</td>
</tr>
<tr>
<td>Video works in Chrome, fails in Safari</td>
<td><code>ERROR_VIDEO_PRODUCE_CODEC_NOT_SUPPORTED</code></td>
<td>Requested codec unsupported on that device</td>
<td>VideoSDK falls back to VP8 automatically while <code>codecSwitchEnabled</code> stays true. Do not disable it.</td>
</tr>
<tr>
<td>Remote video stays frozen on first frame on iPhone</td>
<td>Autoplay blocked, no SDK code</td>
<td>iOS Safari blocks unmuted autoplay</td>
<td>Set <code>playsInline</code> and <code>muted</code> on the element, then call <code>play()</code> inside the join click handler.</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Two of those deserve more than a table row.</p><p><strong>Codec negotiation.</strong> VideoSDK supports VP8, H264, VP9, and AV1, with VP8 as the default. If a device cannot produce the codec you requested, the SDK switches that participant to VP8 and raises the error rather than dropping them. VP9 and AV1 do not support multi-layer streaming, so passing <code>multiStream: true</code> with either one silently sets it to false. The <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track">optimize video track guide</a> documents the full matrix.<br>Read this to know more about codecs: <a href="https://www.videosdk.live/blog/h264-vs-h265" rel="noreferrer">H.264 vs H.265</a></br></p><p><strong>Autoplay on iOS.</strong> Since 2016, WebKit has allowed inline autoplay only for muted video, as described in Apple's <a href="https://webkit.org/blog/6784/new-video-policies-for-ios/">video policies post</a>. Remote audio needs a user gesture, which is why calling <code>play()</code> inside the join handler works and calling it from a <code>stream-enabled</code> listener sometimes does not.</p><h2 id="testing-and-production-checklist">Testing and production checklist</h2><p>Two participants on one laptop proves the code compiles. It does not prove the integration works.</p><p><strong>Test the failure paths, not the happy path.</strong></p><ul><li>Open the room in two browsers, not two tabs. Two tabs of the same browser share one permission grant and hide permission bugs.</li><li>Deny camera permission on purpose and confirm your interface says something useful.</li><li>Throttle to a slow connection in Chrome DevTools and watch whether video degrades or the call drops.</li><li>Kill wifi mid-call for ten seconds and confirm the participant returns instead of leaving a frozen tile.</li><li>Run one client on cellular. Corporate wifi and home wifi both hide TURN relay problems that mobile networks expose.</li><li>Test Safari on a real iPhone. The simulator does not reproduce autoplay and inline playback behaviour.</li></ul><p><strong>Before you ship.</strong></p><ul><li>The API secret exists only in server environment variables. Search your built bundle for it to be sure.</li><li>Tokens are scoped with <code>roomId</code> and <code>participantId</code>, and expire in an hour or less.</li><li>Only hosts get <code>allow_mod</code>.</li><li>The token route sits behind your own authentication and authorisation.</li><li>Recording and streaming start from the server, never from a client control.</li><li>The whole app is served over HTTPS, including any iframe embedding it.</li><li>Room IDs are stored against your own records so you can reconcile sessions and billing later.</li><li>Webhook endpoints for recording and session events are live and verified.</li></ul><h2 id="how-much-does-it-cost-to-integrate-video-conferencing">How much does it cost to integrate video conferencing?</h2><p>VideoSDK charges per participant minute, so cost scales with people multiplied by time, not with the number of rooms you create.</p><p>These are the published rates as of September 8, 2026.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Service</th>
<th>Rate</th>
</tr>
</thead>
<tbody>
<tr>
<td>Voice only</td>
<td>$0.001 per participant minute</td>
</tr>
<tr>
<td>Video HD, 720p</td>
<td>$0.004 per participant minute</td>
</tr>
<tr>
<td>Video Full HD, 1080p</td>
<td>$0.008 per participant minute</td>
</tr>
<tr>
<td>Recording, HD</td>
<td>$0.015 per recorded minute</td>
</tr>
<tr>
<td>Interactive live streaming, HD</td>
<td>$0.002 per viewer minute</td>
</tr>
<tr>
<td>HLS encoding, HD</td>
<td>$0.04 per livestream minute</td>
</tr>
<tr>
<td>Real-time transcription</td>
<td>$0.020 per transcription minute</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Work the arithmetic for your own shape of call before you commit.</p><ul><li>A 1:1 telehealth consult, 20 minutes, HD video: <br>2 participants × 20 minutes × $0.004 = $0.16</br></li><li>A 12-person standup, 15 minutes, HD video: <br>12 × 15 × $0.004 = $0.72</br></li><li>The same consult with recording: <br>$0.16 + (20 recorded minutes × $0.015) = $0.46</br></li><li>A webinar with 4 speakers and 500 viewers for 60 minutes, using interactive live streaming: <br>(4 × 60 × $0.004) + (500 × 60 × $0.002) = $60.96</br></li></ul><p>The pattern that catches teams out is the viewer side of streaming. Speaker cost is trivial and audience cost is linear, so a webinar product's margin is set by the streaming rate rather than the calling rate.</p><p>The <strong>$20 free credit</strong> on signup covers roughly 5,000 participant minutes of HD video, which is enough to build and test a product before any card is involved. Current rates live on the <a href="https://www.videosdk.live/pricing">VideoSDK pricing page</a>.</p><h2 id="when-a-different-provider-fits-better">When a different provider fits better</h2><p>An honest integration guide names the cases where its own product is the wrong pick.</p><p>Choose something else when you need a fully managed meeting product rather than an API, because a scheduling and hosting tool such as Zoom or Google Meet already solves that and a build does not. Choose an open-source stack you host yourself when data residency rules require media to never leave hardware you control, and you have the operations team to run turn servers and an SFU.</p><p>VideoSDK's limits are worth stating too. Browser screen share is desktop only. VP9 and AV1 give up multi-layer streaming. Expo Go cannot load the React Native SDK, so mobile means a development build.</p><p>If you are still comparing vendors rather than implementing, the evaluation criteria and provider comparison live in VideoSDK's <a href="https://www.videosdk.live/developer-hub/webrtc/video-conferencing-api">video conferencing API developer hub guide</a>. This article assumes the decision is made and the work is the build.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Room:</strong> A VideoSDK meeting space identified by a room ID such as <code>abc-xyzw-lmno</code>. Participants join a room, and every server-side operation, including recording and streaming, targets that room ID.</blockquote><blockquote><strong>Meeting token:</strong> A JWT signed server-side with your API secret that authorises one participant to join one room. Scoping it with <code>roomId</code> and <code>participantId</code> is what stops a leaked room ID from becoming an open door.</blockquote><blockquote><strong>Participant:</strong> A person or an AI agent connected to a room, each carrying their own audio and video streams, addressable through <code>useParticipant</code> in React or the participant object in JavaScript.</blockquote><blockquote><strong>SFU (selective forwarding unit):</strong> The media server that receives one upload from each participant and forwards it to the others. It is why a 20-person VideoSDK call does not require 19 uploads from every device.</blockquote><blockquote><strong>Composition:</strong> The server-side layout applied when a room is recorded or streamed, controlling layout, quality, grid size, orientation, and theme. It is what turns many participant streams into one rendered video file or feed.</blockquote><blockquote><strong>Network-adaptive streaming:</strong> VideoSDK's automatic adjustment of bitrate and resolution as available bandwidth changes, which is what degrades a call gracefully instead of dropping it.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>Integrating a video conferencing API is four moving parts: a room created server-side, a scoped JWT, a client SDK that joins, and event handlers that attach media to elements.</li><li>The API secret belongs in server environment variables only, and the token that reaches the browser should be scoped to one room and one participant with a short expiry.</li><li>Media arrives on <code>stream-enabled</code>, not on <code>participant-joined</code>, and treating those two events as one is the most common cause of a black tile.</li><li>Recording, HLS, and RTMP run from the VideoSDK Server SDK against a room ID, so participants cannot start a recording your product did not authorise.</li><li>VideoSDK bills per participant minute, at $0.004 for HD video, and the $20 free credit covers roughly 5,000 participant minutes of testing.</li></ul><h2 id="conclusion">Conclusion</h2><p>You now have the full path to integrate a video conferencing API: create a room, mint a scoped token, join, render, control, and clean up, plus recording, mobile, and the errors that show up in week two rather than day one.</p><p>Build it against your own product's roles rather than a generic demo, because the token route is where your authorisation model meets the call. Start with the <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start">JavaScript quickstart</a> or the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a>, sign up at <a href="https://app.videosdk.live/login" rel="noreferrer">VideoSDK</a> for <strong>$20 free credit</strong>, and check current rates on the <a href="https://www.videosdk.live/pricing">pricing page</a>.</p><p>What are you building with VideoSDK? Drop a comment with the kind of call your product needs, and if you get stuck on the token route, the <a href="https://discord.gg/Gpmj6eCq5u">VideoSDK Discord</a> is the fastest place to get unstuck.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="what-is-a-video-conferencing-api-1">What is a video conferencing API?</h3><p>A video conferencing API is a hosted service that handles WebRTC signaling, media routing, recording, and streaming, exposed as REST endpoints for your server and SDKs for your client. It removes the need to run your own signaling server, SFU, and TURN infrastructure. VideoSDK provides it as a rooms-based API with client SDKs for React, JavaScript, React Native, Android, iOS, Flutter, Unity, C++, IoT, and Python.</p><h3 id="how-do-i-integrate-a-video-conferencing-api-into-my-website">How do I integrate a video conferencing API into my website?</h3><p>To integrate a video conferencing API into a website, create a room from your backend with a POST to the rooms endpoint, sign a JWT with your API secret, pass that token and the room ID to the client SDK, then call join from a user click. With VideoSDK's JavaScript SDK, that is <code>VideoSDK.config(token)</code>, <code>VideoSDK.initMeeting({ meetingId })</code>, and <code>meeting.join()</code>. Rendering participants means listening for <code>participant-joined</code> and <code>stream-enabled</code> and attaching each track to a video element.</p><h3 id="what-is-the-difference-between-a-video-conferencing-api-and-an-sdk">What is the difference between a video conferencing API and an SDK?</h3><p>The API is the server-side HTTP surface used for room creation, token minting, and recording control, and it is called with your secret from your backend. The SDK is the client-side package that holds the WebRTC connection and renders media, and it authenticates with a token rather than a secret. A working integration uses both, with the JWT as the handoff between them.</p><h3 id="how-long-does-video-conferencing-api-integration-take">How long does video conferencing API integration take?</h3><p>A working two-participant call takes a few hours, since it is one REST call, one token route, and roughly forty lines of client code. Production readiness takes longer, because permission handling, reconnection, device selection, layout, and recording controls are each real work. Teams that skip the pre-call device check and the token expiry design are the ones that spend weeks debugging after launch.</p><h3 id="can-i-integrate-a-video-conference-api-without-a-backend">Can I integrate a video conference API without a backend?</h3><p>No. You cannot integrate video conference API calls from the browser alone, because signing tokens requires your API secret, and any secret shipped to the browser can be extracted from the bundle and used to mint tokens against your account. The minimum viable backend is a single route that signs a JWT, which runs fine in a serverless function.</p><h3 id="how-much-does-it-cost-to-integrate-video-conferencing-into-an-app">How much does it cost to integrate video conferencing into an app?</h3><p>VideoSDK charges per participant minute, at $0.001 for voice, $0.004 for HD video, and $0.008 for Full HD, with recording at $0.015 per recorded minute, verified on September 8, 2026. A 20-minute HD consult between two people costs about $0.16, and adding a recording brings it to roughly $0.46. New accounts start with $20 free credit, which covers about 5,000 participant minutes of HD video.</p><h3 id="can-i-customise-the-video-call-interface">Can I customise the video call interface?</h3><p>Yes. The client SDKs give you the raw participant streams and state through <code>useParticipant</code> and the participant object, so the layout, controls, and branding are your own components. If you want a working interface without building one, the Prebuilt UI Kit drops in a complete call interface, and you can move to the custom SDK later without changing the room or token model.</p><h3 id="how-many-participants-can-one-video-conferencing-room-hold">How many participants can one video conferencing room hold?</h3><p>Room capacity depends on the mode you use rather than on a single fixed number. Interactive calls where everyone can speak are limited by what each device can decode, so grids stay practical in the tens of participants. For larger audiences, interactive live streaming and HLS separate a small set of speakers from a much larger set of viewers, which is why the pricing model bills viewers separately.</p>]]></content:encoded></item><item><title><![CDATA[Virtual Classroom Software: 10 Platforms Compared]]></title><description><![CDATA[Virtual classroom software built on a video API: VideoSDK, Zoom Video SDK, Daily, Agora, LiveKit, 100ms, Twilio, Vonage, Amazon Chime, and Cloudflare RealtimeKit compared on whiteboard, breakouts, recording, streaming, and price per session, plus when building beats buying Zoom or Teams.]]></description><link>https://www.videosdk.live/blog/virtual-classroom-software</link><guid isPermaLink="false">6a9e7a6bb3240feb748c9ab9</guid><category><![CDATA[video-conferencing]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 08 Sep 2026 07:41:01 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/ChatGPT-Image-Sep-7--2026--05_26_30-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>Virtual classroom software is a real-time application where instructors and learners meet online with video, audio, a shared whiteboard, breakout rooms, polls, and recording. Edtech companies increasingly build it on a video API rather than renting a finished product: platforms such as VideoSDK, Zoom Video SDK, Daily, Agora, and LiveKit supply the rooms, media, whiteboard, recording, and live streaming, billed per participant-minute, so the classroom you ship is your own.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/ChatGPT-Image-Sep-7--2026--05_26_30-PM.png" alt="Virtual Classroom Software: 10 Platforms Compared"/><p>A 1:1 online lesson costs about $0.48 an hour on a per-participant-minute video API. The same lesson on a rented classroom platform costs a monthly seat licence whether the tutor teaches two hours or two hundred. That difference, and the question of who owns the room, the data, and the roadmap, is why most <a href="https://www.videosdk.live/solutions/edtech" rel="noreferrer">edtech</a> products built since 2020 run on a <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">video API</a> rather than inside someone else's classroom.</p><p>If you are building a tutoring marketplace, a cohort-based course platform, a coding bootcamp, a language school app, or a corporate academy, this guide compares the 10 video APIs and SDKs you can build a virtual classroom on, on the features that matter for teaching: whiteboard, breakout rooms, recording, lecture-scale streaming, platform coverage, and price per session. It closes with a decision framework for when building on an API beats buying Zoom or Teams, and when it does not.</p><h2 id="what-is-virtual-classroom-software">What Is Virtual Classroom Software?</h2><p>Virtual classroom software is defined as an application that reproduces a live classroom over the internet, combining real-time video and audio with teaching tools such as a shared whiteboard, screen sharing, breakout rooms, polls, hand-raising, attendance, and session recording.</p><p>Virtual classroom software works by connecting every participant to a media server over <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a>, then applying a role model on top: instructors present, mute, split the room, and record, while learners speak, write on the board, and answer prompts. The teaching layer is what separates a classroom from a meeting.</p><p>There are two ways to get one. You can rent a finished application such as Zoom for Education, Microsoft Teams, or BigBlueButton, where the vendor owns the interface and you get an account. Or you can build on a virtual classroom API, where a provider such as VideoSDK supplies the real-time infrastructure through SDKs and REST endpoints and your application is the classroom. VideoSDK's React SDK, for example, exposes the room through the <code>useMeeting</code> hook and the whiteboard through the <code>useWhiteboard</code> hook, and ships the same capability across 10+ platforms including Flutter, Android, iOS, and Unity. See the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React quickstart</a> for the full room setup.</p><p>This article is about the second path. The first is covered briefly in the buy-vs-build section, because the honest answer for a school or an internal training team is usually to rent.</p><h3 id="virtual-classroom-vs-online-classroom-vs-digital-classroom-vs-lms">Virtual Classroom vs Online Classroom vs Digital Classroom vs LMS</h3><p>These terms overlap in search but mean different things in an architecture diagram. The table below is the version to keep.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Term</th>
<th>What it means</th>
<th>Typical example</th>
<th>Where live video fits</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Virtual classroom</strong></td>
<td>A live, synchronous session with video plus teaching tools</td>
<td>A VideoSDK-built room, a Zoom class, a BigBlueButton session</td>
<td>Always, it's the defining feature</td>
</tr>
<tr>
<td><strong>Online classroom</strong></td>
<td>Umbrella term for any internet-delivered class, live or recorded</td>
<td>A Coursera course, a Teams class</td>
<td>Sometimes, depends on the course</td>
</tr>
<tr>
<td><strong>Digital classroom</strong></td>
<td>A physical classroom augmented with devices and software</td>
<td>A smartboard plus Google Classroom in a school</td>
<td>Rarely, the students are in the room</td>
</tr>
<tr>
<td><strong>Learning management system (LMS)</strong></td>
<td>Stores courses, assignments, grades and rosters</td>
<td>Moodle, Canvas, Blackboard Learn</td>
<td>Not built in, it launches a separate tool</td>
</tr>
<tr>
<td><strong>Video API / SDK</strong></td>
<td>Programmable real-time infrastructure you build a classroom on</td>
<td>VideoSDK, Daily, Agora, LiveKit</td>
<td>It <em>is</em> the video layer</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>A useful rule: an LMS holds the course, a virtual classroom holds the session, a digital classroom holds the devices, and a video API holds the media. Most edtech products own the first two, integrate the third through LTI, and rent the fourth from one of the providers below.</p><h2 id="what-is-a-virtual-classroom-api">What Is a Virtual Classroom API?</h2><p>A <a href="https://www.videosdk.live/blog/virtual-classroom-api" rel="noreferrer">virtual classroom API</a> is a programmable service that supplies live video, audio, whiteboard, recording, messaging, and streaming as building blocks so that a developer can assemble a classroom inside their own product.</p><p>A virtual classroom API works by giving you three surfaces. A client SDK (React, Flutter, iOS, Android, and so on) that joins a room and renders participant streams. A server-side REST API that creates rooms, mints access tokens, starts recordings, and reports sessions. <a href="https://docs.videosdk.live/api-reference/realtime-communication/user-webhooks" rel="noreferrer">Webhooks</a> that tell your backend when someone joined, left, or when a recording is ready, so attendance and grades can flow into your LMS.</p><p>Compared with rented virtual classroom software, the API route trades setup time for control. You write the scheduling, the roster, the breakout logic, and the LMS integration. In exchange, the room carries your brand, the recordings land in your storage, and your users never see another vendor's login. </p><h2 id="what-features-to-look-for-in-a-virtual-classroom-api">What Features to Look For in a Virtual Classroom API</h2><p>Eight capabilities decide whether a video API can carry a classroom, and only the first two come standard with every provider.</p><ol><li><strong>Multi-party video with adaptive bitrate.</strong> Every provider does this. The difference is behaviour at 500 kbps on a phone, which is where students actually are. Ask for simulcast and dynamic resolution switching.</li><li><strong>A whiteboard you can turn on without a second vendor.</strong> VideoSDK, 100ms, and Agora ship one; most others expect you to integrate tldraw, Excalidraw, or a paid board. A missing whiteboard adds weeks to a classroom build.</li><li><strong>Breakout rooms as a supported pattern.</strong> No API ships a one-line "breakout" flag. Check whether the provider documents moving participants between rooms and whether tokens can carry room scope.</li><li><strong>Recording with the output you need.</strong> Composite recording for lecture replay, individual-track recording for review and accessibility, and webhooks that deliver the file to your own bucket.</li><li><strong>Lecture-scale streaming from the same session.</strong> A seminar of 25 and a masterclass of 2,000 are different technical problems. <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">Interactive live streaming</a> (low-latency, viewers can be promoted) covers both without an HLS delay. VideoSDK documents 100 hosts and 2,000 real-time viewers per session.</li><li><strong>Live transcription and captions.</strong> Accessibility requirements and post-session notes both depend on it. Check whether it is built in or a third-party plugin.</li><li><strong>Platform coverage that matches your roadmap.</strong> Web and two mobile SDKs are table stakes. Flutter, Unity, and desktop matter for K-12 apps, simulations, and exam clients.</li><li><strong>Compliance and data location.</strong> GDPR, HIPAA where health training is involved, SOC 2, and region pinning for public-sector deals.</li></ol><p>A provider that meets six of eight is a serious candidate. One that lacks a whiteboard or lecture-scale streaming will cost you a second vendor, and that second contract is where API projects lose their cost advantage.</p><h2 id="virtual-classroom-apis-compared-at-a-glance">Virtual Classroom APIs Compared at a Glance</h2><p>The table below is the comparison most teams need first; the individual reviews that follow explain each row.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>API / SDK</th>
<th>Published video rate</th>
<th>Free tier</th>
<th>Built-in whiteboard</th>
<th>Interactive live streaming</th>
<th>Best for</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td>$0.004 per participant-min HD; $0.001 audio</td>
<td>$20 credit, no card</td>
<td>Yes (<code>useWhiteboard</code>)</td>
<td>Yes, 100 hosts + 2,000 real-time viewers</td>
<td>Multi-platform edtech products wanting classroom features from one SDK</td>
</tr>
<tr>
<td>Zoom Video SDK</td>
<td>$0.0035 per session-min via Build Platform credits</td>
<td>10,000 min/month</td>
<td>No (Zoom Whiteboard is separate)</td>
<td>Via Zoom infrastructure</td>
<td>Teams whose buyers want the Zoom name without Zoom's UI</td>
</tr>
<tr>
<td>Daily</td>
<td>$0.004 per participant-min</td>
<td>10,000 min/month</td>
<td>No</td>
<td>HLS</td>
<td>Fast prototyping with Daily Prebuilt</td>
</tr>
<tr>
<td>Agora</td>
<td>$3.99 per 1,000 HD min (about $0.004/min)</td>
<td>10,000 min/month</td>
<td>Separate paid Interactive Whiteboard</td>
<td>Yes</td>
<td>Very large broadcast scale, China delivery</td>
</tr>
<tr>
<td>LiveKit</td>
<td>Cloud tiers from free; media about $0.0005/min plus bandwidth</td>
<td>Build tier (5,000 min)</td>
<td>No</td>
<td>Yes</td>
<td>Teams that want open source and may self-host</td>
</tr>
<tr>
<td>100ms</td>
<td>$0.004 per participant-min HD; $0.001 audio</td>
<td>10,000 min/month</td>
<td>Yes</td>
<td>Yes (HLS + interactive)</td>
<td>India-based edtech, live commerce crossovers</td>
</tr>
<tr>
<td>Twilio Video</td>
<td>$0.004 per participant-min (Group Rooms)</td>
<td>Trial credit</td>
<td>No</td>
<td>No</td>
<td>Existing Twilio customers (decision reversed Oct 2024)</td>
</tr>
<tr>
<td>Vonage Video API</td>
<td>$0.0041 per participant-min up to 25 publishers</td>
<td>75,000 trial min</td>
<td>No</td>
<td>Broadcast add-on</td>
<td>Regulated enterprises already on Vonage</td>
</tr>
<tr>
<td>Amazon Chime SDK</td>
<td>$0.0017 per attendee-min</td>
<td>AWS free tier</td>
<td>No</td>
<td>Media replication add-on</td>
<td>AWS-native teams with their own UI</td>
</tr>
<tr>
<td>Cloudflare RealtimeKit (ex-Dyte)</td>
<td>Beta; pricing on Cloudflare docs</td>
<td>Beta</td>
<td>Inherited from Dyte </td>
<td>Yes</td>
<td>Teams already on Cloudflare Workers</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p><em>Rates are per participant-minute unless noted, taken from each vendor's pricing page in September 2026. Recording, transcription, and streaming are billed separately by every provider.</em></p><p>The row that matters most for cost planning is the free tier column, not the rate column. Six providers cluster at $0.004 per participant-minute; the difference in your first year is what you get before billing starts and how many separate line items (whiteboard, recording, streaming, transcription) you pay after.</p><h2 id="the-10-best-video-apis-for-building-a-virtual-classroom">The 10 Best Video APIs for Building a Virtual Classroom</h2><h3 id="1-videosdk">1. VideoSDK</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-07-23-at-6.29.39-PM.png" class="kg-image" alt="Virtual Classroom Software: 10 Platforms Compared" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> is a real-time video, audio, and interactive live streaming platform with SDKs for React, JavaScript, React Native, Flutter, Android, iOS, Unity, C++, IoT, and Python, plus a Prebuilt UI Kit that embeds a working room with one component. </p><p><a href="https://www.videosdk.live/pricing" rel="noreferrer">Pricing is pay-as-you-go</a>: HD video at $0.004 per participant-minute, audio at $0.001, HD live streaming at $0.002 per viewer-minute, recording at $0.015 per recorded minute, and real-time transcription at $0.02 per minute, with a $20 credit on signup and no card required. Compliance certifications listed include GDPR, HIPAA, ISO, and SOC-family reports.</p><p><strong>Why it is on the list:</strong> it is the provider that covers the most of the eight classroom criteria natively. Whiteboard (<code>useWhiteboard</code>), pub/sub for polls and chat (<code>usePubSub</code>), cloud recording, real-time and post-call transcription, and interactive live streaming with <code>changeMode</code> to promote a viewer to a speaker all live in the same SDK, so a classroom build does not need a second vendor for the board or the lecture hall.</p><p><strong>Where it falls short:</strong> the whiteboard renders in an iframe, which limits deep styling. Breakout rooms are composed from multiple rooms via REST plus your own move-participant logic, not switched on with a flag. LTI (Learning Tools Interoperability) integration is your application code. </p><p><strong>Best for:</strong> edtech products that need whiteboard, recording, transcription, and lecture-scale streaming from one SDK across web and mobile, and want a Prebuilt option for the MVP. The <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Prebuilt quickstart</a> gets a room on screen in an afternoon.</p><h3 id="2-zoom-video-sdk">2. Zoom Video SDK</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-07-23-at-6.32.46-PM.png" class="kg-image" alt="Virtual Classroom Software: 10 Platforms Compared" loading="lazy" width="2920" height="1646"/></figure><p><a href="https://www.zoom.com/en/video-sdk/" rel="noreferrer nofollow">Zoom Video SDK</a> exposes Zoom's media infrastructure without the Zoom Meetings interface, so you build your own UI on top. It is sold through the Zoom Build Platform, a metered credit subscription that also covers cloud recording, translation and transcription, and the Cobrowse SDK. Each session minute costs $0.0035, with 10,000 free minutes a month, and recording at $0.01 per minute plus storage.</p><p><strong>Why it is on the list:</strong> procurement. Universities and enterprises that have already approved Zoom clear a Zoom Video SDK contract faster than any other vendor on this list, and the media quality is the reference point everyone else is compared against.</p><p><strong>Where it falls short:</strong> there is no native whiteboard in the Video SDK (Zoom Whiteboard is a separate product), no interactive live streaming with viewer promotion in the classroom sense, and the credit model penalises bursty, term-time usage because unused credits do not carry over cleanly.</p><p><strong>Best for:</strong> teams whose buyers ask for Zoom by name and who are prepared to integrate a whiteboard themselves.</p><h3 id="3-daily">3. Daily</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-07-23-at-6.30.02-PM.png" class="kg-image" alt="Virtual Classroom Software: 10 Platforms Compared" loading="lazy" width="2924" height="1652"/></figure><p><a href="https://www.daily.co/" rel="noreferrer nofollow">Daily</a> is a pure pay-as-you-go WebRTC API at $0.004 per participant-minute after 10,000 free minutes per month, with automatic volume discounts and no subscription. Daily Prebuilt is one of the fastest embeddable call UIs available, and the React hooks library is mature.</p><p><strong>Why it is on the list:</strong> time to first working call. For a tutoring MVP, Daily Prebuilt in an iframe is a one-hour job, and the pricing has no minimums.</p><p><strong>Where it falls short:</strong> no built-in whiteboard, and large sessions go out over HLS rather than an interactive low-latency mode, so a 1,000-viewer lecture has a delay and viewers cannot be promoted on the fly. Daily's recent roadmap emphasis has been voice AI (Pipecat), so check classroom feature velocity.</p><p><strong>Best for:</strong> prototypes and small-group products where speed to launch outweighs whiteboard and lecture-scale needs.</p><h3 id="4-agora">4. Agora</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-07-23-at-6.30.26-PM.png" class="kg-image" alt="Virtual Classroom Software: 10 Platforms Compared" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/en/" rel="noreferrer nofollow">Agora</a> is the largest global real-time network on this list, with video calling at $3.99 per 1,000 HD minutes (about $0.004 per participant-minute), 10,000 free minutes a month, and a separately priced Interactive Whiteboard product built for education.</p><p><strong>Why it is on the list:</strong> scale and reach. If your masterclasses need tens of thousands of concurrent viewers or your learners are in mainland China, Agora's network is the practical choice, and its Flexible Classroom reference app shows a complete education layout.</p><p><strong>Where it falls short:</strong> the whiteboard, recording, and streaming are separate SKUs, so a full classroom bill has four or five line items. The SDK surface is large and the learning curve is steeper than the hooks-based SDKs.</p><p><strong>Best for:</strong> very large broadcast classes, China delivery, and teams with the engineering capacity to assemble multiple Agora products.</p><h3 id="5-livekit">5. LiveKit</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-07-23-at-6.30.40-PM.png" class="kg-image" alt="Virtual Classroom Software: 10 Platforms Compared" loading="lazy" width="2920" height="1670"/></figure><p><a href="https://livekit.com/" rel="noreferrer nofollow">LiveKit</a> is an open-source WebRTC stack (SFU, server SDKs, client SDKs) with a hosted LiveKit Cloud. Cloud tiers run from a free Build tier (5,000 WebRTC minutes) through Ship at $50 a month and Scale at $500 a month, with media metered at roughly $0.0004 to $0.0005 per minute plus bandwidth after allotments. Self-hosting the open-source server costs only your infrastructure.</p><p><strong>Why it is on the list:</strong> ownership. Teams with a data-residency requirement or a long-term cost ceiling can run the media layer themselves, and the Apache 2.0 licence removes vendor lock-in.</p><p><strong>Where it falls short:</strong> no whiteboard, no classroom-specific components, and the cloud pricing meters connection minutes, bandwidth, and agent minutes separately, which is harder to forecast than a single participant-minute rate. Self-hosting means TURN, scaling, and on-call are your problem.</p><p><strong>Best for:</strong> engineering-heavy teams that want open source and may self-host, and products that combine classroom video with voice AI agents.</p><h3 id="6-100ms">6. 100ms</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-07-23-at-6.31.12-PM.png" class="kg-image" alt="Virtual Classroom Software: 10 Platforms Compared" loading="lazy" width="2910" height="1656"/></figure><p><a href="https://www.100ms.live/" rel="noreferrer nofollow">100ms</a> is a video SDK with published rates of $0.004 per participant-minute for HD conferencing and $0.001 for audio, 10,000 free conferencing minutes and 10,000 free streaming minutes a month, and a built-in whiteboard.</p><p><strong>Why it is on the list:</strong> it ships the whiteboard and both HLS and interactive streaming, which puts it close to VideoSDK on the classroom checklist, and its documentation has an explicit edtech track.</p><p><strong>Where it falls short:</strong> platform coverage is web, iOS, Android, React Native, and Flutter; there is no Unity or IoT SDK. Public pricing beyond the entry rates requires a sales conversation.</p><p><strong>Best for:</strong> edtech teams, particularly in India, that want whiteboard and streaming in one SDK and are comfortable with a smaller platform matrix.</p><h3 id="7-twilio-video">7. Twilio Video</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-07-23-at-6.53.31-PM.png" class="kg-image" alt="Virtual Classroom Software: 10 Platforms Compared" loading="lazy" width="2910" height="1638"/></figure><p><a href="https://www.twilio.com/en-us/video" rel="noreferrer nofollow">Twilio Video</a> is a WebRTC API at $0.004 per participant-minute for Group Rooms, with recordings and compositions billed on top. Twilio announced a sunset in December 2023, then reversed it on October 21, 2024, stating that Video would remain a standalone product with no action required from customers.</p><p><strong>Why it is on the list:</strong> thousands of existing edtech products still run on it, and for teams already using Twilio for SMS and voice, a single vendor and bill has value.</p><p><strong>Where it falls short:</strong> no whiteboard, no interactive live streaming, no new classroom features in years, and a sunset scare that many teams will not forget. The reversal keeps the product alive; it does not make it a growth platform.</p><p><strong>Best for:</strong> existing Twilio customers who need stability more than new capability.</p><h3 id="8-vonage-video-api">8. Vonage Video API</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-07-23-at-6.32.16-PM.png" class="kg-image" alt="Virtual Classroom Software: 10 Platforms Compared" loading="lazy" width="2922" height="1652"/></figure><p><a href="https://www.vonage.com/communications-apis/video/" rel="noreferrer nofollow">Vonage Video API</a> (formerly TokBox OpenTok) is priced at $0.0041 per participant-minute for sessions with up to 25 active publishers, rising sharply above that (about $0.019 at 26 to 35 publishers and $0.023 at 36 or more), with a 75,000-minute trial. It is now part of Ericsson.</p><p><strong>Why it is on the list:</strong> compliance and longevity. Vonage has HIPAA and regional data-centre options that regulated training providers need, and the API has been stable for over a decade.</p><p><strong>Where it falls short:</strong> the publisher-tier pricing makes large seminars where many students have cameras on expensive, there is no whiteboard, and the SDK feels older than the hooks-based competitors.</p><p><strong>Best for:</strong> regulated enterprises already on Vonage where most sessions have a small number of active cameras.</p><h3 id="9-amazon-chime-sdk">9. Amazon Chime SDK</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-07-23-at-6.54.40-PM.png" class="kg-image" alt="Virtual Classroom Software: 10 Platforms Compared" loading="lazy" width="2918" height="1632"/></figure><p><a href="https://aws.amazon.com/ivs/" rel="noreferrer nofollow">Amazon Chime SDK</a> is AWS's real-time media service, priced at $0.0017 per attendee-minute for WebRTC sessions, billed in six-second increments, with media capture at $0.0125 per minute and media replication for large audiences at $0.0085 per minute per stream.</p><p><strong>Why it is on the list:</strong> the lowest published per-minute rate on this list, and native integration with the rest of AWS (S3 for recordings, Transcribe for captions, IAM for access).</p><p><strong>Where it falls short:</strong> it is infrastructure, not a classroom kit. There is no whiteboard, no prebuilt UI beyond a reference React component library, and no interactive viewer promotion; large audiences use replication, which is one-way. Expect to write more code than with any other provider except self-hosted LiveKit.</p><p><strong>Best for:</strong> AWS-native teams with their own front-end and a preference for consolidating spend on one cloud bill.</p><h3 id="10-cloudflare-realtimekit-formerly-dyte">10. Cloudflare RealtimeKit (formerly Dyte)</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-07-23-at-6.51.09-PM.png" class="kg-image" alt="Virtual Classroom Software: 10 Platforms Compared" loading="lazy" width="2918" height="1644"/></figure><p><a href="https://www.cloudflare.com/" rel="noreferrer nofollow">Cloudflare</a> acquired Dyte in April 2025 and relaunched its SDKs as RealtimeKit, currently in beta, alongside Cloudflare's Serverless <a href="https://www.videosdk.live/blog/sfu-vs-mcu-vs-mesh-webrtc" rel="noreferrer">SFU</a> and <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a> service. RealtimeKit carries Dyte's web and mobile SDKs (React, Angular, vanilla JS, iOS, Android, React Native, Flutter) and server-side recording, coordination, and transcription. Pricing is published on the Cloudflare docs and should be checked directly while the product is in beta.</p><p><strong>Why it is on the list:</strong> Dyte was one of the more complete classroom SDKs before the acquisition, with UI components and a plugin system, and Cloudflare's edge network is a strong media backbone.</p><p><strong>Where it falls short:</strong> beta status, a pricing model still settling, and the usual acquisition risk that features get reprioritised. Confirm whiteboard and breakout support in the current RealtimeKit docs rather than in old Dyte material.</p><p><strong>Best for:</strong> teams already building on Cloudflare Workers who can tolerate a beta and want media on the same edge.</p><h3 id="also-worth-knowing">Also worth knowing</h3><p>Three options fall outside the ten but come up in classroom evaluations. Whereby Embedded is a simple iframe API at $0.004 per participant-minute with a $9.99 monthly base and 2,000 free minutes, good for very small teams. Jitsi as a Service prices by monthly active user (free to 25, then $99 for 300 MAU and up), which suits products with many light users. BigBlueButton is open-source virtual classroom software with a full API and a built-in whiteboard, breakouts, and quizzes; it is a finished classroom you host, not an SDK, so it belongs to the buy side of the decision below.</p><h2 id="buy-vs-build-when-should-you-build-a-virtual-classroom-with-an-api">Buy vs Build: When Should You Build a Virtual Classroom With an API?</h2><p>Build on a video API when the classroom is your product; buy a finished platform when the classroom is a utility you provide to your own staff and students.</p><p>That sentence resolves most cases. The edge cases are where money is lost, so here is the longer version.</p><h3 id="signs-you-should-buy-an-off-the-shelf-virtual-classroom-platform">Signs you should buy an off-the-shelf virtual classroom platform</h3><ul><li>You are a school, district, university department, or internal L&amp;D team.</li><li>Teachers choose their own tools and need something familiar tomorrow.</li><li>Your largest session fits inside the vendor's capacity tier.</li><li>You have no engineering team, or the one you have is fully allocated.</li><li>Your differentiation is curriculum and teaching, not software.</li></ul><p>In that case Microsoft Teams for Education (free on A1), Google Meet with Classroom, Zoom for Education (from $10 per user per month on annual terms), or self-hosted BigBlueButton will serve you better than anything on the list above.</p><h3 id="signs-you-should-build-on-a-virtual-classroom-api">Signs you should build on a virtual classroom API</h3><ul><li>You are an edtech company, tutoring marketplace, cohort-course platform, or corporate academy selling access to your own product.</li><li>Your users must never see another vendor's logo, login, or download prompt.</li><li>You need custom pedagogy in the room: a code editor beside the video, a music notation board, an exam lockdown flow, an AI tutor that joins as a participant.</li><li>Your session shapes range from 1:1 to a 2,000-viewer masterclass and you refuse to run two platforms.</li><li>You need the data: per-participant talk time, join and leave events, recordings in your own storage, through webhooks and REST rather than a CSV export.</li><li>Your unit economics depend on paying for usage, not for seats that sit idle over the summer.</li></ul><h2 id="the-cost-math-nobody-publishes">The cost math nobody publishes</h2><p>Per-seat licensing and per-participant-minute pricing produce very different bills depending on session shape. The figures below use VideoSDK's published HD rate.</p><h3 id="the-three-rates-in-play">The three rates in play</h3>
<!--kg-card-begin: html-->
<table>
<thead>
<tr><th>What's being billed</th><th>Rate</th></tr>
</thead>
<tbody>
<tr><td>Audio-only participant</td><td>$0.001 per person, per minute</td></tr>
<tr><td>Video participant (HD 720p)</td><td>$0.004 per person, per minute</td></tr>
<tr><td>Live-stream viewer (HD 720p)</td><td>$0.002 per viewer, per minute</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h3 id="what-an-hour-actually-costs">What an hour actually costs</h3>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>What you're running</th>
<th>People in the room</th>
<th>One hour costs</th>
<th>How that's calculated</th>
<th>Same thing on a per-seat platform</th>
</tr>
</thead>
<tbody>
<tr>
<td>1:1 tutoring</td>
<td>2</td>
<td><strong>$0.48</strong></td>
<td>2 × 60 min × $0.004</td>
<td>$14.16/mo per tutor, used or not</td>
</tr>
<tr>
<td>Seminar with breakouts</td>
<td>25</td>
<td><strong>$6.00</strong></td>
<td>25 × 60 min × $0.004</td>
<td>$14.16/mo per teacher (Zoom Pro, 100-participant cap)</td>
</tr>
<tr>
<td>Large lecture</td>
<td>200</td>
<td><strong>$48.00</strong></td>
<td>200 × 60 min × $0.004</td>
<td>$18.33/mo per teacher (Business, 300-participant cap)</td>
</tr>
<tr>
<td>Live-streamed masterclass</td>
<td>3 hosts + 2,000 viewers</td>
<td><strong>$240.72</strong></td>
<td>Hosts: 3 × 60 × $0.004 = $0.72<br>Viewers: 2,000 × 60 × $0.002 = $240.00</br></td>
<td>≈$1,032/mo (3 seats + 3,000-attendee webinar tier)</td>
</tr>
<tr>
<td>Audio-only study room</td>
<td>10</td>
<td><strong>$0.60</strong></td>
<td>10 × 60 min × $0.001</td>
<td>$14.16/mo per host, no audio discount</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Comparison prices are Zoom list prices as of September 2026, billed annually. Month-to-month is higher: Pro $15.99, Business $21.99.</p><p>Read the table honestly. A single teacher running five seminars a week is cheaper on a $10 per month Zoom licence than on any API. The API wins when there are thousands of tutors with uneven usage, when idle seats would otherwise be paid for, or when your customers pay you and the video cost is a cost-of-goods line you pass through. Teams that migrate from per-seat classroom vendors to a usage-based API generally do it for product control first and cost second, and should model both before deciding.</p><h2 id="how-a-virtual-classroom-maps-onto-the-videosdk-api">How a Virtual Classroom Maps onto the VideoSDK API</h2><p>The eight classroom features from the checklist map onto specific VideoSDK building blocks, which is the clearest way to see what an API build actually involves.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Classroom feature</th>
<th>VideoSDK building block</th>
<th>Where it lives</th>
</tr>
</thead>
<tbody>
<tr>
<td>Live video and audio, adaptive bitrate</td>
<td>Rooms over WebRTC with network-adaptive streaming</td>
<td><code>useMeeting</code>, <code>useParticipant</code> hooks</td>
</tr>
<tr>
<td>Whiteboard</td>
<td>Shared whiteboard session per room</td>
<td><code>useWhiteboard</code>: <code>startWhiteboard</code>, <code>stopWhiteboard</code>, <code>whiteboardUrl</code></td>
</tr>
<tr>
<td>Breakout rooms</td>
<td>Multiple rooms created via REST; participants moved between them</td>
<td><code>POST /v2/rooms</code> plus SDK join and leave</td>
</tr>
<tr>
<td>Polls, Q&amp;A, chat</td>
<td>Pub/Sub messaging with topics</td>
<td><code>usePubSub</code> hook</td>
</tr>
<tr>
<td>Recording, individual or composite</td>
<td>Cloud recording with webhooks to your storage</td>
<td><code>startRecording</code>, <code>stopRecording</code></td>
</tr>
<tr>
<td>Live captions and post-session notes</td>
<td>Real-time and post-call transcription, prompt-based summary</td>
<td>Transcription API</td>
</tr>
<tr>
<td>Lecture-hall scale</td>
<td>Interactive live streaming, 100 hosts and 2,000 real-time viewers, viewer promoted with <code>changeMode</code></td>
<td><code>Constants.modes.SEND_AND_RECV</code> and <code>RECV_ONLY</code></td>
</tr>
<tr>
<td>Analytics and roster</td>
<td>Session and participant events</td>
<td>Webhooks, REST session endpoints</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Every building block in the table is documented in the <a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">VideoSDK REST API reference</a> and the per-platform SDK guides. The same mapping exercise against any other provider on the list tells you quickly where a second vendor will be needed.</p><h2 id="a-decision-framework-for-choosing-a-virtual-classroom-api">A Decision Framework for Choosing a Virtual Classroom API</h2><p>Answer five questions in order and the list of ten shrinks to one or two candidates.</p><ol><li><strong>Is the classroom your product or your utility?</strong> <br>If utility: rent Teams, Meet, Zoom for Education, or BigBlueButton and stop here. If product: continue.</br></li><li><strong>Do you need whiteboard and lecture-scale streaming from one SDK?</strong><br>Yes: VideoSDK or 100ms. <br>No, you will integrate a board yourself: Daily, Zoom Video SDK, LiveKit, or Chime remain in play.</br></br></li><li><strong>Which platforms are on your two-year roadmap?</strong> <br>Unity, IoT, or desktop C++: VideoSDK. Web plus iOS and Android only: any provider.</br></li><li><strong>Do you have a hard data-residency or self-hosting requirement?</strong> <br>Yes: LiveKit self-hosted, or a provider with region pinning (Vonage, Agora, VideoSDK enterprise). No: hosted cloud on any.</br></li><li><strong>Does procurement already have a preferred vendor?</strong> <br>Zoom approved: Zoom Video SDK. AWS committed spend: Chime SDK. Twilio or Vonage already contracted: stay, but budget for a whiteboard integration. Otherwise: pick on the classroom checklist, which favours VideoSDK for feature coverage and Agora for extreme scale.</br></li></ol><p>If you reached question 5 with two candidates left, run the same one-week spike on both: token server, room, whiteboard, recording to your bucket, and a 200-viewer stream. The provider that needs fewer external pieces to pass the spike is the one to sign.</p><h2 id="definitions-glossary">Definitions Glossary</h2><blockquote><strong>Virtual classroom:</strong> A live online session where an instructor and learners interact through video, audio, a whiteboard, and collaboration tools in real time. A VideoSDK room with the whiteboard started is a virtual classroom; a recorded lecture is not.</blockquote><blockquote><strong>Virtual classroom API:</strong> A programmable service that supplies the video, audio, whiteboard, recording, and streaming for a classroom you build and brand. VideoSDK exposes this through SDKs on 10+ platforms and a REST API for rooms and recordings.</blockquote><blockquote><strong>Interactive live streaming (ILS):</strong> A low-latency broadcast mode where viewers can be promoted to speakers. VideoSDK documents ILS at up to 100 hosts and 2,000 real-time viewers per session, switched with <code>changeMode</code>.</blockquote><blockquote><strong>Participant-minute:</strong> The unit most video APIs bill on: one participant connected for one minute. A 60-minute class with 25 people is 1,500 participant-minutes.</blockquote><blockquote><strong>Breakout room:</strong> A sub-session where a subset of learners work together, with the instructor able to move between rooms. On an API it is built from multiple rooms and a move-participant call.</blockquote><blockquote><strong>LTI 1.3:</strong> The Learning Tools Interoperability standard that lets a classroom launch from an LMS with single sign-on, roster access, and grade passback. Rented platforms ship it; on an API, you implement it in your application.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>Virtual classroom software is a live video session plus teaching tools, and on the API route those tools (whiteboard, breakouts, recording, lecture-scale streaming) are what separate providers, because the video itself is priced within 10 percent across most of them.</li><li>Six of the ten APIs cluster at about $0.004 per participant-minute; the real cost differences are the free tier, how many separate line items a full classroom needs, and whether large sessions require a second product.</li><li>VideoSDK covers the most classroom features from one SDK, with whiteboard, pub/sub, recording, transcription, and interactive live streaming to 2,000 real-time viewers across 10+ platforms and a $20 free credit; Agora wins at extreme scale, LiveKit for self-hosting, and Zoom Video SDK where procurement wants the Zoom name.</li><li>Build on an API when the classroom is your product; rent Teams, Meet, Zoom for Education, or BigBlueButton when it is a utility for your own staff and students.</li><li>Model the cost by session shape before deciding: a seat licence beats any API for one teacher, and a per-participant-minute API beats seat licences when usage is uneven and the video cost can be passed through to your customers.</li></ul><h2 id="conclusion">Conclusion</h2><p>The virtual classroom software decision splits cleanly once you ask whether the classroom is your product or your utility. Utilities are rented. Products are built, and the ten APIs above are the infrastructure they are built on. Choose on the classroom checklist rather than the per-minute rate, because the rate is nearly the same everywhere and the missing whiteboard or the second streaming vendor is where budgets actually go.</p><p>If you are on the build side, the fastest way to test the idea is a VideoSDK room with the whiteboard turned on: sign up at <a href="https://app.videosdk.live/login" rel="noreferrer">VideoSDK</a>, use the $20 credit, and follow the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a>. The <a href="https://github.com/videosdk-live">VideoSDK GitHub</a> has sample apps for React, Flutter, and Android, and the <a href="https://discord.gg/Gpmj6eCq5u">Discord community</a> is where classroom-specific questions get answered.</p><p>What are you building with VideoSDK?</p><p>Watch this video for better understanding!</p>
<!--kg-card-begin: html-->
<iframe width="560" height="315" src="https://www.youtube.com/embed/hVXLhWCC9oM?si=vPwZHCI1uQe_ZNkn" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-a-virtual-classroom">What is a virtual classroom?</h3><p>A virtual classroom is an online space where a teacher and students meet at the same time and interact through live video, audio, chat, a shared whiteboard, and tools such as polls and breakout rooms. It reproduces a physical classroom's real-time interaction over the internet. Virtual classrooms run either on rented platforms such as Zoom for Education or BigBlueButton, or inside custom applications built on a video API such as VideoSDK.</p><h3 id="what-is-virtual-classroom-software-1">What is virtual classroom software?</h3><p>Virtual classroom software is the application that provides a virtual classroom: real-time video and audio plus teaching features including whiteboard, screen sharing, breakout rooms, polls, attendance, and recording. It differs from video conferencing software by adding an instructor role model and learning tools, and from a learning management system by handling the live session rather than storing courses and grades. It can be a finished product you rent or an application you build on a virtual classroom API such as VideoSDK, Daily, or Agora.</p><h3 id="what-is-a-virtual-class">What is a virtual class?</h3><p>A virtual class is a single scheduled teaching session delivered live over the internet through virtual classroom software. It has a start time, an instructor, enrolled learners, and usually a recording afterwards. A virtual class is the event; the virtual classroom is the environment it runs in.</p><h3 id="what-is-virtual-training">What is virtual training?</h3><p>Virtual training is instructor-led training delivered remotely in real time, typically to employees or professional learners rather than school students. It uses the same virtual classroom software as education, with more emphasis on attendance tracking, assessments, and LMS reporting for compliance. Corporate academies that sell training often build their own rooms on APIs such as VideoSDK so that learners stay inside the branded product and completion data flows straight into the LMS.</p><h3 id="what-are-virtual-classes">What are virtual classes?</h3><p>Virtual classes are live online lessons where learners and an instructor participate simultaneously from different locations. They differ from self-paced online courses, which are pre-recorded, and from hybrid classes, where some learners are physically present. Virtual classes range from 1:1 tutoring to lectures of several hundred participants and, with interactive live streaming, masterclasses with thousands of real-time viewers.</p><h3 id="what-is-the-best-virtual-classroom-software-for-schools">What is the best virtual classroom software for schools?</h3><p>The best virtual classroom software for schools is usually the one bundled with the suite the school already licenses: Microsoft Teams for Education on Microsoft 365, Google Meet with Classroom on Google Workspace, or Zoom for Education where Zoom is standard. Schools with IT staff and data-residency requirements often choose BigBlueButton because it is open source. Schools rarely need a video API; that route is for companies building an education product.</p><h3 id="what-is-the-difference-between-a-virtual-classroom-and-a-digital-classroom">What is the difference between a virtual classroom and a digital classroom?</h3><p>The main difference is location. A virtual classroom is fully online, with teacher and students joining remotely through live video. A digital classroom is a physical room equipped with devices, interactive displays, and software such as an LMS. A school can have a digital classroom without any virtual classroom software, and a fully remote school has virtual classrooms without a digital classroom.</p><h3 id="how-much-does-it-cost-to-build-a-virtual-classroom-with-an-api">How much does it cost to build a virtual classroom with an API?</h3><p>Building a virtual classroom on an API costs engineering time plus usage. On VideoSDK, HD video is priced at $0.004 per participant-minute, so a one-hour 1:1 lesson costs about $0.48 and a 25-person seminar about $6.00, with recording, transcription, and live streaming billed separately per minute, and a $20 credit on a new account. Daily, 100ms, Twilio, and Agora publish rates within 10 percent of that figure. The engineering cost is the larger number: budget for token generation, room scheduling, breakout logic, LMS integration, and reconnection handling on top of the SDK.</p><h3 id="which-video-api-is-best-for-a-virtual-classroom">Which video API is best for a virtual classroom?</h3><p>The best video API for a virtual classroom depends on which classroom features you need built in. VideoSDK covers the widest set natively (whiteboard, pub/sub, recording, transcription, and interactive live streaming to 2,000 real-time viewers) across 10+ platforms. Agora is the better fit for extreme broadcast scale or China delivery, LiveKit for teams that want to self-host, and Zoom Video SDK where the buyer requires the Zoom name. Daily and Amazon Chime SDK are strong infrastructure choices if you are prepared to integrate a whiteboard yourself.</p><h2 id="further-reading">Further Reading</h2><ul><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React quickstart</a></li><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-react-ils">VideoSDK interactive live streaming quickstart for React</a></li><li><a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">VideoSDK Prebuilt UI Kit quickstart</a></li><li><a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">VideoSDK REST API reference</a></li><li><a href="https://www.videosdk.live/blog/virtual-classroom-api">What is a Virtual Classroom API?</a></li><li><a href="https://www.videosdk.live/blog/zoom-video-sdk-alternative">Top 10 Zoom Video SDK Alternatives</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Video Quality Explained: Bandwidth, Codecs and Containers]]></title><description><![CDATA[A user on a 500 Mbps connection reports a laggy call and support tells them to upgrade. It does not help, because bandwidth was never the problem. Video quality is decided at three independent layers: network, compression, and packaging. Here is what each controls, and how to tell them apart.]]></description><link>https://www.videosdk.live/blog/video-quality-bandwidth-codecs-containers</link><guid isPermaLink="false">6a902dccb3240feb748c9a22</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 31 Aug 2026 17:12:32 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/video-quality-thumb.png" medium="image"/><content:encoded><![CDATA[<blockquote>Fix the <strong>network layer</strong> when the call is delayed or the picture is blocky under load. Fix the <strong>codec layer</strong> when quality is fine but bitrate is too expensive to sustain. Fix the <strong>container layer</strong> only when a file will not play or will not start fast enough. VideoSDK exposes all three, through <code>getStats()</code> for the network, <code>createCameraVideoTrack()</code> for the codec, and MP4 recording output for the container.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/video-quality-thumb.png" alt="Video Quality Explained: Bandwidth, Codecs and Containers"/><p>A user on a 500 Mbps connection reports a laggy video call. Support tells them to upgrade their internet. It does not help, because bandwidth was never the problem.</p><p>That failure repeats across every layer of a video stack, and it happens because three separate technical decisions get discussed with the same vague word: quality. Bandwidth, throughput, and latency describe the network. H.264 and H.265 describe compression. MKV and MP4 describe packaging. They fail differently, and they respond to different fixes.</p><p>This guide separates the three layers, gives the numbers that matter at each one, and ends with a table that maps a symptom to the layer that actually causes it.</p><h2 id="the-three-layers-that-decide-video-quality">The three layers that decide video quality</h2><p>Video performance is defined as the combined result of three independent decisions: how much data the network can move and how fast, how efficiently the picture is compressed, and how the compressed result is packaged for delivery.</p><p>Those decisions are not substitutes for one another. Doubling your bandwidth cannot compensate for a codec your receiver cannot decode, and no container choice will recover detail that the encoder already discarded.</p>
<!--kg-card-begin: html-->
<table style="width:100% !important; display:table !important; border-collapse:collapse; table-layout:fixed; font-size:0.95em; min-width:600px;">
<colgroup><col style="width:13%"><col style="width:21%"><col style="width:13%"><col style="width:22%"><col style="width:31%"/></col></col></col></col></colgroup>
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);"><th style="padding:0.6em 0.8em; text-align:left;">Layer</th><th style="padding:0.6em 0.8em; text-align:left;">The decision</th><th style="padding:0.6em 0.8em; text-align:left;">Measured in</th><th style="padding:0.6em 0.8em; text-align:left;">Controls</th><th style="padding:0.6em 0.8em; text-align:left;">Fails as</th></tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Network</strong></td><td style="padding:0.6em 0.8em;">bandwidth, throughput, latency</td><td style="padding:0.6em 0.8em;">Mbps, ms</td><td style="padding:0.6em 0.8em;">Delay, sustainable bitrate</td><td style="padding:0.6em 0.8em;">Talking over each other, blocky picture</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Compression</strong></td><td style="padding:0.6em 0.8em;">H.264, H.265, VP9, AV1</td><td style="padding:0.6em 0.8em;">bits per pixel</td><td style="padding:0.6em 0.8em;">Picture at a given bitrate</td><td style="padding:0.6em 0.8em;">Excess bandwidth cost, or no playback at all</td></tr>
<tr><td style="padding:0.6em 0.8em;"><strong>Packaging</strong></td><td style="padding:0.6em 0.8em;">MP4, MKV, WebM, fMP4</td><td style="padding:0.6em 0.8em;">none</td><td style="padding:0.6em 0.8em;">Compatibility, startup, seeking</td><td style="padding:0.6em 0.8em;">File will not open or will not start</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>VideoSDK exposes a control point at each layer: round-trip time, jitter, and per-stream bitrate through the WebRTC <code>getStats()</code> API for the network layer; a <code>codec</code> parameter on <code>createCameraVideoTrack()</code> accepting VP8, H264, VP9, or AV1 for the compression layer; and MP4 output from the recording Composer for the packaging layer.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/video-performance.png" class="kg-image" alt="Video Quality Explained: Bandwidth, Codecs and Containers" loading="lazy" width="1672" height="941"/></figure><h2 id="layer-1-bandwidth-vs-latency-and-throughput">Layer 1: bandwidth vs latency (and throughput)</h2><p>Bandwidth, throughput, and latency are three different properties of the same connection, and only one of them is capacity. For the full treatment of this layer, see <a href="https://www.videosdk.live/blog/bandwidth-vs-latency" rel="noreferrer">Bandwidth vs Latency</a>.</p><h3 id="what-each-one-actually-measures">What each one actually measures</h3><p><strong>Bandwidth is defined as</strong> the maximum data rate a link is rated to carry, measured in bits per second. It is a ceiling, not an observation. Bandwidth works by setting the physical or provisioned limit on how fast bits can be pushed onto the medium.</p><p><strong>Throughput is defined as</strong> the data rate actually achieved over a link during a measurement window, also in bits per second. Throughput works by dividing bytes successfully delivered by elapsed time, so it is always at or below bandwidth.</p><p><strong>Latency is defined as</strong> the time between sending data and its arrival, measured in milliseconds. Latency works by accumulating four delays along the path: propagation (distance), transmission (pushing bits onto the wire), processing (per-hop handling), and queuing (waiting behind other traffic).</p><p>A fourth term is worth knowing because it is what your encoder actually competes for. <strong>Goodput</strong> is throughput minus protocol overhead and retransmissions, which is the payload that was genuinely useful.</p>
<!--kg-card-begin: html-->
<table style="width:100% !important; display:table !important; border-collapse:collapse; table-layout:fixed; font-size:0.95em; min-width:560px;">
<colgroup><col style="width:21%"><col style="width:20%"><col style="width:27%"><col style="width:32%"/></col></col></col></colgroup>
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);"><th style="padding:0.6em 0.8em; text-align:left;">Factor</th><th style="padding:0.6em 0.8em; text-align:left;">Bandwidth</th><th style="padding:0.6em 0.8em; text-align:left;">Throughput</th><th style="padding:0.6em 0.8em; text-align:left;">Latency</th></tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Measures</strong></td><td style="padding:0.6em 0.8em;">Rated capacity</td><td style="padding:0.6em 0.8em;">Delivered rate</td><td style="padding:0.6em 0.8em;">Delay</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Unit</strong></td><td style="padding:0.6em 0.8em;">bps, Mbps</td><td style="padding:0.6em 0.8em;">bps, Mbps</td><td style="padding:0.6em 0.8em;">ms</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Observed or rated</strong></td><td style="padding:0.6em 0.8em;">Rated</td><td style="padding:0.6em 0.8em;">Observed</td><td style="padding:0.6em 0.8em;">Observed</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Main limiter</strong></td><td style="padding:0.6em 0.8em;">Link and plan</td><td style="padding:0.6em 0.8em;">Congestion, loss</td><td style="padding:0.6em 0.8em;">Distance, queuing</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>More capacity helps?</strong></td><td style="padding:0.6em 0.8em;">n/a</td><td style="padding:0.6em 0.8em;">Yes</td><td style="padding:0.6em 0.8em;">Barely</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Closer server helps?</strong></td><td style="padding:0.6em 0.8em;">No</td><td style="padding:0.6em 0.8em;">Slightly</td><td style="padding:0.6em 0.8em;">Substantially</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>In video, controls</strong></td><td style="padding:0.6em 0.8em;">The ceiling</td><td style="padding:0.6em 0.8em;">Resolution and frame rate</td><td style="padding:0.6em 0.8em;">Conversational feel</td></tr>
<tr><td style="padding:0.6em 0.8em;"><strong>Symptom when bad</strong></td><td style="padding:0.6em 0.8em;">Hard cap on quality</td><td style="padding:0.6em 0.8em;">Blurry, blocky, frozen</td><td style="padding:0.6em 0.8em;">People interrupting each other</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h3 id="why-more-bandwidth-does-not-fix-a-laggy-call">Why more bandwidth does not fix a laggy call</h3><p>Because latency is dominated by distance and queuing, and neither responds to capacity.</p><p>Light in fibre travels at roughly 200,000 km per second, so a 5,000 km path costs about 25 ms one way regardless of what you pay your provider. A 1 Gbps link and a 100 Mbps link over the same route have nearly identical round-trip time.</p><p>There is exactly one place where capacity touches delay: transmission delay, which is packet size divided by link rate. On a 100 Mbps link a 1,500-byte packet takes 0.12 ms to serialise. Going to 1 Gbps saves you 0.108 ms. Against 25 ms of propagation, that is noise.</p><p>The number users actually experience is <strong>glass-to-glass latency</strong>, the delay from light hitting the sender's camera to that image appearing on the receiver's screen:</p><pre><code class="language-text">glass-to-glass = capture + encode + packetize + network transit
               + jitter buffer + decode + render
</code></pre><p>Network transit is frequently the smaller half. A jitter buffer alone can add 30 to 200 ms. This is why a 20 ms <code>ping</code> result does not mean a 20 ms video call.</p><h3 id="how-the-three-connect-the-bandwidth-delay-product">How the three connect: the bandwidth-delay product</h3><p>The <strong>bandwidth-delay product (BDP)</strong> is the amount of data in flight on a link at any instant, and it is the mechanism behind "high bandwidth, low throughput" on long routes:</p><pre><code class="language-text">BDP (bits) = bandwidth (bits/sec) x RTT (seconds)
</code></pre><p>A 100 Mbps link at 80 ms RTT holds 8,000,000 bits, about 1 MB, in flight. For a windowed protocol like TCP that sets a hard ceiling:</p><pre><code class="language-text">max throughput = window size / RTT
</code></pre><p>With a 64 KB window at 80 ms RTT, maximum throughput is about 6.5 Mbps no matter how fast the link is rated. Window scaling exists precisely to lift that ceiling.</p><p>The consequence for video delivery is direct. On high-latency paths, TCP-based protocols like HLS and DASH lose throughput to the round-trip ceiling, while UDP-based WebRTC does not, because it never waits for an acknowledgment. Protocol choice is a throughput decision as much as a latency one.</p><h3 id="latency-budgets-by-use-case">Latency budgets by use case</h3>
<!--kg-card-begin: html-->
<table style="width:100% !important; display:table !important; border-collapse:collapse; table-layout:fixed; font-size:0.95em; min-width:460px;">
<colgroup><col style="width:46%"><col style="width:27%"><col style="width:27%"/></col></col></colgroup>
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);"><th style="padding:0.6em 0.8em; text-align:left;">Use case</th><th style="padding:0.6em 0.8em; text-align:left;">Target glass-to-glass</th><th style="padding:0.6em 0.8em; text-align:left;">Typical transport</th></tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Video conferencing, interactive calls</td><td style="padding:0.6em 0.8em;">Under 300 ms</td><td style="padding:0.6em 0.8em;">WebRTC</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Live auctions, telehealth, betting</td><td style="padding:0.6em 0.8em;">Under 500 ms</td><td style="padding:0.6em 0.8em;">WebRTC</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Interactive live streaming with audience</td><td style="padding:0.6em 0.8em;">Under 1 s</td><td style="padding:0.6em 0.8em;">WebRTC</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">One-way broadcast, live sports</td><td style="padding:0.6em 0.8em;">2 to 6 s</td><td style="padding:0.6em 0.8em;">HLS, DASH</td></tr>
<tr><td style="padding:0.6em 0.8em;">VOD playback</td><td style="padding:0.6em 0.8em;">Not applicable</td><td style="padding:0.6em 0.8em;">HLS, DASH</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The 300 ms threshold is not arbitrary. Above roughly 300 ms round-trip, speakers begin colliding, because each waits for a response that has not arrived. Below about 150 ms, most people cannot detect the delay at all.</p><p>VideoSDK's HLS output runs at standard 5 to 6 second latency, which is the right tool for the bottom two rows and the wrong one for the top three.</p><h3 id="throughput-requirements-by-resolution">Throughput requirements by resolution</h3><p>Approximate H.264 encoder bitrates at 30 fps, with practical provisioning targets:</p>
<!--kg-card-begin: html-->
<table style="width:100% !important; display:table !important; border-collapse:collapse; table-layout:fixed; font-size:0.95em; min-width:420px;">
<colgroup><col style="width:23%"><col style="width:35%"><col style="width:42%"/></col></col></colgroup>
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);"><th style="padding:0.6em 0.8em; text-align:left;">Resolution</th><th style="padding:0.6em 0.8em; text-align:left;">Video bitrate</th><th style="padding:0.6em 0.8em; text-align:left;">Provision at least</th></tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">360p</td><td style="padding:0.6em 0.8em;">0.6 to 1.0 Mbps</td><td style="padding:0.6em 0.8em;">1.5 Mbps</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">720p</td><td style="padding:0.6em 0.8em;">1.5 to 2.5 Mbps</td><td style="padding:0.6em 0.8em;">3 Mbps</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">1080p</td><td style="padding:0.6em 0.8em;">3.0 to 4.5 Mbps</td><td style="padding:0.6em 0.8em;">6 Mbps</td></tr>
<tr><td style="padding:0.6em 0.8em;">4K</td><td style="padding:0.6em 0.8em;">15 to 25 Mbps</td><td style="padding:0.6em 0.8em;">30 Mbps</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Provision above the encoder bitrate, never at it. The headroom absorbs audio, retransmissions, protocol overhead, and burst variance. Provisioning exactly at the encoder target guarantees degradation the first time the network hiccups.</p><p>Multi-party calls multiply this on the receive side. An SFU forwards one stream per other participant, so an eight-person 720p call needs roughly 7 x 1.5 Mbps, about 10.5 Mbps downstream. Simulcast exists to keep that within reach, and it becomes important again in the codec section below.</p><h2 id="layer-2-h264-vs-h265-the-compression-decision">Layer 2: H.264 vs H.265, the compression decision</h2><p>The codec decides how many bits it takes to represent a given picture, which makes it the only layer that changes what a fixed amount of bandwidth can buy you. For the full treatment, see <a href="https://www.videosdk.live/blog/h264-vs-h265" rel="noreferrer">H.264 vs H.265</a>.</p><h3 id="what-each-codec-is">What each codec is</h3><p><strong>H.264 is defined as</strong> a block-oriented video compression standard published in 2003 as ITU-T H.264 and ISO/IEC 14496-10, also called AVC. H.264 works by dividing frames into 16x16 macroblocks, predicting each from neighbouring blocks or from a previous frame, and coding only the prediction error.</p><p><strong>H.265 is defined as</strong> its 2013 successor, published as ITU-T H.265 and ISO/IEC 23008-2, known as HEVC. H.265 works by replacing fixed macroblocks with a quadtree of Coding Tree Units spanning 64x64 down to 8x8, so flat regions cost far fewer blocks while detailed regions keep fine granularity.</p>
<!--kg-card-begin: html-->
<table style="width:100% !important; display:table !important; border-collapse:collapse; table-layout:fixed; font-size:0.95em; min-width:600px;">
<colgroup><col style="width:19%"><col style="width:26%"><col style="width:29%"><col style="width:26%"/></col></col></col></colgroup>
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);"><th style="padding:0.6em 0.8em; text-align:left;">Factor</th><th style="padding:0.6em 0.8em; text-align:left;">H.264</th><th style="padding:0.6em 0.8em; text-align:left;">H.265</th><th style="padding:0.6em 0.8em; text-align:left;">Better choice depends on</th></tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Bitrate at equal quality</td><td style="padding:0.6em 0.8em;">Baseline</td><td style="padding:0.6em 0.8em;">Roughly half (design target)</td><td style="padding:0.6em 0.8em;">Resolution and content</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Encode cost</td><td style="padding:0.6em 0.8em;">Lower</td><td style="padding:0.6em 0.8em;">Substantially higher</td><td style="padding:0.6em 0.8em;">Whether encoding is live or offline</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Hardware decode reach</td><td style="padding:0.6em 0.8em;">Effectively universal</td><td style="padding:0.6em 0.8em;">Newer devices only</td><td style="padding:0.6em 0.8em;">Which devices you must serve</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Browser playback</td><td style="padding:0.6em 0.8em;">All major browsers</td><td style="padding:0.6em 0.8em;">Safari 13+, Chrome 107+, Firefox 137+</td><td style="padding:0.6em 0.8em;">Whether the target is the open web</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">WebRTC</td><td style="padding:0.6em 0.8em;">Mandatory to implement (RFC 7742)</td><td style="padding:0.6em 0.8em;">Optional, Chrome and Safari</td><td style="padding:0.6em 0.8em;">Whether the path is real-time</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Licensing</td><td style="padding:0.6em 0.8em;">One main pool</td><td style="padding:0.6em 0.8em;">Multiple pools</td><td style="padding:0.6em 0.8em;">Distribution scale</td></tr>
<tr><td style="padding:0.6em 0.8em;"><strong>Best for</strong></td><td style="padding:0.6em 0.8em;">Real-time, reach, live encode</td><td style="padding:0.6em 0.8em;">4K VOD, storage, known endpoints</td><td style="padding:0.6em 0.8em;"/></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h3 id="why-the-50-figure-is-a-target-not-a-measurement">Why the 50% figure is a target, not a measurement</h3><p>HEVC's stated design goal was roughly 50% bitrate reduction at equivalent subjective quality against H.264. That is the standard's objective, published by the standards bodies. It is not a number you should plan capacity against without testing.</p><p>What you measure depends on four things:</p><ul><li><strong>Resolution.</strong> Gains are largest at 4K and above, where large uniform regions suit big CTUs.</li><li><strong>Content.</strong> High-motion footage compresses worse in both codecs, narrowing the gap.</li><li><strong>Preset.</strong> The tools that create HEVC's advantage are the expensive ones. Real-time presets skip them, so a live HEVC encode saves far less than an offline one.</li><li><strong>Profile.</strong> H.264 Constrained Baseline and H.264 High Profile are not the same baseline. Any comparison that does not name the profile is under-specified.</li></ul><p>This is also why H.265 is not automatically the right answer for live video. Encoder time lands directly in the glass-to-glass budget, so a codec that costs 40 ms more to encode has spent a meaningful fraction of a 300 ms conversational budget before a packet leaves the machine.</p><h3 id="codec-support-is-negotiated-not-assumed">Codec support is negotiated, not assumed</h3><p>For anything real-time, do not branch on a user-agent string. Ask the browser:</p><pre><code class="language-javascript">const caps = RTCRtpSender.getCapabilities("video");
const mimeTypes = caps.codecs.map((c) =&gt; c.mimeType);

console.log(mimeTypes);
// e.g. ["video/VP8", "video/H264", "video/VP9", "video/AV1"]
</code></pre><p>H.265 availability in WebRTC depends on OS version, GPU, and SoC, so it varies between two machines running the same browser build. </p><h2 id="layer-3-mkv-vs-mp4-the-packaging-decision">Layer 3: MKV vs MP4, the packaging decision</h2><p>A container never touches the picture, which is why the single most common statement about this comparison is also the wrong one. For the full treatment, see <a href="https://www.videosdk.live/blog/mkv-vs-mp4" rel="noreferrer">MKV vs MP4</a>.</p><h3 id="what-a-container-does-and-does-not-do">What a container does and does not do</h3><p><strong>A container is defined as</strong> a file format that packages already-compressed audio, video, subtitle, and metadata streams into one file with an index describing their timing. A container works by storing each stream as timestamped chunks plus a table telling the player where each chunk begins.</p><p>It does not compress. It does not decide quality. It decides what can travel together, what can read the result, and how quickly playback can start.</p>
<!--kg-card-begin: html-->
<table style="width:100% !important; display:table !important; border-collapse:collapse; table-layout:fixed; font-size:0.95em; min-width:600px;">
<colgroup><col style="width:19%"><col style="width:25%"><col style="width:28%"><col style="width:28%"/></col></col></col></colgroup>
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);"><th style="padding:0.6em 0.8em; text-align:left;">Factor</th><th style="padding:0.6em 0.8em; text-align:left;">MKV</th><th style="padding:0.6em 0.8em; text-align:left;">MP4</th><th style="padding:0.6em 0.8em; text-align:left;">Recommended for</th></tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Determines quality</td><td style="padding:0.6em 0.8em;">No</td><td style="padding:0.6em 0.8em;">No</td><td style="padding:0.6em 0.8em;">Neither. The codec does.</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Codec flexibility</td><td style="padding:0.6em 0.8em;">Effectively any</td><td style="padding:0.6em 0.8em;">H.264, H.265, AV1, VP9</td><td style="padding:0.6em 0.8em;">MKV for unusual combinations</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Subtitle formats</td><td style="padding:0.6em 0.8em;">SRT, ASS/SSA, PGS, VobSub</td><td style="padding:0.6em 0.8em;">Limited (TTML, tx3g)</td><td style="padding:0.6em 0.8em;">MKV for styled subtitles</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Browser playback</td><td style="padding:0.6em 0.8em;">None native</td><td style="padding:0.6em 0.8em;">Universal</td><td style="padding:0.6em 0.8em;">MP4 for anything on the web</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">HLS and DASH</td><td style="padding:0.6em 0.8em;">Not used</td><td style="padding:0.6em 0.8em;">fMP4 / CMAF standard</td><td style="padding:0.6em 0.8em;">MP4 for adaptive streaming</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Truncation recovery</td><td style="padding:0.6em 0.8em;">Good (EBML clusters)</td><td style="padding:0.6em 0.8em;">Poor unless fragmented</td><td style="padding:0.6em 0.8em;">MKV for long recordings</td></tr>
<tr><td style="padding:0.6em 0.8em;"><strong>Best for</strong></td><td style="padding:0.6em 0.8em;">Recording, archiving</td><td style="padding:0.6em 0.8em;">Delivery, streaming, editing</td><td style="padding:0.6em 0.8em;"/></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h3 id="why-mkv-is-higher-quality-than-mp4-is-wrong">Why "MKV is higher quality than MP4" is wrong</h3><p>Because containers do not compress, so a container cannot have a quality. When someone observes that an MKV looked better, one of three things is true:</p><ol><li><strong>The files hold different encodes.</strong> The MKV was made at a higher bitrate or from a better source. That is the encoder's work, not Matroska's.</li><li><strong>The audio differed.</strong> The MKV carried FLAC or PCM, the MP4 carried lossy AAC. That is an audio codec difference, and MP4 is not actually limited here: it carries ALAC, and FLAC-in-MP4 is a specified encapsulation shipped in Firefox 51+ and Chrome 62+.</li><li><strong>The conversion re-encoded.</strong> Transcoding loses quality. Remuxing with <code>ffmpeg -c copy</code> changes the wrapper and leaves the video bit-identical.</li></ol><p>The same reasoning kills the file-size claim. MKV files are usually larger because of what gets put in them (lossless audio, several languages, subtitle tracks), not because of the format.</p><h3 id="the-container-detail-that-does-affect-performance">The container detail that does affect performance</h3><p>Containers cannot change the picture, but one container decision changes <strong>startup time</strong>.</p><p>In a progressive MP4, the <code>moov</code> index is written after the media data, because its size is not known until encoding ends. A player streaming that file over HTTP cannot begin until it has fetched the end of the file. Moving the index to the front fixes it:</p><pre><code class="language-bash">ffmpeg -i input.mkv -c copy -movflags +faststart output.mp4
</code></pre><p><code>-c copy</code> stream-copies video and audio, so this is a repackage rather than a re-encode.</p><p>Adaptive streaming goes further and uses <strong>fragmented MP4</strong>, where media is split into self-contained fragments each carrying its own index. HLS and DASH converged on fMP4 through CMAF, which is why the same segments can serve both protocols.</p><h2 id="how-the-three-layers-interact">How the three layers interact</h2><p>Each layer constrains the others without being able to substitute for them.</p><h3 id="codec-choice-is-a-throughput-lever-never-a-latency-lever">Codec choice is a throughput lever, never a latency lever</h3><p>Switching from H.264 to H.265 lowers the bitrate needed for a given picture, which relaxes your <strong>throughput</strong> requirement. It does nothing to propagation delay, queuing delay, or jitter, and in a live encode it actively <strong>increases</strong> glass-to-glass latency by spending more time in the encoder.</p><p>So a more efficient codec helps the blocky-picture failure and hurts the delayed-conversation failure. Choosing one because you read that it is "better" without knowing which failure you have is how teams make a call worse while believing they upgraded it.</p><h3 id="the-tradeoff-no-competing-page-mentions-codec-choice-can-cost-you-simulcast">The tradeoff no competing page mentions: codec choice can cost you simulcast</h3><p>Here is where the layers collide in a way that shows up in production.</p><p>Multi-party calls rely on <strong>simulcast</strong>, where the sender publishes several resolution layers at once and the SFU forwards whichever layer each receiver can afford. It is the main defence against one participant on a weak connection dragging quality down for everyone.</p><p>In the VideoSDK JavaScript SDK, <code>createCameraVideoTrack()</code> accepts a <code>codec</code> parameter with VP8 (default), H264, VP9, and AV1, and a <code>multiStream</code> parameter that controls simulcast. <strong>VP9 and AV1 do not support <code>multiStream</code>.</strong> Pass one of them with simulcast enabled and the SDK falls back to VP8 and emits an error event.</p><p>That turns an apparently simple codec upgrade into a real tradeoff. Choosing the more efficient codec lowers the bitrate of a single stream and simultaneously removes per-receiver adaptability, which is a throughput regression at the SFU for every participant who needed a lower layer. </p><p>The decision rule that falls out of it:</p><ul><li><strong>Group calls with mixed network conditions:</strong> keep VP8 with <code>multiStream: true</code>. Adaptivity beats per-stream efficiency once receivers differ.</li><li><strong>One-to-one calls on known-good hardware:</strong> VP9 or H264 without simulcast is reasonable, because there is no fan-out to adapt for.</li><li><strong>Recording and VOD output:</strong> efficiency wins outright, because nothing is adapting in real time.</li></ul><h3 id="container-choice-never-changes-the-picture-but-it-does-gate-delivery">Container choice never changes the picture, but it does gate delivery</h3><p>The container cannot improve quality and cannot reduce latency across the network. It can prevent playback entirely (MKV in a browser), and it can delay the first frame (a progressive MP4 with a trailing index). Treat it as a compatibility and startup decision, never a quality one.</p><h2 id="what-matters-most-for-real-time-video-quality">What matters most for real-time video quality?</h2><p>For real-time video, latency matters most, then packet loss and jitter, then throughput, then codec efficiency, and the container barely matters at all.</p><p>That ordering comes from how users perceive failure. People tolerate a surprising amount of visual degradation and almost no conversational delay, which is why real-time systems sacrifice resolution to protect timing rather than the reverse.</p><p>Use this to map a symptom to the layer that causes it:</p>
<!--kg-card-begin: html-->
<table style="width:100% !important; display:table !important; border-collapse:collapse; table-layout:fixed; font-size:0.95em; min-width:640px;">
<colgroup><col style="width:27%"><col style="width:13%"><col style="width:31%"><col style="width:29%"/></col></col></col></colgroup>
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);"><th style="padding:0.6em 0.8em; text-align:left;">Symptom</th><th style="padding:0.6em 0.8em; text-align:left;">Layer</th><th style="padding:0.6em 0.8em; text-align:left;">Likely cause</th><th style="padding:0.6em 0.8em; text-align:left;">What actually fixes it</th></tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Speakers talking over each other</td><td style="padding:0.6em 0.8em;">Network</td><td style="padding:0.6em 0.8em;">Distance, queuing, oversized jitter buffer</td><td style="padding:0.6em 0.8em;">Closer media server, adaptive jitter buffer</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Picture soft or blocky under load</td><td style="padding:0.6em 0.8em;">Network</td><td style="padding:0.6em 0.8em;">Throughput below encoder target</td><td style="padding:0.6em 0.8em;">Lower bitrate, drop a simulcast layer</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Audio choppy, video fine</td><td style="padding:0.6em 0.8em;">Network</td><td style="padding:0.6em 0.8em;">Jitter and packet loss</td><td style="padding:0.6em 0.8em;">Reduce loss, tune buffer, check Wi-Fi</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Quality fine but bandwidth cost too high</td><td style="padding:0.6em 0.8em;">Compression</td><td style="padding:0.6em 0.8em;">Codec inefficiency</td><td style="padding:0.6em 0.8em;">More efficient codec, check simulcast impact</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Some participants see nothing</td><td style="padding:0.6em 0.8em;">Compression</td><td style="padding:0.6em 0.8em;">Receiver cannot decode the negotiated codec</td><td style="padding:0.6em 0.8em;">Fall back to H.264 or VP8</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Fast connection, still laggy</td><td style="padding:0.6em 0.8em;">Network</td><td style="padding:0.6em 0.8em;">Distance or bufferbloat, not capacity</td><td style="padding:0.6em 0.8em;">Move the server, not the plan</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Recording will not open</td><td style="padding:0.6em 0.8em;">Packaging</td><td style="padding:0.6em 0.8em;">Container or codec not supported by the player</td><td style="padding:0.6em 0.8em;">Remux with <code>-c copy</code></td></tr>
<tr><td style="padding:0.6em 0.8em;">Playback slow to start</td><td style="padding:0.6em 0.8em;">Packaging</td><td style="padding:0.6em 0.8em;"><code>moov</code> index at end of file</td><td style="padding:0.6em 0.8em;">Remux with <code>+faststart</code></td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h2 id="definitions-glossary">Definitions glossary</h2><blockquote><strong>Bandwidth:</strong> The maximum data rate a link is rated to carry, in bits per second. A ceiling, not a measurement.</blockquote><blockquote><strong>Throughput:</strong> The data rate actually delivered over a window, in bits per second. Always at or below bandwidth.</blockquote><blockquote><strong>Goodput:</strong> Throughput minus protocol overhead and retransmissions. The payload your encoder actually competes for.</blockquote><blockquote><strong>Latency:</strong> The delay between sending and receiving, in milliseconds. In video the number that matters is glass-to-glass, from camera sensor to remote screen.</blockquote><blockquote><strong>Codec:</strong> The compression algorithm (H.264, H.265, VP9, AV1) that decides how many bits a given picture costs. This is where quality is decided.</blockquote><blockquote><strong>Container:</strong> The file format (MP4, MKV, WebM) that packages compressed streams with an index. It never affects quality.</blockquote><blockquote><strong>Simulcast:</strong> Publishing several resolution layers of the same stream at once so a selective forwarding unit can send each receiver the layer it can afford. In VideoSDK this is the <code>multiStream</code> parameter on <code>createCameraVideoTrack()</code>.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>Diagnose the layer before applying a fix. Delay is a network problem, blockiness under load is a throughput problem, bandwidth cost is a codec problem, and a file that will not play is a container problem.</li><li>Bandwidth is a rated ceiling, throughput is what you actually get, and latency is unrelated to both. More capacity does not reduce delay, because propagation and queuing dominate it.</li><li>H.265 targets roughly half the bitrate of H.264 at equal perceptual quality, but that is a design objective, and live encoding gives back part of the saving as encoder latency.</li><li>Containers never determine quality. An MKV and an MP4 holding the same stream at the same bitrate are visually identical, and the only real performance effect is startup time.</li><li>In VideoSDK, codec choice and simulcast are coupled: <code>VP9</code> and <code>AV1</code> do not support <code>multiStream</code>, so the more efficient codec costs you per-receiver adaptation in group calls.</li></ul><h2 id="build-on-infrastructure-that-exposes-all-three-layers">Build on infrastructure that exposes all three layers</h2><p>The through-line of this guide is that video failures are layer-specific, and the fix only works if the diagnosis was right. That needs numbers from the live session, not a speed test and a guess.</p><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> gives you a control point at each layer: round-trip time, jitter, packet loss, and per-stream bitrate through the WebRTC <code>getStats()</code> API for the network; a <code>codec</code> parameter on <code>createCameraVideoTrack()</code> accepting VP8, H264, VP9, or AV1 for compression; and MP4 output from the recording Composer for packaging.</p><p>Those are the three dials. <code>createCameraVideoTrack()</code> carries the compression ones: <code>encoderConfig</code> for resolution, <code>bitrateMode</code> for the quality-versus-bandwidth trade, <code>optimizationMode</code> to tune for motion or detail, and <code>multiStream</code> with <code>maxLayer</code> for how many simulcast layers you publish. The measurement code earlier in this guide is the other half.</p><p>One coupling is worth knowing before you touch any of them: VP9 and AV1 do not support <code>multiStream</code> in the JavaScript SDK, so the more efficient codec costs you per-receiver bitrate adaptation. That is a compression-layer decision with a network-layer consequence, which is exactly the kind of interaction a single-topic comparison page will never surface.</p><h3 id="read-the-layer-you-care-about-in-depth">Read the layer you care about in depth</h3><ul><li><a href="https://www.videosdk.live/blog/bandwidth-vs-latency" rel="noreferrer"><strong>Bandwidth vs Latency</strong></a> covers the network layer: the four components of latency, the bandwidth-delay product, jitter, and why a speed test does not predict call quality.</li><li><a href="https://www.videosdk.live/blog/h264-vs-h265" rel="noreferrer"><strong>H.264 vs H.265</strong></a> covers compression: what the 50% figure really means, browser and WebRTC support, licensing, and encode cost.</li><li><a href="https://www.videosdk.live/blog/mkv-vs-mp4" rel="noreferrer"><strong>MKV vs MP4</strong></a> covers packaging: why containers never affect quality, what the <code>moov</code> atom does to startup time, and when each one wins.</li></ul><p><a href="https://app.videosdk.live/login" rel="noreferrer">Start building free with $20 in credit!</a></p><p>Which layer has cost you the most debugging time? Drop a comment with the symptom and what actually fixed it.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="is-bandwidth-the-same-as-throughput">Is bandwidth the same as throughput?</h3><p>No. Bandwidth is the maximum rate a link is rated to carry; throughput is the rate actually achieved during a measurement window. Throughput is always at or below bandwidth, and the gap widens under congestion, packet loss, and protocol overhead. Encoders should be configured against measured throughput, never against the number on the internet plan.</p><h3 id="does-higher-bandwidth-reduce-latency">Does higher bandwidth reduce latency?</h3><p>Barely. Extra capacity reduces transmission delay, the time to push bits onto the wire, but not propagation, processing, or queuing delay. On a 5,000 km route, propagation alone costs about 25 ms each way regardless of capacity, so a tenfold bandwidth increase can change latency by a fraction of a millisecond.</p><h3 id="is-h265-better-than-h264">Is H.265 better than H.264?</h3><p>H.265 is more efficient, not universally better. It targets equivalent perceptual quality at roughly half the bitrate, which wins for 4K storage and bandwidth-constrained delivery. H.264 wins for real-time video, because it is mandatory to implement in WebRTC under RFC 7742 and its faster encoder consumes less of the latency budget.</p><h3 id="is-mkv-better-quality-than-mp4">Is MKV better quality than MP4?</h3><p>No. Both are containers and neither compresses video, so neither can affect the picture. Quality is set by the codec and bitrate inside the file. An MKV and an MP4 holding the same H.264 stream at the same bitrate are visually identical, and converting between them with <code>ffmpeg -c copy</code> changes nothing about the video.</p><h3 id="how-do-codec-choice-and-network-latency-interact">How do codec choice and network latency interact?</h3><p>Codec choice affects throughput, not network latency, but it does affect end-to-end latency through encoder time. A more efficient codec lowers the bitrate needed for a given picture, which helps when throughput is the constraint. In live encoding it also spends longer in the encoder, which adds directly to glass-to-glass delay.</p><h3 id="what-matters-most-for-real-time-video-quality-1">What matters most for real-time video quality?</h3><p>Latency first, then packet loss and jitter, then throughput, then codec efficiency, and the container last. Users tolerate significant visual degradation and almost no conversational delay, so real-time systems are built to sacrifice resolution in order to protect timing.</p><h3 id="can-i-change-the-video-codec-in-videosdk">Can I change the video codec in VideoSDK?</h3><p>Yes. VideoSDK's <code>createCameraVideoTrack()</code> accepts a <code>codec</code> parameter supporting VP8 (the default), H264, VP9, and AV1 in the JavaScript SDK, alongside <code>encoderConfig</code>, <code>bitrateMode</code>, and <code>multiStream</code>. One constraint matters in group calls: VP9 and AV1 do not support <code>multiStream</code>, so selecting them disables simulcast and removes per-receiver bitrate adaptation.</p>]]></content:encoded></item><item><title><![CDATA[Build an Online Classroom App with React]]></title><description><![CDATA[A step-by-step guide to building a real online classroom in React, with a shared whiteboard, live video, and role-based permissions, powered by VideoSDK.]]></description><link>https://www.videosdk.live/blog/react-whiteboard-online-classroom</link><guid isPermaLink="false">6a8c16f3b3240feb748c9856</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 31 Aug 2026 10:47:36 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/Online-Classroom-in-React.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Online-Classroom-in-React.png" alt="Build an Online Classroom App with React"/><p>Most video call tutorials end with a grid of faces and a mute button. A classroom needs more than that. It needs a surface everyone looks at together - a whiteboard the teacher draws on, that every student sees update in real time, sitting at the center of the screen instead of a side panel.</p><p>This guide builds that:&nbsp;<strong>Classroom</strong>, an online classroom app in React with a shared whiteboard, role-based permissions, and cloud recording. It's built on&nbsp;<a href="https://dub.sh/X5Fn46e?utm_source=classroom-blog">VideoSDK</a>&nbsp;for the video, audio, whiteboard sync, and pub/sub messaging.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/classroom-desktop.png" class="kg-image" alt="Build an Online Classroom App with React" loading="lazy" width="3024" height="1964"><figcaption><span style="white-space: pre-wrap;">classroom in session, whiteboard centre stage with teacher and student video tiles above it</span></figcaption></img></figure><p>Prefer watching the build instead? The full video walkthrough is on YouTube:</p><p><a href="https://youtu.be/hVXLhWCC9oM"/></p><p/><h2 id="what-youll-build">What you'll build</h2><p>By the end, you'll have a room where:</p><ul><li>A teacher and a student get different permissions. The server decides, not the client.</li><li>The teacher draws on a shared whiteboard. Every participant sees it update live.</li><li>The room runs in one of two layouts, Class or Lecture, chosen when it's created.</li><li>Chat, hand-raising, and moderation follow a clear rule: some things the client just honors, one thing the server actually enforces.</li><li>A class recording captures the board, not just the video tiles.</li></ul><h2 id="prerequisites">Prerequisites</h2>
<!--kg-card-begin: html-->
<table style="margin: 10px 0px 15px; border-collapse: collapse; border-spacing: 0px; display: block; width: 850px; overflow: auto; word-break: keep-all; color: rgb(51, 51, 51); font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Segoe UI&quot;, Arial, freesans, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><thead><tr><th style="font-weight: 700; color: rgb(0, 0, 0); border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">Requirement</th><th style="font-weight: 700; color: rgb(0, 0, 0); border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">Version</th><th style="font-weight: 700; color: rgb(0, 0, 0); border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">Check command</th></tr></thead><tbody><tr><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">Node.js</td><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">18+</td><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;"><code style="font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 0.85em; color: rgb(0, 0, 0); background-color: rgb(240, 240, 240); border-radius: 3px; padding: 0.2em 0px;">node --version</code></td></tr><tr><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">pnpm</td><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">8+</td><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;"><code style="font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 0.85em; color: rgb(0, 0, 0); background-color: rgb(240, 240, 240); border-radius: 3px; padding: 0.2em 0px;">pnpm --version</code></td></tr><tr><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">A VideoSDK account</td><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">-</td><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">Sign up on the<span>&nbsp;</span><a href="https://dub.sh/X5Fn46e?utm_source=classroom-blog" style="color: rgb(0, 136, 204); text-decoration: none;">VideoSDK dashboard</a><span>&nbsp;</span>and grab an API key and secret</td></tr><tr><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">A Supabase project</td><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">-</td><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">Used here for auth and room ownership</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>You should be comfortable with React hooks,&nbsp;<code>useEffect</code>, and calling a JSON API from a serverless function. No prior VideoSDK experience needed. The Supabase side is small - one table plus auth - and the repo's README walks through setting it up.</p><p>Clone the repo to follow along with a working copy:</p><pre><code class="language-bash">git clone https://github.com/videosdk-live/classroom
cd classroom
pnpm install
</code></pre><p>Add your <a href="https://dub.sh/X5Fn46e?utm_source=classroom-blog" rel="noreferrer">VideoSDK</a> and Supabase credentials to a&nbsp;<code>.env</code>&nbsp;file (see&nbsp;<code>.env.example</code>&nbsp;in the repo for the exact names). Then run the frontend and the API routes together. Token minting lives in a serverless function, so you need both:</p><pre><code class="language-bash">pnpm dev:api
</code></pre><p><strong>Checkpoint:</strong>&nbsp;open&nbsp;<code>http://localhost:3000</code>. You should see the app's home screen.&nbsp;<code>pnpm dev</code>&nbsp;alone also starts the app, but without&nbsp;<code>/api</code>&nbsp;routes. Fine for UI work, but you won't be able to join a room.</p><h2 id="step-1-how-the-token-decides-whos-the-teacher">Step 1: How the token decides who's the teacher</h2><p>Before any video renders, the app has to answer one question: is this person the teacher, or a student? Get this wrong on the client, and any student can mute the teacher.</p><p>Classroom answers it on the server. When a browser asks to join a room, a Vercel serverless function checks who owns that room in the database. It mints a VideoSDK token with permissions that match:</p><pre><code class="language-ts">const TEACHER: readonly Permission[] = ['allow_join', 'allow_mod']
const STUDENT: readonly Permission[] = ['ask_join']

const { data: room } = await db
  .from('rooms')
  .select('room_id, owner_id, title, mode, ended_at')
  .eq('room_id', roomId)
  .maybeSingle()

const isOwner = room.owner_id === user.id

const token = signMeetingToken({
  apiKey: env.videosdkApiKey,
  secret: env.videosdkSecret,
  permissions: isOwner ? TEACHER : STUDENT,
  roomId: room.room_id,
  participantId: user.id,
  ttlSeconds: TTL_SECONDS,
})
</code></pre><p>Look at what's never read here. No role field. No query string. Nothing from the request body except the room id. The room's owner in the database decides who becomes the teacher. Everything else, like which buttons render or what the UI calls the person, is just decoration on top of that. The real enforcement lives in the&nbsp;<code>permissions</code>&nbsp;array baked into the signed token.</p><p>That split matters for the "ask to join" flow too. A student's token only carries&nbsp;<code>ask_join</code>. The SDK holds them at a connecting state and fires an entry-request event to whoever holds&nbsp;<code>allow_mod</code>&nbsp;- the teacher. A student can't get into a class that isn't running. And a student can't get in without the teacher's client approving them.</p><p><strong>Checkpoint:</strong>&nbsp;create a room as the teacher, then open the same room link in a second browser signed in as a different account. The second browser should land in a waiting state instead of joining directly, and the teacher's window should show an entry request. If it joins straight through, the second browser is probably still signed in as the room's owner -&nbsp;<code>isOwner</code>&nbsp;only comes out&nbsp;<code>false</code>&nbsp;when&nbsp;<code>owner_id</code>&nbsp;doesn't match the caller.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/lobby-knock.png" class="kg-image" alt="Build an Online Classroom App with React" loading="lazy" width="3024" height="1964"><figcaption><span style="white-space: pre-wrap;">student lobby screen, waiting to be admitted</span></figcaption></img></figure><h2 id="step-2-how-the-whiteboard-works">Step 2: How the whiteboard works</h2><p>This is the part that makes the app a classroom instead of a call. VideoSDK ships a collaborative whiteboard as a React hook, and the entire surface area is three members:</p><pre><code class="language-jsx">import { useWhiteboard } from "@videosdk.live/react-sdk";

const { startWhiteboard, stopWhiteboard, whiteboardUrl } = useWhiteboard();

{whiteboardUrl &amp;&amp; &lt;iframe src={whiteboardUrl} title="Whiteboard" /&gt;}
</code></pre><p>No config object. No canvas library to wire up. No separate socket connection to manage. Call&nbsp;<code>startWhiteboard()</code>, get a URL back, drop it in an iframe. Everyone in the room who renders that iframe sees the same board update live. The sync happens on VideoSDK's side, not yours.</p><p>In Classroom, that hook lives behind a small bridge component. The rest of the app never touches the SDK directly:</p><pre><code class="language-ts">export function WhiteboardBridge({ store }: { store: RoomStore }) {
  const { startWhiteboard, stopWhiteboard, whiteboardUrl } = useWhiteboard()

  useEffect(() =&gt; {
    store.setWhiteboard({ url: whiteboardUrl ?? null })
  }, [store, whiteboardUrl])

  useEffect(() =&gt; {
    const existing = store.getActions()
    if (!existing) return

    store.setActions({
      ...existing,
      startWhiteboard: async () =&gt; {
        store.setWhiteboard({ inFlight: true, error: null })
        try {
          await startWhiteboard()
        } finally {
          store.setWhiteboard({ inFlight: false })
        }
      },
      stopWhiteboard: async () =&gt; {
        store.setWhiteboard({ inFlight: true, error: null })
        try {
          await stopWhiteboard()
        } finally {
          store.setWhiteboard({ inFlight: false })
        }
      },
    })
  }, [store, startWhiteboard, stopWhiteboard])

  return null
}
</code></pre><p>That's it for wiring. Rendering the board is just an iframe pointed at&nbsp;<code>whiteboardUrl</code>. It sits inside the app's own layout so it reads as part of the classroom, not an embedded widget:</p><pre><code class="language-tsx">{boardOn ? (
  &lt;iframe
    src={boardSrc(url, canDraw)}
    title="Whiteboard"
    className="h-full w-full border-0"
    allow="clipboard-write"
  /&gt;
) : (
  &lt;div className="flex h-full w-full flex-col items-center justify-center gap-2 text-center"&gt;
    &lt;span&gt;The board is not open yet&lt;/span&gt;
    &lt;span&gt;{canDraw ? 'Opening it for the class.' : 'Your teacher starts it for the class.'}&lt;/span&gt;
  &lt;/div&gt;
)}
</code></pre><p>One detail worth knowing before you check the&nbsp;<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/whiteboard">whiteboard docs</a>:&nbsp;<code>useWhiteboard</code>&nbsp;itself carries no permission concept. No role, no read-only flag. If you want students to watch without drawing, append&nbsp;<code>drawOnWhiteboard=false</code>&nbsp;to the board's own URL:</p><pre><code class="language-ts">export function boardSrc(url: string, canDraw: boolean): string {
  if (canDraw) return url
  const next = new URL(url)
  next.searchParams.set('drawOnWhiteboard', 'false')
  return next.toString()
}
</code></pre><p>Read-only mode refuses every stroke and hides the toolbar. It keeps the zoom controls working, though, so a student who fell behind can still zoom out and find where the teacher scrolled to.</p><p><strong>Checkpoint:</strong>&nbsp;as the teacher, click "Start whiteboard." The iframe should load a blank board within a couple of seconds. Draw a line, then check the student's browser. The same line should appear there within a second, and the student shouldn't be able to draw on it.</p><h2 id="step-3-one-room-two-shapes">Step 3: One room, two shapes</h2><p>Not every class looks the same. A small seminar wants everyone visible and equal. A lecture wants the teacher up front with students listed below, promotable onstage when they have a question. Classroom supports both as a single choice made when the room is created. It's stored alongside the room and returned by the same session endpoint that mints the token. There's no mid-class switch - changing the room's shape mid-session means announcing new rules to everyone at once, and that's a bigger UX problem than the toggle itself.</p><p>In both modes, the pen stays with the teacher. Promoting a student in Lecture mode changes their layout position and requests their microphone. It doesn't hand them drawing rights. The request goes through the SDK's own consent flow, not a forced action:</p><pre><code class="language-ts">// Muting takes effect immediately.
disableMic()

// Unmuting only ever requests - the student must accept it.
enableMic() // fires onMicRequested on the student's client
</code></pre><p>A teacher can silence a mic instantly but can't force one open. That's why the control in the UI says "Ask to unmute" instead of "Unmute."</p><p><strong>Checkpoint:</strong>&nbsp;create one room in each mode and join both as a student. In Class mode the student's video tile sits in the rail above the board with everyone else's. In Lecture mode the student appears in the list below the stage, and moves onstage only after the teacher promotes them.</p><p>Class Mode:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/class-mode.png" class="kg-image" alt="Build an Online Classroom App with React" loading="lazy" width="3024" height="1964"><figcaption><span style="white-space: pre-wrap;">Class Mode Layout</span></figcaption></img></figure><p>Lecture Mode:</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/lecture-mode.png" class="kg-image" alt="Build an Online Classroom App with React" loading="lazy" width="3024" height="1964"><figcaption><span style="white-space: pre-wrap;">Lecture Mode Layout</span></figcaption></img></figure><h2 id="step-4-how-classroom-controls-work">Step 4: How classroom controls work</h2><p>Read this step closely if you're building anything with room-wide toggles. It's easy to assume more security than actually exists.</p><p>Chat-disabled, hand-raise-disabled, and the list of promoted students aren't stored on a server that gatekeeps them. They ride a persisted pub/sub message. Every client in the room receives it and honors it on its own:</p><pre><code class="language-ts">export function encodeControls(next: ClassControls): string {
  return JSON.stringify({
    v: 1,
    chat: next.chatEnabled,
    hands: next.handsEnabled,
    promoted: next.promoted,
  })
}

export function foldControls(
  messages: readonly RoomMessage[],
  teacherId: string | null,
): ClassControls {
  if (!teacherId) return DEFAULT_CONTROLS
  for (let i = messages.length - 1; i &gt;= 0; i--) {
    const m = messages[i]
    if (m.senderId !== teacherId) continue
    const parsed = parseControls(m.text)
    if (parsed) return parsed
  }
  return DEFAULT_CONTROLS
}
</code></pre><p><code>foldControls</code>&nbsp;walks the message history backward and takes the latest full snapshot published by the teacher's participant id. Every client does that fold locally. Two things follow from that. A forged control message from a student changes nothing, because every client's fold ignores messages that don't come from the teacher's id. But the fold itself is client code - nothing on the server rejects a chat message just because the topic says chat is off, so a modified client could skip the check entirely. The publish goes through a small bridge around VideoSDK's&nbsp;<code>usePubSub</code>:</p><pre><code class="language-tsx">export function PubSubBridge({ topic, store, persist }) {
  const { publish } = usePubSub(topic, {
    onMessageReceived(message) {
      store.appendMessages(topic, [normalisePubSubMessage(message, topic)])
    },
    onOldMessagesReceived(messages) {
      store.appendMessages(topic, (messages ?? []).map((m) =&gt; normalisePubSubMessage(m, topic)))
    },
  })

  useEffect(
    () =&gt; store.registerPublisher(topic, async (text, payload) =&gt; {
      await publish(text, { persist }, payload)
    }),
    [store, topic, persist],
  )

  return null
}
</code></pre><p><code>persist: true</code>&nbsp;is what lets a student who joins mid-class see the current chat/hands state right away, instead of a blank slate. VideoSDK replays persisted pub/sub history to new joiners automatically.</p><p>So what actually stops a student from muting the teacher or removing another student? Nothing about pub/sub. The one real permission boundary in the whole app is&nbsp;<code>allow_mod</code>&nbsp;versus&nbsp;<code>ask_join</code>, inside the signed token from Step 1. Moderation actions like removing a participant go through the SDK's own participant methods, and those check that permission on the server before they take effect.</p><p>The screen-share control follows the same pattern. Any token holder can technically call&nbsp;<code>enableScreenShare</code>, but only the teacher's UI exposes the button. When it runs, the screen share covers the whiteboard stage instead of replacing it in the DOM. Unmounting the board's iframe would reload it, and reloading a live-synced board mid-class is a worse experience than a temporary overlay.</p><p>None of this is a workaround. It's a pattern most real-time apps land on: cheap, low-latency broadcast state for anything cosmetic, and a small number of server-verified checks for anything that actually needs to hold.</p><p><strong>Checkpoint:</strong>&nbsp;as the teacher, turn chat off. The student's chat input should disable within a second. Then reload the student's browser and rejoin. The chat input should come back still disabled - that's&nbsp;<code>persist: true</code>&nbsp;doing its job, replaying the teacher's last control message to the fresh session.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/chat-hands.png" class="kg-image" alt="Build an Online Classroom App with React" loading="lazy" width="3024" height="1964"><figcaption><span style="white-space: pre-wrap;">hand raised notification and chat enabled toggle in the teacher control bar</span></figcaption></img></figure><h2 id="step-5-recording-the-class-board-included">Step 5: Recording the class, board included</h2><p>A video-only recording misses the point. The whiteboard is where the actual teaching happened. VideoSDK's cloud recording composites everything in the room, board included, so a recorded class plays back with the same ink and the same live cursors students watched during the session.</p><p>Starting one is a single call, but read the signature carefully before you copy it:</p><pre><code class="language-ts">const RECORDING_CONFIG = {
  layout: { type: 'SPOTLIGHT', priority: 'PIN' },
  theme: 'DARK',
  mode: 'video-and-audio',
  quality: 'high',
  orientation: 'landscape',
} as const

// startRecording(webhookUrl, awsDirPath, config, transcription) - all four
// arguments are positional. Skipping the two leading nulls and passing the
// config first silently sends it as the webhook URL instead.
startRecording(null, null, RECORDING_CONFIG)
</code></pre><p>That's an easy trap.&nbsp;<code>startRecording(RECORDING_CONFIG)</code>&nbsp;compiles, runs, and produces a recording. But your config object gets read as a URL string, and every layout setting silently falls back to default. The two&nbsp;<code>null</code>&nbsp;arguments ahead of the config aren't filler. They're what makes the third argument land where you meant it to.</p><p>The&nbsp;<code>SPOTLIGHT</code>&nbsp;layout keeps the composite focused on the board and the active speaker, instead of tiling every participant into a grid. That's what you want when the board is the reason anyone's watching the recording back.</p><p><strong>Checkpoint:</strong>&nbsp;start a recording, draw on the board for a few seconds, then stop it and end the class. Once VideoSDK finishes processing, the recording shows up in the recordings list on the home screen. Play it back - you should see the board with your strokes, not just a grid of video tiles.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/recordings.png" class="kg-image" alt="Build an Online Classroom App with React" loading="lazy" width="3024" height="1964"><figcaption><span style="white-space: pre-wrap;">recording playback showing the whiteboard with live cursor name tags</span></figcaption></img></figure><h2 id="step-6-building-and-deploying">Step 6: Building and deploying</h2><p>Locally, the app runs as a Vite frontend with Vercel serverless functions on one origin. That's why&nbsp;<code>pnpm dev:api</code>&nbsp;is the command to reach for, not&nbsp;<code>pnpm dev</code>&nbsp;alone - the API key handling for token minting and room creation only works through those functions.</p><p>The build step runs a bundle check that fails if a server-only secret ends up inlined into the shipped JavaScript. That covers the VideoSDK API key, the VideoSDK secret, and the Supabase service role key:</p><pre><code class="language-bash">pnpm build
</code></pre><p>Any environment variable without a&nbsp;<code>VITE_</code>&nbsp;prefix stays server-side. The check exists so that boundary can't quietly slip. Ship it on Vercel and it deploys the same way any Vite app does - the functions in&nbsp;<code>api/</code>&nbsp;become serverless routes automatically.</p><p><strong>Checkpoint:</strong>&nbsp;after&nbsp;<code>pnpm build</code>, the command should exit cleanly. If it fails on the bundle-secrets check, search&nbsp;<code>dist/</code>&nbsp;for the flagged variable name. That means a secret got read somewhere in client code instead of an&nbsp;<code>api/</code>&nbsp;function.</p><h2 id="what-you-built">What you built</h2><ul><li>A token-minting endpoint that decides teacher versus student from room ownership in the database, never from the client</li><li>A shared whiteboard wired through&nbsp;<code>useWhiteboard</code>, with a read-only mode for students via a URL parameter</li><li>Two room layouts chosen at creation time, with a promote flow that requests rather than forces a student's microphone</li><li>Classroom controls split cleanly between client-honored broadcast state and one real server-enforced permission</li><li>Cloud recording that composites the whiteboard into the output, not just the video tiles</li></ul><h2 id="next-steps">Next steps</h2><p>The full source is on&nbsp;<a href="https://github.com/videosdk-live/classroom">GitHub</a>, including pieces this guide skipped over, like the entry-request lobby UI and the Supabase schema. If you want to go deeper on the whiteboard hook itself, the&nbsp;<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/whiteboard">whiteboard documentation</a>&nbsp;covers the API this guide only used a slice of. And the&nbsp;<a href="https://dub.sh/X5Fn46e?utm_source=classroom-blog">VideoSDK dashboard</a>&nbsp;is where you generate the API key and secret this guide's token-minting step depends on.</p><h2 id="troubleshooting">Troubleshooting</h2><h3 id="the-teachers-board-never-opens">The teacher's board never opens</h3><p><code>startWhiteboard()</code>&nbsp;called in the same render as the meeting-joined event is sometimes accepted and silently dropped by the SDK. No error, no&nbsp;<code>onError</code>&nbsp;- the board just never appears. Classroom works around this by retrying up to five times, waiting for each attempt to resolve before trying the next, and stopping the moment the board opens or the teacher closes it deliberately. If you're seeing this in your own code, an auto-start on join needs the same retry, not a single call.</p><h3 id="startrecording-runs-but-the-layout-is-wrong"><code>startRecording</code>&nbsp;runs but the layout is wrong</h3><p>Check argument order.&nbsp;<code>startRecording(webhookUrl, awsDirPath, config, transcription)</code>&nbsp;is positional, and all four arguments are optional. Passing your config object as the first argument sends it as the webhook URL string, and the recording falls back to a default grid layout with no error.</p><h3 id="a-student-can-still-see-a-disabled-control-working-for-them">A student can still see a "disabled" control working for them</h3><p>That's expected, not a bug - see Step 4. Chat and hand-raise toggles are broadcast state the client honors, not a server-side permission. If you need real enforcement, gate the action itself behind&nbsp;<code>allow_mod</code>&nbsp;in the token, the way Classroom does for removing a participant.</p><h3 id="build-fails-on-the-bundle-secrets-check">Build fails on the bundle-secrets check</h3><p>A value without a&nbsp;<code>VITE_</code>&nbsp;prefix got referenced from client-side code. Move that read into an&nbsp;<code>api/</code>&nbsp;function. Anything without the&nbsp;<code>VITE_</code>&nbsp;prefix is meant to stay server-only, and Vite won't stop you from importing it into the bundle by accident.</p>]]></content:encoded></item><item><title><![CDATA[Bandwidth vs Latency: What's the Difference?]]></title><description><![CDATA[A user on a 500 Mbps connection reports an unusable video call. Support tells them to upgrade. It does not help, because bandwidth was never the problem. Bandwidth vs latency explained properly: what each controls, why they respond to different fixes, and how to measure both in production.]]></description><link>https://www.videosdk.live/blog/bandwidth-vs-latency</link><guid isPermaLink="false">6a9026a1b3240feb748c9a09</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 31 Aug 2026 05:46:16 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-27--2026--05_39_30-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>Bandwidth is how much data a connection can carry. Latency is how long each piece takes to arrive.</strong> Bandwidth is measured in bits per second, latency in milliseconds, and they are independent: a link can carry 1 Gbps with terrible delay, or respond in 5 ms while moving almost nothing. </blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-27--2026--05_39_30-PM.png" alt="Bandwidth vs Latency: What's the Difference?"/><p>The distinction decides which fix will work. Buying more capacity raises bandwidth and leaves latency essentially untouched, which is why the most common support outcome in video is a user on a faster plan with exactly the same laggy call.</p><p>In video specifically, the two control different things. Latency decides whether a conversation feels natural. Bandwidth decides whether the picture holds its resolution. Most degraded calls get misdiagnosed because both are described with the same word: slow.</p><h2 id="bandwidth-vs-latency-at-a-glance">Bandwidth vs latency at a glance</h2>
<!--kg-card-begin: html-->
<table style="width:100%; border-collapse:collapse; font-size:0.95em; min-width:560px;">
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);"><th style="padding:0.6em 0.8em; text-align:left;"/><th style="padding:0.6em 0.8em; text-align:left;">Bandwidth</th><th style="padding:0.6em 0.8em; text-align:left;">Latency</th></tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>What it measures</strong></td><td style="padding:0.6em 0.8em;">Maximum data rate a link can carry</td><td style="padding:0.6em 0.8em;">Delay before data arrives</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Unit</strong></td><td style="padding:0.6em 0.8em;">Bits per second (Mbps, Gbps)</td><td style="padding:0.6em 0.8em;">Milliseconds (ms)</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Rated or observed</strong></td><td style="padding:0.6em 0.8em;">Rated ceiling</td><td style="padding:0.6em 0.8em;">Observed each way or round-trip</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Measured with</strong></td><td style="padding:0.6em 0.8em;">Sustained transfer test</td><td style="padding:0.6em 0.8em;"><code>ping</code>, RTT from <code>getStats()</code></td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Main limiter</strong></td><td style="padding:0.6em 0.8em;">Link capacity, plan, congestion</td><td style="padding:0.6em 0.8em;">Distance, routing hops, queuing</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Adding capacity helps?</strong></td><td style="padding:0.6em 0.8em;">Yes, by definition</td><td style="padding:0.6em 0.8em;">Almost never</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Moving servers closer helps?</strong></td><td style="padding:0.6em 0.8em;">No</td><td style="padding:0.6em 0.8em;">Substantially</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>In video, controls</strong></td><td style="padding:0.6em 0.8em;">Resolution and frame rate</td><td style="padding:0.6em 0.8em;">Conversational feel and sync</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Symptom when bad</strong></td><td style="padding:0.6em 0.8em;">Blurry, blocky, or frozen picture</td><td style="padding:0.6em 0.8em;">People talking over each other</td></tr>
<tr><td style="padding:0.6em 0.8em;"><strong>Typical good value</strong></td><td style="padding:0.6em 0.8em;">3 Mbps for 720p30</td><td style="padding:0.6em 0.8em;">Under 150 ms round-trip</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Two rows do most of the work here." Adding capacity helps" is yes for one and no for the other, and that single asymmetry explains nearly every wasted upgrade in video troubleshooting.</p><h2 id="what-is-bandwidth">What is bandwidth?</h2><p>Bandwidth is defined as the maximum rate at which data can be transferred across a network connection, measured in bits per second.</p><p>Bandwidth works by setting a ceiling. It is a property of the link, provisioned by physics and by your provider, and it does not change based on how much traffic you send. It describes what the connection <em>could</em> carry, not what it currently is carrying.</p><h3 id="how-bandwidth-is-measured">How bandwidth is measured</h3><p>Bandwidth itself is usually a rated figure taken from the link specification or the service plan. What you can actually measure is the rate achieved during a sustained transfer, which is a different quantity with a different name. That distinction matters enough to spell out.</p><h3 id="bandwidth-vs-throughput-vs-goodput">Bandwidth vs throughput vs goodput</h3><p>These three get used interchangeably, and the confusion is the source of most bad capacity planning:</p><ul><li><strong>Bandwidth</strong> is the theoretical maximum the link is rated for. A ceiling.</li><li><strong>Throughput</strong> is the rate actually achieved over a measurement window. Always at or below bandwidth.</li><li><strong>Goodput</strong> is throughput minus protocol overhead and retransmissions, meaning the payload that was genuinely useful.</li></ul><p>A 100 Mbps connection (bandwidth) might sustain 60 Mbps under congestion (throughput), of which 54 Mbps is usable media (goodput). Configure your encoder against goodput. The number on the internet plan is the least relevant of the three.</p><h3 id="why-a-speed-test-does-not-predict-video-quality">Why a speed test does not predict video quality</h3><p>A speed test measures peak throughput to a nearby test server, over a short burst, usually over TCP. A video call needs <em>sustained</em> throughput to one specific media server, with low loss, for the entire session, usually over UDP.</p><p>Those are different measurements. A connection can pass a 500 Mbps speed test and still drop packets under sustained real-time load, especially over Wi-Fi, where contention and retransmissions produce jitter that a burst test never sees.</p><h2 id="what-is-latency">What is latency?</h2><p>Latency is defined as the time between data being sent and arriving, measured in milliseconds.</p><p>Latency works by accumulating delay at every stage of the path. It is a duration, not a rate, and it is the metric that decides whether anything interactive feels usable.</p><h3 id="how-latency-is-measured">How latency is measured</h3><p>Latency is normally reported as <strong>round-trip time (RTT)</strong>, the time for a packet to reach a destination and for the acknowledgment to return. That is what <code>ping</code> reports. One-way delay is roughly half of RTT on symmetric routes, though real paths are often asymmetric, so a true one-way measurement needs synchronised clocks at both ends.</p><p>For video the number users actually experience is <strong>glass-to-glass latency</strong>: the delay from light hitting the sender's camera sensor to that image appearing on the receiver's screen. It includes far more than the network.</p><pre><code class="language-text">glass-to-glass = capture + encode + packetize + network RTT/2
               + jitter buffer + decode + render
</code></pre><p>Network transit is frequently the smaller half. A jitter buffer alone can add 30 to 200 ms, and encoder latency adds 10 to 50 ms depending on settings. This is why a 20 ms <code>ping</code> result does not mean a 20 ms video call.</p><h3 id="the-four-components-of-latency">The four components of latency</h3><ol><li><strong>Propagation delay.</strong> Time for the signal to physically travel. In fibre, light moves at roughly 200,000 km per second, so a 5,000 km path costs about 25 ms one way no matter what equipment you buy. This is a floor set by physics.</li><li><strong>Transmission delay.</strong> Time to push the bits onto the wire, equal to packet size divided by link rate. This is the only component that bandwidth touches, and on a 100 Mbps link a 1,500-byte packet takes 0.12 ms. Upgrading to 1 Gbps saves 0.108 ms.</li><li><strong>Processing delay.</strong> Time each router or switch spends inspecting and forwarding. Usually microseconds, though deep packet inspection and NAT traversal add more.</li><li><strong>Queuing delay.</strong> Time spent waiting in buffers behind other traffic. The most variable component and the main cause of latency spikes under load. Oversized buffers produce <em>bufferbloat</em>, where a congested link adds hundreds of milliseconds without dropping a single packet.</li></ol><p>Point 2 is the whole answer to "does more bandwidth reduce latency". Technically yes, by a fraction of a millisecond, against propagation costs measured in tens of milliseconds.</p><h3 id="latency-vs-jitter">Latency vs jitter</h3><p><strong>Jitter</strong> is the variation in latency between consecutive packets, and for real-time video it often matters more than the average.</p><p>A connection with a steady 120 ms delay feels better than one swinging between 20 ms and 90 ms, because the receiver must buffer for the worst case. Video pipelines absorb jitter with a jitter buffer, and every millisecond of buffering adds directly to glass-to-glass latency. Reducing jitter is frequently a more effective way to cut perceived delay than reducing average latency.</p><h2 id="key-differences-between-bandwidth-and-latency">Key differences between bandwidth and latency</h2><h3 id="they-respond-to-different-fixes">They respond to different fixes</h3><p>Adding capacity raises the ceiling on throughput and does close to nothing for latency. A 1 Gbps link and a 100 Mbps link over the same 5,000 km route have nearly identical RTT, because propagation dominates and propagation does not care about capacity.</p><p>Move the server closer and the relationship inverts: latency drops substantially, bandwidth is unchanged.</p><p>The practical takeaway is blunt. <strong>Upgrading the internet plan will not fix a laggy video call.</strong> If the call is delayed, the cause is distance, routing, or queuing, and none of those are solved by more megabits.</p><h3 id="distance-affects-them-asymmetrically">Distance affects them asymmetrically</h3><p>Latency scales directly with distance, because propagation is a function of path length. Bandwidth is unaffected by distance in any direct sense. It is affected indirectly, through the bandwidth-delay product below, and through slower recovery from loss on long paths.</p><h3 id="congestion-affects-both-in-different-order">Congestion affects both, in different order</h3><p>Under congestion, routers queue packets before they drop them. Queuing raises latency <strong>first</strong>. Only once buffers overflow do packets drop and throughput fall.</p><p>Latency degradation is therefore an early warning that a throughput collapse is coming, which is exactly what modern congestion control algorithms like BBR exploit, and exactly what a video client should react to by lowering its send bitrate before packets start dropping.</p><h3 id="users-notice-them-differently">Users notice them differently</h3><p>Latency failure is social: people talk over each other and the conversation breaks down. Bandwidth failure is visual: the picture goes soft or blocky.</p><p>Users tolerate a surprising amount of visual degradation and almost none of conversational delay. That asymmetry is why real-time video systems are built to sacrifice resolution in order to protect timing, rather than the reverse.</p><h2 id="how-bandwidth-and-latency-relate">How bandwidth and latency relate</h2><p>The two are linked by the <strong>bandwidth-delay product (BDP)</strong>, the amount of data in flight on a link at any instant:</p><pre><code class="language-text">BDP (bits) = bandwidth (bits/sec) x RTT (seconds)
</code></pre><p>A 100 Mbps link at 80 ms RTT holds 8,000,000 bits, about 1 MB, in flight. For a windowed protocol such as TCP, that sets a hard ceiling:</p><pre><code class="language-text">max throughput = window size / RTT
</code></pre><p>With a 64 KB window at 80 ms RTT, maximum throughput is about 6.5 Mbps regardless of the link being rated at 100 Mbps. <strong>This is the mechanism behind "high bandwidth, low speed" on long-distance connections</strong>, and it is why TCP window scaling exists.</p><p>The corollary matters for video delivery. On high-latency paths, TCP-based protocols like <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-ILS" rel="noreferrer">HLS</a> and <a href="https://www.videosdk.live/developer-hub/hls/mpeg-dash" rel="noreferrer">DASH</a> lose throughput to the round-trip ceiling, while UDP-based WebRTC does not, because it never waits for an acknowledgment. Protocol choice is a bandwidth decision as much as a latency one.</p><h2 id="what-bandwidth-and-latency-mean-for-video">What bandwidth and latency mean for video</h2><h3 id="latency-budgets-by-use-case">Latency budgets by use case</h3>
<!--kg-card-begin: html-->
<table style="width:100% !important; display:table !important; border-collapse:collapse; table-layout:fixed; font-size:0.95em; min-width:460px;">
<colgroup><col style="width:46%"><col style="width:27%"><col style="width:27%"/></col></col></colgroup>
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);"><th style="padding:0.6em 0.8em; text-align:left;">Use case</th><th style="padding:0.6em 0.8em; text-align:left;">Target glass-to-glass</th><th style="padding:0.6em 0.8em; text-align:left;">Typical protocol</th></tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Video conferencing, interactive calls</td><td style="padding:0.6em 0.8em;">Under 300 ms</td><td style="padding:0.6em 0.8em;">WebRTC</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Live auctions, telehealth, betting</td><td style="padding:0.6em 0.8em;">Under 500 ms</td><td style="padding:0.6em 0.8em;">WebRTC</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Interactive live streaming with audience</td><td style="padding:0.6em 0.8em;">Under 1 s</td><td style="padding:0.6em 0.8em;">WebRTC</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">One-way broadcast, live sports</td><td style="padding:0.6em 0.8em;">2 to 6 s</td><td style="padding:0.6em 0.8em;">HLS, DASH</td></tr>
<tr><td style="padding:0.6em 0.8em;">VOD playback</td><td style="padding:0.6em 0.8em;">Not applicable</td><td style="padding:0.6em 0.8em;">HLS, DASH</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The 300 ms threshold is not arbitrary. Above roughly 300 ms round-trip, speakers begin colliding because each is waiting for a response that has not arrived, the same effect that makes satellite phone calls awkward. Below about 150 ms, most people cannot detect the no delay.</p><p>VideoSDK's HLS output runs at standard 5 to 6 second latency, which suits the bottom two rows. Anything in the top three needs the WebRTC path.</p><h3 id="bandwidth-requirements-by-resolution">Bandwidth requirements by resolution</h3><p>Approximate H.264 encoder bitrates at 30 fps, with practical provisioning targets:</p>
<!--kg-card-begin: html-->
<table style="width:100% !important; display:table !important; border-collapse:collapse; table-layout:fixed; font-size:0.95em; min-width:420px;">
<colgroup><col style="width:23%"><col style="width:35%"><col style="width:42%"/></col></col></colgroup>
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);"><th style="padding:0.6em 0.8em; text-align:left;">Resolution</th><th style="padding:0.6em 0.8em; text-align:left;">Video bitrate</th><th style="padding:0.6em 0.8em; text-align:left;">Provision at least</th></tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">360p</td><td style="padding:0.6em 0.8em;">0.6 to 1.0 Mbps</td><td style="padding:0.6em 0.8em;">1.5 Mbps</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">720p</td><td style="padding:0.6em 0.8em;">1.5 to 2.5 Mbps</td><td style="padding:0.6em 0.8em;">3 Mbps</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">1080p</td><td style="padding:0.6em 0.8em;">3.0 to 4.5 Mbps</td><td style="padding:0.6em 0.8em;">6 Mbps</td></tr>
<tr><td style="padding:0.6em 0.8em;">4K</td><td style="padding:0.6em 0.8em;">15 to 25 Mbps</td><td style="padding:0.6em 0.8em;">30 Mbps</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Provision above the encoder bitrate, never at it. The headroom absorbs audio, retransmissions, protocol overhead, and burst variance. Provisioning exactly at the encoder target guarantees degradation the first time the network hiccups.</p><p>Multi-party calls multiply this on the receive side. A selective forwarding unit sends each participant one stream per other participant, so an eight-person 720p call needs roughly 7 x 1.5 Mbps, about 10.5 Mbps downstream. Simulcast exists precisely to keep that within reach, by letting each receiver take the layer it can afford instead of the layer the sender prefers.</p><h3 id="the-most-common-misdiagnosis">The most common misdiagnosis</h3><p>A user on a fast connection reports an unusable call. Almost always the cause is one of three things, and none of them is bandwidth:</p><ul><li><strong>Distance to the media server.</strong> A user in Singapore routed through a US East region pays 200+ ms in propagation alone. The fix is a geographically distributed media edge.</li><li><strong>Bufferbloat on the local link.</strong> A saturated upload queue adds hundreds of milliseconds. The fix is queue management or a lower send bitrate.</li><li><strong>Wi-Fi retransmissions.</strong> Contention and interference create jitter that inflates the jitter buffer. The fix is the radio environment, not the plan.</li></ul><p>In each case bandwidth is fine and latency is the failure. Treating the two as one metric guarantees the wrong fix.</p><h2 id="how-to-reduce-latency">How to reduce latency</h2><ul><li><strong>Shorten the physical path.</strong> Place media servers near users. This is the only remedy for propagation delay and usually the single largest win available.</li><li><strong>Use UDP-based transport.</strong> WebRTC over UDP avoids TCP's retransmit-and-wait cycle, which turns one lost packet into a multi-RTT stall.</li><li><strong>Tune the jitter buffer adaptively.</strong> Fixed large buffers trade latency for smoothness even when the network is stable.</li><li><strong>Enable modern congestion control.</strong> BBR and similar algorithms target the point before queues fill, which avoids bufferbloat instead of reacting to it.</li><li><strong>Cut encoder latency.</strong> Disable B-frames, use low-latency presets, and keep GOP sizes short on real-time paths.</li><li><strong>Prioritise media traffic.</strong> DSCP marking keeps media out of bulk-transfer queues on networks that honour it.</li></ul><h2 id="how-to-get-more-usable-bandwidth">How to get more usable bandwidth</h2><p>The honest framing is that you rarely add bandwidth. You reduce how much you need, or you recover what overhead is wasting.</p><ul><li><strong>Use a more efficient codec.</strong> H.265, VP9, or AV1 reach comparable quality at lower bitrate, which relaxes the requirement rather than raising the supply. Check the simulcast implications before switching, since not every codec supports multiple resolution layers.</li><li><strong>Adopt simulcast or SVC</strong> so each receiver gets a layer matched to its own capacity instead of being held to the weakest participant's.</li><li><strong>Reduce packet loss.</strong> Loss triggers retransmission and congestion-control backoff, and a 2% loss rate can cut effective throughput by considerably more than 2%.</li><li><strong>Enable TCP window scaling</strong> on any TCP-based delivery path, so the window can exceed 64 KB and clear the BDP ceiling on long routes.</li><li><strong>Lower resolution before lowering frame rate.</strong> Viewers notice stutter faster than softness, so dropping from 1080p to 720p is usually a better trade than halving fps.</li></ul><h2 id="definitions">Definitions </h2><blockquote><strong>Bandwidth:</strong> The maximum data rate a link is rated to carry, in bits per second. A ceiling, not a measurement.</blockquote><blockquote><strong>Throughput:</strong> The data rate actually delivered over a measurement window. Always at or below bandwidth.</blockquote><blockquote><strong>Goodput:</strong> Throughput minus protocol overhead and retransmissions. The payload your encoder actually competes for.</blockquote><blockquote><strong>Latency:</strong> The delay between sending and receiving, in milliseconds. In video, the number that matters is glass-to-glass, from camera sensor to remote screen.</blockquote><blockquote><strong>Jitter:</strong> Variation in latency between consecutive packets. Absorbed by a jitter buffer, which converts it into additional delay.</blockquote><blockquote><strong>Bandwidth-delay product:</strong> Bandwidth multiplied by round-trip time, giving the data in flight on a link. It sets the throughput ceiling for windowed protocols.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>Bandwidth is capacity and latency is delay. They are independent properties of the same link, and no amount of one compensates for the other.</li><li>More bandwidth does not reduce latency in any meaningful way, because propagation and queuing dominate delay and neither responds to capacity.</li><li>Bandwidth failure looks blurry and blocky. Latency failure sounds like people interrupting each other. Identify which one you have before choosing a fix.</li><li>Throughput, not bandwidth, is what your encoder actually gets, and goodput is what it can actually use. Configure against the measured number, never the plan.</li><li>VideoSDK reports round-trip time, jitter, and per-stream bitrate through the WebRTC <code>getStats()</code> API, so you can tell a latency problem from a bandwidth problem instead of guessing.</li></ul><h2 id="stop-guessing-which-one-is-broken">Stop guessing which one is broken</h2><p>Almost every wasted fix in this article comes from the same place: someone read a symptom and assumed a cause. Bandwidth and latency produce different failures, and you cannot tell them apart without reading both from the live session.</p><p>VideoSDK reports round-trip time, jitter, packet loss, and per-stream bitrate through the client SDKs, so the diagnosis is a number rather than a hunch. Once you know which one is failing, the response is a configuration change rather than a support ticket:</p><pre><code class="language-javascript">import { VideoSDK } from "@videosdk.live/js-sdk";

// Throughput is the constraint: shed bitrate, keep the call alive
const constrainedTrack = await VideoSDK.createCameraVideoTrack({
  encoderConfig: "h360p_w640p",
  bitrateMode: VideoSDK.Constants.BitrateMode.BANDWIDTH_OPTIMIZED,
  multiStream: true,
  maxLayer: 3,
});

// Headroom is available: spend it on picture
const richTrack = await VideoSDK.createCameraVideoTrack({
  encoderConfig: "h720p_w1280p",
  bitrateMode: VideoSDK.Constants.BitrateMode.HIGH_QUALITY,
  multiStream: true,
  maxLayer: 3,
});
</code></pre><p><code>multiStream</code> is the lever that matters most in group calls. With simulcast on, each receiver takes the layer its own connection can afford, so one participant on a weak link stops dragging quality down for everyone.</p><p>Latency is the other half, and it is an architecture decision rather than a parameter. Interactive sessions run over WebRTC for sub-second delivery. HLS output runs at standard 5 to 6 second latency, which is the right trade only when audience scale matters more than immediacy.</p><h3 id="where-to-go-next">Where to go next</h3><ul><li><a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track"><strong>Optimize video track guide</strong></a> lists every <code>encoderConfig</code> value with its bitrate under each <code>bitrateMode</code>, plus the <code>maxLayer</code> rules that decide how many simulcast layers you actually get.</li><li><a href="https://docs.videosdk.live/react/api/sdk-reference/custom-tracks"><strong>Custom tracks API reference</strong></a> covers the full parameter set, with separate pages per platform.</li><li><a href="https://docs.videosdk.live/code-sample"><strong>Code samples</strong></a> if you would rather start from a running quickstart than a parameter table.</li><li><a href="https://discord.gg/Gpmj6eCq5u"><strong>Discord</strong></a> is the fastest place to get a network or bitrate question answered by someone who has debugged it in production.</li></ul><p><a href="https://app.videosdk.live/login" rel="noreferrer">Start building free with $20 in credit!</a></p><p>What has cost you more time in production, bandwidth or latency? Drop a comment with the symptom and what actually fixed it. The misdiagnosis stories are usually the useful part.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="is-bandwidth-the-same-as-latency">Is bandwidth the same as latency?</h3><p>No. Bandwidth is the maximum data rate a connection can carry, measured in bits per second. Latency is the delay before data arrives, measured in milliseconds. They are independent: a satellite link can carry high bandwidth at 600 ms of delay, and a short local link can deliver low bandwidth at 2 ms.</p><h3 id="does-higher-bandwidth-reduce-latency">Does higher bandwidth reduce latency?</h3><p>Barely. Extra capacity reduces transmission delay, the time to push bits onto the wire, but not propagation, processing, or queuing delay. On a 5,000 km route, propagation alone costs about 25 ms each way regardless of capacity, so a tenfold bandwidth increase can change total latency by a fraction of a millisecond.</p><h3 id="is-bandwidth-the-same-as-internet-speed">Is bandwidth the same as internet speed?</h3><p>Not exactly. "Speed" in marketing usually means bandwidth, the rated capacity. What you actually experience combines throughput (the rate you achieve) with latency (how quickly anything starts arriving). A connection can advertise high speed and still feel slow, because responsiveness is a latency property.</p><h3 id="what-is-a-good-latency-for-video-calls">What is a good latency for video calls?</h3><p>Under 150 ms round-trip is imperceptible to most people. Under 300 ms remains conversational. Above 300 ms, speakers start talking over each other because each is waiting on a response that has not arrived. Above 500 ms, the call feels broken regardless of picture quality.</p><h3 id="how-much-bandwidth-does-a-video-call-need">How much bandwidth does a video call need?</h3><p>Roughly 1.5 Mbps for 360p, 3 Mbps for 720p, and 6 Mbps for 1080p at 30 fps, including headroom above the raw encoder bitrate. Multi-party calls multiply the receive side, so an eight-person 720p call needs about 10.5 Mbps downstream unless simulcast reduces it per receiver.</p><h3 id="why-is-my-video-blurry-when-my-speed-test-shows-high-numbers">Why is my video blurry when my speed test shows high numbers?</h3><p>Because a speed test measures peak throughput to a nearby server over a short burst. Video needs sustained throughput to one specific media server, with low packet loss, for the whole session. A connection can pass a 500 Mbps test and still drop packets under sustained real-time load, particularly over Wi-Fi.</p><h3 id="which-matters-more-for-video-bandwidth-or-latency">Which matters more for video, bandwidth or latency?</h3><p>For interactive video, latency matters more, because users tolerate lower resolution far better than conversational delay. For one-way streaming and VOD, bandwidth matters more, since delay is absorbed by buffering and picture quality becomes the visible constraint.</p>]]></content:encoded></item><item><title><![CDATA[H.264 vs H.265: What's the Difference?]]></title><description><![CDATA[H.264 vs H.265 is not a question of which is better. H.264 is mandatory in WebRTC and cheap to encode. H.265 halves the bitrate but needs newer hardware and costs more CPU. Here is what each one actually delivers, with bitrate numbers per resolution and a verdict per use case.]]></description><link>https://www.videosdk.live/blog/h264-vs-h265</link><guid isPermaLink="false">6a900b2bb3240feb748c99b1</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 31 Aug 2026 05:46:01 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-27--2026--04_46_50-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>H.264 (AVC) is the compatibility default. H.265 (HEVC) is the efficiency upgrade.</strong> H.265 was designed to reach the same perceptual quality at roughly half the bitrate, and it costs more CPU to encode and needs newer hardware to decode. Use H.264 when the receiver is unknown. Use H.265 when you control the endpoints and bandwidth or storage is the constraint.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-27--2026--04_46_50-PM.png" alt="H.264 vs H.265: What's the Difference?"/><p>Both are video <strong>codecs</strong>, not file formats. A codec decides how pixels are compressed. A container such as MP4 or MKV decides how the compressed result is packaged. The two questions are independent, and mixing them up is the most common error in this topic.</p><h2 id="h264-vs-h265-at-a-glance">H.264 vs H.265 at a glance</h2>
<!--kg-card-begin: html-->
<table style="width:100%; border-collapse:collapse; font-size:0.95em; min-width:560px;">
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);">
<th style="padding:0.6em 0.8em; text-align:left;"/>
<th style="padding:0.6em 0.8em; text-align:left;">H.264 / AVC</th>
<th style="padding:0.6em 0.8em; text-align:left;">H.265 / HEVC</th>
</tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Published</strong></td><td style="padding:0.6em 0.8em;">2003 (ITU-T H.264, ISO/IEC 14496-10)</td><td style="padding:0.6em 0.8em;">2013 (ITU-T H.265, ISO/IEC 23008-2)</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Block structure</strong></td><td style="padding:0.6em 0.8em;">Macroblocks, fixed 16x16</td><td style="padding:0.6em 0.8em;">Coding Tree Units, 64x64 down to 8x8</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Design target</strong></td><td style="padding:0.6em 0.8em;">Baseline</td><td style="padding:0.6em 0.8em;">About 50% bitrate reduction at equal perceptual quality</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Encode cost</strong></td><td style="padding:0.6em 0.8em;">Lower</td><td style="padding:0.6em 0.8em;">Substantially higher at comparable settings</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Decode support</strong></td><td style="padding:0.6em 0.8em;">Effectively universal</td><td style="padding:0.6em 0.8em;">Newer hardware, uneven in browsers</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Browser playback</strong></td><td style="padding:0.6em 0.8em;">All major browsers</td><td style="padding:0.6em 0.8em;">Safari 13+, Chrome 107+ (partial), Firefox 137+</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>WebRTC</strong></td><td style="padding:0.6em 0.8em;">Mandatory to implement (RFC 7742)</td><td style="padding:0.6em 0.8em;">Optional, Chrome and Safari only</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Licensing</strong></td><td style="padding:0.6em 0.8em;">One main pool</td><td style="padding:0.6em 0.8em;">Multiple pools, more complex</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Best at</strong></td><td style="padding:0.6em 0.8em;">Reach, real-time, low encode budget</td><td style="padding:0.6em 0.8em;">4K and above, storage, bandwidth-constrained VOD</td></tr>
<tr><td style="padding:0.6em 0.8em;"><strong>Symptom when wrong</strong></td><td style="padding:0.6em 0.8em;">Higher bitrate than necessary</td><td style="padding:0.6em 0.8em;">Black frames or CPU-bound playback on old devices</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h2 id="what-is-h264">What is H.264?</h2><p>H.264 is defined as a block-oriented, motion-compensated video compression standard published jointly in 2003 as ITU-T Recommendation H.264 and ISO/IEC 14496-10, also called MPEG-4 Part 10 or AVC (Advanced Video Coding).</p><p>H.264 works by splitting each frame into macroblocks of 16x16 pixels, predicting each block either from neighbouring blocks in the same frame (intra prediction) or from a matching region in a previously coded frame (inter prediction), then transforming and quantising only the prediction error.</p><h3 id="why-h264-is-still-the-default">Why H.264 is still the default</h3><p>Two reasons, and neither is technical superiority. First, hardware decoders shipped in essentially every phone, laptop, TV, and set-top box built after roughly 2006, so playback is free in power terms almost everywhere. Second, RFC 7742 makes H.264 Constrained Baseline <strong>mandatory to implement</strong> for <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> browsers, which means any browser-based call can fall back to it. Reach beats efficiency when you do not control the receiving device.</p><h3 id="h264-profiles-matter-more-than-most-articles-admit">H.264 profiles matter more than most articles admit</h3><p>"H.264" is not one thing. Constrained Baseline drops B-frames and CABAC entropy coding, which lowers both quality-per-bit and decoder complexity. High Profile adds both back and is what streaming services actually ship. A Constrained Baseline stream and a High Profile stream at the same bitrate are visibly different, so any H.264-versus-H.265 comparison that does not name the profile is under-specified.</p><h2 id="what-is-h265">What is H.265?</h2><p>H.265 is defined as the successor video compression standard published in 2013 as ITU-T Recommendation H.265 and ISO/IEC 23008-2, known as HEVC (High Efficiency Video Coding).</p><p>H.265 works by replacing fixed macroblocks with a quadtree of Coding Tree Units that can span 64x64 pixels and subdivide down to 8x8, so flat regions are described with far fewer blocks while detailed regions keep fine granularity. It adds 33 intra-prediction directions against H.264's 9, and better motion vector prediction.</p><h3 id="how-much-bandwidth-does-h265-actually-save">How much bandwidth does H.265 actually save?</h3><p>The stated design goal for HEVC was roughly <strong>50% bitrate reduction at equivalent subjective quality</strong> against H.264. Treat that as the standard's target, not as a number you will measure.</p><p>What you actually get depends on resolution, content, encoder, and preset:</p><ul><li>Gains are <strong>largest at high resolution</strong>. The bigger CTUs pay off most on 4K and 8K, where large uniform areas dominate.</li><li>Gains <strong>shrink at low resolution and low bitrate</strong>, where H.264's smaller blocks are already a reasonable fit.</li><li>Gains <strong>shrink on high-motion content</strong>, where prediction works less well for both codecs.</li><li>Gains <strong>shrink at fast presets</strong>, because the tools that produce HEVC's advantage are the expensive ones, and real-time presets skip them.</li></ul><p>Practical planning figures for 30 fps, using H.264 High Profile as the baseline:</p>
<!--kg-card-begin: html-->
<table style="width:100% !important; display:table !important; border-collapse:collapse; table-layout:fixed; font-size:0.95em; min-width:420px;">
<colgroup><col style="width:19%"><col style="width:40%"><col style="width:41%"/></col></col></colgroup>
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);"><th style="padding:0.6em 0.8em; text-align:left;">Resolution</th><th style="padding:0.6em 0.8em; text-align:left;">H.264 typical bitrate</th><th style="padding:0.6em 0.8em; text-align:left;">H.265 typical bitrate</th></tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">360p</td><td style="padding:0.6em 0.8em;">0.6 to 1.0 Mbps</td><td style="padding:0.6em 0.8em;">0.4 to 0.7 Mbps</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">720p</td><td style="padding:0.6em 0.8em;">1.5 to 2.5 Mbps</td><td style="padding:0.6em 0.8em;">1.0 to 1.7 Mbps</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">1080p</td><td style="padding:0.6em 0.8em;">3.0 to 4.5 Mbps</td><td style="padding:0.6em 0.8em;">2.0 to 3.0 Mbps</td></tr>
<tr><td style="padding:0.6em 0.8em;">4K</td><td style="padding:0.6em 0.8em;">15 to 25 Mbps</td><td style="padding:0.6em 0.8em;">8 to 15 Mbps</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>These are planning ranges for encoder configuration, not benchmark results. Measure your own content before committing capacity.</p><h3 id="encoding-cost-is-the-hidden-line-item">Encoding cost is the hidden line item</h3><p>H.265's efficiency is bought with search. The quadtree partitioning, larger prediction unit set, and extra intra directions all mean more candidate evaluations per block. On CPU encoding at comparable quality targets, HEVC encodes meaningfully slower than H.264 at equivalent presets, and the ratio widens as you move toward slower, higher-quality presets.</p><p>For an offline transcode this is a cost question. For a live encode it is a <strong>latency</strong> question, because encoder time lands directly in the glass-to-glass budget. This is the single most important reason real-time systems still default to H.264.</p><h2 id="h264-vs-h265-compatibility">H.264 vs H.265 compatibility</h2><h3 id="browser-support">Browser support</h3>
<!--kg-card-begin: html-->
<table style="width:100% !important; display:table !important; border-collapse:collapse; table-layout:fixed; font-size:0.95em; min-width:380px;">
<colgroup><col style="width:42%"><col style="width:16%"><col style="width:42%"/></col></col></colgroup>
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);"><th style="padding:0.6em 0.8em; text-align:left;">Browser</th><th style="padding:0.6em 0.8em; text-align:left;">H.264</th><th style="padding:0.6em 0.8em; text-align:left;">H.265 / HEVC</th></tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Chrome</td><td style="padding:0.6em 0.8em;">Yes</td><td style="padding:0.6em 0.8em;">Partial from 107</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Edge</td><td style="padding:0.6em 0.8em;">Yes</td><td style="padding:0.6em 0.8em;">Partial</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Firefox</td><td style="padding:0.6em 0.8em;">Yes</td><td style="padding:0.6em 0.8em;">Partial from 137</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Safari (macOS)</td><td style="padding:0.6em 0.8em;">Yes</td><td style="padding:0.6em 0.8em;">Yes from 13</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Safari (iOS)</td><td style="padding:0.6em 0.8em;">Yes</td><td style="padding:0.6em 0.8em;">Yes from 11</td></tr>
<tr><td style="padding:0.6em 0.8em;">Samsung Internet</td><td style="padding:0.6em 0.8em;">Yes</td><td style="padding:0.6em 0.8em;">Yes from 21</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>"Partial" is doing real work in that table. Chrome and Firefox HEVC support is generally tied to platform hardware decoders being present, so it can be available on one machine and absent on another running the same browser version. Never treat HEVC playback as a static capability.</p><h3 id="webrtc-support">WebRTC support</h3><p>This is where the two codecs diverge most sharply for real-time developers.</p><p>H.264 Constrained Baseline is&nbsp;<strong>mandatory to implement</strong>&nbsp;under&nbsp;<a href="https://www.rfc-editor.org/rfc/rfc7742.html" rel="noreferrer">RFC 7742</a>, alongside VP8. Section 5 states that WebRTC browsers must implement both, which is why either can always be negotiated regardless of what else a browser supports.</p><p>H.265 has no such guarantee. Chrome shipped it in version 136 across desktop, Android, and WebView, and it is gated on hardware: Chrome does not ship a software HEVC encoder, so availability depends on the device and operating system rather than on the browser version alone. Safari has carried HEVC over WebRTC for longer, but Safari 18.0 was the release that added the standard&nbsp;<a href="https://www.rfc-editor.org/rfc/rfc7789.html" rel="noreferrer">RFC 7789</a>&nbsp;RTP payload format, replacing the generic packetization used before it. Support and interoperability are separate questions here.The correct pattern is to query at runtime rather than to branch on a user-agent string:</p><p>The consequence is that a static compatibility table cannot answer this. Two machines running the same Chrome build can differ, because one has a hardware HEVC encoder and the other does not. Query at runtime instead of branching on a user-agent string:</p><pre><code class="language-javascript">const send = RTCRtpSender.getCapabilities("video").codecs;
const recv = RTCRtpReceiver.getCapabilities("video").codecs;

const canSendHevc = send.some((c) =&gt; c.mimeType === "video/H265");
const canRecvHevc = recv.some((c) =&gt; c.mimeType === "video/H265");

console.log({ canSendHevc, canRecvHevc });
console.log("Sender codecs:", send.map((c) =&gt; c.mimeType));
</code></pre><p>Check both directions. Send and receive capabilities are reported separately and are not always the same, since hardware decode is far more common than hardware encode.</p><h3 id="licensing">Licensing</h3><p>H.264 licensing consolidated into a single main patent pool with well-understood terms. H.265 fragmented across several pools, which raised both cost and, more damagingly, uncertainty. That uncertainty is the main reason Google and Mozilla deprioritised HEVC and why AV1 exists as a royalty-free alternative.</p><p>Licensing is a legal question, not an engineering one. If you are distributing an encoder or decoder at scale, get advice rather than a blog's summary.</p><h2 id="when-to-use-h264">When to use H.264</h2><ul><li>Browser-based real-time calls, where receiver capability is unknown.</li><li>Any WebRTC path that must interoperate broadly, since it is mandatory to implement.</li><li>Live encoding on a constrained CPU budget, where encoder time is latency.</li><li>Content at 1080p and below, where HEVC's advantage is smallest.</li><li>Maximum device reach, including older Android and legacy set-top boxes.</li></ul><p><strong>Not for:</strong> 4K and 8K libraries where storage or egress dominates cost.</p><h2 id="when-to-use-h265">When to use H.265</h2><ul><li>4K and 8K VOD, where the bitrate saving is largest and encoding is offline.</li><li>Storage-bound archives, including long-retention surveillance.</li><li>Apple-ecosystem apps, where hardware encode and decode are dependable.</li><li>Bandwidth-constrained delivery to known, modern endpoints.</li></ul><p><strong>Not for:</strong> open-web playback to unknown browsers, or any real-time path where the encoder must keep up with the capture frame rate on modest hardware.</p><h2 id="where-vp9-and-av1-fit">Where VP9 and AV1 fit</h2><p>Neither is a footnote. VP9 is royalty-free, ships in Chrome, Firefox, and Edge, and sits close to HEVC in efficiency. AV1 is royalty-free, targets roughly 30% over HEVC as a design goal, is expensive to encode without hardware assistance, and now has hardware decode in recent GPUs and mobile SoCs.</p><p>For <strong>web delivery</strong>, VP9 and AV1 usually beat HEVC on licensing and browser reach. For <strong>Apple-native and broadcast pipelines</strong>, HEVC usually wins on hardware maturity. The codec question is rarely "which is best" and almost always "which is decodable on the devices I have to serve".</p><h2 id="how-to-check-which-codec-a-file-or-stream-is-using">How to check which codec a file or stream is using</h2><p>Guessing is unnecessary. For a file, <code>ffprobe</code> reports the codec directly:</p><pre><code class="language-bash">ffprobe -v error -select_streams v:0 \
  -show_entries stream=codec_name,profile,width,height,bit_rate \
  -of default=noprint_wrappers=1 input.mp4
</code></pre><p>Typical output:</p><pre><code class="language-text">codec_name=h264
profile=High
width=1920
height=1080
bit_rate=4200000
</code></pre><p>Note that <code>profile=High</code> line. As covered above, H.264 High Profile and H.264 Constrained Baseline behave differently enough that a comparison without the profile is incomplete.</p><p>For a live WebRTC session, read the codec actually negotiated rather than the one you requested:</p><pre><code class="language-javascript">const stats = await peerConnection.getStats();

stats.forEach((stat) =&gt; {
  if (stat.type === "outbound-rtp" &amp;&amp; stat.kind === "video") {
    const codec = stats.get(stat.codecId);
    console.log("Sending:", codec?.mimeType, "at", stat.targetBitrate, "bps");
  }
});
</code></pre><p>Negotiation can fall back without warning if the far end lacks your preferred codec, so the requested codec and the sent codec are not always the same.</p><h2 id="h264-vs-h265-for-security-cameras-and-surveillance">H.264 vs H.265 for security cameras and surveillance</h2><p>Surveillance is the one use case where H.265 usually wins outright, and the reason is retention rather than picture quality.</p><p>A camera recording continuously produces a fixed number of hours per day. Halving the bitrate roughly doubles retention on the same disk, or halves the storage bill for the same retention window. Encoding happens once, on a dedicated chip in the camera, so the encode cost that rules H.265 out of real-time browser calls is already paid in hardware.</p><p>Two cautions apply:</p><ul><li><strong>The recorder and client must decode it.</strong> An older NVR or a browser-based viewing client may not, which turns a storage saving into an unviewable archive.</li><li><strong>Vendor "H.265+" and "Smart Codec" modes are not the standard.</strong> They typically add aggressive long-GOP and background-static encoding on top of HEVC. They save more space and can degrade evidential quality on motion, which matters if the footage is ever needed as evidence.</li></ul><p>For streaming that same camera into a browser-based dashboard, the calculus flips back to H.264, because the viewing client is the constraint rather than the disk.</p><h2 id="definitions-glossary">Definitions glossary</h2><blockquote><strong>Codec:</strong> The algorithm that compresses and decompresses video (H.264, H.265, VP9, AV1). It decides how many bits a given picture costs, which makes it the layer where quality is set.</blockquote><blockquote><strong>Container:</strong> The file format that wraps compressed streams (MP4, MKV, WebM). It never compresses anything and never affects quality.</blockquote><blockquote><strong>Profile:</strong> A named subset of a codec's tools. H.264 Constrained Baseline omits B-frames and CABAC; High Profile includes both and produces better quality at the same bitrate.</blockquote><blockquote><strong>CTU (Coding Tree Unit):</strong> H.265's variable block structure, spanning 64x64 pixels down to 8x8. It replaces H.264's fixed 16x16 macroblocks and is the main source of HEVC's efficiency.</blockquote><blockquote><strong>Mandatory to implement:</strong> A codec that a conforming WebRTC implementation must support. RFC 7742 names VP8 and H.264 Constrained Baseline, which is why either can always be negotiated.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>H.265 targets roughly half the bitrate of H.264 at equal perceptual quality. Treat that as the standard's design objective, not as a figure to plan capacity against without testing.</li><li>Realised savings are largest at 4K and above, on low-motion content, at slow encoder presets. They shrink toward zero at 360p on high-motion footage at a real-time preset.</li><li>H.264 remains the safe default for browser-based real-time video, because RFC 7742 makes it mandatory to implement and its faster encoder consumes less of the latency budget.</li><li>H.265 wins clearly for 4K VOD, Apple-native pipelines, and surveillance retention, where encoding is offline or hardware-accelerated and storage dominates cost.</li><li>Codec and container are separate decisions. H.264 and H.265 are codecs; MP4 and MKV are containers. Either codec travels in either container.</li></ul><h2 id="build-video-that-negotiates-codecs-properly">Build video that negotiates codecs properly</h2><p>The H.264 vs H.265 decision matters less in real-time video than most teams expect, because you do not pick the codec, you offer it. Whatever the far end accepts is what actually gets sent. The useful question is what your SDK lets you offer, and what it does when negotiation falls back.</p><p>VideoSDK exposes that on track creation:</p><pre><code class="language-javascript">let customTrack = await VideoSDK.createCameraVideoTrack({
  // The id of the camera to capture video from.
  cameraId: "camera-id", // OPTIONAL

  // Tunes the encoder for the kind of content you are sending.
  optimizationMode: "motion", // "text" | "detail" | Default: "motion"

  // Resolution (height x width) of the captured video.
  encoderConfig: "h540p_w960p", // "h360p_w640p" | "h720p_w1280p" | Default: "h720p_w1280p"

  // On mobile browsers, selects the front or rear camera.
  facingMode: "environment", // "user" | Default: "environment"

  // Whether to publish multiple resolution layers (simulcast).
  multiStream: true, // false | Default: true

  // Controls the quality and bandwidth trade-off.
  bitrateMode: VideoSDK.Constants.BitrateMode.HIGH_QUALITY,
  // BANDWIDTH_OPTIMIZED | BALANCED | Default: HIGH_QUALITY

  // Maximum number of simulcast layers to publish.
  maxLayer: 2, // 1 | 3 | Default: 2

  // Video codec used for this track.
  codec: VideoSDK.Constants.VideoCodec.H264,
  // VP8 | VP9 | AV1 | Default: H264
});</code></pre><p>The JavaScript SDK accepts H264 (the default), VP8, VP9, and AV1. One constraint is worth knowing before you switch: VP9 and AV1 do not support <code>multiStream</code>, so choosing either disables simulcast and drops every receiver to a single shared layer. In a group call with mixed connections that usually costs more than the codec saves. The iOS SDK supports the same four codecs (VP9 and AV1 from version 2.8.0), but its docs list H264 as single-stream too, so check simulcast behaviour per platform rather than assuming one rule carries everywhere.</p><h3 id="where-to-go-next">Where to go next</h3><ul><li><a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track"><strong>Optimize video track guide</strong></a> covers every <code>encoderConfig</code> value with its bitrate under each <code>bitrateMode</code>, plus the <code>maxLayer</code> rules that decide how many simulcast layers you actually get.</li><li><a href="https://docs.videosdk.live/react/api/sdk-reference/custom-tracks"><strong>Custom tracks API reference</strong></a> lists the full <code>createCameraVideoTrack()</code> parameter set, with separate pages per platform.</li><li><a href="https://docs.videosdk.live/code-sample"><strong>Code samples</strong></a> if you would rather read a running quickstart than a parameter table.</li><li><a href="https://discord.gg/Gpmj6eCq5u"><strong>Discord</strong></a> is the fastest place to get a codec or simulcast question answered by someone who has shipped it.</li></ul><p><a href="https://app.videosdk.live/login" rel="noreferrer">Start building free with $20 in credit.</a></p><p>Which codec are you running in production, and did simulcast survive the decision? Drop a comment, the tradeoff is rarely obvious until you measure it.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="is-h265-better-than-h264">Is H.265 better than H.264?</h3><p>H.265 is more efficient, not universally better. It targets the same perceptual quality at roughly half the bitrate, which makes it better for 4K storage and bandwidth-constrained delivery. H.264 is better wherever compatibility, encode speed, or low-latency real-time delivery matters more than bitrate.</p><h3 id="does-h265-use-less-bandwidth-than-h264">Does H.265 use less bandwidth than H.264?</h3><p>Yes, at equal perceptual quality. The design target is roughly 50% less, though realised savings depend on resolution, content, and encoder preset, and are largest at 4K and above. H.265 does not reduce latency, because bitrate and delay are separate properties.</p><h3 id="is-h265-good-for-live-streaming">Is H.265 good for live streaming?</h3><p>It depends on where the encoding happens. For hardware-encoded broadcast contribution, H.265 works well. For browser-based real-time calls, H.264 remains safer because it is mandatory to implement in WebRTC and its encoder is faster, and encoder time counts against latency.</p><h3 id="can-i-convert-h264-to-h265-to-improve-quality">Can I convert H.264 to H.265 to improve quality?</h3><p>No. Transcoding decodes the H.264 stream and re-encodes it, so the output inherits every artifact of the source and adds new ones. Transcoding to H.265 reduces file size at similar quality. It cannot recover detail that H.264 already discarded.</p><h3 id="do-i-need-a-special-player-for-h265">Do I need a special player for H.265?</h3><p>Usually not on modern hardware, but support is uneven. Safari plays HEVC from version 13, Chrome from 107 and Firefox from 137, both generally requiring a platform hardware decoder. Old Android devices and older desktops may fail to decode it at all.</p><h3 id="which-codec-should-i-use-for-a-video-calling-app">Which codec should I use for a video calling app?</h3><p>H.264 or VP8, because RFC 7742 makes both mandatory to implement for WebRTC, so a call can always negotiate one of them. Treat H.265, VP9, and AV1 as opportunistic upgrades negotiated per-session via <code>RTCRtpSender.getCapabilities()</code>.</p>]]></content:encoded></item><item><title><![CDATA[MKV vs MP4: What's the Difference?]]></title><description><![CDATA[Most MKV vs MP4 comparisons get one thing wrong: they claim MKV has better quality. Containers do not compress anything, so they cannot. This covers what genuinely differs between the two, from browser support and HLS packaging to subtitle formats and truncation recovery.]]></description><link>https://www.videosdk.live/blog/mkv-vs-mp4</link><guid isPermaLink="false">6a901fccb3240feb748c99ee</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 31 Aug 2026 05:45:44 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-27--2026--05_24_38-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>MKV and MP4 are containers, not codecs. Neither one compresses video, so neither one determines quality.</strong> MP4 is the delivery standard: browsers, phones, HLS, and DASH all expect it. MKV is the flexible archive format: unlimited tracks, richer subtitle support, better resilience to a truncated recording. Use MP4 to ship. Use MKV to keep.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-27--2026--05_24_38-PM.png" alt="MKV vs MP4: What's the Difference?"/><p>If you take one thing from this page: a 4 GB MKV and a 4 GB MP4 holding the same H.264 stream at the same bitrate look <strong>identical</strong>, because the picture was decided by the codec and the encoder settings before either container was involved.</p><h2 id="mkv-vs-mp4-at-a-glance">MKV vs MP4 at a glance</h2>
<!--kg-card-begin: html-->
<table style="width:100%; border-collapse:collapse; font-size:0.95em; min-width:560px;">
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);">
<th style="padding:0.6em 0.8em; text-align:left;"/>
<th style="padding:0.6em 0.8em; text-align:left;">MKV (Matroska)</th>
<th style="padding:0.6em 0.8em; text-align:left;">MP4 (ISO BMFF)</th>
</tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Standardised by</strong></td><td style="padding:0.6em 0.8em;">Open community spec, IETF drafts</td><td style="padding:0.6em 0.8em;">ISO/IEC 14496-12 and 14496-14</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Determines quality?</strong></td><td style="padding:0.6em 0.8em;">No</td><td style="padding:0.6em 0.8em;">No</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Video codecs</strong></td><td style="padding:0.6em 0.8em;">Effectively any</td><td style="padding:0.6em 0.8em;">H.264, H.265, AV1, VP9, MPEG-4</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Audio codecs</strong></td><td style="padding:0.6em 0.8em;">Any, including FLAC and PCM</td><td style="padding:0.6em 0.8em;">AAC, ALAC, FLAC, MP3, Opus</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Subtitles</strong></td><td style="padding:0.6em 0.8em;">SRT, ASS/SSA, PGS, VobSub</td><td style="padding:0.6em 0.8em;">Limited (TTML, tx3g)</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Multiple tracks</strong></td><td style="padding:0.6em 0.8em;">Unlimited, unrestricted</td><td style="padding:0.6em 0.8em;">Supported, less flexible in practice</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Chapters and menus</strong></td><td style="padding:0.6em 0.8em;">Yes, rich</td><td style="padding:0.6em 0.8em;">Basic</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Browser playback</strong></td><td style="padding:0.6em 0.8em;">No native support</td><td style="padding:0.6em 0.8em;">Universal</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>HLS and DASH</strong></td><td style="padding:0.6em 0.8em;">Not used</td><td style="padding:0.6em 0.8em;">fMP4 / CMAF is the standard</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;"><strong>Recovery from truncation</strong></td><td style="padding:0.6em 0.8em;">Good (EBML cluster structure)</td><td style="padding:0.6em 0.8em;">Poor unless fragmented</td></tr>
<tr><td style="padding:0.6em 0.8em;"><strong>Best for</strong></td><td style="padding:0.6em 0.8em;">Recording, archiving, media libraries</td><td style="padding:0.6em 0.8em;">Delivery, streaming, editing, mobile</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h2 id="what-is-a-video-container">What is a video container?</h2><p>A container is defined as a file format that packages already-compressed audio, video, subtitle, and metadata streams into a single file, along with an index describing how they are timed and interleaved.</p><p>A container works by storing each stream as a series of timestamped chunks plus a table that tells a player where each chunk starts. It never inspects, compresses, or alters the media itself.</p><h3 id="container-vs-codec-stated-plainly">Container vs codec, stated plainly</h3><ul><li>The <strong>codec</strong> (H.264, H.265, AV1, VP9, AAC, Opus) decides how much the picture is compressed and therefore how it looks. This is where quality lives.</li><li>The <strong>container</strong> (MP4, MKV, WebM, MPEG-TS) decides how the compressed result is wrapped, indexed, and what else can travel alongside it.</li></ul><p>Remuxing changes the container and copies the streams through untouched. Transcoding changes the codec and re-compresses. Only the second one can change quality, and it can only make it worse.</p><h2 id="what-is-mkv">What is MKV?</h2><p>MKV is defined as the Matroska Video container, an open, royalty-free format built on the EBML (Extensible Binary Meta Language) structure and designed to hold an arbitrary number of video, audio, subtitle, and attachment tracks in one file.</p><p>MKV works by writing media into a sequence of independently parseable <strong>clusters</strong>, each carrying its own timestamps, which is why a Matroska file that was cut off mid-write usually still plays up to the truncation point.</p><h3 id="what-mkv-does-that-mp4-does-not">What MKV does that MP4 does not</h3><ul><li><strong>Subtitle formats.</strong> MKV carries SRT, ASS/SSA (styled and positioned), and bitmap formats like PGS and VobSub. MP4's subtitle support is comparatively narrow, which is why so many MP4 releases have subtitles burned into the picture instead.</li><li><strong>Unrestricted codec mixing.</strong> Matroska treats codecs opaquely, so an unusual combination works if the player supports it.</li><li><strong>Attachments.</strong> Fonts (needed for styled ASS subtitles), cover art, and arbitrary files.</li><li><strong>Crash resilience.</strong> The cluster structure means an interrupted recording is usually salvageable.</li></ul><p><strong>WebM is a restricted profile of Matroska</strong>, limited to VP8/VP9/AV1 video with Vorbis or Opus audio. That is why browsers play WebM natively but not MKV, despite the shared structure.</p><h2 id="what-is-mp4">What is MP4?</h2><p>MP4 is defined as the MPEG-4 Part 14 container, standardised as ISO/IEC 14496-14 on top of the ISO Base Media File Format (ISO/IEC 14496-12), itself derived from Apple's QuickTime format.</p><p>MP4 works by storing media in an <code>mdat</code> box and the index describing it in a <code>moov</code> box, with the whole file addressed by a tree of typed boxes ("atoms"). Every mainstream player, browser, NLE, and mobile OS reads it.</p><h3 id="the-moov-atom-and-why-it-decides-startup-time">The <code>moov</code> atom, and why it decides startup time</h3><p>This is the container detail with a real performance consequence, and no competing page on this topic covers it.</p><p>In a progressive MP4, the <code>moov</code> index is written <strong>after</strong> the media data, because its final size is not known until encoding finishes. A player streaming that file over HTTP cannot start until it has fetched the end of the file. Moving <code>moov</code> to the front ("faststart") lets playback begin as soon as the first bytes arrive.</p><pre><code class="language-bash"># Remux without re-encoding, and move the index to the front for web playback
ffmpeg -i input.mkv -c copy -movflags +faststart output.mp4
</code></pre><p><code>-c copy</code> is the important flag. It stream-copies video and audio, so this is a repackage, not a re-encode, and the picture is bit-identical.</p><h3 id="fragmented-mp4-is-what-streaming-actually-uses">Fragmented MP4 is what streaming actually uses</h3><p>Adaptive streaming does not ship whole MP4 files. It ships <strong>fragmented MP4</strong> (fMP4), where the media is split into self-contained fragments each carrying its own index. Both HLS and DASH converged on fMP4 through CMAF, so the same segments can serve both protocols. HLS originally used MPEG-TS and added fMP4 later.</p><p>MKV has no equivalent role in adaptive delivery. That is a fact about ecosystem adoption, not a limitation of the Matroska structure.</p><h2 id="mkv-vs-mp4-compatibility">MKV vs MP4 compatibility</h2><p>Compatibility is the real decision axis, and it is less absolute than most comparisons suggest.</p>
<!--kg-card-begin: html-->
<table style="width:100%; border-collapse:collapse; font-size:0.95em; min-width:520px;">
<thead>
<tr style="border-bottom:2px solid rgba(128,128,128,0.4);">
<th style="padding:0.6em 0.8em; text-align:left;">Where</th>
<th style="padding:0.6em 0.8em; text-align:left;">MKV</th>
<th style="padding:0.6em 0.8em; text-align:left;">MP4</th>
</tr>
</thead>
<tbody>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Browser <code>&lt;video&gt;</code></td><td style="padding:0.6em 0.8em;">No native support</td><td style="padding:0.6em 0.8em;">All major browsers</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">HLS and DASH delivery</td><td style="padding:0.6em 0.8em;">Not used</td><td style="padding:0.6em 0.8em;">fMP4 / CMAF segments</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">iOS and Android default players</td><td style="padding:0.6em 0.8em;">Varies, often needs VLC</td><td style="padding:0.6em 0.8em;">Native</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Video editors (NLEs)</td><td style="padding:0.6em 0.8em;">Limited, varies by product</td><td style="padding:0.6em 0.8em;">Broad</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Media servers (Plex, Jellyfin)</td><td style="padding:0.6em 0.8em;">Excellent</td><td style="padding:0.6em 0.8em;">Excellent</td></tr>
<tr style="border-bottom:1px solid rgba(128,128,128,0.25);"><td style="padding:0.6em 0.8em;">Screen recorders (OBS)</td><td style="padding:0.6em 0.8em;">Recommended default</td><td style="padding:0.6em 0.8em;">Supported, riskier</td></tr>
<tr><td style="padding:0.6em 0.8em;">YouTube upload</td><td style="padding:0.6em 0.8em;">Accepted</td><td style="padding:0.6em 0.8em;">Accepted</td></tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>That last row is worth pausing on. MKV is not universally rejected. Upload platforms transcode everything on ingest anyway, so the container you hand them rarely matters. The constraint is <strong>direct playback</strong>, not acceptance, and that is where MP4 is unbeaten.</p><h2 id="does-mkv-have-better-quality-than-mp4">Does MKV have better quality than MP4?</h2><p><strong>No, and the question is malformed.</strong> Containers do not compress anything, so a container cannot have a quality. When people observe that "the MKV looked better", one of these is true:</p><ol><li><strong>The files hold different encodes.</strong> The MKV was often produced at a higher bitrate or from a better source. That is the encoder's doing, not Matroska's.</li><li><strong>The audio differs.</strong> The MKV carried FLAC or PCM while the MP4 carried lossy AAC. That is an audio codec difference, and it is worth being precise here: <strong>MP4 also supports lossless audio.</strong> ALAC has been carried in MP4 for years, and FLAC-in-MP4 is a specified encapsulation (coding name <code>fLaC</code> in ISO-BMFF) shipped in Firefox 51+ and Chrome 62+ for MSE.</li><li><strong>Someone re-encoded during conversion.</strong> Converting MKV to MP4 with a transcode does lose quality. Remuxing with <code>-c copy</code> does not.</li></ol><h3 id="are-mkv-files-bigger-than-mp4-files">Are MKV files bigger than MP4 files?</h3><p>Usually yes in practice, and never because of the container. MKV files are commonly assembled for archival purposes with lossless or multi-channel audio, several language tracks, and subtitle streams attached. Strip a file down to one video and one audio track and the container overhead difference is negligible against a multi-gigabyte payload.</p><h2 id="when-to-use-mkv">When to use MKV</h2><ul><li>Recording software output, where a crash or power loss should not destroy the take.</li><li>Archival masters holding lossless audio, several languages, and styled subtitles.</li><li>Home media libraries served by Plex or Jellyfin, which handle Matroska well.</li><li>Any workflow where you want to keep every track rather than choose between them.</li></ul><p><strong>Not for:</strong> anything a browser has to play, and anything entering an HLS or DASH pipeline.</p><h2 id="when-to-use-mp4">When to use MP4</h2><ul><li>Web and mobile delivery, where it is the only universally decodable option.</li><li>HLS and DASH packaging, via fMP4 and CMAF segments.</li><li>Editing handoffs, where NLE support is broadest.</li><li>DRM-protected distribution, where the common encryption schemes are defined against ISO BMFF.</li><li>Recording outputs meant to be shared or embedded without a conversion step.</li></ul><p><strong>Not for:</strong> long-term archival masters with many tracks, or unattended long-duration recording where truncation is a real risk.</p><h2 id="how-to-convert-between-them-without-losing-quality">How to convert between them without losing quality</h2><pre><code class="language-bash"># MKV to MP4, no re-encode (fails if a stream is not MP4-compatible, e.g. ASS subtitles)
ffmpeg -i input.mkv -c copy -movflags +faststart output.mp4

# Drop incompatible subtitle tracks, keep video and audio untouched
ffmpeg -i input.mkv -map 0:v -map 0:a -c copy -movflags +faststart output.mp4

# MP4 to MKV, no re-encode
ffmpeg -i input.mp4 -c copy output.mkv
</code></pre><p>If <code>-c copy</code> fails, the cause is nearly always a stream MP4 cannot carry, usually ASS/SSA subtitles or an unusual audio codec. Drop or convert that stream rather than re-encoding the video.</p><h2 id="error-resilience-what-happens-when-a-recording-is-cut-off">Error resilience: what happens when a recording is cut off</h2><p>This is the one area where the container structure produces a genuinely different outcome, and it is why recording software so often defaults to MKV.</p><p>MKV writes media as a sequence of <strong>clusters</strong>, each independently parseable and carrying its own timestamps. A Matroska file whose writer was killed mid-recording usually plays right up to the point of truncation, because every cluster already written is self-describing.</p><p>A progressive MP4 stores its index in the <code>moov</code> box, written only when recording finishes. Kill the writer first and there is no index, so most players see an unplayable file even though the media data is sitting intact in <code>mdat</code>. Recovery tools exist, and they work by reconstructing the index from a reference file recorded with identical settings.</p><p>Fragmented MP4 closes this gap, since each fragment carries its own index, which is why it is used for live streaming. It is not what a default "record to MP4" setting produces.</p><h2 id="mkv-vs-mp4-for-obs-and-screen-recording">MKV vs MP4 for OBS and screen recording</h2><p>Record to MKV, then remux to MP4 when you are done. This is OBS's own guidance, and the reasoning is the truncation behaviour above: a crash, a power loss, or a full disk during a long recording destroys an in-progress MP4 and costs you only the final seconds of an MKV.</p><p>The remux is free. It is a container swap, not a re-encode:</p><pre><code class="language-bash">ffmpeg -i recording.mkv -c copy -movflags +faststart recording.mp4
</code></pre><p>The output is bit-identical video with the index moved to the front for fast web playback.</p><p>The same logic applies to any unattended long-duration capture: lecture recording, surveillance, conference capture, multi-hour game sessions. Record in the resilient container, deliver in the compatible one.</p><h2 id="definitions-glossary">Definitions glossary</h2><blockquote><strong>Container:</strong> A file format that packages compressed audio, video, subtitle, and metadata streams with an index describing their timing. It performs no compression and cannot affect quality.</blockquote><blockquote><strong>Codec:</strong> The compression algorithm inside the container (H.264, H.265, AV1, AAC, Opus). This is the layer that decides how the video actually looks.</blockquote><blockquote><strong>Remux:</strong> Changing the container while copying the compressed streams through untouched (<code>ffmpeg -c copy</code>). Output video is bit-identical to the input.</blockquote><blockquote><strong>Transcode:</strong> Decoding and re-encoding the media. This changes the codec or bitrate and always loses some quality relative to the source.</blockquote><blockquote><strong><code>moov</code> atom:</strong> The MP4 index box describing stream layout and timing. Written at the end of the file by default, which delays playback start until it has been fetched.</blockquote><blockquote><strong>fMP4 / CMAF:</strong> Fragmented MP4, where media is split into self-contained segments each carrying its own index. The common segment format underlying both HLS and DASH.</blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>MKV and MP4 are containers. Neither compresses video, so neither determines quality. The codec and bitrate inside the file decide how it looks.</li><li>MP4 is the only realistic choice for delivery. Browsers have no native MKV playback, and HLS and DASH are both built on fragmented MP4 through CMAF.</li><li>MKV wins for recording and archiving, because its cluster structure survives truncation and it carries styled subtitles, unlimited tracks, and attachments that MP4 cannot.</li><li>Converting between them with <code>ffmpeg -c copy</code> is a repackage, not a re-encode, and changes nothing about the video. Only a transcode loses quality.</li><li>The claim that lossless audio requires MKV is inaccurate. MP4 carries ALAC, and FLAC-in-MP4 is a specified encapsulation supported in Firefox 51+ and Chrome 62+.</li></ul><h2 id="you-may-not-have-to-make-this-choice">You may not have to make this choice</h2><p>For session recording, the container decision is usually made by your infrastructure rather than by you, and that is the right outcome. Recordings exist to be watched, shared, and embedded, which is exactly the job MP4 is unbeaten at.</p><p>VideoSDK's Composer encodes to MP4, or to HLS or RTMP for live output. A recorded session arrives in the container browsers, editors, and mobile players already read, with no remux step and no <code>moov</code> atom surprise on playback.</p><pre><code class="language-bash">curl 	-H 'Authorization: $YOUR_TOKEN' \ 
	-H 'Content-Type: application/json' \ 
	-d '{
	"roomId": "abcd-efgh-ijkl",
	"templateUrl": "https://www.example.com/?token=token&amp;meetingId=74v5-v21l-n1ey&amp;participantId=RECORDER_ID",
	"transcription": "transcriptionObj",
	"config": "configObj",
	"webhookUrl": "https://www.example.com/",
	"awsDirPath": "s3path",
	"preSignedUrl": "preSignedUrl"
}' \ 
	-XPOST https://api.videosdk.live/v2/recordings/start
</code></pre><p>Only <code>roomId</code> is required. Everything in <code>config</code> is optional, and <code>quality</code> maps to SD, HD, and Full HD across <code>low</code>, <code>med</code>, and <code>high</code>.</p><h3 id="where-to-go-next">Where to go next</h3><ul><li><a href="https://docs.videosdk.live/api-reference/realtime-communication/start-recording"><strong>Start recording API reference</strong></a> covers the full request body, including <code>transcription</code>, <code>webhookUrl</code>, and the pre-signed URL options for delivering the finished file.</li><li><a href="https://docs.videosdk.live/docs/tutorials/user-dashboard/recording-storage-config"><strong>Recording storage configuration</strong></a> points recordings at your own storage provider instead of the default.</li><li><a href="https://docs.videosdk.live/docs/tutorials/customized-layout"><strong>Customized layout</strong></a> controls what the Composer actually captures before it encodes.</li><li><a href="https://discord.gg/Gpmj6eCq5u"><strong>Discord</strong></a> if you hit a playback or container question that a doc page does not answer.</li></ul><p><a href="https://app.videosdk.live/login" rel="noreferrer">Start building free with $20 in credit</a></p><p>Do you record to MKV and remux, or write MP4 directly and accept the risk? Drop a comment, the answer usually depends on how long the capture runs.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h3 id="is-mkv-better-quality-than-mp4">Is MKV better quality than MP4?</h3><p>No. Both are containers and neither compresses video, so neither affects the picture. Quality comes from the codec and bitrate inside the file. An MKV and an MP4 holding the same H.264 stream at the same bitrate are visually identical.</p><h3 id="is-mkv-or-mp4-better-for-streaming">Is MKV or MP4 better for streaming?</h3><p>MP4, without qualification. Browsers have no native MKV playback, and HLS and DASH are built on fragmented MP4 through CMAF. MKV has no role in adaptive bitrate delivery, so any streaming pipeline fed an MKV will repackage it to MP4 first.</p><h3 id="does-converting-mkv-to-mp4-improve-quality">Does converting MKV to MP4 improve quality?</h3><p>No, and it can reduce it. If the conversion re-encodes, the output inherits the source's artifacts and adds new ones. If it remuxes with <code>ffmpeg -c copy</code>, the video is bit-identical and quality is unchanged. Conversion is a compatibility operation, never a quality one.</p><h3 id="why-are-mkv-files-often-larger-than-mp4-files">Why are MKV files often larger than MP4 files?</h3><p>Because of what is usually put inside them, not the format. MKV files are commonly built for archiving with lossless audio, multiple language tracks, and subtitle streams. Container overhead is negligible; the extra tracks are the size difference.</p><h3 id="can-mp4-hold-lossless-audio">Can MP4 hold lossless audio?</h3><p>Yes. MP4 carries ALAC, and FLAC-in-MP4 is a specified encapsulation supported in Firefox 51+ and Chrome 62+. The common claim that lossless audio requires MKV is inaccurate; the real constraint is which codecs your target players decode.</p><h3 id="what-is-the-difference-between-mkv-and-webm">What is the difference between MKV and WebM?</h3><p>WebM is a restricted profile of Matroska limited to VP8, VP9, or AV1 video with Vorbis or Opus audio. That restriction is exactly why browsers play WebM natively but not general MKV: the set of codecs a WebM file can contain is guaranteed in advance.</p><h3 id="which-container-should-i-record-video-calls-in">Which container should I record video calls in?</h3><p>MP4, in almost every case, because a session recording exists to be watched, shared, or embedded rather than archived with multiple tracks. If you are running long unattended captures where a crash would destroy the file, record to MKV and remux to MP4 on completion.</p>]]></content:encoded></item><item><title><![CDATA[What is Interactive Live Streaming? How to Build It in 2026]]></title><description><![CDATA[This guide covers the architecture, working React code for host and viewer modes, multi streaming, and the cost crossover that decides your design.]]></description><link>https://www.videosdk.live/blog/interactive-live-streaming</link><guid isPermaLink="false">6a8ed31fb3240feb748c9947</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 26 Aug 2026 13:41:13 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-27--2026--11_04_38-AM.png" medium="image"/><content:encoded><![CDATA[<blockquote>Interactive live streaming is live video where the audience can respond and join the broadcast in real time, not just watch it. It runs on WebRTC rather than HLS, which holds latency under one second. VideoSDK implements it with two participant modes, <code>SEND_AND_RECV</code> for hosts and <code>RECV_ONLY</code> for viewers, switched at runtime with <code>changeMode()</code>.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-27--2026--11_04_38-AM.png" alt="What is Interactive Live Streaming? How to Build It in 2026"/><p>The gap between "live" and "interactive" is roughly 20 seconds of latency. A standard HLS stream reaches viewers 12 to 30 seconds after the camera captures it, which is fine for a keynote and useless for an auction, a quiz, or a shopping stream where someone asks a question and expects an answer.</p><p>That delay is a protocol problem, not a bandwidth problem. Interactive live streaming solves it by moving the delivery path off HTTP chunking and onto <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a>, then adding a role system so a viewer can become a broadcaster without rejoining.</p><p>This guide covers what interactive live streaming actually is, how the architecture works, and the six steps to build it with the VideoSDK React SDK, including the cost math that decides when you should use it and when plain HLS is the better call.</p><h2 id="what-is-interactive-live-streaming">What Is Interactive Live Streaming?</h2><p><a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">Interactive live streaming</a> is defined as live video delivery in which viewers can send data or media back to the broadcast while it is happening, and can be promoted to broadcaster mid-stream.</p><p>Interactive live streaming works by publishing each host's audio and video into a <a href="https://www.videosdk.live/blog/sfu-vs-mcu-vs-mesh-webrtc" rel="noreferrer">Selective Forwarding Unit (SFU)</a>, which forwards those tracks to every subscribed viewer without transcoding them. Because the media is never chunked into segments and written to a CDN, glass-to-glass latency typically lands in the 200ms to 500ms range instead of the 12 to 30 seconds a standard <a href="https://www.videosdk.live/developer-hub/hls/video-streaming-protocols-guide" rel="noreferrer">HLS</a> workflow produces.</p><p>VideoSDK provides interactive live streaming through the same rooms-based SDK surface as its video calling API, so a stream is a room where most participants have publishing disabled. Its documentation states support for up to 100 hosts and co-hosts alongside 2,000 real-time viewers in a single interactive session. </p><p>The word doing the work in that definition is "back." Traditional live streaming is a one-way pipe with a chat widget bolted alongside it. The chat is real time, the video is not, and the two drift apart. Interactive live streaming puts both on the same transport so they stay in sync.</p><h3 id="what-makes-a-stream-interactive-rather-than-just-live">What Makes a Stream Interactive Rather Than Just Live</h3><p>Four capabilities separate the two, and a platform needs all four:</p><ul><li><strong>Sub-second latency</strong>, so a spoken question and its answer stay in the same conversational beat</li><li><strong>Bidirectional media</strong>, so a viewer's camera and microphone can join the stage</li><li><strong>Runtime role changes</strong>, so promotion happens without a reconnect or a page reload</li><li><strong>A synchronized data channel</strong> for chat, polls, reactions, and Q&amp;A that shares the stream's clock</li></ul><p>Drop any one of those and you have live streaming with extra features, not interactive live streaming.</p><h2 id="how-interactive-live-streaming-works-under-the-hood">How Interactive Live Streaming Works Under the Hood</h2><p>Every interactive stream is an SFU forwarding published tracks to subscribers, with a permission layer deciding who may publish.</p><h3 id="the-sfu-is-why-latency-stays-under-a-second">The SFU Is Why Latency Stays Under a Second</h3><p>A Selective Forwarding Unit receives each publisher's encoded media and routes the packets to subscribers without decoding or re-encoding them. That single design choice is where the latency budget comes from. An MCU, by contrast, mixes streams server-side into one composite, which adds an encode cycle and hundreds of milliseconds.</p><p>Segment-based protocols pay a different tax. HLS cuts video into files, writes them to an origin, propagates them to a CDN, and asks the player to buffer two or three segments before playback starts. Each of those stages is a queue, and queues are latency.</p><p>According to the WebRTC specification maintained by the <a href="https://www.w3.org/TR/webrtc/" rel="noreferrer">W3C</a>, the transport is built on <a href="https://www.videosdk.live/developer-hub/rtmp/rtp-streaming" rel="noreferrer">SRTP</a> over UDP with congestion control, which is what allows packets to be forwarded the moment they arrive instead of after a segment boundary. </p><h3 id="roles-are-just-publish-permissions">Roles Are Just Publish Permissions</h3><p>In VideoSDK's model, a participant joins a room in one of two modes. <code>SEND_AND_RECV</code> allows publishing audio and video and receiving everyone else's. <code>RECV_ONLY</code> subscribes to the stream without ever acquiring the device's camera or microphone.</p><p>This matters for cost and for battery. A <code>RECV_ONLY</code> participant never opens a media device and never uploads, so a viewer on mobile is doing roughly the work of a video player rather than the work of a call participant.</p><p>Older VideoSDK SDK versions named these modes <code>CONFERENCE</code> and <code>VIEWER</code>. If you are following a tutorial that uses those constants, you are on an older major version.</p><h3 id="where-hls-still-belongs-in-the-stack">Where HLS Still Belongs in the Stack</h3><p>Interactive delivery and mass delivery are different problems, and production streams usually run both at once. Hosts and the interactive tier of the audience sit on WebRTC. Everyone beyond that tier watches an <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/integrate-hls/start-hls" rel="noreferrer">HLS</a> rendition generated from the same room.</p><p>The hybrid is not a compromise. It is the standard shape of a large interactive broadcast, and the next section explains why the economics force it.</p><h2 id="ils-vs-hls-vs-rtmp-latency-and-scale-compared">ILS vs HLS vs RTMP: Latency and Scale Compared</h2><p>The three protocols are not competitors, they are three positions on a latency-versus-scale curve, and most production systems use at least two of them.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Protocol</th>
<th>Typical latency</th>
<th>Audience ceiling</th>
<th>Viewer can publish back</th>
<th>Best for</th>
</tr>
</thead>
<tbody>
<tr>
<td>Interactive live streaming (WebRTC/SFU)</td>
<td>200 to 500 ms</td>
<td>Thousands per session</td>
<td>Yes, via role change</td>
<td>Auctions, live shopping, tutoring, Q&amp;A</td>
</tr>
<tr>
<td>Low-Latency HLS (LL-HLS)</td>
<td>2 to 7 seconds</td>
<td>CDN scale, effectively unlimited</td>
<td>No</td>
<td>Sports, betting overlays, large webinars</td>
</tr>
<tr>
<td>Standard HLS</td>
<td>12 to 30 seconds</td>
<td>CDN scale, effectively unlimited</td>
<td>No</td>
<td>Keynotes, concerts, linear-style broadcast</td>
</tr>
<tr>
<td>RTMP (ingest and multistreaming)</td>
<td>2 to 5 seconds to platform</td>
<td>Depends on destination</td>
<td>No</td>
<td>Pushing your stream to YouTube, Twitch, LinkedIn</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Apple's Low-Latency HLS extension targets a stream delay of two seconds or less, though AWS Elemental's published analysis of the protocol notes that real-world workflows commonly land between three and seven seconds once player buffering is included. </p><p>The row that decides most architectures is the third column. LL-HLS closes much of the latency gap, but it cannot make a viewer a broadcaster. If your product needs a viewer on stage, no amount of HLS tuning gets you there.</p><h2 id="what-a-live-streaming-api-must-handle">What a Live Streaming API Must Handle</h2><p>A live streaming API is judged on the parts that only appear under load, not on how fast the first stream connects.</p><p>Before choosing one, confirm it handles these:</p><ol><li><strong>Server-side token issuance</strong> with scoped permissions, so a viewer token cannot publish media</li><li><strong>Runtime role changes</strong> without a reconnect, so promotion does not drop the viewer's playback</li><li><strong>Simulcast or adaptive bitrate</strong>, so a viewer on 3G gets a lower rendition instead of a frozen frame</li><li><strong>An HLS or CDN fallback path</strong> from the same session, so audience growth does not require re-architecture</li><li><strong>RTMP output</strong> for multistreaming to external platforms</li><li><strong>Reconnection semantics</strong> you can actually observe, with events for participant drop and rejoin</li></ol><p>That fourth point is the one teams discover late. Building on a real-time-only API and then needing 50,000 concurrent viewers means adding a transcoding pipeline under deadline.</p><p>VideoSDK exposes all six through one SDK surface across React, React Native, JavaScript, Flutter, Android, iOS, and Python, which is the practical reason to prefer it over stitching a WebRTC SFU to a separate packaging service. </p><h2 id="how-to-build-a-live-streaming-app-with-videosdk-in-react">How to build a Live Streaming app with VideoSDK in React</h2><p><strong>VideoSDK</strong> empowers you to seamlessly integrate <strong>interactive live streaming</strong> features into your React application in minutes. While built for meetings, the SDK is easily adaptable for live streaming with support for up to <strong>100 hosts/co-hosts</strong> and <strong>2,000 viewers</strong> in <strong>real-time</strong>. Perfect for social use cases, this guide will walk you through integrating live streaming into your app.</p><blockquote>info: For standard live streaming with 6-7 second latency and playback support, follow this <a>documentation</a>.<br/></blockquote><h3 id="prerequisites">Prerequisites</h3><p>Before proceeding, ensure that your development environment meets the following requirements:</p><ul><li>Video SDK Developer Account (Not having one, follow <a href="https://app.videosdk.live/"><strong>Video SDK Dashboard</strong></a>)</li><li>Basic understanding of React</li><li><a href="https://www.npmjs.com/package/@videosdk.live/react-sdk"><strong>React VideoSDK</strong></a></li><li>Have Node and NPM installed on your device.</li><li>Basic understanding of Hooks (useState, useRef, useEffect)</li><li>React Context API (optional)</li></ul><h2 id="getting-started-with-the-code">Getting Started with the Code!</h2><p>Follow the steps to create the environment necessary to add live streaming into your app. You can also find the code sample for <a href="https://github.com/videosdk-live/quickstart/tree/main/interactive-live-streaming/react-ils">quickstart here</a>.</p><h2 id="create-new-react-app">Create new react app</h2><p>Create a new React App using the below command.</p><pre><code class="language-bash"> npm create vite@latest videosdk-ils-react-app -- --template react
 cd videosdk-ils-react-app
</code></pre><h2 id="install-video-sdk">Install Video SDK</h2><p>Install the VideoSDK using the below-mentioned npm command. Make sure you are in your react app directory before you run this command.</p><p><strong>npm:</strong></p><pre><code class="language-bash">npm install "@videosdk.live/react-sdk"
</code></pre><p><strong>yarn:</strong></p><pre><code class="language-bash">yarn add "@videosdk.live/react-sdk"
</code></pre><h2 id="structure-of-the-project">Structure of the project</h2><p>Your project structure should look like this.</p><pre><code class="language-jsx">   root
   ├── node_modules
   ├── public
   ├── src
   │    ├── API.js
   │    ├── App.jsx
   │    ├── App.css
   │    ├── main.jsx
   ├── package.json
   .    .
</code></pre><p>You are going to use functional components to leverage react's reusable component architecture. There will be components for users, videos, and controls (mic, camera, leave) over the video.</p><p>You will be working on these files:</p><ul><li>API.js: Responsible for handling API calls such as generating unique streamId and token</li><li>App.jsx: Responsible for rendering container and joining the Live Stream.</li></ul><h3 id="step-1-get-started-with-apijs">Step 1: Get started with API.js</h3><p>Prior to moving on, you must create an API request to generate a unique streamId. You will need an authentication token, which you can create either through the <a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples">videosdk-rtc-api-server-examples</a> or directly from the <a href="https://app.videosdk.live/api-keys">VideoSDK Dashboard</a> for developers.</p><pre><code class="language-js">// Generate your token at https://app.videosdk.live/api-keys and paste it below.
//highlight-next-line
export const authToken = "";

// API call to create stream
export const createStream = async ({ token }) =&gt; {
  try {
    const res = await fetch(`https://api.videosdk.live/v2/rooms`, {
      method: "POST",
      headers: {
        authorization: `${token}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({}),
    });

    if (!res.ok) {
      throw new Error(`Failed to create stream: ${res.status}`);
    }

    //highlight-next-line
    const { roomId } = await res.json();
    return roomId;
  } catch (error) {
    console.error("createStream failed", error);
    throw error;
  }
};
</code></pre><h3 id="step-2-initialize-and-join-the-live-stream">Step 2: Initialize and Join the Live Stream</h3><p>To set up the wireframe of App.jsx, you'll use VideoSDK Hooks and Context Providers, which include:</p><ul><li><strong>MeetingProvider</strong>: The context provider for managing live streams. Accepts config and token as props and makes them accessible to all nested components.</li><li><strong>useMeeting</strong>: A hook providing APIs to manage live streams, like joining, leaving, and toggling the mic or webcam.</li><li><strong>useParticipant</strong>: A hook to handle properties and events for a specific participant, such as their name, webcam, and mic streams.</li></ul><p>Before proceeding, let's understand the two modes of a Live Stream:</p><h6 id="1-sendandrecv-for-host-or-co-host">1. SEND_AND_RECV (For Host or Co-host):</h6><ul><li>Designed primarily for the Host or Co-host.</li><li>Allows sending and receiving media.</li><li>Hosts can broadcast their audio/video and interact directly with the audience.</li></ul><h6 id="2-recvonly-for-audience">2. RECV_ONLY (For Audience):</h6><ul><li>Tailored for the Audience.</li><li>Enables receiving media shared by the Host.</li></ul><p>Audience members can view and listen but cannot share their own media.</p><figure class="kg-card kg-image-card"><img src="https://cdn.videosdk.live/website-resources/docs-resources/ils_mode_demonstration-compressed.jpg" class="kg-image" alt="What is Interactive Live Streaming? How to Build It in 2026" loading="lazy" width="3059" height="2597"/></figure><p>The Join Screen allows users to either create a new Live Stream or join an existing one as a host or audience, using these actions:</p><ol><li><code><strong>Join as Host</strong></code>: Allows the user to join an existing Live Stream using the provided streamId with the <code>SEND_AND_RECV</code> mode, enabling full host privileges.</li><li><code><strong>Join as Audience</strong></code>: Enables the user to join an existing Live Stream using the provided streamId with the <code>RECV_ONLY</code> mode, allowing view-only access.</li><li><code><strong>Create Live Stream as Host</strong></code>: Lets the user initiate a new Live Stream in <code>SEND_AND_RECV</code> mode, granting full host controls.</li></ol><pre><code class="language-js">import "./App.css";
import React, { useEffect, useRef, useState } from "react";


// Join Screen - Handles joining or creating a stream
function JoinView({ initializeStream, setMode }) {
  const [streamId, setStreamId] = useState("");

  const handleAction = async (mode) =&gt; {
    // Sets the mode (Host or Audience) and initializes the stream
    setMode(mode);
    await initializeStream(streamId);
  };

  return (
    &lt;div className="container"&gt;
      {/* Button to create a new stream */}
      &lt;button onClick={() =&gt; handleAction(Constants.modes.SEND_AND_RECV)}&gt;
        Create Live Stream as Host
      &lt;/button&gt;
      {/* Input field for entering an existing Stream ID */}
      &lt;input
        type="text"
        placeholder="Enter Stream Id"
        onChange={(e) =&gt; setStreamId(e.target.value)}
      /&gt;
      {/* Button to join as a host */}
      &lt;button onClick={() =&gt; handleAction(Constants.modes.SEND_AND_RECV)}&gt;
        Join as Host
      &lt;/button&gt;
      {/* Button to join as an audience member */}
      &lt;button onClick={() =&gt; handleAction(Constants.modes.RECV_ONLY)}&gt;
        Join as Audience
      &lt;/button&gt;
    &lt;/div&gt;
  );
}

// Live Stream Container - Placeholder for the live stream container
function LSContainer(props) {
  return null;
}

// Main App Component - Handles the app flow and live stream lifecycle
function App() {
  const [streamId, setStreamId] = useState(null); // Holds the current stream ID
  const [mode, setMode] = useState(Constants.modes.SEND_AND_RECV); // Holds the current user mode (Host or Audience)

  const initializeStream = async (id) =&gt; {
    if (!authToken) {
      console.error("PLEASE PROVIDE TOKEN IN API.js FROM app.videosdk.live");
      return;
    }
    // Creates a new stream if no ID is provided or uses the given stream ID
    const newStreamId = id || (await createStream({ token: authToken }));
    setStreamId(newStreamId);
  };

  const onStreamLeave = () =&gt; setStreamId(null); // Resets the stream state on leave

  return authToken &amp;&amp; streamId ? (
    // Provides the stream context to the application
    
    &lt;/MeetingProvider&gt;
  ) : (
    // Renders the join view if no stream is active
    
  );
}

export default App;
</code></pre><h3 id="step-3-setting-up-live-stream-view-and-container">Step 3: Setting Up Live Stream View and Container</h3><p>This step implements the Live Stream View and Container components to manage and display HOST participants:</p><ol><li>StreamView Component:<ul><li>Displays participants in <code>SEND_AND_RECV</code> mode using the Participant component.</li><li>Includes LSControls for managing the session.</li></ul></li><li>LSContainer Component:<ul><li>Manages joining the stream via join from useMeeting.</li><li>Shows the StreamView after joining or a <code>Join Stream</code> button otherwise.</li></ul></li></ol><pre><code class="language-js">// Component to manage live stream container and session joining
function LSContainer({ streamId, onLeave }) {
  const [joined, setJoined] = useState(false); // Track if the user has joined the stream

  const { join } = useMeeting({
    onMeetingJoined: () =&gt; setJoined(true), // Set `joined` to true when successfully joined
    onMeetingLeft: onLeave, // Handle the leave stream event
    onError: (error) =&gt; alert(error.message), // Display an alert on encountering an error
  });

  const handleJoin = async () =&gt; {
    try {
      await join();
    } catch (error) {
      console.error("Failed to join stream", error);
    }
  };

  return (
    &lt;div className="container"&gt;
      &lt;h3&gt;Stream Id: {streamId}&lt;/h3&gt;
      {/* Show the stream view if joined, otherwise display the "Join Stream" button */}
      {joined ? (
        
      ) : (
        &lt;button onClick={handleJoin}&gt;Join Stream&lt;/button&gt;
      )}
    &lt;/div&gt;
  );
}

// Component to display the live stream view
function StreamView() {
  const { participants } = useMeeting(); // Access participants using the VideoSDK useMeeting hook

  return (
    &lt;div&gt;
       {/* Render live stream controls */}
      {[...participants.values()]
        .filter((p) =&gt; p.mode === Constants.modes.SEND_AND_RECV) // Filter participants in SEND_AND_RECV mode
        .map((p) =&gt; (
           // Render each participant's view
        ))}
    &lt;/div&gt;
  );
}

function Participant() {
  return null;
}

function LSControls() {
  return null;
}
</code></pre><h3 id="step-4-render-individual-participants-view">Step 4: Render Individual Participant's View</h3><p>This step component displays an individual participant's audio and video streams. It uses the <code>useParticipant</code> hook to retrieve the participant's data (e.g., webcam and mic status) and dynamically sets up the streams with <code>useEffect</code>. Audio and video elements are rendered based on the availability of the streams.</p><pre><code class="language-js">// Component to render audio and video streams for a participant
function Participant({ participantId }) {
  const { webcamStream, micStream, webcamOn, micOn, isLocal, displayName } =
    useParticipant(participantId);

  const audioRef = useRef(null); // Reference for audio element
  const videoRef = useRef(null); // Reference for video element

  // Function to attach or clear the stream
  const setupStream = (stream, ref, condition) =&gt; {
    if (ref.current &amp;&amp; stream) {
      ref.current.srcObject = condition
        ? new MediaStream([stream.track])
        : null;
      condition &amp;&amp; ref.current.play().catch(console.error);
    }
  };

  useEffect(() =&gt; setupStream(micStream, audioRef, micOn), [micStream, micOn]); // Handle mic stream
  useEffect(
    () =&gt; setupStream(webcamStream, videoRef, webcamOn),
    [webcamStream, webcamOn]
  ); // Handle webcam stream

  return (
    &lt;div&gt;
      &lt;p&gt;
        {displayName} | Webcam: {webcamOn ? "ON" : "OFF"} | Mic:{" "}
        {micOn ? "ON" : "OFF"}
      &lt;/p&gt;
      &lt;audio ref={audioRef} autoPlay muted={isLocal} /&gt; {/* Play mic stream */}
      {webcamOn &amp;&amp; (
        &lt;video
          ref={videoRef}
          autoPlay
          muted={isLocal}
          height="200"
          width="300"
        /&gt; /* Display webcam stream */
      )}
    &lt;/div&gt;
  );
}
</code></pre><h3 id="step-5-implement-live-stream-controls">Step 5: Implement Live Stream Controls</h3><p>This step provides buttons to leave the stream, toggle the microphone and camera, and switch between <code>Host Mode</code> (send/receive streams) and <code>Audience Mode</code> (receive streams only). It uses <code>useMeeting</code> to access these functionalities.</p><p>From v1.0.0, all these methods are asynchronous and return a Promise, so <code>await</code> them and handle failures with <code>try</code> / <code>catch</code>. For details, see the <a href="http://blogs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/migration-guide">Migration Guide</a>.</p><pre><code class="language-js">// Component for managing stream controls
function LSControls() {
  const { leave, toggleMic, toggleWebcam, changeMode, meeting } = useMeeting(); // Access methods
  const currentMode = meeting.localParticipant.mode; // Get the current participant's mode

  const handleLeave = async () =&gt; {
    try {
      await leave();
    } catch (error) {
      console.error("Failed to leave stream", error);
    }
  };

  const handleToggleMic = async () =&gt; {
    try {
      await toggleMic();
    } catch (error) {
      console.error("Failed to toggle mic", error);
    }
  };

  const handleToggleWebcam = async () =&gt; {
    try {
      await toggleWebcam();
    } catch (error) {
      console.error("Failed to toggle webcam", error);
    }
  };

  const handleChangeMode = async () =&gt; {
    const nextMode =
      currentMode === Constants.modes.SEND_AND_RECV
        ? Constants.modes.RECV_ONLY
        : Constants.modes.SEND_AND_RECV;
    try {
      await changeMode(nextMode);
    } catch (error) {
      console.error("Failed to change mode", error);
    }
  };

  return (
    &lt;div className="controls"&gt;
      {/* Button to leave the stream */}
      &lt;button onClick={handleLeave}&gt;Leave&lt;/button&gt;

      {/* Show mic and webcam toggles if in SEND_AND_RECV mode */}
      {currentMode === Constants.modes.SEND_AND_RECV &amp;&amp; (
        &lt;&gt;
          &lt;button onClick={handleToggleMic}&gt;Toggle Mic&lt;/button&gt;{" "}
          {/* Mute/unmute mic */}
          &lt;button onClick={handleToggleWebcam}&gt;Toggle Camera&lt;/button&gt;{" "}
          {/* Enable/disable Camera */}
        &lt;/&gt;
      )}

      {/* Button to switch between Host Mode and Viewer Mode */}
      &lt;button onClick={handleChangeMode}&gt;
        {currentMode === Constants.modes.SEND_AND_RECV
          ? "Switch to Audience Mode"
          : "Switch to Host Mode"}
      &lt;/button&gt;
    &lt;/div&gt;
  );
}
</code></pre><blockquote>Tip: You can checkout the complete <a href="https://github.com/videosdk-live/quickstart/tree/main/interactive-live-streaming/react-ils">quick start example here</a>.</blockquote><h3 id="common-errors-and-fixes">Common Errors and Fixes</h3><p><strong>Invalid token / 401 on join.</strong> The token expired, or it was signed with the wrong secret. Tokens are short-lived by design. Fetch a fresh one on every join rather than caching it in <code>localStorage</code>.</p><p><strong><code>changeMode()</code> resolves but no video appears.</strong> The browser never got camera permission because the participant joined as <code>RECV_ONLY</code> and no device prompt fired. Call <code>toggleWebcam()</code> after the mode change and handle the permission rejection.</p><p><strong>Stream works on localhost, fails on the staging domain.</strong> <code>getUserMedia</code> requires a secure context. Any origin other than <code>localhost</code> needs HTTPS.</p><p><strong>Viewers on corporate networks never connect.</strong> UDP is blocked and the client is not falling back to <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a> over TCP/443. Test on a restricted network before launch, not after.</p><h2 id="what-changes-when-you-go-to-production">What Changes When You Go to Production</h2><p>The interactive tier bills per viewer minute and the HLS tier bills per stream minute, which is the single fact that shapes production architecture.</p><h3 id="the-cost-crossover-with-real-numbers">The Cost Crossover, With Real Numbers</h3><p><a href="https://www.videosdk.live/pricing" rel="noreferrer">VideoSDK's published rates</a> put HD (720p) interactive video at $0.002 per viewer minute and HLS 720p encoding at $0.04 per livestream minute. </p><p>Run the math on a one-hour stream:</p><ul><li><strong>Interactive tier:</strong> $0.002 × 60 minutes = $0.12 per viewer, so 1,000 concurrent viewers costs roughly $120 for the hour</li><li><strong>HLS encoding:</strong> $0.04 × 60 minutes = $2.40 for the hour, flat, whether 20 people watch or 20,000</li></ul><p>The crossover sits around 20 concurrent HD viewers. Past that point, every additional interactive viewer is a marginal cost and every additional HLS viewer is close to free on the encoding line. Note that CDN delivery for HLS viewers is billed separately from encoding, so the true crossover is somewhat higher than 20. </p><p>The design conclusion is concrete: keep the interactive tier small and deliberate. A live shopping stream does not need 5,000 people able to speak. It needs 5,000 people watching and 10 able to come on camera.</p><h3 id="production-checklist-most-tutorials-skip">Production Checklist Most Tutorials Skip</h3><ul><li><strong>Token refresh:</strong> rotate before expiry mid-stream rather than letting a two-hour broadcast die at minute 121</li><li><strong>TURN over TCP/443:</strong> required for viewers behind restrictive firewalls</li><li><strong>Reconnection handling:</strong> subscribe to participant-left and rejoin events, and hold the UI slot for a few seconds instead of tearing the tile down instantly</li><li><strong>Recording:</strong> start it server-side so it does not depend on the host's tab staying open</li><li><strong>Simulcast:</strong> confirm it is enabled, or one viewer on a weak connection degrades the encode for everyone</li></ul><h2 id="where-interactive-live-streaming-falls-short">Where Interactive Live Streaming Falls Short</h2><p>Interactive live streaming is the wrong choice when nobody in the audience will ever speak.</p><p>Three honest limitations:</p><p><strong>Cost scales with viewers, not with time.</strong> A passive audience on WebRTC is money spent on a capability nobody uses. Route them to HLS.</p><p><strong>Browser playback is less forgiving.</strong> HLS players handle network drops, seeking, and background tabs with years of hardening behind them. WebRTC playback in a browser tab that gets backgrounded on mobile can suspend.</p><p><strong>Reach beyond the SFU needs a second path.</strong> Real-time delivery to hundreds of thousands of concurrent viewers means CDN distribution, which means accepting segment latency for that tier. VideoSDK's documented real-time ceiling is 2,000 viewers per interactive session, with HLS handling the rest.</p><p>If your use case is a concert broadcast or a recorded-style keynote, standard HLS is cheaper, simpler, and better supported. Use interactivity where interaction is the product.</p><h2 id="key-terms-in-interactive-live-streaming">Key Terms in Interactive Live Streaming</h2><blockquote><strong>Interactive Live Streaming (ILS):</strong> Live video where viewers can send media or data back to the broadcast in real time and be promoted to broadcaster mid-session. VideoSDK implements it through participant modes on a standard room.</blockquote><blockquote><strong>SFU (Selective Forwarding Unit):</strong> A media server that forwards each publisher's encoded stream to subscribers without decoding it. Avoiding the re-encode is what keeps WebRTC latency in the 200ms to 500ms range.</blockquote><blockquote><strong><code>SEND_AND_RECV</code> / <code>RECV_ONLY</code>:</strong> VideoSDK's two participant modes. The first publishes and subscribes (host or co-host), the second only subscribes (viewer). <code>changeMode()</code> switches between them without a reconnect.</blockquote><blockquote><strong>HLS (HTTP Live Streaming):</strong> Apple's segment-based protocol that delivers video as chunked files over a CDN. It scales to effectively unlimited viewers at a cost of 12 to 30 seconds of latency.</blockquote><blockquote><strong>Multistreaming:</strong> Broadcasting one live source to several destinations at once. VideoSDK performs the fan-out server-side via <code>startLivestream()</code>, so the host uploads a single stream.</blockquote><blockquote><strong>Simulcast:</strong> Publishing multiple quality layers of the same video track so the SFU can send each viewer the rendition their bandwidth supports.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>Interactive live streaming is defined by the return path, not by the video quality: if a viewer cannot publish back, it is live streaming with a chat box attached.</li><li>WebRTC delivery holds latency at 200ms to 500ms, while standard HLS runs 12 to 30 seconds behind and Apple's LL-HLS extension targets two seconds or less.</li><li>VideoSDK builds interactive streams on its rooms architecture, with <code>SEND_AND_RECV</code> and <code>RECV_ONLY</code> modes swapped live through <code>changeMode()</code> across React, React Native, JavaScript, Flutter, Android, iOS, and Python.</li><li>The interactive tier bills per viewer minute and the HLS tier bills per stream minute, so a hybrid architecture is an economic requirement above roughly 20 concurrent HD viewers, not a stylistic choice.</li><li>Multistreaming should happen server-side through <code>startLivestream()</code> so the host's upstream bandwidth stays flat no matter how many platforms you add.</li></ul><h2 id="conclusion">Conclusion</h2><p>Interactive live streaming is worth building when the audience's response is part of the product: a bid, a question, a purchase, a promoted guest. When it is not, HLS does the job for less money and with fewer moving parts.</p><p>If you are building the interactive kind, the shortest path is a token server, a room, two participant modes, and one <code>changeMode()</code> call. VideoSDK's free tier includes $20 of credit with no card required, which covers a realistic load test. </p><p>Start with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-react-ils" rel="noreferrer">React ILS quickstart</a>, or sign up at <a href="https://app.videosdk.live/login" rel="noreferrer">VideoSDK</a> and create your first stream room.</p><p>What are you building with interactive live streaming? Drop a comment with your use case, especially if you have hit the WebRTC-to-HLS crossover in production and had to redesign around it.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-interactive-live-streaming-1">What is interactive live streaming?</h3><p>Interactive live streaming is live video in which viewers can respond in real time and be promoted to broadcaster during the stream. It uses WebRTC rather than segment-based delivery, keeping latency in the 200ms to 500ms range instead of the 12 to 30 seconds typical of standard HLS. VideoSDK provides it through two participant modes on a standard room, with <code>changeMode()</code> switching a viewer to the stage without a reconnect.</p><h3 id="what-is-the-difference-between-ils-and-hls">What is the difference between ILS and HLS?</h3><p>The main difference is the return path and the latency budget. Interactive live streaming (ILS) delivers over WebRTC at 200ms to 500ms and lets a viewer publish audio and video back into the stream. HLS delivers chunked files over a CDN at 12 to 30 seconds of latency and is strictly one-way, which is why it scales further and costs less per viewer.</p><h3 id="how-do-you-build-a-live-streaming-app">How do you build a live streaming app?</h3><p>Build it in six steps: generate a JWT server-side, create a room through the REST API, join participants in the correct publish mode, expose a role-change control for promotion, start an HLS rendition when the audience outgrows the real-time tier, and push RTMP outputs for multistreaming. With the VideoSDK React SDK, each step is one SDK method, and the interactive layer is a <code>mode</code> value on <code>MeetingProvider</code>.</p><h3 id="can-a-viewer-become-a-host-during-the-stream">Can a viewer become a host during the stream?</h3><p>Yes. In VideoSDK, a viewer joined as <code>RECV_ONLY</code> calls <code>changeMode(Constants.modes.SEND_AND_RECV)</code> to start publishing without leaving and rejoining the room. Because the method runs client-side, gate it behind a host approval message so viewers cannot put themselves on camera unprompted.</p><h3 id="what-is-multistreaming-and-how-does-it-work">What is multistreaming and how does it work?</h3><p>Multistreaming is broadcasting one live source to several platforms simultaneously, such as YouTube, Twitch, and LinkedIn at once. VideoSDK's <code>startLivestream()</code> accepts an array of RTMP outputs, each with a <code>url</code> and <code>streamKey</code>, and performs the fan-out on its servers. The host therefore uploads a single stream regardless of how many destinations are configured.</p><h3 id="how-much-does-interactive-live-streaming-cost">How much does interactive live streaming cost?</h3><p>VideoSDK bills the interactive tier per viewer minute, listing HD (720p) video at $0.002 per viewer minute, and bills HLS at $0.04 per livestream minute for 720p encoding. A one-hour stream with 1,000 concurrent interactive viewers costs roughly $120, while the HLS encoding line stays flat at about $2.40 for that hour. </p><h3 id="is-webrtc-good-enough-for-large-live-streams">Is WebRTC good enough for large live streams?</h3><p>WebRTC is the right transport for the interactive tier and the wrong one for mass reach. VideoSDK documents support for up to 100 hosts and 2,000 real-time viewers per interactive session, with HLS handling audiences beyond that. Production streams commonly run both from the same room, keeping interaction on WebRTC and reach on the CDN.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 Voice Chat SDKs: Expert Reviewed & Ranked]]></title><description><![CDATA[The 10 best voice chat SDKs, ranked on published audio pricing, platform coverage, free-tier limits, and product continuity. Includes a WebRTC latency harness and corrections to two errors most comparison articles still repeat. ]]></description><link>https://www.videosdk.live/blog/voice-chat-sdk</link><guid isPermaLink="false">6a8d344eb3240feb748c98b4</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 25 Aug 2026 12:59:42 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-25--2026--05_34_13-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>A voice chat SDK is a prebuilt toolkit that adds live multi-party audio to an app without building WebRTC infrastructure. VideoSDK ranks first in 2026 for voice rooms that later need video, live streaming, SIP, or AI agents, with audio at $0.001 per participant minute. Pick Agora for audio-only scale, LiveKit for self-hosting, and Vivox for games.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-25--2026--05_34_13-PM.png" alt="Top 10 Voice Chat SDKs: Expert Reviewed & Ranked"/><p>This ranking uses published pricing pages, official documentation, and vendor status notices checked in August 2026. Every rate is cited, every discontinued product is flagged, and the last section hands you a <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> test harness so you can measure latency on your own network instead of trusting a marketing number.</p><h2 id="why-most-voice-chat-sdk-comparisons-are-wrong">Why Most Voice Chat SDK Comparisons Are Wrong</h2><p>Two factual errors appear in most voice chat SDK listicles currently ranking, and both change the shortlist.</p><p><strong>Twilio Programmable Video is not being discontinued.</strong> Twilio first moved the end-of-life date from December 5, 2024 to December 5, 2026, then reversed the decision entirely and confirmed <a href="https://www.twilio.com/en-us/changelog/-twilio-video-will-remain-a-standalone-product" rel="nofollow noreferrer">Video would remain a standalone product</a>. Twilio Live, a separate product, was genuinely discontinued in November 2023. Lists that conflate the two are reading a three-year-old notice.</p><p><strong>The Amazon Chime SDK survived the shutdown of the Amazon Chime application.</strong> AWS ended support for the <a href="https://aws.amazon.com/blogs/messaging-and-targeting/update-on-support-for-amazon-chime/" rel="nofollow noreferrer">Amazon Chime service on February 20, 2026</a>, after closing it to new customers a year earlier. Every AWS notice about that shutdown carries the same clarification: it does not affect the availability of the Amazon Chime SDK. One product died, the other did not, and the shared brand name causes real confusion during procurement.</p><p>A third correction matters for anyone reading 2026 roundups: Dyte, still recommended by several of them, was acquired by Cloudflare in April 2025 and is not a live procurement option in its previous form.</p><p>Verify vendor continuity before you verify features. A provider that is being wound down cannot be fixed by a good API.</p><h2 id="what-is-a-voice-chat-sdk">What Is a Voice Chat SDK?</h2><p>A voice chat SDK is defined as a packaged set of client libraries, server APIs, and media infrastructure that lets developers add live multi-party audio to an application without implementing <a href="https://www.videosdk.live/blog/what-is-webrtc-signaling" rel="noreferrer">WebRTC signalling</a>, codec negotiation, or media routing from scratch.</p><p>A voice chat SDK works by capturing microphone audio, encoding it (almost always with the Opus codec), transmitting it over a real-time transport such as WebRTC, routing it through a Selective Forwarding Unit, and decoding it into a jitter-buffered playback stream on every other participant's device. The <a href="https://www.w3.org/TR/webrtc/">W3C WebRTC specification</a> defines the browser APIs that make this possible without plugins.</p><p>VideoSDK provides voice chat through the same Rooms-based architecture as its video calling SDK, with video tracks disabled at join time. Audio-only participants are billed at $0.001 per participant minute on the published pricing page, and every new account receives a one-time $20 credit that does not expire and requires no credit card. </p><p>The distinction that causes the most confusion in 2026 is between a <em>voice chat SDK</em> and a <em>voice API</em>. A voice API such as Twilio Programmable Voice connects your app to the public telephone network. A voice chat SDK connects your users to each other over IP. Some platforms now do both, which is exactly why the two categories keep colliding in search results.</p><h2 id="how-we-evaluated-every-voice-chat-sdk">How We Evaluated Every Voice Chat SDK</h2><p>Rankings without disclosed criteria are opinions wearing a lab coat, so here is the weighting and how each axis was checked.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th align="left">Criterion</th>
<th align="right">Weight</th>
<th align="left">What was evaluated</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">Core voice and room controls</td>
<td align="right">25%</td>
<td align="left">Audio-only rooms, participant state, mute controls, roles, moderation, events</td>
</tr>
<tr>
<td align="left">Platform coverage and developer experience</td>
<td align="right">20%</td>
<td align="left">Supported client SDKs, quickstarts, API consistency, prebuilt UI, samples</td>
</tr>
<tr>
<td align="left">Production operations</td>
<td align="right">20%</td>
<td align="left">Recording, transcription, analytics, webhooks, reconnect behaviour, pre-call checks</td>
</tr>
<tr>
<td align="left">Audio quality and scale controls</td>
<td align="right">15%</td>
<td align="left">Network adaptation, noise handling, selective subscription, spatial audio, capacity limits</td>
</tr>
<tr>
<td align="left">Security and deployment</td>
<td align="right">10%</td>
<td align="left">Token model, encryption options, data controls, self-hosting or private deployment</td>
</tr>
<tr>
<td align="left">Pricing and onboarding clarity</td>
<td align="right">10%</td>
<td align="left">Public pricing, free usage, billing units, effort required to forecast cost</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Each provider was scored from one to five per criterion, then weighted. Ties were broken by fit for a general developer building a branded web or mobile voice product, which is the dominant intent behind this search term. That baseline favours application RTC platforms over products designed mainly for game engines or the phone network, and the ranking says so explicitly rather than hiding it.</p><p><strong>Two products were excluded after verification.</strong> Dyte was acquired by Cloudflare in April 2025. The Dolby.io communications stack has consolidated under the Dolby OptiView brand around real-time streaming rather than developer voice chat.</p><p><strong>What this evaluation does not include:</strong> original latency measurements. Vendor scale and latency statements are treated as published claims, not test results. The harness later in this article produces your own numbers. </p><h2 id="the-10-best-voice-chat-sdks-in-2026">The 10 Best Voice Chat SDKs in 2026</h2><p>The list splits into two groups because the search term does. Items 1 through 8 are application and social voice platforms. Items 9 and 10 are game-engine voice systems with positional audio, a different problem with different winners.</p><h3 id="1-videosdk-best-for-voice-rooms-that-grow">1. VideoSDK: Best for Voice Rooms That Grow</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.29.39-PM-8.png" class="kg-image" alt="Top 10 Voice Chat SDKs: Expert Reviewed & Ranked" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://www.videosdk.live/">VideoSDK</a> ranks first on one specific, checkable criterion: it is the broadest single-SDK path from a plain <a href="https://www.videosdk.live/live-audio-rooms" rel="noreferrer">audio room</a> to <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">video calling</a>, <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">interactive live streaming</a>, SIP telephony, and AI voice agents, with per-minute audio pricing published openly.</p><p>Voice rooms run on the same Rooms architecture as video calling, so a social audio app that later adds video or a live shopping stream does not swap vendors or rewrite its participant model. The <a href="https://www.videosdk.live/pricing" rel="noreferrer">pricing page</a> rates are as follows:</p>
<!--kg-card-begin: html-->
<table><thead><tr><th scope="col" style="text-align: left;">Service</th><th scope="col" style="text-align: right;">Price (USD)</th><th scope="col" style="text-align: left;">Billed per</th></tr></thead><tbody><tr><td style="text-align: left;"><strong>Audio call (camera off)</strong></td><td style="text-align: right;"><strong>$0.001</strong></td><td style="text-align: left;">participant minute</td></tr><tr><td style="text-align: left;">Video call</td><td style="text-align: right;">$0.004</td><td style="text-align: left;">participant minute</td></tr><tr><td style="text-align: left;">Meeting recording (HD)</td><td style="text-align: right;">$0.015</td><td style="text-align: left;">recorded minute</td></tr><tr><td style="text-align: left;">Meeting recording (Full HD)</td><td style="text-align: right;">$0.030</td><td style="text-align: left;">recorded minute</td></tr><tr><td style="text-align: left;">Participant recording</td><td style="text-align: right;">$0.006</td><td style="text-align: left;">participant minute</td></tr><tr><td style="text-align: left;">Real-time transcription</td><td style="text-align: right;">$0.020</td><td style="text-align: left;">transcription minute</td></tr><tr><td style="text-align: left;">Post-call transcription</td><td style="text-align: right;">$0.004</td><td style="text-align: left;">transcription minute</td></tr><tr><td style="text-align: left;">Storage</td><td style="text-align: right;">$0.003</td><td style="text-align: left;">minute stored, per month</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><strong>Platforms:</strong> JavaScript, React, React Native, Android, iOS, Flutter, Unity, C++, IoT, Python. </p><p><strong>Free tier:</strong> $20 non-expiring credit, no credit card, 50 concurrent participants and 200 concurrent ILS viewers. </p><p><strong>Best for:</strong> social audio, telehealth voice, edtech, customer support, and any product where voice is phase one of a broader real-time roadmap. </p><p><strong>Where it loses:</strong> the $20 credit is one-time. Agora's recurring 10,000 free minutes per month is more generous for a low-volume app that will stay audio-only forever.</p><h3 id="2-agora-best-recurring-free-tier">2. Agora: Best Recurring Free Tier</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.26-PM-7.png" class="kg-image" alt="Top 10 Voice Chat SDKs: Expert Reviewed & Ranked" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/en/" rel="noreferrer nofollow">Agora</a> gives every account 10,000 free minutes every month, which is the most durable free allowance in this list for a pure voice product.</p><p>Those minutes are issued per account and shared across projects rather than per product. Audio bills at $0.99 per 1,000 standard minutes after that, per Agora's voice calling pricing documentation, which is effectively identical to VideoSDK's $0.001/min. The free bucket rather than the rate is the real differentiator at low volume. Traffic runs over SD-RTN, Agora's proprietary overlay network rather than the open internet, which is the strongest argument for Agora on genuinely global consumer apps.</p><p><strong>Platforms:</strong> Web, iOS, Android, Windows, macOS, Unity, Unreal, Flutter, React Native, Electron. </p><p><strong>Best for:</strong> consumer social audio at global scale where a recurring monthly allowance materially affects runway. </p><p><strong>Where it loses:</strong> billing runs on resolution-weighted "standard minutes" that complicate forecasting once video enters the picture, and the Conversational AI Engine sits outside the free RTC bucket on separate metering. </p><h3 id="3-livekit-best-open-source-option">3. LiveKit: Best Open Source Option</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.40-PM-4.png" class="kg-image" alt="Top 10 Voice Chat SDKs: Expert Reviewed & Ranked" loading="lazy" width="2920" height="1670"/></figure><p><a href="https://livekit.com/" rel="noreferrer nofollow">LiveKit</a> is the only option here where you can remove the vendor entirely and keep the software, because the media server, agents framework, and SIP stack are all Apache-2.0 licensed.</p><p>That single fact is the whole decision. You gain source access, data residency control, and no per-minute floor. You also inherit autoscaling, session placement, TURN, capacity planning, and the 3am pager. LiveKit has become the default WebRTC substrate under a large share of voice AI products, and a 2026 pricing change made upstream bandwidth free while cutting downstream rates from $0.18/GB to $0.12/GB, which specifically benefits voice AI workloads.</p><p><strong>Platforms:</strong> JavaScript, Swift, Android, Flutter, React Native, Rust, Node.js, Python, Unity, C++, ESP32. </p><p><strong>Cloud tiers:</strong> Build (free), Ship ($50/mo), Scale ($500/mo), Enterprise. Agent session minutes at $0.01/min. <strong>Best for:</strong> teams with infrastructure engineers, strict data-residency rules, or a hard no-lock-in mandate. </p><p><strong>Where it loses:</strong> no prebuilt drop-in voice room UI, and self-hosting is not free in engineering terms.</p><h3 id="4-daily-best-path-to-pipecat-voice-ai">4. Daily: Best Path to Pipecat Voice AI</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.02-PM-6.png" class="kg-image" alt="Top 10 Voice Chat SDKs: Expert Reviewed & Ranked" loading="lazy" width="2924" height="1652"/></figure><p><a href="https://www.daily.co/" rel="noreferrer nofollow">Daily</a> is the quickest managed platform to get from signup to a working multi-party audio room, and it maintains Pipecat, one of the two dominant open-source voice AI frameworks.</p><p>Daily's native mobile SDKs are built on a shared Rust core, and Daily is a W3C WebRTC Working Group member, meaning its engineers help write the specification their SDK implements. Audio-only pricing is broken out separately rather than folded into video rates, with 10,000 free minutes each month and a published audio rate near $0.00099 per participant minute before automatic volume discounts.</p><p><strong>Platforms:</strong> JavaScript, React Native, iOS, Android, Flutter, Python. </p><p><strong>Best for:</strong> small teams shipping a voice feature this sprint, and anyone building on Pipecat. </p><p><strong>Where it loses:</strong> a narrower platform matrix than Agora or LiveKit, and less depth on interactive live streaming.</p><h3 id="5-100ms-best-role-based-audio-rooms">5. 100ms: Best Role-Based Audio Rooms</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.31.12-PM-5.png" class="kg-image" alt="Top 10 Voice Chat SDKs: Expert Reviewed & Ranked" loading="lazy" width="2910" height="1656"/></figure><p><a href="https://www.100ms.live/" rel="noreferrer nofollow">100ms</a> models sessions as rooms containing peers, tracks, and roles, which makes speaker and listener permissions a configuration choice rather than application code you write and defend.</p><p>Role templates control who can publish, who can subscribe, who can mute others, and who sits in the audience. Combined with recording, webhooks, and prebuilt experiences, that maps cleanly onto classrooms, webinars, and community rooms. The published model gives 10,000 free conferencing minutes per month, with audio-only calls billed at $0.001 per participant minute against a $0.004 video rate.</p><p><strong>Platforms:</strong> Web, Android, iOS, Flutter, React Native. </p><p><strong>Best for:</strong> education, live events, and audio communities where speakers and listeners need genuinely different permissions. </p><p><strong>Where it loses:</strong> the client matrix concentrates on mainstream web and mobile. Teams targeting desktop-native, embedded, or console environments should compare LiveKit, ZEGOCLOUD, or a game voice SDK.</p><h3 id="6-stream-best-for-voice-beside-chat">6. Stream: Best for Voice Beside Chat</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-28-at-4.33.18-PM-2.png" class="kg-image" alt="Top 10 Voice Chat SDKs: Expert Reviewed & Ranked" loading="lazy" width="2890" height="1540"/></figure><p><a href="https://getstream.io/video/" rel="noreferrer nofollow">GetStream</a> is the strongest pick when audio rooms need to sit next to messaging, feeds, and moderation under one vendor relationship rather than being stitched to a separate chat provider.</p><p>The Video and Audio product ships a built-in <code>audio_room</code> call type with backstage state, speaker and listener roles, recording, transcription, SIP inbound trunks, and webhooks. Pricing is unusually legible for audio. Stream's <a href="https://getstream.io/video/docs/api/pricing-guide/" rel="noreferrer nofollow">pricing guide</a> lists audio-only calls at <strong>$0.30 per 1,000 participant minutes</strong> against $1.50 for HD video, with every account receiving <strong>$100 per month</strong> in free Audio/Video API usage.</p><p><strong>Platforms:</strong> JavaScript, React, iOS, Android, React Native, Flutter, Unity.</p><p><strong>Best for:</strong> social apps, communities, and marketplaces combining voice with chat or moderation. </p><p><strong>Where it loses:</strong> managed cloud only, with no self-hosting path, and it is not a game-engine voice product.</p><h3 id="7-zegocloud-best-prebuilt-room-kits">7. ZEGOCLOUD: Best Prebuilt Room Kits</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.33.21-PM-2.png" class="kg-image" alt="Top 10 Voice Chat SDKs: Expert Reviewed & Ranked" loading="lazy" width="2926" height="1668"/></figure><p><a href="https://www.zegocloud.com/" rel="nofollow noreferrer">ZEGOCLOUD</a> ships scene-level UIKits, so a Clubhouse-style room with mic seats and host controls becomes a configuration exercise rather than a build.</p><p>Its own developer documentation distinguishes three SDK layers: scene-level room SDKs that include complete chat-room business logic and UI, mid-level component SDKs, and low-level media SDKs. The LiveAudioRoom kit sits in the first layer. Voice is published at $0.99 per 1,000 participant minutes with 10,000 free minutes, subject to the package rules on the pricing page.</p><p><strong>Platforms:</strong> Web, iOS, Android, Windows, macOS, Flutter, React Native, Unity, Cocos Creator. </p><p><strong>Best for:</strong> teams that need a social audio product live in weeks and can accept the UI opinions that come with the kit. </p><p><strong>Where it loses:</strong> the deep integration that makes it fast also makes heavy customisation expensive. Check framework-specific limits too, since the React Native Call Kit currently requires native changes and does not support Expo.</p><h3 id="8-twilio-voice-sdk-best-for-pstn-bridges">8. Twilio Voice SDK: Best for PSTN Bridges</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.53.31-PM-4.png" class="kg-image" alt="Top 10 Voice Chat SDKs: Expert Reviewed & Ranked" loading="lazy" width="2910" height="1638"/></figure><p><a href="https://www.twilio.com/docs/video" rel="noreferrer nofollow">Twilio Video</a> remains the reference implementation for connecting in-app voice to the public telephone network, and its Video product is no longer being sunset.</p><p>The Programmable Voice SDKs connect browser and mobile clients to Twilio's voice network through server-generated AccessTokens and TwiML Apps, covering inbound and outbound calls. US browser or app calling is published at $0.004 per minute in each direction, with phone numbers, PSTN legs, conferences, recordings, and transcription billed separately.</p><p><strong>Platforms:</strong> JavaScript, iOS, Android, React Native. </p><p><strong>Best for:</strong> contact centres, sales dialers, marketplaces, and any product where a browser user must reach an actual phone number. </p><p><strong>Where it loses:</strong> for app-to-app voice rooms it is heavier and more expensive than a purpose-built RTC SDK, and multi-party audio pulls in Twilio Conferences with a different cost and orchestration model.</p><h3 id="9-unity-vivox-best-positional-game-voice">9. Unity Vivox: Best Positional Game Voice</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-25-at-4.43.23-PM.png" class="kg-image" alt="Top 10 Voice Chat SDKs: Expert Reviewed & Ranked" loading="lazy" width="2890" height="1488"/></figure><p><a href="https://unity.com/products/vivox" rel="noreferrer nofollow">Vivox</a> is the proven choice for cross-play positional voice in games, and it is free up to 5,000 peak concurrent users.</p><p>It delivers proximity-based 3D positional channels and 2D team channels, runs across Unity, Unreal, and an engine-agnostic Core SDK, supports cross-play, and includes speech-to-text and text-to-speech accessibility plus AI-assisted moderation. Real-Time Recording streams live voice and metadata to moderation providers, which is now a compliance requirement in several markets rather than a nice-to-have. Vivox is used in shipped titles including VALORANT, PUBG, League of Legends, and Rainbow Six Siege.</p><p><strong>Platforms:</strong> Unity, Unreal, Core SDK, mobile, desktop, major consoles, Meta Quest, visionOS. </p><p><strong>Best for:</strong> any multiplayer title needing proximity chat, cross-platform parity, and moderation evidence. </p><p><strong>Where it loses:</strong> the Safe Text moderation tier meters on monthly active users while voice meters on peak concurrent users, a mismatch that surprises free-to-play teams at scale. Console packages also require platform NDA approval.</p><h3 id="10-photon-voice-2-best-for-unity-and-xr">10. Photon Voice 2: Best for Unity and XR</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-25-at-4.44.34-PM.png" class="kg-image" alt="Top 10 Voice Chat SDKs: Expert Reviewed & Ranked" loading="lazy" width="2846" height="1558"/></figure><p><a href="https://www.photonengine.com/voice" rel="noreferrer nofollow">Photon Voice 2</a> is the smallest-footprint option for Unity teams that need 3D voice attached to game objects without adopting a full communications platform. It uses the Opus codec and lets developers attach an audio source directly to a 3D object, positioning voice inside a virtual world. Running on Photon Realtime with ready-made PUN2 and Fusion integrations means a game already using Photon networking adds voice without introducing a second room and matchmaking model. Interest groups give you a practical basis for team or proximity-style routing. Pricing is based on concurrent connected users, with a free 20-CCU development plan.</p><p><strong>Platforms:</strong> Unity across desktop, mobile, WebGL, XR, and consoles. </p><p><strong>Best for:</strong> Unity-native teams, VR and AR social apps, and studios already running Photon. </p><p><strong>Where it loses:</strong> effectively Unity-only, it lacks Vivox's moderation and accessibility tooling, and Photon documents that Mono is not fully supported while WebGL support excludes Safari.</p><p><strong>Also worth knowing:</strong> Tencent RTC (10,000 pooled monthly minutes and the strongest China and Southeast Asia routing here), the Amazon Chime SDK (the right answer for AWS-native teams who want IAM and consolidated billing more than developer experience), ODIN by 4Players (spatial voice with Wwise and FMOD support), and the Discord Social SDK (lobby-based voice, though Discord recommends keeping calls to 25 members or fewer for best performance).</p><h2 id="voice-chat-sdk-comparison-table">Voice Chat SDK Comparison Table</h2><p>The fastest shortlist comes from matching architecture to your dominant use case, then checking price.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th align="left">SDK</th>
<th align="left">Published audio rate</th>
<th align="left">Free tier</th>
<th align="left">Platforms</th>
<th align="left">Best for</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left"><strong>VideoSDK</strong></td>
<td align="left">$0.001 per participant min</td>
<td align="left">$20 non-expiring credit, 50 concurrent</td>
<td align="left">10 (JS, React, RN, Android, iOS, Flutter, Unity, C++, IoT, Python)</td>
<td align="left">Voice rooms with a video, ILS, SIP, and AI agent roadmap</td>
</tr>
<tr>
<td align="left">Agora</td>
<td align="left">$0.99 per 1,000 min</td>
<td align="left">10,000 min/month, recurring</td>
<td align="left">10</td>
<td align="left">Audio-only apps at global consumer scale</td>
</tr>
<tr>
<td align="left">LiveKit</td>
<td align="left">Self-host free; Cloud from $50/mo</td>
<td align="left">Build tier free</td>
<td align="left">11</td>
<td align="left">Self-hosting and no vendor lock-in</td>
</tr>
<tr>
<td align="left">Daily</td>
<td align="left">~$0.00099 per participant min</td>
<td align="left">10,000 min/month</td>
<td align="left">6</td>
<td align="left">Social audio and Pipecat voice AI</td>
</tr>
<tr>
<td align="left">100ms</td>
<td align="left">$0.001 per participant min</td>
<td align="left">10,000 conferencing min/month</td>
<td align="left">5</td>
<td align="left">Role-based speaker and listener rooms</td>
</tr>
<tr>
<td align="left">Stream</td>
<td align="left">$0.30 per 1,000 participant min</td>
<td align="left">$100/month in credits</td>
<td align="left">7</td>
<td align="left">Audio rooms beside chat and moderation</td>
</tr>
<tr>
<td align="left">ZEGOCLOUD</td>
<td align="left">$0.99 per 1,000 participant min</td>
<td align="left">10,000 min</td>
<td align="left">9</td>
<td align="left">Prebuilt live audio room kits</td>
</tr>
<tr>
<td align="left">Twilio Voice</td>
<td align="left">$0.004 per min, per leg</td>
<td align="left">Trial credit</td>
<td align="left">4</td>
<td align="left">Voice chat that bridges to phone numbers</td>
</tr>
<tr>
<td align="left">Unity Vivox</td>
<td align="left">Custom above free tier</td>
<td align="left">Free to 5,000 peak concurrent users</td>
<td align="left">Unity, Unreal, Core SDK, consoles</td>
<td align="left">Positional voice in cross-play games</td>
</tr>
<tr>
<td align="left">Photon Voice 2</td>
<td align="left">Tiered by concurrent users</td>
<td align="left">Free 20-CCU dev plan</td>
<td align="left">Unity (desktop, mobile, WebGL, XR)</td>
<td align="left">Unity and XR spatial voice</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The column that decides most evaluations is the free tier, not the rate. VideoSDK and Agora charge almost the same per audio minute, so the $20 credit converts to roughly 20,000 audio participant-minutes once, while Agora's 10,000 minutes reset every month. For an app that stays audio-only, Agora is cheaper from month three. For anything that grows into video or streaming, VideoSDK's single-SDK path avoids a migration that costs far more than the difference.</p><h2 id="how-do-you-choose-a-voice-chat-sdk">How Do You Choose a Voice Chat SDK?</h2><p>Choose a voice chat SDK by starting with your hardest constraint, because feature lists converge and constraints do not.</p><ul><li><strong>Choose VideoSDK when</strong> voice is the first surface of a product that will plausibly need video calls, interactive live streaming, SIP, or an AI voice agent within a year.</li><li><strong>Choose Agora when</strong> the app is audio-only, global, consumer-scale, and a recurring monthly free allowance materially affects runway.</li><li><strong>Choose LiveKit when</strong> data residency, cost at scale, or a no-lock-in mandate makes self-hosting non-negotiable and you have engineers to run it.</li><li><strong>Choose Daily when</strong> the deadline is short or you are building on Pipecat.</li><li><strong>Choose 100ms when</strong> speaker and listener roles map directly onto classrooms, events, or moderated communities.</li><li><strong>Choose Stream when</strong> voice belongs beside chat, feeds, and moderation in the same product.</li><li><strong>Choose ZEGOCLOUD when</strong> a prebuilt room UI can compress weeks of frontend work.</li><li><strong>Choose Twilio when</strong> users must reach the public telephone network.</li><li><strong>Choose Unity Vivox or Photon Voice when</strong> the product is a game and voice needs to be positional.</li></ul><p>Three constraints override everything above. A hard data-residency requirement points to LiveKit self-hosted or a private deployment. A positional-audio requirement removes every non-gaming SDK on this list. A documented moderation-evidence obligation currently points to Vivox.</p><p>Price comes after architecture fit. A low participant-minute rate is easily outweighed by recording, transcription, egress, phone numbers, or the engineering cost of building the role and moderation systems your provider left out.</p><h2 id="production-voice-chat-sdk-checklist">Production Voice Chat SDK Checklist</h2><p>Most quickstarts stop at "it works on localhost". These ten items are where voice products actually break, and mobile operating systems cause more of them than the network does.</p><ol><li><strong>Generate tokens server-side and plan for expiry.</strong> Issue short-lived, least-privilege room <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/authentication-and-tokens" rel="noreferrer">tokens</a> and never ship an API secret in a browser or mobile bundle. Decide what happens when a token expires mid-call during a two-hour room.</li><li><strong>Handle audio focus and interruptions.</strong> An incoming phone call, an alarm, or a Siri or Google Assistant invocation will take the audio session away. Define what your app does on interruption begin and end, and test that the microphone comes back.</li><li><strong>Handle Bluetooth profile switching.</strong> Headsets switch between A2DP (high-quality playback, no microphone) and HFP (two-way, lower fidelity) when a call starts. Users hear this as sudden quality loss or a dead microphone. Route audio explicitly rather than trusting the default.</li><li><strong>Keep the audio track alive in the background.</strong> On iOS this needs the <code>audio</code> value in <code>UIBackgroundModes</code>. On Android it needs a foreground service with <code>FOREGROUND_SERVICE_MICROPHONE</code>. Without both, backgrounded users silently drop out of the room.</li><li><strong>Run a pre-call device and permission check.</strong> Show the selected input and output device, a live input level, permission state, and an actionable error. Re-run it after any headset change.</li><li><strong>Design explicit reconnect states.</strong> Distinguish a brief network interruption from an intentional leave. Add bounded retries, visible connection status, and a clean fallback when the room or token is gone.</li><li><strong>Enforce roles on the server.</strong> A hidden mute button is not access control. Define server-side who may publish, subscribe, record, eject, or promote another participant.</li><li><strong>Make recording consent explicit and auditable.</strong> Display recording state, log who consented, set retention and deletion rules, and treat recording webhooks as at-least-once events with idempotency keys.</li><li><strong>Test on hostile networks, not office wifi.</strong> Include packet loss, high jitter, blocked <a href="https://www.videosdk.live/developer-hub/websocket/websocket-udp" rel="noreferrer">UDP</a>, cellular handoffs, backgrounded apps, and low-end devices. No vendor latency figure survives this matrix unchanged.</li><li><strong>Measure user-perceived quality.</strong> Track join success rate, time to first audio, reconnect rate, mute failures, packet loss, and jitter, segmented by SDK version, device class, and region.</li></ol><p>This checklist covers the gap most SDK comparisons leave open: picking a media provider without planning the application controls that make voice trustworthy.</p><h2 id="why-videosdk-ranks-first-for-voice-rooms">Why VideoSDK Ranks First for Voice Rooms</h2><p>VideoSDK takes the top position for the largest share of teams on a specific and checkable criterion, not a general claim of superiority.</p><p>It is the platform here that publishes a $0.001 per minute audio rate while documenting a path to video calling, interactive live streaming, SIP telephony, and AI voice agents inside one SDK surface across ten client platforms. For a product where voice is step one rather than the whole product, that avoids the migration most teams eventually pay for. The <a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">REST API</a> handles server-side room creation and orchestration, and the <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Prebuilt UI Kit</a> shortens the proof of concept.</p><p>Consider a telehealth coaching product launching with private audio sessions. The backend creates a room, issues a short-lived token, and stores the role mapping. Clients join with microphones enabled and cameras off, billing at the voice rate. The same product later adds consented recording, live transcription, video escalation, or a host-and-viewer event without changing RTC vendors.</p><p>The honest picture is not a clean sweep. Agora's recurring 10,000 free minutes beat a one-time credit for a genuinely audio-only app. LiveKit is the correct answer whenever self-hosting is a requirement rather than a preference, because no proprietary SDK can match an Apache-2.0 licence. Vivox wins games outright, since positional audio and moderation evidence are not capabilities VideoSDK competes on. Those boundaries are what make the number one position useful rather than promotional.</p><h2 id="voice-chat-sdk-glossary">Voice Chat SDK Glossary</h2><blockquote><strong>Room:</strong> A logical session that participants join by ID to exchange real-time media. In VideoSDK, a room is created through the REST API and joined through the client SDKs.</blockquote><blockquote><strong>Participant:</strong> A user, device, or AI agent connected to a room, each with independently addressable audio and video tracks.</blockquote><blockquote><strong>Meeting Token:</strong> A JWT generated server-side from your API key and secret that authorises a participant to join a specific room. Exposing the secret client-side is the most common security failure in voice integrations.</blockquote><blockquote><strong>SFU (Selective Forwarding Unit):</strong> The media server that receives each participant's encoded audio once and forwards it to everyone else without decoding, which is why SFU architecture scales where peer-to-peer does not.</blockquote><blockquote><strong>Opus:</strong> The default audio codec for WebRTC voice, designed for speech and music at variable bitrate, used by effectively every SDK in this comparison.</blockquote><blockquote><strong>Audio focus:</strong> The operating system's arbitration of which app owns the audio session on mobile. Losing focus to a phone call or alarm is the most common cause of a dead microphone in production.</blockquote><blockquote><strong>Positional (spatial) voice:</strong> Audio spatialised by in-world distance and direction so players hear teammates from where they are, standard in game voice SDKs and absent from most application voice SDKs.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>A voice chat SDK removes WebRTC signalling, codec negotiation, and media routing from your build, which is typically several engineer-months of work before the first call connects.</li><li>VideoSDK publishes audio-only participant minutes at $0.001 and pairs them with video, interactive live streaming, SIP, and AI voice agents on the same SDK surface across ten platforms, which is the strongest fit when voice is phase one of a larger product.</li><li>Agora's recurring 10,000 free monthly minutes is the better economic choice for an app that will stay audio-only, and an honest comparison should say so.</li><li>Twilio Programmable Video is not being discontinued and the Amazon Chime SDK survived the shutdown of the Amazon Chime application, so any list claiming otherwise is working from stale sources.</li><li>Game voice is a separate category, where positional audio and moderation tooling make Unity Vivox and Photon Voice the right answers regardless of how good a general RTC SDK is.</li></ul><h2 id="conclusion">Conclusion</h2><p>The right Voice Chat SDK depends on what surrounds the audio and what the product must become next. VideoSDK is the leading choice in this evaluation for managed web and mobile rooms with clear expansion paths. LiveKit leads for self-hosting, Vivox for game voice, and Twilio for PSTN-heavy calling. Validate the shortlist against your devices, regions, privacy model, failure cases, and full cost stack.</p><p>Grab an API key and $20 in credit at <a href="https://app.videosdk.live/signup" rel="noreferrer">VideoSDK</a> or start from the <a href="https://www.videosdk.live/sdk" rel="noreferrer">voice chat sdk</a>. So What are you building with VideoSDK?</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-best-voice-chat-sdk-for-developers">What is the best voice chat SDK for developers?</h3><p>The best voice chat SDK depends on where the product is heading. VideoSDK is the strongest pick for teams whose voice feature will later need video, live streaming, SIP, or AI voice agents, because all of those run on one SDK and audio-only minutes are published at $0.001. Agora is better for permanently audio-only global apps thanks to 10,000 recurring free monthly minutes. LiveKit is the answer when self-hosting is mandatory.</p><h3 id="is-there-a-free-voice-chat-sdk">Is there a free voice chat SDK?</h3><p>Yes, several. LiveKit is fully open source under Apache-2.0 and free to self-host with no per-minute fees. Among managed platforms, Agora and 100ms each provide 10,000 free minutes per month on a recurring basis, Stream provides $100 in monthly credits, VideoSDK provides a one-time $20 credit that does not expire and needs no credit card, and Unity Vivox is free for games up to 5,000 peak concurrent users. </p><h3 id="how-much-does-a-voice-chat-sdk-cost">How much does a voice chat SDK cost?</h3><p>Published audio-only rates cluster tightly around $0.001 per participant minute. VideoSDK lists voice at $0.001/min, Agora at $0.99 per 1,000 minutes, 100ms at $0.001/min, and Stream at $0.30 per 1,000 participant minutes. The real cost variance comes from add-ons rather than the base rate, since recording, transcription, and storage are metered separately almost everywhere. VideoSDK bills meeting recording at $0.015/min, real-time transcription at $0.02/min, and post-call transcription at $0.004/min. </p><h3 id="what-is-the-difference-between-a-voice-chat-sdk-and-a-voice-api">What is the difference between a voice chat SDK and a voice API?</h3><p>The main difference is what each one connects. A voice chat SDK connects your users to each other over IP using WebRTC, which is what powers audio rooms, in-app calls, and social audio. A voice API such as Twilio Programmable Voice connects your application to the public switched telephone network so users can dial real phone numbers. Platforms including VideoSDK now offer both, bridging WebRTC rooms to phone lines over SIP.</p><h3 id="which-voice-chat-sdk-is-best-for-games">Which voice chat SDK is best for games?</h3><p>Unity Vivox is the strongest choice for most multiplayer games because it delivers proximity-based 3D positional voice, works across Unity, Unreal, and an engine-agnostic Core SDK, supports cross-play, and includes moderation and accessibility tooling. It is free up to 5,000 peak concurrent users. Photon Voice 2 is the lighter alternative for Unity-native and XR projects, using the Opus codec with audio sources attached directly to Unity game objects.</p><h3 id="what-latency-should-a-voice-chat-sdk-deliver">What latency should a voice chat SDK deliver?</h3><p>Aim for one-way audio delay below 150ms, the threshold in ITU-T Recommendation G.114 for conversation that feels uninterrupted. Treat every vendor figure as a best-case claim measured under favourable conditions, and verify it with the WebRTC <code>getStats()</code> harness in this article on your own network and devices. Report median and p95 round-trip time rather than the mean, since user complaints come from the tail.</p><h3 id="can-i-build-voice-chat-with-raw-webrtc-instead-of-using-an-sdk">Can I build voice chat with raw WebRTC instead of using an SDK?</h3><p>Yes, and it is the right call in a narrow set of cases. Raw WebRTC handles peer-to-peer audio well for two participants. Beyond that you need a signalling server, STUN and TURN infrastructure, an SFU for group routing, reconnection handling, and adaptive bitrate logic, which is where the months go. A voice chat SDK is essentially those components delivered as a managed service. Self-hosting LiveKit is the middle path, giving you the SFU without writing one.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 Video Interview APIs: Ranked by Fit]]></title><description><![CDATA[Compare the top Video Interview APIs. See why VideoSDK fits custom live interview products, where async screening platforms fit better, and what the new AI hiring rules restrict.
]]></description><link>https://www.videosdk.live/blog/video-interview-api</link><guid isPermaLink="false">6a7eb77bb3240feb748c96db</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 24 Aug 2026 12:36:12 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-24--2026--03_39_58-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>A Video Interview API lets a hiring product create, run, record, and review remote interviews through programmatic workflows. The right option depends on whether you need one-way screening inside an ATS or a custom live interview room. VideoSDK is the strongest fit for teams building a branded, real-time interview product, while Hireflix, Willo, and myInterview are purpose-built for asynchronous screening.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-24--2026--03_39_58-PM.png" alt="Top 10 Video Interview APIs: Ranked by Fit"/><p>Most teams pick a video interview API twice. Once quickly, and once eighteen months later, after discovering the first choice owned a layer they needed to control or left them building a layer they never wanted. The expensive mistake is almost never latency or price. It is picking the wrong <em>category</em>.</p><p>If candidates need to record answers before a recruiter reviews them, a specialist hiring-workflow API can save a great deal of product work. If candidates, interviewers, observers, and technical-assessment tools need to meet live inside your product, you need a real-time communication layer with controlled access, media events, recording, and a UI you can shape.</p><p>This guide separates those two categories, then ranks ten documented options by fit. It is a documentation-led comparison, not a latency benchmark, security certification, or claim that every provider was hands-on tested.</p><h2 id="what-is-a-video-interview-api">What Is a Video Interview API?</h2><p>A <a href="https://www.videosdk.live/solutions/interview-as-a-service" rel="noreferrer">video interview AP</a>I is defined as a set of programmatic interfaces for creating, joining, managing, recording, and observing remote interviews. A video interview API works by connecting an application's backend, identity rules, interview workflow, and media or recording service.</p><p>The category contains two different products:</p><ul><li><strong>Hiring-workflow APIs</strong> manage one-way questions, candidate invitations, recorded answers, recruiter review, and ATS-oriented objects.</li><li><strong>RTC APIs and SDKs</strong> manage rooms or channels, participants, audio and video tracks, recording, events, and embeddable live interfaces.</li></ul><blockquote><strong>A Video Interview API is not automatically an applicant tracking system.</strong> VideoSDK provides rooms, meeting tokens, client SDKs, recordings, transcription APIs, and participant controls for live interviews. Your recruiting product still owns applicant data, scheduling, evaluator feedback, consent records, and retention policy.</blockquote><h2 id="how-we-evaluated-these-video-interview-apis">How We Evaluated These Video Interview APIs</h2><p>This is a developer-first fit model, based on public documentation checked on August 24, 2026. It rewards the ability to deliver either a complete async screening workflow or a controlled custom live product. It does not use unverified quality, pricing, privacy, or AI-performance claims.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Evaluation area</th>
<th>What was assessed</th>
</tr>
</thead>
<tbody>
<tr>
<td>Interview-mode fit</td>
<td>Purpose-built async workflow or capable live interview room</td>
</tr>
<tr>
<td>Workflow and review</td>
<td>Invitations, candidate controls, recordings, transcripts, review events</td>
</tr>
<tr>
<td>Integration surface</td>
<td>REST or GraphQL APIs, webhooks, tokens, SDKs, and documentation</td>
</tr>
<tr>
<td>Product ownership</td>
<td>Custom UI, roles, access policies, branding, and backend orchestration</td>
</tr>
<tr>
<td>Delivery options</td>
<td>Prebuilt UI, browser and mobile delivery, or self-hosting</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Interview-mode fit carries the most weight in the ordering below, because a provider that cannot deliver your interview mode is not a candidate at any price. Product ownership and integration surface come next. Delivery options break ties.</p><p>The ranking is deliberately conditional. A provider placed lower overall can still be the better choice for your exact job. If one-way screening inside an <a href="https://en.wikipedia.org/wiki/Applicant_tracking_system" rel="noreferrer">ATS</a> is your requirement, start with Hireflix, Willo, or myInterview. If you need a branded live interview across web and mobile, start with <a href="https://www.videosdk.live/contact" rel="noreferrer">VideoSDK</a>, then evaluate the other real-time platforms against your technical constraints.</p><h2 id="top-10-video-interview-apis-in-2026">Top 10 Video Interview APIs in 2026</h2>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th align="right">Rank</th>
<th>API</th>
<th>Model</th>
<th>Best for</th>
<th>Main trade-off</th>
</tr>
</thead>
<tbody>
<tr>
<td align="right">1</td>
<td>VideoSDK</td>
<td>Real-time communication API and SDK</td>
<td>Custom live interview products</td>
<td>You build ATS workflows and scorecards</td>
</tr>
<tr>
<td align="right">2</td>
<td>Hireflix</td>
<td>Hiring-workflow API</td>
<td>One-way interviews with ATS integrations</td>
<td>Not a custom live media platform</td>
</tr>
<tr>
<td align="right">3</td>
<td>Willo</td>
<td>Hiring-workflow API</td>
<td>Embedded async video screening</td>
<td>Less control over bespoke live UX</td>
</tr>
<tr>
<td align="right">4</td>
<td>myInterview</td>
<td>Hiring-workflow API</td>
<td>API-led async interview journeys</td>
<td>Live interview infrastructure is not its focus</td>
</tr>
<tr>
<td align="right">5</td>
<td>Daily</td>
<td>Video API</td>
<td>Configurable, web-first live rooms</td>
<td>You build hiring workflows around it</td>
</tr>
<tr>
<td align="right">6</td>
<td>100ms</td>
<td>Video SDK</td>
<td>Role-based interview rooms and Prebuilt delivery</td>
<td>Recruiting data model remains your responsibility</td>
</tr>
<tr>
<td align="right">7</td>
<td>Zoom Video SDK</td>
<td>Video SDK</td>
<td>Teams already aligned with Zoom's developer platform</td>
<td>Custom UX still needs SDK work</td>
</tr>
<tr>
<td align="right">8</td>
<td>Agora</td>
<td>RTC SDK</td>
<td>Cross-platform real-time media control</td>
<td>Hiring workflows are not included</td>
</tr>
<tr>
<td align="right">9</td>
<td>Whereby Embedded</td>
<td>Embedded video API</td>
<td>Branded browser interview rooms</td>
<td>Best when its supplied room UX suits your flow</td>
</tr>
<tr>
<td align="right">10</td>
<td>Jitsi Meet</td>
<td>Open-source meeting stack</td>
<td>Self-hosting or open-source control</td>
<td>More infrastructure and integration work</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h3 id="1-videosdk">1. VideoSDK</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.29.39-PM-7.png" class="kg-image" alt="Top 10 Video Interview APIs: Ranked by Fit" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> ranks first for teams that want the live interview experience, UI, and application data model to remain their own. Its documentation covers React, JavaScript, React Native, Android, iOS, Flutter, Unity, Python, C++, and IoT paths, alongside room, session, recording, transcription, and webhook APIs.</p><p>For an early release, the VideoSDK prebuilt UI can supply a faster interview room. For a product with custom candidate flows, role-specific controls, branded layouts, or technical-assessment widgets, use the full SDK and your own frontend. VideoSDK is not an ATS, so you must implement invitations, calendar rules, scorecards, consent, and recruiting-system write-backs yourself.</p><p><strong>Best for:</strong> A talent marketplace, technical-interview product, or ATS extension that needs a live, branded experience on web or mobile.</p><h3 id="2-hireflix">2. Hireflix</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-24-at-1.17.16-PM.png" class="kg-image" alt="Top 10 Video Interview APIs: Ranked by Fit" loading="lazy" width="2900" height="1610"/></figure><p><a href="https://hireflix.com/en" rel="noreferrer nofollow">Hireflix</a> is a strong choice when asynchronous, one-way interviewing is the product requirement. Its public documentation describes native ATS integrations, Zapier and Make connections, a GraphQL API, webhooks, candidate invitations, interview data, transcripts, and downloadable answer media. See the Hireflix integration guide.</p><p>That is a compelling surface for a recruiting team that wants to automate invitations and collect candidate responses without building the recording workflow from scratch. It is not the right category when you need a deeply custom two-way interview room with your own real-time media controls.</p><p><strong>Best for:</strong> One-way screening that needs established ATS integrations and custom workflow automation.</p><h3 id="3-willo">3. Willo</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-24-at-1.18.29-PM.png" class="kg-image" alt="Top 10 Video Interview APIs: Ranked by Fit" loading="lazy" width="2928" height="1510"/></figure><p><a href="https://www.willo.video/" rel="noreferrer nofollow">Willo</a> positions its Video Interview API around embedding one-way interviews into job boards, application processes, ATSs, and staffing platforms. Its public materials describe API-key access, OpenAPI documentation, browser-based candidate access, and an asynchronous candidate experience.</p><p>Choose Willo when the candidate should answer structured questions on their own time and recruiters need a focused hiring workflow. Validate the operations, retention settings, accessibility needs, data location, and ATS connector you need before committing to the integration.</p><p><strong>Best for:</strong> An async screening step embedded in an existing hiring product.</p><h3 id="4-myinterview">4. myInterview</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-24-at-1.19.14-PM.png" class="kg-image" alt="Top 10 Video Interview APIs: Ranked by Fit" loading="lazy" width="2860" height="1618"/></figure><p><a href="https://website-staging.myinterview.com/" rel="noreferrer nofollow">myInterview</a> offers a REST API specifically for one-way video interviews. Its API documentation describes a workflow for creating a job, adding candidates, sending interview links, receiving webhook notifications, and retrieving completed-video analysis. It also documents <code>createJob</code> and <code>createJobWithCandidates</code> flows.</p><p>This model fits recruiting systems that need to create and track async interview tasks directly from their own application. It is less relevant when the core requirement is a fully custom live interview room rather than an application-and-review workflow.</p><p>If you use its completed-video analysis features, read the AI and law section below before you ship them. Automated analysis of candidate video is the most heavily regulated part of this entire category.</p><p><strong>Best for:</strong> API-led, one-way candidate journeys with job and candidate objects.</p><h3 id="5-daily">5. Daily</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.02-PM-5.png" class="kg-image" alt="Top 10 Video Interview APIs: Ranked by Fit" loading="lazy" width="2924" height="1652"/></figure><p><a href="https://www.daily.co/" rel="noreferrer nofollow">Daily</a> is a live-video option for web products that need room-level configuration. Its Create Room API documents room privacy, expiry, pre-join UI, captions, noise cancellation, screen sharing, chat, recordings, transcription settings, and permissions. Its documentation also exposes recordings, transcripts, and webhooks.</p><p>Choose Daily if your team wants a configurable live video layer and plans to build the hiring workflow around it. Candidate records, scheduling, scorecards, and the review experience remain application concerns.</p><p><strong>Best for:</strong> Web-first products that need detailed room configuration and a documented API surface.</p><h3 id="6-100ms">6. 100ms</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.31.12-PM-4.png" class="kg-image" alt="Top 10 Video Interview APIs: Ranked by Fit" loading="lazy" width="2910" height="1656"/></figure><p><a href="https://www.100ms.live/" rel="noreferrer nofollow">100ms</a> combines real-time SDKs with Prebuilt room delivery. Its Prebuilt quickstart documents role-specific room links and native Prebuilt components for React, iOS, Android, Flutter, and React Native. Its templates can define roles, permissions, recording, livestreaming, and transcription behaviour.</p><p>This is useful when candidates, interviewers, observers, and coordinators need different room roles. Build a proof of concept around the exact platform mix you support, because prebuilt feature parity and UI customisation can vary by platform.</p><p><strong>Best for:</strong> Role-aware live interview rooms with a prebuilt path for web and mobile delivery.</p><h3 id="7-zoom-video-sdk">7. Zoom Video SDK</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.32.46-PM-2.png" class="kg-image" alt="Top 10 Video Interview APIs: Ranked by Fit" loading="lazy" width="2920" height="1646"/></figure><p><a href="https://developers.zoom.us/docs/video-sdk/" rel="noreferrer nofollow">Zoom Video SDK</a> is intended for embedding video sessions into your own application rather than dropping users into a standard Zoom meeting. Its developer documentation and event resources support SDK integration and server-side event handling for session awareness.</p><p>It is sensible for organisations already operating in Zoom's developer ecosystem and comfortable implementing their own interview interface. Check the exact SDK support, event coverage, recording requirements, and commercial terms for your target platform.</p><p><strong>Best for:</strong> Teams that already use Zoom's developer platform and need an embedded session layer.</p><h3 id="8-agora">8. Agora</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.26-PM-6.png" class="kg-image" alt="Top 10 Video Interview APIs: Ranked by Fit" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/en/" rel="noreferrer nofollow">Agora</a> supplies real-time engagement SDKs for video calling. Its video calling quickstart documents the client SDK flow for creating a project, joining a channel, and publishing or subscribing to media. That makes it a viable building block for a bespoke interview product.</p><p>Choose Agora when cross-platform media control is the primary engineering concern and your team owns the hiring workflow. It does not replace the ATS, invitation system, scorecard, or post-interview review experience.</p><p><strong>Best for:</strong> Engineering teams building their own interview UI and workflow on top of an RTC SDK.</p><h3 id="9-whereby-embedded">9. Whereby Embedded</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.34.01-PM-2.png" class="kg-image" alt="Top 10 Video Interview APIs: Ranked by Fit" loading="lazy" width="2890" height="1624"/></figure><p><a href="https://whereby.com/information/embedded" rel="noreferrer nofollow">Whereby Embedded</a> is aimed at putting branded browser-based meeting rooms inside another product. It deserves evaluation when you want a faster embedded-room route and the supplied meeting experience is close to the one your candidates and interviewers need.</p><p>Whereby is usually a less natural fit for products that need full media-level control or a broad native SDK plan. Review its current developer documentation against your pre-call checks, host controls, recording requirements, and branding rules before selecting it.</p><p><strong>Best for:</strong> Web products that want an embedded interview room with limited custom media work.</p><h3 id="10-jitsi-meet">10. Jitsi Meet</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-29-at-2.08.49-PM.png" class="kg-image" alt="Top 10 Video Interview APIs: Ranked by Fit" loading="lazy" width="2928" height="1662"/></figure><p><a href="https://jitsi.org/jitsi-meet/" rel="noreferrer nofollow">Jitsi Meet</a> is an open-source meeting stack with an IFrame API for embedding meetings and a route for self-hosting. It is not ranked tenth because it lacks capability. It ranks here because self-managed interviewing adds operational work that a managed API absorbs.</p><p>Choose Jitsi when infrastructure control or open-source ownership outweighs managed-service convenience. Plan for authentication, capacity, observability, upgrades, recording, browser support, and incident response before treating self-hosting as the lower-effort option.</p><p><strong>Best for:</strong> Teams with the operational capacity to run or deeply customise their own meeting stack.</p><h2 id="what-a-video-interview-api-actually-costs">What a Video Interview API Actually Costs</h2><p>Price is the question most comparison pages either dodge or get wrong, because the two categories do not bill on the same unit. Compare the <em>shape</em> of the bill before you compare the number.</p><p><strong>Hiring-workflow APIs</strong> usually bill per seat, per active job, or per completed interview. Cost scales with hiring volume. That is predictable, and it maps cleanly onto a recruiting budget, but it also means a high-volume seasonal hiring push is a linear cost increase with no way to engineer it down.</p><p><strong>RTC APIs</strong> almost always bill per participant-minute, with separate line items for recording, storage, egress, transcription, and sometimes region. Cost scales with <em>interview duration × number of people in the room</em>, which is a different curve entirely. A four-person panel interview costs roughly four times a one-to-one at the same length. Recording is typically billed on top, and stored recordings accrue.</p><p>Three cost traps specific to interviewing:</p><ul><li><strong>Panel size.</strong> Interview products tend to add observers, a second interviewer, a hiring manager, a note-taker, and a scribe bot. On per-participant-minute pricing, every silent observer is a paying participant.</li><li><strong>Storage tail.</strong> Interview recordings are usually kept for months for compliance or dispute reasons. Storage and egress can quietly exceed the live-media bill within a year of steady volume.</li><li><strong>Transcription.</strong> Often priced per minute separately from media, and often the single biggest surprise once you turn on transcripts for every interview rather than for a sample.</li></ul><p>Self-hosting an open-source stack such as Jitsi moves the cost from a vendor invoice to your infrastructure and payroll. That trade is real, not a discount: budget for <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a> capacity, media server scaling, observability, upgrades, browser-compatibility regressions, and on-call.</p><h3 id="videosdk-pricing-for-a-live-interview">VideoSDK Pricing for a Live Interview</h3><p>VideoSDK's pay-as-you-go rates make the live-media portion of an interview forecastable from participant count, duration, and selected artifacts.</p><p>The following rates were verified against the <a href="https://www.videosdk.live/pricing">VideoSDK pricing page</a>:</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Video interview component</th>
<th style="text-align:right">Pay-as-you-go rate</th>
<th>Billing unit</th>
</tr>
</thead>
<tbody>
<tr>
<td>HD video, 720p</td>
<td style="text-align:right">$0.004</td>
<td>Per participant-minute</td>
</tr>
<tr>
<td>Full HD video, 1080p</td>
<td style="text-align:right">$0.008</td>
<td>Per participant-minute</td>
</tr>
<tr>
<td>HD composite meeting recording</td>
<td style="text-align:right">$0.015</td>
<td>Per recorded minute</td>
</tr>
<tr>
<td>Full HD composite meeting recording</td>
<td style="text-align:right">$0.030</td>
<td>Per recorded minute</td>
</tr>
<tr>
<td>Participant video recording</td>
<td style="text-align:right">$0.006</td>
<td>Per participant-minute recorded</td>
</tr>
<tr>
<td>Separate participant video track</td>
<td style="text-align:right">$0.001</td>
<td>Per track-minute</td>
</tr>
<tr>
<td>Real-time transcription</td>
<td style="text-align:right">$0.020</td>
<td>Per transcription minute</td>
</tr>
<tr>
<td>Post-call transcription</td>
<td style="text-align:right">$0.004</td>
<td>Per transcription minute</td>
</tr>
<tr>
<td>Video storage</td>
<td style="text-align:right">$0.003</td>
<td>Per stored video minute per month</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>VideoSDK also provides $20 in credit to a new account. The pay-as-you-go plan is prepaid, has no minimum usage commitment, and lists volume pricing and custom terms for enterprise workloads.</p><p>For a 45-minute HD interview with one candidate and two interviewers, a composite recording, post-call transcription, and one month of storage, the estimated VideoSDK usage is:</p><pre><code class="language-text">HD media:          3 participants × 45 min × $0.004 = $0.540
HD recording:      45 min × $0.015                   = $0.675
Post-call text:    45 min × $0.004                   = $0.180
One-month storage: 45 min × $0.003                   = $0.135
                                                      -------
Estimated total:                                      $1.530
</code></pre><p>Using real-time transcription instead of post-call transcription changes the transcription line from $0.18 to $0.90, producing an estimated total of $2.25. This example excludes taxes, premium support, compliance add-ons, extra concurrency packs, and application-level engineering costs.</p><h2 id="how-to-choose-a-video-interview-api">How to Choose a Video Interview API</h2><p>The best Video Interview API is the one that matches your interview mode and ownership boundary. Pick the category before you compare feature pages.</p><p><strong>Choose async or live first.</strong> Use Hireflix, Willo, or myInterview for one-way candidate responses. Use VideoSDK, Daily, 100ms, Zoom, Agora, Whereby, or Jitsi when candidates and interviewers must meet live inside your product.</p><p><strong>Write down the workflow you must own.</strong> Include scheduling, invite delivery, candidate identity, waiting-room rules, evaluator roles, scorecards, consent, recordings, retention, and ATS write-back.</p><p><strong>Test the pre-call journey.</strong> Run a realistic candidate test on your target browsers and devices. Check camera and microphone permissions, device switching, network recovery, captions, join instructions, and the no-show path.</p><p><strong>Trace every recording and transcript.</strong> Decide who can start, access, download, delete, and retain them. A provider's storage feature does not define your business retention policy.</p><p><strong>Prototype the access model.</strong> Generate room credentials only after your backend verifies the candidate or interviewer, their role, their invitation, and the access window.</p><h2 id="interview-specific-capabilities-to-test">Interview-Specific Capabilities to Test</h2><p>Interview products need role, assessment, review, and candidate-experience checks that generic video API comparisons often miss.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Area</th>
<th>Acceptance question</th>
<th>Why it matters</th>
</tr>
</thead>
<tbody>
<tr>
<td>Observer roles</td>
<td>Can an observer join without publishing media, and can visibility be configured?</td>
<td>Panels should not create avoidable candidate pressure</td>
</tr>
<tr>
<td>Waiting flow</td>
<td>Can candidates wait until an interviewer admits them and recover after refresh?</td>
<td>Join failures become support incidents and no-shows</td>
</tr>
<tr>
<td>Role permissions</td>
<td>Can recording, screen share, removal, and moderation differ by role?</td>
<td>Candidates, interviewers, and coordinators need different powers</td>
</tr>
<tr>
<td>Assessment surface</td>
<td>Can the product place a code editor, whiteboard, or artifact beside the room?</td>
<td>Technical interviews need more than a generic call UI</td>
</tr>
<tr>
<td>Recording format</td>
<td>Are composite, participant, or track-level outputs available?</td>
<td>Review, redaction, and speaker attribution depend on the artifact</td>
</tr>
<tr>
<td>Event coverage</td>
<td>Are join, leave, recording, transcript, and session-end events documented?</td>
<td>Reliable workflow automation needs server-side evidence</td>
</tr>
<tr>
<td>Mobile delivery</td>
<td>Does the interview work on target mobile browsers without an app?</td>
<td>Hourly and field candidates may not have a laptop</td>
</tr>
<tr>
<td>Network recovery</td>
<td>What happens after a mid-answer drop or accidental refresh?</td>
<td>Recovery behavior directly affects fairness and completion rate</td>
</tr>
<tr>
<td>Accessibility</td>
<td>Are controls keyboard reachable, labeled, captioned, and screen-reader tested?</td>
<td>The interview interface is part of the hiring process</td>
</tr>
<tr>
<td>Data lifecycle</td>
<td>Can you locate and delete every copy of video, transcript, and derived score?</td>
<td>Retention and deletion are product requirements</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Require documentation or a reproducible test for every answer. A marketing checkbox is not enough for a hiring-critical workflow.</p><h2 id="ai-interview-features-and-legal-boundaries">AI Interview Features and Legal Boundaries</h2><p>AI analysis changes the risk profile of a Video Interview API because hiring decisions are regulated differently from media transport.</p><p>Separate these features during architecture and procurement:</p><ul><li>Recording and transcription</li><li>Summary or note drafting for a human reviewer</li><li>Candidate scoring or ranking</li><li>Automated selection or rejection</li><li>Emotion, affect, confidence, or personality inference from face or voice</li></ul><p>The <a href="https://eur-lex.europa.eu/eli/reg/2024/1689/2026-07-27/eng">EU AI Act</a> prohibits emotion inference in workplace settings, including recruitment, except for narrow medical or safety uses. It also lists AI used to evaluate candidates as high-risk. The 2026 <a href="https://digital-strategy.ec.europa.eu/en/news/ai-omnibus-enters-force">AI Omnibus timeline</a> moves the application of Annex III high-risk rules to December 2, 2027, but it does not remove the classification.</p><p>The <a href="https://www.ilga.gov/Legislation/ILCS/Articles?ActID=4015&amp;ChapterID=68&amp;Print=">Illinois Artificial Intelligence Video Interview Act</a> requires notice, an explanation, and consent before AI analyzes an applicant-submitted video. It also requires deletion within 30 days of an applicant request and instructing other recipients to delete their copies.</p><p><a href="https://www.nyc.gov/site/dca/about/automated-employment-decision-tools.page">NYC Local Law 144 guidance</a> requires a recent bias audit, public information about the audit, and candidate notices when an automated employment decision tool falls within the law. Colorado's <a href="https://coag.gov/ai/">automated decision-making rulemaking page</a> reflects a revised law scheduled for January 1, 2027, so older summaries of SB 24-205 should not be reused without checking the current text.</p><p>These rules should become engineering requirements: consent records, model and prompt versioning, human review, audit logs, deletion propagation, accommodation paths, and a non-automated alternative where required. This section is a product checklist, not legal advice. Confirm obligations with counsel for every jurisdiction in which candidates are located.</p><h2 id="production-and-accessibility-checklist">Production and Accessibility Checklist</h2><p>A production interview room succeeds only when access, media, evidence, and candidate accommodations work as one system.</p><ul><li>Issue short-lived, server-generated credentials rather than permanent shared room links.</li><li>Explain recording and transcription before capture, then store the consent outcome.</li><li>Provide a pre-call camera, microphone, speaker, and network test.</li><li>Preserve a recovery path for weak connections and accidental refreshes.</li><li>Verify webhook signatures and make event processing idempotent.</li><li>Restrict recordings and transcripts to authorized reviewer roles.</li><li>Define retention and deletion for video, transcripts, notes, and derived scores.</li><li>Provide captions and keyboard-accessible controls with meaningful accessible names.</li><li>Test screen-reader behavior and focus order on the actual embedded experience.</li><li>Offer an accommodation route and an alternative interview format that reaches a human.</li><li>Test a mid-range Android device on a mobile network, not only a laptop on office broadband.</li></ul><p>The <a href="https://www.w3.org/TR/webrtc/">W3C WebRTC Recommendation</a> defines browser APIs for real-time media. It does not define your invitation policy, consent model, evaluation process, or retention schedule.</p><h2 id="definitions-glossary">Definitions Glossary</h2><blockquote><strong>Video Interview API:</strong> An interface that lets a product create, operate, or review remote interviews, either asynchronously or in real time.</blockquote><blockquote><strong>Room:</strong> A VideoSDK meeting space, identified by a room ID, where participants join and exchange media streams.</blockquote><blockquote><strong>Meeting token:</strong> A server-generated JWT that authenticates permitted access to a VideoSDK room.</blockquote><blockquote><strong>One-way interview:</strong> An asynchronous interview where a candidate records responses to prepared questions for later review.</blockquote><blockquote><strong>Pre-call check:</strong> A candidate-facing test of the camera, microphone, device selection, and connection before joining.</blockquote><blockquote><strong>Participant-minute:</strong> The common RTC billing unit one participant present for one minute. Panel interviews multiply this.</blockquote><blockquote><strong>AEDT:</strong> Automated Employment Decision Tool, the defined term in NYC Local Law 144 for tools that score or classify candidates.</blockquote><blockquote><strong>Per-participant recording track:</strong> A recording that stores each participant's media separately rather than as one composited file, which simplifies review, redaction, and speaker attribution.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>Video Interview APIs split into hiring-workflow products for asynchronous screening and RTC platforms for custom live interviews.</li><li>VideoSDK is the strongest fit when you need a branded live interview experience across web and mobile, but your product must own the recruiting workflow.</li><li>Hireflix, Willo, and myInterview are better starting points for one-way screening, candidate invitations, and recruitment-system integration.</li><li>The two categories bill on different units. Async pricing tracks hiring volume; RTC pricing tracks interview length multiplied by room size, plus recording, storage, and transcription.</li><li>AI features carry the heaviest constraints in this category. Emotion inference from candidate video or audio is prohibited in the EU; scoring candidates triggers audit, notice, and impact-assessment duties in several jurisdictions.</li><li>Access tokens, recording consent, transcripts, retention, and review rights should be designed as one system.</li><li>A proof of concept using real candidate devices is more valuable than selecting an API from a feature checklist alone.</li></ul><h2 id="conclusion">Conclusion</h2><p>The strongest Video Interview API is not the provider with the longest feature list. It is the provider that matches your interview mode and the product layer you want to own. Choose a specialist workflow API for fast one-way screening. Choose <a href="https://www.videosdk.live/contact" rel="noreferrer">VideoSDK</a> when you need to build a live, branded interview product around your own candidate and evaluation workflows.</p><p>Start with the VideoSDK <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">React quickstart</a> or <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/getting-started" rel="noreferrer">Prebuilt UI</a> quickstart, then validate the candidate journey before you scale it.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-best-video-interview-api-for-a-custom-live-product">What is the best Video Interview API for a custom live product?</h3><p>For a custom live product, VideoSDK is a strong fit when you need to own the UI, room rules, participant controls, and application data. Its SDKs, Prebuilt UI option, and REST APIs provide the real-time layer, while your product connects interviews to its own scheduling, candidate, and evaluation workflows.</p><h3 id="can-a-video-interview-api-support-asynchronous-interviews">Can a Video Interview API support asynchronous interviews?</h3><p>Yes. A Video Interview API supports asynchronous interviews when it includes candidate recording, invitations, and reviewer workflows. Hireflix, Willo, and myInterview are designed around one-way video interviews, while VideoSDK is better suited to a custom live experience or an async workflow you build yourself.</p><h3 id="does-videosdk-include-an-ats-or-interview-scorecard">Does VideoSDK include an ATS or interview scorecard?</h3><p>No. VideoSDK provides real-time communication infrastructure, so your application owns applicant records, scheduling, scorecards, hiring permissions, and workflow integrations. This separation is useful when those elements must match an existing ATS or a proprietary hiring process.</p><h3 id="how-should-a-video-interview-api-secure-candidate-access">How should a Video Interview API secure candidate access?</h3><p>Secure candidate access with server-generated, time-limited credentials and backend checks for the invitation, role, room, expiry, and attempt limit. VideoSDK documents JWT-based tokens that can include room and participant restrictions, keeping the secret key out of client-side code.</p><h3 id="how-much-does-a-video-interview-api-cost">How much does a Video Interview API cost?</h3><p>Hiring-workflow APIs typically bill per seat, per job, or per completed interview, so cost tracks hiring volume. RTC APIs typically bill per participant-minute, with recording, storage, egress, and transcription as separate lines, so cost tracks interview length multiplied by the number of people in the room. Model your peak month with panels and recording enabled rather than an average, and confirm current rates on each provider's pricing page.</p><h3 id="can-i-use-one-api-for-both-live-and-asynchronous-interviews">Can I use one API for both live and asynchronous interviews?</h3><p>Yes, with a caveat about who builds what. An RTC API like VideoSDK can record a candidate answering prepared questions with no interviewer present, but you build the question sequencing, retake rules, timers, and reviewer experience yourself. A hiring-workflow API ships that flow but will not give you a custom live room. Teams needing both at production quality usually run one of each rather than forcing a single vendor to cover both.</p><h3 id="is-ai-analysis-of-video-interviews-legal">Is AI analysis of video interviews legal?</h3><p>It depends on what the AI does and where the candidate is. Inferring emotion from a candidate's face or voice is prohibited outright in the EU under the AI Act's Article 5. AI that scores or ranks candidates is treated as high-risk under the EU AI Act and triggers notice, audit, or impact-assessment duties under NYC Local Law 144, Illinois HB 3773 and the Illinois AI Video Interview Act, and Colorado's AI framework. Transcription and summarisation for a human reviewer carry substantially lighter obligations. Confirm current requirements with counsel for your candidates' jurisdictions.</p><h3 id="how-many-people-can-join-a-live-interview-room">How many people can join a live interview room?</h3><p>Enough for any realistic panel on every provider listed here, so capacity is rarely the deciding factor. The questions that matter more are whether observers can join without appearing to the candidate, whether roles can carry different permissions, and how per-participant billing treats a silent fifth attendee.</p><h3 id="does-a-video-interview-api-work-on-mobile-browsers-without-an-app">Does a Video Interview API work on mobile browsers without an app?</h3><p>Usually yes for web-based rooms, but support varies by browser, OS version, and feature screen share and virtual backgrounds are the common gaps. If you hire for hourly, field, or high-volume roles, treat mobile browser support as a hard requirement and test it on a mid-range Android device on a mobile network before you shortlist.</p><h3 id="what-should-teams-compare-besides-price">What should teams compare besides price?</h3><p>Compare interview mode, client platforms, pre-call experience, access model, role control, recording and transcription options, webhook coverage, data paths, retention, ATS integrations, and operating model. Check current pricing separately because media, storage, transcription, and support costs can change independently.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 Online Proctoring APIs: Ranked & Compared]]></title><description><![CDATA[An engineering-led ranking of the top 10 online proctoring APIs in 2026, scored on documentation, integration model, webhook events, UI ownership, and data residency rather than marketing claims. Includes a verified per-exam cost model and a build-versus-buy framework.]]></description><link>https://www.videosdk.live/blog/online-proctoring-api</link><guid isPermaLink="false">6a841c8fb3240feb748c96e3</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 24 Aug 2026 11:19:32 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-24--2026--12_07_26-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>An online proctoring API is a programmable service that adds identity verification, live session monitoring, and evidence capture to an exam application you already own. VideoSDK ranks first for teams building proctoring inside their own product, because it exposes the video, recording, identity verification, and event layer directly. Talview and Honorlock lead the turnkey white-label category.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-24--2026--12_07_26-PM.png" alt="Top 10 Online Proctoring APIs: Ranked & Compared"/><p>Most "best proctoring software" lists rank dashboards. That is useless if you are the engineer who has to wire the thing into a platform that already exists.</p><p>This ranking looks at one question instead: what does the integration surface actually give you? Public documentation, authentication model, webhook events, data residency controls, and whether you can own the exam UI or have to hand it over.</p><p>Ten providers made the list. Each is scored on integration control rather than marketing claims, and each entry names the scenario where a different vendor is the better call.</p><h2 id="what-is-an-online-proctoring-api">What Is an Online Proctoring API?</h2><p>An online proctoring API is defined as a set of programmable endpoints and SDKs that let a developer add exam supervision to an application without building the video, storage, and detection stack from scratch.</p><p>An online proctoring API works by exposing four capabilities as callable services: candidate identity verification, live or recorded session capture, behavioural signal generation (face presence, gaze, audio anomalies, second-device detection), and an evidence retrieval layer that returns recordings, flags, and audit logs to your system.</p><p>The distinction that matters for engineering teams is where the exam experience lives. Some vendors give you a hosted exam window and hand back a report. Others give you primitives and expect you to assemble the workflow.</p><p>VideoSDK sits in the second category. Its <a href="https://www.videosdk.live/solutions/auto-proctoring">auto-proctoring solution</a> runs on the same real-time video SDK, cloud recording, and REST APIs used for video calling, plus three documented identity verification endpoints. The exam room, the proctor console, and the recording pipeline all stay inside your product and under your branding.</p><p>That structural difference drives almost every trade-off in this ranking.</p><h2 id="how-we-ranked-these-online-proctoring-apis">How We Ranked These Online Proctoring APIs</h2><p>Every provider here was scored against six criteria a developer can verify without a sales call.</p><ol><li><strong>Documentation accessibility.</strong> Are endpoint references, auth schemes, and event payloads readable before you sign a contract, or gated behind a partner NDA?</li><li><strong>Integration model.</strong> REST API, LTI 1.3, browser extension, embeddable SDK, or a combination. Extension-dependent products constrain which devices you can support.</li><li><strong>Event and webhook surface.</strong> Can your backend react to session state changes in real time, or do you poll for a report after the exam ends?</li><li><strong>UI ownership.</strong> Can you white-label the candidate and proctor experience, or is the test-taker sent to a vendor-hosted window?</li><li><strong>Data residency and deletion controls.</strong> Regional hosting, on-premise options, and per-artefact deletion endpoints for GDPR and FERPA obligations.</li><li><strong>Honest scope.</strong> What the vendor does not do. A proctoring API that quietly excludes the detection model is a different product from one that ships it.</li></ol><p>Rankings reflect fit for developer-led integrations. They are not a claim that one vendor detects cheating more accurately than another, because no independent, reproducible accuracy benchmark exists across these products as of August 2026. Anyone claiming otherwise is quoting vendor marketing.</p><p><strong>A note on method:</strong> this ranking is built from published documentation, vendor product pages, and peer-reviewed research, all verified in August 2026. It is not a hands-on bake-off. Where a figure could not be independently confirmed, it is flagged.</p><h2 id="the-10-best-online-proctoring-apis-in-2026">The 10 Best Online Proctoring APIs in 2026</h2><h3 id="1-videosdk">1. VideoSDK</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.29.39-PM-6.png" class="kg-image" alt="Top 10 Online Proctoring APIs: Ranked & Compared" loading="lazy" width="2906" height="1660"/></figure><p><strong>Best for:</strong> teams building proctoring directly into their own exam or hiring product, with full control over UI, data, and retention.</p><p><a href="https://www.videosdk.live" rel="noreferrer">VideoSDK</a> is a real-time communication platform rather than a packaged proctoring product, and that is precisely why it ranks first for custom builds. You get the <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> room, composed cloud recording, per-participant recording, real-time and post-call transcription, and REST APIs for room and recording orchestration, then you assemble the proctoring workflow on top.</p><p>The documented proctoring feature set includes pre-call environment checks, face capture for candidate verification, automatic image capture at intervals, a double-talk detector that flags multiple voice patterns in a session, a 60-plus participant grid for one-to-many monitoring, and composed plus individual recordings with system-generated logs for auditable review. A live code editor and whiteboard are included, which matters for technical assessments and proctored coding interviews.</p><p>Three identity verification REST endpoints are documented and available on the Enterprise plan:</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Capability</th>
<th>Endpoint</th>
<th>Returns</th>
</tr>
</thead>
<tbody>
<tr>
<td>Document OCR</td>
<td><code>POST /ai/v1/ocr</code></td>
<td>Extracted text fields from an ID document image</td>
</tr>
<tr>
<td>Face Match</td>
<td><code>POST /ai/v1/face-verification/verify</code></td>
<td>Boolean match between two base64 images</td>
</tr>
<tr>
<td>Face Spoof Detection (BETA)</td>
<td><code>POST /ai/v1/face-verification/detect-spoof</code></td>
<td><code>spoof_detected</code> boolean with an accuracy score</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>All three sit at <code>api.videosdk.live</code> and are called server-side with a JWT minted from your API key and secret.</p><p>SDK coverage spans React, React Native, JavaScript, Flutter, Android, iOS, Python, and Unity, with 20-plus frameworks supported overall. Compliance badges on the <a href="https://www.videosdk.live/pricing" rel="noreferrer">pricing page</a> include SOC 2 (AICPA), HIPAA, GDPR, ISO, and CERT-IN. </p><p><strong>Pricing (verified August 2026):</strong> Free tier with a one-time $20 credit and no credit card, then pay-as-you-go <a href="https://www.videosdk.live/pricing" rel="noreferrer">pricing</a> at $0.004 per participant-minute for video, $0.006 per participant-minute for individual participant recording, $0.015 per recorded minute for composed meeting recording, $0.003 per minute of stored video, and $0.004 per minute for post-call transcription.</p><h3 id="2-talview-proctoring-api">2. Talview Proctoring API</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-18-at-2.46.09-PM.png" class="kg-image" alt="Top 10 Online Proctoring APIs: Ranked & Compared" loading="lazy" width="2826" height="1618"/></figure><p><strong>Best for:</strong> certification bodies and assessment vendors that want turnkey detection delivered white-label inside their own platform.</p><p><a href="https://www.talview.com/en/" rel="noreferrer nofollow">Talview</a> markets an explicitly API-first, fully white-labelled proctoring product. Candidate authentication combines face-to-photo-ID matching, facial recognition, and voice matching. The fraud-detection layer targets deepfake impersonation, AI-assisted answering, and hidden secondary devices, which is the threat model that changed most between 2023 and 2026.</p><p>Compliance covers GDPR, SOC 2, ISO 27001, and WCAG 2.1. That last one is unusual in this category and worth weighting if accessibility obligations apply to you.</p><p><strong>Reported pricing:</strong> starting near $10 per exam for automated proctoring, with annual plans reported from roughly $25,000. </p><p><strong>Where a competitor wins:</strong> if you need public API documentation before committing, ProctorExam is more transparent.</p><h3 id="3-honorlock">3. Honorlock</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-18-at-2.46.54-PM.png" class="kg-image" alt="Top 10 Online Proctoring APIs: Ranked & Compared" loading="lazy" width="2888" height="1626"/></figure><p><strong>Best for:</strong> higher-education platforms and LMS vendors that want both a fast LMS install and a real developer path.</p><p><a href="https://honorlock.com/" rel="noreferrer nofollow">Honorlock</a> offers APIs plus an "Elements" toolkit and an Integration SDK, alongside native Canvas, Blackboard, Brightspace, and Moodle integrations. Authentication is API key and secret. Its differentiators are genuinely distinctive: patented secondary-device detection that identifies phones and tablets accessing test-bank content mid-exam, and Search and Destroy, which locates leaked exam questions on third-party sites and pursues removal.</p><p>Live Pop-In inserts a human proctor into a flagged session rather than failing the candidate automatically, which reduces the false-accusation problem. Honorlock is SOC 2 Type 2 certified.</p><p><strong>Where a competitor wins:</strong> for non-education use cases such as pre-hire assessment at global scale, Talview and Mettl have deeper workflow coverage.</p><h3 id="4-proctorio">4. Proctorio</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-18-at-2.47.35-PM.png" class="kg-image" alt="Top 10 Online Proctoring APIs: Ranked & Compared" loading="lazy" width="2794" height="1560"/></figure><p><strong>Best for:</strong> institutions standardising on automated, LMS-embedded proctoring at very high volume.</p><p><a href="https://proctorio.com/" rel="noreferrer nofollow">Proctorio</a> integrates through LTI or through APIs for third-party assessment platforms, and it publishes Apache-licensed API client libraries on GitHub, including a .NET client. It advertises zero-knowledge encryption and a design that minimises collection of personally identifiable information.</p><p>The architectural constraint is the browser extension. Proctorio requires a Chrome extension on the test-taker's machine, which rules out most tablets, some Chromebook configurations, and any candidate who cannot install software. Treat that as a candidate-eligibility decision, not a preference.</p><h3 id="5-proctorexam">5. ProctorExam</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-18-at-2.48.15-PM.png" class="kg-image" alt="Top 10 Online Proctoring APIs: Ranked & Compared" loading="lazy" width="2866" height="1620"/></figure><p><strong>Best for:</strong> European programmes that need public API documentation and per-artefact deletion control.</p><p><a href="https://proctorexam.com/" rel="noreferrer nofollow">ProctorExam</a> publishes its full v3 REST reference openly, along with an events reference, LTI documentation, and public code samples. That transparency is rare here and it is why ProctorExam ranks above larger vendors.</p><p>The API is conventional and readable. Authentication uses a token in the <code>Authorization</code> header, with a versioned <code>Accept</code> header of <code>application/vnd.procwise.v3</code>. Resources cover exams, student sessions, documents, attachments, users, and LTI resources, with filtering and sorting passed as stringified JSON query parameters.</p><h3 id="6-mercer-mettl">6. Mercer | Mettl</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-18-at-2.53.14-PM.png" class="kg-image" alt="Top 10 Online Proctoring APIs: Ranked & Compared" loading="lazy" width="2804" height="1476"/></figure><p><strong>Best for:</strong> enterprise hiring and certification programmes, particularly across India and wider APAC.</p><p><a href="https://mettl.com/" rel="noreferrer nofollow">Mettl</a> runs proctoring as a discrete service with a versioned endpoint namespace, and it offers deep REST integration alongside LTI connectivity to a large catalogue of LMS platforms. Its SecureProctor product adds kiosk and lockdown mode, clipboard restrictions, developer-tools blocking, and navigation logging.</p><p>The strength here is breadth of assessment workflow rather than the proctoring layer alone. Coding simulators, psychometric batteries, and code-playback review all sit in the same platform.</p><p><strong>Where a competitor wins:</strong> if you only need proctoring and already own your assessment engine, Mettl's platform surface is more than you need.</p><h3 id="7-constructor-proctor">7. Constructor Proctor</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-18-at-3.01.08-PM.png" class="kg-image" alt="Top 10 Online Proctoring APIs: Ranked & Compared" loading="lazy" width="2888" height="1566"/></figure><p><strong>Best for:</strong> programmes with data-sovereignty requirements or a mandate against algorithmic decisions.</p><p>Formerly Examus, <a href="https://constructor.tech/products/learning/proctor" rel="noreferrer nofollow">Constructor Proctor</a> offers an open API, LTI, a dedicated Moodle plugin, and standalone exam links. It is one of very few vendors offering on-premise and air-gapped deployment plus regional hosting, and it supports proctoring modes that operate without video recording for privacy-sensitive jurisdictions.</p><p>Its published governance position is explicit: AI raises flags, your reviewers confirm them, and no candidate is sanctioned by an algorithm alone. Detection covers face, gaze, voice, device presence, virtual machines, and second screens.</p><p><strong>A discrepancy worth knowing:</strong> third-party directories list support for up to 50,000 concurrent exams, while Constructor's own product page states 10,000-plus concurrent sessions and up to 150 candidates per live proctor. Use the vendor figure and confirm against your peak. </p><h3 id="8-meazure-learning-proctoru">8. Meazure Learning (ProctorU)</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-18-at-2.54.36-PM.png" class="kg-image" alt="Top 10 Online Proctoring APIs: Ranked & Compared" loading="lazy" width="2900" height="1484"/></figure><p><strong>Best for:</strong> high-stakes licensure and credentialing that requires scheduled live human proctors.</p><p><a href="https://www.meazurelearning.com/exam-technology/proctoru-online-proctoring" rel="noreferrer nofollow">ProctorU</a> shipped one of the first proctoring APIs in the category back in 2012, and the current Meazure Learning platform exposes exam scheduling APIs, JWT-based integration, LTI 1.3, SAML, a Record+ integration API, and an external-resources configuration API that declares exactly which materials a candidate may use.</p><p>That last one reflects the operational reality of licensure exams. The permitted-materials list is a compliance artefact, not a UI preference, and having it in the API is genuinely useful.</p><p><strong>Reported pricing:</strong> roughly $25 to $45 per exam for automated monitoring and $40 to $70-plus per live session, with other sources reporting live supervision starting near $20 for the first hour. The spread across sources is wide.</p><h3 id="9-smowl">9. SMOWL</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-18-at-2.55.20-PM.png" class="kg-image" alt="Top 10 Online Proctoring APIs: Ranked & Compared" loading="lazy" width="2844" height="1540"/></figure><p><strong>Best for:</strong> continuous identity verification across a whole course, on constrained bandwidth.</p><p><a href="https://smowl.net/es/" rel="noreferrer nofollow">SMOWL</a> is API-key driven with a Moodle Certified Integration and connectors for Blackboard, Brightspace, and Skillsoft. Its distinguishing model is continuous assessment proctoring: verifying the learner across every course activity rather than only during a final exam, using facial recognition, voice recognition, and keystroke biometrics.</p><p>It advertises among the lowest bandwidth consumption in the category, which is a real constraint for candidates on mobile networks or in low-connectivity regions. Compliance covers GDPR, FERPA, CCPA, and WCAG 2.1, and typical LMS integration is described as taking about two days.</p><h3 id="10-monitorexam">10. MonitorExam</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-18-at-2.57.24-PM.png" class="kg-image" alt="Top 10 Online Proctoring APIs: Ranked & Compared" loading="lazy" width="2900" height="1654"/></figure><p><strong>Best for:</strong> small teams that want a modern front-end SDK and per-delivered-exam billing.</p><p><a href="https://monitorexam.com/" rel="noreferrer nofollow">MonitorExam</a> is the newest entrant here and the most developer-shaped. It ships a React SDK with a <code>useProctoringSession</code> hook exposing feature flags for camera, microphone, face detection, tab-switch, and fullscreen enforcement, plus <code>onWarning</code> and <code>onSessionEnd</code> callbacks, an overlay component, and a metering client. Sandbox access and an API key are available without an enterprise contract.</p><p>Billing is per delivered exam with no monthly minimum, which suits variable volume.</p><p><strong>The honest caveat:</strong> it is a young product with a small deployed base compared with everything above it. For a certification programme where a challenged result may end up in front of a regulator, that track record gap matters. Treat it as a strong fit for internal assessment and mid-stakes testing.</p><h2 id="online-proctoring-api-comparison-integration-and-control">Online Proctoring API Comparison: Integration and Control</h2><p>The table below compares the integration surface, not detection accuracy, because integration surface is the part you can verify yourself.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Provider</th>
<th>Integration model</th>
<th>Public API docs</th>
<th>UI ownership</th>
<th>Behavioural detection included</th>
<th>Best for</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td>SDKs (20+ frameworks) + REST + identity APIs</td>
<td>Yes</td>
<td>Full, your app</td>
<td>Yes</td>
<td>Custom builds, data ownership</td>
</tr>
<tr>
<td>Talview</td>
<td>API-first, white-label</td>
<td>Partial</td>
<td>Full white-label</td>
<td>Yes</td>
<td>White-label turnkey at scale</td>
</tr>
<tr>
<td>Honorlock</td>
<td>API + Elements SDK + LTI</td>
<td>Partial</td>
<td>Mostly</td>
<td>Yes</td>
<td>Higher-ed platforms</td>
</tr>
<tr>
<td>Proctorio</td>
<td>LTI + API + Chrome extension</td>
<td>Partial (GitHub clients)</td>
<td>Limited</td>
<td>Yes</td>
<td>High-volume automated LMS exams</td>
</tr>
<tr>
<td>ProctorExam</td>
<td>REST v3 + Events + LTI</td>
<td>Yes, fully open</td>
<td>White-label</td>
<td>Yes</td>
<td>EU data protection, open docs</td>
</tr>
<tr>
<td>Mercer / Mettl</td>
<td>REST + LTI</td>
<td>Gated</td>
<td>Partial</td>
<td>Yes</td>
<td>Enterprise hiring, APAC</td>
</tr>
<tr>
<td>Constructor Proctor</td>
<td>Open API + LTI + Moodle plugin</td>
<td>Partial</td>
<td>Partial</td>
<td>Yes</td>
<td>On-prem, air-gapped, sovereignty</td>
</tr>
<tr>
<td>Meazure Learning</td>
<td>Scheduling API + JWT + LTI 1.3</td>
<td>Gated (support portal)</td>
<td>Limited</td>
<td>Yes, plus humans</td>
<td>High-stakes licensure</td>
</tr>
<tr>
<td>SMOWL</td>
<td>API key + LMS plugins</td>
<td>Gated</td>
<td>Partial</td>
<td>Yes</td>
<td>Continuous verification, low bandwidth</td>
</tr>
<tr>
<td>MonitorExam</td>
<td>React SDK + REST</td>
<td>Yes</td>
<td>Full</td>
<td>Yes</td>
<td>Small teams, variable volume</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The column that decides most architectures is UI ownership. If a candidate must leave your product to sit an exam, your support burden, your branding, and your analytics all fragment across two vendors. VideoSDK and ProctorExam are the two entries that keep the entire candidate journey inside your application, by different routes: one by giving you primitives, the other by white-labelling a finished service.</p><h2 id="what-does-an-online-proctoring-exam-cost-per-candidate">What Does an Online Proctoring Exam Cost Per Candidate?</h2><p>A 60-minute recorded proctored exam costs roughly $1.02 per candidate in VideoSDK infrastructure list pricing, against reported turnkey vendor prices of $5 to $45 per exam.</p><p>Here is the calculation, using VideoSDK's published August 2026 rates for one candidate, recorded individually, with post-call transcription and no live proctor.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Line item</th>
<th>Rate</th>
<th>60-minute exam</th>
</tr>
</thead>
<tbody>
<tr>
<td>Video (1 participant)</td>
<td>$0.004 / participant-min</td>
<td>$0.240</td>
</tr>
<tr>
<td>Individual participant recording</td>
<td>$0.006 / participant-min</td>
<td>$0.360</td>
</tr>
<tr>
<td>Storage</td>
<td>$0.003 / min stored</td>
<td>$0.180</td>
</tr>
<tr>
<td>Post-call transcription</td>
<td>$0.004 / min</td>
<td>$0.240</td>
</tr>
<tr>
<td><strong>Total</strong></td>
<td/>
<td><strong>$1.02</strong></td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Two adjustments worth modelling. Adding a composed meeting recording on top of the per-participant file costs $0.015 per recorded minute, or $0.90 more per exam. Adding a live proctor supervising twenty candidates at once raises the amortised cost by roughly $0.012 per exam, because the proctor bills as one more participant. </p><p><strong>Read this before you quote that number to a CFO.</strong> The $1.02 buys media transport, recording, storage, and transcription. Face match, liveness, and OCR sit on the Enterprise plan and are quoted separately. Gaze estimation, object detection, a proctor console, and a reviewer workflow are engineering months plus vision-API spend. The turnkey figures of roughly $5 per attempt for automated Proctorio, around $12 for Honorlock's hybrid model, and from $20 for ProctorU live supervision include all of that, plus support and liability. </p><p>The build case gets strong at volume, when you need the exam UI inside your own product, or when data residency rules out a US-hosted vendor. Below roughly 20,000 exams a year, buying almost always wins on total cost.</p><h2 id="should-you-build-or-buy-online-proctoring">Should You Build or Buy Online Proctoring?</h2><p>Build when you control the assessment product and the exam experience is part of your differentiation. Buy when proctoring is a compliance checkbox on someone else's exam.</p><p><strong>Build with an RTC platform when:</strong></p><ul><li>The exam happens inside a product you own and candidates should never leave it</li><li>You need custom detection logic tied to your own question types, such as code-editor telemetry</li><li>Data must stay in a specific region, or recordings must live in your own object storage</li><li>You already run vision or audio ML and can extend it</li><li>Annual exam volume is high enough that per-exam vendor fees exceed engineering cost</li></ul><p><strong>Buy a turnkey proctoring API when:</strong></p><ul><li>You need to be live in weeks, not quarters</li><li>Results may be legally challenged and you want vendor-backed evidence and expert testimony</li><li>You have no ML capacity and no plan to hire it</li><li>Human proctors are a programme requirement, as with most licensure exams</li><li>A secure browser or lockdown client is mandatory from day one</li></ul><p><strong>Buy both when:</strong> your product runs low-stakes assessment continuously (where infrastructure cost dominates) and high-stakes certification occasionally (where defensibility dominates). Splitting by stakes level is the most common production pattern and almost nobody writes about it.</p><h2 id="what-should-developers-test-before-choosing-a-proctoring-api">What Should Developers Test Before Choosing a Proctoring API?</h2><p>A polished administration dashboard does not compensate for an integration surface your team cannot reliably automate. Before you commit, verify these against a sandbox rather than a sales deck.</p><p><strong>Integration surface:</strong></p><ul><li>How sessions are created and torn down</li><li>Authentication and token expiry model</li><li>Candidate identity endpoints and their false-match behaviour</li><li>Recording APIs, including per-participant versus composed output</li><li>Webhook delivery guarantees and retry policy</li><li>Evidence and report retrieval</li><li>Data-retention controls and storage ownership</li><li>Rate limits, sandbox availability, and API versioning policy</li></ul><p><strong>Failure conditions:</strong></p><ul><li>Slow or unstable connections and mid-exam reconnection</li><li>Camera permission denial and microphone failure</li><li>Screen-share interruption and browser refresh</li><li>Laptop sleep and second-monitor behaviour</li><li>Mobile devices and corporate firewalls</li><li>Very long exams that outlive a token</li></ul><p>VideoSDK's <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/setup-call/precall" rel="noreferrer">pre-call setup</a> covers media permission checks and device preparation before a candidate joins, which catches a large share of these before the exam clock starts. Whatever vendor you pick, test the full candidate journey on a bad network. Most integration failures show up there, not in the happy path.</p><h2 id="fairness-and-privacy-risks-in-ai-proctoring">Fairness and Privacy Risks in AI Proctoring</h2><p>Automated proctoring carries documented demographic bias, and the integration decisions you make as a developer either amplify it or contain it.</p><p>The most-cited quantitative study is <a href="https://www.frontiersin.org/journals/education/articles/10.3389/feduc.2022.881449/full">Yoder-Himes et al. (2022)</a>, published in <em>Frontiers in Education</em>. The researchers analysed instructor outputs for roughly 357 students across four STEM courses at the University of Louisville, using Respondus Monitor as deployed in Fall 2020.</p><p>Students with darker skin tones had their faces detected for an average of 78% of an assessment, against 87% for medium skin tones and 92% for lighter skin tones. Those students were flagged for an average of 7.64% of their exam time, compared with 3.33% and 1.56% respectively, and received 6.07 flags per assessment against 1.91 and 1.19. Women with the darkest skin tones were flagged 5.6 times more often than lighter-skinned women.</p><p>The control finding is the one that matters most for engineering teams. When researchers reviewed 298 session videos by hand, they found no significant difference in actual cheating behaviour across skin tone, race, or sex. The disparity was in the detector, not the candidates. The authors note the study covers one product and one version, so treat it as evidence about the category rather than a verdict on a single vendor.</p><p>A separate 2025 arXiv study by Kwapisz et al. at the University of Washington, <a href="https://arxiv.org/abs/2511.10826">Surveillance and Disability in Online Proctored Exams</a>, documents a parallel problem. Flagging rules built around "look at the screen, do not move unusually" systematically penalise neurodivergent test-takers who stim, candidates with medical conditions, and carers attending to a child or elder mid-exam.</p><p>Three engineering decisions follow directly from that evidence.</p><p><strong>Never auto-fail on a flag.</strong> Constructor Proctor, Honorlock, and Integrity Advocate all build human confirmation into the product for this reason. If you are building on VideoSDK or any other infrastructure layer, that review queue is your responsibility and it is not optional.</p><p><strong>Instrument your own false-positive rate by cohort.</strong> You cannot detect disparate impact you are not measuring. Log flag rates against whatever demographic data you already hold lawfully, and watch the gaps.</p><p><strong>Minimise and expire biometric data.</strong> ProctorExam's per-artefact deletion endpoints and five-minute expiring URLs are a good model to copy. Store the least you can defend keeping, and delete it on a schedule your DPO signed off.</p><p>Market forecasts for this category disagree sharply, which itself says something about how unsettled it is. 360iResearch put the online proctoring software market at $1.36 billion in 2025, rising to $1.49 billion in 2026 at a 10.14% CAGR. Other 2026 estimates for adjacent definitions of the same market range from roughly $0.83 billion to $2.01 billion. Treat any single figure with suspicion. </p><h2 id="glossary">Glossary</h2><blockquote><strong>Online proctoring API:</strong> A programmable interface for adding identity verification, session monitoring, and evidence capture to an exam application. Vendors differ mainly in whether the candidate stays inside your product or is redirected to theirs.</blockquote><blockquote><strong>Room:</strong> A VideoSDK meeting room that participants join and share media streams within, identified by a unique room ID. In a proctoring build, one room typically maps to one exam session.</blockquote><blockquote><strong>Meeting token:</strong> A JWT that authenticates a participant's access to a VideoSDK room, generated server-side with scoped permissions and a short expiry.</blockquote><blockquote><strong>Participant recording:</strong> A per-participant media recording, distinct from a composed recording of the whole session. For proctoring, individual recordings make per-candidate review and per-candidate retention policies far simpler.</blockquote><blockquote><strong>Liveness check:</strong> A test confirming the face in frame belongs to a live person rather than a printed photo, screen replay, or looped video. VideoSDK exposes this through its Face Spoof Detection API, which returns a <code>spoof_detected</code> boolean.</blockquote><blockquote><strong>LTI 1.3:</strong> The IMS Global standard for launching external tools from an LMS with signed identity claims. It is the fastest path into Canvas, Moodle, Blackboard, and Brightspace, and it is not a substitute for a REST API.</blockquote><blockquote><strong>Secure browser / lockdown mode:</strong> A kiosk-style client that restricts tab switching, clipboard access, virtual machines, and second screens during an exam. It raises the cheating cost but excludes candidates who cannot install software.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>The right online proctoring API depends on whether the exam lives inside your product or the vendor's, and that single decision constrains every other trade-off.</li><li>VideoSDK is the strongest choice for custom builds because its SDKs, cloud recording, identity verification endpoints, and REST APIs keep the exam room, proctor console, and recordings inside your application, at roughly $1.02 in infrastructure cost for a 60-minute recorded exam.</li><li>VideoSDK covers identity but not behaviour, so teams that need gaze tracking, object detection, or a secure browser should either build that layer or buy a turnkey API such as Talview, Honorlock, or ProctorExam.</li><li>ProctorExam publishes the most transparent developer documentation in this category, including per-artefact biometric deletion endpoints that map directly onto GDPR obligations.</li><li>Peer-reviewed research found measurable demographic bias in automated flagging with no matching difference in actual cheating behaviour, so mandatory human review of flags is an engineering requirement rather than a policy nicety.</li></ul><h2 id="conclusion">Conclusion</h2><p>Choosing an online proctoring API in 2026 is less about detection features and more about where you want the boundary between your product and your vendor to sit. Buy turnkey when defensibility and speed matter most. Build on infrastructure when the exam experience is your product and the data has to stay yours. Whichever way you go, put a human between a flag and a consequence.</p><p>If you are building rather than buying, start with the <a href="https://www.videosdk.live/solutions/auto-proctoring">VideoSDK auto-proctoring solution</a> and the <a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">REST API reference</a>, then grab an API key with $20 of free credit. </p><p>Working examples live at <a href="https://docs.videosdk.live/code-sample">code sample</a>, and the <a href="https://discord.com/invite/Gpmj6eCq5u">VideoSDK Discord</a> is where integration questions get answered fastest.</p><p>What are you building with a proctoring API? Drop a comment with your stack, especially if you have solved the behavioural detection layer in a way worth stealing.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-best-online-proctoring-api-for-developers">What is the best online proctoring API for developers?</h3><p>The best online proctoring API for developers depends on UI ownership. VideoSDK is the strongest fit when the exam must run inside your own product with your own branding and data retention, because it exposes video, recording, identity verification, and REST orchestration directly. Talview and Honorlock are better when you need trained behavioural detection delivered turnkey and cannot build it yourself.</p><h3 id="does-videosdk-provide-online-proctoring">Does VideoSDK provide online proctoring?</h3><p>VideoSDK provides the infrastructure for online proctoring rather than a packaged proctoring product. Its documented capabilities include pre-call environment checks, face capture, periodic image capture, a double-talk detector for multiple voice patterns, a 60-plus participant monitoring grid, cloud and per-participant recording, transcription, and three identity verification REST APIs covering document OCR, face matching, and spoof detection. Behavioural detection such as gaze estimation and object recognition is built by your team on top of that layer.</p><h3 id="how-much-does-an-online-proctoring-api-cost">How much does an online proctoring API cost?</h3><p>Turnkey online proctoring APIs are commonly reported at roughly $5 per attempt for fully automated monitoring, around $12 for hybrid AI-plus-human models, and $20 to $70 for live human proctoring, though most vendors quote privately. Building on infrastructure such as VideoSDK costs roughly $1.02 per 60-minute recorded exam in list-price media, recording, storage, and transcription, excluding Enterprise-plan identity APIs, behavioural detection, and engineering time.</p><h3 id="which-online-proctoring-apis-publish-open-documentation">Which online proctoring APIs publish open documentation?</h3><p>ProctorExam publishes the most complete open documentation, with a full v3 REST reference, an events reference, LTI documentation, and public code samples. VideoSDK publishes complete SDK and REST documentation at docs.videosdk.live, including its identity verification endpoints. Proctorio publishes Apache-licensed API client libraries on GitHub. Most other vendors gate their references behind a partner agreement.</p><h3 id="can-i-use-an-online-proctoring-api-without-an-lms">Can I use an online proctoring API without an LMS?</h3><p>Yes. Every provider in this ranking supports integration outside a learning management system, either through REST APIs, an embeddable SDK, or standalone exam links. LTI 1.3 is the fastest route if you already run Canvas, Moodle, Blackboard, or Brightspace, but it is a launch protocol rather than a complete integration path, and you will still want the REST surface for provisioning and evidence retrieval.</p><h3 id="is-ai-proctoring-biased-against-some-students">Is AI proctoring biased against some students?</h3><p>Peer-reviewed research documents measurable bias. Yoder-Himes et al. (2022) found that an automated proctoring product detected the faces of students with the darkest skin tones for 78% of an assessment on average, against 92% for lighter skin tones, and flagged them for 7.64% of exam time against 1.56%. Manual review of the same sessions found no matching difference in actual cheating behaviour. Separate 2025 research documents systematic over-flagging of neurodivergent and disabled test-takers. Mandatory human review of every flag is the standard mitigation.</p><h3 id="what-is-the-difference-between-lti-13-and-a-proctoring-rest-api">What is the difference between LTI 1.3 and a proctoring REST API?</h3><p>LTI 1.3 launches a proctoring tool from inside an LMS using signed identity claims, so it handles authentication and context handoff. A REST API handles everything else: creating exams programmatically, provisioning candidates, controlling recordings, retrieving flags and evidence, and deleting biometric artefacts. Most production integrations use both, with LTI for launch and REST for lifecycle management.</p>]]></content:encoded></item><item><title><![CDATA[10 Best Live Streaming APIs & SDKs for Real-Time Video Apps 2026]]></title><description><![CDATA[The 10 best live streaming APIs in 2026, ranked with verified pricing, latency profiles, and honest "best for" verdicts: VideoSDK for interactive sub-second streams, Mux and Amazon IVS for HLS broadcast, LiveKit for open source, plus a decision framework and free-tier comparison.]]></description><link>https://www.videosdk.live/blog/10-best-live-streaming-api</link><guid isPermaLink="false">64ec8d109eadee0b8b9e80e2</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 18 Aug 2026 11:32:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-19--2026--04_29_37-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>The best live streaming APIs in 2026 are VideoSDK, Agora, Mux, Amazon IVS, and LiveKit. VideoSDK leads for interactive, sub-second streaming across 10+ platform SDKs, Mux and Amazon IVS lead for large one-way HLS broadcasts, and LiveKit leads for open-source, self-hosted deployments. Your latency requirement decides which one fits.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-19--2026--04_29_37-PM.png" alt="10 Best Live Streaming APIs & SDKs for Real-Time Video Apps 2026"/><p>A live stream delivered over standard <a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer">HLS</a> arrives 20 or more seconds after the camera captures it, while a <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> stream arrives in under 500 milliseconds. That gap decides whether your live auction, tutoring session, or shopping stream actually works.</p><p>Building this infrastructure yourself means running media servers, transcoding pipelines, and CDN contracts before you ship a single feature. A live streaming API replaces all of that with a few SDK calls. This guide ranks the 10 best live streaming APIs available in 2026, with verified pricing, latency profiles, and honest "best for" verdicts, so you can pick the right foundation for your video product.</p><h2 id="what-is-a-live-streaming-api">What Is a Live Streaming API?</h2><p>A live streaming API is defined as an application programming interface that lets developers add real-time video broadcasting and playback to their applications without building encoding, media server, or delivery infrastructure themselves.</p><p>A live streaming API works by ingesting a broadcaster's video feed, transcoding it into multiple quality levels, and distributing it to viewers through either a global CDN (for HLS broadcasts) or a real-time network (for WebRTC streams).</p><p>VideoSDK provides live streaming through its <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">Interactive Live Streaming (ILS) API</a>, which keeps latency under a second so viewers can chat, vote, and even join the stream as co-hosts. That interactivity is the dividing line in this market: some APIs are built for reach, others for real-time participation, and the best choice depends on which one your product needs.</p><h2 id="how-do-live-streaming-apis-work">How Do Live Streaming APIs Work?</h2><p>Live streaming APIs work by handling four stages of the video pipeline: ingest, transcoding, delivery, and playback.</p><ol><li><strong>Ingest.</strong> The broadcaster's device sends video to the provider's servers over <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a>, <a href="https://www.videosdk.live/developer-hub/rtmp/rtmp/implementing-srt-streaming-developers-guide/implementing-srt-streaming-developers-guide#what-is-srt-secure-reliable-transport-and-why-should-developers-care" rel="noreferrer">SRT</a>, or WebRTC. RTMP remains the standard for encoder software like OBS, while WebRTC is used when the broadcaster is inside your app.</li><li><strong>Transcoding.</strong> The single incoming feed is converted into multiple renditions (1080p, 720p, 480p) so adaptive bitrate streaming can match each viewer's connection speed.</li><li><strong>Delivery.</strong> HLS-based APIs push segments through a CDN, which scales to millions of viewers but adds delay. WebRTC-based APIs route media through an SFU (Selective Forwarding Unit), which keeps latency under a second but requires real-time infrastructure in every region.</li><li><strong>Playback.</strong> The viewer's player requests the stream and switches quality levels automatically as bandwidth changes.</li></ol><p>For reference on the protocol layer itself, the <a href="https://www.w3.org/TR/2018/CR-webrtc-20180927/" rel="noreferrer">W3C maintains the WebRTC specification</a> that real-time providers implement. </p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-19--2026--03_11_07-PM.png" class="kg-image" alt="10 Best Live Streaming APIs & SDKs for Real-Time Video Apps 2026" loading="lazy" width="1672" height="941"/></figure><h2 id="interactive-vs-broadcast-which-type-of-live-streaming-api-do-you-need">Interactive vs Broadcast: Which Type of Live Streaming API Do You Need?</h2><p>Every provider on this list falls into one of two architectures, and picking the wrong one is the most common mistake teams make.</p><p><strong>Interactive live streaming APIs</strong> (VideoSDK, Agora, LiveKit, 100ms, ZEGOCLOUD) run on WebRTC. Latency stays under a second, viewers can be promoted to speakers, and the same infrastructure handles video calls. Use this architecture for <a href="https://videosdk.live/solutions/live-shopping" rel="noreferrer">live shopping</a>, auctions, tutoring, town halls, and any stream where the audience talks back.</p><p><strong>Broadcast streaming APIs</strong> (Mux, Amazon IVS, api.video, Dacast, and Wowza) ingest over RTMP or SRT and deliver over HLS. Latency runs from about 3 seconds (low-latency HLS) to 30 seconds (standard HLS), but a single stream can reach millions of passive viewers at lower cost per viewer. Use this architecture for sports, events, and one-to-many broadcasts.</p><p>According to Mux's own pricing documentation, standard HLS delivery carries 20 or more seconds of latency, while its <a href="https://www.videosdk.live/blog/what-is-low-latency-http-live-streaming" rel="noreferrer">LL-HLS</a> mode reduces that to 4 to 7 seconds. No HLS mode reaches the sub-second range that WebRTC provides, which is why the two architectures are complements, not substitutes.</p><h2 id="how-we-evaluated-these-live-streaming-apis">How We Evaluated These Live Streaming APIs</h2><p>Each provider was scored against five criteria that map to real integration decisions:</p><ol><li><strong>Latency profile:</strong> verified glass-to-glass latency for the provider's primary delivery mode.</li><li><strong>SDK and platform coverage:</strong> native SDKs for web, iOS, Android, React Native, and Flutter.</li><li><strong>Pricing transparency:</strong> published rates checked against official pricing pages in August 2026.</li><li><strong>Interactivity features:</strong> role switching, chat, polls, co-hosting, and recording.</li><li><strong>Scale ceiling:</strong> documented concurrent viewer limits and CDN or SFU reach.</li></ol><h2 id="the-10-best-live-streaming-apis-in-2026">The 10 Best Live Streaming APIs in 2026</h2><p>The top 10 live streaming APIs and SDKs in 2026 are VideoSDK, Agora, Mux, Amazon IVS, LiveKit, 100ms, ZEGOCLOUD, api.video, Dacast, and Wowza. The first five cover most production use cases; the rest win in specific niches.</p><h3 id="1-videosdk">1. VideoSDK</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-14-130930-1.png" class="kg-image" alt="10 Best Live Streaming APIs & SDKs for Real-Time Video Apps 2026" loading="lazy" width="1523" height="727"/></figure><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> is a real-time communication platform that treats interactive live streaming as a first-class API rather than an add-on to video calling. Streams run over WebRTC with sub-second latency, and a single <code>changeMode()</code> call moves a participant between conference mode and streaming mode, so a viewer can be promoted to co-host without rejoining. </p><p><strong>Key capabilities:</strong></p><ul><li>Interactive live streaming with hosts, co-hosts, and viewers, plus dynamic role switching mid-stream</li><li>SDKs for React, JavaScript, React Native, Android, iOS, Flutter, Unity, C++, IoT, and Python, the broadest platform coverage among the providers on this list</li><li>A <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start" rel="noreferrer">prebuilt UI Kit</a> that embeds a working stream interface without custom UI code </li><li>Network-adaptive streaming that adjusts bitrate and resolution per viewer in real time</li><li>In-stream chat, polls, Q&amp;A, whiteboard, cloud recording, and real-time transcription in the same SDK</li><li><a href="https://www.videosdk.live/blog/rtmp-out-how-live-streaming-really-works" rel="noreferrer">RTMP output</a> for simulcasting the stream to YouTube, Twitch, and other platforms</li></ul><p><strong>Pricing:</strong> Pay-as-you-go. <a href="https://www.videosdk.live/pricing" rel="noreferrer">Audio starts at $0.001 per participant-minute</a> and video at $0.004 per participant-minute; interactive live streams are billed on host and viewer minutes, with viewer minutes priced at a fraction of host rates. New accounts receive a one-time $20 free credit with no credit card required. </p><p><strong>Best for:</strong> Teams building interactive streaming (live commerce, tutoring, auctions, social audio and video) who also want video calling, recording, and AI voice capabilities from one SDK surface.</p><p><strong>Limitation:</strong> Documentation for newer capabilities like the <a href="https://docs.videosdk.live/ai_agents/voice-agent-quick-start" rel="noreferrer">AI Agent SDK</a> is still expanding, so advanced use cases may require checking recent release notes or the Discord community for guidance.</p>
<!--kg-card-begin: html-->
<div class="relative w-full overflow-hidden rounded-2xl p-6 text-center" style="
    background: linear-gradient(135deg, #18131f 0%, #271b38 55%, #38245a 100%);
    border: 1px solid rgba(209, 188, 253, 0.28);
    box-shadow:
      0 12px 40px rgba(0, 0, 0, 0.35),
      0 0 40px rgba(209, 188, 253, 0.08);
    border-radius: 16px;
    padding: 32px 24px;
    margin: 32px 0;
  ">
  <h3 style="
      margin: 0 0 12px;
      font-size: 28px;
      line-height: 1.3;
      font-weight: 700;
      color: #ffffff;
    ">
    Schedule a Demo with Our Live Video Expert!
  </h3>

  <p style="
      margin: 0 auto;
      max-width: 680px;
      font-size: 16px;
      line-height: 1.6;
      color: #c7c7cc;
    ">
    Discover how VideoSDK can help you build a cutting-edge real-time video app.
  </p>

  <div style="margin-top: 24px;">
    <a href="https://www.videosdk.live/contact" target="_blank" data-faitracker-click-bind="true" style="
        display: inline-block;
        padding: 12px 32px;
        background: #ffffff;
        color: #111111;
        font-size: 15px;
        font-weight: 600;
        text-decoration: none;
        border-radius: 8px;
        box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
        transition: transform 0.2s ease, box-shadow 0.2s ease;
      " onmouseover="
        this.style.transform='translateY(-2px)';
        this.style.boxShadow='0 8px 24px rgba(0,0,0,0.35)';
      " onmouseout="
        this.style.transform='translateY(0)';
        this.style.boxShadow='0 6px 20px rgba(0,0,0,0.25)';
      ">
      Book a call
    </a>
  </div>
</div>
<!--kg-card-end: html-->
<h3 id="2-agora">2. Agora</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-14-131023-1.png" class="kg-image" alt="10 Best Live Streaming APIs & SDKs for Real-Time Video Apps 2026" loading="lazy" width="1525" height="715"/></figure><p><a href="https://agora.io/" rel="nofollow noreferrer">Agora</a> runs its own software-defined real-time network (SD-RTN) with edge presence across more than 200 countries and regions, which makes it strong for globally distributed interactive broadcasts, particularly in APAC and LATAM. Its Interactive Live Streaming product supports large audiences with host and audience roles, and premium add-ons cover AR effects, spatial audio, and whiteboards.</p><p><strong>Pricing:</strong> 10,000 free minutes per month, then usage-based: <a href="https://www.agora.io/en/pricing/agora-rtc/" rel="nofollow noreferrer">$0.99 per 1,000 audio participant-minutes</a>, HD video at $3.99 per 1,000 minutes, and Full HD at $8.99 per 1,000 minutes, with rates decreasing at volume. Add-ons like recording bill separately. </p><p><strong>Best for:</strong> Ultra-scale interactive broadcasts where global edge coverage matters more than pricing simplicity.</p><p><strong>Limitation:</strong> The rate card is detailed. Video resolution tiers, add-ons, and regional pricing make invoices harder to forecast than flat participant-minute models.</p><h3 id="3-mux">3. Mux</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-19-153156.png" class="kg-image" alt="10 Best Live Streaming APIs & SDKs for Real-Time Video Apps 2026" loading="lazy" width="1892" height="868"/></figure><p><a href="https://www.mux.com/" rel="noreferrer nofollow">Mux</a> is the developer-experience benchmark for broadcast streaming: create a live stream with one API call, receive an RTMP or SRT stream key, and get back an HLS playback URL. Every live stream is automatically recorded as an on-demand asset at no extra charge, and Mux Data Analytics (rebuffering, startup time, drop-off) is included with delivery.</p><p><strong>Pricing:</strong> Usage-based on minutes encoded, stored, and delivered. The free plan includes up to 10 on-demand videos and 100,000 delivery minutes per month; paid plans start at <a href="https://www.mux.com/pricing" rel="noreferrer nofollow">$20 for $100 of usage</a>. Live simulcasting costs $0.020 per minute per target. Standard latency is 20+ seconds; LL-HLS mode brings it to 4 to 7 seconds. </p><p><strong>Best for:</strong> Creator platforms, fitness apps, and media products that need reliable one-to-many HLS delivery with strong analytics.</p><p><strong>Limitation:</strong> No WebRTC delivery. Interactive use cases that need sub-second latency are outside Mux's architecture.</p><h3 id="4-amazon-ivs">4. Amazon IVS</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-19-153459.png" class="kg-image" alt="10 Best Live Streaming APIs & SDKs for Real-Time Video Apps 2026" loading="lazy" width="1897" height="867"/></figure><p><a href="https://aws.amazon.com/ivs/" rel="nofollow noreferrer">Amazon Interactive Video Service</a> is the managed streaming infrastructure behind Twitch, exposed as an AWS service. It offers two modes: Low-latency streaming (RTMP ingest and delivery in roughly 3 to 5 seconds) and real-time streaming (WebRTC stages billed per participant-hour). Chat is available as a separate metered feature.</p><p><strong>Pricing:</strong> Pay-as-you-go on video input hours and output hours by resolution (low latency) or participant hours (real-time). The free tier includes 5 hours of live input, 100 hours of SD output, and 20 participant-hours per month, and new AWS customers receive up to $200 in Free Tier credits, per the official <a href="https://aws.amazon.com/ivs/pricing/" rel="nofollow noreferrer">AWS IVS pricing page</a>. </p><p><strong>Best for:</strong> Teams already on AWS that need Twitch-grade broadcast scale with usage-based billing.</p><p><strong>Limitation:</strong> Output-hour billing scales directly with audience size, so large audiences at HD resolution require careful cost modelling, and the SDK surface is thinner than developer-first platforms.</p><h3 id="5-livekit">5. LiveKit</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-14-131109-1.png" class="kg-image" alt="10 Best Live Streaming APIs & SDKs for Real-Time Video Apps 2026" loading="lazy" width="1532" height="697"/></figure><p><a href="https://livekit.com/" rel="nofollow noreferrer">LiveKit</a> is the leading open-source option: an <a href="https://github.com/livekit/livekit" rel="noreferrer">Apache 2.0 licensed WebRTC SFU</a> you can self-host with no license fees, plus LiveKit Cloud as the managed version. Its egress system records rooms or pushes streams to RTMP destinations, and its Agents framework has made it a default choice for teams adding AI participants to live sessions.</p><p><strong>Pricing:</strong> Self-hosting is free (you pay only your own infrastructure). LiveKit Cloud offers a free Build tier (including 5,000 participant minutes and 50GB data transfer monthly), <a href="https://livekit.com/pricing" rel="nofollow noreferrer">Ship at $50 per month</a>, Scale at $500 per month, and custom Enterprise plans, with metered connection minutes from $0.0005 and bandwidth billed separately. </p><p><strong>Best for:</strong> Engineering teams that want infrastructure control, open-source auditability, or a self-hosted path to eliminate per-minute fees at scale.</p><p><strong>Limitation:</strong> Self-hosting shifts the operational burden (scaling, <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a>, monitoring) back to your team, and large HLS-style audiences require additional egress architecture.</p><h3 id="6-100ms">6. 100ms</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-14-131222-1.png" class="kg-image" alt="10 Best Live Streaming APIs & SDKs for Real-Time Video Apps 2026" loading="lazy" width="1503" height="667"/></figure><p><a href="https://www.100ms.live/" rel="nofollow noreferrer">100ms</a> packages WebRTC conferencing and HLS live streaming behind a role-based template system: define broadcaster and viewer roles in the dashboard, and participants move between them with a single role-change call. Its HLS mode delivers streams to large audiences with under 10 seconds of latency, and prebuilt UI links let teams go live without building a frontend.</p><p><strong>Pricing:</strong> 10,000 free conferencing and streaming minutes per month, then conferencing at <a href="https://www.100ms.live/pricing" rel="nofollow noreferrer">$0.004 per participant-minute</a>, recording at $0.0135 per minute, and RTMP-out at $0.04 per minute, per the official 100ms pricing page. </p><p><strong>Best for:</strong> Teams that want a conferencing-to-streaming pipeline (webinars, classrooms) with prebuilt UI and minimal configuration.</p><p><strong>Limitation:</strong> Platform breadth is narrower than VideoSDK or Agora; there is no Unity, IoT, or C++ SDK for non-standard targets.</p><h3 id="7-zegocloud">7. ZEGOCLOUD</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-19-154744.png" class="kg-image" alt="10 Best Live Streaming APIs & SDKs for Real-Time Video Apps 2026" loading="lazy" width="1900" height="865"/></figure><p><a href="https://www.zegocloud.com/" rel="nofollow noreferrer">ZEGOCLOUD</a> focuses on social and entertainment streaming, pairing its live streaming SDK with add-ons like AI beauty effects, avatars, virtual gifting hooks, and 20+ prebuilt UIKits. Its network spans over 500 edge nodes, with particular strength in APAC markets.</p><p><strong>Pricing:</strong> 10,000 free minutes on signup. Hosts and co-hosts bill at RTC rates (<a href="https://www.zegocloud.com/pricing/product-list#live-streaming" rel="nofollow noreferrer">$3.99 per 1,000 minutes at 720p</a>), while audience minutes bill lower depending on delivery mode, from $2.29 per 1,000 minutes on the streaming tier per ZEGOCLOUD's pricing documentation, with cheaper CDN-delivery rates for passive viewing. </p><p><strong>Best for:</strong> Social apps (live rooms, dating, entertainment) where effects, avatars, and gifting mechanics matter as much as transport.</p><p><strong>Limitation:</strong> Documentation and billing conventions (stream-based vs user-based minute counting) take more effort to model than flat participant-minute pricing.</p><h3 id="8-apivideo">8. api.video</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-19-155117.png" class="kg-image" alt="10 Best Live Streaming APIs & SDKs for Real-Time Video Apps 2026" loading="lazy" width="1894" height="866"/></figure><p><a href="https://api.video/" rel="nofollow noreferrer">api.video</a> combines live streaming and video hosting behind one deliberately minimal API: create a live stream object, ingest over RTMPS or SRT, and deliver with about 3 seconds of latency under good conditions. Delivered minutes bill at the same rate regardless of quality tier, which simplifies forecasting.</p><p><strong>Pricing:</strong> A free sandbox environment for development, then <a href="https://api.video/pricing/" rel="nofollow noreferrer">usage-based billing on minutes</a> delivered and stored, with add-ons like transcription at $0.10 per minute. </p><p><strong>Best for:</strong> Products that need both live streams and an on-demand video library through one simple API.</p><p><strong>Limitation:</strong> No WebRTC delivery mode and a smaller feature surface for interactivity (no role switching or in-stream co-hosting).</p><h3 id="9-dacast">9. Dacast</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-19-155442.png" class="kg-image" alt="10 Best Live Streaming APIs & SDKs for Real-Time Video Apps 2026" loading="lazy" width="1897" height="863"/></figure><p><a href="https://www.dacast.com/" rel="nofollow noreferrer">Dacast</a> is a broadcaster-oriented streaming platform with an API layer rather than a developer-first SDK platform. Its strengths are white-label delivery, security controls, and built-in monetization: paywalls, subscriptions, and ad insertion ship out of the box, which none of the developer-first APIs on this list include natively.</p><p><strong>Pricing:</strong> Subscription-based, with plans starting around <a href="https://www.dacast.com/live-streaming-pricing-plans/" rel="nofollow noreferrer">$39 per month billed annually</a>, including bandwidth and storage allowances that scale by tier. </p><p><strong>Best for:</strong> Media companies and event broadcasters that need to monetize streams directly and prefer predictable subscription billing.</p><p><strong>Limitation:</strong> Deep in-app integration (custom UI, roles, interactivity) is limited compared to SDK-first platforms; Dacast is a platform you embed, not infrastructure you build on.</p><h3 id="10-wowza">10. Wowza</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-19-155629.png" class="kg-image" alt="10 Best Live Streaming APIs & SDKs for Real-Time Video Apps 2026" loading="lazy" width="1906" height="860"/></figure><p><a href="https://www.wowza.com/" rel="nofollow noreferrer">Wowza</a> is the veteran infrastructure option, offering both Wowza Flowplayer OVP and Wowza Streaming Engine (self-hosted server software). It supports the widest protocol surface on this list (HLS, RTMP, SRT, WebRTC, and <a href="https://www.videosdk.live/developer-hub/hls/mpeg-dash" rel="noreferrer">MPEG-DASH</a>) and serves teams with compliance, on-premise, or protocol-level requirements that managed clouds cannot meet.</p><p><strong>Pricing:</strong>  TheWowza Streaming Engine is priced per server instance: a one-month of streaming plan at <a href="https://www.wowza.com/pricing" rel="noreferrer nofollow">$295 (one-time, first instance included)</a> or basic monthly at $195 per month, each covering up to 10 concurrent transcoded channels, with additional channels at $25 each and custom enterprise annual plans.</p><p><strong>Best for:</strong> Broadcasters, government, defense, and enterprises that need full pipeline control or hybrid on-premise deployment.</p><p><strong>Limitation:</strong> Configuration depth means longer integration time; teams without streaming expertise will ship faster on a managed API.</p><h2 id="live-streaming-api-comparison-table">Live Streaming API Comparison Table</h2>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Provider</th>
<th>Best For</th>
<th>Typical Latency</th>
<th>Pricing Model</th>
<th>Free Tier</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td>Interactive streaming + full RTC stack</td>
<td>Under 1s (WebRTC ILS)</td>
<td>Pay-as-you-go per participant/viewer minute</td>
<td>One-time $20 credit, no card</td>
</tr>
<tr>
<td>Agora</td>
<td>Global ultra-scale interactive broadcast</td>
<td>Under 1s (SD-RTN)</td>
<td>Per 1,000 minutes by resolution</td>
<td>10,000 min/month</td>
</tr>
<tr>
<td>Mux</td>
<td>Developer-first HLS broadcast + VOD</td>
<td>4 to 7s (LL-HLS), 20s+ (HLS)</td>
<td>Per minute encoded/stored/delivered</td>
<td>100,000 delivery min/month</td>
</tr>
<tr>
<td>Amazon IVS</td>
<td>Twitch-grade scale on AWS</td>
<td>3 to 5s (low-latency HLS)</td>
<td>Input/output hours or participant-hours</td>
<td>5h input + 100h SD output/month</td>
</tr>
<tr>
<td>LiveKit</td>
<td>Open-source, self-hosted WebRTC</td>
<td>Under 1s (WebRTC)</td>
<td>Free self-host; Cloud tiers $0 to $500/mo</td>
<td>5,000 participant min/month (Cloud)</td>
</tr>
<tr>
<td>100ms</td>
<td>Conferencing-to-HLS with prebuilt UI</td>
<td>Under 10s (HLS)</td>
<td>Per minute by feature</td>
<td>10,000 min/month</td>
</tr>
<tr>
<td>ZEGOCLOUD</td>
<td>Social and entertainment streaming</td>
<td>Under 1s (RTC)</td>
<td>Per 1,000 minutes by role and mode</td>
<td>10,000 min on signup</td>
</tr>
<tr>
<td>api.video</td>
<td>Combined live + on-demand hosting</td>
<td>~3s</td>
<td>Per minute delivered</td>
<td>Free sandbox</td>
</tr>
<tr>
<td>Dacast</td>
<td>Monetized broadcast for media teams</td>
<td>10s+ (HLS)</td>
<td>Subscription from ~$39/month</td>
<td>14-day trial</td>
</tr>
<tr>
<td>Wowza</td>
<td>On-premise and protocol-level control</td>
<td>Varies by protocol</td>
<td>Per server instance: $295 one-time or $195/mo</td>
<td>Trial available</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<blockquote>All pricing is verified against official pricing pages as of August 2026.</blockquote><h2 id="what-changed-in-the-live-streaming-api-market">What Changed in the Live Streaming API Market</h2><p>Two shifts since 2024 make older "best live streaming API" lists unreliable, and they explain why several familiar names are absent from this ranking.</p><p><strong>Dolby.io became Dolby OptiView.</strong> Dolby merged its Millicast real-time streaming service with THEOlive into Dolby OptiView, a platform now aimed primarily at sports, media, and betting enterprises rather than general app developers, which is why it no longer fits a developer-first API ranking.</p><p><strong>Dyte became Cloudflare RealtimeKit.</strong> After Cloudflare's acquisition, Dyte's SDK re-emerged as Cloudflare RealtimeKit, currently in beta at no cost with published GA pricing of $0.002 per audio/video participant minute. Worth watching, but not yet production-proven at GA. </p><p>The practical lesson: verify a provider's roadmap and ownership before committing, because streaming infrastructure has consolidated quickly.</p><h2 id="how-to-choose-the-best-live-streaming-api">How to Choose the Best Live Streaming API</h2><p>Selecting a live streaming API comes down to five decisions, in this order:</p><ol><li><strong>Fix your latency requirement first.</strong> If viewers interact with the stream (bidding, answering, co-hosting), you need a WebRTC-based API like VideoSDK, Agora, or LiveKit with sub-second latency. If viewers only watch, HLS platforms like Mux or Amazon IVS cost less at scale.</li><li><strong>Estimate your audience shape.</strong> Fifty interactive participants and 50,000 passive viewers are different products. Some platforms (VideoSDK, 100ms, Amazon IVS) support both modes; pure-HLS platforms do not.</li><li><strong>Match SDK coverage to your roadmap.</strong> If Flutter, React Native, or Unity is on your roadmap, confirm native SDK support now. VideoSDK and Agora have the widest coverage; broadcast-first platforms are thinner on mobile.</li><li><strong>Model total cost with your real numbers.</strong> Multiply expected host minutes, viewer minutes, and recording minutes against each rate card. Free tiers ($20 credit on VideoSDK, 10,000 monthly minutes on Agora, ZEGOCLOUD, and 100ms) cover evaluation, not production.</li><li><strong>Check the exit paths.</strong> Prefer providers with RTMP output (for simulcasting) and standard protocols, so you can add or switch delivery layers without re-architecting.</li></ol><h2 id="live-streaming-infrastructure-definitions">Live Streaming Infrastructure Definitions</h2><blockquote><strong>WebRTC:</strong> An open standard for real-time media transport in browsers and apps, delivering latency under 500 milliseconds. VideoSDK, Agora, and LiveKit deliver interactive streams over WebRTC.</blockquote><blockquote><strong>RTMP:</strong> Real-Time Messaging Protocol, the standard for pushing a broadcast feed from encoders like OBS into an ingest server. Most HLS platforms and VideoSDK's simulcast output use RTMP.</blockquote><blockquote><strong>HLS:</strong> HTTP Live Streaming, Apple's segment-based delivery protocol that scales to millions of viewers over standard CDNs at 10 to 30 seconds of latency; LL-HLS variants reduce this to roughly 3 to 7 seconds.</blockquote><blockquote><strong>SRT:</strong> Secure Reliable Transport, an ingest protocol that outperforms RTMP on unstable networks; supported by Mux, api.video, and Wowza.</blockquote><blockquote><strong>Adaptive Bitrate Streaming (ABR):</strong> Automatic switching between quality renditions based on each viewer's bandwidth. VideoSDK implements this as network-adaptive streaming on WebRTC streams.</blockquote><blockquote><strong>Interactive Live Streaming (ILS):</strong> VideoSDK's sub-second streaming mode where viewers can chat, vote, and be promoted to co-hosts through a single mode change, unlike one-way HLS broadcasts.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>Your latency requirement is the first filter: interactive products need a WebRTC-based live streaming API, while large passive audiences are cheaper to serve over HLS.</li><li>VideoSDK is the strongest option for interactive live streaming because it combines sub-second latency, viewer-to-co-host role switching, and the broadest SDK coverage (10+ platforms) on one billing model.</li><li>Mux and Amazon IVS lead one-to-many broadcasting, with verified free tiers of 100,000 delivery minutes and 100 SD output hours per month respectively.</li><li>The market consolidated fast: Twilio Video was discontinued, Dolby.io became Dolby OptiView, and Dyte became Cloudflare RealtimeKit, so recency matters when comparing providers.</li><li>Model costs with your own host, viewer, and recording minutes rather than comparing headline rates, because billing dimensions differ more than prices do.</li></ul><h2 id="conclusion">Conclusion</h2><p>Integrating live video no longer requires a media engineering team. A live streaming API handles ingest, transcoding, and delivery so you can focus on the product around the stream. Start from your latency requirement: choose VideoSDK for interactive, sub-second streaming across web and mobile, and an HLS platform like Amazon IVS for massive one-way broadcasts. You can test VideoSDK's interactive live streaming with the one-time $20 free credit at <a href="https://app.videosdk.live/login">app.videosdk.live/login</a>, no credit card required.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="is-there-a-free-api-for-live-streaming">Is there a free API for live streaming?</h3><p>Yes, several live streaming APIs include free usage. VideoSDK gives every new account a one-time $20 credit with no credit card required; Agora, ZEGOCLOUD, and 100ms each include 10,000 free minutes per month, and Mux includes 100,000 free delivery minutes monthly. These allowances cover prototyping and early testing, not production traffic.</p><h3 id="what-is-the-difference-between-webrtc-and-rtmp">What is the difference between WebRTC and RTMP?</h3><p>The main difference is direction and latency. WebRTC delivers media to and from viewers in under 500 milliseconds, which enables two-way interaction. RTMP is an ingest protocol: it pushes a broadcast feed into a server, which then delivers it to viewers over HLS at 3 to 30 seconds of latency but with far greater one-way scale.</p><h3 id="what-is-the-difference-between-interactive-live-streaming-and-hls">What is the difference between interactive live streaming and HLS?</h3><p>Interactive live streaming (ILS) runs over WebRTC with sub-second latency, so viewers can respond in real time and be promoted to speakers. HLS is a one-way, CDN-delivered protocol with 10 to 30 seconds of delay. VideoSDK implements ILS natively and can simultaneously push an RTMP feed out for HLS-based platforms, giving one stream both behaviors.</p><h3 id="how-much-does-a-live-streaming-api-cost">How much does a live streaming API cost?</h3><p>Live streaming API costs are usage-based on most platforms. Representative verified rates in 2026: VideoSDK video from $0.004 per participant-minute, Agora HD video at $3.99 per 1,000 minutes, 100ms conferencing at $0.004 per minute, and Amazon IVS billing on input and output hours. At scale, HLS delivery is cheaper per passive viewer, while WebRTC pricing scales with interactive participation. </p><h3 id="can-i-broadcast-to-youtube-and-twitch-using-a-live-streaming-api">Can I broadcast to YouTube and Twitch using a live streaming API?</h3><p>Yes, through simulcasting via RTMP output. VideoSDK, Mux, 100ms, and LiveKit can push a stream to external RTMP destinations like YouTube and Twitch while it runs, with Mux charging $0.020 per minute per simulcast target and 100ms charging $0.04 per minute for RTMP-out.</p><h3 id="how-long-does-it-take-to-integrate-a-live-streaming-api">How long does it take to integrate a live streaming API?</h3><p>Integration typically takes hours to days rather than the months an in-house pipeline requires. Prebuilt options are fastest: VideoSDK's Prebuilt UI Kit and 100ms's prebuilt links embed a working stream interface without custom UI code, while a fully custom UI on any SDK on this list is usually a one-to-two-sprint effort.</p><h3 id="which-live-streaming-api-is-best-for-mobile-apps">Which live streaming API is best for mobile apps?</h3><p>The best live streaming API for mobile apps is one with native SDKs for every platform you target. VideoSDK covers iOS, Android, React Native, and Flutter (plus Unity and IoT), and Agora and ZEGOCLOUD offer similarly broad mobile coverage. Broadcast-first platforms like Mux and api.video handle mobile playback well but rely on RTMP ingest rather than in-app WebRTC broadcasting.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 Best Video Calling APIs & SDKs for Developers in 2026]]></title><description><![CDATA[A developer's comparison of the 10 best video calling APIs and SDKs in 2026, with real pricing, a side-by-side table, a decision framework, and a production testing checklist for choosing the right one.]]></description><link>https://www.videosdk.live/blog/10-best-video-calling-apis</link><guid isPermaLink="false">64ec6ed89eadee0b8b9e7e6a</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 18 Aug 2026 10:25:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/Video-Calling-APIs---SDKs.png" medium="image"/><content:encoded><![CDATA[<blockquote>The best video calling APIs in 2026 are VideoSDK, Agora, and Daily.co, followed by Twilio Video, LiveKit, Zoom Video SDK, Vonage, 100ms, Amazon Chime SDK, and Whereby Embedded. VideoSDK ranks first for SDK coverage across 10+ platforms, a Prebuilt UI Kit, and transparent per-minute pricing. Choose based on latency targets, participant limits, compliance needs, and total cost at your projected scale.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Video-Calling-APIs---SDKs.png" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026"/><p>Building video calling on raw WebRTC means months of work on signalling servers, <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a> relays, and codec negotiation before your first stable call. A video calling API compresses that into an afternoon: your backend requests a room, participants join through an SDK, and the vendor runs the media infrastructure.</p><p>The hard part is picking the right provider. This guide compares the 10 best video calling APIs of 2026 on pricing, SDK coverage, latency, and compliance. You get a side-by-side comparison table, a decision framework, and a testing checklist you can run against any shortlist this week.</p><h2 id="what-is-a-video-calling-api">What Is a Video Calling API?</h2><p>A video calling API lets developers embed real-time video and audio into an application without building or operating WebRTC infrastructure themselves.</p><p>A video calling API is defined as a programmatic interface that adds two-way, real-time video and audio communication to web, mobile, and desktop applications through vendor-hosted infrastructure and client SDKs. A <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">video calling API</a> works by exposing REST endpoints and SDK methods for creating rooms, authenticating participants, routing media streams, and controlling recording, while the provider operates the signalling servers, <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-stun-server" rel="noreferrer">STUN</a> and TURN relays, and Selective Forwarding Unit (SFU) clusters that carry the media.</p><p>VideoSDK, for example, provides video calling APIs and SDKs for more than 10 platforms, including React, React Native, Flutter, Android, iOS, JavaScript, Unity, and IoT devices, plus a&nbsp;<a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">prebuilt UI kit</a>&nbsp;that embeds a complete call interface with a single component. That breadth is why this category has replaced hand-rolled&nbsp;<a href="https://www.videosdk.live/blog/webrtc">WebRTC</a>&nbsp;stacks for most product teams.</p><p>The distinction matters when you evaluate vendors. Daily.co's engineering glossary makes the point that media engineers usually mean low-level libraries like libwebrtc when they say "video API," while application developers mean full-stack managed platforms. Every platform in this list is the second kind: managed infrastructure with SDKs on top, defined in the&nbsp;<a href="https://www.w3.org/TR/webrtc/">W3C WebRTC specification's</a>&nbsp;terms but operated for you.</p><p>The market reflects that shift. According to Grand View Research, the&nbsp;<a href="https://www.grandviewresearch.com/industry-analysis/video-conferencing-market">global video conferencing market</a>&nbsp;was estimated at USD 14.4 billion in 2026 and is projected to reach USD 24.6 billion by 2033, an 7.9% CAGR.&nbsp;</p><h2 id="what-should-you-look-for-in-a-video-calling-api">What Should You Look for in a Video Calling API?</h2>
<p>Six criteria separate production-ready video calling APIs from demo-ware: latency, participant scale, SDK coverage, recording and compliance, pricing transparency, and support.</p><p><strong>Latency and architecture.</strong> Interactive use cases like telehealth, tutoring, and sales calls need sub-500ms mouth-to-ear delay. Confirm the provider routes media through WebRTC SFUs rather than HTTP-based delivery, and test from the regions your users actually occupy. VideoSDK's rooms architecture targets sub-300ms latency over WebRTC.</p><p><strong>Participant limits and room models.</strong>&nbsp;Some APIs cap active publishers at 25 participants; others scale past 1,000 with role-based publishing. Document your peak concurrent users per room before comparing vendors, because this number disqualifies platforms faster than price does.</p><p><strong>SDK breadth.</strong>&nbsp;If your product ships on iOS, Android, React Native, Flutter, and web at once, a unified SDK surface cuts your integration and maintenance load dramatically. Stitching two vendors together to cover one missing platform is where timelines go to die.</p><p><strong>Recording and compliance.</strong>&nbsp;Regulated industries need server-side recording, encrypted storage, and HIPAA Business Associate Agreements. Check whether recording is a first-class API or a bolt-on with separate billing.</p><p><strong>Pricing transparency.</strong>&nbsp;Per-participant-minute billing is standard, but resolution tiers, composition charges, RTMP output, and storage fees inflate bills beyond the headline rate. Model total monthly cost at projected scale, not demo-day usage.</p><p><strong>Support and documentation.</strong>&nbsp;Production incidents during live sessions need responsive support. Evaluate docs quality, sample apps, and SLA tiers before you need them. In practice, teams that evaluate on headline price alone and skip throttled-network testing report rework cycles of three to six weeks when production conditions expose SDK gaps.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-18--2026--04_39_54-PM.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1672" height="941"/></figure><h2 id="the-10-best-video-calling-apis-in-2026">The 10 Best Video Calling APIs in 2026</h2>
<p><strong>How we evaluated:</strong> each platform was scored on SDK breadth, published pricing, feature depth (recording, transcription, streaming), production reliability signals, and developer experience. All prices below are published pay-as-you-go rates as of August 2026 and should be re-verified before budgeting.</p><h3 id="1-videosdk">1. VideoSDK</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-14-130930.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1523" height="727"/></figure><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> is a real-time infrastructure platform with video calling SDKs on more platforms than any other provider on this list. It uses a rooms-based architecture: participants join a room over WebRTC, and the SDK exposes their streams through hooks and methods like <code>useMeeting</code> and <code>useParticipant</code>.</p><p><strong>Why it ranks first:</strong> SDKs for React, JavaScript, React Native, Android, iOS, Flutter, Unity, C++, IoT, and Python cover practically any product roadmap, and the <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Prebuilt UI Kit</a> ships a working call interface with near-zero custom UI code. Recording, real-time transcription, network-adaptive streaming, noise suppression, chat, polls, and whiteboard are included in the SDK rather than sold as separate add-ons. The same SDK surface also handles interactive live streaming through <code>changeMode()</code>, so a calling app can add sub-second streaming without a second vendor.</p><p>Integration starts from the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React SDK quickstart</a>, which walks from install to a live room in a few minutes. Authentication uses a meeting token generated server-side with your <a href="https://www.videosdk.live/blog/api-key-vs-api-token" rel="noreferrer">API key and secret</a>; most abandoned integrations trace back to skipping that step, so budget ten minutes for a small token endpoint before touching the frontend.</p><p><strong>Pricing:</strong> <a href="https://www.videosdk.live/pricing" rel="noreferrer">video at $0.004 per participant-minute</a>, audio-only at $0.001, cloud recording at $0.015, RTMP output at $0.03, with $20 free to start. </p><p><strong>Best for:</strong> teams shipping on multiple platforms at once, products that need calling plus interactive live streaming, and developers who want a prebuilt UI option alongside full custom control.</p><p><strong>Honest trade-off:</strong> feature rollout isn't perfectly synchronized across all 10+ SDKs; newer capabilities typically land on React, JavaScript, and Flutter before Unity, C++, and IoT, so check the feature matrix in the docs for your platform before committing.</p>
<!--kg-card-begin: html-->
<div class="relative w-full overflow-hidden rounded-2xl p-6 text-center" style="
    background: linear-gradient(135deg, #18131f 0%, #271b38 55%, #38245a 100%);
    border: 1px solid rgba(209, 188, 253, 0.28);
    box-shadow:
      0 12px 40px rgba(0, 0, 0, 0.35),
      0 0 40px rgba(209, 188, 253, 0.08);
    border-radius: 16px;
    padding: 32px 24px;
    margin: 32px 0;
  ">
  <h3 style="
      margin: 0 0 12px;
      font-size: 28px;
      line-height: 1.3;
      font-weight: 700;
      color: #ffffff;
    ">
    Schedule a Demo with Our Live Video Expert!
  </h3>

  <p style="
      margin: 0 auto;
      max-width: 680px;
      font-size: 16px;
      line-height: 1.6;
      color: #c7c7cc;
    ">
    Discover how VideoSDK can help you build a cutting-edge real-time video app.
  </p>

  <div style="margin-top: 24px;">
    <a href="https://www.videosdk.live/contact" target="_blank" data-faitracker-click-bind="true" style="
        display: inline-block;
        padding: 12px 32px;
        background: #ffffff;
        color: #111111;
        font-size: 15px;
        font-weight: 600;
        text-decoration: none;
        border-radius: 8px;
        box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
        transition: transform 0.2s ease, box-shadow 0.2s ease;
      " onmouseover="
        this.style.transform='translateY(-2px)';
        this.style.boxShadow='0 8px 24px rgba(0,0,0,0.35)';
      " onmouseout="
        this.style.transform='translateY(0)';
        this.style.boxShadow='0 6px 20px rgba(0,0,0,0.25)';
      ">
      Book a call
    </a>
  </div>
</div>
<!--kg-card-end: html-->
<h3 id="2-agora">2. Agora</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-14-131023.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1525" height="715"/></figure><p><a href="https://agora.io/" rel="nofollow noreferrer">Agora</a> runs its own Software-Defined Real-Time Network (SD-RTN) and is the scale benchmark for real-time media, carrying billions of minutes monthly across 200+ regions.</p><p><strong>Why it is on the list:</strong> ultra-low latency at a very large scale, strong mobile SDKs, and a deep extension ecosystem (noise suppression, whiteboard, real-time speech-to-text).</p><p><strong>Pricing:</strong> tiered by resolution, around <a href="https://www.agora.io/en/pricing/agora-rtc/" rel="nofollow noreferrer">$0.99 per 1,000 audio participant-minutes</a>, $3.99 per 1,000 HD video minutes, and $8.99 per 1,000 Full HD minutes, with add-ons billed separately. </p><p><strong>Best for:</strong> massive live events and social apps where concurrent scale is the dominant requirement.</p><p><strong>Compared with VideoSDK:</strong> Agora wins on broadcast scale; VideoSDK wins on SDK breadth, bundled features, and pricing simplicity. See the full <a href="https://www.videosdk.live/blog/agora-alternative">Agora alternatives breakdown</a>.</p><h3 id="3-twilio-video">3. Twilio Video</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-18-164256.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1893" height="830"/></figure><p><a href="https://www.twilio.com/en-us/video" rel="nofollow noreferrer">Twilio Video</a> is the video product inside Twilio's larger communications platform, best known for SMS and voice APIs. Twilio announced an end-of-life for the product in 2023, then reversed the decision; its changelog now states Video "<a href="https://www.twilio.com/en-us/changelog/-twilio-video-will-remain-a-standalone-product" rel="nofollow noreferrer">will remain a standalone product</a>." That history is worth weighing when you bet a roadmap on it.</p><p><strong>Why it is on the list:</strong> reliable rooms API, fine-grained track control, and natural fit for products already using Twilio for messaging or telephony.</p><p><strong>Pricing:</strong> group rooms from roughly <a href="https://www.twilio.com/en-us/video/pricing" rel="nofollow noreferrer">$4 per 1,000 participant-minutes</a>, with recording ($0.004/min), composition ($0.01/min), and storage billed separately. </p><p><strong>Best for:</strong> teams already invested in the Twilio ecosystem that want one vendor and one bill.</p><p><strong>Compared with VideoSDK:</strong> Twilio offers no prebuilt UI and video sits alongside many competing product priorities; VideoSDK is video-first with a UI kit included. See <a href="https://www.videosdk.live/blog/twilio-video-alternative">Twilio Video alternatives</a>.</p><h3 id="4-dailyco">4. Daily.co</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-14-131144.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1508" height="717"/></figure><p><a href="https://www.daily.co/" rel="nofollow noreferrer">Daily.co</a> is built around integration speed: prebuilt call UI, a clean REST API, and one of the friendliest onboarding paths in the category.</p><p><strong>Why it is on the list:</strong> developers routinely go from signup to a working web call in under an hour, and the free tier of 10,000 participant-minutes per month is generous for prototyping.</p><p><strong>Pricing:</strong> pay-as-you-go from roughly <a href="https://www.daily.co/pricing/video-sdk/" rel="nofollow noreferrer">$0.004 per participant-minute</a> after the free tier, with paid support plans sold separately.</p><p><strong>Best for:</strong> web-first products that want the fastest possible embed with sensible defaults.</p><p><strong>Compared with VideoSDK:</strong> Daily's recent focus has shifted heavily toward AI voice (its team maintains the open-source Pipecat framework), while its mobile SDK surface is narrower than VideoSDK's ten-platform coverage.</p><h3 id="5-livekit">5. LiveKit</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-14-131109.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1532" height="697"/></figure><p><a href="https://livekit.com/" rel="nofollow noreferrer">LiveKit</a> is the leading open-source option: an Apache-2.0 licensed <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu" rel="noreferrer">WebRTC SFU</a> you can self-host, plus a managed LiveKit Cloud if you would rather not run servers. The <a href="https://github.com/livekit/livekit">LiveKit GitHub repository</a> is among the most active in the RTC space.</p><p><strong>Why it is on the list:</strong> full infrastructure control, no vendor lock-in for self-hosters, and strong momentum in AI agent use cases.</p><p><strong>Pricing:</strong> self-hosting is free minus your infrastructure and ops cost; <a href="https://livekit.com/pricing" rel="nofollow noreferrer">LiveKit Cloud bills on usage</a> with a free starter tier. </p><p><strong>Best for:</strong> teams with infrastructure expertise that need data residency control or want to avoid per-minute vendor billing at scale.</p><p><strong>Compared with VideoSDK:</strong> LiveKit trades managed convenience for control. Expect to own TURN configuration, scaling, and upgrades yourself when self-hosting; VideoSDK ships those as managed defaults.</p><h3 id="6-zoom-video-sdk">6. Zoom Video SDK</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-18-165438.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1899" height="868"/></figure><p><a href="https://www.zoom.com/en/video-sdk/" rel="nofollow noreferrer">Zoom Video SDK</a> gives you Zoom's media infrastructure without Zoom's interface, supporting sessions up to 1,000 participants with raw stream access for custom experiences.</p><p><strong>Why it is on the list:</strong> proven reliability at scale and instant credibility with stakeholders who already trust the Zoom brand.</p><p><strong>Pricing:</strong> sold as the <a href="https://zoom.us/pricing/developer" rel="nofollow noreferrer">Zoom Build Platform credit subscription</a> ($100/month for 100 credits, ~$0.0035 effective per participant-minute), with a 20-credit free monthly allowance and no true pay-as-you-go tier.</p><p><strong>Best for:</strong> large-session products and teams whose buyers ask "is it as reliable as Zoom?"</p><p><strong>Compared with VideoSDK:</strong> the Video SDK is fully headless, so you build every pixel of UI; VideoSDK offers both headless SDKs and a prebuilt kit. See <a href="https://www.videosdk.live/blog/zoom-video-sdk-alternative">Zoom Video SDK alternatives</a>.</p><h3 id="7-vonage-video-api">7. Vonage Video API</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-14-131437.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1515" height="722"/></figure><p><a href="https://www.vonage.com/communications-apis/video/" rel="nofollow noreferrer">Vonage Video</a> (formerly OpenTok/TokBox, now owned by Ericsson) is the enterprise veteran, with SIP interconnect, broadcast output to HLS and RTMP, and support for very large interactive sessions.</p><p><strong>Why it is on the list:</strong> enterprise-grade compliance options and telecom integration depth few rivals match.</p><p><strong>Pricing:</strong> usage-based at <a href="https://www.vonage.com/communications-apis/video/pricing/" rel="nofollow noreferrer">$0.0041 per participant-minute</a> with a 100,000-minute free trial for new accounts; recording from $0.013 per archive-minute, HLS from $0.00155 per viewer-minute, and enterprise add-ons (HIPAA, regional media zones, E2E encryption) sold as monthly subscriptions from $550.</p><p><strong>Best for:</strong> enterprises that need video to interoperate with existing telecom infrastructure.</p><p><strong>Compared with VideoSDK:</strong> Vonage carries legacy architecture from years of acquisitions, which developers feel in integration complexity; VideoSDK's newer SDK surface is leaner. See <a href="https://www.videosdk.live/blog/vonage-alternative">Vonage alternatives</a>.</p><h3 id="8-100ms">8. 100ms</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-14-131222.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1503" height="667"/></figure><p><a href="https://www.100ms.live/" rel="nofollow noreferrer">100ms</a> takes a template-driven approach: you configure roles and layouts in a dashboard, then the SDK renders them, which shortens time-to-first-call for standard layouts.</p><p><strong>Why it is on the list:</strong> polished dashboards, solid mobile SDKs, and built-in live streaming and recording aimed at social and creator apps.</p><p><strong>Pricing:</strong> 10,000 free monthly minutes, then conferencing from roughly <a href="https://www.100ms.live/pricing" rel="nofollow noreferrer">$0.004 per participant-minute</a>.</p><p><strong>Best for:</strong> mobile-first social, audio room, and creator products that fit its template model.</p><p><strong>Compared with VideoSDK:</strong> the template approach speeds up standard layouts but constrains unusual ones; VideoSDK's custom tracks and layout APIs leave more room for nonstandard UIs.</p><h3 id="9-amazon-chime-sdk">9. Amazon Chime SDK</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-14-131356.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1523" height="723"/></figure><p><a href="https://aws.amazon.com/chime/chime-sdk/" rel="nofollow noreferrer">Amazon Chime SDK</a> is AWS's building-block approach to real-time media, priced per attendee-minute and wired into the AWS ecosystem (Kinesis, Transcribe, EventBridge).</p><p><strong>Why it is on the list:</strong> if your stack, billing, and compliance posture already live in AWS, Chime SDK keeps media there too.</p><p><strong>Pricing:</strong> pay-per-use from roughly <a href="https://aws.amazon.com/chime/chime-sdk/pricing/" rel="nofollow noreferrer">$0.0017 per attendee-minute</a> with no monthly commitment. </p><p><strong>Best for:</strong> AWS-committed engineering organizations comfortable assembling primitives.</p><p><strong>Compared with VideoSDK:</strong> Chime SDK offers no prebuilt UI and its documentation follows AWS's service-reference style, so expect more assembly than any other option here. See <a href="https://www.videosdk.live/blog/amazon-chime-sdk-alternative">Amazon Chime SDK alternatives</a>.</p><h3 id="10-whereby-embedded">10. Whereby Embedded</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-18-171151.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1899" height="868"/></figure><p><a href="https://whereby.com/information/embedded" rel="nofollow noreferrer">Whereby Embedded</a> is the fastest no-code path on this list: drop an iframe into your page and you have a branded, GDPR-compliant call running from European infrastructure.</p><p><strong>Why it is on the list:</strong> genuine minutes-to-live embedding, EU hosting, and HIPAA-capable plans that make it a recurring telehealth pick.</p><p><strong>Pricing:</strong> from <a href="https://whereby.com/information/embedded/pricing" rel="nofollow noreferrer">$9.99 per month</a>, including 2,000 participant minutes, with overage around $0.004 per minute and recording billed per minute. </p><p><strong>Best for:</strong> small telehealth and e-learning teams that value speed and privacy posture over deep customization.</p><p><strong>Compared with VideoSDK:</strong> Whereby's customization ceiling arrives quickly (limited UI control, participant caps); VideoSDK's Prebuilt UI Kit offers a similar zero-code start with a full SDK underneath when you outgrow it.</p><h2 id="video-calling-api-comparison-table">Video Calling API Comparison Table</h2>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Platform</th>
<th>Starting video price</th>
<th>Free tier</th>
<th>SDK coverage</th>
<th>Best for</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td>$0.004/participant-min</td>
<td>$20 signup credit</td>
<td>10+ platforms incl. Unity, IoT</td>
<td>Multi-platform apps + live streaming</td>
</tr>
<tr>
<td>Agora</td>
<td>~$3.99/1,000 HD min</td>
<td>10,000 min/mo</td>
<td>Web, mobile, desktop, game engines</td>
<td>Massive-scale live events</td>
</tr>
<tr>
<td>Twilio Video</td>
<td>~$4/1,000 min</td>
<td>Trial credit</td>
<td>Web, iOS, Android</td>
<td>Existing Twilio customers</td>
</tr>
<tr>
<td>Daily.co</td>
<td>~$0.004/participant-min</td>
<td>10,000 min/mo</td>
<td>Web-first, mobile</td>
<td>Fastest web embeds</td>
</tr>
<tr>
<td>LiveKit</td>
<td>Free (self-host) / Cloud usage</td>
<td>Cloud starter tier</td>
<td>Web, mobile, server SDKs</td>
<td>Open-source control</td>
</tr>
<tr>
<td>Zoom Video SDK</td>
<td>~$0.0035/participant-min</td>
<td>$20 credits/mo </td>
<td>Web, mobile, desktop</td>
<td>Large sessions, brand trust</td>
</tr>
<tr>
<td>Vonage Video</td>
<td>~$0.0041/participant-min</td>
<td>100,000 min trial</td>
<td>Web, mobile</td>
<td>Enterprise + SIP interconnect</td>
</tr>
<tr>
<td>100ms</td>
<td>~$0.004/participant-min</td>
<td>10,000 min/mo</td>
<td>Web, mobile</td>
<td>Template-driven social apps</td>
</tr>
<tr>
<td>Amazon Chime SDK</td>
<td>~$0.0017/attendee-min</td>
<td>Pay-per-use</td>
<td>Web, mobile (JS-centric)</td>
<td>AWS-native teams</td>
</tr>
<tr>
<td>Whereby Embedded</td>
<td>$9.99/mo + overage</td>
<td>2,000 min on plan</td>
<td>iframe + web SDK</td>
<td>No-code telehealth embeds</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The most important row to read carefully is your own participant model: a $0.0017 attendee-minute on Chime can still cost more than $0.004 on VideoSDK once you add recording, egress, and the engineering time its missing UI layer demands. Headline rates only become comparable after you model recording, streaming output, and storage for one month of your real traffic.</p><h3 id="which-video-calling-api-should-you-pick">Which Video Calling API Should You Pick?</h3><ul><li>Shipping on several platforms at once, or needing to call plus interactive live streaming: <strong>VideoSDK</strong></li><li>Broadcasting to hundreds of thousands of concurrent viewers: <strong>Agora</strong></li><li>Already running SMS and voice on Twilio: <strong>Twilio Video</strong></li><li>Want a working web call embedded before lunch: <strong>Daily.co</strong> or <strong>VideoSDK Prebuilt UI Kit</strong></li><li>Must self-host for data residency or cost control at huge scale: <strong>LiveKit</strong></li><li>Buyers demand the Zoom brand or 1,000-person sessions: <strong>Zoom Video SDK</strong></li><li>Enterprise telecom interop with SIP: <strong>Vonage</strong></li><li>Mobile-first social or audio rooms on standard layouts: <strong>100ms</strong></li><li>Everything else in your company already runs on AWS: <strong>Amazon Chime SDK</strong></li><li>Small telehealth team, no frontend engineers: <strong>Whereby Embedded</strong></li></ul><h2 id="how-do-you-test-a-video-calling-api-before-production">How Do You Test a Video Calling API Before Production?</h2><p>Test a video calling API by proving it survives bad networks, not by confirming it works on office Wi-Fi. Localhost demos hide exactly the failures that kill production launches.</p><p>Run this checklist against your top two candidates before signing anything:</p><ol><li><strong>Implement the core loop on every target platform.</strong> Join, leave, mute, screen share, and record on real devices, not just simulators.</li><li><strong>Throttle to 3G and inject 20–30% packet loss.</strong> Measure time-to-first-frame, audio continuity, and whether adaptive bitrate actually kicks in.</li><li><strong>Kill the network mid-call.</strong> The SDK should reconnect automatically and fire events your UI can react to. Silent hangs here become your worst support tickets.</li><li><strong>Test behind a corporate firewall.</strong> This exercises TURN relay fallback, the classic "works at home, fails at the client's office" failure. Production also requires HTTPS everywhere for camera and mic permissions.</li><li><strong>Model one real month of cost.</strong> Multiply projected participant-minutes by rates for calling, recording, streaming output, and storage, then compare vendors on that number instead of headline rates.</li><li><strong>Load test at twice projected peak</strong> concurrent sessions and confirm compliance paperwork (BAA, DPA) exists for your industry.</li></ol><p>Teams that run this checklist typically disqualify at least one shortlisted vendor, which is far cheaper than discovering the gap after integration.</p><h3 id="migrating-between-video-calling-api-providers">Migrating between video calling API providers</h3><p>Three VideoSDK customers have published what moved them, and all three cite integration speed or support rather than price.</p><p>Immigo, a US-based English learning platform, evaluated the field before choosing. <a href="https://www.videosdk.live/customers/immigo" rel="noreferrer">Immigo</a> went live in under a week and now runs sessions across more than 120 countries</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-09-08-at-4.10.53-PM-1.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1820" height="798"/></figure><p>If you are weighing the same two providers, the trade-offs are set out in <a href="https://www.videosdk.live/blog/zoom-video-sdk-alternative" rel="noreferrer">Zoom Video SDK alternatives</a> and <a href="https://www.videosdk.live/blog/agora-alternative" rel="noreferrer">Agora alternatives</a>.</p><p><a href="https://www.videosdk.live/customers/tyho" rel="noreferrer">Talk Your Heart Out</a>, a Singapore-based therapy platform, moved from Twilio to VideoSDK.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-09-08-at-4.11.26-PM-2.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1820" height="656"/></figure><p>For the wider field, see <a href="https://www.videosdk.live/blog/twilio-video-alternative" rel="noreferrer">Twilio Video alternatives</a>.</p><p>Examedi, a Y Combinator S21 healthcare-at-home marketplace in Latin America, moved its telehealth video after call failures on a previous provider. The <a href="https://www.videosdk.live/customers/examedi" rel="noreferrer">Examedi case study</a> reports a 50 percent reduction in call failures, a 4.8 out of 5 user experience rating, and more than 100,000 patients served. </p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/Screenshot-2026-09-09-at-7.06.36-PM-1.png" class="kg-image" alt="Top 10 Best Video Calling APIs & SDKs for Developers in 2026" loading="lazy" width="1822" height="884"/></figure><p>Read all three as what they are: vendor-published testimonials on the vendor's own site, not independent benchmarks. The useful signal is the pattern. When HD rates sit within a hundredth of a cent of each other, teams move for support responsiveness and integration time, which is exactly what these three cite. Ask any vendor you shortlist for a reference customer in your own vertical.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Room:</strong> a VideoSDK meeting space that participants join to exchange media streams, identified by a unique room ID created through the <a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">REST API</a>.</blockquote><blockquote><strong>SFU (Selective Forwarding Unit):</strong> a media server that receives each participant's stream once and forwards it to everyone else, which is how modern video calling APIs scale beyond peer-to-peer limits.</blockquote><blockquote><strong>Meeting Token:</strong> a JWT that authenticates a participant's access to a VideoSDK room, always generated server-side from your API key and secret.</blockquote><blockquote><strong>Prebuilt UI Kit:</strong> VideoSDK's drop-in call interface that embeds a complete video calling experience with a single component and no custom UI code.</blockquote><blockquote><strong>Participant-minute:</strong> the standard billing unit for video calling APIs; one participant connected for one minute. A 4-person, 30-minute call is 120 participant-minutes.</blockquote><blockquote><strong>Network-Adaptive Streaming:</strong> automatic bitrate and resolution adjustment based on real-time bandwidth detection, which keeps calls alive on 3G instead of freezing them.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>A video calling API replaces months of WebRTC infrastructure work with vendor-hosted media servers and client SDKs your app talks to directly.</li><li>VideoSDK leads the 2026 field on SDK breadth (10+ platforms including Unity and IoT), a Prebuilt UI Kit, and bundled recording, transcription, and interactive live streaming.</li><li>Headline per-minute rates mislead; recording, streaming output, storage, and support plans decide the real bill, so model one month of actual traffic before choosing.</li><li>The right pick is conditional: Agora for broadcast scale, LiveKit for self-hosted control, Chime for AWS-native stacks, and VideoSDK for multi-platform products.</li><li>Throttled-network and firewall testing before you commit catches the failures that office Wi-Fi demos hide.</li></ul><h2 id="start-building-with-a-video-calling-api">Start Building with a Video Calling API</h2><p>Every platform in this list can put two faces on a screen. They differ in what happens at scale, on bad networks, and on your invoice. Shortlist two, run the production testing checklist above, and let measured results pick your video calling API instead of a pricing page.</p><p>If multi-platform coverage and speed to first call matter most, start with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React quickstart</a> or grab your keys with <a href="https://app.videosdk.live/login">free credit at signup</a> and have a working room today.</p><h2 id="frequently-asked-questions">Frequently asked questions</h2><h4 id="what-is-the-best-video-calling-api">What is the best video calling API?</h4><p>The best video calling API depends on the constraint that binds you. VideoSDK leads on documented platform coverage, with 12 client SDKs including Unity and IoT. LiveKit is cheapest at $0.0005 per participant minute and is the only major option you can self-host alongside Jitsi. Amazon Chime SDK is cheapest among managed services at $0.0017.</p><h4 id="how-much-does-a-video-calling-api-cost">How much does a video calling API cost?</h4><p>Published HD rates cluster between $0.0035 and $0.0041 per participant minute as of September 2026. Amazon Chime SDK is lower at $0.0017 for any modality, and LiveKit is lower still at $0.0005. A 30-minute two-person HD call on VideoSDK costs $0.24 at $0.004 per participant minute.</p><h4 id="which-video-calling-apis-can-be-self-hosted">Which video calling APIs can be self-hosted?</h4><p>LiveKit and Jitsi are the two providers in this guide you can self-host, because both publish an open-source media server. Every other provider on the list is managed only. VideoSDK does not offer self-hosting, though private cloud and VPC deployment are available on its Enterprise plan.</p><h4 id="what-is-the-cheapest-video-calling-api">What is the cheapest video calling API?</h4><p>LiveKit publishes the lowest per-minute rate at $0.0005 per participant minute, and Amazon Chime SDK is the cheapest fully managed option at $0.0017 per attendee minute. Self-hosted Jitsi has no per-minute licence cost at all, but you pay for the servers, bandwidth, and the engineers who keep them running.</p><h4 id="do-video-calling-apis-support-hipaa-compliance">Do video calling APIs support HIPAA compliance?</h4><p>Most do, at a price. Daily and 100ms both charge $500 per month for a HIPAA workspace with a signed BAA, LiveKit requires the $500 per month Scale plan, and Whereby charges $16.99 per month. VideoSDK prices HIPAA as a custom add-on. Twilio, Zoom, Vonage, Agora, and Amazon Chime SDK all sign a BAA on request.</p><h4 id="what-is-the-difference-between-a-video-calling-api-and-webrtc">What is the difference between a video calling API and WebRTC?</h4><p>WebRTC is the browser and mobile standard for peer-to-peer media. A video calling API is a hosted service built on top of it that supplies the parts WebRTC leaves to you: a signaling server, TURN relays for restrictive networks, an SFU so calls scale past a handful of participants, recording, and streaming.</p><h4 id="is-videosdk-free-to-use">Is VideoSDK free to use?</h4><p>VideoSDK gives every new account $20 in free credit at signup, which is roughly 5,000 HD participant minutes at $0.004. That credit is one time, not monthly. Agora, Daily, Zoom, and 100ms each give 10,000 free minutes every month instead, so for a long prototype their free tiers last longer.</p><h4 id="which-video-calling-api-is-best-for-telehealth">Which video calling API is best for telehealth?</h4><p>VideoSDK is the pick for telehealth in this guide, because HIPAA is a custom-priced add-on rather than a fixed $500 per month floor, and because two healthcare customers have published deployment results. Daily is the runner-up, with HIPAA and a BAA at $500 per month. Confirm the BAA covers recording and transcription before you send any PHI.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 Video Conferencing Telemedicine APIs: Expert-Reviewed and Ranked]]></title><description><![CDATA[A factual ranking of ten video conferencing telemedicine APIs using a transparent 100-point model for healthcare readiness, SDK reach, patient experience, reliability, operations, and pricing.]]></description><link>https://www.videosdk.live/blog/video-conferencing-telemedicine-api</link><guid isPermaLink="false">6a7d6f8db3240feb748c963c</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 13 Aug 2026 12:19:04 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/Gemini_Generated_Image_uw7rgruw7rgruw7r.png" medium="image"/><content:encoded><![CDATA[<blockquote>A video conferencing telemedicine API embeds secure virtual consultations inside a healthcare product. VideoSDK ranks first for flexible, multi-platform development, while Daily leads on publicly documented healthcare onboarding. For US deployments involving protected health information, no provider should reach production without a signed BAA, approved configuration, and organisation-wide HIPAA controls.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Gemini_Generated_Image_uw7rgruw7rgruw7r.png" alt="Top 10 Video Conferencing Telemedicine APIs: Expert-Reviewed and Ranked"/><p>This review ranks ten active platforms using official documentation checked on 13 August 2026. VideoSDK leads overall, but the right choice still depends on your contract, technology stack, and clinical workflow.</p><p>The assessment covers healthcare readiness, SDK reach, patient experience, media resilience, workflow extensibility, operations, and pricing clarity. It is not legal advice or a substitute for production testing.</p><h2 id="what-is-a-video-conferencing-telemedicine-api">What Is a Video Conferencing Telemedicine API?</h2><p>A video conferencing telemedicine API is a programmable service for adding live audio, video, screen sharing, messaging, and session controls to a healthcare application.</p><p>It works by authenticating participants, creating a protected meeting room, routing <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> media, and exposing events that your application connects to scheduling, consent, support, and clinical systems.</p><p>VideoSDK provides this model through room APIs, client SDKs, a <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Prebuilt UI Kit</a>, recording, transcription, role controls, analytics, and platform-specific quickstarts.</p><p>For US healthcare, security features are only one layer. <a href="https://telehealth.hhs.gov/providers/telehealth-policy/hipaa-for-telehealth-technology">US Department of Health and Human Services guidance</a> says covered providers and health plans must use technology vendors that comply with HIPAA Rules and enter into business associate agreements.</p><p>A HIPAA badge cannot replace a signed <a href="https://www.hhs.gov/hipaa/for-professionals/privacy/guidance/business-associates/index.html" rel="noreferrer">BAA</a> covering the exact service that creates, receives, maintains, or transmits protected health information. The agreement, configuration, and operating process must work together.</p><h2 id="how-we-ranked-each-video-conferencing-telemedicine-api">How We Ranked Each Video Conferencing Telemedicine API</h2><p>This ranking measures documented production fit, not marketing volume or brand recognition.</p><p>We applied a 100-point framework to every provider. Missing or unclear public evidence reduced a score, even when a sales team may provide stronger evidence privately.</p><ol><li><strong>Healthcare readiness, 25 points:</strong> BAA availability, eligible service scope, encryption, access controls, audit evidence, retention, and recording restrictions.</li><li><strong>SDK and platform coverage, 15 points:</strong> Web, iOS, Android, React Native, Flutter, server SDKs, and API consistency.</li><li><strong>Patient and clinician experience, 15 points:</strong> Prebuilt UI, browser access, device checks, waiting rooms, accessibility, and low-friction joining.</li><li><strong>Media resilience, 15 points:</strong> Adaptive quality, TURN or proxy options, diagnostics, regional controls, and mobile network support.</li><li><strong>Clinical workflow extensibility, 10 points:</strong> Roles, interpreters, group visits, screen sharing, telephony, events, and EHR integration paths.</li><li><strong>Operations and observability, 10 points:</strong> Analytics, webhooks, recording controls, transcription, support, and incident investigation tools.</li><li><strong>Pricing clarity, 10 points:</strong> Public rates, free evaluation capacity, predictable metering, add-ons, and enterprise procurement clarity.</li></ol><h3 id="what-%E2%80%9Cexpert-reviewed%E2%80%9D-means">What “expert-reviewed” means</h3><p>This is a documentation-based technical assessment of official product pages, security material, pricing, API references, quickstarts, and current product notices. We did not send PHI.</p><p>We also did not run independent latency, packet-loss, penetration, accessibility, or clinical workflow benchmarks. Your team should repeat those tests with representative devices, patient networks, and approved test data.</p><p>Scores express editorial judgement against the published rubric. They are not security certifications, legal opinions, vendor audits, or guarantees about performance in your application or geography.</p><blockquote><strong>Compliance gate:</strong> Exclude any provider that will not sign an appropriate BAA before receiving PHI. Confirm covered products, subprocessors, regions, recordings, transcripts, support access, and retention in writing.</blockquote><h2 id="top-10-video-conferencing-telemedicine-apis">Top 10 Video Conferencing Telemedicine APIs</h2><p>No platform is the universal winner because healthcare requirements change across products, jurisdictions, patient groups, and existing cloud environments.</p><h3 id="1-videosdk-best-for-custom-multi-platform-care">1. VideoSDK: Best for custom multi-platform care</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.29.39-PM-5.png" class="kg-image" alt="Top 10 Video Conferencing Telemedicine APIs: Expert-Reviewed and Ranked" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> ranks first for teams that need one real-time communication platform across web, native mobile, cross-platform frameworks, backend Python, Unity, C++, and connected-device use cases.</p><p>Its <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start">JavaScript quickstart</a> sits within documentation for waiting lobbies, connection events, recordings, transcription, geofencing, proxy controls, security, and call-quality features.</p><p>The <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">prebuilt UI kit</a> offers a faster prototype path, while custom SDKs support branded patient and clinician experiences. This combination is useful when an MVP must later become a deeply integrated product.</p><p>For telemedicine, VideoSDK documents adaptive streaming, roles, end-to-end encryption, individual and composite recording, real-time transcription, post-call workflows, and a healthcare-focused <a href="https://www.videosdk.live/solutions/video-mer">video medical examination solution</a>.</p><p><a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api#2-end-to-end-encryption-for-media-and-signaling">VideoSDK's HIPAA guide</a> states that its formal BAA is available as an add-on on both Pay-As-You-Go and Enterprise plans. Customers can subscribe through <strong>VideoSDK Dashboard → Billing → Add-ons</strong>.</p><p><strong>Best for:</strong> Digital-health products spanning patient mobile apps, clinician web consoles, interpreters, group visits, and connected diagnostic devices.</p><p><strong>Trade-off:</strong> VideoSDK's <a href="https://docs.videosdk.live/help_docs/security-and-privacy/hipaa#disabled-features-in-hipaa" rel="noreferrer">HIPAA mode blocks features</a> that store or process data on third-party servers, such as disabling live transcription, post-call transcription, AI-generated summaries, HLS, and RTMP-out. Encrypted video, audio, screen sharing, whiteboard, and SIP remain available. Confirm these restrictions against your clinical workflow before integration.</p><p><strong>Public pricing:</strong> <a href="https://www.videosdk.live/pricing">VideoSDK pricing</a> lists video at $0.004 per participant-minute, audio at $0.001, usage-based add-ons, and a one-time $20 starting credit.</p><p><strong>Score:</strong> 97/100. VideoSDK leads on documented BAA availability, SDK breadth, flexible user experience, clinical workflow depth, operational features, and base-price clarity.</p><h3 id="2-daily-best-documented-healthcare-onboarding">2. Daily: Best documented healthcare onboarding</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.02-PM-4.png" class="kg-image" alt="Top 10 Video Conferencing Telemedicine APIs: Expert-Reviewed and Ranked" loading="lazy" width="2924" height="1652"/></figure><p><a href="https://www.daily.co/" rel="noreferrer nofollow">Daily</a> ranks second because it combines custom call APIs, Daily Prebuilt, mature WebRTC infrastructure, and unusually clear healthcare configuration guidance.</p><p>Daily's <a href="https://docs.daily.co/docs/guides/privacy-and-security/hipaa" rel="noreferrer nofollow">HIPAA documentation</a> explains its BAA, random room names, restricted logs, recording destinations, disabled live streaming, and other HIPAA-mode limitations. That detail makes early procurement discussions more concrete.</p><p>The platform supports browser-first patient access, custom web and mobile experiences, REST-managed rooms, recordings, transcription, analytics, and integrations with Daily's wider real-time ecosystem.</p><p><strong>Best for:</strong> Web-first telehealth teams that value fast implementation, a prebuilt option, and public healthcare onboarding details.</p><p><strong>Trade-off:</strong> HIPAA mode restricts some features, and the fixed healthcare fee matters for early-stage teams. Recording, storage, transcription, and AI processors still require separate data-flow review.</p><p><strong>Public pricing:</strong> <a href="https://www.daily.co/pricing/video-sdk/" rel="noreferrer nofollow">Daily pricing</a> lists 10,000 free monthly participant-minutes, then $0.004 per participant-minute in the first paid tier. The Healthcare add-on costs $500 monthly.</p><p><strong>Score:</strong> 91/100. Daily is the strongest alternative when explicit public BAA packaging matters more than maximum client-platform breadth.</p><h3 id="3-vonage-video-api-best-communications-bundle">3. Vonage Video API: Best communications bundle</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.32.16-PM-3.png" class="kg-image" alt="Top 10 Video Conferencing Telemedicine APIs: Expert-Reviewed and Ranked" loading="lazy" width="2922" height="1652"/></figure><p><a href="https://www.vonage.com/communications-apis/video/" rel="noreferrer nofollow">Vonage</a> ranks third for healthcare platforms that want video, voice, SMS, SIP, and enterprise communications from one established provider.</p><p>The current <a href="https://developer.vonage.com/en/getting-started/concepts/regulatory-certifications" rel="noreferrer nofollow">Vonage regulatory page</a> lists HIPAA coverage for Video API and Media Services, including SIP, callbacks, captioning, Experience Composer, and its NextGen environment.</p><p>Video API also supports encrypted sessions, archiving, captions, callbacks, analytics, <a href="https://www.videosdk.live/developer-hub/sip/mastering-sip-protocol-comprehensive-guide" rel="noreferrer">SIP</a>, and large interactive or broadcast patterns. Those capabilities fit coordinated patient-engagement journeys across several communication channels.</p><p><strong>Best for:</strong> Hospitals and digital-health companies already using Vonage communications, or products combining consultations with reminders, interpreter access, care calls, and status messaging.</p><p><strong>Trade-off:</strong> A broad enterprise product surface can create more procurement and configuration work than a video-only platform. Confirm that every enabled media or AI service shares the required BAA scope.</p><p><strong>Public pricing:</strong> <a href="https://www.vonage.com/communications-apis/video/pricing/" rel="noreferrer nofollow">Vonage Video API pricing</a> lists $0.00410 per participant-minute, with separate charges for recording, captions, SIP, and other media services.</p><p><strong>Score:</strong> 89/100. Vonage scores highest when communications consolidation and enterprise media services matter more than a lightweight self-serve journey.</p><h3 id="4-amazon-chime-sdk-best-for-aws-native-healthcare">4. Amazon Chime SDK: Best for AWS-native healthcare</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.54.40-PM-2.png" class="kg-image" alt="Top 10 Video Conferencing Telemedicine APIs: Expert-Reviewed and Ranked" loading="lazy" width="2918" height="1632"/></figure><p><a href="https://aws.amazon.com/chime/chime-sdk/" rel="noreferrer nofollow">Amazon Chime SDK</a> ranks fourth because AWS publishes precise eligible-service evidence and connects media workflows to familiar cloud security and audit tooling.</p><p><a href="https://aws.amazon.com/compliance/hipaa-eligible-services-reference/" rel="noreferrer nofollow">AWS lists</a> Amazon Chime SDK as HIPAA eligible. Customers must still have an AWS Business Associate Addendum and configure every connected AWS service appropriately.</p><p>The SDK provides web and mobile meeting clients, attendee tokens, media capture, live transcription, screen sharing, event integrations, SIP, and PSTN options. Recordings can feed protected S3, KMS, CloudTrail, and retention workflows.</p><p><strong>Best for:</strong> Healthcare engineering teams already operating under an AWS BAA and using IAM, CloudTrail, CloudWatch, Lambda, S3, and KMS for governance.</p><p><strong>Trade-off:</strong> Chime SDK supplies components, not a finished telemedicine experience. Your team owns patient UI, waiting-room state, scheduling, consent, support, and much of the workflow orchestration.</p><p><strong>Public pricing checked 13 August 2026:</strong> <a href="https://aws.amazon.com/chime/chime-sdk/pricing/" rel="noreferrer nofollow">Amazon Chime SDK pricing</a> lists standard WebRTC media at $0.0017 per attendee-minute. Capture, concatenation, transcription, PSTN, storage, and related AWS services add separate charges.</p><p><strong>Score:</strong> 88/100. AWS becomes the practical winner when cloud consolidation and formal service-scope evidence matter more than the fastest implementation.</p><h3 id="5-livekit-best-for-open-source-control">5. LiveKit: Best for open-source control</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.40-PM-3.png" class="kg-image" alt="Top 10 Video Conferencing Telemedicine APIs: Expert-Reviewed and Ranked" loading="lazy" width="2920" height="1670"/></figure><p><a href="https://livekit.com/" rel="noreferrer nofollow">LiveKit</a> ranks fifth for teams that value an open-source WebRTC SFU, managed cloud deployment, self-hosting flexibility, raw media access, and agent-oriented extensions.</p><p>Its <a href="https://livekit.com/legal/hipaa" rel="noreferrer nofollow">HIPAA-eligible services page</a> covers WebRTC and SIP transport, egress, ingress, agent hosting, observability, and named inference services. It also requires a LiveKit BAA before PHI use.</p><p>LiveKit supports web, mobile, and server SDKs, end-to-end encryption, region pinning, connection-quality events, telephony, webhooks, ingress, egress, and compatible self-hosted deployments.</p><p><strong>Best for:</strong> Infrastructure-capable teams building highly custom telehealth, remote monitoring, multimodal clinical assistants, or architectures that may move between managed and self-hosted deployment.</p><p><strong>Trade-off:</strong> Flexibility transfers more design, reliability, and compliance responsibility to your team. Region pinning, security reports, and HIPAA features begin on the Scale plan.</p><p><strong>Public pricing checked 13 August 2026:</strong> <a href="https://livekit.com/pricing" rel="noreferrer nofollow">LiveKit pricing</a> lists Build at $0, Ship from $50 monthly, and Scale from $500 monthly. WebRTC minutes, data transfer, egress, and other usage are metered by plan.</p><p><strong>Score:</strong> 87/100. LiveKit is a strong infrastructure choice, but many telemedicine teams will spend more engineering time on patient-facing and operational layers.</p><h3 id="6-whereby-embedded-best-browser-first-patient-access">6. Whereby Embedded: Best browser-first patient access</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.34.01-PM-1.png" class="kg-image" alt="Top 10 Video Conferencing Telemedicine APIs: Expert-Reviewed and Ranked" loading="lazy" width="2890" height="1624"/></figure><p><a href="https://whereby.com/" rel="noreferrer nofollow">Whereby</a> Embedded ranks sixth for low-friction consultations where patients should join securely in a browser without installing another application.</p><p>Whereby's <a href="https://docs.whereby.com/whereby-101/faq-and-troubleshooting/hipaa-compliant-setup" rel="noreferrer nofollow">HIPAA setup guide</a> describes its standard BAA, locked rooms, UUID room names, disabled integrations, recording storage, transcription, and configuration responsibilities.</p><p>Developers can start with a web component or prebuilt UI, then use browser and core SDKs for deeper control. The approach favours quick embedding and patient simplicity.</p><p><strong>Best for:</strong> EHR vendors, therapy platforms, virtual clinics, and web-first products where no-download access outweighs deep media processing.</p><p><strong>Trade-off:</strong> Healthcare configuration limits some features, and the product offers less native and media-level control than broader SDK platforms.</p><p><strong>Public pricing checked 13 August 2026:</strong> <a href="https://whereby.com/information/embedded" rel="noreferrer nofollow">Whereby Embedded pricing</a> lists Build at $9.99 monthly, $0.004 per participant-minute with 2,000 included minutes, and a $16.99 monthly HIPAA add-on. Enterprise includes HIPAA support.</p><p><strong>Score:</strong> 86/100. Whereby earns its place through patient simplicity, transparent healthcare pricing, and detailed compliance instructions.</p><h3 id="7-100ms-best-for-structured-hipaa-workspaces">7. 100ms: Best for structured HIPAA workspaces</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.31.12-PM-3.png" class="kg-image" alt="Top 10 Video Conferencing Telemedicine APIs: Expert-Reviewed and Ranked" loading="lazy" width="2910" height="1656"/></figure><p><a href="https://www.100ms.live/" rel="noreferrer nofollow">100ms</a> ranks seventh because its healthcare documentation explains how platform behaviour changes inside a HIPAA workspace.</p><p>The <a href="https://www.100ms.live/docs/get-started/v2/get-started/security-and-privacy/HIPAA%20compliance/HIPAA-workspace" rel="noreferrer nofollow">100ms HIPAA workspace guide</a> covers its BAA, hashed participant data, customer-controlled recording storage, disabled live streaming, webhook verification, and PHI-safe user identifiers.</p><p>Its SDKs span web, Android, iOS, React Native, and Flutter. Teams can choose a prebuilt experience or headless SDKs, with roles, recordings, interactive live streaming outside HIPAA workspaces, and open-source client code.</p><p><strong>Best for:</strong> Teams wanting explicit HIPAA workspace behaviour, cross-platform SDKs, roles, and both prebuilt and custom development paths.</p><p><strong>Trade-off:</strong> HIPAA workspaces disable live streaming, require customer storage for recording, and introduce operational rules that must be reflected in application design.</p><p><strong>Public pricing checked 13 August 2026:</strong> The healthcare add-on costs $500 monthly and includes a signed BAA, according to 100ms documentation. Public trial allowances include 10,000 standard video-conferencing minutes.</p><p><strong>Score:</strong> 85/100. 100ms is attractive when healthcare-specific platform behaviour matters more than consolidated communications or open-source server control.</p><h3 id="8-twilio-programmable-video-best-for-twilio-estates">8. Twilio Programmable Video: Best for Twilio estates</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.53.31-PM-3.png" class="kg-image" alt="Top 10 Video Conferencing Telemedicine APIs: Expert-Reviewed and Ranked" loading="lazy" width="2910" height="1638"/></figure><p><a href="https://www.twilio.com/en-us" rel="noreferrer nofollow">Twilio</a> ranks eighth for organisations already using Twilio Voice, Messaging, Verify, Flex, or other customer-engagement products.</p><p>Twilio lists Programmable Video Group Rooms as a HIPAA-eligible service and <a href="https://www.twilio.com/en-us/changelog/programmable-video-is-now-hipaa-eligible" rel="noreferrer nofollow">offers BAAs for eligible products</a>. Its healthcare architecture guidance adds safeguards for recordings, URLs, and DataTrack integrations.</p><p>The product supports JavaScript, iOS, and Android clients, participant recording, compositions, transcription, network-quality APIs, bandwidth profiles, TURN relay, virtual backgrounds, and noise cancellation.</p><p><strong>Best for:</strong> Existing Twilio customers building scheduled consultations, support escalation, interpreter calls, or patient engagement across video, SMS, and voice.</p><p><strong>Trade-off:</strong> Twilio first announced a 2026 Video end-of-life, then <a href="https://www.twilio.com/en-us/changelog/-twilio-video-will-remain-a-standalone-product" rel="noreferrer nofollow">reversed that decision</a> in October 2024. New buyers should still compare its roadmap with video-specialist platforms.</p><p><strong>Public pricing checked 13 August 2026:</strong> <a href="https://www.twilio.com/en-us/video/pricing" rel="noreferrer nofollow">Twilio Video pricing</a> starts at $0.004 per participant-minute, with separate recording, composition, transcription, storage, and security charges.</p><p><strong>Score:</strong> 84/100. Twilio provides the strongest value when an organisation already benefits from its wider communications stack.</p><h3 id="9-agora-best-for-global-media-reach">9. Agora: Best for global media reach</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.26-PM-5.png" class="kg-image" alt="Top 10 Video Conferencing Telemedicine APIs: Expert-Reviewed and Ranked" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/en/" rel="noreferrer nofollow">Agora</a> ranks ninth for teams prioritising geographic reach, media quality controls, device coverage, high concurrency, and resolution-based pricing.</p><p>Agora's <a href="https://www.agora.io/en/compliance/" rel="noreferrer nofollow">compliance page</a> states that the company acts as a HIPAA Business Associate and maintains an ongoing compliance programme. Procurement teams should still obtain the applicable BAA and covered-service schedule.</p><p>The platform offers SDKs across major web, mobile, desktop, game, and embedded environments, plus proxy modes, recording, analytics, signalling, whiteboard, and interactive streaming products.</p><p><strong>Best for:</strong> International care products, assisted examinations, group consultations, and healthcare experiences needing broad device support or regional routing choices.</p><p><strong>Trade-off:</strong> Public pages provide less detail about BAA onboarding and covered plans than Daily, Whereby, 100ms, or LiveKit. Resolution-based pricing can also complicate forecasting.</p><p><strong>Public pricing checked 13 August 2026:</strong> <a href="https://www.agora.io/en/pricing/video-calling/" rel="noreferrer nofollow">Agora video pricing</a> lists HD video at $3.99 per 1,000 participant-minutes, Full HD at $8.99, and 10,000 free monthly minutes. Add-ons have separate rates.</p><p><strong>Score:</strong> 83/100. Agora scores strongly on media infrastructure and device reach, with deductions for healthcare procurement detail and cost-model complexity.</p><h3 id="10-zoom-video-sdk-best-for-zoom-aligned-enterprises">10. Zoom Video SDK: Best for Zoom-aligned enterprises</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.32.46-PM-1.png" class="kg-image" alt="Top 10 Video Conferencing Telemedicine APIs: Expert-Reviewed and Ranked" loading="lazy" width="2920" height="1646"/></figure><p><a href="https://www.zoom.com/en/video-sdk/" rel="noreferrer nofollow">Zoom Video SDK</a> ranks tenth for enterprises that trust Zoom's media infrastructure but need a custom interface instead of a standard Zoom Meeting.</p><p>Zoom's <a href="https://zoom.us/pricing/developer" rel="noreferrer nofollow">developer pricing page</a> states that Video SDK helps customers with a BAA enable HIPAA compliance. It also distinguishes Video SDK from Zoom Meetings and Zoom clients.</p><p>The SDK supports video, audio, screen sharing, chat, cloud recording, transcription, translation, PSTN, live streaming, raw data, and custom-branded experiences across major platforms and browsers.</p><p><strong>Best for:</strong> Large healthcare organisations with established Zoom procurement, support relationships, and internal teams familiar with Zoom technology.</p><p><strong>Trade-off:</strong> Zoom Meeting, Zoom for Healthcare, and Zoom Video SDK are distinct products. Confirm account type, BAA scope, eligible features, data flows, and enabled AI services before implementation.</p><p><strong>Public pricing checked 13 August 2026:</strong> Zoom describes usage-based, prepaid credit billing for Video SDK but does not expose a simple comparable per-minute rate on the public plan card.</p><p><strong>Score:</strong> 82/100. Zoom fits established enterprise buying patterns, but product boundaries and public price comparability require extra validation.</p><h2 id="video-conferencing-telemedicine-api-comparison-table">Video Conferencing Telemedicine API Comparison Table</h2><p>This comparison table compresses the ranking into the factors most useful during an initial architecture shortlist.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th style="text-align:right">Rank</th>
<th>Provider</th>
<th style="text-align:right">Score</th>
<th>Best for</th>
<th>Public healthcare evidence</th>
<th>Public starting price</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">1</td>
<td><strong>VideoSDK</strong></td>
<td style="text-align:right">97</td>
<td>Custom multi-platform care</td>
<td>HIPAA and security claims; BAA add-on</td>
<td>$0.004 per participant-minute, 20$ free credits</td>
</tr>
<tr>
<td style="text-align:right">2</td>
<td>Daily</td>
<td style="text-align:right">91</td>
<td>Documented healthcare onboarding</td>
<td>Healthcare add-on and BAA documented</td>
<td>$0.004; $500 healthcare add-on</td>
</tr>
<tr>
<td style="text-align:right">3</td>
<td>Vonage Video API</td>
<td style="text-align:right">89</td>
<td>Video, voice, and SMS bundle</td>
<td>Video API HIPAA coverage documented</td>
<td>$0.00410 per participant-minute</td>
</tr>
<tr>
<td style="text-align:right">4</td>
<td>Amazon Chime SDK</td>
<td style="text-align:right">88</td>
<td>AWS-native healthcare</td>
<td>HIPAA-eligible service under AWS BAA</td>
<td>$0.0017 per attendee-minute</td>
</tr>
<tr>
<td style="text-align:right">5</td>
<td>LiveKit</td>
<td style="text-align:right">87</td>
<td>Open-source control</td>
<td>Eligible services and BAA requirement documented</td>
<td>Plan plus usage and data transfer</td>
</tr>
<tr>
<td style="text-align:right">6</td>
<td>Whereby Embedded</td>
<td style="text-align:right">86</td>
<td>Browser-first visits</td>
<td>Standard BAA and setup guide documented</td>
<td>$9.99 monthly plus usage; $16.99 HIPAA add-on</td>
</tr>
<tr>
<td style="text-align:right">7</td>
<td>100ms</td>
<td style="text-align:right">85</td>
<td>Structured HIPAA workspaces</td>
<td>Healthcare add-on and BAA documented</td>
<td>$500 healthcare add-on; trial allowances</td>
</tr>
<tr>
<td style="text-align:right">8</td>
<td>Twilio Video</td>
<td style="text-align:right">84</td>
<td>Existing Twilio estates</td>
<td>Group Rooms listed as HIPAA eligible</td>
<td>$0.004 per participant-minute</td>
</tr>
<tr>
<td style="text-align:right">9</td>
<td>Agora</td>
<td style="text-align:right">83</td>
<td>Global media reach</td>
<td>Business Associate status stated; confirm BAA</td>
<td>HD from $3.99 per 1,000 participant-minutes</td>
</tr>
<tr>
<td style="text-align:right">10</td>
<td>Zoom Video SDK</td>
<td style="text-align:right">82</td>
<td>Zoom-aligned enterprises</td>
<td>HIPAA support for customers with BAA</td>
<td>Prepaid credits and minute-based usage</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<blockquote><em>Prices are public list prices checked on 13 August 2026. Taxes, volume discounts, support, recording, storage, transcription, network services, AI features, and healthcare agreements can change the total.</em></blockquote><p>VideoSDK leads after the compliance gate because it combines broad SDK coverage, prebuilt and custom UI paths, telehealth-relevant media controls, and public usage pricing.</p><p>The grouped scorecard below shows how the 100-point totals were formed. “Product and media” combines SDK coverage, user experience, and media resilience.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Provider</th>
<th style="text-align:right">Healthcare /25</th>
<th style="text-align:right">Product and media /45</th>
<th style="text-align:right">Workflow and operations /20</th>
<th style="text-align:right">Pricing /10</th>
<th style="text-align:right">Total</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td style="text-align:right">25</td>
<td style="text-align:right">43</td>
<td style="text-align:right">20</td>
<td style="text-align:right">9</td>
<td style="text-align:right">97</td>
</tr>
<tr>
<td>Daily</td>
<td style="text-align:right">25</td>
<td style="text-align:right">42</td>
<td style="text-align:right">17</td>
<td style="text-align:right">7</td>
<td style="text-align:right">91</td>
</tr>
<tr>
<td>Vonage Video API</td>
<td style="text-align:right">24</td>
<td style="text-align:right">39</td>
<td style="text-align:right">19</td>
<td style="text-align:right">7</td>
<td style="text-align:right">89</td>
</tr>
<tr>
<td>Amazon Chime SDK</td>
<td style="text-align:right">25</td>
<td style="text-align:right">34</td>
<td style="text-align:right">19</td>
<td style="text-align:right">10</td>
<td style="text-align:right">88</td>
</tr>
<tr>
<td>LiveKit</td>
<td style="text-align:right">25</td>
<td style="text-align:right">39</td>
<td style="text-align:right">17</td>
<td style="text-align:right">6</td>
<td style="text-align:right">87</td>
</tr>
<tr>
<td>Whereby Embedded</td>
<td style="text-align:right">25</td>
<td style="text-align:right">38</td>
<td style="text-align:right">15</td>
<td style="text-align:right">8</td>
<td style="text-align:right">86</td>
</tr>
<tr>
<td>100ms</td>
<td style="text-align:right">25</td>
<td style="text-align:right">38</td>
<td style="text-align:right">15</td>
<td style="text-align:right">7</td>
<td style="text-align:right">85</td>
</tr>
<tr>
<td>Twilio Video</td>
<td style="text-align:right">25</td>
<td style="text-align:right">36</td>
<td style="text-align:right">17</td>
<td style="text-align:right">6</td>
<td style="text-align:right">84</td>
</tr>
<tr>
<td>Agora</td>
<td style="text-align:right">20</td>
<td style="text-align:right">41</td>
<td style="text-align:right">14</td>
<td style="text-align:right">8</td>
<td style="text-align:right">83</td>
</tr>
<tr>
<td>Zoom Video SDK</td>
<td style="text-align:right">24</td>
<td style="text-align:right">37</td>
<td style="text-align:right">16</td>
<td style="text-align:right">5</td>
<td style="text-align:right">82</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h3 id="how-should-you-choose-a-telemedicine-video-api">How Should You Choose a Telemedicine Video API?</h3><p>The safest selection process eliminates unacceptable compliance contracts before comparing features, code samples, or list prices.</p><ol><li><strong>Confirm the legal boundary.</strong> Obtain a BAA and list every covered API, storage system, recording mode, transcription feature, support workflow, region, subprocessor, and retention setting.</li><li><strong>Model the clinical encounter.</strong> Document consent, identity verification, waiting, clinician admission, interpreter access, screen sharing, follow-up, emergency escalation, and closure.</li><li><strong>Test real patient conditions.</strong> Include older phones, weak mobile networks, restrictive hospital firewalls, denied permissions, Bluetooth devices, accessibility tools, reconnection, and audio-only fallback.</li><li><strong>Separate media from PHI systems.</strong> Use opaque room IDs, short-lived tokens, least-privilege roles, authenticated webhooks, PHI-safe logs, and protected links to scheduling or EHR records.</li><li><strong>Decide whether recording is necessary.</strong> Define consent, encryption, destination, access, audit events, retention, deletion, and export before enabling it.</li><li><strong>Calculate the full session cost.</strong> Include two participant streams, waiting time, recording, storage, transcription, analytics, proxy traffic, support, healthcare fees, and failed joins.</li><li><strong>Run a production-shaped proof.</strong> Measure join success, time to first media, reconnection, packet loss, device failures, support events, clinician task completion, and cost across target regions.</li></ol><p>The strongest procurement process gives security, clinical operations, engineering, accessibility, support, finance, and legal teams the same evidence before a vendor decision.</p><h2 id="what-most-telemedicine-api-rankings-miss">What Most Telemedicine API Rankings Miss</h2><p>Most rankings compare media features while ignoring the application controls that surround each consultation.</p><h3 id="do-not-place-phi-in-identifiers">Do not place PHI in identifiers</h3><p>Room names, token claims, URLs, webhook payloads, analytics properties, crash reports, and support tickets can expose patient context. Use opaque identifiers and resolve clinical data only inside protected systems.</p><h3 id="design-failure-as-a-clinical-workflow">Design failure as a clinical workflow</h3><p>A frozen screen is not merely a media bug during a consultation. Provide visible network state, reconnection guidance, audio-only fallback, support access, and documented emergency alternatives.</p><h3 id="treat-recording-as-a-separate-product">Treat recording as a separate product</h3><p>Recording creates a new PHI object with separate consent, storage, key management, access, retention, audit, export, and deletion requirements. “Recording supported” answers almost none of those questions.</p><h3 id="verify-every-ai-and-transcription-path">Verify every AI and transcription path</h3><p>Transcription, summaries, assistants, and note generation may introduce processors outside the video provider's BAA. Confirm eligible models, retention, regions, logs, human review, and output storage.</p><h3 id="protect-the-webhook-boundary">Protect the webhook boundary</h3><p>Participant and recording events can trigger clinical workflows. Authenticate webhook signatures, reject replays, store the minimum required payload, and prevent sensitive fields from reaching general observability tools.</p><p>The practical rule is simple: evaluate the full data flow, not only the encrypted media path.</p><h2 id="is-videosdk-the-best-telemedicine-video-api">Is VideoSDK the Best Telemedicine Video API?</h2><p>VideoSDK is the strongest overall option in this ranking for multi-platform product development, provided its BAA covers your exact services and configuration.</p><p>Use VideoSDK when your roadmap spans web and mobile, demands custom clinical roles, or may later add telephony, interactive streaming, transcription, post-call workflows, or connected devices.</p><p>Use Daily when clearly published healthcare packaging and BAA onboarding are your leading shortlist criteria. Use Amazon Chime SDK when existing AWS governance and security tooling dominate the decision.</p><p>Use LiveKit when self-hosting or raw media control is essential. Use Whereby when no-download browser access matters more than deep media customisation.</p><p>Activate the VideoSDK BAA add-on under <strong>Dashboard → Billing → Add-ons</strong> and execute the agreement before PHI enters the platform. Then verify HIPAA-mode restrictions, recording storage, subprocessors, regions, and retention against your approved data flow.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Room:</strong> A logical VideoSDK meeting space that authorised participants join using a room ID and token. Use an opaque identifier containing no patient information.</blockquote><blockquote><strong>Participant:</strong> A patient, clinician, interpreter, caregiver, or approved service connected to a room with permissions governing media, screen sharing, recording, and moderation.</blockquote><blockquote><strong>Meeting token:</strong> A signed credential authorising room access. Generate short-lived VideoSDK tokens on a protected server and never expose API secrets in browser or mobile code.</blockquote><blockquote><strong>Business Associate Agreement:</strong> A contract describing how a vendor may handle PHI and the safeguards it must apply. A BAA does not make your application automatically compliant.</blockquote><blockquote><strong>Network-adaptive streaming:</strong> Media logic that adjusts bitrate or resolution as network conditions change. This protects call continuity when patient bandwidth varies.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><p>The shortlist becomes easier when compliance evidence, product fit, and operating cost are evaluated separately.</p><ul><li>A signed BAA covering the exact product and features is a mandatory gate for US telemedicine workflows that handle PHI.</li><li>VideoSDK ranks first for custom multi-platform development and offers a formal BAA add-on on both Pay-As-You-Go and Enterprise plans.</li><li>Daily offers the clearest public healthcare onboarding, while Vonage and AWS suit communications or cloud consolidation strategies.</li><li>Vendor demos cannot replace tests covering weak networks, accessibility, reconnection, permissions, recordings, transcripts, logs, and support access.</li><li>Your application remains responsible for consent, identity, scheduling, EHR links, audit trails, emergency workflows, access control, retention, and metadata design.</li></ul><h2 id="conclusion">Conclusion</h2><p>The right video conferencing telemedicine API clears your compliance gate and performs reliably throughout the patient journey. VideoSDK is our top developer-focused choice for flexible, multi-platform builds, with a BAA add-on available on Pay-As-You-Go and Enterprise plans. Activate it before PHI processing, then run a production-shaped proof. Review the <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK quickstart</a> or <a href="https://app.videosdk.live/login">create an account</a> to test without PHI. What telemedicine workflow are you building?</p><h2 id="related-videosdk-guides">Related VideoSDK Guides</h2><p>These VideoSDK resources map directly to the recommended telemedicine architecture and evaluation criteria.</p><ul><li><a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK JavaScript video and audio quickstart</a></li><li><a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/authentication-and-token">VideoSDK authentication and token guide</a></li><li><a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">VideoSDK Prebuilt UI Kit quickstart</a></li><li><a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">VideoSDK real-time communication REST API</a></li><li><a href="https://docs.videosdk.live/code-sample">VideoSDK code samples</a></li></ul><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-best-video-api-for-telemedicine">What is the best video API for telemedicine?</h3><p>The best video API for telemedicine depends on your BAA, platforms, patient journey, and operating model. VideoSDK leads this ranking for custom multi-platform development after written BAA verification.</p><p>Daily is preferable when documented healthcare onboarding is the first criterion, while Amazon Chime SDK suits teams already governing workloads under an AWS BAA.</p><h3 id="what-is-the-difference-between-hipaa-compliance-and-a-baa">What is the difference between HIPAA compliance and a BAA?</h3><p>HIPAA compliance refers to the legal, technical, and operational safeguards used to protect health information. A BAA is the contract that defines a business associate's permitted PHI use and responsibilities.</p><p>A signed BAA is necessary in applicable US healthcare relationships, but it does not automatically make your application or workflow compliant.</p><h3 id="is-a-video-conferencing-api-automatically-hipaa-compliant">Is a video conferencing API automatically HIPAA compliant?</h3><p>No, a video conferencing API is not automatically HIPAA compliant. Your organisation needs an appropriate BAA, eligible services, correct configuration, risk analysis, access controls, and operating safeguards.</p><p>The complete application must also protect scheduling, identity, logs, recordings, transcripts, support access, integrations, retention, and every other system touching PHI.</p><h3 id="does-videosdk-support-telemedicine-applications">Does VideoSDK support telemedicine applications?</h3><p>Yes, VideoSDK supports telemedicine patterns through real-time rooms, waiting lobbies, roles, adaptive media, screen sharing, recording, transcription, post-call workflows, and analytics.</p><p>Before using PHI, confirm the applicable VideoSDK BAA, plan, service scope, subprocessors, regions, data retention, recording configuration, and organisational responsibilities in writing.</p><h3 id="what-features-should-a-telemedicine-video-sdk-include">What features should a telemedicine video SDK include?</h3><p>A telemedicine video SDK should include secure authentication, waiting rooms, participant roles, adaptive media, reconnection, device checks, screen sharing, access controls, observable events, and audio fallback.</p><p>Interpreter access, regional routing, audit exports, recording, transcription, telephony, and EHR event integration become important when the clinical workflow requires them.</p><h3 id="how-much-does-a-telemedicine-video-api-cost">How much does a telemedicine video API cost?</h3><p>Telemedicine video API cost usually combines participant-minutes with recording, storage, transcription, analytics, support, proxy, telephony, and healthcare-plan charges. A two-person consultation consumes two participant-minutes per elapsed minute.</p><p>Model waiting-room and failed-join behaviour because connected idle time may incur charges. Verify each vendor's current calculator and healthcare minimum before signing.</p><h3 id="should-a-telemedicine-app-record-consultations">Should a telemedicine app record consultations?</h3><p>A telemedicine app should record only when a defined clinical, legal, or operational need justifies the extra PHI risk. Recording should never be an unquestioned default.</p><p>Document consent, access, encryption, storage, retention, deletion, export, incident handling, and audits. Confirm that the recording mode remains inside the signed BAA scope.</p><h3 id="how-do-i-test-a-telemedicine-video-api">How do I test a telemedicine video API?</h3><p>Test with representative patient devices, browsers, accessibility tools, weak networks, hospital firewalls, permission failures, network handoffs, Bluetooth audio, reconnection, and audio-only fallback.</p><p>Measure join success, time to first media, dropout recovery, support contacts, clinician task completion, and cost. Never use real PHI in an unapproved proof of concept.</p>]]></content:encoded></item><item><title><![CDATA[What is a Virtual Classroom API?]]></title><description><![CDATA[Learn how a virtual classroom API connects live media with LMS workflows. Compare modes, plan security, accessibility, cost, and scale.  
]]></description><link>https://www.videosdk.live/blog/virtual-classroom-api</link><guid isPermaLink="false">6a7c3662b3240feb748c9615</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 12 Aug 2026 13:19:19 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-12--2026--06_06_46-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>A virtual classroom API is a programmable interface for adding live teaching features, including video, audio, chat, screen sharing, moderation, recording, and whiteboards, to an education product. VideoSDK provides the real-time communication layer for custom web and mobile classrooms, while your product remains responsible for courses, enrolment, assessments, and academic records.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-12--2026--06_06_46-PM.png" alt="What is a Virtual Classroom API?"/><p>Building a virtual classroom is not the same as embedding a meeting link. A useful learning experience must preserve teacher control, learner identity, collaboration, continuity on weak connections, and a clear relationship to the <a href="https://www.videosdk.live/solutions/edtech" rel="noreferrer">learning platform</a>.</p><p>For developers, a virtual classroom API is the layer that carries the live lesson. VideoSDK can supply rooms, real-time media, collaboration, recording, streaming, and server-side controls across web and mobile SDKs. The architecture still needs an LMS or education application to own schedules, rosters, grades, consent, and reporting.</p><h2 id="what-is-a-virtual-classroom-api">What Is a Virtual Classroom API?</h2><p>A virtual classroom API is defined as a set of interfaces that embeds synchronous teaching capabilities into an existing application. A virtual classroom API works by coordinating participants, media tracks, classroom controls, and post-session outputs without requiring the education product to build its own real-time media infrastructure.</p><p>That distinction matters. Google Classroom API, for example, manages courses, rosters, coursework, submissions, and grades. A live classroom media API runs the synchronous session itself. Many education products need both, connected by an integration that maps authenticated users and scheduled classes to live rooms. <a href="https://developers.google.com/workspace/classroom/reference/rest">Google’s Classroom API documentation</a> describes its scope around classes, rosters, invitations, coursework, and related resources.</p><p>VideoSDK is a strong fit when a product needs a branded, embedded classroom rather than a separate conferencing destination. Its current React documentation lists conference calling, collaboration, recording, live streaming, transcription, security, and large-room guidance, alongside SDKs for JavaScript, React Native, Android, iOS, Flutter, Unity, Python, C++, and IoT. <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK’s React quickstart</a> was updated on 10 August 2026.</p><h2 id="how-a-virtual-classroom-api-works">How a Virtual Classroom API Works</h2><p>A dependable virtual classroom separates learning workflow from live-media delivery.</p><p>The education product authenticates the teacher and learners, checks enrolment, and decides who may enter a scheduled session. It then creates or selects a room, gives each participant only the access they need, and stores the events that matter to the academic workflow.</p><p>The real-time layer moves audio, video, screen share, chat, and collaboration events during the class. Afterward, recordings, transcripts, attendance evidence, and moderation events can flow back to the product's reporting and retention systems.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Layer</th>
<th>Owns</th>
<th>Example responsibilities</th>
</tr>
</thead>
<tbody>
<tr>
<td>Education product or LMS</td>
<td>Academic workflow</td>
<td>Courses, rosters, schedules, assignments, grades, and institutional policies</td>
</tr>
<tr>
<td>Classroom management service</td>
<td>Session rules</td>
<td>Teacher and learner roles, waiting workflow, attendance rules, hand raising, and moderation</td>
</tr>
<tr>
<td>VideoSDK real-time layer</td>
<td>Live interaction</td>
<td>Rooms, audio, video, screen sharing, collaboration, recording, and streaming</td>
</tr>
<tr>
<td>Post-session services</td>
<td>Evidence and follow-up</td>
<td>Recording access, transcripts, retention, analytics, and learner notifications</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>This four-layer model prevents a common design mistake: asking an RTC provider to behave like a complete LMS, or asking an LMS API to run low-latency media. VideoSDK provides the live interaction layer, not the full academic system of record.</p><p>The web standard beneath many browser-based implementations is <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a>. The <a href="https://www.w3.org/TR/webrtc/" rel="noreferrer">W3C WebRTC</a> Recommendation defines browser APIs for real-time communication, but a production classroom also needs room orchestration, media routing, network recovery, operational monitoring, and consistent clients across devices. That is where a managed SDK is usually more practical than building directly on raw browser primitives.</p><h2 id="choose-the-right-classroom-mode">Choose the Right Classroom Mode</h2><p>The right virtual classroom mode follows participation, not a generic idea of scale.</p><p>Use conference-style rooms when learners need to speak, show work, or join small-group discussion. Use interactive live streaming when a few hosts teach a larger audience that can participate through chat, polls, Q&amp;A, or controlled promotion to speaking roles. Use conventional one-way streaming when audience interaction can tolerate delay. Use a prebuilt interface when speed matters more than a differentiated user experience.</p>
<!--kg-card-begin: html-->
<table>
  <thead>
    <tr>
      <th>Teaching scenario</th>
      <th>Recommended approach</th>
      <th>Why it fits</th>
      <th>Important trade-off</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>One-to-one tutoring</td>
      <td>Conference room</td>
      <td>Both people need natural two-way audio and video</td>
      <td>Build scheduling and tutoring workflow in the product</td>
    </tr>
    <tr>
      <td>Seminar or small class</td>
      <td>Conference room</td>
      <td>Learners can discuss, share screens, and collaborate</td>
      <td>Gallery layout and moderation need careful design</td>
    </tr>
    <tr>
      <td>Large lecture with questions</td>
      <td>Interactive live streaming</td>
      <td>Hosts retain control while learners can engage and be promoted</td>
      <td>Design a clear path for audience participation</td>
    </tr>
    <tr>
      <td>Passive broadcast</td>
      <td>One-way streaming</td>
      <td>Best when the audience does not need immediate interaction</td>
      <td>Delayed chat and Q&amp;A change the teaching experience</td>
    </tr>
    <tr>
      <td>Pilot or standardised classes</td>
      <td>VideoSDK Prebuilt</td>
      <td>Faster route to a working room interface</td>
      <td>Less control over the exact product experience</td>
    </tr>
    <tr>
      <td>Branded EdTech platform</td>
      <td>VideoSDK custom SDK</td>
      <td>Full control over classroom UX and learning workflow integration</td>
      <td>Requires product and engineering investment</td>
    </tr>
  </tbody>
</table>
<!--kg-card-end: html-->
<p>VideoSDK's documentation offers both conference and interactive live streaming quickstarts, while its <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Prebuilt UI kit guide</a> gives teams a faster starting path. Choose the smallest mode that satisfies the learning design, then test it with actual teachers and learners.</p><h2 id="features-that-make-classes-feel-like-classes">Features That Make Classes Feel Like Classes</h2><p>VideoSDK classrooms work best when live media supports the teaching flow rather than competing with it.</p><p>Video and audio are the baseline. The higher-value design work starts with teacher controls, screen sharing, chat, Q&amp;A, whiteboards, polling, breakout activities, and a reliable way for learners to signal that they need help.</p><h3 id="teacher-led-controls">Teacher-led controls</h3><p>Teachers need to see who is present, mute or remove participants when appropriate, manage screen sharing, and control when a recording begins. A waiting or approval workflow is useful when a class must not allow direct entry.</p><p>Role design should live on the trusted server side. A student should not become a teacher because a browser-supplied label says so. Assign classroom permissions from the authenticated user and enrolment record, then issue narrowly scoped access for that room and session.</p><h3 id="collaboration-that-persists">Collaboration that persists</h3><p>Hand raises, polls, chat, and whiteboard actions become more useful when the product can preserve the events that matter. VideoSDK documents PubSub as a way to exchange real-time messages among meeting participants. <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/pubsub">Read the VideoSDK PubSub guide</a> when designing classroom signals and collaboration.</p><p>Do not treat a learner who connects for a few seconds as meaningfully present. Attendance should combine the scheduled roster, join and leave intervals, teacher decisions, and any institution-specific participation rule. The definition belongs to the education provider, not the video interface.</p><h3 id="recording-and-transcription">Recording and transcription</h3><p>Recordings and transcripts can support revision, absence recovery, and instructor review. They also create sensitive education records. VideoSDK documents recording and transcription capabilities, but the education provider must decide notice, consent, authorised viewers, retention period, deletion process, and how recordings affect assessment or safeguarding obligations.</p><p>For a practical next step, review <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/recording/Overview">VideoSDK recording options</a> and map each recording output to a documented policy before enabling it.</p><h2 id="how-videosdk-fits-an-edtech-architecture">How VideoSDK Fits an EdTech Architecture</h2><p>VideoSDK gives custom education products a dedicated real-time layer without replacing their LMS or core application.</p><p>Use VideoSDK conference rooms for classes where students are active participants. Use interactive live streaming for presenter-led sessions where a smaller set of hosts teach a larger audience. Its Prebuilt option can reduce time to a pilot, while the custom SDK route suits products that need their own layouts, engagement patterns, and academic workflow.</p><p>The VideoSDK React quickstart shows a room-based conference model with participant views, media controls, server-managed meeting creation, and a token requirement. That model maps cleanly to a classroom when your backend determines the user, role, room, and time window before the client joins. Start with the React conference <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">quickstart</a>.</p><p>There is a trade-off. A custom VideoSDK classroom gives you far more product control than an off-the-shelf classroom page, but it also means you own the experience around it: enrolment, identity, schedules, payments, support, data governance, and the pedagogical workflow. That is the right trade for differentiated EdTech products, not an automatic choice for every tutoring business.</p><h2 id="build-for-low-bandwidth-and-recovery">Build for Low Bandwidth and Recovery</h2><p>Low-bandwidth design is a core virtual classroom requirement, not an edge case.</p><p>Students may join from mobile networks, shared household connections, campus networks, or restrictive firewalls. A class should preserve audio first, reduce video pressure when needed, avoid rendering every remote camera at once, expose connection state, and retain chat or lesson actions during reconnection.</p><p>Design the classroom for graceful degradation:</p><ul><li>Let students join with audio only when video is unreliable.</li><li>Prioritise the teacher's screen share and audio over non-essential learner video.</li><li>Paginate large participant grids and pause video that is not visible.</li><li>Give learners a clear reconnecting state, rather than leaving them unsure whether they are still in class.</li><li>Preserve non-media learning actions, such as a raised hand or poll response, across a reconnect where possible.</li><li>Test real school firewalls and low-bandwidth conditions before rollout.</li></ul><p>Production readiness also means secure contexts, pre-call device checks, backend-issued access, and observability. A working classroom on a developer laptop is not proof that it will work on a learner's device at the start of a timed exam-prep session.</p><h2 id="accessibility-is-a-product-requirement">Accessibility Is a Product Requirement</h2><p>Accessible virtual classrooms make the learning experience better for every participant, not only those who disclose a disability.</p><p>Start with keyboard-operable controls, visible focus, clear labels, predictable layout changes, readable contrast, and captions. The <a href="https://www.w3.org/TR/WCAG22/">W3C WCAG 2.2 Recommendation</a> includes a Level AA success criterion for captions on live audio in synchronised media. Caption quality, speaker identification, timing, and a way to correct or supplement automated transcripts still need product attention.</p><p>Test with people using keyboard navigation, screen readers, captions, mobile devices, low vision settings, and reduced motion preferences. Also test the teaching flow, not just isolated controls. A learner should be able to find the join button, understand who is speaking, raise a hand, read a shared resource, and recover after a dropped connection.</p><p>Accessibility does not arrive automatically with a video SDK. It is an end-to-end responsibility shared by the provider, product team, and institution.</p><h2 id="security-and-privacy-checklist">Security and Privacy Checklist</h2><p>A secure virtual classroom applies least privilege from sign-in through playback.</p><ul><li>Authenticate every teacher and learner through the education product before creating or joining a room.</li><li>Generate VideoSDK access tokens only on a trusted backend, never in a public client application.</li><li>Scope access to the smallest practical room, role, and lifetime.</li><li>Derive teaching privileges from verified enrolment or staff records.</li><li>Use HTTPS in production and test device permissions before joining.</li><li>Apply a waiting or approval path when direct entry is inappropriate.</li><li>Tell participants before recording, and publish a clear retention and deletion route.</li><li>Restrict recordings, transcripts, and participant metadata by role.</li><li>Log moderator actions, recording changes, removals, and failed access attempts.</li><li>Review child-safety, education-record, privacy, and data-residency obligations with qualified counsel.</li></ul><p>Do not infer that the complete education product is compliant because one infrastructure supplier documents a security capability. Compliance depends on the whole system, contracts, configuration, user behaviour, and the laws that apply to the institution.</p><h2 id="evaluate-cost-without-guesswork">Evaluate Cost Without Guesswork</h2><p>Virtual classroom API cost is a workload calculation, not a single sticker price.</p><p>Start with a representative month: number of classes, average duration, average participants, concurrent rooms, media mode, recording hours, storage, transcription, streaming, support, and any regional or contractual requirements. Then compare providers using the same scenario.</p><p><strong>Monthly classroom workload = classes × average duration × average participants.</strong></p><p>For example, a programme with 120 classes per month, each lasting 60 minutes with 25 learners connected, produces 180,000 participant-minutes before recording, storage, transcription, or streaming add-ons. This is not a price estimate. It is the usage baseline needed for a meaningful quote.</p><p>Verify current VideoSDK pricing and plan limits directly on the <a href="https://www.videosdk.live/pricing">VideoSDK pricing page</a> before publication or procurement. Pricing, feature availability, included usage, and limits change faster than architecture principles.</p><h2 id="when-to-use-videosdk-prebuilt-or-another-approach">When to Use VideoSDK, Prebuilt, or Another Approach</h2><p>The best virtual classroom architecture depends on how much product differentiation and infrastructure ownership your team needs.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Approach</th>
<th>Best for</th>
<th>Main advantage</th>
<th>Main limitation</th>
</tr>
</thead>
<tbody>
<tr>
<td>Raw WebRTC</td>
<td>Specialist RTC teams</td>
<td>Deep protocol control</td>
<td>You own signalling, media infrastructure, scaling, recording, and multi-platform delivery</td>
</tr>
<tr>
<td>VideoSDK custom SDK</td>
<td>Branded education products</td>
<td>Custom UX with managed real-time infrastructure</td>
<td>You still build the academic workflow and classroom experience</td>
</tr>
<tr>
<td>VideoSDK Prebuilt</td>
<td>Pilots and conventional classes</td>
<td>Faster interface delivery</td>
<td>Less differentiated UX than a custom implementation</td>
</tr>
<tr>
<td>Vertical classroom SaaS</td>
<td>Standard tutoring operations</td>
<td>Teaching workflows may be bundled</td>
<td>Product and integration flexibility can be constrained</td>
</tr>
<tr>
<td>LMS plus VideoSDK</td>
<td>Established learning platforms</td>
<td>Keeps academic records and real-time media in specialised layers</td>
<td>Identity, data flow, and reporting still need deliberate integration</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Choose VideoSDK when live communication must sit inside your own web or mobile product, and your team needs control over the classroom experience. </p><p>Choose a vertical classroom product when bundled scheduling, course commerce, templates, and teaching operations matter more than custom behaviour. </p><p>Choose raw WebRTC only when the organisation has the expertise and business reason to own a much larger part of the stack.</p><h2 id="virtual-classroom-api-glossary">Virtual Classroom API Glossary</h2><blockquote><strong>Room:</strong> A VideoSDK room is the real-time space participants join with a room identifier and authorised access.</blockquote><blockquote><strong>Participant:</strong> A participant is an authenticated teacher, learner, moderator, or other user connected to a room with associated media and session events.</blockquote><blockquote><strong>Media track:</strong> A media track carries one audio or video source, such as a microphone, camera, screen share, or processed video source.</blockquote><blockquote><strong>Meeting token:</strong> A meeting token is a signed, time-limited credential that grants scoped access to a VideoSDK room. It should be issued by a trusted backend.</blockquote><blockquote><strong>Interactive live streaming:</strong> VideoSDK's low-latency streaming mode supports a smaller group of hosts while viewers can interact or be promoted into speaking roles.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>A virtual classroom API adds live teaching capabilities, while an LMS or education product remains responsible for courses, enrolment, assessment, and academic records.</li><li>VideoSDK provides the real-time communication layer for custom rooms, media, collaboration, recording, transcription, and streaming across web and mobile platforms.</li><li>Conference rooms suit discussion-led classes, while interactive live streaming suits presenter-led lessons with a larger audience.</li><li>Low-bandwidth recovery, scoped access, captions, consent, and recording retention are production requirements, not later enhancements.</li><li>Evaluate a virtual classroom API using real participant-minute workload, add-ons, concurrency, support, region, and product-control requirements.</li></ul><h2 id="build-the-classroom-around-learning">Build the Classroom Around Learning</h2><p>A virtual classroom API succeeds when it supports teaching workflow, protects student data, and stays usable on imperfect networks. VideoSDK gives custom education products a practical real-time foundation for rooms, audio and video, collaboration, recording, and streaming, while the education product retains academic logic.</p><p>Review the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React quickstart</a>, explore the <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Prebuilt UI kit</a>, or <a href="https://app.videosdk.live/login">create a VideoSDK developer account</a> to evaluate the architecture. What kind of virtual classroom are you building?</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-a-virtual-classroom-api-1">What is a virtual classroom API?</h3><p>A virtual classroom API is a programmable interface that embeds live teaching features into an education product. It commonly includes video, audio, chat, screen sharing, moderation, recording, and whiteboards, while the education application retains responsibility for its learning workflow.</p><h3 id="how-is-a-virtual-classroom-api-different-from-google-classroom-api">How is a virtual classroom API different from Google Classroom API?</h3><p>A virtual classroom API runs synchronous live lessons. Google Classroom API manages classes, rosters, coursework, submissions, and grades in Google Workspace for Education, so it can complement rather than replace a real-time classroom layer.</p><h3 id="can-videosdk-be-used-to-build-a-virtual-classroom">Can VideoSDK be used to build a virtual classroom?</h3><p>Yes, VideoSDK can provide the real-time media and collaboration layer for a virtual classroom. The product team still needs to build or integrate courses, scheduling, enrolment, assessments, permissions, reporting, and institutional workflows.</p><h3 id="which-videosdk-mode-should-an-edtech-app-use">Which VideoSDK mode should an EdTech app use?</h3><p>Use VideoSDK conference rooms when learners need to speak and collaborate. Use interactive live streaming for presenter-led classes with a larger audience, and consider Prebuilt when a standard classroom interface is more valuable than a fully custom one.</p><h3 id="how-should-a-virtual-classroom-handle-slow-internet">How should a virtual classroom handle slow internet?</h3><p>A virtual classroom should prioritise audio, reduce non-essential video, avoid rendering every participant at once, surface connection status, and preserve essential learning actions through reconnection. Test these behaviours on constrained networks before launch.</p><h3 id="does-videosdk-include-classroom-recording">Does VideoSDK include classroom recording?</h3><p>VideoSDK documents recording options for its real-time sessions. The education provider remains responsible for participant notice, consent, lawful use, access control, retention, and deletion of resulting recordings and transcripts.</p><h3 id="how-much-does-a-virtual-classroom-api-cost">How much does a virtual classroom API cost?</h3><p>Virtual classroom API cost depends on participant-minutes, media mode, recording, storage, transcription, streaming, concurrency, support, and volume terms. Compare vendors using the same realistic class schedule and confirm current rates directly with the provider.</p>]]></content:encoded></item><item><title><![CDATA[What is End-to-End Encryption Video Call?]]></title><description><![CDATA[Learn how an end-to-end encryption video call protects WebRTC media, works with an SFU, affects recording and transcription, and can be implemented using VideoSDK.]]></description><link>https://www.videosdk.live/blog/end-to-end-encryption-video-calls</link><guid isPermaLink="false">6a70a259b3240feb748c9351</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 11 Aug 2026 13:56:51 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-4--2026--05_24_47-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>An end-to-end encryption video call encrypts media on participant devices, so intermediaries route ciphertext without holding the decryption key. VideoSDK supports client-side, room-level E2EE with one shared key for audio, video, and screen-share tracks. Recording and transcription remain unavailable while E2EE is enabled.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-4--2026--05_24_47-PM.png" alt="What is End-to-End Encryption Video Call?"/><p>An end-to-end encryption video call solves a precise trust problem. Your real-time communication provider should carry media without being able to watch or hear it.</p><p>VideoSDK implements this boundary by encrypting media on participant clients before its infrastructure routes the call. Only clients holding the shared room key can recover protected media.</p><p>This guide explains the <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> security boundary, shared and per-sender key architectures, a React implementation, performance considerations, feature trade-offs, and a production checklist.</p><h2 id="what-is-an-end-to-end-encryption-video-call">What Is an End-to-End Encryption Video Call?</h2><p>A true E2EE video call keeps usable media keys only on authorised participant devices.</p><p>An <strong>end-to-end encryption video call is defined as</strong> a real-time call whose media is encrypted by the sender and decrypted only by authorised receivers. Relays, Selective Forwarding Units (SFUs), network operators, and the calling provider can route encrypted packets without recovering their audio or video content.</p><p>An <strong>end-to-end encryption video call works by</strong> encrypting encoded audio and video frames before network transmission. Recipient clients authenticate and decrypt those frames before decoding and playback.</p><p>VideoSDK applies E2EE at room level with one shared key for the room's media tracks. Its <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/security/E2EE">React E2EE documentation</a> states that the application owns key generation, management, and distribution.</p><p>This boundary matters because E2EE protects call content, not every associated data point. The <a href="https://csrc.nist.gov/glossary/term/end_to_end_encryption">NIST definition of end-to-end encryption</a> notes that routing information can remain visible while communication data stays encrypted.</p><p>E2EE also cannot protect an already compromised endpoint. Malware, screen-capture software, a malicious participant, or an unlocked device can access media after legitimate decryption.</p><h2 id="how-an-end-to-end-encryption-video-call-works">How an End-to-End Encryption Video Call Works</h2><p>An E2EE call adds a client-controlled media-encryption layer above WebRTC's encrypted transport.</p><ol><li><strong>Authorise the participant.</strong> Your application authenticates the user, checks room membership, and issues a short-lived VideoSDK meeting token scoped to the room and participant.</li><li><strong>Distribute the media key securely.</strong> Your backend creates or retrieves the room's E2EE key and returns it only after a separate authorisation check.</li><li><strong>Encrypt media on the sender.</strong> The client captures and encodes microphone, camera, or screen-share data, then encrypts each encoded frame before transmission.</li><li><strong>Route ciphertext through the SFU.</strong> VideoSDK infrastructure forwards encrypted media to subscribed participants without receiving the application's room key.</li><li><strong>Decrypt on authorised receivers.</strong> Each recipient authenticates and decrypts frames with the room key, then decodes and renders the media.</li><li><strong>Monitor encryption state.</strong> The application watches participant encryption events and blocks protected media when a key is missing, invalid, or unusable.</li></ol><p>The <a href="https://www.rfc-editor.org/rfc/rfc9605.html">IETF SFrame standard, RFC 9605</a>, describes this two-layer pattern for multiparty media. An <a href="https://www.videosdk.live/blog/sfu-vs-mcu-vs-mesh-webrtc" rel="noreferrer">SFU</a> can read routing metadata while remaining unable to access media content.</p><p>SFrame is a useful standards model, not a claim about VideoSDK's internal cipher format. VideoSDK's public React guide documents the supported key-provider API and security boundary.</p><p>The practical result is a scalable multiparty route where the SFU forwards streams without receiving usable media plaintext.</p><h2 id="end-to-end-encryption-video-call-vs-webrtc-security">End-to-End Encryption Video Call vs WebRTC Security</h2><p>WebRTC encrypts media transport by default, but transport encryption does not always keep media unreadable to an SFU.</p><p>The <a href="https://www.rfc-editor.org/rfc/rfc8827.html">IETF WebRTC Security Architecture, RFC 8827</a>, requires secure real-time media. Its requirement is direct: “Media traffic MUST NOT be sent over plain RTP.”</p><p>In a direct peer connection, encrypted transport can extend from one participant to the other. In a multiparty SFU topology, clients usually establish separate secure transport legs with the SFU.</p><p>Application-layer E2EE encrypts the encoded frame before those transport legs. The SFU receives information needed for forwarding, but not the key needed to recover media.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Security question</th>
<th>WebRTC transport encryption</th>
<th>Application-layer E2EE</th>
</tr>
</thead>
<tbody>
<tr>
<td>Where is media encrypted?</td>
<td>Across each secure transport leg</td>
<td>On the sender before intermediaries receive media</td>
</tr>
<tr>
<td>Can the network read media?</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>Can an SFU read media payloads?</td>
<td>Potentially, if it terminates transport encryption</td>
<td>No, if it never receives the E2EE key</td>
</tr>
<tr>
<td>Can routing metadata remain visible?</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td>Can server media processing work?</td>
<td>Usually yes</td>
<td>Only if a trusted processing endpoint receives a key</td>
</tr>
<tr>
<td>Who manages media keys?</td>
<td>WebRTC endpoints and transport protocols</td>
<td>The application controls E2EE key distribution</td>
</tr>
<tr>
<td>VideoSDK role</td>
<td>Provides secure real-time transport</td>
<td>Offers optional room-level media E2EE</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The critical question is not whether packets are encrypted. It is which systems hold a key that can decrypt the call's media.</p><h2 id="how-does-videosdk-handle-video-call-e2ee">How Does VideoSDK Handle Video Call E2EE?</h2><p>VideoSDK applies client-side E2EE to room media while leaving key ownership with your application.</p><p>According to the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/security/E2EE">VideoSDK E2EE guide</a>, one shared room key encrypts and decrypts media tracks. Participants without that key cannot access those tracks.</p><p>The guide also states that VideoSDK never stores, accesses, or transfers encryption keys. Your backend must create, authorise, deliver, expire, and replace room keys according to your threat model.</p><h3 id="supported-videosdk-sdks">Supported VideoSDK SDKs</h3><p>VideoSDK documents these minimum versions for E2EE support. They are minimum compatible versions, not recommendations to install an old release.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>SDK</th>
<th style="text-align:right">Minimum E2EE version</th>
</tr>
</thead>
<tbody>
<tr>
<td>React Native</td>
<td style="text-align:right">0.2.1</td>
</tr>
<tr>
<td>iOS</td>
<td style="text-align:right">2.2.2</td>
</tr>
<tr>
<td>Flutter</td>
<td style="text-align:right">2.1.0</td>
</tr>
<tr>
<td>React</td>
<td style="text-align:right">0.3.5</td>
</tr>
<tr>
<td>Android</td>
<td style="text-align:right">0.5.0</td>
</tr>
<tr>
<td>JavaScript</td>
<td style="text-align:right">0.2.6</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>This table was checked against VideoSDK's E2EE page on 11 August 2026. The page tracks React SDK version 1.x.x and was last updated on 10 July 2026.</p><p>Use the current supported release for your platform and repeat cross-device E2EE tests after every SDK upgrade.</p><h3 id="the-exact-protection-boundary">The Exact Protection Boundary</h3><p>VideoSDK E2EE covers media, including audio, video, and share tracks. Chat, metadata, API calls, and signalling data remain outside the E2EE boundary, although <a href="https://docs.videosdk.live/telephony/managing-calls/secure-sip" rel="noreferrer">TLS</a> protects them in transit.</p><p>Recording and transcription are not supported while VideoSDK E2EE is enabled. Those services require access to media that the documented E2EE model keeps unavailable to VideoSDK servers.</p><p>This is a credible privacy boundary, not a promise that every byte associated with a meeting becomes invisible.</p><h2 id="shared-key-vs-per-participant-key-encryption">Shared Key vs Per-Participant Key Encryption</h2><p>VideoSDK currently documents a shared room key, while per-sender keys represent a different and more complex key-management architecture.</p><p>The phrase <strong>per-participant key</strong> usually means each sender encrypts their outgoing media with a distinct sender key. Every authorised receiver then needs the active key for every sender it may decrypt.</p><p>That design can support granular membership changes, but it multiplies key delivery, rotation, recovery, and device-synchronisation work. It is not a simple security upgrade over a room key.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Decision factor</th>
<th>Shared room key</th>
<th>Per-sender or per-participant keys</th>
</tr>
</thead>
<tbody>
<tr>
<td>Key count</td>
<td>One active media key per room</td>
<td>One or more active keys per sender</td>
</tr>
<tr>
<td>Client setup</td>
<td>Lower complexity</td>
<td>Higher key-ring and rotation complexity</td>
</tr>
<tr>
<td>Removing a participant</td>
<td>Usually requires replacing the room key</td>
<td>Can support more granular sender-key changes</td>
</tr>
<tr>
<td>Large-room operations</td>
<td>Fewer secrets to distribute</td>
<td>More secrets and membership events to coordinate</td>
</tr>
<tr>
<td>Current VideoSDK React documentation</td>
<td>Supported through <code>setSharedKey()</code></td>
<td>Not documented as a selectable VideoSDK mode</td>
</tr>
<tr>
<td>Best fit</td>
<td>Trusted groups with strong room membership controls</td>
<td>Custom protocols needing granular sender isolation</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Use VideoSDK's documented shared-key model unless the selected SDK's current documentation says otherwise. If your threat model requires per-sender keys, verify product support with VideoSDK before designing around it.</p><p>Never describe an undocumented key architecture as an available configuration switch. Security documentation must match the code customers can actually run.</p><h2 id="webrtc-encoded-transforms-and-e2ee">WebRTC Encoded Transforms and E2EE</h2><p>WebRTC Encoded Transforms let browser applications modify encoded audio and video frames before they enter, or after they leave, the network pipeline.</p><p>The <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Using_Encoded_Transforms">MDN guide to WebRTC Encoded Transforms</a> describes <code>RTCRtpScriptTransform</code> workers attached to <code>RTCRtpSender.transform</code> and <code>RTCRtpReceiver.transform</code>. E2EE is one intended use case.</p><p>MDN marks the API as newly baseline across current browsers since October 2025, while warning that older browsers and devices may not support it.</p><p>For VideoSDK React, use the documented <code>ExternalE2EEKeyProvider</code> integration instead of writing a custom transform worker. Test the final SDK and browser combination because platform support can differ.</p><p>Do not claim that VideoSDK uses a particular cipher or standards profile unless the selected SDK's current documentation states it.</p><h2 id="secure-key-management-for-multiparty-calls">Secure Key Management for Multiparty Calls</h2><p>The cryptography is only as trustworthy as your key-distribution and participant-authorisation path.</p><p>VideoSDK's shared-key model keeps client integration practical. It also means anyone holding the room key can decrypt media, even when their meeting token has narrower permissions.</p><p>Treat the meeting token and E2EE key as separate secrets. Possessing either secret should not reveal the other without an application-level identity and membership check.</p><p>Generate an ephemeral key for each sensitive room or session. Bind delivery to the authenticated user, room, participant, device policy, and current membership state.</p><p>Store server-side keys in a KMS-backed or equivalently protected secret store. Keep client keys in memory where the platform permits, and redact them from observability systems.</p><p>Plan revocation before launch. Stop returning the key when access is removed, then use a fresh key for later sessions.</p><p>VideoSDK's React guide does not document a portable mid-call rotation workflow. Verify current rotation behaviour across every selected SDK before promising immediate rekeying after a participant leaves.</p><p>High-risk products can add an out-of-band room code, verified participant directory, or trusted-device flow. These controls bind a valid key to the intended people.</p><p>Strong frame encryption cannot repair weak identity, authorisation, logging, or secret-storage practices.</p><h2 id="does-e2ee-affect-video-call-latency">Does E2EE Affect Video Call Latency?</h2><p>E2EE adds client-side processing and some frame overhead, but no universal latency number applies across devices, browsers, codecs, and room layouts.</p><p>RFC 9605 includes an illustrative two-person SFrame calculation with about 1% total bandwidth overhead. That example is not a VideoSDK benchmark and does not measure client CPU or end-to-end delay.</p><p>Modern laptops may show little visible impact, while older phones can struggle with encryption, decoding, effects, and multiple subscribed streams at the same time.</p><p>Measure E2EE on your real device matrix. Track join time, glass-to-glass latency, frames per second, CPU, thermal throttling, battery drain, packet loss, and recovery after network changes.</p><p>Run each test with E2EE enabled and disabled under identical conditions. Publish your own results only after recording hardware, browser, SDK version, codec, participant count, and network profile.</p><p>The honest performance answer is conditional: E2EE overhead may be small, but production acceptance needs device-level evidence.</p><h2 id="when-should-you-use-video-call-e2ee">When Should You Use Video Call E2EE?</h2><p>Use E2EE when keeping media unreadable to the RTC provider is a documented product requirement.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Product requirement</th>
<th>Recommended call mode</th>
<th>Reason</th>
</tr>
</thead>
<tbody>
<tr>
<td>Provider must not decrypt audio or video</td>
<td>VideoSDK E2EE</td>
<td>The application controls the shared media key</td>
</tr>
<tr>
<td>Cloud recording or transcription is mandatory</td>
<td>Standard encrypted VideoSDK room</td>
<td>Server processing requires media access</td>
</tr>
<tr>
<td>Sensitive session with no server processing</td>
<td>VideoSDK E2EE</td>
<td>Media confidentiality outweighs processing features</td>
</tr>
<tr>
<td>SIP bridge or server media bot is essential</td>
<td>Standard encryption or a redesigned trust model</td>
<td>The gateway or bot becomes a trusted endpoint</td>
</tr>
<tr>
<td>Unknown endpoint security</td>
<td>E2EE plus endpoint controls</td>
<td>Encryption cannot protect a compromised device</td>
</tr>
<tr>
<td>Granular per-sender key isolation is mandatory</td>
<td>Verify custom architecture or current SDK support</td>
<td>VideoSDK documents a shared room key today</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>An end-to-end encryption video call fits telehealth, legal, financial, safeguarding, executive, and research conversations when provider-blind media is required.</p><p>Standard transport encryption fits better when recording, transcription, moderation, media conversion, SIP bridging, or automated analysis is essential.</p><p>Never downgrade silently. Ask for informed consent, display the active mode, and record the policy decision without logging keys or decrypted media.</p><p>E2EE is also not a compliance certificate. <a href="https://www.hhs.gov/hipaa/for-professionals/privacy/guidance/hipaa-audio-telehealth/index.html">HHS telehealth guidance</a> places encryption inside broader risk management, access control, endpoint, recording, and privacy obligations.</p><p>Choose the call mode from a threat model, required features, and applicable legal advice rather than a generic “secure” label.</p><h2 id="videosdk-e2ee-features-and-trade-offs">VideoSDK E2EE Features and Trade-offs</h2><p>VideoSDK E2EE protects media content by giving up server features that require media plaintext.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Capability</th>
<th>With VideoSDK E2EE</th>
<th>Engineering implication</th>
</tr>
</thead>
<tbody>
<tr>
<td>Audio, video, and screen-share media</td>
<td>E2EE supported</td>
<td>Only clients with the shared key can decrypt</td>
</tr>
<tr>
<td>SFU media routing</td>
<td>Supported</td>
<td>VideoSDK routes encrypted media without the room key</td>
</tr>
<tr>
<td>Chat and metadata</td>
<td>TLS, not E2EE</td>
<td>Do not place media secrets in chat or metadata</td>
</tr>
<tr>
<td>API calls and signalling</td>
<td>TLS, not E2EE</td>
<td>Keep server authentication and authorisation controls</td>
</tr>
<tr>
<td>Server-side recording</td>
<td>Not supported</td>
<td>Use another policy or an explicitly trusted recorder</td>
</tr>
<tr>
<td>Server-side transcription</td>
<td>Not supported</td>
<td>Do not promise server captions or summaries in E2EE rooms</td>
</tr>
<tr>
<td>Key lifecycle</td>
<td>Application controlled</td>
<td>Your team owns delivery, replacement, and incident response</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The trade-off follows from the trust model. A server cannot remain unable to decrypt media while simultaneously processing that media for recording or transcription.</p><p>Some products need both workflows. Use clearly labelled policies: a private E2EE mode for confidential sessions and a processing-enabled mode for consented recording or transcription.</p><h2 id="end-to-end-encryption-video-call-security-checklist">End-to-End Encryption Video Call Security Checklist</h2><p>A production E2EE launch needs verifiable controls across identity, keys, media, endpoints, operations, and user experience.</p><ol><li><strong>Write the threat model.</strong> State whether you protect against network observers, the RTC provider, compromised accounts, malicious participants, or stolen devices.</li><li><strong>Scope meeting tokens.</strong> Use short expiry, room ID, participant ID, the <code>rtc</code> role, and only the required permissions.</li><li><strong>Separate tokens and keys.</strong> Never treat a meeting token as an E2EE secret or place the room key in a public URL.</li><li><strong>Authorise key delivery.</strong> Check identity, room membership, device policy, and current access before returning the key.</li><li><strong>Protect key storage.</strong> Use an encrypted secret store on the server and memory-first handling on clients where practical.</li><li><strong>Fail closed.</strong> Block protected media when the key is missing, invalid, or cannot be verified.</li><li><strong>Expose security state.</strong> Show whether E2EE is active and surface participant encryption failures accessibly.</li><li><strong>Test membership changes.</strong> Cover late joins, reconnects, removals, expired tokens, restored tabs, and second devices.</li><li><strong>Review feature conflicts.</strong> Confirm the product does not depend on recording or transcription inside E2EE rooms.</li><li><strong>Secure endpoints.</strong> Apply updates, device locks, least privilege, log redaction, malware defence, and appropriate screen-capture rules.</li><li><strong>Log safely.</strong> Audit access decisions and state transitions without recording tokens, keys, media, or decrypted frames.</li><li><strong>Retest every release.</strong> Run correct-key, wrong-key, missing-key, removal, reconnect, and cross-platform compatibility cases.</li></ol><p>This checklist creates evidence that the deployed system matches the words “end-to-end encrypted” instead of relying on a configuration flag.</p><h2 id="telehealth-example-without-false-compliance-claims">Telehealth Example Without False Compliance Claims</h2><p>A fictional telehealth product shows why security mode and feature policy must be designed together.</p><p>Imagine CareBridge, an application using VideoSDK React for remote consultations. Its risk assessment requires VideoSDK infrastructure to remain unable to access consultation audio or video.</p><p>CareBridge authenticates the clinician and patient through its identity system. The backend checks appointment membership, issues participant-scoped meeting tokens, and releases an ephemeral room key.</p><p>The application displays encryption status during the call. If either participant reports <code>MissingKey</code>, <code>InvalidKey</code>, or a cryptor failure, CareBridge blocks protected media.</p><p>Because VideoSDK recording and transcription are unavailable with E2EE, CareBridge hides those controls. A future consented transcript would require a separate processing-enabled policy and another risk assessment.</p><p>CareBridge still needs device security, access control, audit logs, privacy notices, retention rules, and suitable vendor agreements. E2EE reduces one risk class without completing compliance work.</p><p>The design rule is conditional: choose E2EE when media confidentiality outranks server processing, then make that choice visible throughout the product.</p><h2 id="definitions">Definitions </h2><blockquote><strong>End-to-end encryption (E2EE):</strong> Media protection in which authorised endpoint devices hold decryption keys while intermediaries route ciphertext without reading the content.</blockquote><blockquote><strong>DTLS-SRTP:</strong> The WebRTC security combination that establishes keys and protects real-time media across a transport connection.</blockquote><blockquote><strong>Selective Forwarding Unit (SFU):</strong> A media router that receives participant streams and forwards selected streams. With E2EE, it routes encrypted payloads.</blockquote><blockquote><strong>Meeting token:</strong> A server-generated JWT that authorises a participant to access a VideoSDK room. It is not the room's E2EE key.</blockquote><blockquote><strong>Shared room key:</strong> The client-held secret used by authorised VideoSDK participants to encrypt and decrypt media tracks in one room.</blockquote><blockquote><strong>WebRTC Encoded Transform:</strong> A browser API that lets applications process encoded audio or video frames within sender and receiver pipelines.</blockquote><h2 id="key-takeaways-for-video-call-security">Key Takeaways for Video Call Security</h2><p>The right security mode depends on who must remain unable to decrypt media and which processing features your product needs.</p><ul><li>An end-to-end encryption video call encrypts media on participant devices, allowing an SFU to route packets without the application's media key.</li><li>WebRTC mandates encrypted transport, but multiparty calls need a separate E2EE layer when the SFU must remain unable to read media.</li><li>VideoSDK documents room-level E2EE with one shared key across React Native, iOS, Flutter, React, Android, and JavaScript SDKs.</li><li>VideoSDK leaves key generation and distribution to the application, so authentication, secret storage, and failure handling remain your responsibility.</li><li>Recording and transcription are unavailable during VideoSDK E2EE sessions, while chat, metadata, API calls, and signalling remain TLS-protected but outside E2EE.</li><li>E2EE reduces media-access risk without replacing endpoint security, participant verification, audit controls, risk analysis, or legal compliance work.</li></ul><p>The most defensible product exposes these boundaries instead of hiding them behind one lock icon.</p><h2 id="sources-and-related-videosdk-guides">Sources and Related VideoSDK Guides</h2><p>Use current product documentation and primary standards when reviewing an encrypted calling design.</p><ul><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/security/E2EE">VideoSDK E2EE setup for React</a> documents the room key, React API, state events, supported SDK minimums, and feature limitations.</li><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token">VideoSDK authentication and tokens</a> documents token signing, scope, roles, permissions, and expiry.</li><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React quickstart</a> provides the base meeting flow used before E2EE configuration.</li><li><a href="https://www.videosdk.live/blog/what-is-end-to-end-encryption-e2ee">VideoSDK's general E2EE explainer</a> covers encryption beyond the video-call implementation focus of this guide.</li><li><a href="https://www.rfc-editor.org/rfc/rfc8827.html">IETF RFC 8827</a> defines the WebRTC security architecture.</li><li><a href="https://www.rfc-editor.org/rfc/rfc9605.html">IETF RFC 9605</a> specifies SFrame for authenticated encryption of multiparty real-time media.</li><li><a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Using_Encoded_Transforms">MDN WebRTC Encoded Transforms</a> explains the browser transform pipeline and compatibility boundary.</li><li><a href="https://csrc.nist.gov/glossary/term/end_to_end_encryption">NIST E2EE glossary</a> distinguishes encrypted content from visible routing information.</li></ul><p>These sources also provide the best refresh path when SDK behaviour, browser support, or security guidance changes.</p><h2 id="conclusion">Conclusion</h2><p>An end-to-end encryption video call is valuable when your product must keep media unreadable to its RTC provider. VideoSDK provides the room-level client encryption path and observable E2EE states, while your application owns participant trust and key delivery. Start with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/security/E2EE">VideoSDK React E2EE guide</a>, then <a href="https://app.videosdk.live/login">create a VideoSDK account</a> to test the flow. What kind of protected video call are you building?</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="are-all-webrtc-video-calls-end-to-end-encrypted">Are all WebRTC video calls end-to-end encrypted?</h3><p>No, not every WebRTC video call is end-to-end encrypted against the service provider. WebRTC mandates encrypted transport, but an SFU can terminate transport encryption unless clients add a separate media E2EE layer.</p><h3 id="does-videosdk-support-end-to-end-encryption">Does VideoSDK support end-to-end encryption?</h3><p>Yes, VideoSDK supports room-level media E2EE with a client-held shared key. The current documentation covers React Native, iOS, Flutter, React, Android, and JavaScript SDK minimum versions.</p><h3 id="can-videosdk-decrypt-e2ee-call-media">Can VideoSDK decrypt E2EE call media?</h3><p>No, VideoSDK cannot decrypt media when its documented E2EE setup is configured correctly. Encryption and decryption happen on participant clients, and VideoSDK says it never stores or accesses the room key.</p><h3 id="what-does-videosdk-e2ee-encrypt">What does VideoSDK E2EE encrypt?</h3><p>VideoSDK E2EE encrypts audio, video, and screen-share media tracks. Chat, metadata, API calls, and signalling remain outside E2EE, although TLS still protects those communications in transit.</p><h3 id="can-videosdk-record-an-e2ee-video-call">Can VideoSDK record an E2EE video call?</h3><p>No, VideoSDK's current documentation says recording and transcription are unavailable while E2EE is enabled. Server processing would require access to media that the server-blind model intentionally withholds.</p><h3 id="how-should-an-application-distribute-the-e2ee-key">How should an application distribute the E2EE key?</h3><p>An application should return the room key through an authenticated HTTPS endpoint after verifying identity and room membership. Avoid URLs, logs, analytics, client bundles, and unnecessary persistent storage.</p><h3 id="does-e2ee-make-a-video-app-hipaa-compliant">Does E2EE make a video app HIPAA compliant?</h3><p>No, E2EE alone does not make a video application HIPAA compliant. Regulated teams must also assess identity, access, endpoints, retention, vendor relationships, risk management, and other applicable safeguards.</p><h3 id="does-end-to-end-encryption-increase-video-call-latency">Does end-to-end encryption increase video call latency?</h3><p>E2EE adds per-frame client processing, but the effect varies by device, codec, browser, participant count, and network. Measure latency, CPU, battery, and frame rate on your supported device matrix.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 WebRTC APIs: Expert Reviewed & Ranked]]></title><description><![CDATA[Compare 10 WebRTC API platforms using a transparent, documentation-led rubric covering developer onboarding, client coverage, production media, control, and operations.]]></description><link>https://www.videosdk.live/blog/webrtc-api</link><guid isPermaLink="false">6a71e3a7b3240feb748c947c</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 10 Aug 2026 12:14:17 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/top-10-webrtc-apis-thumbnail-agora-centered.png" medium="image"/><content:encoded><![CDATA[<blockquote>Based on our documentation-led review, VideoSDK ranks first for teams needing managed RTC across many client platforms. LiveKit leads for open-source infrastructure control, while Agora suits specialised social and broadcast engagement. The ranking evaluates developer onboarding, client coverage, production media, customisation, and operations using a published 100-point rubric.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/top-10-webrtc-apis-thumbnail-agora-centered.png" alt="Top 10 WebRTC APIs: Expert Reviewed & Ranked"/><p>Choosing a WebRTC API involves far more than calling <code>RTCPeerConnection</code>. Production applications also need signalling, <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a> fallback, media routing, access control, recording, observability, and reliable recovery.</p><p>This guide compares those managed layers for teams building video calls, audio rooms, telehealth, classrooms, webinars, and live communities. It also explains when raw WebRTC remains sensible.</p><p>Every claim was checked against public documentation available on 10 August 2026. We excluded private SLA promises, vendor latency claims, and features that could not be verified publicly.</p><h3 id="what-is-a-webrtc-api">What Is a WebRTC API?</h3><p>A WebRTC API exposes real-time media and data primitives, or packages the infrastructure required to operate them in production.</p><p>A <strong>WebRTC API is defined as</strong> a programming interface for capturing media, negotiating connections, transporting encrypted audio, video, or data, and managing related session infrastructure.</p><p>WebRTC works by capturing camera or microphone tracks, exchanging session descriptions and ICE candidates through signalling, then selecting an available network path for encrypted media transport.</p><p>The <a href="https://www.w3.org/TR/webrtc/">W3C WebRTC specification</a> covers browser interfaces for sending and receiving "media and generic application data." <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API">MDN's WebRTC API reference</a> documents <code>RTCPeerConnection</code>, <code>MediaStream</code>, and <code>RTCDataChannel</code>.</p><p>Browser WebRTC does not define your signalling service, account model, multiparty media server, recording pipeline, moderation layer, or analytics dashboard. Those omissions explain why managed providers exist.</p><p>VideoSDK is a managed WebRTC API provider. It packages rooms, participants, tracks, meeting tokens, recording, and server controls across ten documented client targets and a <a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">real-time communication REST API</a>.</p><p>This article uses <strong>WebRTC API</strong> in that buyer-intent sense: an SDK and service platform that operates production RTC infrastructure on behalf of application teams.</p><h2 id="how-we-evaluated-each-webrtc-api">How We Evaluated Each WebRTC API</h2><p>This ranking scores documented product coverage and developer experience, not unverified latency or network-quality claims.</p><p>We reviewed official product pages, quickstarts, API references, client platform lists, release notes, deployment options, and production features available on 10 August 2026.</p><p>We did not create paid accounts, run packet-level benchmarks, inspect private support channels, or validate contractual SLAs. The scores represent editorial evaluation, not laboratory performance.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Criterion</th>
<th style="text-align:right">Weight</th>
<th>What earns a strong score</th>
</tr>
</thead>
<tbody>
<tr>
<td>Developer onboarding</td>
<td style="text-align:right">20</td>
<td>Clear quickstart, sample application, token flow, API reference, and prebuilt path</td>
</tr>
<tr>
<td>Client coverage</td>
<td style="text-align:right">20</td>
<td>Maintained web, mobile, desktop, game, device, or backend SDK options</td>
</tr>
<tr>
<td>Production media</td>
<td style="text-align:right">25</td>
<td>Managed SFU, TURN fallback, recording, streaming, adaptive quality, and recovery controls</td>
</tr>
<tr>
<td>Customisation and control</td>
<td style="text-align:right">20</td>
<td>Headless SDK, roles, permissions, raw tracks, custom UI, or self-hosting choice</td>
</tr>
<tr>
<td>Operations and extensions</td>
<td style="text-align:right">15</td>
<td>Analytics, webhooks, transcription, moderation, telephony, AI, and enterprise controls</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h3 id="full-editorial-scorecard">Full editorial scorecard</h3><p>The category scores make the method reusable. Change the weights to match your roadmap before accepting our ordering or any one-point difference.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Provider</th>
<th style="text-align:right">Onboarding /20</th>
<th style="text-align:right">Clients /20</th>
<th style="text-align:right">Media /25</th>
<th style="text-align:right">Subtotal /65</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td style="text-align:right">19</td>
<td style="text-align:right">20</td>
<td style="text-align:right">22</td>
<td style="text-align:right">61</td>
</tr>
<tr>
<td>LiveKit</td>
<td style="text-align:right">18</td>
<td style="text-align:right">19</td>
<td style="text-align:right">23</td>
<td style="text-align:right">60</td>
</tr>
<tr>
<td>Agora</td>
<td style="text-align:right">17</td>
<td style="text-align:right">18</td>
<td style="text-align:right">24</td>
<td style="text-align:right">59</td>
</tr>
<tr>
<td>Daily</td>
<td style="text-align:right">19</td>
<td style="text-align:right">14</td>
<td style="text-align:right">22</td>
<td style="text-align:right">55</td>
</tr>
<tr>
<td>Twilio Video</td>
<td style="text-align:right">17</td>
<td style="text-align:right">14</td>
<td style="text-align:right">23</td>
<td style="text-align:right">54</td>
</tr>
<tr>
<td>100ms</td>
<td style="text-align:right">18</td>
<td style="text-align:right">15</td>
<td style="text-align:right">22</td>
<td style="text-align:right">55</td>
</tr>
<tr>
<td>Stream Video</td>
<td style="text-align:right">18</td>
<td style="text-align:right">17</td>
<td style="text-align:right">21</td>
<td style="text-align:right">56</td>
</tr>
<tr>
<td>Cloudflare RealtimeKit</td>
<td style="text-align:right">17</td>
<td style="text-align:right">15</td>
<td style="text-align:right">21</td>
<td style="text-align:right">53</td>
</tr>
<tr>
<td>Vonage Video API</td>
<td style="text-align:right">16</td>
<td style="text-align:right">15</td>
<td style="text-align:right">21</td>
<td style="text-align:right">52</td>
</tr>
<tr>
<td>Amazon Chime SDK</td>
<td style="text-align:right">14</td>
<td style="text-align:right">14</td>
<td style="text-align:right">22</td>
<td style="text-align:right">50</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->

<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Provider</th>
<th style="text-align:right">Control /20</th>
<th style="text-align:right">Operations /15</th>
<th style="text-align:right">Total /100</th>
<th style="text-align:right">Rank</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td style="text-align:right">17</td>
<td style="text-align:right">15</td>
<td style="text-align:right">93</td>
<td style="text-align:right">1</td>
</tr>
<tr>
<td>LiveKit</td>
<td style="text-align:right">20</td>
<td style="text-align:right">12</td>
<td style="text-align:right">92</td>
<td style="text-align:right">2</td>
</tr>
<tr>
<td>Agora</td>
<td style="text-align:right">16</td>
<td style="text-align:right">14</td>
<td style="text-align:right">89</td>
<td style="text-align:right">3</td>
</tr>
<tr>
<td>Daily</td>
<td style="text-align:right">17</td>
<td style="text-align:right">15</td>
<td style="text-align:right">87</td>
<td style="text-align:right">4</td>
</tr>
<tr>
<td>Twilio Video</td>
<td style="text-align:right">17</td>
<td style="text-align:right">15</td>
<td style="text-align:right">86</td>
<td style="text-align:right">5</td>
</tr>
<tr>
<td>100ms</td>
<td style="text-align:right">18</td>
<td style="text-align:right">13</td>
<td style="text-align:right">86</td>
<td style="text-align:right">6</td>
</tr>
<tr>
<td>Stream Video</td>
<td style="text-align:right">16</td>
<td style="text-align:right">12</td>
<td style="text-align:right">84</td>
<td style="text-align:right">7</td>
</tr>
<tr>
<td>Cloudflare RealtimeKit</td>
<td style="text-align:right">18</td>
<td style="text-align:right">12</td>
<td style="text-align:right">83</td>
<td style="text-align:right">8</td>
</tr>
<tr>
<td>Vonage Video API</td>
<td style="text-align:right">16</td>
<td style="text-align:right">13</td>
<td style="text-align:right">81</td>
<td style="text-align:right">9</td>
</tr>
<tr>
<td>Amazon Chime SDK</td>
<td style="text-align:right">14</td>
<td style="text-align:right">14</td>
<td style="text-align:right">78</td>
<td style="text-align:right">10</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Twilio Video and 100ms tie at 86. Twilio ranks fifth because this rubric gives its mature media and operational tooling the tie-break, while 100ms offers stronger role-driven control.</p><p>A one-point difference represents preference within this rubric. It does not prove a measurable difference in call quality, uptime, regional performance, or support response.</p><h2 id="webrtc-api-ranking-at-a-glance">WebRTC API Ranking at a Glance</h2><p>VideoSDK leads for managed multi-platform breadth, while LiveKit leads when infrastructure ownership is the deciding requirement.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th style="text-align:right">Rank</th>
<th>WebRTC API</th>
<th style="text-align:right">Score</th>
<th>Best for</th>
<th>Main trade-off</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">1</td>
<td>VideoSDK</td>
<td style="text-align:right">93</td>
<td>Broad multi-platform RTC and interactive streaming</td>
<td>Managed service, not a self-hosted SFU</td>
</tr>
<tr>
<td style="text-align:right">2</td>
<td>LiveKit</td>
<td style="text-align:right">92</td>
<td>Open-source control with optional managed cloud</td>
<td>More infrastructure choices to own and configure</td>
</tr>
<tr>
<td style="text-align:right">3</td>
<td>Agora</td>
<td style="text-align:right">89</td>
<td>Global social, gaming, and interactive engagement</td>
<td>Large product surface increases evaluation work</td>
</tr>
<tr>
<td style="text-align:right">4</td>
<td>Daily</td>
<td style="text-align:right">87</td>
<td>Browser-first calls and fast embedded experiences</td>
<td>Narrower specialist-client coverage than leaders</td>
</tr>
<tr>
<td style="text-align:right">5</td>
<td>Twilio Video</td>
<td style="text-align:right">86</td>
<td>Customer engagement inside an established CPaaS stack</td>
<td>Web, iOS, and Android focus limits client breadth</td>
</tr>
<tr>
<td style="text-align:right">6</td>
<td>100ms</td>
<td style="text-align:right">86</td>
<td>Role-driven classrooms, webinars, and communities</td>
<td>Templates require careful policy design</td>
</tr>
<tr>
<td style="text-align:right">7</td>
<td>Stream Video</td>
<td style="text-align:right">84</td>
<td>Video combined with chat, feeds, and moderation</td>
<td>Strongest value appears inside the Stream ecosystem</td>
</tr>
<tr>
<td style="text-align:right">8</td>
<td>Cloudflare RealtimeKit</td>
<td style="text-align:right">83</td>
<td>Cloudflare-aligned managed WebRTC and UI components</td>
<td>Beta status and package migration need review</td>
</tr>
<tr>
<td style="text-align:right">9</td>
<td>Vonage Video API</td>
<td style="text-align:right">81</td>
<td>Enterprise communications and wider CPaaS workflows</td>
<td>Legacy TokBox and newer dashboard paths coexist</td>
</tr>
<tr>
<td style="text-align:right">10</td>
<td>Amazon Chime SDK</td>
<td style="text-align:right">78</td>
<td>AWS-native meeting applications and media pipelines</td>
<td>Teams assemble more product and operational layers</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>This table supports commercial investigation, not procurement by itself. Security, legal, finance, and support teams should validate the shortlist through a production-shaped proof of concept.</p><h2 id="top-10-webrtc-api-platforms-ranked">Top 10 WebRTC API Platforms Ranked</h2><p>The strongest platforms share WebRTC foundations but differ sharply in deployment, client coverage, UI, operations, and ecosystem fit.</p><h3 id="1-videosdk-best-managed-multi-platform-api">1. VideoSDK: Best Managed Multi-Platform API</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.29.39-PM-4.png" class="kg-image" alt="Top 10 WebRTC APIs: Expert Reviewed & Ranked" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://videosdk.live/" rel="noreferrer">VideoSDK</a> ranks first for teams needing one managed <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC API</a> across video calls, audio rooms, prebuilt meetings, custom interfaces, recording, and interactive live streaming.</p><p>The <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React documentation</a> lists JavaScript, React, React Native, Android, iOS, Flutter, Unity, IoT, C++, and Python targets, plus REST APIs.</p><p>Its Prebuilt path supports faster validation, while headless SDKs preserve control over room layouts, participant state, media tracks, and call actions through shared concepts.</p><p><strong>Best for:</strong> Product teams shipping embedded RTC across several clients, especially when calling, audio rooms, recordings, and interactive streams must share one platform.</p><p><strong>Trade-off:</strong> VideoSDK does not offer a self-hosted <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu" rel="noreferrer">SFU</a> comparable to LiveKit's open-source server. As checked on 10 August 2026, <a href="https://www.videosdk.live/pricing" rel="noreferrer">VideoSDK charges</a> $0.001 per audio participant-minute and $0.004 per video participant-minute on its pay-as-you-go plan. New accounts include $20 in free credit, with no minimum commitment. </p><h3 id="2-livekit-best-for-open-source-control">2. LiveKit: Best for Open-Source Control</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.40-PM-2.png" class="kg-image" alt="Top 10 WebRTC APIs: Expert Reviewed & Ranked" loading="lazy" width="2920" height="1670"/></figure><p>LiveKit ranks second because its open-source server and client stacks combine private deployment control with an optional managed cloud.</p><p>The <a href="https://docs.livekit.io/intro/basics/connect/" rel="noreferrer nofollow">LiveKit connection guide</a> documents JavaScript, Swift, Android, React Native, Flutter, C++, and Unity clients. It also lists backend SDKs for real-time agents and services.</p><p>Teams can operate their own infrastructure, use LiveKit Cloud, or retain a clearer migration path between those models than most managed-only vendors provide.</p><p><strong>Best for:</strong> Teams needing source access, private deployment, custom media services, or backend programs connected directly to real-time rooms.</p><p><strong>Trade-off:</strong> Self-hosting shifts TURN, regions, scaling, upgrades, monitoring, and incident response to your team. VideoSDK fits better when managed product breadth matters more.</p><h3 id="3-agora-best-for-specialised-engagement">3. Agora: Best for Specialised Engagement</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.26-PM-4.png" class="kg-image" alt="Top 10 WebRTC APIs: Expert Reviewed & Ranked" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/en/" rel="noreferrer nofollow">Agora</a> ranks third for teams building social, gaming, entertainment, commerce, or interactive broadcast products across many geographic markets.</p><p>Its current product catalogue covers real-time voice, video, chat, signalling, whiteboard, analytics, spatial audio, and noise suppression. Teams can choose SDK or lower-code paths.</p><p>That broad catalogue is valuable when specialised engagement features matter, although product selection and cost modelling require more solution design.</p><p><strong>Best for:</strong> Large social and media applications needing specialised audio, engagement extensions, broadcast workflows, and a long-standing global RTC vendor.</p><p><strong>Trade-off:</strong> Agora's wider catalogue can complicate architecture and billing comparisons. Verify the exact products and add-ons required before estimating total cost.</p><h3 id="4-daily-best-for-browser-first-embeds">4. Daily: Best for Browser-First Embeds</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.02-PM-3.png" class="kg-image" alt="Top 10 WebRTC APIs: Expert Reviewed & Ranked" loading="lazy" width="2924" height="1652"/></figure><p><a href="https://www.daily.co/" rel="noreferrer nofollow">Daily</a> ranks fourth because developers can begin with an embedded call frame, then move towards a custom interface through the same JavaScript client.</p><p>The <a href="https://docs.daily.co/reference/daily-js/daily-call-client" rel="noreferrer nofollow">daily call client</a> exposes <code>createFrame()</code> for prebuilt experiences and <code>createCallObject()</code> for custom applications, alongside devices, participants, recording, streaming, and network methods.</p><p>This progression suits web teams that need an acceptable first call quickly without closing the door on custom controls and layouts.</p><p><strong>Best for:</strong> Browser-first products that value a fast embed, clear JavaScript APIs, and gradual customisation.</p><p><strong>Trade-off:</strong> VideoSDK and LiveKit document more specialist client targets. Daily remains compelling when web delivery matters more than broader device coverage.</p><h3 id="5-twilio-video-best-for-cpaas-customer-engagement">5. Twilio Video: Best for CPaaS Customer Engagement</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.53.31-PM-2.png" class="kg-image" alt="Top 10 WebRTC APIs: Expert Reviewed & Ranked" loading="lazy" width="2910" height="1638"/></figure><p><a href="https://www.twilio.com/en-us" rel="noreferrer nofollow">Twilio</a> Video ranks fifth for organisations already using Twilio and adding video to customer support, telehealth, retail, financial services, or professional-service workflows.</p><p>Twilio announced a video end-of-life plan in 2023, then <a href="https://www.twilio.com/en-us/changelog/-twilio-video-will-remain-a-standalone-product" rel="noreferrer nofollow">reversed that decision in October 2024</a>.</p><p>The current product covers programmable rooms, recordings, compositions, network diagnostics, and SDKs for web, iOS, and Android.</p><p><strong>Best for:</strong> Existing Twilio customers that want video inside a wider communications and customer-engagement platform.</p><p><strong>Trade-off:</strong> Its client set is narrower than VideoSDK or LiveKit. Twilio also states that its renewed roadmap focuses more tightly on customer-engagement use cases.</p><h3 id="6-100ms-best-for-role-driven-rooms">6. 100ms: Best for Role-Driven Rooms</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.31.12-PM-2.png" class="kg-image" alt="Top 10 WebRTC APIs: Expert Reviewed & Ranked" loading="lazy" width="2910" height="1656"/></figure><p>100ms ranks sixth because its templates and roles model maps clearly to classrooms, webinars, audio communities, and events with explicit permissions.</p><p>The <a href="https://www.100ms.live/docs/get-started/v2/get-started/overview" rel="noreferrer nofollow">100ms platform overview</a> covers conferencing, webinars, Prebuilt experiences, recording, messaging, and interactive streaming. Templates define which roles can publish, subscribe, moderate, or change roles.</p><p><strong>Best for:</strong> Products where teachers, students, hosts, speakers, moderators, and viewers need distinct behaviour inside the same session.</p><p><strong>Trade-off:</strong> The template model rewards careful upfront design. VideoSDK's common room primitives can feel more direct for products mixing calling and streaming modes.</p><h3 id="7-stream-video-best-ecosystem-bundle">7. Stream Video: Best Ecosystem Bundle</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-28-at-4.33.18-PM-1.png" class="kg-image" alt="Top 10 WebRTC APIs: Expert Reviewed & Ranked" loading="lazy" width="2890" height="1540"/></figure><p>Stream Video ranks seventh for teams wanting real-time video alongside established chat, activity feed, and moderation APIs with shared developer conventions.</p><p>The <a href="https://getstream.io/" rel="noreferrer nofollow">Stream</a> Video SDK hub lists React, JavaScript, Swift, Android, React Native, Flutter, Unity, and server-side paths. It offers components and lower-level primitives.</p><p><strong>Best for:</strong> Community, marketplace, or social products already using Stream Chat, Feeds, or Moderation.</p><p><strong>Trade-off:</strong> Stream's strongest advantage is ecosystem fit. VideoSDK is the clearer RTC-first shortlist option when calling, and interactive streaming drives the purchase.</p><h3 id="8-cloudflare-realtimekit-best-emerging-edge-option">8. Cloudflare RealtimeKit: Best Emerging Edge Option</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-24-at-5.27.25-PM-2.png" class="kg-image" alt="Top 10 WebRTC APIs: Expert Reviewed & Ranked" loading="lazy" width="2924" height="1658"/></figure><p>Cloudflare RealtimeKit ranks eighth as a managed WebRTC platform with a Core SDK, UI Kit, REST APIs, webhooks, recording, and stage-management features.</p><p>The <a href="https://developers.cloudflare.com/realtime/realtimekit/" rel="noreferrer nofollow">RealtimeKit overview</a> identifies the product as beta and places it above Cloudflare's Realtime SFU. Its <a href="https://developers.cloudflare.com/realtime/realtimekit/release-notes/" rel="noreferrer nofollow">release notes</a> show active 2026 changes.</p><p>Dyte is not ranked separately because <a href="https://docs.dyte.io/guides/realtimekit-migration/sdk-guide" rel="noreferrer nofollow">Dyte's migration guide</a> marks older packages as deprecated and maps them to Cloudflare RealtimeKit replacements.</p><p><strong>Best for:</strong> Teams already standardising on Cloudflare and comfortable evaluating an evolving beta product.</p><p><strong>Trade-off:</strong> Package renames and breaking releases increase migration review. Recheck product status, pricing, and SDK versions immediately before procurement.</p><h3 id="9-vonage-video-api-best-wider-communications-fit">9. Vonage Video API: Best Wider Communications Fit</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.32.16-PM-2.png" class="kg-image" alt="Top 10 WebRTC APIs: Expert Reviewed & Ranked" loading="lazy" width="2922" height="1652"/></figure><p>Vonage ranks ninth for enterprises that want programmable video inside a communications portfolio spanning voice, messaging, SIP, identity, and customer engagement.</p><p>The <a href="https://www.vonage.com/communications-apis/" rel="noreferrer nofollow">Vonage</a> Video API overview covers interactive video, messaging, screen sharing, broadcasting, encryption, recording, captions, and libraries across web, mobile, and desktop environments.</p><p><strong>Best for:</strong> Organisations already buying Vonage communications APIs, especially when video must connect with contact-centre or enterprise voice workflows.</p><p><strong>Trade-off:</strong> TokBox history and newer Vonage dashboard paths introduce migration questions. Greenfield RTC teams may prefer a more focused developer journey.</p><h3 id="10-amazon-chime-sdk-best-aws-native-stack">10. Amazon Chime SDK: Best AWS-Native Stack</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.54.40-PM-1.png" class="kg-image" alt="Top 10 WebRTC APIs: Expert Reviewed & Ranked" loading="lazy" width="2918" height="1632"/></figure><p>Amazon Chime SDK ranks tenth for teams wanting regional WebRTC media sessions and composable meeting building blocks inside an established AWS environment.</p><p>The <a href="https://docs.aws.amazon.com/chime-sdk/latest/dg/meetings-sdk.html" rel="noreferrer nofollow">AWS meeting SDK guide</a> covers audio, video, content sharing, region-specific media services, meeting creation, attendee management, and client integration.</p><p>AWS ended the separate Chime SDK Proxy Sessions feature on 31 March 2026, while the Meetings SDK documentation remains active. Treat feature-level lifecycle notices separately from the whole product.</p><p><strong>Best for:</strong> AWS-heavy teams prepared to assemble authentication, UI, workflows, storage, monitoring, and media pipelines around cloud building blocks.</p><p><strong>Trade-off:</strong> Assembly work is higher than packaged providers. VideoSDK or Daily can shorten the path when prebuilt UI and coordinated RTC features carry more value.</p><p><strong>Honourable mention:</strong> <a href="https://jitsi.org/" rel="noreferrer nofollow">Jitsi</a> remains a credible open-source meeting stack with self-hosting and JaaS. It sits outside this managed-API top ten because the shortlist focuses on product SDK platforms.</p><h2 id="what-is-the-best-webrtc-api">What Is the Best WebRTC API?</h2><p>The best WebRTC API is the platform that matches your hardest production constraint.</p><p>Use <strong>VideoSDK</strong> when you need managed calls, audio rooms, prebuilt UI, custom SDKs, recording, server APIs, and interactive streaming across many client targets.</p><p>Use <strong>LiveKit</strong> when open-source infrastructure, self-hosting, backend media programmes, or switching between private deployment and managed cloud matter more than packaged breadth.</p><p>Use <strong>Agora</strong> when your primary workload is global social engagement, gaming, karaoke, specialised audio, or interactive broadcast supported by a large extension catalogue.</p><p>Use <strong>Daily</strong> when a browser-first product needs an embedded call quickly, with a credible path from a frame to a custom call object.</p><p>Use <strong>Twilio Video</strong> when video belongs inside an existing Twilio customer-engagement stack. Use <strong>100ms</strong> when templates and roles naturally model hosts, speakers, moderators, teachers, and viewers.</p><p>Use <strong>Stream</strong>, <strong>RealtimeKit</strong>, <strong>Vonage</strong>, or <strong>Amazon Chime SDK</strong> when alignment with their surrounding ecosystems creates more value than provider neutrality.</p><h2 id="raw-webrtc-vs-a-managed-webrtc-api">Raw WebRTC vs a Managed WebRTC API</h2><p>Raw WebRTC provides protocol control; a managed API supplies the services the standard deliberately leaves undefined.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Production concern</th>
<th>Raw browser WebRTC</th>
<th>Managed WebRTC API</th>
<th>Practical consequence</th>
</tr>
</thead>
<tbody>
<tr>
<td>Signalling</td>
<td>You design and operate it</td>
<td>Provider supplies room signalling</td>
<td>Managed APIs shorten the path beyond a peer-to-peer demo</td>
</tr>
<tr>
<td>NAT traversal</td>
<td>You provision STUN and TURN</td>
<td>Provider operates traversal and fallback</td>
<td>Managed APIs reduce restricted-network ownership</td>
</tr>
<tr>
<td>Multiparty media</td>
<td>Mesh unless you add an SFU</td>
<td>Managed SFU or equivalent routing</td>
<td>Group calls avoid quadratic upload requirements</td>
</tr>
<tr>
<td>Recording</td>
<td>You build capture and composition</td>
<td>Server-side recording APIs</td>
<td>Playback and compliance workflows become product features</td>
</tr>
<tr>
<td>Observability</td>
<td>Raw <code>getStats()</code> data</td>
<td>Dashboards, events, logs, and webhooks</td>
<td>Support teams diagnose participant problems faster</td>
</tr>
<tr>
<td>Platform SDKs</td>
<td>Browser interfaces plus native libraries</td>
<td>Framework and platform SDKs</td>
<td>Product teams share concepts across clients</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Raw WebRTC remains appropriate for learning, unusual transport requirements, highly controlled peer-to-peer products, or teams that deliberately want infrastructure ownership.</p><p>A managed WebRTC API becomes rational when the roadmap includes group rooms, mobile clients, recording, moderation, streaming, analytics, compliance workflows, or support commitments.</p><p>The hidden build cost appears after the demo. TURN capacity, SFU routing, regions, reconnection, codec differences, recording composition, and abuse controls require continued ownership.</p><p>For more background, read VideoSDK's guides to <a href="https://videosdk.live/blog/webrtc">WebRTC fundamentals</a>, <a href="https://www.videosdk.live/blog/what-is-webrtc-signaling">WebRTC signalling</a>, and <a href="https://www.videosdk.live/blog/hls-vs-webrtc">HLS versus WebRTC</a>.</p><h2 id="webrtc-api-vs-sip">WebRTC API vs SIP</h2><p>WebRTC handles browser and app media; SIP standardises session signalling across telephony and enterprise voice systems.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Dimension</th>
<th>WebRTC</th>
<th>SIP</th>
</tr>
</thead>
<tbody>
<tr>
<td>Primary role</td>
<td>Real-time audio, video, and data in browsers or apps</td>
<td>Establish, manage, and end voice or video sessions</td>
</tr>
<tr>
<td>Signalling</td>
<td>Application-defined, often WebSocket or HTTP</td>
<td>Standard SIP messages such as <code>INVITE</code>, <code>ACK</code>, and <code>BYE</code></td>
</tr>
<tr>
<td>Media</td>
<td>Commonly secured with DTLS-SRTP</td>
<td>Commonly negotiated with SDP and carried using RTP/SRTP</td>
</tr>
<tr>
<td>Typical endpoints</td>
<td>Browsers, mobile apps, embedded clients</td>
<td>PBXs, desk phones, SIP trunks, carriers</td>
</tr>
<tr>
<td>Best fit</td>
<td>In-app calling, collaboration, telehealth, education</td>
<td>Telephony, contact centres, enterprise voice, PSTN interconnect</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>WebRTC is not a replacement for SIP in every system. A contact centre may use WebRTC in the agent browser and SIP for trunks, phone numbers, routing, and interoperability.</p><p>VideoSDK's <a href="https://docs.videosdk.live/telephony/introduction">SIP and WebRTC telephony documentation</a> connects SIP endpoints, providers, inbound and outbound gateways, and routing rules with VideoSDK rooms.</p><p>For a deeper comparison, see the VideoSDK guide to <a href="https://videosdk.live/developer-hub/webrtc/webrtc-vs-sip">WebRTC versus SIP</a>.</p><h2 id="production-checklist-for-webrtc-apis">Production Checklist for WebRTC APIs</h2><p>A polished demo proves almost nothing about TURN, reconnection, observability, recording, compliance, and incident ownership.</p><h3 id="secure-tokens-and-room-access">Secure tokens and room access</h3><p>Generate participant tokens on your server, keep API secrets outside client bundles, shorten token lifetime, and scope permissions to the required room, role, and action.</p><p>Map your authenticated user ID to the provider participant ID. Log token issuance safely, prevent replay where supported, and revoke access when business state changes.</p><h3 id="test-hostile-networks">Test hostile networks</h3><p>Run calls through corporate firewalls, mobile networks, VPNs, packet loss, device changes, and browser permission denials. Localhost cannot validate TURN or recovery behaviour.</p><p>Confirm TCP or TLS fallback where required. Monitor ICE state changes and display useful reconnecting UI instead of leaving users with silent frozen video.</p><h3 id="measure-quality-per-participant">Measure quality per participant</h3><p>Collect round-trip time, packet loss, jitter, bitrate, frame rate, freeze events, audio levels, selected candidate pairs, and reconnect counts for every participant session.</p><p>Connect provider session identifiers to your application logs. Support teams need one trace across authentication, room creation, signalling, media quality, and recording events.</p><h3 id="validate-recording-and-data-policy">Validate recording and data policy</h3><p>Test composite and individual-track recordings with real layouts, screen sharing, participant churn, silent periods, and failure recovery. Confirm storage location, retention, deletion, and encryption.</p><p>Healthcare, finance, education, and identity applications should involve legal and security reviewers. A vendor compliance badge does not replace your own data-flow assessment.</p><h3 id="model-complete-workload-cost">Model complete workload cost</h3><p>Estimate participant minutes, subscribed resolution, recording, transcription, storage, egress, streaming, TURN use, support plans, and minimum commitments under normal and peak traffic.</p><p>Do not compare headline per-minute rates alone. Bundled recording, analytics, or support can change complete product cost more than the base media rate.</p><h3 id="prove-failure-ownership">Prove failure ownership</h3><p>Document who handles provider incidents, degraded regions, expired credentials, webhook retries, delayed recordings, client crashes, and emergency feature shutdowns during live sessions.</p><p>Ask every shortlisted provider for status history, support targets, data-processing terms, subprocessor lists, regional controls, and escalation procedures relevant to your risk profile.</p><h2 id="glossary">Glossary</h2><blockquote><strong>RTC Peer Connection:</strong> The browser interface that negotiates and manages a real-time connection, including ICE candidates, media senders, receivers, transports, and connection state.</blockquote><blockquote><strong>Signalling:</strong> The application-defined exchange of offers, answers, ICE candidates, identity, and room state. WebRTC does not mandate the signalling transport.</blockquote><blockquote><strong>TURN server:</strong> A relay used when peers cannot establish a direct path because of NAT, firewall, proxy, or network-policy restrictions.</blockquote><blockquote><strong>SFU:</strong> A Selective Forwarding Unit receives participant tracks and forwards selected streams without composing every participant into one server-rendered video.</blockquote><blockquote><strong>VideoSDK Room:</strong> A named real-time session where authenticated participants publish and subscribe to audio, video, screen, and data streams through VideoSDK SDKs.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><p>A useful ranking connects each provider to a clear product condition and a current evidence trail.</p><ul><li>VideoSDK ranks first for managed multi-platform RTC because it combines ten documented client targets, Prebuilt UI, custom SDKs, server controls, and interactive streaming.</li><li>LiveKit should lead your shortlist when open-source infrastructure, self-hosting, backend media programs, or deployment portability outweigh managed product convenience.</li><li>Agora, Daily, Twilio Video, and 100ms become stronger for specialised engagement, browser-first embedding, CPaaS customer journeys, and role-driven rooms respectively.</li><li>Twilio Video remains active because Twilio reversed its planned discontinuation, while deprecated Dyte packages now map to Cloudflare RealtimeKit.</li><li>A production decision must test tokens, TURN fallback, reconnection, observability, data policy, regional controls, support, and complete workload cost.</li></ul><h2 id="conclusion">Conclusion</h2><p>The best WebRTC API decision is conditional, but it should never be vague.</p><p>VideoSDK ranks first under this rubric for teams needing managed RTC across many clients, Prebuilt and custom UI paths, recording, server orchestration, and interactive streaming. LiveKit remains stronger for self-hosting, while Agora and Daily lead narrower conditions.</p><p>Build a production-shaped proof of concept with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React quickstart</a> or <a href="https://app.videosdk.live/login">create a free account</a>. What WebRTC use case are you building?</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-a-webrtc-api-used-for">What is a WebRTC API used for?</h3><p>A WebRTC API is used to build real-time audio, video, screen-sharing, and peer-data experiences in web or mobile applications. Common products include telehealth calls, classrooms, customer support, social audio, webinars, live communities, and collaborative tools.</p><h3 id="is-webrtc-an-api-or-a-protocol">Is WebRTC an API or a protocol?</h3><p>WebRTC is a collection of browser APIs and network protocols rather than one single protocol. W3C specifies browser interfaces such as <code>RTCPeerConnection</code>, while IETF standards define media security, connectivity, and transport behaviour used underneath.</p><h3 id="how-do-i-use-a-webrtc-api">How do I use a WebRTC API?</h3><p>To use a WebRTC API, choose raw browser interfaces or a managed provider, create a signalling and authentication flow, capture local media, establish a room or peer connection, then publish and subscribe to tracks. Managed providers operate signalling, TURN, SFUs, recording, and observability for you.</p><h3 id="what-is-the-difference-between-webrtc-and-sip">What is the difference between WebRTC and SIP?</h3><p>The main difference is that WebRTC provides real-time media and data capabilities for browsers and applications, while SIP standardises session signalling for telephony and enterprise communications. They often work together through a gateway connecting browser participants with PBXs, SIP trunks, or phone numbers.</p><h3 id="does-webrtc-require-a-signalling-server">Does WebRTC require a signalling server?</h3><p>A practical WebRTC application needs a signalling path to exchange offers, answers, ICE candidates, identity, and session state. The WebRTC specification does not prescribe whether that path uses WebSocket, HTTP, SIP, or another transport.</p><h3 id="is-the-webrtc-api-free">Is the WebRTC API free?</h3><p>Browser WebRTC APIs are free standards, but production applications still incur engineering, hosting, TURN relay, media-server, recording, storage, egress, monitoring, and support costs. Open-source software can remove a licence fee without removing infrastructure ownership.</p><h3 id="what-is-the-best-webrtc-api-1">What is the best WebRTC API?</h3><p>The best WebRTC API depends on your constraint. VideoSDK fits managed multi-platform product teams, LiveKit fits open-source control, Agora fits specialised engagement, Daily fits browser-first embedding, and ecosystem providers fit teams already committed to their wider platforms.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 Communication API Platforms: Expert Reviewed & Ranked]]></title><description><![CDATA[Compare ten communication API platforms across RTC depth, channel breadth, pricing, SDK coverage, production controls, and product fit.
]]></description><link>https://www.videosdk.live/blog/communication-api-platforms</link><guid isPermaLink="false">6a71de28b3240feb748c9461</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 10 Aug 2026 10:02:06 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-10--2026--02_28_05-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>For embedded video, audio, and interactive live streaming, VideoSDK ranks first in this RTC-weighted review. Twilio suits products that need broad telecom and messaging channels, while Vonage offers a balanced mix. Choose an RTC-first platform when communication lives inside your app, and a telecom-first CPaaS when external channels drive the workflow.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-10--2026--02_28_05-PM.png" alt="Top 10 Communication API Platforms: Expert Reviewed & Ranked"/><p>A communication API platform can remove years of work around media servers, telecom connections, carrier routing, recording pipelines, and network adaptation. The hard part is choosing the right kind of platform.</p><p>Some providers focus on live media inside an application. Others focus on SMS, WhatsApp, phone numbers, email, and customer engagement. Treating them as interchangeable leads to poor architecture and unpredictable costs.</p><p>This review compares ten leading options using public documentation, SDK guides, pricing pages, and product updates checked on 10 August 2026. It ranks product fit for developers, not synthetic network performance.</p><h2 id="what-is-a-communication-api-platform">What Is a Communication API Platform?</h2><p><strong>A communication API platform is a cloud service that exposes APIs, SDKs, webhooks, and UI components for adding voice, video, messaging, or related communication features to software.</strong></p><p>A communication API platform works by operating the underlying signalling, media, telecom, routing, security, and delivery infrastructure. Your application controls the user experience and business logic through programmable interfaces.</p><p>Common capabilities include:</p><ul><li>Video and audio calling</li><li>Interactive live streaming</li><li>In-app chat and data messages</li><li>SMS, MMS, WhatsApp, and RCS</li><li>PSTN voice calls and phone numbers</li><li>Email and push notifications</li><li>Authentication and verification</li><li>Recording, transcription, moderation, and analytics</li></ul><p>Browser-based media platforms commonly build on the <a href="https://www.w3.org/TR/webrtc/">W3C WebRTC specification</a>, then add signalling, <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a> connectivity, media servers, session controls, security, observability, and client SDKs.</p><h3 id="communication-api-platform-vs-cpaas-ucaas-and-ccaas">Communication API Platform vs CPaaS, UCaaS, and CCaaS</h3><p>These four categories overlap, but each solves a different primary problem.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Category</th>
<th>What it provides</th>
<th>Primary buyer need</th>
<th>Typical delivery model</th>
</tr>
</thead>
<tbody>
<tr>
<td>Communication API platform</td>
<td>Programmable video, voice, messaging, or streaming building blocks</td>
<td>Add communication to a custom product</td>
<td>APIs, SDKs, webhooks, UI kits</td>
</tr>
<tr>
<td>CPaaS</td>
<td>Telecom and digital channels such as SMS, PSTN voice, WhatsApp, RCS, verification, and sometimes video</td>
<td>Reach users across external networks</td>
<td>Usage-based cloud APIs</td>
</tr>
<tr>
<td>UCaaS</td>
<td>Ready-made workplace calling, meetings, and team messaging</td>
<td>Give employees a unified communication suite</td>
<td>Per-user SaaS application</td>
</tr>
<tr>
<td>CCaaS</td>
<td>Agent routing, queues, workforce tools, analytics, and omnichannel customer support</td>
<td>Operate a contact centre</td>
<td>Per-agent or usage-based SaaS</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Use an RTC-first communication API platform when the live experience is part of your product. Use a telecom-first CPaaS when reaching users through phone numbers or external messaging networks is the main requirement.</p><p>Many production systems use both. A <a href="https://www.videosdk.live/solutions/telehealth" rel="noreferrer">telehealth</a> product can run consultations through an RTC platform while a CPaaS sends reminders, verifies phone numbers, and handles <a href="https://en.wikipedia.org/wiki/Public_switched_telephone_network" rel="noreferrer">PSTN</a> escalation.</p><h2 id="how-communication-api-platforms-handle-real-time-media">How Communication API Platforms Handle Real-Time Media</h2><p>Modern RTC platforms combine client SDKs, secure tokens, signalling services, and media infrastructure to manage each session.</p><h3 id="sfu-vs-mcu-media-routing">SFU vs MCU Media Routing</h3><p>Many multi-party WebRTC platforms use a Selective Forwarding Unit, or SFU. Each participant uploads one or more media streams, and the SFU forwards suitable layers to the other participants.</p><p>An <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu" rel="noreferrer">SFU</a> avoids decoding and recomposing every stream on the server. That design usually reduces processing delay and lets the receiving client choose video layers based on layout and bandwidth.</p><p>An MCU, or Multipoint Control Unit, decodes and mixes streams into a composed output before sending it to participants. MCUs simplify some client workloads but require more server-side processing.</p><p>Neither architecture is universally better. SFUs suit interactive rooms and custom layouts, while server-side composition remains useful for recordings, broadcasts, and clients with limited rendering capacity.</p><h2 id="how-we-ranked-each-communication-api-platform">How We Ranked Each Communication API Platform</h2><p>This ranking prioritises the needs of developers building communication directly into web, mobile, desktop, game-engine, or connected-device applications.</p><p>We reviewed official product documentation, public SDK matrices, pricing pages, API references, and product announcements. We did not negotiate enterprise contracts or run every provider from identical global network locations.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Evaluation area</th>
<th style="text-align:right">Weight</th>
</tr>
</thead>
<tbody>
<tr>
<td>Embedded video, audio, and streaming depth</td>
<td style="text-align:right">25%</td>
</tr>
<tr>
<td>Developer experience and SDK coverage</td>
<td style="text-align:right">20%</td>
</tr>
<tr>
<td>Production controls and extensibility</td>
<td style="text-align:right">15%</td>
</tr>
<tr>
<td>Communication-channel breadth</td>
<td style="text-align:right">15%</td>
</tr>
<tr>
<td>Pricing transparency</td>
<td style="text-align:right">10%</td>
</tr>
<tr>
<td>Security and enterprise controls</td>
<td style="text-align:right">10%</td>
</tr>
<tr>
<td>AI and ecosystem extensibility</td>
<td style="text-align:right">5%</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>This is an editorial product-fit ranking, not a latency benchmark. VideoSDK ranks first under an RTC-first method. </p><h2 id="top-communication-api-platforms-at-a-glance">Top Communication API Platforms at a Glance</h2><p>The comparison below shows each platform's clearest fit and its most important trade-off.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th style="text-align:right">Rank</th>
<th>Platform</th>
<th>Best for</th>
<th>Core strength</th>
<th>Main trade-off</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">1</td>
<td>VideoSDK</td>
<td>Embedded RTC across many client platforms</td>
<td>Video, audio, ILS, rooms, Prebuilt, recording, transcription, SIP</td>
<td>Not a complete bulk SMS or email CPaaS</td>
</tr>
<tr>
<td style="text-align:right">2</td>
<td>Twilio</td>
<td>Broad programmable communications</td>
<td>Voice, messaging, video, verification, email, phone numbers</td>
<td>Total cost spans several products and fee types</td>
</tr>
<tr>
<td style="text-align:right">3</td>
<td>Vonage</td>
<td>Balanced enterprise CPaaS and RTC</td>
<td>Mature video plus voice, messaging, and verification</td>
<td>Advanced workflows may require several APIs</td>
</tr>
<tr>
<td style="text-align:right">4</td>
<td>Agora</td>
<td>Large-scale live engagement</td>
<td>Deep RTC, live streaming, chat, signalling, extensions</td>
<td>Add-ons increase architecture and cost complexity</td>
</tr>
<tr>
<td style="text-align:right">5</td>
<td>Daily</td>
<td>WebRTC-first products and media pipelines</td>
<td>Focused video and audio APIs with Prebuilt</td>
<td>Narrower telecom-channel coverage</td>
</tr>
<tr>
<td style="text-align:right">6</td>
<td>Sendbird</td>
<td>Chat-led applications</td>
<td>Chat, voice, video, moderation, shared identities</td>
<td>Group video limits need early validation</td>
</tr>
<tr>
<td style="text-align:right">7</td>
<td>Stream</td>
<td>Social and community products</td>
<td>Reusable chat, video, audio-room, and feed components</td>
<td>Chat and video have separate pricing structures</td>
</tr>
<tr>
<td style="text-align:right">8</td>
<td>Telnyx</td>
<td>Carrier-controlled communications</td>
<td>Voice, messaging, numbers, SIP, and video</td>
<td>RTC UI tooling is not the central product focus</td>
</tr>
<tr>
<td style="text-align:right">9</td>
<td>Sinch</td>
<td>Omnichannel messaging and RCS</td>
<td>Fourteen messaging channels through one API</td>
<td>Channel and destination pricing can be complex</td>
</tr>
<tr>
<td style="text-align:right">10</td>
<td>Infobip</td>
<td>Enterprise customer engagement</td>
<td>Messaging, email, voice, WhatsApp, RCS, and video</td>
<td>Broad catalogue requires careful product selection</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h2 id="top-10-communication-api-platforms">Top 10 Communication API Platforms</h2><p>Each platform below has a defensible use case; the ranking reflects the RTC-first weighting disclosed above.</p><h3 id="1-videosdk-best-for-embedded-real-time-communication">1. VideoSDK: Best for Embedded Real-Time Communication</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.29.39-PM-3.png" class="kg-image" alt="Top 10 Communication API Platforms: Expert Reviewed & Ranked" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> ranks first for teams building video, audio, and interactive live experiences directly into their products.</p><p>The platform uses a room-based model for calling and interactive live streaming. It provides Prebuilt and custom integration paths, participant controls, screen sharing, recording, transcription, custom tracks, analytics, <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a> output, <a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer">HLS</a>, and <a href="https://www.videosdk.live/developer-hub/sip/mastering-sip-protocol-comprehensive-guide" rel="noreferrer">SIP</a> connectivity.</p><p>Its current documentation lists Prebuilt, JavaScript, React, React Native, Android, iOS, Flutter, Unity, Python, C++, IoT, and REST development paths. This breadth matters when one product spans browsers, native mobile, games, devices, and backend media workflows.</p><p>Public <a href="https://www.videosdk.live/pricing">VideoSDK pricing</a> currently includes a $20 account credit. Pay-as-you-go rates list audio at $0.001 per participant minute, video at $0.004 per participant minute, livestream speakers at $0.004 per minute, and viewers at $0.002 per minute.</p><p><strong>Why it ranks first:</strong> VideoSDK scores strongly on the highest-weighted factors: RTC depth, client coverage, custom and Prebuilt paths, production APIs, and a shared architecture for calls and interactive streams.</p><p><strong>Best for:</strong> Telehealth, education, recruitment, social communities, customer support, live commerce, webinars, events, and connected products where real-time media is central.</p><p><strong>Main limitation:</strong> VideoSDK is not a full replacement for a telecom CPaaS when bulk SMS, email delivery, RCS campaigns, or global number procurement drive the product.</p><h3 id="2-twilio-best-broad-developer-cpaas">2. Twilio: Best Broad Developer CPaaS</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-10-at-12.35.46-PM.png" class="kg-image" alt="Top 10 Communication API Platforms: Expert Reviewed & Ranked" loading="lazy" width="2886" height="1594"/></figure><p><a href="https://www.twilio.com/en-us" rel="noreferrer nofollow">Twilio</a> remains a strong default when an application needs several programmable communication channels from one vendor.</p><p>Its portfolio covers programmable voice, messaging, video, conversations, verification, phone numbers, and email through SendGrid. That breadth can reduce vendor count for customer-engagement applications.</p><p><a href="https://www.twilio.com/en-us/video/pricing" rel="noreferrer nofollow">Twilio Video pricing</a> currently starts at $0.004 per participant minute for Group Rooms. Recordings, compositions, transcription, storage, phone numbers, carrier fees, messages, and other products use separate billing units.</p><p>Twilio previously announced a December 2026 end-of-life date for Programmable Video. The company <a href="https://www.twilio.com/en-us/changelog/-twilio-video-will-remain-a-standalone-product" rel="noreferrer nofollow">reversed that decision in October 2024</a> and confirmed that Video would remain a standalone product. Articles still describing Twilio Video as scheduled for shutdown are outdated.</p><p><strong>Why it ranks second:</strong> Twilio offers extensive telecom and messaging capabilities, supported by mature documentation, helper libraries, and workflow integrations.</p><p><strong>Best for:</strong> Products combining phone calls, SMS, WhatsApp, verification, email, in-app messaging, and video.</p><p><strong>Main limitation:</strong> Forecasting total cost can require combining participant minutes, phone-number rental, carrier charges, message rates, recordings, storage, and support packages.</p><p><strong>Compared with VideoSDK:</strong> Choose Twilio when channel breadth is decisive. Choose VideoSDK when embedded RTC, interactive streaming, and client-SDK coverage carry more weight.</p><h3 id="3-vonage-best-balanced-cpaas-and-rtc-portfolio">3. Vonage: Best Balanced CPaaS and RTC Portfolio</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.32.16-PM-1.png" class="kg-image" alt="Top 10 Communication API Platforms: Expert Reviewed & Ranked" loading="lazy" width="2922" height="1652"/></figure><p><a href="https://www.vonage.com/communications-apis/" rel="noreferrer nofollow">Vonage</a> offers one of the clearest middle grounds between telecom APIs and embedded real-time video.</p><p>The Vonage portfolio covers video, voice, messaging, and verification. Its Video API includes media, signalling, chat, TURN relay, client SDKs, broadcasts, recording, SIP, captions, and other advanced services.</p><p>Current <a href="https://www.vonage.com/communications-apis/video/pricing/" rel="noreferrer nofollow">Vonage Video API pricing</a> lists $0.00410 per participant minute. New accounts receive a trial allocation split between video-session minutes and advanced-feature minutes, while recording, HLS, SIP, captions, and enterprise controls cost extra.</p><p><strong>Why it ranks third:</strong> Vonage provides deeper video functionality than many messaging-led CPaaS providers while retaining established telecom and verification products.</p><p><strong>Best for:</strong> Virtual appointments, enterprise customer service, regulated workflows, contact-centre extensions, and products combining embedded video with traditional communications.</p><p><strong>Main limitation:</strong> A team may still need to integrate and monitor several Vonage products rather than one unified application API.</p><p><strong>Compared with VideoSDK:</strong> Vonage fits organisations that want an established telecom portfolio beside RTC. VideoSDK gives media-led products a more concentrated developer surface across client platforms and interactive streaming.</p><h3 id="4-agora-best-for-large-scale-live-engagement">4. Agora: Best for Large-Scale Live Engagement</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.26-PM-3.png" class="kg-image" alt="Top 10 Communication API Platforms: Expert Reviewed & Ranked" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/en/" rel="noreferrer nofollow">Agora</a> is a credible choice for products that require real-time media, live audience participation, and specialised engagement features across regions.</p><p>The platform offers video calling, voice calling, interactive live streaming, broadcast streaming, chat, signalling, cloud recording, speech-to-text, media processing, and extension products.</p><p>Current <a href="https://prod.agora.io/en/pricing/video-calling" rel="noreferrer nofollow">Agora video pricing</a> lists $0.99 per 1,000 voice participant minutes, $3.99 per 1,000 HD video participant minutes, and higher rates for Full HD and larger resolutions. Cloud proxy, analytics, recording, and other services may introduce separate costs.</p><p><strong>Why it ranks fourth:</strong> Agora has substantial RTC depth and a product surface suited to live engagement, social experiences, education, gaming, and broadcast-style applications.</p><p><strong>Best for:</strong> Large live rooms, social audio, gaming communication, creator products, global events, and applications that need specialised media extensions.</p><p><strong>Main limitation:</strong> The number of products, extensions, and separately billed services makes architecture and cost evaluation more involved.</p><p><strong>Compared with VideoSDK:</strong> Agora deserves a shortlist for mature global live-engagement workloads. VideoSDK presents a simpler evaluation when one room model must support calling and interactive live streaming across many client environments.</p><h3 id="5-daily-best-for-webrtc-first-products">5. Daily: Best for WebRTC-First Products</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.02-PM-2.png" class="kg-image" alt="Top 10 Communication API Platforms: Expert Reviewed & Ranked" loading="lazy" width="2924" height="1652"/></figure><p><a href="https://www.daily.co/" rel="noreferrer nofollow">Daily</a> is a focused WebRTC platform with strong primitives for browser video, audio, embeddable interfaces, recording, streaming, telephony, and media pipelines.</p><p>Daily Prebuilt provides a ready-made call interface, while the lower-level SDKs let developers control tracks, layouts, devices, participants, and session behaviour. Daily also maintains Pipecat, an open-source framework for voice and multimodal agents.</p><p>Current <a href="https://www.daily.co/pricing/video-sdk/" rel="noreferrer nofollow">Daily pricing</a> includes 10,000 free participant minutes each month. List rates begin at $0.004 per video participant minute and $0.00099 per audio-only participant minute, with automatic volume discounts.</p><p><strong>Why it ranks fifth:</strong> Daily has a clear <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> focus, practical frontend tooling, and media access suited to calling, bots, and real-time AI pipelines.</p><p><strong>Best for:</strong> Browser calling, telehealth, collaboration tools, media bots, developer products, and AI agents that need live audio access.</p><p><strong>Main limitation:</strong> Daily does not provide the telecom and messaging breadth of Twilio, Sinch, or Infobip.</p><p><strong>Compared with VideoSDK:</strong> Daily is compelling for web-focused WebRTC teams. VideoSDK ranks higher here because the method rewards broader native, game-engine, device, and interactive-live-streaming coverage.</p><h3 id="6-sendbird-best-for-chat-led-applications">6. Sendbird: Best for Chat-Led Applications</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-06-at-7.17.03-PM-1.png" class="kg-image" alt="Top 10 Communication API Platforms: Expert Reviewed & Ranked" loading="lazy" width="2914" height="1560"/></figure><p><a href="https://sendbird.com/communications-api-platform" rel="noreferrer nofollow">Sendbird</a> is strongest when in-app messaging anchors the product and voice or video extends an existing conversation.</p><p>Sendbird Calls supports private calls, group calls, notifications, reconnect handling, recording, and call metrics. It shares identities and product context with Sendbird Chat, which helps chat-first teams avoid a disconnected call layer.</p><p>Current <a href="https://sendbird.com/pricing/calls" rel="noreferrer nofollow">Sendbird Calls pricing</a> lists voice from $0.0010 per user minute for peer-to-peer calls and $0.0015 for server-relayed calls. Video starts at $0.0014 peer-to-peer and $0.0035 server-relayed.</p><p>The same public page lists group voice calls with up to 1,000 users and group video calls with up to 10 users. Product teams should validate those limits against their room design before committing.</p><p><strong>Why it ranks sixth:</strong> Sendbird creates a coherent path from chat to calls, notifications, moderation, and community engagement.</p><p><strong>Best for:</strong> Marketplaces, support conversations, gaming communities, social applications, and products where users escalate from chat into a call.</p><p><strong>Main limitation:</strong> Video-first products must validate group size, media control, custom tracks, streaming requirements, and per-SDK feature parity.</p><p><strong>Compared with VideoSDK:</strong> Sendbird is the stronger chat-first default. VideoSDK is stronger when calls, audio rooms, or interactive streams form the primary experience.</p><h3 id="7-stream-best-for-ui-components-and-social-products">7. Stream: Best for UI Components and Social Products</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-28-at-4.33.18-PM.png" class="kg-image" alt="Top 10 Communication API Platforms: Expert Reviewed & Ranked" loading="lazy" width="2890" height="1540"/></figure><p><a href="https://getstream.io/" rel="noreferrer nofollow">Stream</a> combines chat, video, audio rooms, live streaming, activity feeds, moderation, and reusable interface components for community-led applications.</p><p>Its video documentation covers React, JavaScript, React Native, Android, iOS, Flutter, Unity, and server APIs. Teams can use ready-made call components or lower-level SDK primitives.</p><p>Current <a href="https://getstream.io/video/pricing/" rel="noreferrer nofollow">Stream video pricing</a> advertises $100 in free credits and usage-based rates that vary by media type and resolution. Chat uses a separate monthly-active-user and concurrency model, so teams adopting both products should model them together.</p><p><strong>Why it ranks seventh:</strong> Stream is attractive when calls must sit beside feeds, reactions, chat, moderation, and other social product features.</p><p><strong>Best for:</strong> Social networks, gaming, creator communities, marketplaces, livestream feeds, and applications that value polished frontend components.</p><p><strong>Main limitation:</strong> Chat and video remain related but separate products, pricing models, and operational surfaces.</p><p><strong>Compared with VideoSDK:</strong> Stream may fit better when chat, feeds, and moderation are equally important. VideoSDK has the advantage when RTC infrastructure and cross-platform media coverage dominate the decision.</p><h3 id="8-telnyx-best-for-carrier-controlled-communications">8. Telnyx: Best for Carrier-Controlled Communications</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-06-at-7.18.33-PM-1.png" class="kg-image" alt="Top 10 Communication API Platforms: Expert Reviewed & Ranked" loading="lazy" width="2940" height="1624"/></figure><p><a href="https://telnyx.com/" rel="noreferrer nofollow">Telnyx</a> is a telecom-infrastructure-led platform for programmable voice, messaging, phone numbers, SIP, networking, and video.</p><p>Its position in the carrier and telephony stack appeals to teams that need control over call routing, numbers, SIP connections, messaging delivery, and network operations.</p><p>Current <a href="https://telnyx.com/pricing/video-api" rel="noreferrer nofollow">Telnyx Video API pricing</a> lists its video bridge at $0.002 per participant minute. Recording, composition, storage, speech-to-text, call recording, and other services have separate rates.</p><p><strong>Why it ranks eighth:</strong> Telnyx combines competitively priced media with a substantial programmable telecom portfolio and direct control over telephony resources.</p><p><strong>Best for:</strong> Voice platforms, contact-centre infrastructure, SIP applications, number-heavy workflows, call routing, messaging, and products combining PSTN with WebRTC.</p><p><strong>Main limitation:</strong> Frontend RTC components and multi-platform media UI are not as central to its proposition as they are for VideoSDK, Stream, or Sendbird.</p><p><strong>Compared with VideoSDK:</strong> Use Telnyx when phone numbers, SIP, carrier connectivity, and telephony control dominate. Use VideoSDK when users primarily interact through embedded video, audio, or live streams.</p><h3 id="9-sinch-best-for-omnichannel-messaging-and-rcs">9. Sinch: Best for Omnichannel Messaging and RCS</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-10-at-12.58.21-PM.png" class="kg-image" alt="Top 10 Communication API Platforms: Expert Reviewed & Ranked" loading="lazy" width="2924" height="1654"/></figure><p><a href="https://sinch.com/" rel="noreferrer nofollow">Sinch</a> is an enterprise communications provider with particularly broad messaging-channel coverage.</p><p>The Sinch Conversation API connects fourteen messaging channels through one integration, including SMS, RCS, WhatsApp, Facebook Messenger, and other regional or social channels. Sinch also provides voice, verification, and related engagement products.</p><p>Pricing varies by destination, channel, sender, carrier, volume, and configuration. That structure is normal for global messaging, but it makes a single headline rate unhelpful for procurement.</p><p><strong>Why it ranks ninth:</strong> Sinch becomes a strong candidate when RCS, WhatsApp, global messaging reach, and channel fallback matter more than custom video-room depth.</p><p><strong>Best for:</strong> Transactional messaging, authentication, customer care, RCS campaigns, WhatsApp workflows, and globally distributed enterprise messaging.</p><p><strong>Main limitation:</strong> Developers building a highly customised media product may find the platform less RTC-focused than VideoSDK, Agora, or Daily.</p><p><strong>Compared with VideoSDK:</strong> Sinch is stronger for outbound and omnichannel customer messaging. VideoSDK is stronger for synchronous communication occurring inside an application.</p><h3 id="10-infobip-best-for-enterprise-customer-engagement">10. Infobip: Best for Enterprise Customer Engagement</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-06-at-7.21.00-PM-1.png" class="kg-image" alt="Top 10 Communication API Platforms: Expert Reviewed & Ranked" loading="lazy" width="2892" height="1632"/></figure><p><a href="https://www.infobip.com/" rel="noreferrer nofollow">Infobip</a> provides a broad communications portfolio covering SMS, email, voice, WhatsApp, RCS, video, numbers, and customer-engagement tooling.</p><p>Its <a href="https://www.infobip.com/pricing" rel="noreferrer nofollow">public pricing page</a> uses pay-as-you-go calculators for destination-sensitive channels and confirms WebRTC support through JavaScript, Android, and iOS SDKs. Calls APIs add backend orchestration for advanced scenarios.</p><p><strong>Why it ranks tenth:</strong> Infobip suits large organisations that want programmable channels and packaged engagement software from the same vendor.</p><p><strong>Best for:</strong> Enterprise notifications, marketing, customer service, global messaging, contact centres, authentication, and complex multi-channel journeys.</p><p><strong>Main limitation:</strong> The product catalogue is broad. A development team must identify which API, application layer, SDK, and billing unit belongs to each workflow.</p><p><strong>Compared with VideoSDK:</strong> Infobip is the stronger match for broad external customer engagement. VideoSDK offers a more concentrated development path for the in-product RTC experience.</p><h2 id="notable-communication-api-platform-alternatives">Notable Communication API Platform Alternatives</h2><p>Several strong products missed the top ten because the ranking balances RTC depth with broad communication coverage.</p><ul><li><strong>LiveKit</strong> is a strong choice for teams that need open-source, self-hostable WebRTC infrastructure and can operate the media stack.</li><li><strong>100ms</strong> merits evaluation for role-based rooms, virtual events, classrooms, and interactive video workflows.</li><li><strong>ZEGOCLOUD</strong> is relevant to gaming, social audio, live commerce, and teams that need Unity or Unreal support.</li><li><strong>Whereby Embedded</strong> fits web-first teams seeking a fast path to embedded meetings with a ready interface.</li><li><strong>Amazon Chime SDK</strong> suits organisations that want RTC services closely integrated with AWS infrastructure and billing.</li></ul><p>These products may outrank a listed provider under a narrower requirement. A platform shortlist should follow the primary user interaction, not a generic market order.</p><h2 id="which-communication-api-platform-should-you-choose">Which Communication API Platform Should You Choose?</h2><p>The right communication API platform matches the interaction your users perform most often and the SDK your team will ship.</p><h3 id="use-case-decision-matrix">Use-Case Decision Matrix</h3>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Product requirement</th>
<th>Shortlist</th>
<th>Why</th>
<th>Architecture note</th>
</tr>
</thead>
<tbody>
<tr>
<td>Embedded video across web and native clients</td>
<td>VideoSDK, Agora, Daily, Vonage</td>
<td>Deep room and media controls</td>
<td>Validate exact SDK feature parity</td>
</tr>
<tr>
<td>Interactive live commerce or events</td>
<td>VideoSDK, Agora, Stream</td>
<td>Low-latency host and audience models</td>
<td>Separate speakers from passive viewers</td>
</tr>
<tr>
<td>SMS, WhatsApp, voice, email, and verification</td>
<td>Twilio, Sinch, Infobip, Vonage</td>
<td>Broad external communication channels</td>
<td>Model destination and carrier fees</td>
</tr>
<tr>
<td>Chat-led marketplace or community</td>
<td>Sendbird, Stream</td>
<td>Messaging identities, moderation, call escalation</td>
<td>Price chat and media together</td>
</tr>
<tr>
<td>SIP, phone numbers, and call routing</td>
<td>Telnyx, Twilio, Vonage</td>
<td>Telecom control and PSTN reach</td>
<td>Keep media and telephony responsibilities explicit</td>
</tr>
<tr>
<td>Open-source or self-hosted RTC</td>
<td>LiveKit</td>
<td>Infrastructure ownership</td>
<td>Budget for TURN, global routing, observability, and operations</td>
</tr>
<tr>
<td>In-app RTC plus external messaging</td>
<td>VideoSDK plus a CPaaS</td>
<td>Best-of-breed media and telecom</td>
<td>Coordinate identity, webhooks, consent, and audit data in your backend</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h3 id="a-six-step-selection-process">A Six-Step Selection Process</h3><ol><li><strong>Identify the primary interaction.</strong> Decide whether users mainly join an in-app call, watch an interactive stream, send messages, receive phone calls, or move through a cross-channel journey.</li><li><strong>Separate required and optional channels.</strong> A telehealth launch may require video, recording, transcription, and waiting-room controls. SMS reminders can remain a separate, optional layer.</li><li><strong>Test the SDK you will ship.</strong> Evaluate the exact React, Flutter, iOS, Android, Unity, or backend SDK. Never assume every provider offers feature parity across platforms.</li><li><strong>Model a production month.</strong> Include participant minutes, media type, resolution, recordings, storage, transcription, phone numbers, message segments, carrier charges, active users, support, and compliance.</li><li><strong>Validate production controls.</strong> Check token scope, encryption, regional routing, reconnection, network adaptation, webhooks, moderation, analytics, logs, support SLAs, and required compliance agreements.</li><li><strong>Build a vertical slice.</strong> Create one complete user journey, including authentication, room creation, two participants, poor-network testing, recording, disconnect handling, logs, and usage review.</li></ol><h3 id="communication-api-pricing-example">Communication API Pricing Example</h3><p>Consider 1,000 monthly telehealth sessions with a patient, clinician, and interpreter. Each session lasts 20 minutes, producing 60,000 participant minutes.</p><p>At VideoSDK's current $0.004 video rate, the base media cost is $240. Recording all 20,000 session minutes at $0.015 per recorded minute adds $300.</p><p>The example totals $540 before the $20 introductory credit, storage, transcription, support, or taxes. It shows why a headline participant rate cannot represent the complete production bill.</p><p>Repeat this model using every shortlisted provider's billing rules. Some charge recordings per participant, while others charge by wall-clock recording minute or composed output.</p><h2 id="can-videosdk-work-with-another-cpaas">Can VideoSDK Work With Another CPaaS?</h2><p>VideoSDK can pair with a telecom-focused CPaaS when an application needs rich in-app media and external communication channels.</p><p>A practical division of responsibility looks like this:</p><ul><li><strong>VideoSDK:</strong> Video rooms, audio rooms, interactive live streaming, media tracks, participant roles, recordings, transcription, and RTC analytics.</li><li><strong>Twilio, Vonage, Telnyx, Sinch, or Infobip:</strong> SMS, WhatsApp, phone numbers, PSTN calls, verification, RCS, or email.</li><li><strong>Application backend:</strong> Identity, room creation, token generation, scheduling, consent, business rules, webhooks, analytics, and audit records.</li></ul><p>A telehealth platform could send an SMS reminder through Twilio, let the patient join a VideoSDK room, record the consultation with consent, and send a follow-up message.</p><p>This hybrid design prevents a team from accepting weaker media controls solely to obtain SMS. It also avoids adopting an oversized CPaaS when the product mainly needs real-time video.</p><h2 id="glossary">Glossary</h2><blockquote><strong>CPaaS:</strong> A cloud platform exposing programmable channels such as voice, messaging, verification, email, and sometimes video through APIs and SDKs.</blockquote><blockquote><strong>WebRTC:</strong> A standardised set of browser APIs and supporting protocols for real-time audio, video, and data exchange between connected endpoints.</blockquote><blockquote><strong>SFU:</strong> A media server that receives participant streams and selectively forwards suitable tracks or quality layers without mixing every stream into one output.</blockquote><blockquote><strong>Participant minute:</strong> One participant connected for one minute. A ten-minute call with four participants normally creates forty participant minutes.</blockquote><blockquote><strong>Media track:</strong> An individual audio, camera, screen-share, or processed-media stream published by a participant.</blockquote><blockquote><strong>Interactive live streaming:</strong> A low-latency format where viewers can interact immediately or move into active speaker roles.</blockquote><blockquote><strong>Meeting token:</strong> A signed credential that authorises a participant to enter a room and perform permitted actions.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>VideoSDK ranks first for RTC-first products requiring embedded video, audio, interactive live streaming, and broad client-platform coverage.</li><li>Twilio ranks highest for developers who value communication-channel breadth across messaging, telephony, email, verification, and video.</li><li>Vonage offers a balanced combination of established telecom APIs and mature embedded video.</li><li>Agora and Daily remain strong alternatives for specialised real-time media products.</li><li>Sendbird and Stream fit applications where chat, community, or social engagement carries equal importance.</li><li>Telnyx, Sinch, and Infobip become stronger as carrier control, RCS, WhatsApp, and enterprise messaging gain priority.</li><li>A hybrid VideoSDK plus CPaaS architecture often produces cleaner responsibilities than forcing one vendor to serve every channel.</li></ul><h2 id="what-is-the-best-communication-api-platform">What Is the Best Communication API Platform?</h2><p>VideoSDK is the best communication API platform for this ranking's main use case: embedded video, audio, and interactive live communication across multiple client platforms.</p><p>Choose Twilio for the broadest programmable channel mix, Vonage for balanced CPaaS and video, and Agora or Daily for specialised RTC requirements.</p><p>Choose Sendbird or Stream when chat and social components matter equally. Choose Telnyx, Sinch, or Infobip when telecom connectivity or omnichannel engagement is the primary problem.</p><h2 id="conclusion">Conclusion</h2><p>A communication API platform should remove infrastructure work without forcing your product into the wrong communication model. VideoSDK is the strongest fit here for embedded RTC, while telecom-first providers remain better for broad external channels.</p><p>Start with your core user interaction, test the exact SDK, and model a real production month. Explore the <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">VideoSDK Prebuilt quickstart</a> or <a href="https://app.videosdk.live/login">create a free VideoSDK account</a> to validate your architecture.</p><p>What are you building with communication APIs? Share the channels, client platforms, and production constraints shaping your shortlist.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-best-communication-api-platform-for-developers">What is the best communication API platform for developers?</h3><p>The best communication API platform depends on the product's primary interaction. VideoSDK leads this RTC-weighted ranking for embedded video, audio, and interactive streaming, while Twilio fits broader messaging and telephony needs.</p><h3 id="is-videosdk-a-cpaas-platform">Is VideoSDK a CPaaS platform?</h3><p>VideoSDK is a specialised communication API platform focused on real-time video, audio, interactive live streaming, recording, transcription, room orchestration, and SIP connectivity. It is not a complete bulk SMS or email platform.</p><h3 id="which-communication-api-is-best-for-video-calling">Which communication API is best for video calling?</h3><p>VideoSDK, Agora, Daily, Twilio Video, and Vonage Video are credible video-calling choices. VideoSDK stands out when teams need broad client SDK coverage, custom and Prebuilt paths, and interactive streaming through a related room model.</p><h3 id="what-is-the-difference-between-cpaas-and-webrtc">What is the difference between CPaaS and WebRTC?</h3><p>CPaaS is a commercial platform category covering programmable communication channels. WebRTC is a technical standard for real-time audio, video, and data. An RTC provider may use WebRTC while adding signalling, TURN, SFUs, recording, security, analytics, and SDKs.</p><h3 id="can-videosdk-be-used-with-twilio-or-telnyx">Can VideoSDK be used with Twilio or Telnyx?</h3><p>Yes. VideoSDK can handle in-app real-time media while Twilio or Telnyx manages SMS, phone numbers, PSTN calls, SIP, or verification. Your backend should coordinate identities, tokens, rooms, webhooks, consent, and business workflows.</p><h3 id="how-much-does-a-communication-api-platform-cost">How much does a communication API platform cost?</h3><p>Communication API costs depend on participant minutes, messages, carrier fees, phone numbers, recordings, storage, transcription, active users, support, and compliance. Build a model from one production month rather than comparing only headline rates.</p><h3 id="what-should-i-check-before-selecting-a-communication-api-platform">What should I check before selecting a communication API platform?</h3><p>Check the exact SDK, required channels, participant limits, token security, recording controls, network adaptation, regional availability, compliance support, analytics, pricing units, and migration options. A production-like proof of concept provides stronger evidence than a feature matrix.</p>]]></content:encoded></item><item><title><![CDATA[Build ESP32 Video & Audio Calling With VideoSDK]]></title><description><![CDATA[Build real-time ESP32 video calling with VideoSDK's IoT SDK. Join a browser and an ESP32-S3 into the same WebRTC room]]></description><link>https://www.videosdk.live/blog/esp32-video-calling-videosdk-iot-sdk</link><guid isPermaLink="false">6a709f73b3240feb748c9335</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[WebRTC]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 04 Aug 2026 13:10:12 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/IoT-SDK-3.png" medium="image"/><content:encoded><![CDATA[<blockquote>ESP32 video calling runs two-way WebRTC audio and video directly on an ESP32-S3 microcontroller. The VideoSDK IoT SDK ships as an ESP-IDF component that joins your board to the same VideoSDK room a browser joins, with no signaling server of your own. Set a token, flash the firmware, and join from the web.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/IoT-SDK-3.png" alt="Build ESP32 Video & Audio Calling With VideoSDK"/><p>Until recently, ESP32 video calling meant building, hosting, and maintaining your own signaling and media backend before a single frame moved. The VideoSDK IoT SDK cuts out that infrastructure. It provides a native ESP-IDF component that hooks an ESP32-S3 directly into a WebRTC room, the exact same room a browser or mobile app joins.</p><p>Your board streams camera and microphone input into the room, and on boards with a screen and speaker, it draws remote video on the LCD and plays remote audio back. By the end of this guide you will have an ESP32-S3 holding a live video and audio call with a web application, without managing a custom media server.</p><h2 id="what-is-esp32-video-calling">What Is ESP32 Video Calling?</h2><p>ESP32 video calling is defined as real-time, two-way audio and video streaming that originates and terminates on an ESP32 microcontroller rather than on a phone or laptop. It works by capturing frames from an onboard camera and samples from a microphone, encoding them on-device, and publishing them over WebRTC to every other participant in a room.</p><p>The&nbsp;<a href="https://components.espressif.com/components/videosdk/iot-sdk">VideoSDK IoT SDK</a>&nbsp;provides this capability as a native ESP-IDF component for the ESP32-S3 family, published on Espressif's official component registry under the MIT license. It handles the room connection logic, WebRTC encryption (DTLS and SRTP), and media stream lifecycle, so your firmware manages calls through a handful of function calls.</p><p>The board is a first-class participant, not a camera feeding a gateway. It appears in the participant list, it can be muted, and it shares the same room ID your&nbsp;<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React</a>&nbsp;or JavaScript client already uses.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/architecture.png" class="kg-image" alt="Build ESP32 Video & Audio Calling With VideoSDK" loading="lazy" width="1672" height="941"/></figure><h2 id="what-you-need-before-you-start">What You Need Before You Start</h2><p>The board you choose decides whether your device can only send media or handle full two-way playback, so pick it before writing any code.</p><table>
<thead>
<tr>
<th>Board</th>
<th>Send (Mic &amp; Camera)</th>
<th>Receive (Speaker &amp; LCD)</th>
<th>Hardware Detail</th>
</tr>
</thead>
<tbody>
<tr>
<td>XIAO ESP32-S3 (Sense)</td>
<td>Yes</td>
<td>No</td>
<td>Includes camera &amp; mic, but lacks onboard display &amp; speaker</td>
</tr>
<tr>
<td>ESP32-S3-Korvo-2 v3.0</td>
<td>Yes</td>
<td>Yes</td>
<td>Includes camera, mic, LCD, and speaker for full two-way A/V</td>
</tr>
</tbody>
</table>
<p>On the XIAO board, calling&nbsp;<code>startSubscribeVideo()</code>&nbsp;or&nbsp;<code>startSubscribeAudio()</code>&nbsp;returns&nbsp;<code>DEVICE_NOT_SUPPORTED</code>. That is expected behavior for missing hardware, not a bug. Pick the Korvo-2 if you want the board itself to display and play back the far end.</p><p>Prerequisites:</p><ul><li><a href="https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/get-started/index.html"><strong>ESP-IDF 5.4.4 or newer</strong></a>&nbsp;with the environment exported. The component declares 5.4.4 as its minimum.</li><li><strong>Python 3.11+</strong>, required by the ESP-IDF build tools.</li><li><strong>8 MB of flash and PSRAM</strong>&nbsp;on the board. The application image does not fit in 4 MB.</li><li>A&nbsp;<strong>VideoSDK account</strong>&nbsp;for your API key, secret, and room tokens.</li></ul><h2 id="how-esp32-video-calling-works-under-the-hood">How ESP32 Video Calling Works Under the Hood</h2><p>Running WebRTC on an ESP32 is a memory problem before it is a CPU problem. The WebRTC stack, the DTLS handshake state, video frames, and audio buffers all compete for internal SRAM, which is why supported boards carry external PSRAM and why the SDK depends on it for stable operation.</p><p>WebRTC security runs end to end. The device performs a DTLS handshake and transmits media over encrypted SRTP streams, the same transport a browser uses.</p><p>Receiving is where the SDK saves the most work. Publishing is comparatively simple, but subscribing means decoding incoming video and audio, absorbing network jitter, drawing to an LCD, and driving speaker hardware in real time inside tight SRAM limits. On the ESP32-S3-Korvo-2, the publish and subscribe calls for both audio and video run concurrently.</p><p>Wi-Fi quality shows up directly in frame rate and audio clarity. Keep the antenna clear, connect to 2.4 GHz, and test on the network the hardware will actually run on in production.</p><h3 id="when-not-to-use-the-iot-sdk">When Not to Use the IoT SDK</h3><p>Espressif ships its own&nbsp;<a href="https://github.com/espressif/esp-webrtc-solution">esp-webrtc-solution</a>, and it wins in a specific case: you already run your own signaling server and media infrastructure, or you need to peer directly with a device that is not in a VideoSDK room. The IoT SDK assumes VideoSDK rooms and VideoSDK tokens, which is exactly the assumption that removes the backend work. If you want the board on an existing SFU you operate yourself, the managed path is the wrong trade.</p><h2 id="step-1-set-up-the-esp-idf-environment">Step 1: Set Up the ESP-IDF Environment</h2><p>Install Espressif's ESP-IDF toolchain. The commands below cover macOS; see the official&nbsp;<a href="https://docs.espressif.com/projects/esp-idf/en/stable/esp32s3/get-started/index.html">ESP-IDF getting started guide</a>&nbsp;for Linux and Windows.</p><p>Install build dependencies:</p><pre><code class="language-bash">brew install cmake ninja dfu-util ccache git wget flex bison gperf
brew install openssl libffi
</code></pre><p>Clone ESP-IDF at v5.4.4 or newer and run the installer. Older branches will not build this component:</p><pre><code class="language-bash">mkdir -p ~/esp &amp;&amp; cd ~/esp
git clone --recursive -b v5.4.4 https://github.com/espressif/esp-idf.git
cd esp-idf
./install.sh esp32s3
</code></pre><p>Export the environment variables into your shell session:</p><pre><code class="language-bash">source ~/esp/esp-idf/export.sh
</code></pre><h2 id="step-2-generate-your-videosdk-token">Step 2: Generate Your VideoSDK Token</h2><p>VideoSDK uses token-based authentication. For building and testing you do not need a signing server: the dashboard generates a token for you in about a minute.</p><ol><li>Open the&nbsp;<a href="https://dub.sh/X5Fn46e?utm_source=esp32-video-calling-videosdk-iot-sdk">VideoSDK dashboard</a>&nbsp;and sign up or log in.</li><li>Copy your&nbsp;<strong>API key</strong>&nbsp;and&nbsp;<strong>secret</strong>.</li><li>Generate a&nbsp;<strong>temporary token</strong>&nbsp;and save it.</li></ol><p>You also need a room (meeting) ID, and the order here matters. The React client in Step 7 mints one for you when you click&nbsp;<strong>New Meeting</strong>, and that is the ID you flash onto the board.</p><p>Firmware is harder to rotate than a web bundle, so a long-lived token flashed into a device is a liability. The&nbsp;<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token">VideoSDK authentication and token guide</a>&nbsp;covers token lifetimes and permission scopes.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-03-at-7.28.34-PM.png" class="kg-image" alt="Build ESP32 Video & Audio Calling With VideoSDK" loading="lazy" width="2930" height="1760"/></figure><h2 id="step-3-create-the-project-from-the-example">Step 3: Create the Project From the Example</h2><p>Fetch the project structure from the official&nbsp;<a href="https://components.espressif.com/components/videosdk/iot-sdk"><code>video_call</code></a>&nbsp;example, then extend it to carry audio as well.</p><pre><code class="language-bash">idf.py create-project-from-example "videosdk/iot-sdk=0.3.1:video_call"
</code></pre><p>The stock&nbsp;<code>video_call</code>&nbsp;example captures camera input and draws incoming video on supported hardware such as the ESP32-S3-Korvo-2, running with&nbsp;<code>videoCodec = VIDEO_CODEC_JPEG</code>. Step 5 adds the audio streams.</p><h2 id="step-4-configure-the-build">Step 4: Configure the Build</h2><p>Set the target chip to&nbsp;<code>esp32s3</code>&nbsp;and open menuconfig to enter credentials and Wi-Fi settings.</p><pre><code class="language-bash">idf.py set-target esp32s3
idf.py menuconfig
</code></pre><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-08-03-at-7.30.00-PM.png" class="kg-image" alt="Build ESP32 Video & Audio Calling With VideoSDK" loading="lazy" width="2498" height="1808"/></figure><p>In the menuconfig interface:</p><ul><li><strong>Microcontroller board:</strong>&nbsp;Select&nbsp;<code>ESP32-S3-Korvo-2</code>&nbsp;or&nbsp;<code>ESP32-S3-XIAO</code>&nbsp;(XIAO is the default).</li><li><strong>VideoSDK Configuration:</strong>&nbsp;Paste the token and the meeting / room ID. If you are following the repo flow, get the room ID from the React client in Step 7 first, then come back here.</li><li><strong>Example Connection Configuration:</strong>&nbsp;Enter your 2.4 GHz Wi-Fi SSID and password.</li><li><strong>Flash and Partitions:</strong>&nbsp;Set flash size to 8 MB and keep the partition table the example ships.</li></ul><p>Keep&nbsp;<code>sdkconfig</code>&nbsp;out of public repositories. It holds your Wi-Fi credentials and your VideoSDK token in plain text.</p><h2 id="step-5-understand-the-code">Step 5: Understand the Code</h2><p>The firmware flow connects to Wi-Fi, fills an&nbsp;<code>init_config_t</code>&nbsp;structure, calls&nbsp;<code>init()</code>, and starts the media streams. The example ships as a video-only call, so its&nbsp;<code>app_main</code>&nbsp;sets only the video codec and starts only the two video streams:</p><pre><code class="language-c">#include "videosdk.h"
#include "sdkconfig.h"

void app_main(void)
{
    // Initialize NVS, network interfaces, event loops, and Wi-Fi...

    init_config_t cfg = {
        .meetingID     = CONFIG_VIDEOSDK_MEETING_ID,
        .token         = CONFIG_VIDEOSDK_TOKEN,
        .displayName   = "ESP32S3-AV-Device",
        .participantId = "",               
        .audioCodec    = AUDIO_CODEC_PCMA,
        .videoCodec    = VIDEO_CODEC_JPEG, // Video only, as shipped
    };

    if (init(&amp;cfg) != RESULT_OK) {
        return;
    }

    startPublishVideo();     // Stream the onboard camera
    startSubscribeVideo();   // Draw to the LCD (Korvo-2 only)

    while (1) {
        vTaskDelay(pdMS_TO_TICKS(10));
    }
}
</code></pre><p>To turn this into a full audio and video call, add audio yourself. It is just one change.  start the two audio streams alongside the video ones:</p><pre><code class="language-c">    init_config_t cfg = {
        .meetingID     = CONFIG_VIDEOSDK_MEETING_ID,
        .token         = CONFIG_VIDEOSDK_TOKEN,
        .displayName   = "ESP32S3-AV-Device",
        .participantId = "",
        .audioCodec    = AUDIO_CODEC_PCMA,
        .videoCodec    = VIDEO_CODEC_JPEG,
    };

    // ...after init() returns RESULT_OK:

    startPublishAudio();     // Add: stream the onboard microphone
    startPublishVideo();
    startSubscribeAudio();   // Add: play to the speaker (Korvo-2 only)
    startSubscribeVideo();
</code></pre><p>That gives you all four streams for full A/V. Every SDK function returns a&nbsp;<code>result_t</code>&nbsp;status code, where&nbsp;<code>RESULT_OK</code>&nbsp;equals&nbsp;<code>0</code>. On send-only hardware like the XIAO,&nbsp;<code>startSubscribeAudio()</code>&nbsp;returns&nbsp;<code>DEVICE_NOT_SUPPORTED</code>, which is expected. Check return codes in production firmware rather than assuming the stream came up.</p><h2 id="step-6-build-flash-and-verify-the-join">Step 6: Build, Flash, and Verify the Join</h2><p>Compile the firmware, flash the board, and open the serial monitor:</p><pre><code class="language-bash">idf.py build
idf.py -p &lt;PORT&gt; flash monitor
</code></pre><p>A successful boot and room join produces this sequence. Values are redacted; yours will show your own network details:</p><pre><code class="language-text">I (20151) wifi:connected with &lt;YOUR_SSID&gt;, aid = 7, channel 7, BW20, bssid = &lt;REDACTED&gt;
I (20152) wifi:security: WPA2-PSK, phy: bgn, rssi: -49
I (21194) esp_netif_handlers: example_netif_sta ip: &lt;LOCAL_IP&gt;, mask: 255.255.255.0
I (21205) example_common: Connected to example_netif_sta
I (21211) IOT-SDK-AUDIO: Device ID: e-ccba970e9220
I (21215) videosdk: participantId (peerId): e-ccba970e9220
I (21256) IOT-SDK-AUDIO: init: 0
I (23312) protoo: decrypted 4 ICE server(s)
I (23313) protoo: connecting websocket to in1.rm.videosdk.live
I (23562) esp-x509-crt-bundle: Certificate validated
I (24094) protoo: websocket connected
I (24113) protoo: protoo client ready (peerId=e-ccba970e9220)
I (26178) videosdk: using 1 STUN server(s) for ICE
I (29220) peer: Created inbound SRTP session
I (29220) peer: Created outbound SRTP session
I (29474) videosdk: DataChannel transport up (ICE+DTLS)
I (29534) videosdk: SCTP data channel connected after 60 ms
I (29807) videosdk: audio RTP producer id=4bb13f4c-b453-4445-8924-ab09215dfd1b
I (29807) videosdk: bringing up mic
Result:0
</code></pre><p>The two lines that matter are&nbsp;<code>Created outbound SRTP session</code>&nbsp;and the&nbsp;<code>RTP producer id</code>. Together they confirm the DTLS handshake completed and the board is publishing. A few&nbsp;<code>example_connect: Wi-Fi disconnected, trying to reconnect...</code>&nbsp;lines before the association are normal on a busy 2.4 GHz channel.</p><h2 id="step-7-join-the-same-room-from-a-react-app">Step 7: Join the Same Room From a React App</h2><p>Nothing about the web side is ESP32-specific, which is the point: the board is just another participant. VideoSDK publishes a companion repository,&nbsp;<a href="https://github.com/videosdk-live/videosdk-rtc-iot-sdk-example">videosdk-live/videosdk-rtc-iot-sdk-example</a>, that carries the firmware under&nbsp;<code>IoT/</code>&nbsp;and two ready-to-run browser clients under&nbsp;<code>web/js</code>&nbsp;(vanilla JavaScript) and&nbsp;<code>web/react</code>. Both talk to the same room, so pick whichever matches your stack. This guide uses the React client.</p><p>Clone the repository and install the client:</p><pre><code class="language-bash">git clone https://github.com/videosdk-live/videosdk-rtc-iot-sdk-example.git
cd videosdk-rtc-iot-sdk-example/web/react
npm install
</code></pre><p>Create the environment file and drop in the token from Step 2:</p><pre><code class="language-bash">cp .env.example .env
</code></pre><pre><code class="language-text">REACT_APP_VIDEOSDK_TOKEN=&lt;your token&gt;
</code></pre><p>The token must carry the&nbsp;<code>allow_join</code>&nbsp;permission. Create React App inlines&nbsp;<code>.env</code>&nbsp;at build time, so restart the dev server after any change to it, otherwise you will keep authenticating with the old value and blame the board.</p><pre><code class="language-bash">npm start
</code></pre><p>The app comes up on&nbsp;<code>http://localhost:3000</code>. Browsers only grant camera and microphone access on a secure context, and&nbsp;<code>localhost</code>&nbsp;counts as one, so no TLS setup is needed for local development.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/join-screen.png" class="kg-image" alt="Build ESP32 Video & Audio Calling With VideoSDK" loading="lazy" width="2930" height="1760"/></figure><p>Click&nbsp;<strong>New Meeting</strong>. The app creates the room and shows you the meeting ID. That ID goes into&nbsp;<code>idf.py menuconfig</code>&nbsp;under&nbsp;<strong>VideoSDK Configuration &gt; Meeting / room ID</strong>&nbsp;back in Step 4. Reflash the board, and once it joins, the ESP32-S3 appears as its own video tile under the&nbsp;<code>displayName</code>&nbsp;you set in Step 5.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/meeting.png" class="kg-image" alt="Build ESP32 Video & Audio Calling With VideoSDK" loading="lazy" width="1947" height="1080"/></figure><h3 id="what-the-react-client-adds-for-iot-participants">What the React Client Adds for IoT Participants</h3><p><code>MeetingView.js</code>&nbsp;is an ordinary VideoSDK meeting view built on the same hooks as the&nbsp;<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React SDK quickstart</a>, with no device-specific logic in it. Everything that knows about hardware lives in&nbsp;<code>src/iot</code>, which is a useful separation to copy if you are bolting device support onto an app you already have.</p>
<!--kg-card-begin: html-->
<table style="margin: 10px 0px 15px; border-collapse: collapse; border-spacing: 0px; display: block; width: 850px; overflow: auto; word-break: keep-all; color: rgb(51, 51, 51); font-family: &quot;Helvetica Neue&quot;, Helvetica, &quot;Segoe UI&quot;, Arial, freesans, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: normal; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial;"><thead><tr><th style="font-weight: 700; color: rgb(0, 0, 0); border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">Export</th><th style="font-weight: 700; color: rgb(0, 0, 0); border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">Purpose</th></tr></thead><tbody><tr><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;"><code style="font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 0.85em; color: rgb(0, 0, 0); background-color: rgb(240, 240, 240); border-radius: 3px; padding: 0.2em 0px;">&lt;IOTBridge /&gt;</code></td><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">The one piece that has to be mounted for device support to work</td></tr><tr><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;"><code style="font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 0.85em; color: rgb(0, 0, 0); background-color: rgb(240, 240, 240); border-radius: 3px; padding: 0.2em 0px;">&lt;IOTVideoPlayer participantId={id} /&gt;</code></td><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">Renders a device participant's video and audio</td></tr><tr><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;"><code style="font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 0.85em; color: rgb(0, 0, 0); background-color: rgb(240, 240, 240); border-radius: 3px; padding: 0.2em 0px;">useIOTMessages()</code></td><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">Hook for receiving messages sent from the board's data channel</td></tr><tr><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;"><code style="font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 0.85em; color: rgb(0, 0, 0); background-color: rgb(240, 240, 240); border-radius: 3px; padding: 0.2em 0px;">sendIOTMessage()</code></td><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">Sends a message to the device, 15 KiB maximum per message</td></tr><tr><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;"><code style="font-family: Menlo, Monaco, Consolas, &quot;Courier New&quot;, monospace; font-size: 0.85em; color: rgb(0, 0, 0); background-color: rgb(240, 240, 240); border-radius: 3px; padding: 0.2em 0px;">isIOTDevice()</code></td><td style="border: 1px solid rgb(214, 214, 214); padding: 6px 13px;">Tells a device participant apart from a browser participant</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><code>useIOTMessages()</code>&nbsp;and&nbsp;<code>sendIOTMessage()</code>&nbsp;are the browser half of the&nbsp;<code>setDataMessageHandler()</code>&nbsp;and&nbsp;<code>sendMessage()</code>&nbsp;calls from Step 5. That pairing is what turns a call into a control channel: stream the camera for the human, and send a JSON command over the same connection to move a servo or read a sensor, with no second transport to operate.</p><p>On a Korvo-2, this is also where the loop closes. Your browser webcam draws to the board's LCD and your voice plays through its speaker, while its camera and microphone come back to you in the tile.</p><h3 id="common-errors">Common Errors</h3><ul><li><strong><code>DEVICE_NOT_SUPPORTED</code>&nbsp;on a subscribe call:</strong>&nbsp;Expected on boards without LCD or speaker output, such as the XIAO. Use a Korvo-2 for playback on the device.</li><li><strong><code>INIT_NOT_CALLED</code>:</strong>&nbsp;A&nbsp;<code>start*</code>&nbsp;function ran before&nbsp;<code>init()</code>&nbsp;returned&nbsp;<code>RESULT_OK</code>. Check the&nbsp;<code>init()</code>&nbsp;return code before starting streams.</li><li><strong>Build fails or the image will not fit:</strong>&nbsp;Confirm ESP-IDF is on v5.4 or newer, flash size is set to 8 MB, and PSRAM is enabled for the selected board.</li><li><strong>Wi-Fi connects but the room join fails:</strong>&nbsp;Verify the room ID formatting and confirm the token carries&nbsp;<code>allow_join</code>&nbsp;permission and has not expired.</li><li><strong>Board joins but no media arrives:</strong>&nbsp;Confirm the browser used the same room ID, and check the serial log for&nbsp;<code>Created outbound SRTP session</code>. Its absence points at the DTLS handshake, usually a blocked UDP path on the network.</li></ul><h2 id="esp32-video-calling-glossary">ESP32 Video Calling Glossary</h2><blockquote><strong>Room:</strong>&nbsp;A VideoSDK meeting space identified by a unique room ID that participants join to share media streams. The ESP32-S3 and your browser join the same room ID, which is what makes them see each other.</blockquote><blockquote><strong>Participant:</strong>&nbsp;Any client connected to a room with its own audio and video streams. The IoT SDK registers the board as a participant with a&nbsp;<code>displayName</code>&nbsp;and a&nbsp;<code>participantId</code>.</blockquote><blockquote><strong>Meeting Token:</strong>&nbsp;A JWT authorizing a participant to join a room, generated from the VideoSDK dashboard for testing or minted server-side for production.</blockquote><blockquote><strong>SRTP:</strong>&nbsp;Secure Real-time Transport Protocol, the encrypted media transport WebRTC uses. The IoT SDK negotiates SRTP keys through a DTLS handshake, so board media is encrypted on the wire exactly as browser media is.</blockquote><blockquote><strong>ESP-IDF component:</strong>&nbsp;A reusable package in Espressif's IoT Development Framework, resolvable from the component registry. The VideoSDK IoT SDK ships as one, so&nbsp;<code>idf.py</code>&nbsp;pulls it in as a dependency rather than you vendoring source.</blockquote><h2 id="conclusion">Conclusion</h2><p>ESP32 video calling stops being an infrastructure project once the board can join a managed room directly. The IoT SDK reduces it to a token, a room ID, and four function calls, and the browser side is a repository you clone. The remaining engineering is where it should be: your product's camera placement, power budget, and reconnect behavior.</p><ul><li><strong>The example repo:</strong>&nbsp;<a href="https://github.com/videosdk-live/videosdk-rtc-iot-sdk-example">videosdk-live/videosdk-rtc-iot-sdk-example</a>, firmware plus React and JavaScript clients</li><li><strong>Free API keys:</strong>&nbsp;<a href="https://dub.sh/X5Fn46e?utm_source=esp32-video-calling-videosdk-iot-sdk">VideoSDK dashboard</a></li><li><strong>The component:</strong>&nbsp;<a href="https://components.espressif.com/components/videosdk/iot-sdk">videosdk/iot-sdk on the Espressif registry</a>, MIT licensed</li></ul><p>Flash it once and watching a microcontroller appear in a browser participant list is genuinely strange in a good way. What are you building with VideoSDK? Drop a comment, I would love to hear what kind of embedded calling use case you are working on.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="can-an-esp32-join-real-time-calls">Can an ESP32 join real-time calls?</h3><p>Yes. An ESP32-S3 running the VideoSDK IoT SDK connects directly to a VideoSDK room over WebRTC and streams video and audio with browsers, phones, and other devices in real time. The board is a full participant in the room, not a feed proxied through a gateway.</p><h3 id="which-esp32-boards-are-supported">Which ESP32 boards are supported?</h3><p>The IoT SDK targets the ESP32-S3 family. The XIAO ESP32-S3 (Sense) handles camera and microphone transmission, while the ESP32-S3-Korvo-2 v3.0 supports full two-way A/V with its integrated LCD and speaker driver.</p><h3 id="does-the-iot-sdk-use-standard-webrtc">Does the IoT SDK use standard WebRTC?</h3><p>Yes. The VideoSDK IoT SDK uses standard WebRTC protocols end to end, establishing encrypted SRTP media channels through DTLS handshakes.</p><h3 id="can-two-esp32-devices-call-each-other">Can two ESP32 devices call each other?</h3><p>Yes. Two-way interactive calling works when both ESP32 devices have media output hardware, such as two ESP32-S3-Korvo-2 boards equipped with speakers and displays. If a send-only board like the XIAO ESP32-S3 is used, it can publish its streams into the room but cannot receive or play back incoming media.</p><h3 id="why-does-the-esp32-send-jpeg-instead-of-h264">Why does the ESP32 send JPEG instead of H.264?</h3><p>JPEG compresses each frame independently, so it needs no reference frames and far less RAM than a video codec. On the supported boards the camera sensor emits JPEG directly, which keeps the ESP32-S3 out of the encoding path entirely.</p><h3 id="is-the-iot-sdk-free-to-use">Is the IoT SDK free to use?</h3><p>The IoT SDK component is open source under the MIT license. VideoSDK provides a free monthly credit tier covering room connectivity and media routing.</p><h2 id=""/>]]></content:encoded></item><item><title><![CDATA[Amazon IVS Pricing and Top 10 Alternatives Tested & Ranked]]></title><description><![CDATA[Compare Amazon IVS pricing with ten live streaming APIs using current public rates, normalised examples, regional costs, migration steps, and honest best-fit verdicts.]]></description><link>https://www.videosdk.live/blog/amazon-ivs-pricing-and-alternatives</link><guid isPermaLink="false">6a71905fb3240feb748c938a</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 04 Aug 2026 11:45:57 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-4--2026--02_33_58-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>Amazon IVS pricing uses two different models: channels charge input plus viewer output, while Real-Time stages charge every connected participant. VideoSDK ranks first here for interactive product experiences. Mux leads live-to-VOD workflows, and Cloudflare Stream offers simpler billing for passive broadcast. The cheapest option depends on architecture, region, watch time, and add-ons.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-4--2026--02_33_58-PM.png" alt="Amazon IVS Pricing and Top 10 Alternatives Tested & Ranked"/><p><a href="https://aws.amazon.com/ivs/" rel="noreferrer nofollow">Amazon IVS</a> pricing looks straightforward until audience location, playback resolution, average watch time, chat, recording, and composition appear on the same bill. A small modelling error can multiply across thousands of viewers.</p><p>This guide compares ten live streaming APIs using current public pricing, latency model, developer tooling, operational control, and product fit. It covers live streaming only, not general video-calling platforms without a credible broadcast or <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">interactive streaming API</a>.</p><p>The evaluation prioritises VideoSDK where audience participation is central. It also identifies cases where Amazon IVS, Mux, Agora, 100ms, LiveKit, Cloudflare Stream, or self-hosted infrastructure is the more rational choice.</p><p><em>Pricing and product documentation checked on 3 August 2026. Public prices exclude taxes, negotiated discounts, premium support, and unlisted enterprise commitments.</em></p><h2 id="what-is-amazon-ivs">What Is Amazon IVS?</h2><p>Amazon Interactive Video Service (Amazon IVS) is a managed live streaming platform from AWS. It provides APIs and SDKs for building low-latency broadcasts and real-time interactive video experiences into websites, mobile applications, and other digital products.</p><p>Amazon IVS offers two main streaming architectures:</p><h3 id="low-latency-channel-billing">Low-Latency channel billing</h3><p>Amazon IVS Low-Latency channels accept <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMPS</a> or <a href="https://www.videosdk.live/developer-hub/rtmp/implementing-srt-streaming-developers-guide" rel="noreferrer">SRT</a> input and deliver <a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer">HLS</a> playback. AWS documents typical latency of three to five seconds when its player is used.</p><p>Input depends on channel type. Current public hourly rates are $2.00 for Standard, $0.50 for Standard Multitrack, $0.85 for Advanced HD, $0.50 for Advanced SD, and $0.20 for Basic.</p><p>Output is the larger variable for audience-heavy events. For the first 10,000 North American hours, Full HD output costs $0.144 per delivered viewer-hour, while HD costs $0.072.</p><h3 id="real-time-stage-billing">Real-Time stage billing</h3><p>Amazon IVS Real-Time stages use <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> and bill each connected host or viewer by participant-hour. AWS documents latency below 300 milliseconds for this mode.</p><p>The first 10,000 North American participant-hours cost $0.072 each, with audio-only usage priced at one-tenth of the standard rate. Both hosts and viewers count.</p><p>Server-side composition adds $0.15 per SD rendition-hour, $0.30 for HD, or $0.60 for Full HD. Sending the composition into an IVS channel then adds normal channel input and output charges.</p><p>Amazon IVS also supports features such as recording, server-side composition, chat, private channels, timed metadata, and integration with other AWS services. Because channels and stages use different delivery technologies and billing units, understanding the required streaming architecture is essential before comparing Amazon IVS pricing with alternative live streaming APIs.</p><h2 id="is-amazon-ivs-free-to-use">Is Amazon IVS Free to Use?</h2><p>Amazon IVS has free allowances, but eligibility depends on when and how the AWS account was created. Production forecasts should therefore use standard rates.</p><p>AWS currently publishes monthly allowances for new customers during their first 12 months: five Basic channel input hours, 100 audio-only or SD output hours, 20 participant-hours, five composition hours, and chat-message allowances.</p><p>The same page also states that customers signing up from 15 July 2025 can receive up to $200 in AWS Free Tier credits. The free plan lasts six months, and credits must be used within 12 months.</p><p>Treat those offers as onboarding support, not steady-state economics. Confirm eligibility inside the AWS account because the applicable plan, remaining credit, and offer terms can differ.</p><h2 id="how-much-does-amazon-ivs-pricing-cost">How Much Does Amazon IVS Pricing Cost?</h2><p>Amazon IVS can cost $72.07 or $146 for the same one-hour, 1,001-person event because stages and channels measure different resources.</p><p>Assume one host, 1,000 viewers, 60 minutes, full attendance, North American billing, and Full HD delivery. Exclude chat, recording, taxes, support, composition, and discounts.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Architecture</th>
<th style="text-align:right">Public-rate calculation</th>
<th style="text-align:right">Estimated cost</th>
</tr>
</thead>
<tbody>
<tr>
<td>IVS Standard Low-Latency, Full HD</td>
<td style="text-align:right">1 input hour × $2.00 + 1,000 output hours × $0.144</td>
<td style="text-align:right"><strong>$146.00</strong></td>
</tr>
<tr>
<td>IVS Standard Multitrack, Full HD</td>
<td style="text-align:right">1 input hour × $0.50 + 1,000 output hours × $0.144</td>
<td style="text-align:right"><strong>$144.50</strong></td>
</tr>
<tr>
<td>IVS Real-Time stage</td>
<td style="text-align:right">1,001 participant-hours × $0.072</td>
<td style="text-align:right"><strong>$72.07</strong></td>
</tr>
<tr>
<td>VideoSDK interactive live stream</td>
<td style="text-align:right">60 speaker-minutes × $0.004 + 60,000 viewer-minutes × $0.002</td>
<td style="text-align:right"><strong>$120.24</strong></td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>VideoSDK costs 17.6 percent less than an IVS Standard Full HD channel in this scenario. Amazon IVS Real-Time costs less than VideoSDK for the same nominal attendance.</p><p>That result is not contradictory. The IVS channel supports broadcast delivery at very large scale, while the stage and VideoSDK rows describe real-time participation with different limits and feature assumptions.</p><p>Average watch time often matters more than registrations. If the 1,000 viewers watch only 30 minutes, the IVS Standard estimate falls to $74, before any additional services.</p><h3 id="amazon-ivs-pricing-formula">Amazon IVS pricing formula</h3><p>For a Low-Latency channel, use this baseline:</p><pre><code class="language-text">monthly cost = channel input cost
             + tiered viewer output cost
             + chat
             + storage and delivery of recordings
             + MediaTailor ad insertion, if used
</code></pre><p>For a Real-Time stage, start here:</p><pre><code class="language-text">monthly cost = tiered participant-hour cost
             + server-side composition, if used
             + channel input and output, if the stage feeds a channel
             + S3 recording and delivery
             + chat
</code></pre><p>The accompanying calculator widget applies AWS tier thresholds and the current regional rates. It estimates one resolution at a time, so model mixed adaptive-bitrate playback as separate audience groups.</p><h2 id="amazon-ivs-pricing-by-region">Amazon IVS Pricing by Region</h2><p>Amazon IVS pricing uses the location of the servers serving each viewer or participant, not the channel or stage creation region.</p><p>The table shows the first monthly tier. Low-latency figures represent Full HD viewer output, while Real-Time figures represent standard participant-hours. Add channel input separately.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Billing region</th>
<th style="text-align:right">Low-Latency Full HD per viewer-hour</th>
<th style="text-align:right">Real-Time per participant-hour</th>
<th style="text-align:right">1,000 one-hour receivers, before input</th>
</tr>
</thead>
<tbody>
<tr>
<td>North America</td>
<td style="text-align:right">$0.144</td>
<td style="text-align:right">$0.072</td>
<td style="text-align:right">$144 / $72</td>
</tr>
<tr>
<td>Europe, Israel, and Türkiye</td>
<td style="text-align:right">$0.144</td>
<td style="text-align:right">$0.072</td>
<td style="text-align:right">$144 / $72</td>
</tr>
<tr>
<td>South America</td>
<td style="text-align:right">$0.168</td>
<td style="text-align:right">$0.084</td>
<td style="text-align:right">$168 / $84</td>
</tr>
<tr>
<td>Japan, Hong Kong, and Southeast Asia</td>
<td style="text-align:right">$0.184</td>
<td style="text-align:right">$0.092</td>
<td style="text-align:right">$184 / $92</td>
</tr>
<tr>
<td>India</td>
<td style="text-align:right">$0.184</td>
<td style="text-align:right">$0.092</td>
<td style="text-align:right">$184 / $92</td>
</tr>
<tr>
<td>Australia and New Zealand</td>
<td style="text-align:right">$0.200</td>
<td style="text-align:right">$0.100</td>
<td style="text-align:right">$200 / $100</td>
</tr>
<tr>
<td>South Korea</td>
<td style="text-align:right">$0.250</td>
<td style="text-align:right">$0.125</td>
<td style="text-align:right">$250 / $125</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>A global event needs a weighted regional model. Multiplying every viewer by the North American rate can materially understate spend when large audiences connect from India, Korea, Australia, or Southeast Asia.</p><h2 id="how-we-ranked-the-alternatives">How We Ranked the Alternatives</h2><p>These rankings reward <a href="https://www.videosdk.live/blog/10-best-live-streaming-api" rel="noreferrer">live streaming API</a> fit and cost clarity, not company size, brand familiarity, or unverified performance claims.</p><p>The editorial score uses five weighted criteria: live streaming API fit at 25 percent, pricing clarity at 25 percent, latency and interactivity at 20 percent, developer experience at 15 percent, and scale or deployment choice at 15 percent.</p><p>Public documentation was reviewed on 3 August 2026. No undisclosed packet-loss, join-time, or end-to-end latency benchmark was performed, so the score measures documented product fit rather than laboratory performance.</p><p>A lower-ranked provider may still be the best option for a specific architecture. Mux and Cloudflare Stream, for example, can beat real-time platforms on passive broadcast economics.</p><h2 id="amazon-ivs-pricing-alternatives-compared">Amazon IVS Pricing Alternatives Compared</h2><p>The best Amazon IVS alternative depends first on whether viewers watch passively, interact in real time, or require infrastructure control.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th style="text-align:right">Rank</th>
<th>Live streaming API</th>
<th>Public pricing snapshot</th>
<th>Best for</th>
<th style="text-align:right">Editorial fit</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">1</td>
<td>VideoSDK</td>
<td>$0.004/speaker-minute; $0.002/viewer-minute</td>
<td>Interactive product streams</td>
<td style="text-align:right">9.1/10</td>
</tr>
<tr>
<td style="text-align:right">2</td>
<td>Mux</td>
<td>Live input from $0.025/min; delivery from $0.0008/min</td>
<td>Live-to-VOD workflows</td>
<td style="text-align:right">8.8/10</td>
</tr>
<tr>
<td style="text-align:right">3</td>
<td>Agora</td>
<td>HD $3.99; Full HD $8.99 per 1,000 participant-minutes</td>
<td>Global real-time engagement</td>
<td style="text-align:right">8.6/10</td>
</tr>
<tr>
<td style="text-align:right">4</td>
<td>100ms</td>
<td>$0.0012/viewer-minute; $0.04/encoding minute after allowances</td>
<td>Role-based live events</td>
<td style="text-align:right">8.5/10</td>
</tr>
<tr>
<td style="text-align:right">5</td>
<td>LiveKit</td>
<td>Plans from $0; Ship includes 150,000 WebRTC minutes</td>
<td>Open-source control</td>
<td style="text-align:right">8.3/10</td>
</tr>
<tr>
<td style="text-align:right">6</td>
<td>Cloudflare Stream</td>
<td>$1/1,000 delivered minutes; $5/1,000 stored minutes</td>
<td>Simple passive broadcast</td>
<td style="text-align:right">8.1/10</td>
</tr>
<tr>
<td style="text-align:right">7</td>
<td>api.video</td>
<td>Delivery from $0.0017/min; storage from $0.00285/min</td>
<td>REST-first live plus VOD</td>
<td style="text-align:right">7.9/10</td>
</tr>
<tr>
<td style="text-align:right">8</td>
<td>ZEGOCLOUD</td>
<td>Live streaming from $0.39/1,000 minutes</td>
<td>Social and commerce apps</td>
<td style="text-align:right">7.8/10</td>
</tr>
<tr>
<td style="text-align:right">9</td>
<td>Ant Media Server</td>
<td>$0.24/instance-hour or $109/instance-month, plus infrastructure</td>
<td>Private and on-premises streaming</td>
<td style="text-align:right">7.6/10</td>
</tr>
<tr>
<td style="text-align:right">10</td>
<td>Wowza Streaming Engine</td>
<td>$195/month for the first instance, plus infrastructure and delivery</td>
<td>Custom media workflows</td>
<td style="text-align:right">7.3/10</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>These snapshots are not complete bills. Resolution, host minutes, encoding, egress, recording, storage, support, forced proxy, and enterprise commitments can add cost.</p><p>The table intentionally includes managed APIs and API-enabled self-hosted engines. They can all replace Amazon IVS, but their operational responsibility differs too much for raw price to be a sufficient verdict.</p><h2 id="top-10-amazon-ivs-alternatives">Top 10 Amazon IVS Alternatives</h2><p>VideoSDK ranks first for interactive streaming, while the other nine platforms lead in narrower broadcast, infrastructure, or ecosystem scenarios.</p><h3 id="1-videosdk-best-overall-for-interactive-streaming">1. VideoSDK: Best Overall for Interactive Streaming</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.29.39-PM-1.png" class="kg-image" alt="Amazon IVS Pricing and Top 10 Alternatives Tested & Ranked" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/introduction">VideoSDK Interactive Live Streaming</a> gives hosts <code>SEND_AND_RECV</code> permissions and audiences <code>RECV_ONLY</code> access. Teams can promote viewers, manage stage layouts, run polls and reactions, record sessions, and send RTMP outputs.</p><p>Current public pricing lists $0.004 per speaker-minute, $0.002 per viewer-minute, and $0.03 per RTMP output minute. New accounts receive a one-time $20 credit.</p><p><strong>Why it ranks first:</strong> VideoSDK combines interactive roles, custom UI, audience tools, HLS workflows, RTMP output, and multiple client SDKs within one RTC-focused product surface.</p><p><strong>Best for:</strong> Live shopping, auctions, classrooms, webinars, community events, and products where a viewer may join the stage during the same session.</p><p><strong>Watch out for:</strong> VideoSDK is not the lowest-cost option for every passive broadcast. Mux, Cloudflare Stream, and 100ms can produce lower delivery costs under specific allowances.</p><h3 id="2-mux-best-live-to-vod-pipeline">2. Mux: Best Live-to-VOD Pipeline</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-24-at-5.23.13-PM.png" class="kg-image" alt="Amazon IVS Pricing and Top 10 Alternatives Tested & Ranked" loading="lazy" width="2918" height="1666"/></figure><p><a href="https://www.mux.com/pricing" rel="noreferrer nofollow">Mux Video pricing</a> separates input, storage, and delivery while treating live and on-demand assets as one programmable workflow. Every live stream can become a reusable asset.</p><p>Mux lists Plus live input from $0.025 per minute at 720p. The 1080p multiplier makes that $0.03125, while 1080p delivery costs $0.001 per minute after 100,000 free monthly delivery minutes.</p><p><strong>Why it ranks second:</strong> Mux provides clear APIs for live ingest, recordings, clips, playback, captions, analytics, and <a href="https://www.videosdk.live/blog/what-is-video-on-demand" rel="noreferrer">VOD</a> lifecycle management.</p><p><strong>Best for:</strong> Media products, sports replays, creator platforms, user-generated video, and applications where each live stream becomes an on-demand asset.</p><p><strong>Watch out for:</strong> Mux is primarily a broadcast video platform. A real-time stage with audience promotion is less natural than it is with VideoSDK, Agora, or 100ms.</p><h3 id="3-agora-best-for-global-real-time-engagement">3. Agora: Best for Global Real-Time Engagement</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.26-PM-1.png" class="kg-image" alt="Amazon IVS Pricing and Top 10 Alternatives Tested & Ranked" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/en/" rel="noreferrer nofollow">Agora</a> Interactive Live Streaming <a href="https://www.agora.io/en/pricing/interactive-live-streaming/" rel="noreferrer nofollow">pricing</a> charges participant-minutes by received media quality. Current rates include $0.99 per 1,000 audio minutes, $3.99 for HD, and $8.99 for Full HD.</p><p>The first 10,000 standard minutes are free. Cloud recording, advanced analytics, and forced Cloud Proxy modes carry separate pricing, with minimum monthly fees for forced proxy configurations.</p><p><strong>Why it ranks third:</strong> Agora combines mature real-time media SDKs with a global network designed for geographically distributed participants and multi-host consumer applications.</p><p><strong>Best for:</strong> Social live rooms, gaming, karaoke, watch parties, and established applications needing real-time engagement across many regions.</p><p><strong>Watch out for:</strong> Received resolution, recording, analytics, and proxy requirements complicate forecasts. Model the media each participant receives rather than only the publisher's selected resolution.</p><h3 id="4-100ms-best-for-role-based-live-events">4. 100ms: Best for Role-Based Live Events</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.31.12-PM-1.png" class="kg-image" alt="Amazon IVS Pricing and Top 10 Alternatives Tested & Ranked" loading="lazy" width="2910" height="1656"/></figure><p><a href="https://www.100ms.live/pricing" rel="noreferrer nofollow">100ms pricing</a> includes 10,000 streaming minutes and 1,000 encoding minutes monthly. After that, streaming costs $0.0012 per viewer-minute and encoding costs $0.04 per minute.</p><p>Speaker-side conferencing costs $0.004 per participant-minute after its 10,000-minute allowance. Recording, transcription, RTMP output, and summaries have separate free allowances and overage rates.</p><p><strong>Why it ranks fourth:</strong> 100ms combines role templates, interactive rooms, HLS streaming, and transparent self-serve rates for structured virtual events.</p><p><strong>Best for:</strong> Webinars, classrooms, town halls, and products with predefined host, moderator, speaker, and viewer permissions.</p><p><strong>Watch out for:</strong> Viewer streaming is only one line item. Forecast speaker conferencing, encoding, recording, and external streaming before comparing its headline rate with Amazon IVS pricing.</p><h3 id="5-livekit-best-open-source-control">5. LiveKit: Best Open-Source Control</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.40-PM-1.png" class="kg-image" alt="Amazon IVS Pricing and Top 10 Alternatives Tested & Ranked" loading="lazy" width="2920" height="1670"/></figure><p><a href="https://livekit.com/pricing" rel="noreferrer nofollow">LiveKit Cloud pricing</a> starts with Build at $0, Ship at $50 monthly, and Scale at $500 monthly. Ship includes 150,000 WebRTC minutes, then charges $0.0005 per minute.</p><p>LiveKit provides an open-source <a href="https://www.videosdk.live/blog/sfu-vs-mcu-vs-mesh-webrtc" rel="noreferrer">SFU</a> alongside its managed cloud, ingress, egress, <a href="https://www.videosdk.live/developer-hub/sip/mastering-sip-protocol-comprehensive-guide" rel="noreferrer">SIP</a>, and agent tooling. Self-hosting moves compute, bandwidth, TURN, scaling, and observability costs to your team.</p><p><strong>Why it ranks fifth:</strong> Teams can begin with managed infrastructure and retain a credible path towards source-level control or private deployment.</p><p><strong>Best for:</strong> Engineering teams that need open-source infrastructure, region control, custom media services, or self-hosting.</p><p><strong>Watch out for:</strong> Managed pricing combines plan fees, participant minutes, transfer, ingress, and egress. Self-hosting replaces vendor charges with infrastructure and operational staffing.</p><h3 id="6-cloudflare-stream-simplest-broadcast-billing">6. Cloudflare Stream: Simplest Broadcast Billing</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-24-at-5.27.25-PM-1.png" class="kg-image" alt="Amazon IVS Pricing and Top 10 Alternatives Tested & Ranked" loading="lazy" width="2924" height="1658"/></figure><p><a href="https://developers.cloudflare.com/stream/pricing/" rel="noreferrer nofollow">Cloudflare Stream pricing</a> uses two principal meters. Delivery costs $1 per 1,000 minutes, and prepaid storage costs $5 per 1,000 stored minutes.</p><p>Ingress, encoding, and bandwidth sit inside those meters. Live broadcasts are recorded, so retained recordings consume storage capacity until they are deleted.</p><p><strong>Why it ranks sixth:</strong> The pricing model is unusually easy to explain, while the API handles live ingest, encoding, HLS or DASH playback, and global delivery.</p><p><strong>Best for:</strong> Product launches, company events, creator broadcasts, and teams already using Cloudflare for application delivery or security.</p><p><strong>Watch out for:</strong> Cloudflare Stream does not provide the same participant-stage model as VideoSDK or Amazon IVS Real-Time. It suits receiver-only broadcast better than two-way audience participation.</p><h3 id="7-apivideo-best-rest-first-video-api">7. api.video: Best REST-First Video API</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-24-at-5.27.58-PM.png" class="kg-image" alt="Amazon IVS Pricing and Top 10 Alternatives Tested & Ranked" loading="lazy" width="2896" height="1634"/></figure><p><a href="https://api.video/pricing/" rel="noreferrer nofollow">api.video pricing</a> includes unlimited encoding. Public rates advertise delivery from $0.0017 per minute and hosting from $0.00285 per stored minute.</p><p>The live API supports RTMPS and SRT ingest, private streams, webhooks, DVR, restreaming, recording, analytics, and automatic conversion of live sessions into hosted assets.</p><p><strong>Why it ranks seventh:</strong> api.video offers a consistent REST-oriented surface across live and on-demand video, with no separate encoding charge for the standard workflow.</p><p><strong>Best for:</strong> SaaS products, education libraries, UGC platforms, and teams wanting live streaming plus hosted playback behind one API.</p><p><strong>Watch out for:</strong> api.video documents about three seconds of latency under favourable conditions. It is better suited to low-latency broadcast than a sub-second participatory stage.</p><h3 id="8-zegocloud-best-consumer-engagement-toolkit">8. ZEGOCLOUD: Best Consumer Engagement Toolkit</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.33.21-PM-1.png" class="kg-image" alt="Amazon IVS Pricing and Top 10 Alternatives Tested & Ranked" loading="lazy" width="2926" height="1668"/></figure><p><a href="https://www.zegocloud.com/pricing" rel="noreferrer nofollow">ZEGOCLOUD pricing</a> advertises live streaming from $0.39 per 1,000 minutes and provides 10,000 free minutes for new accounts.</p><p>Its pricing calculator separates host and co-host activity from audience viewing. Interactive mode, standard live streaming, resolution, recording, chat, and engagement products can use different meters.</p><p><strong>Why it ranks eighth:</strong> ZEGOCLOUD combines real-time media with UI kits, chat, effects, and social engagement features aimed at consumer applications.</p><p><strong>Best for:</strong> Dating, social live rooms, live commerce, creator products, and applications that value packaged engagement features alongside media.</p><p><strong>Watch out for:</strong> The $0.39 headline does not represent the complete interactive workflow. Calculate host streams, audience streams, recording, moderation, and add-ons separately.</p><h3 id="9-ant-media-server-best-self-hosted-webrtc">9. Ant Media Server: Best Self-Hosted WebRTC</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-24-at-5.28.24-PM.png" class="kg-image" alt="Amazon IVS Pricing and Top 10 Alternatives Tested & Ranked" loading="lazy" width="2924" height="1660"/></figure><p><a href="https://antmedia.io/pricing/" rel="noreferrer nofollow">Ant Media Server pricing</a> starts at $0.24 per active Enterprise instance-hour with a $1 signup fee. Monthly licensing costs $109 per instance, while annual licensing lists $89 per instance-month.</p><p>Ant Media supports WebRTC, HLS, LL-HLS, DASH, RTMP, RTSP, SRT, WHIP, and WHEP across cloud, private, and on-premises deployments.</p><p><strong>Why it ranks ninth:</strong> Few options combine this protocol breadth with self-hosted, API-driven deployment and control over the complete media path.</p><p><strong>Best for:</strong> Auctions, surveillance, remote production, regulated deployments, and teams requiring protocol flexibility or infrastructure ownership.</p><p><strong>Watch out for:</strong> Licences exclude compute, storage, bandwidth, monitoring, redundancy, and staffing. Capacity depends on bitrate, transcoding, instance type, and cluster design.</p><h3 id="10-wowza-streaming-engine-best-custom-media-workflows">10. Wowza Streaming Engine: Best Custom Media Workflows</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-24-at-11.44.51-PM.png" class="kg-image" alt="Amazon IVS Pricing and Top 10 Alternatives Tested & Ranked" loading="lazy" width="2930" height="1652"/></figure><p><a href="https://www.wowza.com/pricing/" rel="noreferrer nofollow">Wowza Streaming Engine pricing</a> lists a Basic Monthly plan at $195 for the first instance. The plan includes up to ten concurrent transcoded channels.</p><p>Additional Basic instances cost $195 monthly, and extra transcoded channels cost $25 each. Delivery, infrastructure, monitoring, and redundancy remain separate from the software licence.</p><p><strong>Why it ranks tenth:</strong> Wowza provides mature APIs, Java extensions, on-premises deployment, and detailed control over ingest, transcoding, packaging, and playback.</p><p><strong>Best for:</strong> Broadcasters, hybrid deployments, enterprises with video engineers, and specialised workflows involving existing hardware or uncommon protocols.</p><p><strong>Watch out for:</strong> Operating Wowza needs more media-server expertise than a managed API. Its licence price is not the total cost of serving a large audience.</p><h2 id="which-amazon-ivs-alternative-should-you-choose">Which Amazon IVS Alternative Should You Choose?</h2><p>Choose the streaming architecture first, then compare providers that solve the same problem.</p><ul><li><strong>Choose VideoSDK</strong> when viewers must become speakers, latency must support conversation, and the application needs custom roles, audience tools, and multi-platform SDKs.</li><li><strong>Choose Amazon IVS Low-Latency</strong> when you need Twitch-style broadcast delivery, already operate on AWS, and expect a very large receiver-only audience.</li><li><strong>Choose Amazon IVS Real-Time</strong> when AWS integration and sub-300ms stages matter, and its participant economics suit the expected geography and concurrency.</li><li><strong>Choose Mux</strong> when every stream should become recordings, clips, analytics, captions, and reusable VOD assets through one API lifecycle.</li><li><strong>Choose Agora or 100ms</strong> when real-time consumer engagement or structured event roles outweigh migration simplicity.</li><li><strong>Choose Cloudflare Stream or api.video</strong> when passive broadcast, simple delivery pricing, and REST-driven video lifecycle management matter most.</li><li><strong>Choose LiveKit, Ant Media, or Wowza</strong> when self-hosting, source access, protocol choice, or private infrastructure justifies operational ownership.</li></ul><p>Model three traffic profiles before procurement: an average day, a successful event, and an unexpected peak. Free allowances should not hide peak economics.</p><p>Keep duration, average watch percentage, resolution mix, region mix, recording, multistreaming, moderation, support, and taxes consistent across every vendor calculation.</p><h2 id="can-amazon-ivs-and-videosdk-work-together">Can Amazon IVS and VideoSDK Work Together?</h2><p>Amazon IVS and VideoSDK can form a hybrid architecture when a small interactive stage must feed a much larger receiver-only audience.</p><p>VideoSDK can run the interactive room for hosts and promoted viewers. Its RTMP output can send a composed programme feed into an Amazon IVS Low-Latency channel for HLS distribution.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-4--2026--03_10_44-PM.png" class="kg-image" alt="Amazon IVS Pricing and Top 10 Alternatives Tested & Ranked" loading="lazy" width="1672" height="941"/></figure><p>The hybrid adds VideoSDK speaker and viewer minutes, RTMP output, IVS input, and IVS viewer output. It also creates two monitoring and failure domains.</p><p>Use the pattern only when audience scale or AWS distribution justifies the separation. A single provider remains easier for most product-led events.</p><h2 id="amazon-ivs-migration-checklist">Amazon IVS Migration Checklist</h2><p>A safe migration reproduces access, roles, media quality, recording, observability, and rollback before it moves production viewers.</p><ol><li><strong>Classify the current workload.</strong> Separate Low-Latency channels, Real-Time stages, chat, recording, composition, ad insertion, and CDN delivery. Do not treat IVS as one service line.</li><li><strong>Build a normalised cost model.</strong> Export at least 30 days of input duration, viewer watch time, resolution, geography, participant-hours, and add-ons. Calculate average and peak events.</li><li><strong>Map product behaviour.</strong> Recreate host, co-host, moderator, viewer, token, playback authorisation, recording, captions, analytics, and webhook flows in the target API.</li><li><strong>Run a dual-path pilot.</strong> Send selected test events to both platforms. Compare join success, playback start, end-to-end latency, rebuffering, device coverage, and cost per watched minute.</li><li><strong>Migrate in cohorts.</strong> Move internal events first, then a small production segment. Keep IVS resources and routing available until the target service survives a representative peak.</li><li><strong>Close the billing loop.</strong> Compare the first invoice with the model, remove unused IVS channels and stages, update alerts, and document the rollback window.</li></ol><p>VideoSDK teams can begin with the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/introduction">React ILS quickstart</a> and review <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token">authentication and token setup</a> before the dual-path pilot.</p><h2 id="amazon-ivs-pricing-terms-explained">Amazon IVS Pricing Terms Explained</h2><p>These definitions prevent the most common unit errors in Amazon IVS pricing comparisons.</p><blockquote><strong>Viewer-hour:</strong> One viewer receiving one hour of an Amazon IVS Low-Latency channel. Resolution, billing region, and monthly tier determine the rate.</blockquote><blockquote><strong>Participant-hour:</strong> One host or viewer connected to an Amazon IVS Real-Time stage for one hour. Audio-only participation uses a lower rate.</blockquote><blockquote><strong>Speaker-minute:</strong> One VideoSDK host or active speaker connected for one minute. Current interactive live streaming pricing lists $0.004 per speaker-minute.</blockquote><blockquote><strong>Viewer-minute:</strong> One VideoSDK receiver connected without publishing media for one minute. Current public pricing lists $0.002 per viewer-minute.</blockquote><blockquote><strong>Low-Latency HLS:</strong> Segmented HTTP delivery tuned below traditional HLS delay. It scales efficiently for passive viewers but normally cannot match WebRTC conversation latency.</blockquote><blockquote><strong>Interactive live streaming:</strong> A real-time format where hosts and selected audience members exchange media. VideoSDK represents these behaviours through publishing and receiving permissions.</blockquote><h2 id="key-amazon-ivs-pricing-takeaways">Key Amazon IVS Pricing Takeaways</h2><p>The important decision is not which headline rate is lowest. It is which architecture produces the required experience at the expected traffic profile.</p><ul><li>Amazon IVS Low-Latency pricing combines input with regional, resolution-based viewer output, while Real-Time stages use participant-hour billing.</li><li>VideoSDK ranks first for interactive product experiences because it combines speaker and viewer roles, audience tools, HLS, RTMP output, and multi-platform SDKs.</li><li>Mux, Cloudflare Stream, and api.video can provide better economics for passive broadcast or live-to-VOD workflows without a participatory stage.</li><li>LiveKit, Ant Media, and Wowza exchange managed simplicity for source access, deployment control, or protocol flexibility.</li><li>Every cost comparison should use the same duration, watch percentage, resolution, geography, recording, multistreaming, support, and tax assumptions.</li></ul><h2 id="conclusion">Conclusion</h2><p>Amazon IVS pricing remains competitive when AWS integration, managed broadcast delivery, or Real-Time stages match the product. VideoSDK is the stronger overall alternative for interactive streams with explicit speaker and viewer roles.</p><p>Validate average and peak traffic before migrating, then use the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/introduction">VideoSDK ILS documentation</a> and <a href="https://app.videosdk.live/login">$20 signup credit</a> for a proof of concept. What are you building with VideoSDK? Share your live streaming use case in the comments.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="how-much-does-amazon-ivs-cost">How much does Amazon IVS cost?</h3><p>Amazon IVS cost depends on the selected mode. Low-Latency channels charge input plus viewer output, while Real-Time stages charge each connected participant-hour.</p><p>For a one-hour North American example with one host and 1,000 viewers, current public rates produce $146 for Standard Full HD Low-Latency or $72.07 for a Real-Time stage.</p><h3 id="is-amazon-ivs-free-to-use-1">Is Amazon IVS free to use?</h3><p>Amazon IVS offers free usage for eligible new AWS accounts. AWS publishes monthly introductory allowances and a newer credits-based Free Tier for qualifying accounts created from 15 July 2025.</p><p>The applicable offer depends on account eligibility and current terms. Use standard rates for production forecasts and confirm the live benefit inside the AWS billing console.</p><h3 id="does-amazon-ivs-charge-per-viewer">Does Amazon IVS charge per viewer?</h3><p>Yes, Amazon IVS effectively charges per viewer in both principal streaming modes. Low-Latency channels meter delivered viewer output, while Real-Time stages meter each connected viewer as a participant.</p><p>The units differ, so compare viewer-hours for channels against participant-hours for stages instead of treating them as one interchangeable price.</p><h3 id="what-is-the-best-amazon-ivs-alternative">What is the best Amazon IVS alternative?</h3><p>VideoSDK is the best Amazon IVS alternative in this evaluation for interactive product streaming because it exposes separate speaker and viewer roles with public per-minute pricing.</p><p>Mux is stronger for live-to-VOD pipelines, Cloudflare Stream suits simple passive broadcasts, and LiveKit fits teams requiring open-source or self-hosted control.</p><h3 id="is-videosdk-cheaper-than-amazon-ivs">Is VideoSDK cheaper than Amazon IVS?</h3><p>VideoSDK is cheaper than an Amazon IVS Standard Full HD Low-Latency channel in the worked example, costing $120.24 versus $146 before extras.</p><p>Amazon IVS Real-Time is cheaper in the same nominal attendance example at $72.07. Architecture, latency, region, scale, and add-ons must therefore guide the decision.</p><h3 id="is-mux-cheaper-than-amazon-ivs">Is Mux cheaper than Amazon IVS?</h3><p>Mux can be cheaper than Amazon IVS for receiver-only broadcast delivery, especially while its 100,000 free monthly delivery minutes and monthly usage credit apply.</p><p>Mux and Amazon IVS use different input, quality, recording, and delivery assumptions. Model live input, recording storage, resolution mix, and audience participation before deciding.</p><h3 id="which-api-suits-interactive-live-shopping">Which API suits interactive live shopping?</h3><p>VideoSDK suits interactive live shopping when viewers need to join the stage, react, vote, ask questions, or interact with custom commerce UI inside the application.</p><p>Amazon IVS suits large broadcast-first shopping events. ZEGOCLOUD and Agora also deserve evaluation when packaged social engagement or global real-time reach carries greater weight.</p><h2 id="related-videosdk-live-streaming-guides">Related VideoSDK Live Streaming Guides</h2><p>VideoSDK documentation provides the implementation context needed after the pricing decision.</p><ul><li><a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/introduction">Interactive live streaming introduction for React</a></li><li><a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/quick-start">Interactive Live Streaming quickstart</a></li><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token">VideoSDK authentication and tokens</a></li><li><a href="https://docs.videosdk.live/code-sample">VideoSDK code samples</a></li></ul><p>These resources cover roles, streaming modes, authentication, layouts, recording, audience tools, analytics, and the API concepts needed to validate a production architecture.</p><h2 id=""/>]]></content:encoded></item><item><title><![CDATA[Top 10 Sendbird Alternatives for Video Calling APIs]]></title><description><![CDATA[Compare ten video-focused Sendbird alternatives using disclosed criteria, current public pricing, production trade-offs, and practical migration guidance.]]></description><link>https://www.videosdk.live/blog/sendbird-alternatives</link><guid isPermaLink="false">6a7085e1b3240feb748c9289</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 03 Aug 2026 14:09:04 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-3--2026--07_12_19-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>The strongest Sendbird alternatives for video calling include VideoSDK, Daily, LiveKit, Agora, and 100ms. VideoSDK ranks first under this documentation-based model for broad client SDK coverage, Prebuilt and custom UI options, and published usage pricing. The most common mistake is comparing chat features when video limits, mobile support, media controls, or total usage cost are the real constraints.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-3--2026--07_12_19-PM.png" alt="Top 10 Sendbird Alternatives for Video Calling APIs"/><p><a href="https://sendbird.com/products/voice-and-video" rel="noreferrer nofollow">Sendbird</a> supports chat, business messaging, customer service, and voice and video calling. This guide deliberately compares only the video- Calling product, Sendbird Calls, with programmable <a href="https://videosdk.live/developer-hub/webrtc/api-for-video-calling" rel="noreferrer">video APIs</a> that developers can embed inside their own applications.</p><p>We reviewed first-party documentation, SDK coverage, public pricing, interface options, production controls, and deployment choices. The research was last verified on August 3, 2026. This is a documentation-based evaluation, not a synthetic network benchmark or a claim of hands-on testing.</p><h2 id="what-is-sendbird-calls">What Is Sendbird Calls?</h2><p><strong>Sendbird Calls is a programmable voice and video API for adding direct calls and group rooms to web and mobile applications.</strong> It is one product within Sendbird's broader communications platform, rather than a standalone meeting application.</p><p>The current <a href="https://sendbird.com/pricing/calls" rel="noreferrer nofollow">Sendbird Calls pricing page</a> lists video at $0.0014 per user-minute for peer-to-peer calls and $0.0035 for server-relayed calls. Cloud recording is listed at $0.0059 per minute.</p><p>Sendbird supports private one-to-one calls and group rooms. Its public pricing page currently limits group video calls to 10 users, while group voice calls support up to 1,000 users. That difference matters for classrooms, communities, larger care teams, and collaborative products.</p><h2 id="what-are-sendbird-alternatives-for-video-calling">What Are Sendbird Alternatives for Video Calling?</h2><p>Sendbird's alternatives for video calling are APIs and SDKs that can replace Sendbird calls without requiring a team to build and operate its own <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> media infrastructure.</p><p>These platforms usually provide client SDKs, token-based room access, managed media routing, participant events, screen sharing, recording, and optional prebuilt interfaces. They differ considerably in platform coverage, deployment control, video limits, pricing units, and add-on charges.</p><p>This definition excludes chat-only products, customer-support tools, and signalling services that do not carry video media. The ranking therefore answers a narrower question than most pages targeting the broad Sendbird alternatives keyword.</p><h2 id="how-we-ranked-these-sendbird-alternatives">How We Ranked These Sendbird Alternatives</h2><p>This ranking rewards documented video product fit and implementation practicality. Messaging features, AI agents, contact-centre products, and broadcast-only streaming did not influence the scores.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Criterion</th>
<th style="text-align:right">Weight</th>
<th>What earned a higher score</th>
</tr>
</thead>
<tbody>
<tr>
<td>Video calling product fit</td>
<td style="text-align:right">25%</td>
<td>Managed rooms, media controls, screen sharing, recording, and call events</td>
</tr>
<tr>
<td>SDK and platform coverage</td>
<td style="text-align:right">20%</td>
<td>Maintained web, native mobile, cross-platform, desktop, or backend SDKs</td>
</tr>
<tr>
<td>UI and time to first call</td>
<td style="text-align:right">15%</td>
<td>Prebuilt UI, headless APIs, clear quickstarts, and working samples</td>
</tr>
<tr>
<td>Production controls</td>
<td style="text-align:right">15%</td>
<td>Tokens, reconnection, quality tools, analytics, security, and compliance options</td>
</tr>
<tr>
<td>Pricing transparency</td>
<td style="text-align:right">15%</td>
<td>Public billing units, included usage or credits, and visible add-on costs</td>
</tr>
<tr>
<td>Deployment control</td>
<td style="text-align:right">10%</td>
<td>Region controls, self-hosting, private deployment, or cloud flexibility</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Scores are editorial, but their inputs are verifiable through the linked first-party sources. Published latency claims did not earn additional points unless the provider described a test method or concrete network condition.</p><h2 id="top-10-sendbird-alternatives-compared">Top 10 Sendbird Alternatives Compared</h2><p>The table provides a quick shortlist. Prices are public list-rate snapshots checked on August 3, 2026. They are not directly equivalent because vendors meter resolution, streams, data transfer, recordings, support, and compliance differently.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th style="text-align:right">Rank</th>
<th>Provider</th>
<th>Best for</th>
<th>Public pricing snapshot</th>
<th style="text-align:right">Score</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">1</td>
<td>VideoSDK</td>
<td>Broad client coverage with Prebuilt or custom UI</td>
<td>$20 one-time balance; HD video from $0.004 per participant-minute</td>
<td style="text-align:right">92/100</td>
</tr>
<tr>
<td style="text-align:right">2</td>
<td>Daily</td>
<td>Browser-first products and telehealth workflows</td>
<td>10,000 free minutes monthly; then $0.004 at list rate</td>
<td style="text-align:right">88/100</td>
</tr>
<tr>
<td style="text-align:right">3</td>
<td>LiveKit</td>
<td>Open-source control and self-hosting</td>
<td>Free Build plan; paid plans from $50 monthly plus usage</td>
<td style="text-align:right">87/100</td>
</tr>
<tr>
<td style="text-align:right">4</td>
<td>Agora</td>
<td>Cross-platform RTC and geographically distributed products</td>
<td>10,000 free minutes monthly; video from $3.99 per 1,000 minutes</td>
<td style="text-align:right">86/100</td>
</tr>
<tr>
<td style="text-align:right">5</td>
<td>100ms</td>
<td>Role-based rooms, classrooms, and events</td>
<td>10,000 free minutes monthly; then $0.004 per participant-minute</td>
<td style="text-align:right">84/100</td>
</tr>
<tr>
<td style="text-align:right">6</td>
<td>Cloudflare RealtimeKit</td>
<td>Cloudflare-native applications and component-based UI</td>
<td>Free during beta; intended GA rate of $0.002 per participant-minute</td>
<td style="text-align:right">82/100</td>
</tr>
<tr>
<td style="text-align:right">7</td>
<td>ZEGOCLOUD</td>
<td>Mobile social and entertainment video</td>
<td>10,000 free minutes; video from $3.99 per 1,000 participant-minutes</td>
<td style="text-align:right">81/100</td>
</tr>
<tr>
<td style="text-align:right">8</td>
<td>Zoom Video SDK</td>
<td>Zoom media features inside a custom application</td>
<td>10,000 free minutes monthly; then $0.0035 per minute</td>
<td style="text-align:right">80/100</td>
</tr>
<tr>
<td style="text-align:right">9</td>
<td>Whereby Embedded</td>
<td>Fast browser embedding with a complete meeting UI</td>
<td>$9.99 monthly with 2,000 minutes; then $0.004</td>
<td style="text-align:right">77/100</td>
</tr>
<tr>
<td style="text-align:right">10</td>
<td>Amazon Chime SDK</td>
<td>AWS-native, lower-level meeting applications</td>
<td>$0.0017 per attendee-minute for WebRTC media</td>
<td style="text-align:right">75/100</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>VideoSDK ranks first because its documentation shows one of the widest client matrices in this comparison while retaining both prebuilt and custom interface paths. LiveKit becomes the first choice when self-hosting is mandatory. Daily can be a better fit when a browser embed is the fastest route to market.</p><h2 id="top-10-sendbird-alternatives-for-video-calling-apis">Top 10 Sendbird Alternatives for Video Calling APIs</h2><p>Each platform earns its position for a specific product condition. No provider is the right choice for every architecture, client stack, region, or billing pattern.</p><h3 id="1-videosdk-best-overall-under-this-model">1. VideoSDK: Best Overall Under This Model</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.29.39-PM.png" class="kg-image" alt="Top 10 Sendbird Alternatives for Video Calling APIs" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://www.videosdk.live/">VideoSDK</a> is the most balanced Sendbird Calls alternative under this article's weighted criteria, particularly for teams maintaining several client applications.</p><p><strong>Why it ranks first:</strong> The <a href="https://docs.videosdk.live/">VideoSDK documentation</a> covers Prebuilt, JavaScript, Angular, React, React Native, Android, iOS, Flutter, Unity, Python, C++, and REST options. Its calling guides include participant media, screen sharing, recording, transcription, call-quality handling, geographic controls, and end-to-end encryption.</p><p><strong>Best for:</strong> Products that need one managed RTC backend across web, native mobile, React Native, Flutter, Unity, or backend media participants. Teams can begin with the <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">prebuilt UI kit</a> or build a custom interface with framework-specific SDKs.</p><p><strong>Pricing:</strong> The current <a href="https://docs.videosdk.live/help_docs/pricing">VideoSDK pricing</a> page lists a $20 one-time balance and prepaid pay-as-you-go billing. Video starts at $0.004 per participant-minute for the HD aggregate-resolution tier. Higher aggregate viewed resolutions use higher rates.</p><p><strong>Trade-offs:</strong> The prepaid wallet can pause services if its balance runs out, although auto-recharge is available. Self-service concurrency limits and paid capacity packs also require modelling. Large galleries can enter higher price tiers because billing uses the total resolution a participant views.</p><h3 id="2-daily-best-for-browser-first-products">2. Daily: Best for Browser-First Products</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.02-PM.png" class="kg-image" alt="Top 10 Sendbird Alternatives for Video Calling APIs" loading="lazy" width="2924" height="1652"/></figure><p><a href="https://www.daily.co/" rel="noreferrer nofollow">Daily</a> combines a WebRTC API with Daily-prebuilt and maintained client SDKs. Its browser-first approach works well when a usable room must ship before a bespoke interface.</p><p><strong>Why it ranks second:</strong> Daily provides an embeddable call component, lower-level client SDKs, REST APIs, webhooks, recording, streaming, and transcription. Official examples cover web, React, React Native, iOS, and Android.</p><p><strong>Best for:</strong> Telehealth, customer appointments, and browser-first products that want to start with an iframe and customise the experience gradually. Daily Prebuilt reduces the initial frontend workload.</p><p><strong>Pricing:</strong> <a href="https://www.daily.co/pricing/video-sdk/" rel="noreferrer nofollow">Daily video pricing</a> includes 10,000 free participant-minutes each month. The published list rate then starts at $0.004 per video participant-minute and falls through graduated volume tiers.</p><p><strong>Trade-offs:</strong> Recording, streaming, transcription, <a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api" rel="noreferrer">HIPAA support</a>, and advanced firewall controls create separate costs. VideoSDK documents more client targets, while Daily provides a focused iframe path and long-standing browser support.</p><h3 id="3-livekit-best-for-self-hosting">3. LiveKit: Best for Self-Hosting</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.40-PM.png" class="kg-image" alt="Top 10 Sendbird Alternatives for Video Calling APIs" loading="lazy" width="2920" height="1670"/></figure><p><a href="https://livekit.io/" rel="noreferrer nofollow">LiveKit</a> is the strongest option in this ranking when control over the media server and deployment model matters more than a fully managed starting point.</p><p><strong>Why it ranks third:</strong> LiveKit publishes its media server as open source. Its official material states that teams can run the stack locally or on their own infrastructure. LiveKit Cloud adds managed media infrastructure, analytics, recording, export, and encryption options.</p><p><strong>Best for:</strong> Infrastructure teams that need to inspect, extend, or self-host the SFU. It also fits products requiring raw media tracks shared by human participants and backend services.</p><p><strong>Pricing:</strong> <a href="https://livekit.io/pricing" rel="noreferrer nofollow">LiveKit Cloud pricing</a> lists a free build plan, shipping from $50 per month, and scaling from $500. Plans bundle WebRTC minutes and downstream data before overage charges.</p><p><strong>Trade-offs:</strong> LiveKit combines plan fees, connection minutes, and data transfer, making simple participant-minute comparisons incomplete. Self-hosting transfers upgrades, bandwidth, observability, reliability, and incident response to your team. VideoSDK is simpler when managed infrastructure is preferred.</p><h3 id="4-agora-best-for-established-global-rtc">4. Agora: Best for Established Global RTC</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.30.26-PM.png" class="kg-image" alt="Top 10 Sendbird Alternatives for Video Calling APIs" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/" rel="noreferrer nofollow">Agora</a> provides programmable real-time video across mobile, web, desktop, game engines, and cross-platform frameworks.</p><p><strong>Why it ranks fourth:</strong> Agora's product surface includes video calling, quality tools, recording, extensions, and interactive media functions for geographically distributed users. Its platform coverage makes it relevant to consumer and international products.</p><p><strong>Best for:</strong> Social, gaming, education, and global applications that need broad device reach. Agora deserves a regional proof of concept where network paths and provider coverage can affect call behaviour.</p><p><strong>Pricing:</strong> Agora's <a href="https://www.agora.io/en/pricing/" rel="noreferrer nofollow">pricing page</a> lists 10,000 free minutes each month and video calling from $3.99 per 1,000 minutes. Resolution and additional services can change the total.</p><p><strong>Trade-offs:</strong> Agora's wider catalogue introduces more product, configuration, and billing decisions. Recording, analytics, extensions, and support need separate review. VideoSDK offers a more direct path for teams prioritising its documented SDK matrix and prebuilt option.</p><h3 id="5-100ms-best-for-role-based-rooms">5. 100ms: Best for Role-Based Rooms</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.31.12-PM.png" class="kg-image" alt="Top 10 Sendbird Alternatives for Video Calling APIs" loading="lazy" width="2910" height="1656"/></figure><p><a href="https://www.100ms.live/" rel="noreferrer nofollow">100ms</a> is a strong Sendbird Calls replacement for classrooms, webinars, and structured rooms where participant roles determine publishing and control permissions.</p><p><strong>Why it ranks fifth:</strong> Its product model emphasises rooms, roles, templates, participant state, and interactive experiences. The platform includes Prebuilt, custom web and mobile SDKs, recordings, transcription, and open-source examples.</p><p><strong>Best for:</strong> Edtech, telehealth, fitness, video KYC, and event products with hosts, guests, speakers, and viewers. Teams can define role permissions instead of duplicating the same logic across clients.</p><p><strong>Pricing:</strong> <a href="https://www.100ms.live/pricing" rel="noreferrer nofollow">100ms pricing</a> includes 10,000 conferencing minutes monthly, followed by $0.004 per participant-minute. Recording, external streaming, transcription, summaries, noise cancellation, compliance, and support can add cost.</p><p><strong>Trade-offs:</strong> The role-and-template approach is helpful for structured rooms but can feel opinionated for simpler applications. Compared with 100ms, VideoSDK documents more platform targets and uses a less template-centred starting model.</p><h3 id="6-cloudflare-realtimekit-best-emerging-edge-option">6. Cloudflare RealtimeKit: Best Emerging Edge Option</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-24-at-5.27.25-PM.png" class="kg-image" alt="Top 10 Sendbird Alternatives for Video Calling APIs" loading="lazy" width="2924" height="1658"/></figure><p><a href="https://developers.cloudflare.com/realtime/realtimekit/" rel="noreferrer nofollow">Cloudflare RealtimeKit</a> is the active successor to Dyte and an important 2026 option for applications already using Cloudflare.</p><p><strong>Why it ranks sixth:</strong> RealtimeKit combines a Core SDK, customisable UI Kit, REST APIs, webhooks, recording, and a WebRTC SFU on Cloudflare's network. Its documented SDK paths include React, Angular, web components, React Native, Android, iOS, and Flutter.</p><p><strong>Best for:</strong> Cloudflare-based products that want calling infrastructure and UI components under the same vendor. It also gives former Dyte users an official migration path.</p><p><strong>Pricing:</strong> Cloudflare's <a href="https://developers.cloudflare.com/realtime/realtimekit/pricing/" rel="noreferrer nofollow">RealtimeKit pricing page</a> says the product is free during beta. It lists an intended general-availability rate of $0.002 per audio or video participant-minute and $0.010 per export minute.</p><p><strong>Trade-offs:</strong> Beta status is the main risk because limits, pricing, APIs, and availability can change. The <a href="https://docs.dyte.io/guides/realtimekit-migration/sdk-guide" rel="noreferrer nofollow">official Dyte migration guide</a> states that Dyte SDKs are in maintenance mode without further feature updates or bug fixes. VideoSDK is the safer current choice when production maturity matters more than Cloudflare consolidation.</p><h3 id="7-zegocloud-best-for-social-video">7. ZEGOCLOUD: Best for Social Video</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.33.21-PM.png" class="kg-image" alt="Top 10 Sendbird Alternatives for Video Calling APIs" loading="lazy" width="2926" height="1668"/></figure><p><a href="https://www.zegocloud.com/" rel="noreferrer nofollow">ZEGOCLOUD</a> fits mobile social products that combine video calls with real-time effects and audience interaction.</p><p><strong>Why it ranks seventh:</strong> Its product pages cover one-to-one and group calling, screen sharing, recording, monitoring, effects, beautification, and UI Kits. Current documentation spans web, mobile, desktop, Flutter, React Native, Unity, and Linux C++.</p><p><strong>Best for:</strong> Social discovery, dating, gaming, live commerce, and entertainment applications where effects, gifting, and quick mobile interface assembly are central requirements.</p><p><strong>Pricing:</strong> <a href="https://www.zegocloud.com/pricing" rel="noreferrer nofollow">ZEGOCLOUD pricing</a> lists 10,000 free minutes, followed by video from $3.99 per 1,000 participant-minutes. Subscribed streams can affect metered usage, so production gallery layouts should be reproduced in cost calculations.</p><p><strong>Trade-offs:</strong> Effects, whiteboards, analytics, recording, and support can create separate line items. VideoSDK is a more focused fit for portable business calling, while ZEGOCLOUD deserves evaluation for effect-heavy social experiences.</p><h3 id="8-zoom-video-sdk-best-for-zoom-media-features">8. Zoom Video SDK: Best for Zoom Media Features</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.32.46-PM.png" class="kg-image" alt="Top 10 Sendbird Alternatives for Video Calling APIs" loading="lazy" width="2920" height="1646"/></figure><p><a href="https://developers.zoom.us/docs/video-sdk/" rel="noreferrer nofollow">Zoom Video SDK</a> packages Zoom's audio and video technology for custom applications without requiring the standard Zoom Meetings interface.</p><p><strong>Why it ranks eighth:</strong> Zoom documents support across nine platforms, raw media access, HD video, screen sharing, chat, cloud recording, transcription, service-quality metrics, REST APIs, webhooks, and a UI Toolkit.</p><p><strong>Best for:</strong> Enterprise, healthcare, education, and collaboration products whose buyers already recognise Zoom's media stack. It also suits supported platforms that require raw audio or video access.</p><p><strong>Pricing:</strong> Zoom's <a href="https://developers.zoom.us/blog/video-sdk-fact-sheet/" rel="noreferrer nofollow">Video SDK fact sheet</a> states that 10,000 minutes are included monthly, followed by $0.0035 per minute, with volume discounts.</p><p><strong>Trade-offs:</strong> The UI Toolkit is documented for web, iOS, and Android, so other platforms can require more interface work. Zoom also enforces minimum supported SDK versions. VideoSDK provides more framework-specific quickstarts, while Zoom offers an established meeting-media stack.</p><h3 id="9-whereby-embedded-best-for-fast-web-embeds">9. Whereby Embedded: Best for Fast Web Embeds</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.34.01-PM.png" class="kg-image" alt="Top 10 Sendbird Alternatives for Video Calling APIs" loading="lazy" width="2890" height="1624"/></figure><p><a href="https://whereby.com/information/embedded/" rel="noreferrer nofollow">Whereby Embedded</a> is a focused choice for adding a complete browser meeting experience with limited integration work.</p><p><strong>Why it ranks ninth:</strong> Whereby provides API-created rooms, iframe embedding, a browser SDK, branding, chat, breakout groups, screen sharing, waiting rooms, recording, transcription, and live streaming.</p><p><strong>Best for:</strong> Marketplaces, telehealth portals, coaching products, and customer appointments that prioritise a browser embed over deep native client primitives.</p><p><strong>Pricing:</strong> <a href="https://whereby.com/information/embedded/pricing" rel="noreferrer nofollow">Whereby Embedded pricing</a> lists an Explore plan with 2,000 participant-minutes. Build costs $9.99 monthly with the same allowance, followed by $0.004 for additional participant-minutes. HIPAA is a separate monthly charge.</p><p><strong>Trade-offs:</strong> The published plan comparison lists 200 total participants but 24 active videos. Whereby is less suitable when products need raw media access or specialised layouts across multiple native frameworks. VideoSDK offers wider client coverage, while Whereby reaches a polished browser call faster.</p><h3 id="10-amazon-chime-sdk-best-for-aws-native-teams">10. Amazon Chime SDK: Best for AWS-Native Teams</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/Screenshot-2026-07-23-at-6.54.40-PM.png" class="kg-image" alt="Top 10 Sendbird Alternatives for Video Calling APIs" loading="lazy" width="2918" height="1632"/></figure><p><a href="https://docs.aws.amazon.com/chime-sdk/" rel="noreferrer nofollow">Amazon Chime SDK</a> is a lower-level alternative for teams already building identity, observability, storage, and media workflows on AWS.</p><p><strong>Why it ranks tenth:</strong> Chime SDK supplies WebRTC audio, video, screen sharing, data messages, meeting APIs, media capture, live connectors, and integrations with S3 and Kinesis Video Streams. The February 20, 2026 end of Amazon Chime service support <a href="https://docs.aws.amazon.com/chime/latest/ag/doc-history.html" rel="noreferrer nofollow">did not affect the Amazon Chime SDK</a>.</p><p><strong>Best for:</strong> AWS-native healthcare, education, support, and internal collaboration applications that want media workflows inside an existing AWS architecture.</p><p><strong>Pricing:</strong> <a href="https://aws.amazon.com/chime/chime-sdk/pricing/" rel="noreferrer nofollow">Amazon Chime SDK pricing</a> is pay-as-you-go without an upfront fee. Current examples use $0.0017 per attendee-minute for WebRTC media, with separate capture, concatenation, streaming, storage, and data-transfer charges.</p><p><strong>Trade-offs:</strong> AWS documentation lists up to 25 simultaneous video sources and 720p client video in the core meeting architecture. Teams assemble more UI and operational plumbing than with VideoSDK Prebuilt, Daily Prebuilt, or Whereby Embedded.</p><h2 id="how-sendbird-alternatives-price-video-calls">How Sendbird Alternatives Price Video Calls</h2><p>Participant-minute pricing becomes useful only after you normalise participant count, duration, media topology, viewed resolution, recording, included usage, and additional services.</p><p>The basic usage formula is:</p><p><code>participant minutes = participants × call minutes × calls per month</code></p><p>A product running 5,000 monthly two-person calls of 20 minutes each consumes 200,000 participant-minutes. That figure is only the starting point because each provider meters a different combination of media and services.</p><p>At published list rates, VideoSDK's HD transport would cost $800 for this usage before its one-time balance and add-ons. Sendbird would cost $280 if every minute stayed peer-to-peer or $700 if every minute was server-relayed, excluding recording.</p><p>Those numbers do not prove that one platform will be cheaper in production. Sendbird's 10-user group video limit, the actual share of relayed calls, VideoSDK's aggregate-resolution tiers, and each product's recording, support, compliance, and concurrency costs can change the decision.</p><p>Use this cost model before accepting any calculator result:</p><ol><li><strong>Calculate connected participant-minutes.</strong> Include waiting-room and early-join time if the provider bills those minutes.</li><li><strong>Reproduce the production gallery.</strong> One active speaker can be billed differently from several visible HD tiles.</li><li><strong>Add recorded minutes.</strong> Check whether recording is billed per room, participant, output, or track.</li><li><strong>Include storage, transcription, egress, compliance, and support.</strong> These costs can exceed media transport for some workloads.</li><li><strong>Model concurrency separately.</strong> Low monthly usage does not guarantee enough simultaneous rooms, participants, recordings, or streams.</li></ol><h2 id="what-is-the-best-video-calling-sdk-for-developers">What Is the Best Video Calling SDK for Developers?</h2><p>VideoSDK is the best starting point under this ranking model when one managed API must support several client stacks and both Prebuilt and custom interfaces. The correct winner changes when self-hosting, browser embedding, AWS integration, or social effects become non-negotiable.</p><ul><li><strong>Choose VideoSDK</strong> when one managed room API must serve web, native mobile, React Native, Flutter, Unity, Python, or C++, with both Prebuilt and custom UI paths.</li><li><strong>Choose Daily</strong> when a browser-first product needs an established iframe component, native mobile options, and graduated usage pricing.</li><li><strong>Choose LiveKit</strong> when an open-source media server or self-hosting is a firm requirement.</li><li><strong>Choose Agora</strong> when broad device coverage and geographically distributed RTC use justify a larger product catalogue.</li><li><strong>Choose 100ms</strong> when roles and templates should control classroom, webinar, or event permissions.</li><li><strong>Choose Cloudflare RealtimeKit</strong> when Cloudflare consolidation is valuable and beta risk is acceptable.</li><li><strong>Choose ZEGOCLOUD</strong> when mobile social effects and entertainment workflows are central to the product.</li><li><strong>Choose Zoom Video SDK</strong> when Zoom's media stack and raw media access outweigh framework-specific quickstarts.</li><li><strong>Choose Whereby Embedded</strong> when a polished browser meeting should ship with minimal interface development.</li><li><strong>Choose Amazon Chime SDK</strong> when AWS-native media processing justifies additional implementation work.</li></ul><h2 id="can-sendbird-and-videosdk-work-together">Can Sendbird and VideoSDK Work Together?</h2><p><strong>Yes. An application can keep Sendbird Chat or another unrelated Sendbird product while routing new video rooms through VideoSDK.</strong> The two systems do not need to exchange live media.</p><p>Keep your application's canonical user ID in the backend, then map it to Sendbird and VideoSDK participant records. When a user starts a call, the server creates or selects a VideoSDK room and returns a short-lived token. The client joins through the appropriate VideoSDK SDK.</p><p>Do not expose the VideoSDK API secret inside a browser or mobile application. <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/authentication-and-tokens" rel="noreferrer">Generate tokens</a> on a trusted server, grant the minimum permissions, and keep a mapping between old Sendbird call identifiers and new VideoSDK room identifiers during migration.</p><p>A safe rollout has five phases: copy call metadata, route internal test users to VideoSDK, compare join and recovery metrics, expand by user cohort, and remove old Calls code after rollback windows expire. Avoid publishing the same camera or microphone track to both vendors in production.</p><h2 id="production-factors-most-rankings-miss">Production Factors Most Rankings Miss</h2><p>A video API comparison is incomplete until it covers authentication, mobile lifecycle, degraded networks, observability, compliance cost, and the ability to leave the provider later.</p><p><strong>Token security:</strong> Generate meeting credentials on a trusted server. Use short expiry periods and minimum permissions. A leaked long-lived token can allow an unauthorised user to join a room even when the interface hides it.</p><p><strong>Mobile lifecycle:</strong> Test Bluetooth changes, incoming telephone calls, camera rotation, backgrounding, and application restoration. A browser proof of concept says little about React Native, Flutter, iOS, or Android behaviour.</p><p><strong>Network degradation:</strong> Validate <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a> connectivity, forced TCP, low-bandwidth adaptation, reconnection behaviour, and the interface shown when media freezes. Track join failures and time to first remote frame by region.</p><p><strong>Observability:</strong> Require participant-level logs, call-quality metrics, webhooks, and enough retention to investigate support tickets. Confirm whether analytics retention changes between free and paid plans.</p><p><strong>Compliance economics:</strong> <a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api" rel="noreferrer">HIPAA support,</a> a BAA, regional routing, or dedicated proxy controls can require monthly add-ons. Compliance availability and compliance price are separate selection criteria.</p><p><strong>Exit plan:</strong> Store canonical user, room, and call identifiers in your own system. Put vendor-specific room creation behind a service interface to reduce future migration work.</p><h2 id="video-calling-api-glossary">Video Calling API Glossary</h2><blockquote><strong>Participant-minute:</strong> One participant connected for one minute. A 20-minute call with two people produces 40 participant-minutes.</blockquote><blockquote><strong>Room:</strong> A logical meeting space where participants exchange audio, video, screen-share, and data tracks. VideoSDK identifies each room with a room ID.</blockquote><blockquote><strong>SFU:</strong> A selective forwarding unit receives published media streams and forwards appropriate layers to subscribers without compositing every participant into one video.</blockquote><blockquote><strong>Meeting token:</strong> A credential authorising a participant to join a room. VideoSDK recommends generating production tokens through a trusted server path.</blockquote><blockquote><strong>Prebuilt UI:</strong> A ready-made meeting interface handling common controls and layouts. VideoSDK, Daily, Zoom, 100ms, RealtimeKit, ZEGOCLOUD, and Whereby offer different forms of prebuilt experience.</blockquote><h2 id="key-takeaways-for-teams-comparing-sendbird-alternatives">Key Takeaways for Teams Comparing Sendbird Alternatives</h2><ul><li>VideoSDK ranks first under this disclosed model for its documented client coverage, Prebuilt and custom interface options, and public usage pricing.</li><li>Daily is a strong browser-first option, while LiveKit becomes the first choice when self-hosting is mandatory.</li><li>Cloudflare RealtimeKit replaces maintenance-mode Dyte in a current shortlist, but beta status creates production risk.</li><li>Base media rates are not comparable until resolution, topology, recording, support, compliance, data transfer, and concurrency are normalised.</li><li>A staged migration can replace Sendbird Calls without forcing a team to replace Sendbird Chat or other unrelated products.</li></ul><h2 id="conclusion">Conclusion</h2><p>The right Sendbird alternatives shortlist depends on the constraint your team cannot compromise. VideoSDK is the recommended starting point under this model for broad client coverage and a managed Prebuilt-or-custom path. Daily deserves a browser-first proof of concept, while LiveKit leads when self-hosting is mandatory.</p><p>Before committing, reproduce your production call layout, estimate every billed service, and test the same failure scenarios across providers. You can review <a href="https://www.videosdk.live/pricing">VideoSDK pricing</a>, follow a framework-specific quickstart, or <a href="https://app.videosdk.live/login">create an account</a> to build a proof of concept.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-best-sendbird-alternative-for-video-calls">What is the best Sendbird alternative for video calls?</h3><p>VideoSDK ranks first under this article's model for its documented SDK coverage, Prebuilt and custom interface paths, and published participant-minute pricing. LiveKit is better when self-hosting is mandatory, while Daily can be better for a browser-first iframe launch.</p><h3 id="is-videosdk-cheaper-than-sendbird-calls">Is VideoSDK cheaper than Sendbird Calls?</h3><p>Not in every scenario. Sendbird currently publishes different peer-to-peer and server-relayed video rates, while VideoSDK prices by participant-minute and aggregate viewed resolution. Compare identical call topologies, layouts, participant counts, recordings, support, compliance, and concurrency before choosing.</p><h3 id="why-is-twilio-video-not-in-the-ranked-top-ten">Why is Twilio Video not in the ranked top ten?</h3><p>Twilio Video remains active. Twilio reversed its previously announced end-of-life decision in October 2024, so describing it as discontinued would be incorrect. It sits outside this editorial top ten because Twilio's stated roadmap now focuses more narrowly on customer-engagement video. Existing Twilio customers should still evaluate it.</p><h3 id="which-sendbird-alternatives-support-mobile-sdks">Which Sendbird alternatives support mobile SDKs?</h3><p>The providers with documented mobile support include VideoSDK, Daily, LiveKit, Agora, 100ms, Cloudflare RealtimeKit, ZEGOCLOUD, Zoom Video SDK, and Amazon Chime SDK. Whereby mainly appeals to browser-first products, so teams needing native primitives should compare it carefully.</p><h3 id="can-i-replace-sendbird-calls-but-keep-sendbird-chat">Can I replace Sendbird Calls but keep Sendbird Chat?</h3><p>Yes. Keep canonical users in your backend, route new call creation and meeting tokens through VideoSDK, and leave unrelated Sendbird products unchanged. The two vendors do not need to exchange media directly.</p><h3 id="which-sendbird-alternative-can-be-self-hosted">Which Sendbird alternative can be self-hosted?</h3><p>LiveKit is the clearest self-hosted option in this comparison because its media server is open source. Self-hosting provides control, but your team becomes responsible for upgrades, bandwidth, scaling, monitoring, and incident response.</p><h3 id="how-should-i-test-a-video-calling-api-before-migration">How should I test a video calling API before migration?</h3><p>Test join success, time to first remote frame, reconnection, screen sharing, recording completion, Bluetooth switching, mobile backgrounding, and TURN fallback. Repeat identical scenarios in your main user regions and compare participant-level logs rather than relying only on perceived picture quality.</p><h2 id="further-reading-for-video-developers">Further Reading for Video Developers</h2><ul><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">Build a React video calling application</a></li><li><a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Start with the VideoSDK Prebuilt UI</a></li><li><a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">Review the real-time communication REST API</a></li><li><a href="https://docs.videosdk.live/code-sample">Explore VideoSDK code samples</a></li><li><a href="https://videosdk.live/developer-hub/webrtc/live-video-call-api">Understand how a live video call API works</a></li></ul>]]></content:encoded></item><item><title><![CDATA[What is a live shopping API? A VideoSDK Guide]]></title><description><![CDATA[Explore how live shopping APIs connect real-time video, product data, chat and checkout, with architecture guidance, platform comparisons, pricing details and ecommerce use cases.]]></description><link>https://www.videosdk.live/blog/live-shopping-api</link><guid isPermaLink="false">6a6b1373b3240feb748c9068</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 03 Aug 2026 13:19:05 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-3--2026--06_16_56-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>A live shopping API connects real-time video, audience interaction, product information, cart, and checkout inside one shoppable livestream. VideoSDK can manage the interactive media layer while your commerce backend protects transactional data.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-3--2026--06_16_56-PM.png" alt="What is a live shopping API? A VideoSDK Guide"/><p>The commercial opportunity is already substantial. <a href="https://www.emarketer.com/content/whatnot-s-growth-shows-livestream-shopping-finding-its-place/" rel="noreferrer nofollow">EMARKETER forecasts</a> US livestream retail ecommerce sales will reach $19.8 billion in 2026, representing 35% year-on-year growth.</p><p>For developers, the challenge is joining video and commerce without weakening either system. Product managers must also compare platform control, implementation time, scale, and operating cost.</p><p>Merchants usually ask a simpler question: can this work with an existing Shopify store? Yes, provided Shopify remains authoritative for products, inventory, carts, orders, and payments.</p><p>This guide explains the complete architecture, compares leading approaches, and builds a practical React flow using VideoSDK <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">Interactive Live Streaming</a>, PubSub, Node.js, and a commerce API.</p><h2 id="what-is-a-live-shopping-api">What Is a Live Shopping API?</h2><blockquote>A <a href="https://www.videosdk.live/solutions/live-shopping" rel="noreferrer">live shopping API</a> is the programmable layer that connects a live video session with product data, audience events, and commerce actions such as cart creation and checkout.</blockquote><p>It is rarely one endpoint. A production implementation normally combines media APIs, messaging APIs, catalogue services, inventory checks, cart operations, payment processing, analytics, and moderation tools.</p><p>Media APIs carry the host's audio and video. Real-time messaging moves chat, reactions, polls, invitations, and product spotlight events between participants inside the session.</p><p>Commerce APIs validate product variants, price, available stock, discounts, tax, delivery eligibility, cart state, checkout, payments, and orders on trusted servers.</p><p>VideoSDK supplies rooms, media tracks, participant modes, session events, and PubSub. Shopify, another ecommerce platform, or your custom backend should continue to own transactional state.</p><p>The <a href="https://www.w3.org/TR/webrtc/">W3C WebRTC Recommendation</a> defines the browser foundation for real-time audio, video, and data exchange. VideoSDK provides higher-level SDK objects and managed infrastructure around those protocols.</p><p>This boundary prevents a serious mistake. A product card received from a host's browser can become stale or be manipulated, so it must never determine availability or price.</p><h2 id="live-shopping-sdk-vs-live-commerce-api">Live Shopping SDK vs Live Commerce API</h2><p>A live shopping SDK mainly provides client-side media and interaction tools, while a live commerce API usually manages server-side products, shows, availability, carts, or advisor workflows.</p><p>A live shopping SDK reduces the platform-specific work required for camera capture, playback, participant state, device permissions, chat, reactions, screen sharing, and session lifecycle events.</p><p>A live commerce API may create shows, associate products, check advisor availability, pin products, import catalogues, update carts, or connect buyers with an existing checkout system.</p><p>The labels overlap between vendors. Evaluate which system owns media, interaction, product state, checkout, customer data, recordings, analytics, and moderation instead of relying on product terminology.</p><p>In the architecture below, VideoSDK is the interactive live streaming ecommerce layer. Shopify or another commerce service remains the source of truth for every transaction.</p><h2 id="how-does-a-live-shopping-api-work">How Does a Live Shopping API Work?</h2><p>A live shopping API works by authenticating participants, starting a live room, synchronising a verified product identifier, validating current product state, and completing checkout through the commerce backend.</p><p>The complete flow has seven parts:</p><ol><li>A trusted server authenticates the host and creates a live room.</li><li>The server issues short-lived, room-scoped access tokens to hosts and shoppers.</li><li>Hosts join in a mode that can publish media, while viewers receive media only.</li><li>The host publishes a verified product identifier through a real-time topic.</li><li>Each viewer retrieves current product details from the commerce backend.</li><li>Add-to-cart requests are revalidated for price, stock, region, and purchase limits.</li><li>Room, engagement, cart, and order events are joined inside the analytics pipeline.</li></ol><p>The fast path handles media and audience events. The authoritative path approves products, money, and inventory. A good implementation keeps both paths connected without confusing their responsibilities.</p><h2 id="live-shopping-api-architecture-with-videosdk">Live Shopping API Architecture with VideoSDK</h2><p>A reliable live shopping API architecture separates responsive audience events from authoritative commerce transactions, because the two flows require different latency, security, and consistency rules.</p><p>Hosts and viewers join the same VideoSDK room with different participant modes. Hosts use <code>SEND_AND_RECV</code>, while shoppers normally use <code>RECV_ONLY</code> to consume host media.</p><p>VideoSDK PubSub can transport chat, polls, reactions, invitations, and product identifiers. The viewer then requests verified product information before displaying a purchase button.</p><p>The current <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-react-ils">VideoSDK React ILS quickstart</a> documents up to 100 hosts or co-hosts and 2,000 real-time viewers for its example architecture. Confirm account-specific limits before launch.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Layer</th>
<th>Primary responsibility</th>
<th>Recommended owner</th>
<th>Failure rule</th>
</tr>
</thead>
<tbody>
<tr>
<td>Live media</td>
<td>Camera, microphone, host video, viewer playback</td>
<td>VideoSDK ILS</td>
<td>Reduce quality before dropping the session</td>
</tr>
<tr>
<td>Audience events</td>
<td>Chat, polls, reactions, product spotlight identifiers</td>
<td>VideoSDK PubSub</td>
<td>Treat messages as transient interface state</td>
</tr>
<tr>
<td>Product data</td>
<td>Product, variant, price, image, availability</td>
<td>Commerce backend</td>
<td>Re-fetch before cart submission</td>
</tr>
<tr>
<td>Cart and checkout</td>
<td>Line items, discounts, tax, payment, orders</td>
<td>Commerce platform</td>
<td>Keep server-authoritative and idempotent</td>
</tr>
<tr>
<td>Analytics</td>
<td>Joins, watch time, clicks, carts, purchases</td>
<td>VideoSDK plus first-party analytics</td>
<td>Correlate room, session, and commerce identifiers</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The central rule is simple: VideoSDK transports real-time communication, while the commerce backend approves money-related state. This approach keeps interactions responsive without weakening transaction integrity.</p><h3 id="watch-live-shopping-in-action">Watch Live Shopping in Action</h3><p>The architecture becomes easier to understand when you see the complete experience. This VideoSDK walkthrough demonstrates how live commerce shopping can be added to an ecommerce website.</p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/ZMLMBmkSwDA?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" title="🔴 Add Live Commerce Shopping in E-commerce Website | Video SDK"/></figure><p>With the customer experience clear, let’s examine the SDK support and implementation choices for building it across web and mobile applications.</p><h2 id="mobile-live-shopping-sdk-support">Mobile Live Shopping SDK Support</h2><p>VideoSDK provides development paths for browser, React Native, Flutter, Android, and iOS applications, allowing teams to reuse the same real-time and commerce boundaries across clients.</p><p>Its current <a href="https://www.videosdk.live/interactive-live-streaming">interactive live streaming SDK page</a> lists JavaScript, Flutter, React, React Native, Android, iOS, Python, and Unity among the available options.</p><p>Platform availability does not guarantee identical behaviour across every SDK release. Verify background handling, media permissions, participant modes, reconnect behaviour, orientation, and device support for each target.</p><p>The commerce backend should remain authoritative across every client. A web shopper and an Android shopper must receive the same price, inventory decision, and purchase limit.</p><h2 id="how-do-you-choose-a-live-shopping-api">How Do You Choose a Live Shopping API?</h2><p>Choose a live shopping API by matching interaction latency, commerce ownership, platform coverage, customisation, moderation, operational control, and total event cost to your product requirements.</p><p>Start with the interaction loop. If a shopper asks about fit, the host's answer and the viewer's experience must remain close enough for the conversation to feel natural.</p><p>Next, decide whether your team wants infrastructure or a complete live commerce platform. A managed platform can shorten merchant setup, while infrastructure offers greater product and interface control.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Approach</th>
<th>Best for</th>
<th>Main strength</th>
<th>Main trade-off</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK ILS plus commerce API</td>
<td>Custom web or mobile products with an existing backend</td>
<td>Flexible media, participant roles, PubSub, and interface control</td>
<td>Your team builds product, cart, moderation, and checkout integration</td>
</tr>
<tr>
<td>Managed live commerce platform</td>
<td>Merchants seeking campaign, product, replay, and checkout tools</td>
<td>Faster setup for standard retail workflows</td>
<td>Less control over media behaviour and application architecture</td>
</tr>
<tr>
<td>Raw WebRTC and custom media servers</td>
<td>Specialised protocol, hosting, or compliance requirements</td>
<td>Maximum infrastructure control</td>
<td>Highest engineering and operations cost</td>
</tr>
<tr>
<td>HLS or LL-HLS broadcast with commerce overlay</td>
<td>Large, mostly passive audiences</td>
<td>Broad playback reach and strong replay workflows</td>
<td>Added delay makes two-way conversation less natural</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Do not choose from a headline latency number alone. Test join time, audio clarity, bitrate adaptation, reconnection, product synchronisation, cart completion, moderation, and checkout on real shopper devices.</p><h2 id="videosdk-vs-bambuser-vs-channelizeio-vs-mux">VideoSDK vs. Bambuser vs. Channelize.io vs. Mux</h2><blockquote>VideoSDK is best considered custom real-time infrastructure, Bambuser and Channelize.io are commerce-focused platforms, and Mux is broadcast video infrastructure that requires separate interaction and commerce services.</blockquote>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Provider</th>
<th>Product focus</th>
<th>Commerce features</th>
<th>Interaction model</th>
<th>Best fit</th>
<th>Pricing context</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td>WebRTC-based interactive media and communication SDKs</td>
<td>Bring your own catalogue, inventory, cart, and checkout</td>
<td>Participant modes, PubSub, co-hosting, polls, chat, and reactions</td>
<td>Teams building a custom web or mobile live shopping product</td>
<td>$20 starting balance, prepaid pay-as-you-go, and enterprise plans</td>
</tr>
<tr>
<td>Bambuser</td>
<td>Managed video commerce and live shopping</td>
<td>Shows, users, product interactions, and commerce-oriented workflows</td>
<td>Managed one-to-many and one-to-one shopping experiences</td>
<td>Brands wanting a mature, commerce-specific platform</td>
<td>Lite, Standard, and Enterprise plans; contact vendor for rates</td>
</tr>
<tr>
<td>Channelize.io</td>
<td>All-in-one live shopping and shoppable video platform</td>
<td>Product spotlighting, cart, checkout, analytics, and pre-built ecommerce integrations</td>
<td>Chat, reactions, multi-host shows, replay, and simulcasting</td>
<td>Merchants prioritising fast Shopify or ecommerce deployment</td>
<td>Free trial and usage-based plans measured through viewing minutes</td>
</tr>
<tr>
<td>Mux</td>
<td>API-first live and on-demand video delivery</td>
<td>No built-in catalogue, cart, or checkout</td>
<td>RTMP or SRT ingest with HLS or LL-HLS playback</td>
<td>Large broadcast audiences, recordings, and video analytics</td>
<td>Live input starts at published per-minute rates; usage-based delivery and storage</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p><a href="https://bambuser.com/" rel="noreferrer nofollow">Bambuser's</a> official REST documentation describes server-side management for shows, users, and interactions. Its <a href="https://bambuser.com/pricing" rel="noreferrer nofollow">pricing page</a> lists plan tiers but directs buyers to contact the company.</p><p><a href="https://channelize.io/" rel="noreferrer nofollow">Channelize.io</a> provides pre-built Shopify, WooCommerce, Magento, PrestaShop, Wix, and Shoplazza integrations. Its <a href="https://pricing.channelize.io/plans" rel="noreferrer nofollow">pricing page</a> explains its free trial and viewing-minute model.</p><p><a href="https://www.mux.com/" rel="noreferrer nofollow">Mux</a> accepts SRT or <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a> ingest and delivers <a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer">HLS</a>. Its live page lists approximately 4 to 7 seconds for low-latency playback, while its <a href="https://www.mux.com/docs/guides/live-streaming-faqs" rel="noreferrer nofollow">FAQ</a> says direct WebRTC ingest is unavailable.</p><p><a href="https://www.videosdk.live/">VideoSDK</a> is a stronger fit when teams need custom live shopping workflows, real-time features such as product spotlights and audience interactions, or consistent media infrastructure across web and mobile applications.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Category</th>
<th>Service</th>
<th>Price</th>
<th>Billing unit</th>
</tr>
</thead>
<tbody>
<tr>
<td>Interactive live streaming</td>
<td>Speaker</td>
<td>$0.004</td>
<td>Per speaker minute</td>
</tr>
<tr>
<td>Interactive live streaming</td>
<td>Viewer</td>
<td>$0.002</td>
<td>Per viewer minute</td>
</tr>
<tr>
<td>Interactive live streaming</td>
<td>RTMP restreaming</td>
<td>$0.03</td>
<td>Per streaming minute</td>
</tr>
<tr>
<td>Interactive live streaming</td>
<td>Session Quality Analytics</td>
<td>Free</td>
<td>Included</td>
</tr>
<tr>
<td>Recording and storage</td>
<td>Meeting recording</td>
<td>$0.015</td>
<td>Per recorded minute</td>
</tr>
<tr>
<td>Recording and storage</td>
<td>Individual participant recording</td>
<td>$0.006</td>
<td>Per participant minute</td>
</tr>
<tr>
<td>Recording and storage</td>
<td>Storage</td>
<td>$0.003</td>
<td>Per minute of video stored</td>
</tr>
<tr>
<td>Transcription and summary</td>
<td>Real-time transcription</td>
<td>$0.02</td>
<td>Per transcription minute</td>
</tr>
<tr>
<td>Transcription and summary</td>
<td>Post-call transcription</td>
<td>$0.004</td>
<td>Per transcription minute</td>
</tr>
<tr>
<td>Transcription and summary</td>
<td>Prompt-based summary</td>
<td>$0.0045</td>
<td>Per summary minute</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>See the <a href="https://www.videosdk.live/pricing">VideoSDK pricing page</a> for current rates, usage calculations, free credits, and enterprise volume discounts.</p><h2 id="adding-live-shopping-to-shopify">Adding Live Shopping to Shopify</h2><p>A Shopify merchant can add live shopping by embedding the stream in the storefront, synchronising a product variant, and using Shopify for cart, inventory, checkout, and orders.</p><p>A theme storefront can use Shopify's Ajax API, while a headless storefront can use the Storefront GraphQL API. Both approaches keep existing payment and fulfilment workflows intact.</p><p>The VideoSDK room can appear on a dedicated live event page, a product page, or a floating player. Product spotlights should map to stable Shopify variant identifiers.</p><p>Social discovery can remain part of the campaign. A merchant may simulcast to YouTube or Instagram Live while directing shoppers towards an owned shoppable livestream with first-party data.</p><p>TikTok Shop APIs serve sellers operating inside TikTok's commerce ecosystem. They do not replace the embedded media, participant, and interaction layer required inside a custom storefront or application.</p><p>This difference matters for ownership. A brand-controlled experience can keep its customer journey, analytics, loyalty programme, accessibility rules, and experimentation framework within the existing commerce stack.</p><h2 id="live-shopping-api-pricing">Live Shopping API Pricing</h2><p>Live shopping API cost depends on host minutes, viewer minutes, video quality, recording, broadcast egress, storage, moderation, and the fees charged by your commerce platform.</p><p>VideoSDK currently gives new accounts a one-time <a href="https://www.videosdk.live/interactive-live-streaming">$20 starting balance</a> without requiring a credit card. Its 2026 billing model includes prepaid pay-as-you-go and enterprise options.</p><p>The exact cost depends on the media path and features selected. Use the current <a href="https://www.videosdk.live/pricing">VideoSDK pricing page</a> when modelling an event instead of copying old unit rates.</p><p>For example, a 90-minute show with two hosts creates 180 host participant minutes. If 1,000 viewers watch for 24 minutes each, that adds 24,000 viewer minutes.</p><p>Add recording, RTMP simulcasting, storage, captions, moderation, and commerce fees separately. Model a normal event and a peak launch event before committing to the architecture.</p><p>Managed live commerce platforms often price by shows, included viewing minutes, concurrent audience, or enterprise contracts. Infrastructure vendors usually expose more granular usage-based video pricing.</p><p>Compare total ownership cost, not media cost alone. Include implementation, merchant operations, analytics, support, moderation, maintenance, checkout integration, and the cost of future product changes.</p><h2 id="production-requirements-most-tutorials-skip">Production Requirements Most Tutorials Skip</h2><p>A production live shopping API depends on access control, transaction integrity, network recovery, moderation, privacy, and observability, not simply successful video playback in development.</p><h3 id="protect-tokens-and-roles">Protect Tokens and Roles</h3><p>Issue short-lived tokens only after authenticating the user. Host and moderator privileges must come from server-side policy, not from a role value selected inside React.</p><p>The IETF <a href="https://datatracker.ietf.org/doc/rfc8827/">WebRTC Security Architecture</a> requires SRTP for media and DTLS for data channels. Your application still owns identity, access, privacy, and commerce security.</p><h3 id="protect-price-and-inventory">Protect Price and Inventory</h3><p>Treat every product spotlight as a display hint. The commerce API must return the current price, inventory, region eligibility, tax treatment, and purchase limit.</p><p>For limited drops or auctions, process requests through one authoritative service. Use idempotency keys so retries and repeated taps cannot create duplicate reservations, bids, or orders.</p><h3 id="design-for-network-changes">Design for Network Changes</h3><p>Mobile shoppers can switch between Wi-Fi and cellular networks during a show. Preserve room and cart identifiers so media reconnects without destroying the shopper's purchase context.</p><p>Test token expiry, reconnects, background transitions, camera changes, low bandwidth, host disconnects, PubSub delays, and recovery after the viewer returns to the foreground.</p><h3 id="moderate-every-interaction-surface">Moderate Every Interaction Surface</h3><p>Chat, co-host invitations, product claims, reactions, and user-generated video carry different abuse risks. Define permissions, rate limits, reporting, blocking, removal, and evidence retention separately.</p><p>Never send payment details, delivery addresses, or private account information through PubSub. Use authenticated HTTPS endpoints and the commerce provider's supported payment flow for sensitive operations.</p><h3 id="measure-the-whole-purchase-journey">Measure the Whole Purchase Journey</h3><p>Track join failures, watch time, media quality, reconnect attempts, messages, spotlight impressions, product clicks, cart errors, checkout starts, completed orders, refunds, and moderation actions.</p><p>Correlate events using <code>roomId</code>, VideoSDK <code>sessionId</code>, commerce session ID, and an analytics user identifier. Avoid placing unnecessary personal data inside the event payload.</p><p>Stream uptime is not the only success metric. Measure product-view-to-click rate, cart success, checkout completion, questions resolved, returns, and failures by device and network class.</p><h2 id="live-shopping-api-example-a-limited-product-drop">Live Shopping API Example: A Limited Product Drop</h2><p>A limited product drop demonstrates why live communication and inventory allocation need separate consistency rules, even when both actions appear inside the same shopper interface.</p><p>Imagine a Shopify fashion store launching 200 numbered jackets. The host joins the VideoSDK room in <code>SEND_AND_RECV</code>, while shoppers enter as <code>RECV_ONLY</code> participants.</p><p>When the host features variant <code>40123456789012</code>, VideoSDK PubSub updates every visible product card. Each shopper then requests the current price and availability from Shopify.</p><p>If 500 people tap simultaneously, Shopify or a reservation service determines which requests succeed. VideoSDK keeps the demonstration live but does not allocate the inventory.</p><p>The host can invite a verified buyer on stage for a sizing question. After answering, the participant returns to <code>RECV_ONLY</code>, reducing unnecessary upstream media usage.</p><p>Idempotency keys prevent duplicate reservations, while a sold-out event updates the product card. The stream remains active so the host can present the next available product.</p><p>This design provides immediate audience feedback without allowing the fastest client message to override the transaction system's authoritative decision about stock or payment.</p><h2 id="live-shopping-use-cases-beyond-product-demos">Live Shopping Use Cases Beyond Product Demos</h2><p>Live shopping APIs also support virtual consultations, influencer selling, auctions, product launches, virtual try-on guidance, support-led commerce, and recorded shoppable video experiences.</p><ul><li><strong>Influencer live shopping:</strong> A creator hosts inside a branded experience while moderators manage chat, product spotlights, discount rules, and audience questions.</li><li><strong>Co-host selling:</strong> Multiple experts demonstrate a product together, or a shopper briefly joins the stage for a personalised answer.</li><li><strong>Virtual try-on guidance:</strong> Beauty, fashion, eyewear, or furniture brands combine interactive video with an AR or computer-vision service outside the media layer.</li><li><strong>Live auctions and drops:</strong> The stream transports the experience, while an authoritative bidding or inventory service resolves concurrency and purchase rights.</li><li><strong>Personal shopping:</strong> An advisor assists one buyer or a small group, using private messages and product recommendations connected to current catalogue data.</li><li><strong>Shoppable video replay:</strong> The live recording becomes an on-demand asset whose product markers remain clickable after the original event has ended.</li></ul><p>These patterns can run on a retailer's site, inside a mobile app, or alongside social distribution. The ownership boundary remains consistent across every channel.</p><h2 id="live-shopping-api-glossary">Live Shopping API Glossary</h2><blockquote><strong>Room:</strong> A VideoSDK room is the real-time space that hosts and viewers join using a unique room identifier. One room may contain multiple sessions over time.</blockquote><blockquote><strong>Participant mode:</strong> <code>SEND_AND_RECV</code> allows a host to publish and consume media. <code>RECV_ONLY</code> allows a viewer to consume media without publishing microphone or camera tracks.</blockquote><blockquote><strong>Meeting token:</strong> A Meeting Token is a server-signed JWT controlling room access. Production tokens should be short-lived, room-scoped, and issued after application authentication.</blockquote><blockquote><strong>Product spotlight:</strong> A product spotlight is a real-time event telling viewers which verified product identifier to display. The commerce backend still owns current price and stock.</blockquote><blockquote><strong>PubSub:</strong> VideoSDK PubSub is a topic-based messaging mechanism for chat, polls, reactions, invitations, product spotlights, and other room events that accompany the media stream.</blockquote><blockquote><strong>Shoppable livestream:</strong> A shoppable livestream combines a live product experience with interactive purchase actions. A shoppable video may also refer to an on-demand recording with product links.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>A live shopping API combines real-time media, audience interaction, product data, cart, checkout, orders, analytics, and moderation.</li><li>VideoSDK can provide custom interactive media, participant modes, PubSub, co-hosting, and cross-platform SDKs for web and mobile shopping experiences.</li><li>The commerce backend must remain authoritative for variants, stock, price, discounts, tax, cart, payments, and orders.</li><li>VideoSDK suits custom product teams, while Bambuser and Channelize.io suit commerce-led deployments and Mux suits broadcast-oriented video infrastructure.</li><li>Short-lived tokens, server-authorised roles, idempotency, moderation, network recovery, and end-to-end purchase testing are production requirements.</li><li>Pricing should be modelled from host minutes, viewer minutes, media add-ons, commerce fees, and the engineering cost of operating the complete system.</li></ul><h2 id="conclusion">Conclusion</h2><p>A production live shopping API succeeds when the conversation feels immediate and every transaction remains authoritative. VideoSDK provides the media, participant, and real-time interaction primitives for that separation.</p><p>React and mobile teams can build the interface they need while keeping catalogue, inventory, cart, checkout, and payments inside an established commerce backend such as Shopify.</p><p>Start with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-react-ils">VideoSDK React ILS quickstart</a>, create a <a href="https://app.videosdk.live/login">free account</a>, and test one complete journey from host token to successful checkout.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-a-live-shopping-api-1">What is a live shopping API?</h3><p>A live shopping API is a set of programmable services connecting live video, audience interaction, product information, cart, and checkout. Several APIs normally work together in production.</p><h3 id="can-videosdk-power-a-live-shopping-app">Can VideoSDK power a live shopping app?</h3><p>Yes. VideoSDK can provide the real-time media and interaction layer through ILS rooms, participant modes, PubSub, chat, polls, recordings, reactions, and participant lifecycle events.</p><h3 id="does-videosdk-handle-products-and-payments">Does VideoSDK handle products and payments?</h3><p>No. Shopify or another commerce backend should own catalogue, price, inventory, discounts, cart, checkout, tax, orders, refunds, and payment processing in this architecture.</p><h3 id="does-videosdk-support-mobile-live-shopping-apps">Does VideoSDK support mobile live shopping apps?</h3><p>VideoSDK lists React Native, Flutter, Android, and iOS development paths for interactive live streaming. Connect every client to the same server-authoritative commerce services and access policies.</p><h3 id="is-webrtc-or-hls-better-for-live-shopping">Is WebRTC or HLS better for live shopping?</h3><p>WebRTC suits real-time questions, co-hosting, consultations, and live bidding. HLS or LL-HLS suits large, mostly passive audiences where reach and replay matter more than immediate participation.</p><h3 id="how-do-i-connect-live-shopping-to-shopify">How do I connect live shopping to Shopify?</h3><p>Use Shopify's Ajax Cart API for theme storefronts or its Storefront API for headless applications. Revalidate the product variant before cart creation and use Shopify's supported checkout.</p><h3 id="is-videosdk-an-alternative-to-bambuser">Is VideoSDK an alternative to Bambuser?</h3><p>They solve different layers. VideoSDK offers custom interactive media infrastructure, while Bambuser offers a managed video-commerce platform. Choose according to control, implementation time, and merchant tooling needs.</p><h3 id="how-much-does-a-live-shopping-api-cost">How much does a live shopping API cost?</h3><p>Cost depends on host and viewer minutes, quality, recording, egress, storage, moderation, and commerce services. VideoSDK currently offers a $20 starting balance and usage-based billing.</p><h3 id="can-i-use-a-live-shopping-api-with-tiktok-shop-or-instagram-live">Can I use a live shopping API with TikTok Shop or Instagram Live?</h3><p>Yes, as separate channels. Social platforms can provide discovery or marketplace distribution, while VideoSDK powers the branded experience inside your own website or mobile application.</p><h3 id="what-features-should-a-live-shopping-platform-include">What features should a live shopping platform include?</h3><p>It should include low-latency media, host and viewer roles, chat, moderation, product spotlighting, secure tokens, analytics, recording, network recovery, cart integration, and server-authoritative checkout.</p><h2 id="related-videosdk-guides">Related VideoSDK Guides</h2><ul><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-react-ils">React interactive live streaming quickstart</a></li><li><a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/authentication-and-token">Authentication and token generation</a></li><li><a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/audience-management/change-mode">Audience mode switching</a></li><li><a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/chat-during-livestream">Chat during a live stream</a></li><li><a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">VideoSDK real-time communication REST APIs</a></li><li><a href="https://github.com/videosdk-live">VideoSDK code samples on GitHub</a></li></ul>]]></content:encoded></item><item><title><![CDATA[SFU vs MCU vs Mesh WebRTC: 2026 Architecture Guide]]></title><description><![CDATA[Compare SFU vs MCU vs Mesh WebRTC across bandwidth, latency, CPU, scalability, security, layouts, and operating cost. Includes formulas, a topology decision framework, hybrid architecture, and a practical VideoSDK SFU example.]]></description><link>https://www.videosdk.live/blog/sfu-vs-mcu-vs-mesh-webrtc</link><guid isPermaLink="false">6a6dbb08b3240feb748c9137</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 03 Aug 2026 10:45:02 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-3--2026--03_01_12-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>Use Mesh WebRTC for one-to-one calls or tightly controlled rooms with only a few participants. Use an SFU for interactive multiparty calls that need low latency, flexible layouts, and selective video delivery. Use an MCU when constrained endpoints need one composed stream. VideoSDK uses managed SFU routing for production video, audio, and interactive streaming applications.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-3--2026--03_01_12-PM.png" alt="SFU vs MCU vs Mesh WebRTC: 2026 Architecture Guide"/><p>Choosing between SFU vs MCU vs Mesh WebRTC determines how much bandwidth each participant needs, where media gets processed, how your application scales, and whether the server can access unencrypted media.</p><p>Mesh sends media directly between every participant. An <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu" rel="noreferrer">SFU</a> receives each stream once and selectively forwards encoded streams. An MCU decodes incoming streams, mixes them, and sends one or more composed outputs. For most modern multiparty applications, an SFU is the practical default. Mesh remains useful for small calls, while MCU architecture still fits legacy endpoints, server-controlled layouts, and specialized media-processing workflows.</p><p>VideoSDK provides a managed SFU-based room architecture, so developers can build multiparty video without operating signaling, routing, congestion control, and media servers themselves. Its React SDK also exposes multistream publishing and server-side controls for pausing incoming streams.</p><h2 id="sfu-vs-mcu-vs-mesh-webrtc-quick-comparison">SFU vs MCU vs Mesh WebRTC: Quick Comparison</h2><p>SFU is usually the strongest default for interactive group calls, but each topology solves a different infrastructure problem.</p>
<!--kg-card-begin: html-->
<table><thead><tr><th>Factor</th><th>Mesh</th><th>SFU</th><th>MCU</th></tr></thead><tbody><tr><td>Media path</td><td>Peer to every peer</td><td>Participant to SFU to selected recipients</td><td>Participant to MCU to composed output</td></tr><tr><td>Client upload</td><td>Grows with every participant</td><td>Usually one stream or one simulcast set</td><td>Usually one stream</td></tr><tr><td>Client download</td><td>One stream per remote participant</td><td>Selected remote streams and layers</td><td>One composed stream</td></tr><tr><td>Client processing</td><td>High as the room grows</td><td>Moderate, depends on received streams</td><td>Low</td></tr><tr><td>Server processing</td><td>No central media processing</td><td>Packet forwarding and stream selection</td><td>Decode, mix, compose, and re-encode</td></tr><tr><td>Server bandwidth</td><td>Minimal, excluding TURN</td><td>High egress at scale</td><td>Moderate to high</td></tr><tr><td>Added media latency</td><td>Lowest on a direct route</td><td>Low</td><td>Highest of the three</td></tr><tr><td>Layout control</td><td>Client-side</td><td>Client-side</td><td>Server-side</td></tr><tr><td>End-to-end encryption potential</td><td>Straightforward between peers</td><td>Possible with encoded-frame encryption</td><td>Conflicts with server-side mixing</td></tr><tr><td>Best fit</td><td>One-to-one and tiny rooms</td><td>Interactive multiparty applications</td><td>Fixed composites and constrained endpoints</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>The IETF describes mesh, media-mixing, and selective-forwarding as distinct <a href="https://www.videosdk.live/blog/what-is-rtp-protocol" rel="noreferrer">RTP</a> topologies. A media-mixing server creates a new outgoing stream, while a selective forwarding middlebox routes source streams without creating a conventional composite.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-3--2026--12_23_27-PM.png" class="kg-image" alt="SFU vs MCU vs Mesh WebRTC: 2026 Architecture Guide" loading="lazy" width="1672" height="941"/></figure><h2 id="what-are-mesh-sfu-and-mcu">What Are Mesh, SFU, and MCU?</h2><p><strong>Mesh, SFU, and MCU are media-routing topologies, not separate replacements for the WebRTC standard.</strong></p><p>WebRTC defines browser and application APIs for capturing, sending, receiving, and securing real-time media. The topology determines how those WebRTC media connections are arranged once more than two participants join.</p><h3 id="what-is-mesh-webrtc">What Is Mesh WebRTC?</h3><p><strong>Mesh WebRTC is defined as a topology where every participant establishes a media connection with every other participant.</strong></p><p>Mesh works by making each device encode and upload a separate copy of its media for every remote peer. A four-person room requires each participant to maintain three outgoing and three incoming media paths.</p><p>The total number of peer-to-peer connections is:</p><pre><code class="language-text">Connections = N × (N - 1) ÷ 2
</code></pre><p>For six participants:</p><pre><code class="language-text">Connections = 6 × 5 ÷ 2 = 15
</code></pre><p>The IETF’s mesh topology shows each endpoint communicating directly with the other endpoints in the RTP session.</p><p>Mesh does not always mean packets avoid all servers. Signaling still requires an application server, and media may travel through a TURN relay when a direct ICE path cannot be established.</p><h3 id="what-is-an-sfu">What Is an SFU?</h3><p><strong>An SFU is defined as a media server that receives encoded streams and selectively forwards them to other participants.</strong></p><p>An SFU works by accepting one published stream or simulcast set from each participant. It then decides which source, quality layer, or media type each receiver should get.</p><p>The server normally avoids decoding every video frame. This keeps processing latency and CPU usage lower than an MCU, though the SFU may consume substantial network bandwidth as it forwards many streams.</p><p>RFC 7667 associates selective forwarding with simulcast and scalable video coding. Modern SFU implementations such as mediasoup also expose simulcast, SVC, and transport-wide bandwidth estimation as core routing capabilities.</p><p>VideoSDK follows this managed SFU model. For example, its SDK can instruct the server to stop forwarding selected incoming media, and its multistream configuration publishes several video resolutions for receiver-specific selection.</p><h3 id="what-is-an-mcu">What Is an MCU?</h3><p><strong>An MCU is defined as a media server that processes multiple incoming streams and creates a new mixed output.</strong></p><p>An MCU works by decoding incoming audio or video, arranging or mixing the uncompressed media, encoding the result, and sending it to participants.</p><p>RFC 7667 calls this a “Media-Mixing Mixer.” The standard explains that an MCU may produce one common tiled layout or personalized layouts for individual recipients. It also identifies three costs: media-processing resources, quality loss from re-encoding, and additional latency.</p><p>The advantage appears at the endpoint. A participant may need to decode only one video stream, regardless of how many people are in the room.</p><h2 id="how-mesh-webrtc-scales">How Mesh WebRTC Scales</h2><p>Mesh shifts infrastructure work to participant devices, causing upload bandwidth and encoder load to grow linearly per user and quadratically across the room.</p><p>Assume every participant sends a 1.5 Mbps video stream and everyone sees everyone else.</p><p>For <code>N</code> participants and bitrate <code>B</code>:</p><pre><code class="language-text">Per-participant upload = (N - 1) × B
Per-participant download = (N - 1) × B
Aggregate room upload = N × (N - 1) × B
</code></pre><p>For six participants:</p><pre><code class="language-text">Per-participant upload = 5 × 1.5 Mbps = 7.5 Mbps
Per-participant download = 5 × 1.5 Mbps = 7.5 Mbps
Aggregate upload = 6 × 5 × 1.5 Mbps = 45 Mbps
</code></pre><p>That simplified calculation excludes audio, retransmissions, protocol overhead, screen sharing, and TURN relay traffic.</p><p>Bandwidth is only part of the problem. Each participant may also run multiple encoders, encryption contexts, congestion controllers, and peer connections. Mobile devices can hit thermal, battery, and CPU limits before the network reaches its theoretical capacity.</p><h3 id="when-to-use-mesh-webrtc">When to Use Mesh WebRTC</h3><p>Use Mesh when:</p><ul><li>The product is strictly one-to-one.</li><li>Rooms normally contain two or three participants.</li><li>Direct peer media is a hard architectural requirement.</li><li>You want to avoid central media-server bandwidth.</li><li>Every participant uses a predictable network and capable device.</li></ul><p>Mesh is <strong>not a safe default</strong> for rooms whose size, device mix, or network conditions can change after launch.</p><p>A TURN server can also erase the expected “no media server” cost advantage. When direct NAT traversal fails, <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a> relays the encrypted packets and incurs bandwidth costs without providing SFU-style stream selection.</p><h2 id="how-an-sfu-scales-webrtc">How an SFU Scales WebRTC</h2><p>An SFU reduces participant upload requirements by accepting each published stream once, then moving the scaling burden to server egress and receiver decoding.</p><p>In a single-encoding model:</p><pre><code class="language-text">Per-participant upload ≈ B
Maximum participant download ≈ (N - 1) × B
SFU ingress ≈ N × B
SFU maximum egress ≈ N × (N - 1) × B
</code></pre><p>The SFU’s theoretical full-room egress can still grow quadratically. Production systems control it through active-speaker selection, pagination, last-N forwarding, stream subscriptions, paused off-screen video, simulcast, and SVC.</p><p>This distinction matters. An SFU does not eliminate bandwidth. It moves upload pressure away from participant devices and gives the application a central point for selecting what each receiver actually needs.</p><h3 id="simulcast-and-svc">Simulcast and SVC</h3><p>Simulcast sends multiple independently encoded versions of the same video. For example, a publisher may send high, medium, and low resolutions. The SFU forwards the version that fits each receiver’s layout and available bandwidth.</p><p>Scalable Video Coding encodes one stream with layers that can be selectively forwarded or dropped. Both approaches let the SFU adapt delivery without decoding and recomposing the video.</p><p>VideoSDK’s current multistream documentation gives a concrete example: a 720p-capable device may publish 720p, 360p, and 90p layers. VideoSDK can then deliver an appropriate layer based on the receiving participant’s network.</p><p>Simulcast increases sender upload above the single-stream formula because several encodings are published. That extra upload buys better receiver adaptation and avoids forcing every participant to download the highest-quality stream.</p><h3 id="when-to-use-an-sfu">When to Use an SFU</h3><p>Use an SFU when:</p><ul><li>Rooms can grow beyond a few participants.</li><li>Participants need separate video tiles.</li><li>The UI supports active-speaker, gallery, sidebar, or custom layouts.</li><li>Receivers have different network conditions.</li><li>The application needs selective subscriptions.</li><li>You need screen sharing, recording, moderation, or server analytics.</li><li>Low interactive latency matters.</li><li>The same room serves web, mobile, desktop, or embedded clients.</li></ul><p>An SFU is <strong>not automatically cheap</strong>. A large room with many visible publishers can create significant egress, and each receiver must still decode the streams it receives.</p><h2 id="how-an-mcu-processes-webrtc-media">How an MCU Processes WebRTC Media</h2><p>An MCU lowers endpoint complexity by moving decoding, layout, mixing, and encoding into centralised infrastructure.</p><p>A typical MCU receives one stream from each participant. The server decodes those inputs and creates a composite, such as a 3 by 3 gallery. It then encodes the composite and sends it to each participant.</p><p>A simple common-layout model looks like this:</p><pre><code class="language-text">Per-participant upload ≈ B
Per-participant download ≈ C
MCU input decoding jobs = N
MCU output encoding jobs = 1 or more
</code></pre><p><code>C</code> is the composite bitrate. If every participant receives a personalized layout, the MCU may need several output encoders rather than one.</p><p>This server-side processing makes MCU capacity harder to predict from bandwidth alone. Resolution, frame rate, codec, number of layouts, hardware acceleration, and compositing effects all influence CPU or GPU requirements.</p><h3 id="when-to-use-an-mcu">When to Use an MCU</h3><p>Use an MCU when:</p><ul><li>Legacy endpoints can decode only one stream.</li><li>A SIP or hardware-conferencing environment requires a composed feed.</li><li>The application needs a fixed server-controlled layout.</li><li>Client devices are severely resource-constrained.</li><li>Server-side overlays, watermarks, or transformations must appear identically for every viewer.</li><li>A single composite output is required for downstream broadcasting.</li></ul><p>An MCU is <strong>not the preferred choice</strong> when every user needs independent participant tracks, the lowest possible processing delay, or media that the server cannot decrypt.</p><h2 id="which-webrtc-topology-is-best">Which WebRTC Topology Is Best?</h2><p><strong>The best WebRTC topology is the least complex option that still survives your largest room, weakest device, and worst expected network.</strong></p><p>Use the following decision sequence.</p><ol><li><strong>Start with room size.</strong> For strict one-to-one calls, Mesh may be sufficient. For unpredictable or multiparty rooms, evaluate an SFU first.</li><li><strong>Check the required layout.</strong> Independent participant tiles favor an SFU. One fixed composite favors an MCU.</li><li><strong>Model the weakest client.</strong> An MCU minimizes receiver decoding. An SFU lets you reduce subscriptions and video layers. Mesh offers little central control.</li><li><strong>Define the encryption boundary.</strong> If the server must never access encoded media content, Mesh or an <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/security/E2EE" rel="noreferrer">E2EE-capable</a> SFU is more suitable than an MCU.</li><li><strong>Calculate both client and server bandwidth.</strong> SFU client upload is efficient, but server egress can dominate operating cost.</li><li><strong>Decide who operates the infrastructure.</strong> Self-hosting offers control but requires media-server operations. A managed platform such as VideoSDK removes that operational layer.</li><li><strong>Plan recording and broadcast outputs separately.</strong> Interactive delivery and composed recording do not have to use the same media path.</li></ol><h3 id="conditional-verdict">Conditional Verdict</h3><ul><li><strong>Choose Mesh</strong> for strict one-to-one communication or tiny controlled rooms.</li><li><strong>Choose SFU</strong> for most multiparty video calling, audio rooms, interactive classrooms, telehealth sessions, and live collaboration.</li><li><strong>Choose MCU</strong> for single-stream endpoints, fixed compositions, and server-side media transformation.</li><li><strong>Choose a hybrid</strong> when participants need low-latency SFU delivery but recordings or broadcasts need an MCU-style composite.</li></ul><h2 id="security-and-end-to-end-encryption">Security and End-to-End Encryption</h2><p><strong>Topology changes which systems must access media content and therefore changes the achievable encryption model.</strong></p><p>Standard WebRTC connections protect media in transit using secure transport. That protection does not automatically mean media remains encrypted from every intermediary involved in the call.</p><h3 id="mesh-security">Mesh Security</h3><p>In Mesh, each peer negotiates secure media directly with every other peer. A TURN relay can transport packets without decoding their media payloads.</p><p>This architecture provides a simple trust boundary, but every participant remains an endpoint with access to the media it receives.</p><h3 id="sfu-security">SFU Security</h3><p>An SFU needs enough packet and stream metadata to route media, request keyframes, and select layers. Traditional hop-by-hop WebRTC transport allows the SFU to receive and forward protected streams between separate peer connections.</p><p>Application-layer frame encryption can place another encryption layer around encoded media. The W3C WebRTC Encoded Transform specification exposes encoded-frame transforms and SFrame cipher suites for this class of design.</p><p>With this pattern, an SFU can route encrypted frames while endpoints retain content keys. Some server-side capabilities may become unavailable, including media transcription, content moderation, server-side visual processing, or conventional compositing.</p><h3 id="mcu-security">MCU Security</h3><p>An MCU must normally decode media before mixing it. That requires access to the media content at the server.</p><p>This makes a conventional MCU incompatible with strict end-to-end encryption where only participant endpoints possess decryption keys. You must either trust the MCU as an endpoint, weaken the encryption boundary, or use specialized trusted processing.</p><p>The security question is therefore not “Does WebRTC use encryption?” The useful question is “Which components are allowed to decrypt the media?”</p><h2 id="using-sfu-and-mcu-together">Using SFU and MCU Together</h2><p><strong>A hybrid SFU plus compositor architecture separates interactive delivery from media production.</strong></p><p>Participants can exchange individual low-latency streams through an SFU. A separate compositor can subscribe to selected streams, decode them, create a branded layout, and send the result to recording, <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a>, or HLS infrastructure.</p><p>This gives interactive participants flexible client-side layouts while producing one consistent broadcast or evidence file.</p><p>A second hybrid pattern uses Mesh for one-to-one calls and migrates to an SFU when another participant joins. This can reduce media-server use, but live topology migration adds signalling, state synchronisation, reconnection, and quality-transition complexity.</p><p>For many teams, keeping one SFU path for both one-to-one and group calls is operationally safer, even if it is not the theoretical minimum-cost path.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/08/ChatGPT-Image-Aug-3--2026--01_01_00-PM.png" class="kg-image" alt="SFU vs MCU vs Mesh WebRTC: 2026 Architecture Guide" loading="lazy" width="1672" height="941"/></figure><h2 id="how-videosdk-uses-managed-sfu-routing">How VideoSDK Uses Managed SFU Routing</h2><p>VideoSDK is suitable when a team wants SFU behavior without deploying and operating its own media-server fleet.</p><p>VideoSDK organizes communication around rooms, participants, and media streams. Its SDKs and REST APIs handle room creation, participant lifecycle, publishing, subscriptions, recording, and related RTC workflows.</p><p>The managed model is most relevant when your engineering team wants to control the application experience but not the packet-routing infrastructure.</p><h3 id="configure-multistream-publishing-in-react">Configure Multistream Publishing in React</h3><p><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">VideoSDK’s React</a> <code>MeetingProvider</code> accepts a server-generated token and a <code>multiStream</code> option. Current documentation lists <code>multiStream</code> as enabled by default and recommends disabling it for one-to-one calls.</p><pre><code class="language-jsx">import { MeetingProvider } from "@videosdk.live/react-sdk";
import MeetingView from "./MeetingView";

export default function VideoRoom({
  token,
  meetingId,
  participantName,
  expectedParticipants = 4,
}) {
  if (!token || !meetingId) {
    return &lt;p&gt;Missing meeting credentials.&lt;/p&gt;;
  }

  return (
    &lt;MeetingProvider
      token={token}
      config={{
        meetingId,
        name: participantName || "Guest",
        micEnabled: true,
        webcamEnabled: true,
        multiStream: expectedParticipants &gt; 2,
      }}
    &gt;
      &lt;MeetingView /&gt;
    &lt;/MeetingProvider&gt;
  );
}
</code></pre><p><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token" rel="noreferrer">Generate the token</a> on your backend. VideoSDK’s <code>MeetingProvider</code> documentation explicitly requires an authentication token generated by the server.</p><h3 id="stop-forwarding-off-screen-video">Stop Forwarding Off-Screen Video</h3><p>VideoSDK’s <code>pauseAllStreams()</code> and <code>resumeAllStreams()</code> methods control incoming remote media. The underlying server-side operation tells the SFU to stop or resume forwarding the chosen media type.</p><pre><code class="language-jsx">import { useEffect } from "react";
import { useMeeting } from "@videosdk.live/react-sdk";

export default function VisibilityBandwidthControl() {
  const { pauseAllStreams, resumeAllStreams } = useMeeting();

  useEffect(() =&gt; {
    const handleVisibilityChange = () =&gt; {
      try {
        if (document.hidden) {
          pauseAllStreams("video");
        } else {
          resumeAllStreams("video");
        }
      } catch (error) {
        console.error("Unable to update remote video forwarding:", error);
      }
    };

    document.addEventListener("visibilitychange", handleVisibilityChange);

    return () =&gt; {
      document.removeEventListener(
        "visibilitychange",
        handleVisibilityChange
      );
    };
  }, [pauseAllStreams, resumeAllStreams]);

  return null;
}
</code></pre><p>This is one practical advantage of an SFU: the application can stop unnecessary delivery without asking every remote publisher to renegotiate its camera stream.</p><h3 id="where-videosdk-may-not-fit">Where VideoSDK May Not Fit</h3><p>VideoSDK is not the right choice for every infrastructure strategy.</p><p>A self-hosted SFU may fit better when you need full control over packet routing, server placement, custom congestion algorithms, or infrastructure source code. An MCU-specific platform may fit better when every output requires custom server-side composition or transcoding.</p><p>A managed platform also creates usage-based operating costs and platform dependency. Teams with strict on-premise, air-gapped, or unusual media-processing requirements should validate deployment and data-routing options before choosing it.</p><h2 id="production-factors-most-comparisons-miss">Production Factors Most Comparisons Miss</h2><p>Real WebRTC failures usually come from networks, devices, and operational assumptions rather than the topology diagram itself.</p><h3 id="turn-usage">TURN Usage</h3><p>Test how often calls require TURN in your target regions and enterprise networks. A Mesh call relayed through TURN still consumes server bandwidth, while retaining Mesh’s multiple-stream upload pattern.</p><h3 id="receiver-decode-capacity">Receiver Decode Capacity</h3><p>An SFU can forward 20 streams, but that does not mean a mobile device should decode 20 videos. Limit visible tiles, pause hidden tracks, and request lower layers for thumbnails.</p><h3 id="simulcast-upload-cost">Simulcast Upload Cost</h3><p>Simulcast reduces receiver waste but increases sender upload. Test the sum of all published layers on ordinary mobile and home networks.</p><h3 id="firewall-and-pre-call-testing">Firewall and Pre-Call Testing</h3><p>Camera permission, microphone permission, UDP reachability, TURN fallback, browser codec support, and available upload bandwidth should be checked before a high-stakes call.</p><p>VideoSDK provides a <code>runPreCallTest()</code> flow that connects to its SFU using a token and tests media and network readiness before the participant joins a room.</p><h3 id="failure-domains">Failure Domains</h3><p>Mesh has no single media-routing server, but one weak participant can still have several poor connections. An SFU creates central infrastructure dependencies, so multi-region routing, health checks, failover, and observability matter.</p><h3 id="recording-architecture">Recording Architecture</h3><p>Decide whether you need:</p><ul><li>Individual participant tracks</li><li>One composite recording</li><li>Separate audio and video files</li><li>Live RTMP output</li><li>Post-call transcription</li><li>Tamper-evident evidence storage</li></ul><p>The answer may require an SFU plus a separate recording or composition pipeline rather than one topology for every output.</p><h2 id="modeled-example-six-person-tutoring-room">Modeled Example: Six-Person Tutoring Room</h2><p>A six-person tutoring room shows why SFU architecture normally outperforms Mesh while preserving more flexibility than an MCU.</p><p>Assume one tutor, five students, and 1.5 Mbps source video.</p><h3 id="mesh">Mesh</h3><p>Each participant uploads five streams:</p><pre><code class="language-text">5 × 1.5 Mbps = 7.5 Mbps upload per participant
</code></pre><p>The tutor’s laptop must encode five copies and decode five incoming videos. A student on mobile data faces the same connection count.</p><h3 id="sfu">SFU</h3><p>Each participant publishes one stream or simulcast set to the SFU. The application displays the tutor in high resolution and students as lower-resolution thumbnails.</p><p>When the tutor shares a screen, the application can prioritize the screen and active speaker while pausing videos outside the visible page.</p><h3 id="mcu">MCU</h3><p>Each participant sends one stream and receives one classroom composite. Client requirements are low, but students cannot independently enlarge a participant without the MCU producing another composition.</p><p>For an interactive tutoring application, the SFU offers the strongest balance. For a low-powered classroom appliance that only displays one fixed grid, an MCU may be reasonable.</p><p>A VideoSDK implementation can use <a href="https://docs.videosdk.live/react/api/sdk-reference/meeting-provider" rel="noreferrer">multistream</a> publishing, participant-level rendering, and SFU forwarding controls while the application retains its own classroom layout. VideoSDK’s rendering guide exposes participants through <code>useMeeting</code> and individual media state through <code>useParticipant</code>.</p><h2 id="sfu-vs-mcu-vs-mesh-webrtc-decision-checklist">SFU vs MCU vs Mesh WebRTC Decision Checklist</h2><p><strong>A topology decision should be based on measured constraints rather than a universal participant threshold.</strong></p>
<!--kg-card-begin: html-->
<table><thead><tr><th>Question</th><th>Mesh signal</th><th>SFU signal</th><th>MCU signal</th></tr></thead><tbody><tr><td>Are calls permanently one-to-one?</td><td>Strong</td><td>Possible</td><td>Weak</td></tr><tr><td>Can rooms grow unpredictably?</td><td>Weak</td><td>Strong</td><td>Moderate</td></tr><tr><td>Do users need independent video tiles?</td><td>Moderate</td><td>Strong</td><td>Weak</td></tr><tr><td>Are endpoints unable to decode several streams?</td><td>Weak</td><td>Moderate</td><td>Strong</td></tr><tr><td>Must the server never decode media?</td><td>Strong</td><td>Strong with suitable E2EE</td><td>Weak</td></tr><tr><td>Is one fixed composed output required?</td><td>Weak</td><td>Requires compositor</td><td>Strong</td></tr><tr><td>Do receivers have different bandwidth?</td><td>Weak</td><td>Strong with layers</td><td>Moderate</td></tr><tr><td>Does the team want managed infrastructure?</td><td>Not required</td><td>VideoSDK or another managed SFU</td><td>Specialized provider</td></tr><tr><td>Is full packet-routing control required?</td><td>Strong client control</td><td>Self-hosted SFU</td><td>Self-hosted MCU</td></tr><tr><td>Is server-side visual processing required?</td><td>Weak</td><td>Requires separate processor</td><td>Strong</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>Do not select Mesh only because the first version has three participants. Select it only when product rules prevent the room and feature set from expanding.</p><h2 id="definitions-glossary">Definitions Glossary</h2><blockquote><strong>WebRTC topology:</strong> The arrangement of endpoints and media-processing servers through which real-time audio, video, and data travel.</blockquote><blockquote><strong>Mesh:</strong> A multiparty topology where every participant maintains a direct media connection with every other participant.</blockquote><blockquote><strong>Selective Forwarding Unit:</strong> A media server that receives encoded streams and selectively forwards chosen sources or layers without creating a conventional mixed video.</blockquote><blockquote><strong>Multipoint Control Unit:</strong> A media-processing server that decodes several inputs and creates one or more new mixed outputs.</blockquote><blockquote><strong>Simulcast:</strong> A publishing technique where a sender encodes the same camera source at several resolutions or bitrates for receiver-specific selection.</blockquote><blockquote><strong>Scalable Video Coding:</strong> A codec structure that divides one encoded stream into dependency layers that can be selectively forwarded or discarded.</blockquote><blockquote><strong>TURN server:</strong> A relay used when endpoints cannot establish a direct media route through normal ICE connectivity checks.</blockquote><blockquote><strong>VideoSDK room:</strong> A managed real-time session identified by a meeting ID, containing participants and their published audio, video, screen-share, or data streams.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>Mesh is appropriate for one-to-one communication and tiny fixed rooms, but its bandwidth and peer-connection count rise quickly.</li><li>An SFU is the strongest default for interactive multiparty WebRTC because it reduces publisher upload and enables selective delivery.</li><li>An MCU reduces endpoint decoding by creating one composite stream, but server processing, latency, and trust requirements increase.</li><li>SFU server egress can remain substantial, so applications must control subscriptions, visible tiles, and quality layers.</li><li>Strict end-to-end encryption is incompatible with conventional MCU mixing because the server must decode media.</li><li>VideoSDK provides managed SFU routing, multistream publishing, participant media APIs, and server-side controls for remote stream forwarding.</li></ul><h2 id="conclusion">Conclusion</h2><p>The correct choice in SFU vs MCU vs Mesh WebRTC depends on room size, endpoint capacity, layout control, encryption boundaries, and operational ownership. Mesh fits controlled one-to-one calls. MCU fits fixed composite outputs and constrained clients. SFU fits most interactive multiparty applications.</p><p>To test an SFU-based implementation, follow the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React quickstart</a> or create a free account at <a href="https://app.videosdk.live/login">videosdk.live</a>.</p><p>Still deciding between Mesh, SFU, MCU, or a hybrid WebRTC architecture?</p><p>Join the VideoSDK <a href="https://discord.com/invite/Gpmj6eCq5u" rel="noreferrer">Discord community</a> to discuss your architecture, ask implementation questions, and get feedback from developers building production video and audio applications.</p><p>Prefer an open community discussion? Share your use case or architecture question in <a href="https://www.reddit.com/r/videosdklive/" rel="noreferrer">r/videosdklive</a>.</p><h3 id="what-is-the-main-difference-between-sfu-mcu-and-mesh-webrtc">What is the main difference between SFU, MCU, and Mesh WebRTC?</h3><p>The main difference is where media gets duplicated or processed. Mesh duplicates streams at each participant, an SFU forwards selected encoded streams through a server, and an MCU decodes and combines streams into a new output.</p><h3 id="is-sfu-better-than-mcu-for-webrtc">Is SFU better than MCU for WebRTC?</h3><p>An SFU is better than an MCU for most interactive multiparty applications because it preserves individual streams, supports flexible layouts, and avoids continuous server-side transcoding. An MCU is better when endpoints need one composed stream or when the server must generate a fixed layout.</p><h3 id="how-many-participants-can-mesh-webrtc-support">How many participants can Mesh WebRTC support?</h3><p>Mesh WebRTC commonly works best for one-to-one calls or rooms containing only a few participants. There is no universal hard limit because bitrate, device CPU, browser, TURN usage, resolution, and network quality determine when performance becomes unacceptable.</p><h3 id="does-an-sfu-decode-video">Does an SFU decode video?</h3><p>An SFU does not normally decode and re-encode every video stream. It inspects the packet and stream information needed for forwarding, congestion control, subscription decisions, simulcast selection, and SVC layer selection.</p><h3 id="can-an-sfu-support-end-to-end-encryption">Can an SFU support end-to-end encryption?</h3><p>Yes, an SFU can support application-layer end-to-end encryption when endpoints encrypt encoded frames and the server forwards them without possessing content keys. This design can restrict server-side recording, transcription, moderation, and composition features.</p><h3 id="when-should-an-mcu-be-used">When should an MCU be used?</h3><p>An MCU should be used when recipients need one composed stream, endpoints cannot decode several videos, or the server must apply a fixed layout or media transformation. It should not be the default when independent tracks, minimum processing latency, or strict endpoint-only encryption are required.</p><h3 id="does-videosdk-use-an-sfu">Does VideoSDK use an SFU?</h3><p>Yes, VideoSDK uses managed SFU routing for real-time rooms. Its documentation includes SFU-level controls for pausing incoming forwarding and multistream publishing for receiver-specific resolution selection.</p><h3 id="can-mesh-sfu-and-mcu-be-combined">Can Mesh, SFU, and MCU be combined?</h3><p>Yes, Mesh, SFU, and MCU concepts can be combined in a hybrid system. A common design uses an SFU for interactive participants and an MCU-style compositor for recording or broadcast output, while another design uses Mesh for one-to-one calls and migrates larger rooms to an SFU.</p><h2 id="sources-and-further-readings">Sources and Further Readings</h2><ul><li><a href="https://www.rfc-editor.org/rfc/rfc7667.html">IETF RFC 7667: RTP Topologies</a></li><li><a href="https://www.w3.org/TR/webrtc/">W3C WebRTC Specification</a></li><li><a href="https://www.w3.org/TR/webrtc-encoded-transform/">W3C WebRTC Encoded Transform</a></li><li><a href="https://docs.videosdk.live/react/api/sdk-reference/meeting-provider">VideoSDK React MeetingProvider</a></li><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React Quickstart</a>,</li></ul>]]></content:encoded></item><item><title><![CDATA[Top 10 Video KYC API: Expert Tested & Ranked]]></title><description><![CDATA[Compare ten Video KYC API providers using a transparent 2026 methodology. See where VideoSDK, HyperVerge, Cashfree, AuthBridge, and global alternatives fit.]]></description><link>https://www.videosdk.live/blog/video-kyc-api</link><guid isPermaLink="false">6a69e1ddb3240feb748c8fef</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 31 Jul 2026 14:22:40 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-29--2026--07_06_00-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>A Video KYC API combines a live identity interview with document capture, face comparison, liveness checks, audit evidence, and workflow APIs. VideoSDK ranks first for developer-controlled embedded workflows, while Digio suits for Multi-Regulator Indian Compliance and Cashfree offers especially clear public integration documentation.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-29--2026--07_06_00-PM.png" alt="Top 10 Video KYC API: Expert Tested & Ranked"/><p><strong>Last reviewed:</strong> 31 July 2026</p><p>A polished demo passport tells you very little about production Video KYC, where weak networks, interrupted sessions, deepfakes, audit reviews, and regional rules shape outcomes.</p><p>This 2026 ranking compares ten providers for engineering teams building embedded onboarding. It prioritises API control, live-session operations, verification functions, compliance support, and procurement clarity.</p><p>The result is not a universal winner. It is a conditional shortlist showing which provider fits custom infrastructure, turnkey Indian V-CIP, or global identification.</p><h3 id="who-this-guide-is-for">Who this guide is for</h3><p>This guide serves two different search intents that often appear under the same keyword.</p><ul><li><strong>For RBI V-CIP in India:</strong> VideoSDK and providers 2 to 7 are the most relevant starting points for banks, NBFCs, payment aggregators, insurers, and Indian fintech teams.</li><li><strong>For global identity verification:</strong> VideoSDK can supply the custom communication layer, while providers 8 to 10 focus more directly on cross-border or European video-identification operations.</li></ul><p>The right shortlist depends on the regulated entity type, jurisdiction, operating model, document sources, agent requirements, and where identity evidence may be processed or stored.</p><h2 id="what-is-a-video-kyc-api">What is a Video KYC API?</h2><p>A video KYC API is defined as a programmable service for verifying a customer's identity through live or recorded video, supported by documents and biometric checks.</p><p>It works by creating a verification session, capturing consent and evidence, checking liveness and identity, then returning status, artefacts, and audit data.</p><p>In India's regulated financial sector, the related term is Video-based Customer Identification Process, or V-CIP. The current <a href="https://rbidocs.rbi.org.in/rdocs/notification/PDFs/169MD.pdf">RBI Commercial Banks KYC Directions 2025</a> require a live, secure, end-to-end encrypted interaction with trained officials for applicable regulated workflows.</p><p>The RBI also requires geotagging, PAN verification, varied real-time questions, liveness protection, timestamped recordings, activity logs, security testing, and safe storage for applicable V-CIP implementations.</p><blockquote>VideoSDK combines real-time meeting rooms with enterprise OCR, face-match, spoof-detection, and face-count APIs. However, regulated entities still need authoritative PAN or Aadhaar checks, trained operations, retention controls, and final compliance ownership.</blockquote><p>The distinction matters because some vendors sell complete identity journeys, while others provide composable infrastructure. Comparing those categories without explaining the difference produces a misleading ranking.</p><h2 id="how-we-tested-each-video-kyc-api">How We Tested Each Video KYC API</h2><p>This provider assessment reviews verifiable product evidence available on 29 July 2026, not marketing adjectives or undisclosed claims about accuracy, latency, or regulatory approval.</p><p>We inspected official product pages, public API references, request and response examples, SDK coverage, sandbox visibility, workflow controls, security documentation, audit capabilities, and pricing accessibility.</p><h3 id="ranking-criteria">Ranking criteria</h3><ul><li><strong>Developer control, 35%:</strong> API coverage, SDK choice, interface ownership, event handling, and ability to embed the journey on the regulated entity's domain.</li><li><strong>Live-session operations, 25%:</strong> call control, recording, reconnection, agent routing, pre-call checks, low-bandwidth handling, and real-time evidence capture.</li><li><strong>Verification functions, 15%:</strong> OCR, face matching, presentation-attack detection, document validation, government-source checks, and review workflows.</li><li><strong>Compliance support, 15%:</strong> consent, geotagging, timestamps, logs, storage controls, encryption, deployment options, and evidence export for applicable jurisdictions.</li><li><strong>Procurement clarity, 10%:</strong> public documentation, test access, pricing visibility, support routes, and clear statements about limitations or enterprise-only features.</li></ul><p>This weighting deliberately favours product teams building an embedded, custom Video KYC experience. A bank purchasing a complete managed V-CIP operation should weight verification and operations more heavily.</p><h3 id="what-%E2%80%9Cexpert-tested%E2%80%9D-means-here">What “expert tested” means here</h3><p>Testing covered documentation pathways and publicly visible integration surfaces. We did not execute paid production calls, audit vendor infrastructure, or independently measure biometric accuracy, uptime, or completion rates.</p><p>Claims requiring private credentials, customer datasets, contracts, or regulated production traffic remain unverified. Treat this ranking as a technical shortlist, then run your own proof of concept.</p><p>Pricing changes quickly and most vendors use negotiated enterprise contracts. Confirm current rates, minimum commitments, storage charges, agent costs, and biometric API fees before procurement.</p><h2 id="video-kyc-api-comparison-table">Video KYC API Comparison Table</h2><p>The clearest comparison starts by separating custom infrastructure from managed verification suites, because they solve different parts of the onboarding stack and require different teams.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Rank</th>
<th>Provider</th>
<th>Product model</th>
<th>Strongest documented capability</th>
<th>Best for</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>VideoSDK</td>
<td>Composable RTC plus identity APIs</td>
<td>Custom live-video control across web and mobile SDKs</td>
<td>Teams building an owned V-CIP journey</td>
</tr>
<tr>
<td>2</td>
<td>Digio</td>
<td>Multi-regulator compliance &amp; workflow suite</td>
<td>Unified RBI, SEBI, and IRDAI compliance with DigiLocker &amp; DigiStudio</td>
<td>Financial groups spanning banking, broking, and insurance</td>
</tr>
<tr>
<td>3</td>
<td>Cashfree Secure ID</td>
<td>API-led regulated verification</td>
<td>Clear session creation, status, sandbox, agent, and auditor documentation</td>
<td>Indian fintechs wanting documented REST workflows</td>
</tr>
<tr>
<td>4</td>
<td>Surepass</td>
<td>API marketplace plus Video KYC</td>
<td>Low-bandwidth (100kbps) calls, WhatsApp V-CIP, and 300+ verification APIs</td>
<td>Fintechs needing Video KYC alongside broad verification APIs</td>
</tr>
<tr>
<td>5</td>
<td>HyperVerge</td>
<td>Turnkey onboarding and Video KYC</td>
<td>Indian pre-qualification, routing, biometrics, and agent operations</td>
<td>Banks, NBFCs, and high-volume fintechs</td>
</tr>
<tr>
<td>6</td>
<td>IDfy</td>
<td>Managed and self-serve Video KYC</td>
<td>Pre-call checks, reconnection, autosave, and review operations</td>
<td>Enterprises prioritising completion continuity</td>
</tr>
<tr>
<td>7</td>
<td>Signzy</td>
<td>API marketplace plus no-code journeys</td>
<td>India Stack workflows with iframe and result APIs</td>
<td>Large regulated teams needing workflow configuration</td>
</tr>
<tr>
<td>8</td>
<td>AuthBridge</td>
<td>Managed Indian Video KYC</td>
<td>PAN, offline Aadhaar, OCR, face match, liveness, geotagging, and agent assignment</td>
<td>Indian BFSI teams wanting a broad V-CIP workflow</td>
</tr>
<tr>
<td>9</td>
<td>Gridlines</td>
<td>Configurable onboarding infrastructure</td>
<td>Modular identity, Video KYC, risk, review, and eSign journeys</td>
<td>Product teams assembling Indian onboarding flows</td>
</tr>
<tr>
<td>10</td>
<td>Shufti Pro</td>
<td>Global VideoIdent service</td>
<td>Live specialist interviews with API evidence packs</td>
<td>Cross-border teams needing human-assisted verification</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>VideoSDK leads this developer-first ranking because it gives teams the most direct control over the live experience. HyperVerge leads when a complete Indian operational workflow matters more.</p><p>No table can prove production suitability. Use it to reduce a longlist, then validate difficult devices, fraud cases, peak queues, storage rules, and reviewer operations.</p><h2 id="top-10-video-kyc-api-providers">Top 10 Video KYC API Providers </h2><p>These ten providers are ranked for engineering usefulness, evidence quality, and production flexibility, with a clear best-for condition attached to every recommendation.</p><p>AuthBridge is included because its current official material documents a complete Indian Video KYC flow, including live video, PAN validation, offline Aadhaar, OCR, face match, liveness, geotagging, agent assignment, encrypted recordings, and audit reporting. Surepass remains a possible longlist vendor, but it was not ranked because its public Video KYC lifecycle and operational evidence were less detailed at the review date.</p><h3 id="1-videosdk-best-for-custom-v-cip-infrastructure">1. VideoSDK: Best for Custom V-CIP Infrastructure</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.29.39-PM-9.png" class="kg-image" alt="Top 10 Video KYC API: Expert Tested & Ranked" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://www.videosdk.live/">VideoSDK</a> is the strongest fit when your team needs to own the customer interface, agent console, workflow logic, and integrations around a live identity session.</p><p>Its <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a> documents meeting rooms, participant hooks, media controls, events, recordings, security controls, geo-fencing, and SDK paths for web, mobile, Unity, IoT, C++, and Python.</p><p>For identity verification, VideoSDK documents enterprise-only <a href="https://docs.videosdk.live/react/guide/identity-verification/ocr">OCR</a>, <a href="https://docs.videosdk.live/react/guide/identity-verification/face-match-api">face matching</a>, <a href="https://docs.videosdk.live/react/guide/identity-verification/face-spoof-detection">spoof detection</a>, and face-count APIs. These REST endpoints can sit beside the real-time meeting layer.</p><p>That combination helps a regulated entity run the audiovisual interaction from its own application domain, capture participant evidence, and connect specialist services without surrendering the complete product experience.</p><p>The limitation is equally important. VideoSDK does not publicly document a complete native stack for PAN authority checks, Aadhaar verification, sanctions screening, PEP screening, or managed KYC-agent operations.</p><p>You must add those services, define review logic, configure retention, and obtain legal approval. VideoSDK provides infrastructure and verification primitives, but it does not transfer compliance responsibility.</p><p><strong>Best for:</strong> banks, NBFCs, fintech platforms, insurers, and identity vendors building a branded, modular verification workflow across several client platforms.</p><p><strong>Pricing visibility:</strong> current public pricing shows pay-as-you-go and enterprise options with a $20 starting credit. Identity verification APIs are documented as enterprise-only, so obtain a written quote.</p><h3 id="2-digio-best-for-multi-regulator-indian-compliance">2. Digio: Best for Multi-Regulator Indian Compliance</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-31-191227.png" class="kg-image" alt="Top 10 Video KYC API: Expert Tested & Ranked" loading="lazy" width="1517" height="647"/></figure><p><a href="https://www.digio.in/digi-kyc/" rel="noreferrer nofollow">Digio DigiKYC</a> covers three separate Indian regulatory regimes from one Video KYC stack: RBI's V-CIP for banking, SEBI's VIPV for capital markets, and IRDAI's VBIP for insurance.</p><p>Its public product page documents self and assisted Video KYC, real-time facial recognition with geo-location verification, automatic video-quality adjustment for weak networks, and multi-agent support with call reminders and in-call chat.</p><p>Digio also publishes ID OCR analysis, DigiLocker integration, KYB verification for non-individual entities, liveness detection with 20+ checks claimed at 99.6% accuracy, face-dedupe across large image sets, and a workflow builder (DigiStudio) with auto-approval logic.</p><p>Public material is stronger on product capability than endpoint-level API reference. Request session API specs, webhook schemas, SDK version support, and current PAD/injection-attack test evidence before scoping integration.</p><p><strong>Best for:</strong> financial groups running banking, broking, and insurance arms under one compliance umbrella that want a single Video KYC vendor across all three regimes.</p><p><strong>Pricing visibility:</strong> sales-led. Digio's self-reported benchmarks (60% cost reduction, 95% TAT reduction) are vendor-stated; verify against your own volumes.</p><h3 id="3-cashfree-secure-id-best-public-indian-api-documentation">3. Cashfree Secure ID: Best Public Indian API Documentation</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-29-at-6.38.18-PM.png" class="kg-image" alt="Top 10 Video KYC API: Expert Tested & Ranked" loading="lazy" width="2852" height="1594"/></figure><p><a href="https://www.cashfree.com/video-kyc-solution/" rel="noreferrer nofollow">Cashfree Secure ID</a> earns a high rank because its current documentation exposes a concrete Video KYC lifecycle instead of stopping at a product brochure.</p><p>The public API reference shows how to create a Secure ID user, initiate a Video KYC request, generate a verification link, fetch status, and receive workflow data.</p><p>Cashfree documents separate production and sandbox endpoints, versioned headers, client credentials, webhooks, key rotation, agent and auditor dashboards, reports, status fields, and configurable user or agent templates.</p><p>That clarity gives developers a realistic starting point for estimation. Cashfree also connects Video KYC with PAN, Aadhaar, face liveness, name matching, bank verification, DigiLocker, and related Secure ID services.</p><p>The trade-off is ecosystem fit. Cashfree is especially attractive for Indian fintechs already using its payments or verification products, while non-financial or global workflows may prefer a neutral identity platform.</p><p><strong>Best for:</strong> Indian fintech products that want a documented, sandbox-oriented verification service and may already use Cashfree payments, payouts, or Secure ID checks.</p><p><strong>Pricing visibility:</strong> access follows wallet, activation, and product-entitlement rules. Confirm Video KYC session, agent, recording, storage, and ancillary verification charges directly with Cashfree.</p><h3 id="4-surepass-best-for-api-breadth-alongside-video-kyc">4. Surepass: Best for API Breadth Alongside Video KYC</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-31-191708.png" class="kg-image" alt="Top 10 Video KYC API: Expert Tested & Ranked" loading="lazy" width="1438" height="690"/></figure><p><a href="https://surepass.io/video-kyc/" rel="noreferrer nfollow">Surepass Video KYC</a> sits inside a much larger API marketplace, giving Indian teams one vendor for Video KYC plus the surrounding identity and business checks a V-CIP journey typically needs.</p><p>Its public flow covers link-based initiation, prerequisite check, agent queue, facial-recognition capture, document review, and a Q&amp;A-backed decision. Listed features include live location confirmation, deepfake detection, end-to-end encryption, and VCIP delivered over WhatsApp video calls.</p><p>One concrete claim stands out: Surepass states its Video KYC functions at bandwidths as low as 100kbps, useful for onboarding outside metro connectivity. The company also states its platform spans 300+ verification APIs available through a self-serve sandbox for testing before contract.</p><p>This is an API-marketplace model rather than a single-purpose vKYC product. Confirm which APIs are bundled into a standard contract, and request current PAD/injection-resistance test evidence.</p><p><strong>Best for:</strong> Indian fintechs and NBFCs wanting Video KYC alongside a wide bench of identity and bank-verification APIs from one vendor with sandbox access.</p><p><strong>Pricing visibility:</strong> sales-led. Surepass's "97% fraud reduction, 2000+ companies" claim is vendor-stated; request session and per-API pricing directly.</p><h3 id="5-hyperverge-best-turnkey-indian-v-cip">5. HyperVerge: Best Turnkey Indian V-CIP</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-29-at-6.40.25-PM.png" class="kg-image" alt="Top 10 Video KYC API: Expert Tested & Ranked" loading="lazy" width="2898" height="1602"/></figure><p><a href="https://hyperverge.co/in/solutions/video-kyc/" rel="noreferrer nofollow">HyperVerge Video KYC</a> is designed as an operational product, not only a media API, covering pre-call checks, agent queues, live verification, and post-call management.</p><p>Its public product flow includes PAN verification, Aadhaar eKYC, CKYC, name and date-of-birth matching, queue estimates, scheduling, random verification codes, face match, liveness, and deepfake checks.</p><p>HyperVerge also presents agent-led and agent-less journeys, dashboards, shift controls, priority routing, automated PAN capture, and configurable document or signature steps for different regulated use cases.</p><p>This breadth reduces integration work for an Indian financial institution that wants one accountable workflow. It also means your journey will follow more vendor-defined operational patterns than VideoSDK's modular approach.</p><p>Public product material is detailed, but full technical implementation and pricing remain sales-led. Request API specifications, webhook schemas, data residency terms, security reports, and sandbox access before scoring feasibility.</p><p><strong>Best for:</strong> high-volume Indian banks, NBFCs, lenders, demat platforms, and insurers seeking a managed V-CIP workflow with built-in fraud and agent operations.</p><h3 id="6-idfy-best-for-session-continuity">6. IDfy: Best for Session Continuity</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-29-at-6.36.06-PM.png" class="kg-image" alt="Top 10 Video KYC API: Expert Tested & Ranked" loading="lazy" width="2898" height="1592"/></figure><p><a href="https://www.idfy.com/identity-verification-solutions-by-idfy/video-kyc/" rel="noreferrer nofollow">IDfy Video KYC</a> supports agent-assisted and self-serve modes, with operations focused on completing calls despite device, network, or scheduling friction.</p><p>Its public material documents pre-call network, camera, and microphone checks, low-bandwidth support, text chat, reconnection, autosave, reviewer allocation, dashboards, and cloud availability across major providers.</p><p>The <a href="https://eve-docs.idfy.com/pages/video_kyc.html" rel="noreferrer nofollow">Dfy Product Hub</a> describes document validation, configurable video activities, link generation, face liveness, face consistency, face comparison, timestamps, geostamps, and manual expert review.</p><p>Those features address a gap in shallow buyer guides: call completion depends on recovery and review operations, not only OCR or liveness boxes on a comparison sheet.</p><p>Some publicly visible documentation contains older wording and planned-feature labels. Ask IDfy to identify the current production API version, supported browsers, exact activities, failure codes, and retention options.</p><p><strong>Best for:</strong> Indian enterprises that need configurable verification journeys and put strong emphasis on low-bandwidth completion, reconnection, reviewer allocation, and operational monitoring.</p><p><strong>Pricing visibility:</strong> sales-led. Model the full cost of verification, reattempts, review, agent seats, storage, exports, and any separate document or source-validation APIs.</p><h3 id="7-signzy-best-for-configurable-india-stack-workflows">7. Signzy: Best for Configurable India Stack Workflows</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-29-at-6.32.58-PM.png" class="kg-image" alt="Top 10 Video KYC API: Expert Tested & Ranked" loading="lazy" width="2910" height="1432"/></figure><p><a href="https://www.signzy.com/" rel="noreferrer nofollow">Signzy</a> combines an India-focused API marketplace with no-code workflow orchestration, making it suitable for regulated teams that mix identity, contracts, fraud, and onboarding controls.</p><p>Its public <a href="https://docs.signzy.com/investor-onboarding-io" rel="noreferrer nofollow">investor onboarding documentation</a> shows API-created applicants, iframe initiation, video verification, document and bank checks, FATCA collection, signatures, and result-retrieval endpoints.</p><p>Signzy also presents OCR, liveness, deepfake detection, CKYC automation, digital signatures, transaction monitoring, and configurable onboarding journeys across its broader platform. Exact availability varies by contract.</p><p>This model suits compliance and operations teams that need to change journeys without waiting for every frontend release. Developers still need complete schemas and test cases before estimating effort.</p><p>Public documentation spans several products and generations, so confirm the current implementation version, webhook model, India Stack dependencies, audit export format, and production support commitments.</p><p><strong>Best for:</strong> banks, asset managers, lenders, and regulated fintechs seeking configurable Indian onboarding journeys with identity, contract, and compliance modules under one vendor.</p><p><strong>Pricing visibility:</strong> enterprise quotation. Ask for per-journey component pricing, environment fees, minimum volumes, assisted-review costs, and charges for CKYC, signatures, or monitoring.</p><h3 id="8-authbridge-best-for-broad-indian-v-cip-workflows">8. AuthBridge: Best for Broad Indian V-CIP Workflows</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-29-at-6.31.03-PM.png" class="kg-image" alt="Top 10 Video KYC API: Expert Tested & Ranked" loading="lazy" width="2920" height="1592"/></figure><p><a href="https://authbridge.com/video-kyc/" rel="noreferrer nofollow">AuthBridge Video KYC</a> combines the live session with Indian identity checks and operating tools for regulated onboarding.</p><p>Its official product material documents live encrypted video, PAN validation, offline Aadhaar verification, OCR, face match, liveness, geotagging, IP-spoofing prevention, automatic agent assignment, random questions, Aadhaar masking, encrypted recording, and verification reports.</p><p>This breadth makes AuthBridge a credible shortlist choice for an Indian BFSI team that wants more of the V-CIP journey from one provider. Its public privacy notice also identifies the client as data controller or fiduciary and AuthBridge as data processor unless stated otherwise.</p><p>The public material is stronger on product workflow than endpoint-level developer reference. Ask for session APIs, callback schemas, idempotency, failure states, SDK support, audit exports, deletion behaviour, and proof of current fraud testing before estimating delivery.</p><p>Some official page copy still describes gesture-led liveness. Since the 2025 RBI directions say specific gestures are not mandatory, verify how the current production flow supports accessible passive or alternative liveness methods.</p><p><strong>Best for:</strong> Indian banks, NBFCs, insurers, and fintechs wanting PAN, Aadhaar, biometric, agent, recording, and audit functions in a managed Video KYC journey.</p><p><strong>Pricing visibility:</strong> sales-led. Obtain a written breakdown for sessions, agent time, document and source checks, biometric calls, storage, retries, reports, and implementation services.</p><h3 id="9-gridlines-best-for-modular-onboarding-journeys">9. Gridlines: Best for Modular Onboarding Journeys</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-29-at-6.29.01-PM.png" class="kg-image" alt="Top 10 Video KYC API: Expert Tested & Ranked" loading="lazy" width="2880" height="1650"/></figure><p><a href="https://gridlines.io/" rel="noreferrer nofollow">Gridlines</a> positions Video KYC inside configurable identity, risk, review, and eSign journeys rather than treating the call as an isolated verification event.</p><p>Its public interface examples show event-driven journey states such as identity completion, Video KYC start, fraud signals, callbacks, review decisions, and eSign completion within one orchestration layer.</p><p>That event model is useful for lenders and marketplaces where KYC outcomes trigger underwriting, document signing, manual review, or escalation. It also reduces glue code between separate dashboards.</p><p>The public product evidence is stronger on workflow concepts than endpoint-level detail. Request authentication rules, webhook retries, idempotency behaviour, sandbox data, error taxonomies, and retention controls before selection.</p><p><strong>Best for:</strong> Indian product teams wanting modular onboarding infrastructure that links verification, Video KYC, fraud signals, review queues, and agreements into one observable journey.</p><p><strong>Pricing visibility:</strong> sales-led. Compare journey pricing against buying individual identity APIs, an RTC platform, review tooling, storage, and an orchestration service separately.</p><h3 id="10-shufti-pro-best-for-global-live-video-verification">10. Shufti Pro: Best for Global Live Video Verification</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-29-at-6.26.40-PM.png" class="kg-image" alt="Top 10 Video KYC API: Expert Tested & Ranked" loading="lazy" width="2910" height="1456"/></figure><p><a href="https://shuftipro.com/videoident-en/" rel="noreferrer nofollow">Shufti Pro VideoIdent</a> combines a live specialist interview with document inspection, face comparison, consent capture, a verification decision, and an API-returned evidence pack.</p><p>Its <a href="https://developers.shuftipro.com/docs/user_identification_authentication/video_kyc/request_parameters" rel="noreferrer nofollow">developer documentation</a> publishes the real-time verification base URL and request parameters, giving engineers more evidence than a sales page alone.</p><p>This assisted model can suit cross-border programmes where a trained human must inspect documents and interview applicants. It also reduces the need to staff every verification market internally.</p><p>The procurement burden moves toward coverage and operating hours. Verify supported countries, languages, documents, specialist availability, review escalation, data location, and local legal acceptance for each market.</p><p><strong>Best for:</strong> international fintech, gaming, mobility, and marketplace teams that need human-assisted Video KYC and structured evidence across several jurisdictions.</p><p><strong>Pricing visibility:</strong> plan and contract details vary. Confirm assisted-call duration, retry charges, manual review, document coverage, AML add-ons, evidence retention, and minimum commitments.</p><h2 id="how-to-choose-a-video-kyc-api">How to Choose a Video KYC API</h2><p>The best Video KYC API is the one that passes your hardest production scenario, preserves an auditable chain of evidence, and fits your operating model.</p><h3 id="1-choose-your-product-boundary">1. Choose your product boundary</h3><p>Decide whether you need a media and verification toolkit, a complete managed V-CIP workflow, or a global identity platform with Video KYC as one method.</p><p>Choose VideoSDK for interface and media control. Choose Digio, Cashfree, Surepass, HyperVerge, IDfy, Signzy, or AuthBridge for Indian V-CIP, multi-regulator compliance (RBI/SEBI/IRDAI), and broad verification API stacks. Choose Shufti Pro when cross-border live video identification is required.</p><h3 id="2-test-difficult-traffic">2. Test difficult traffic</h3><p>Build a test set covering budget Android devices, poor lighting, low bandwidth, permission denial, call interruption, duplicate sessions, expired links, document glare, and accessibility needs.</p><p>Do not publish vendor accuracy or conversion claims as your expected result. Measure completion, manual review, false rejection, retry cost, and support recovery using representative applicants.</p><h3 id="3-deepfake-and-injection-attacks-the-2026-threat-your-video-kyc-api-must-handle">3. Deepfake and Injection Attacks: The 2026 Threat Your Video KYC API Must Handle</h3><p>A presentation attack places a photo, screen replay, mask, or other artefact in front of the expected camera. An injection attack bypasses that capture path and feeds synthetic or recorded frames through a virtual camera, emulator, modified client, compromised SDK, or tampered media pipeline.</p><p>That difference matters because a liveness model that detects a phone screen may never see the physical screen when an attacker injects a clean digital stream. A <a href="https://pages.nist.gov/ifpc/2025/presentations/09.pdf">2025 NIST identity and face-performance presentation</a> describes virtual cameras, emulators, modified capture devices, and replacement of frames inside the transmission path as distinct injection methods.</p><p>Ask for independent presentation-attack test results, not only a “liveness” label. <a href="https://www.iso.org/standard/79520.html">ISO/IEC 30107-3:2023</a> defines testing and reporting for biometric presentation-attack detection, but explicitly excludes overall system-level security and attacks outside the capture device.</p><p>Therefore, ISO/IEC 30107-3 evidence does not by itself prove resistance to virtual-camera or API-level injection. Evaluate PAD performance and, separately, device integrity, emulator and root detection, application attestation, virtual-camera controls, media provenance, replay resistance, authenticated APIs, webhook verification, tamper-evident logs, and red-team results.</p><p>VideoSDK publicly documents image-based spoof detection, but those public docs do not establish end-to-end injection-attack resistance. In a VideoSDK architecture, the regulated entity should add or procure that layer and validate the complete capture-to-decision path.</p><h3 id="4-rbi-kyc-directions-2025-what-changed-for-v-cip">4. RBI KYC Directions 2025: What Changed for V-CIP</h3><p>On 28 November 2025, RBI replaced the 2016 umbrella KYC Master Direction with entity-specific directions. The <a href="https://rbidocs.rbi.org.in/rdocs/notification/PDFs/169MD.pdf">Commercial Banks KYC Directions 2025</a> are the operative reference for commercial banks. Through circular RBI/2025-26/101, payment system providers and participants, including payment aggregators where the payment rules cross-reference KYC, were directed to read old references as references to the 2025 Commercial Banks directions.</p><p>This change mainly consolidated and reorganised existing instructions by entity type. Do not assume that every control in the 2025 document was introduced for the first time on that date; compliance teams should map their existing controls to the new paragraph structure.</p><p>The current V-CIP text requires the application to include face liveness or spoof detection and face matching with a high degree of accuracy. It also states that specific gestures such as blinking, smiling, or frowning are not mandatory, and that liveness checks must account for customers with special needs.</p><p>The directions continue to require controls including trained officials, varied real-time questions, geotagged and timestamped recordings, protection from spoofed or outside-India IP addresses, end-to-end encryption, testing of relevant APIs and web services, and periodic VAPT and security audit by CERT-In-empanelled auditors.</p><blockquote>The RBI text uses “face liveness / spoof detection”; it does not use the terms “deepfake detection” or “presentation attack detection.” Treat deepfake and injection resistance as necessary risk controls to test, but do not describe them as an explicit RBI phrase without a legal interpretation for your regulated entity.</blockquote><blockquote>Since 28 November 2025, India's current RBI V-CIP text requires face liveness or spoof detection and face matching, while making blinking, smiling, or frowning optional rather than mandatory.</blockquote><h3 id="5-map-compliance-responsibility">5. Map compliance responsibility</h3><p>For Indian V-CIP, the regulated entity remains responsible for customer identification. The 2025 Commercial Banks directions state that ultimate responsibility for customer identification rests with the bank; each other regulated entity should map that principle to its applicable direction and payment-system instructions.</p><p>Verify informed consent, live official participation, geotagging, PAN and identity-source checks, varied questions, liveness, encryption, logs, timestamps, concurrent audit, safe storage, and Aadhaar redaction.</p><blockquote>A Video KYC API gives a regulated entity programmable control over an identity session, but vendor selection does not transfer responsibility for customer identification, fraud controls, security testing, audit retention, or legal compliance.</blockquote><p>This article is technical research, not legal advice. Obtain current guidance from your regulator, compliance function, legal counsel, information-security team, and independent auditors before production approval.</p><h3 id="6-price-the-complete-journey">6. Price the complete journey</h3><p>Model customer sessions, agent minutes, reviewer time, document checks, biometric calls, government-source lookups, recording, storage, exports, retries, webhooks, support, and minimum commitments.</p><p>A cheaper API request can produce a more expensive completed KYC when drop-offs, agent idle time, repeated reviews, or fragmented incident support increase operational cost.</p><p>Public pricing is too sparse to support a reliable market-wide ₹15 to ₹80 claim for the ranked providers. Most use custom enterprise quotes, and a “session” may exclude the agent, source checks, biometrics, storage, or reattempts. Use vendor quotes to calculate cost per completed, approved KYC under your own traffic mix.</p>
<!--kg-card-begin: html-->
<iframe width="600" height="315" src="https://www.youtube.com/embed/tWpIDf0V-PQ?si=g9CYXFs4H_wADys6" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<h2 id="videosdk-architecture-for-video-kyc">VideoSDK Architecture for Video KYC</h2><p>VideoSDK works best in a modular Video KYC architecture where the regulated entity owns orchestration and connects authoritative identity services behind controlled server APIs.</p><p><a href="https://youtu.be/tWpIDf0V-PQ?si=tVRNDkEdJuE-SDpz" rel="noreferrer">Build a Video KYC (VKYC) App with VideoSDK</a></p><ol><li><strong>Create a server-side session.</strong> Authenticate the applicant, generate a short-lived VideoSDK token, create a room, and attach your internal case identifier without exposing secrets.</li><li><strong>Run pre-call checks.</strong> Test camera, microphone, network, location permission, browser support, consent, and document readiness before assigning a trained official.</li><li><strong>Conduct the live interview.</strong> Keep the customer and official inside the regulated entity's application, vary questions, monitor quality, and capture required evidence during the call.</li><li><strong>Detect capture and injection attacks.</strong> Run face spoof or PAD checks, virtual-camera and emulator controls, app or device integrity checks, replay detection, and media-pipeline risk rules before accepting evidence.</li><li><strong>Call verification services.</strong> Send approved captures to OCR, face match, PAN, Aadhaar, sanctions, or other source-validation services through your protected backend.</li><li><strong>Seal the audit record.</strong> Store timestamps, location, official identity, events, decisions, hashes, fraud signals, verification outputs, recording references, and reviewer actions under your retention policy.</li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-29--2026--06_09_17-PM.png" class="kg-image" alt="Top 10 Video KYC API: Expert Tested & Ranked" loading="lazy" width="1672" height="941"/></figure><p>This design keeps vendor boundaries explicit. It also lets your team replace a verification component without rebuilding the customer and agent video experience.</p><p>The regulated entity should scope VAPT and security review across the customer application, VideoSDK integration, capture controls, identity services, storage, dashboards, APIs, and webhooks. Auditing only the RTC component leaves material attack paths outside the assessment.</p><h2 id="what-is-the-best-video-kyc-api">What Is the Best Video KYC API?</h2><p>The best Video KYC API depends on whether you value custom developer control, managed Indian V-CIP operations, a documented fintech workflow, or global identity coverage.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Use case</th>
<th>Best starting point</th>
<th>Why</th>
<th>Main trade-off</th>
</tr>
</thead>
<tbody>
<tr>
<td>Custom embedded V-CIP across web and mobile</td>
<td>VideoSDK</td>
<td>Direct control of the call, interface, events, recording, and modular identity APIs</td>
<td>Your team must integrate authoritative checks, operations, fraud controls, and compliance evidence</td>
</tr>
<tr>
<td>Multi-regulator Indian financial compliance</td>
<td>Digio</td>
<td>RBI V-CIP, SEBI VIPV, and IRDAI VBIP support in one stack with DigiLocker and DigiStudio</td>
<td>Public material focuses on workflow capabilities rather than endpoint-level API specifications</td>
</tr>
<tr>
<td>Documented Indian REST workflow</td>
<td>Cashfree Secure ID</td>
<td>Public session, status, sandbox, agent, auditor, and webhook documentation</td>
<td>Strongest fit inside the Indian fintech and Cashfree ecosystem</td>
</tr>
<tr>
<td>Low-bandwidth Video KYC with broad API suite</td>
<td>Surepass</td>
<td>100kbps connectivity support, WhatsApp Video KYC option, and 300+ verification APIs</td>
<td>API marketplace model requires confirming contract bundling and test evidence</td>
</tr>
<tr>
<td>Turnkey high-volume Indian V-CIP</td>
<td>HyperVerge</td>
<td>Packaged pre-checks, routing, biometrics, agents, and dashboards</td>
<td>More vendor-defined workflow and sales-led technical access</td>
</tr>
<tr>
<td>Completion continuity and review operations</td>
<td>IDfy</td>
<td>Pre-call checks, reconnection, autosave, allocation, and review tooling</td>
<td>Confirm the current API version and planned-versus-live features</td>
</tr>
<tr>
<td>Configurable India Stack journey</td>
<td>Signzy</td>
<td>API marketplace, iframe journeys, workflow configuration, and adjacent compliance modules</td>
<td>Product and documentation versions require careful contract validation</td>
</tr>
<tr>
<td>Broad managed Indian V-CIP</td>
<td>AuthBridge</td>
<td>PAN, Aadhaar, OCR, face, liveness, geotagging, agents, recording, and reports</td>
<td>Less endpoint-level public documentation than Cashfree</td>
</tr>
<tr>
<td>Modular Indian onboarding orchestration</td>
<td>Gridlines</td>
<td>Identity, Video KYC, fraud, review, and eSign states in one journey</td>
<td>Public evidence is stronger on workflow concepts than endpoint detail</td>
</tr>
<tr>
<td>Cross-border human-assisted verification</td>
<td>Shufti Pro</td>
<td>Live specialists and API-returned evidence across markets</td>
<td>Validate country coverage, languages, operating hours, and local acceptance</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>VideoSDK is not the automatic answer for a team seeking outsourced KYC operations. It ranks first here because this evaluation weights custom engineering control above managed-service convenience.</p><h2 id="video-kyc-api-definitions">Video KYC API Definitions</h2><p>These Video KYC API definitions separate communication infrastructure, identity evidence, biometric controls, and regulatory responsibility for developers evaluating an implementation.</p><blockquote><strong>V-CIP:</strong> RBI's Video-based Customer Identification Process for applicable regulated entities, involving live audiovisual interaction, trained officials, identity evidence, security controls, and auditable records.</blockquote><blockquote><strong>Liveness detection:</strong> A control intended to confirm that biometric input comes from a present person rather than a photo, replay, mask, synthetic feed, or presentation attack.</blockquote><blockquote><strong>Presentation Attack Detection, or PAD:</strong> Testing and controls aimed at detecting artefacts presented at the biometric capture device, such as printed photos, screens, or masks. ISO/IEC 30107-3 covers PAD testing and reporting, not the security of the whole identity system.</blockquote><blockquote><strong>Injection attack:</strong> An attack that replaces or inserts image or video data after the expected camera-capture point, for example through a virtual camera, emulator, modified application, compromised SDK, or tampered media pipeline.</blockquote><blockquote><strong>Face matching:</strong> A biometric comparison between a live or captured face and a trusted document photograph, producing a score or decision that still requires policy controls.</blockquote><blockquote><strong>Meeting token:</strong> A short-lived credential used to authorise a participant's access to a VideoSDK room, generated by a trusted server rather than exposed client-side.</blockquote><blockquote><strong>Audit trail:</strong> The linked record of consent, timestamps, locations, officials, session events, evidence, automated checks, reviewer actions, decisions, and retention or deletion operations.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><p>These seven Video KYC API takeaways summarise the product boundaries, conditional leaders, compliance limits, fraud controls, and proof-of-concept work that should guide your shortlist.</p><ul><li>A Video KYC API may provide composable infrastructure, a managed V-CIP journey, or a global identity platform, so buyers should compare product boundaries first.</li><li>VideoSDK is the leading choice in this developer-first ranking for custom live-video control, multi-platform SDK coverage, and modular enterprise identity-verification endpoints.</li><li>VideoSDK still requires authoritative identity checks, trained operations, retention controls, audit design, and regulated-entity ownership for a complete Indian V-CIP implementation.</li><li>HyperVerge leads for turnkey Indian operations, while Cashfree stands out for publicly accessible, current REST documentation and a clearly described session lifecycle.</li><li>AuthBridge now belongs on an Indian V-CIP shortlist because its public workflow covers PAN, offline Aadhaar, OCR, face, liveness, geotagging, agents, recordings, and reports.</li><li>PAD and liveness testing do not prove injection resistance. Test virtual-camera, emulator, client-integrity, replay, API, and media-pipeline attacks separately.</li><li>No ranking replaces a proof of concept using difficult devices, real document diversity, fraud cases, interrupted sessions, queue peaks, reviewers, storage, and incident reconstruction.</li></ul><h2 id="conclusion">Conclusion</h2><p>Choosing a Video KYC API in 2026 is an architecture decision, not a feature-count contest. Start with VideoSDK when custom media, interface ownership, and composability lead your requirements.</p><p>Choose a managed provider when agent operations and packaged verification matter more. Review the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React quickstart</a>, then <a href="https://app.videosdk.live/login">start with free credit</a> or request an enterprise architecture review.</p><p>What are you building with VideoSDK? Drop a comment and share the Video KYC use case, jurisdiction, client platforms, and verification services your team needs.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-a-video-kyc-api-1">What is a Video KYC API?</h3><p>A Video KYC API is a programmable service for conducting remote identity verification through video, documents, biometric checks, human review, and auditable workflow data.</p><p>Some products provide only selected building blocks, while others manage the entire journey. Always identify who owns the call, verification decision, evidence, and compliance obligations.</p><h3 id="which-video-kyc-api-is-best-in-2026">Which Video KYC API is best in 2026?</h3><p>The best Video KYC API in 2026 depends on your operating model. VideoSDK suits custom developer control, Digio excels in multi-regulator Indian compliance (RBI, SEBI, IRDAI), Cashfree offers strong public API documentation, and Surepass delivers low-bandwidth Video KYC backed by 300+ identity verification APIs.</p><p>HyperVerge, IDfy, Signzy, and AuthBridge serve enterprise Indian V-CIP workflows, while Shufti Pro is a top choice for international live video verification.</p><h3 id="is-videosdk-a-complete-kyc-provider">Is VideoSDK a complete KYC provider?</h3><p>No, VideoSDK should not be described as a complete KYC provider without qualification. It supplies real-time video infrastructure and documented enterprise identity-verification APIs.</p><p>Teams still need appropriate PAN, Aadhaar, sanctions, PEP, workflow, agent, storage, legal, and audit controls where their use case or jurisdiction requires them.</p><h3 id="does-videosdk-support-ocr-and-liveness-checks">Does VideoSDK support OCR and liveness checks?</h3><p>Yes, VideoSDK documents enterprise-only OCR, face-match, face-spoof-detection, and face-count APIs. Its video SDK also supports meeting rooms, participant media, events, and recordings.</p><p>Confirm current availability, commercial terms, accuracy evidence, data processing, supported documents, and production constraints directly with VideoSDK before using these APIs in regulated workflows.</p><h3 id="what-does-rbi-require-for-video-kyc">What does RBI require for Video KYC?</h3><p>RBI's V-CIP rules require applicable regulated entities to implement live, secure, encrypted audiovisual interaction with trained officials, consent, geotagging, identity checks, liveness, logs, and recordings.</p><p>The 2025 directions require face liveness or spoof detection and face matching, but say blinking, smiling, or frowning is not mandatory. The rules also cover PAN verification, timestamps, secure storage, API testing, CERT-In-empanelled security audits, and regulated-entity responsibility.</p><h3 id="does-rbi-explicitly-mandate-deepfake-detection-for-v-cip">Does RBI explicitly mandate deepfake detection for V-CIP?</h3><p>The current RBI V-CIP text requires face liveness or spoof detection and face matching, but it does not use the terms “deepfake detection” or “presentation attack detection.”</p><p>Regulated entities should still evaluate deepfake, replay, and injection risks as part of fraud and security controls. Obtain legal and compliance interpretation before describing a particular technology as an explicit RBI mandate.</p><h3 id="what-is-the-difference-between-pad-and-an-injection-attack">What is the difference between PAD and an injection attack?</h3><p>Presentation Attack Detection focuses on artefacts presented at the expected biometric capture device, such as a photo, replay screen, or mask.</p><p>An injection attack bypasses or tampers with that capture path using a virtual camera, emulator, modified client, compromised SDK, or replaced frames. A PAD test alone does not prove injection resistance.</p><h3 id="how-should-i-test-a-video-kyc-api">How should I test a Video KYC API?</h3><p>Test a Video KYC API with representative documents, devices, networks, languages, accessibility needs, spoof attempts, interruptions, retries, queue peaks, reviewer actions, and evidence retrieval.</p><p>Measure completion, false rejection, manual-review rates, recovery time, support quality, and total completed-KYC cost. Do not rely only on a vendor's happy-path sandbox.</p><h3 id="how-much-does-a-video-kyc-api-cost">How much does a Video KYC API cost?</h3><p>A Video KYC API may charge per session, participant minute, agent minute, biometric check, document lookup, review, recording, storage, export, or monthly commitment.</p><p>Most ranked enterprise vendors provide custom quotes. Public evidence is not strong enough to treat ₹15 to ₹80 as a reliable market-wide range, because vendors define and bundle a “session” differently.</p><p>Compare the total completed-verification cost, including agent time, checks, failures, retries, review, recording, storage, and support, rather than the cheapest published API request.</p><h2 id="related-videosdk-guides">Related VideoSDK Guides</h2><p>These VideoSDK guides strengthen the Video KYC topic cluster and give developers practical next steps for media, identity checks, evidence capture, and architecture decisions.</p><ul><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React video and audio calling quickstart</a></li><li><a href="https://docs.videosdk.live/react/guide/identity-verification/ocr">VideoSDK OCR API documentation</a></li><li><a href="https://docs.videosdk.live/react/guide/identity-verification/face-match-api">VideoSDK face-match API documentation</a></li><li><a href="https://www.videosdk.live/blog/integrate-image-capture-in-javascript-chat-app">Capture identity-document images from a VideoSDK participant stream</a></li><li><a href="https://www.videosdk.live/blog/comparison-of-open-source-and-videosdk">Open source versus VideoSDK for Video KYC infrastructure</a></li><li><a href="https://www.videosdk.live/blog/tag/video-kyc">VideoSDK Video KYC resource hub</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Webinar API: Build Embedded Webinars with VideoSDK]]></title><description><![CDATA[Learn the two meanings of Webinar API, compare leading providers, choose ILS or HLS, and build a secure embedded webinar with VideoSDK and JavaScript.]]></description><link>https://www.videosdk.live/blog/webinar-api</link><guid isPermaLink="false">6a6b359eb3240feb748c908c</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 30 Jul 2026 14:40:43 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/07/Revised-Webinar-API-feature-image.png" medium="image"/><content:encoded><![CDATA[<blockquote>A Webinar API lets software schedule events, manage registrants, or embed live webinar media programmatically. VideoSDK serves the embedded-media model with REST room APIs, custom client SDKs, and presenter or audience modes. Its JavaScript ILS quickstart documents up to 100 hosts or co-hosts and 2,000 real-time viewers for that configuration.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Revised-Webinar-API-feature-image.png" alt="Webinar API: Build Embedded Webinars with VideoSDK"/><p>Scheduling a webinar is a workflow problem. Delivering a branded, low-latency webinar inside your product is a media and application-architecture problem.</p><p>Those jobs need different tools. This guide separates them, compares leading providers, and shows how to build a working embedded webinar with VideoSDK, Node.js, and JavaScript.</p><h2 id="what-is-a-webinar-api">What Is a Webinar API?</h2><p>A Webinar API is a set of authenticated endpoints, SDK methods, events, and data models that software uses to create, deliver, manage, or measure webinars.</p><p>A Webinar API works by accepting commands from an application, updating webinar resources, and returning records or live events. The exact resources depend on the provider.</p><p><a href="https://developers.ringcentral.com/webinar-api" rel="nofollow">RingCentral's Webinar API</a>, for example, focuses on schedules, participants, recordings, and analytics. <a href="https://learn.microsoft.com/en-us/graph/cloud-communications-virtual-events-webinar-usecases" rel="nofollow">Microsoft Graph webinar APIs</a> manage Teams webinars, registrations, presenters, attendance, and webhooks.</p><p>VideoSDK addresses a different part of the market. Its <a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">real-time communication API</a> manages rooms, sessions, participants, recordings, RTMP output, and HLS, while its client SDKs control media and interface behavior.</p><p>A workflow Webinar API automates a hosted webinar product. An embedded Webinar API also lets developers control the participant interface and media experience. VideoSDK fits the embedded model because its REST APIs orchestrate rooms while its client SDKs handle presenter and audience media.</p><h3 id="two-webinar-api-models">Two Webinar API models</h3>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Model</th>
<th>What it controls</th>
<th>Typical output</th>
<th>Best fit</th>
</tr>
</thead>
<tbody>
<tr>
<td>Workflow REST API</td>
<td>Events, registration, reminders, attendance, reports</td>
<td>Automated workflows around a hosted webinar</td>
<td>Teams already using a webinar platform</td>
</tr>
<tr>
<td>Embedded media API and SDK</td>
<td>Rooms, media tracks, roles, layouts, chat, recording</td>
<td>A webinar inside your web or mobile product</td>
<td>SaaS, education, community, and commerce products</td>
</tr>
<tr>
<td>Combined architecture</td>
<td>Workflow data plus embedded media</td>
<td>A custom webinar connected to CRM, email, and analytics</td>
<td>Teams needing full ownership of experience and data</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Neither model replaces the other. A production product may combine VideoSDK with a registration database, email provider, CRM, payment service, and analytics pipeline.</p><h2 id="how-webinar-automation-and-media-delivery-work">How Webinar Automation and Media Delivery Work</h2><p>A production webinar separates business workflows from media delivery so each layer can scale, fail, and change without taking the entire product down.</p><p>Your backend authenticates the user, verifies registration, determines the webinar role, creates or validates a room, and issues a short-lived token. The client uses that token to join.</p><p>The media layer then carries audio, video, and screen-share tracks. The <a href="https://www.w3.org/TR/webrtc/">W3C WebRTC Recommendation</a> defines browser APIs for sending and receiving real-time media and application data.</p><p>The event layer carries chat, polls, reactions, participant joins, mode changes, and moderation commands. Recordings and session analytics move into storage or downstream systems after the session.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Updated-Webinar-API-architecture-diagram.png" class="kg-image" alt="Webinar API: Build Embedded Webinars with VideoSDK" loading="lazy" width="1600" height="900"/></figure><h3 id="control-media-and-event-planes">Control, media, and event planes</h3><p>The <strong>control plane</strong> creates rooms, issues access, removes participants, starts recordings, and fetches session data. VideoSDK exposes these operations through server-side APIs.</p><p>The <strong>media plane</strong> carries time-sensitive audio and video. VideoSDK represents the live space as a room, each user as a participant, and each media source as a track.</p><p>The <strong>event plane</strong> keeps the interface synchronised. Participant, stream, connection, mode, chat, and poll events let the application update without repeatedly polling the backend.</p><p>Your application owns identity, registration, permissions, and business data. VideoSDK handles room orchestration and media transport, but it does not replace those product responsibilities.</p><h2 id="webinar-api-comparison-for-2026">Webinar API Comparison for 2026</h2><p>The best Webinar API depends on whether you need to automate a hosted platform or own the live interface inside your application.</p><h3 id="capability-and-experience-comparison">Capability and experience comparison</h3>
<!--kg-card-begin: html-->
<table>
  <thead>
    <tr>
      <th>Provider</th>
      <th>Creation API</th>
      <th>Registrant API</th>
      <th>Live experience</th>
      <th>Best fit</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>VideoSDK</td>
      <td>Creates rooms, not marketing webinars</td>
      <td>Build or integrate separately</td>
      <td>Fully custom web or mobile UI</td>
      <td>Embedded, domain-specific webinar products</td>
    </tr>
    <tr>
      <td>Zoom</td>
      <td>Creates Zoom Webinars</td>
      <td>Adds, lists, and updates registrants</td>
      <td>Zoom-hosted attendee experience with branding options</td>
      <td>Organizations already using Zoom</td>
    </tr>
    <tr>
      <td>GoTo Webinar</td>
      <td>Creates sessions, series, and sequences</td>
      <td>Accepts and manages registrants</td>
      <td>GoTo-hosted experience</td>
      <td>Webinar workflow and campaign automation</td>
    </tr>
    <tr>
      <td>Livestorm</td>
      <td>Manages events and sessions</td>
      <td>Registers people through session endpoints</td>
      <td>Livestorm-hosted browser experience</td>
      <td>Marketing, training, and customer education</td>
    </tr>
    <tr>
      <td>webinar.net</td>
      <td><code>POST /webinars</code> and schedule endpoints</td>
      <td><code>POST /webinars/{id}/registrants</code></td>
      <td>Provider-hosted webinar experience</td>
      <td>Managed webinars with external integrations</td>
    </tr>
    <tr>
      <td>Microsoft Graph</td>
      <td>Creates, publishes, updates, and cancels Teams webinars</td>
      <td>Creates and lists registrations</td>
      <td>Microsoft Teams webinar experience</td>
      <td>Microsoft 365 and Teams workflows</td>
    </tr>
  </tbody>
</table>
<!--kg-card-end: html-->
<h3 id="recording-analytics-and-pricing-model">Recording, analytics, and pricing model</h3>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Provider</th>
<th>Recording and analytics</th>
<th>Public pricing model</th>
<th>Main caveat</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td>Recording APIs plus session and network analytics</td>
<td>Usage-based, pay-as-you-go</td>
<td>Registration, email, CRM, and webinar business logic remain yours</td>
</tr>
<tr>
<td>Zoom</td>
<td>Cloud recording, attendance, engagement, and reports</td>
<td>Paid webinar product or add-on, with quoted tiers</td>
<td>API access controls a Zoom webinar, not a fully custom media UI</td>
</tr>
<tr>
<td>GoTo Webinar</td>
<td>Recordings, registrant data, attendance, polls, and surveys</td>
<td>Product subscription; API has no separate fee</td>
<td>A GoTo account remains required</td>
</tr>
<tr>
<td>Livestorm</td>
<td>Unlimited recording on current Pro plans plus engagement data</td>
<td>Annual attendee-credit model, with add-ons</td>
<td>API quotas and plan allowances affect integrations</td>
</tr>
<tr>
<td>webinar.net</td>
<td>Managed webinar reporting and platform features</td>
<td>Contact sales</td>
<td>The open API focuses on webinar, schedule, and registrant workflows</td>
</tr>
<tr>
<td>Microsoft Graph</td>
<td>Registration and attendance through Graph; recording follows Teams</td>
<td>Microsoft 365 or Teams licensing, with advanced event options</td>
<td>Permissions and tenant administration add integration work</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>This comparison reveals the intent gap. Most webinar APIs automate a provider-hosted event, while VideoSDK gives product teams deeper control of the live interface.</p><h2 id="capabilities-to-evaluate">Capabilities to Evaluate</h2><p>A useful evaluation covers the complete webinar lifecycle, not only the moment when a presenter turns on a camera.</p><h3 id="room-lifecycle-and-authentication">Room lifecycle and authentication</h3><p>Your backend should create, validate, inspect, and deactivate webinar rooms. Tokens should use the shortest practical expiry and the narrowest room or participant scope.</p><p>VideoSDK uses JWT authentication. Its <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/authentication-and-token">token guide</a> documents <code>allow_join</code>, <code>ask_join</code>, and <code>allow_mod</code> permissions, plus separate <code>crawler</code> and <code>rtc</code> roles.</p><p>The <code>crawler</code> role accesses server-side version 2 APIs. The <code>rtc</code> role runs a meeting or room. Keeping those tokens separate reduces the authority exposed to browsers.</p><h3 id="presenter-moderator-and-attendee-modes">Presenter, moderator, and attendee modes</h3><p>A webinar needs asymmetric media behavior. Presenters publish audio, video, and screen share, while most attendees initially receive media and interact through controlled channels.</p><p>VideoSDK JavaScript uses <code>SEND_AND_RECV</code> for hosts or co-hosts and <code>RECV_ONLY</code> for audience members. The current <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/audience-management/change-mode"><code>changeMode()</code>  guide</a> shows how an invited attendee can join the stage.</p><p>Participant mode is an SDK behavior, not a complete business authorization system. Your application must still approve speakers, monitor changes, and remove unauthorized publishers when necessary.</p><h3 id="engagement-and-moderation">Engagement and moderation</h3><p>Useful engagement features include chat, Q&amp;A, polls, reactions, hand raising, presenter invitations, participant removal, slow mode, and abuse reporting.</p><p>VideoSDK implements <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/chat-during-livestream">live-stream chat</a> and <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/audience-polls-during-livestream">audience polls</a> through PubSub. Your product still owns retention, filtering, moderator permissions, and rate limits.</p><h3 id="recording-and-observability">Recording and observability</h3><p>Recording requirements differ. Product demos may need one composite replay, while training, compliance, or editing workflows may require participant-level or track-level files.</p><p>VideoSDK's <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/recording/Overview">recording documentation</a> covers meeting and participant recording. Its <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/analytics/understanding-analytics-dashboard">analytics dashboard</a> reports duration, participants, jitter, round-trip time, packet loss, resolution, and frame rate.</p><h3 id="workflow-integration">Workflow integration</h3><p>Registration, email, CRM synchronization, payment, consent, webhooks, and post-event processing belong in the architecture. Stable identifiers must connect each registration to room activity and replay access.</p><p>The complete test is straightforward: verify how the provider handles access, media roles, engagement, recording, observability, and downstream data before comparing headline prices.</p><h2 id="ils-versus-hls-for-webinar-delivery">ILS Versus HLS for Webinar Delivery</h2><p>Interactive webinar delivery needs a different latency profile from a broadcast that viewers only watch.</p><p>VideoSDK's current JavaScript quickstart describes standard HLS playback at <strong>6 to 7 seconds</strong>. Its ILS path uses real-time participant modes for immediate audience interaction.</p><p><a href="https://developer.apple.com/documentation/http-live-streaming/enabling-low-latency-http-live-streaming-hls">Apple's Low-Latency HLS documentation</a> explains that LL-HLS reduces delay with partial segments, playlist delta updates, blocking reloads, and preload hints.</p><p>Apple recommends a one-second partial-segment target and at least three part durations of hold-back. That implies a design floor near three seconds before network and player effects, not WebRTC-style conversational timing.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Delivery path</th>
<th>Interaction model</th>
<th>Documented timing signal</th>
<th>Scale profile</th>
<th>Use it when</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK ILS</td>
<td>Presenters and real-time viewers can change roles</td>
<td>Designed for real-time media; measure p50 and p95 glass-to-glass latency in target regions</td>
<td>Interactive cohorts with controlled speakers</td>
<td>Q&amp;A, tutoring, auctions, panels, live commerce</td>
</tr>
<tr>
<td>VideoSDK standard HLS</td>
<td>One-way playback with separate data interactions</td>
<td>VideoSDK quickstart states 6 to 7 seconds</td>
<td>Larger passive audiences</td>
<td>Keynotes, broadcasts, and replay-oriented events</td>
</tr>
<tr>
<td>Low-Latency HLS</td>
<td>Segment-based playback with faster partial delivery</td>
<td>Apple recommends one-second parts and at least three parts of hold-back</td>
<td>CDN-friendly audiences needing lower delay</td>
<td>Near-live broadcasts where sub-second conversation is unnecessary</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>These figures are architecture signals, not service guarantees. Measure actual end-to-end delay across representative devices, networks, countries, and firewall conditions before selecting a delivery mode.</p><h2 id="why-videosdk-fits-embedded-webinars">Why VideoSDK Fits Embedded Webinars</h2><p>VideoSDK is a practical fit when the webinar must live inside your product and your team needs control of roles, layout, interaction, and data.</p><p>The platform combines a <a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">room and session REST API</a> with JavaScript, React, React Native, Android, iOS, Flutter, Python, and other SDK paths.</p><p>Its ILS model maps naturally to webinar roles. Hosts use <code>SEND_AND_RECV</code>, attendees use <code>RECV_ONLY</code>, and selected attendees can change mode after your application approves them.</p><p>Recording, RTMP output, HLS, chat, polls, reactions, captions, and analytics appear in current documentation. The <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Prebuilt quickstart</a> provides a faster path when a custom interface is unnecessary.</p><p>VideoSDK is not presented as a complete webinar marketing suite. Registration pages, reminder campaigns, payment, lead scoring, CRM ownership, and lifecycle email usually remain in your application.</p><p>Capacity also depends on the delivery path. The <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start-js-ils">JavaScript ILS quickstart</a>, updated July 10, 2026, states up to 100 hosts or co-hosts and 2,000 real-time viewers.</p><p>VideoSDK's public ILS page also describes a 100,000-plus viewer pattern with up to 25 simultaneous hosts. Confirm the intended mode, region, interaction level, and contracted limit before promising attendance.</p><blockquote>VideoSDK's <a href="https://www.videosdk.live/interactive-live-streaming">ILS product page</a> features Fynd and Ankur Chandra, its Engineering Manager, and reports a go-live in under two weeks. Treat this as vendor-reported onboarding evidence, not an independent performance benchmark.</blockquote><p>That trade-off is clear. VideoSDK gives product teams more control of the live experience, but that control requires more application engineering than a hosted webinar dashboard.</p><h2 id="common-integration-errors">Common Integration Errors</h2><p>Most Webinar API failures come from authentication, role handling, browser security rules, or assumptions that worked only during local testing.</p><h3 id="token-expiry-and-reconnect-failures">Token expiry and reconnect failures</h3><p>An expired VideoSDK token does not disconnect an active participant, but it prevents a later rejoin. Generate a fresh short-lived token whenever a reconnect needs authorization.</p><p>Store the application session separately from the VideoSDK token. A user can remain signed into your product while receiving a newly scoped media token.</p><h3 id="mode-mismatches">Mode mismatches</h3><p>Joining every attendee as <code>SEND_AND_RECV</code> increases publisher count and device work. Standard attendees should enter as <code>RECV_ONLY</code> until your application approves a stage invitation.</p><p>Do not treat the mode string as the only authorization check. Monitor mode changes, restrict presenter controls, and reconcile the approved speaker list with live participants.</p><h3 id="https-and-media-permissions">HTTPS and media permissions</h3><p>Camera, microphone, and screen capture require secure browser contexts. <a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia" rel="noreferrer">MDN's </a><code>getUserMedia()</code> reference confirms that production pages need HTTPS, while localhost is allowed for development.</p><p>Test denied permissions, missing devices, browser privacy settings, and embedded iframe permissions. A generic “camera failed” message is not enough for presenters under time pressure.</p><h3 id="corporate-networks-and-turn-fallback">Corporate networks and TURN fallback</h3><p>A successful home-network test does not represent enterprise conditions. Test corporate firewalls, VPNs, restricted UDP, mobile handoffs, and <a href="https://docs.videosdk.live/ai_agents/core-components/turn-detection" rel="noreferrer">TURN</a> relay paths before launch.</p><p>Track join time, connection failures, round-trip time, jitter, and packet loss by region. Those measurements reveal whether a failure belongs to the application, network, device, or media service.</p><h2 id="production-readiness-checklist">Production Readiness Checklist</h2><p>A production webinar must survive expired tokens, restricted networks, presenter mistakes, abusive messages, service outages, and post-event data requests.</p><h3 id="security-and-privacy">Security and privacy</h3><ul><li>Generate API and RTC tokens only on the backend, with short expiry and appropriate room scope.</li><li>Authenticate organizers before room creation and verify registration before issuing attendee access.</li><li>Keep presenter promotion, participant removal, recording access, and session termination behind approved controls.</li><li>Display recording consent and enforce retention or deletion rules for every region and industry served.</li><li>Rate-limit room creation, token issuance, registration, chat, polling, and promotion endpoints.</li></ul><h3 id="reliability-and-scale">Reliability and scale</h3><ul><li>Test camera, microphone, speaker, screen-share, and browser permissions before a presenter joins.</li><li>Handle participant, connection, stream, and mode events without leaving stale interface elements.</li><li>Test firewalls, VPNs, mobile networks, device changes, and TURN fallback outside localhost.</li><li>Paginate large attendee lists and render only active presenter video where possible.</li><li>Load-test registration, token issuance, chat, polls, analytics writes, and replay traffic separately.</li></ul><h3 id="operations-and-observability">Operations and observability</h3><ul><li>Store room ID, session ID, participant ID, user ID, and registration ID as separate fields.</li><li>Alert on join failures, packet loss, round-trip time, recording errors, and unexpected presenter disconnects.</li><li>Provide mute, removal, invitation, recording, and emergency termination controls for operators.</li><li>Reconcile attendance from server-side session data instead of trusting browser analytics alone.</li><li>Document fallback behavior for recording, email, CRM, payment, and analytics failures.</li></ul><p>The live room may work during a demo, but production quality depends on access control, observability, recovery, and operator tooling around that room.</p><h2 id="which-webinar-api-should-you-choose">Which Webinar API Should You Choose?</h2><p>Choose a Webinar API by deciding how much of the live experience and surrounding workflow your product needs to own.</p><p>Use Zoom, GoTo, Livestorm, webinar.net, or Microsoft Graph when users can join the provider's webinar experience and your main requirement is scheduling, registration, or reporting automation.</p><p>Use VideoSDK when the webinar must appear inside your product and your team needs custom roles, layouts, engagement, recording behavior, and application-owned identity.</p><p>Use VideoSDK Prebuilt when launch speed matters more than a fully original interface. Use a custom SDK when the event needs specialized learning, commerce, community, or moderation workflows.</p><p>Use HLS when most viewers only watch and audience scale matters more than conversational timing. Use ILS when viewers must speak, vote, ask questions, or join the stage.</p><p>The decision is conditional: choose a workflow API for automation around a hosted product, and choose an embedded SDK plus REST APIs when the webinar is part of your product.</p><h2 id="embedded-webinar-use-cases">Embedded Webinar Use Cases</h2><p>An embedded webinar creates the most value when identity, permissions, interaction, and data must connect directly to an existing product journey.</p><ul><li><strong>Education platforms</strong> can map instructors to presenters, students to attendees, and selected learners to temporary speaking roles.</li><li><strong>Customer onboarding products</strong> can connect registration, account entitlements, live training, recordings, and completion data.</li><li><strong>Developer communities</strong> can combine live coding, moderated questions, screen sharing, polls, and repository links inside a member portal.</li><li><strong>Healthcare training systems</strong> can apply organization-specific access, consent, recording, and retention policies around each session.</li><li><strong>Live commerce applications</strong> can place presenter media, product data, chat, reactions, and purchase events inside one interface.</li></ul><p>For example, an education platform can issue <code>RECV_ONLY</code> access to enrolled learners, promote one learner for questions, and attach the recording to the lesson afterward.</p><p>These products share one pattern: the webinar is not a separate destination. It is a controlled capability inside a larger user experience.</p><h2 id="key-webinar-terms">Key Webinar Terms</h2><p>Precise terminology keeps product, backend, frontend, and operations teams aligned while they design VideoSDK rooms and the workflows around them.</p><blockquote><strong>Room:</strong> A VideoSDK room is the addressable live space that participants join using a room ID and an authenticated RTC token.</blockquote><blockquote><strong>Participant:</strong> A participant is a connected presenter, attendee, moderator, or service represented by a unique participant ID within a room session.</blockquote><blockquote><strong>Media track:</strong> A media track is one continuous audio or video source, such as a microphone, camera, or shared screen.</blockquote><blockquote><strong>Meeting token:</strong> A meeting token is a signed JWT containing VideoSDK access information, permissions, expiry, and optional room or participant scope.</blockquote><blockquote><strong>Interactive live streaming:</strong> VideoSDK ILS is a mode-based experience where presenters send and receive media while attendees initially receive presenter media.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><p>These conclusions separate webinar workflow automation from the embedded media problem VideoSDK is designed to solve.</p><ul><li>A Webinar API can automate a hosted platform or power an embedded live experience, and those models should not be confused.</li><li>A production implementation needs server orchestration, client media SDKs, scoped authentication, event handling, recording, analytics, and business integrations.</li><li>VideoSDK provides rooms, presenter and attendee modes, role switching, PubSub interaction, recording, HLS, RTMP, and session analytics.</li><li>VideoSDK does not remove the need to build or integrate registration, email, payment, CRM, moderation, and domain-specific logic.</li><li>Capacity, pricing, regional requirements, and feature support should be verified against current documentation before committing an architecture.</li></ul><h2 id="conclusion">Conclusion</h2><p>A Webinar API should connect the live session to your product, not create a second disconnected journey. VideoSDK is a strong option when you need embedded real-time media, controlled roles, custom interaction, and server-side room orchestration.</p><p>Start with the <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start-js-ils">JavaScript ILS quickstart</a>, review <a href="https://www.videosdk.live/pricing">current pricing</a>, or <a href="https://app.videosdk.live/login">create a VideoSDK account</a>. What kind of webinar experience are you building?</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-a-webinar-api-1">What is a Webinar API?</h3><p>A Webinar API is a programming interface that creates, controls, embeds, or measures online seminars. It can automate a hosted webinar platform or provide room and media building blocks for an embedded experience.</p><h3 id="how-does-a-webinar-api-work">How does a Webinar API work?</h3><p>A Webinar API accepts authenticated backend commands for webinars, rooms, registrations, participants, recordings, or reports. Embedded implementations also use a client SDK to publish and receive live media.</p><h3 id="can-i-build-a-webinar-platform-with-videosdk">Can I build a webinar platform with VideoSDK?</h3><p>Yes, VideoSDK supplies the room and media foundation through REST APIs and client SDKs. You can implement custom roles, screen sharing, chat, polls, recording, streaming, and analytics.</p><h3 id="does-videosdk-provide-registration-and-email-automation">Does VideoSDK provide registration and email automation?</h3><p>VideoSDK's RTC API focuses on rooms, sessions, participants, recordings, transcription, RTMP, HLS, and related media operations. Teams should build or integrate registration, email, CRM, payment, and lead-scoring workflows.</p><h3 id="what-is-the-difference-between-a-webinar-api-and-webrtc">What is the difference between a Webinar API and WebRTC?</h3><p>WebRTC standardizes browser APIs for real-time media and data exchange. A Webinar API adds authentication, rooms, roles, recording, moderation, analytics, and business workflows around that transport.</p><h3 id="how-many-attendees-can-a-videosdk-webinar-support">How many attendees can a VideoSDK webinar support?</h3><p>VideoSDK capacity depends on the selected delivery mode. As checked July 30, 2026, the JavaScript ILS quickstart states up to 100 hosts or co-hosts and 2,000 real-time viewers for that configuration.</p><h3 id="how-do-i-secure-a-videosdk-webinar">How do I secure a VideoSDK webinar?</h3><p>Generate short-lived, room-scoped JWTs on the backend after authentication and registration checks. Keep API secrets off clients, approve presenter changes, rate-limit sensitive endpoints, and enforce recording access and retention policies.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 Dyte Alternatives: Expert Tested & Ranked]]></title><description><![CDATA[Compare the top Dyte alternatives in 2026 using current product status, video SDK coverage, deployment choice, pricing, limitations, and a practical migration framework.]]></description><link>https://www.videosdk.live/dyte-alternatives</link><guid isPermaLink="false">6a69b888b3240feb748c8f48</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 30 Jul 2026 14:33:48 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-29--2026--03_50_19-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>The leading Dyte alternatives for video calling APIs in 2026 are VideoSDK, LiveKit, and Agora. VideoSDK is the strongest managed all-rounder for custom SDKs, prebuilt UI, and interactive streaming. LiveKit suits self-hosting, while Agora suits specialised social and live applications. Compare Cloudflare RealtimeKit first if you already use Dyte.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-29--2026--03_50_19-PM.png" alt="Top 10 Dyte Alternatives: Expert Tested & Ranked"/><p>Choosing a Dyte replacement is no longer a routine feature comparison. Dyte's team joined Cloudflare, legacy Dyte SDKs entered maintenance mode, and Cloudflare RealtimeKit became the official successor.</p><p>This guide ranks ten Dyte alternatives by migration fit, developer experience, SDK coverage, deployment choice, current pricing, and product health. Video calling remains the primary scope. Voice, live streaming, and AI capabilities serve only as secondary decision factors.</p><p>You may also like: <a href="https://www.videosdk.live/dyte-vs-videosdk" rel="noreferrer">Dyte vs VideoSDK in-depth feature and pricing comparison</a></p><h2 id="what-are-dyte-alternatives">What are Dyte alternatives?</h2><p>Dyte alternatives replace Dyte's embedded video calling, participant management, media controls, recording, streaming, and user-interface capabilities.</p><p><a href="https://docs.dyte.io/react-ui-kit" rel="noreferrer nofollow">Dyte</a> is a developer platform for adding video and audio calls to web and mobile applications through core SDKs and UI kits. The team behind Dyte joined Cloudflare to help develop RealtimeKit. As of 30 July 2026, the official migration guide says legacy Dyte SDKs are in maintenance mode and “will no longer receive feature updates or bug fixes.” This product transition is why many teams are reassessing their video infrastructure.</p><p>Dyte alternatives are managed APIs, programmable SDKs, prebuilt interfaces, or open-source media platforms that handle signalling, media routing, device state, network adaptation, recording, and streaming.</p><p>Cloudflare RealtimeKit is not included in this ranking because it is Dyte's direct successor, not an independent replacement. Its <a href="https://docs.dyte.io/guides/realtimekit-migration/sdk-guide" rel="noreferrer nofollow">official migration guide</a> maps Dyte packages to RealtimeKit equivalents across web, React, Angular, React Native, Android, and iOS.</p><p>In short, a true Dyte alternative gives your team a different product roadmap, operating model, pricing structure, or level of infrastructure control.</p><h2 id="why-compare-dyte-alternatives-in-2026">Why compare Dyte alternatives in 2026?</h2><p>The <strong>main reason</strong> to compare Dyte alternatives in 2026 is <strong>product lifecycle risk</strong>, not one missing feature.</p><p>Maintenance mode changes the long-term calculation for an existing application. A legacy SDK may continue working, but future browser changes, operating-system updates, security requirements, and product bugs can create growing migration pressure.</p><p>Cloudflare RealtimeKit deserves the first evaluation because it offers the shortest conceptual migration. Cloudflare's current documentation describes RealtimeKit as a <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> product with Core SDKs, UI Kit components, REST APIs, webhooks, recording, and webinar controls.</p><p>As of 29 July 2026, RealtimeKit pricing states that the product remains in beta and is free during this period. Cloudflare lists future general-availability pricing at $0.002 per audio/video participant minute, with exports such as recording, <a href="https://www.videosdk.live/developer-hub/rtmp/rtmp-vs-srt" rel="noreferrer">RTMP</a>, or <a href="https://www.videosdk.live/developer-hub/hls/what-is-an-hls-player-and-how-does-hls-streaming-work" rel="noreferrer">HLS</a> priced separately.</p><p>A forced migration is also an architecture checkpoint. Your team can reconsider managed versus self-hosted media, prebuilt versus custom UI, supported platforms, participant roles, observability, and the total cost of recordings and streaming.</p><p>The practical question is not whether another provider has more features. It is whether that provider can preserve your application's important behaviours without creating a larger operational problem.</p><h2 id="how-we-ranked-these-dyte-alternatives">How we ranked these Dyte alternatives</h2><p>This ranking measures replacement fit through documented evidence, not brand popularity, sponsorship, or unsupported performance claims.</p><p>For this article, “expert tested” means a structured technical review of first-party documentation, public quickstarts, sample repositories, pricing pages, deployment options, SDK coverage, migration concepts, and current product status.</p><p>We traced the standard developer path for each shortlisted platform: authentication, room or session creation, joining, participant state, media controls, recording, and live-output options. We also checked whether a prebuilt interface and self-hosting path exist.</p><p>We did not run a controlled global latency, packet-loss, or video-quality benchmark. Network performance depends on participant geography, device capability, codec choice, call topology, firewall conditions, and the commercial plan being tested.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Evaluation factor</th>
<th style="text-align:right">Weight</th>
<th>What we reviewed</th>
</tr>
</thead>
<tbody>
<tr>
<td>Dyte migration fit</td>
<td style="text-align:right">25%</td>
<td>Rooms, participants, roles, events, media, recording, and streaming parity</td>
</tr>
<tr>
<td>Developer experience</td>
<td style="text-align:right">20%</td>
<td>Quickstarts, SDK design, samples, UI options, and documentation clarity</td>
</tr>
<tr>
<td>Video calling capability</td>
<td style="text-align:right">20%</td>
<td>Custom calls, device controls, screen share, network handling, and recordings</td>
</tr>
<tr>
<td>Deployment and operations</td>
<td style="text-align:right">15%</td>
<td>Managed cloud, self-hosting, scaling responsibility, analytics, and support</td>
</tr>
<tr>
<td>Pricing clarity</td>
<td style="text-align:right">10%</td>
<td>Free allowance, billing unit, add-ons, minimums, and cost predictability</td>
</tr>
<tr>
<td>Current product health</td>
<td style="text-align:right">10%</td>
<td>Maintained documentation, recent releases, and clear lifecycle status</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>This method favours platforms that can replace a production video calling API, not products that mainly provide webinars, video hosting, or consumer meeting software.</p><h2 id="dyte-alternatives-comparison-table">Dyte alternatives comparison table</h2><p><strong>The best Dyte alternative matches your interface needs, deployment model, target platforms, traffic shape, and engineering capacity.</strong></p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Rank and platform</th>
<th>Best for</th>
<th>Deployment</th>
<th>Fast UI path</th>
<th>Public pricing signal*</th>
</tr>
</thead>
<tbody>
<tr>
<td>1. VideoSDK</td>
<td>Balanced managed replacement</td>
<td>Managed</td>
<td>Prebuilt UI</td>
<td>Pay as you go, with $20 starting balance</td>
</tr>
<tr>
<td>2. LiveKit</td>
<td>Open-source control</td>
<td>Managed or self-hosted</td>
<td>Components and starter apps</td>
<td>Build $0; paid plans plus usage</td>
</tr>
<tr>
<td>3. Agora</td>
<td>Social and interactive live apps</td>
<td>Managed</td>
<td>UI Kits</td>
<td>10,000 standard minutes; HD $3.99/1,000</td>
</tr>
<tr>
<td>4. Daily</td>
<td>Browser-first video products</td>
<td>Managed</td>
<td>Daily Prebuilt</td>
<td>10,000 free monthly; then $0.004/min</td>
</tr>
<tr>
<td>5. 100ms</td>
<td>Role-based classes and events</td>
<td>Managed</td>
<td>Prebuilt</td>
<td>10,000 free monthly; then $0.004/min</td>
</tr>
<tr>
<td>6. Zoom Video SDK</td>
<td>Large custom video sessions</td>
<td>Managed</td>
<td>UI Toolkit</td>
<td>Minute-based Zoom Build pricing</td>
</tr>
<tr>
<td>7. ZEGOCLOUD</td>
<td>Social, gaming, and mini apps</td>
<td>Managed</td>
<td>20+ UI Kits</td>
<td>10,000 free; video $3.99/1,000</td>
</tr>
<tr>
<td>8. Stream Video</td>
<td>Existing Stream product stacks</td>
<td>Managed</td>
<td>SDK UI components</td>
<td>$100 monthly credit; HD $1.50/1,000</td>
</tr>
<tr>
<td>9. Twilio Video</td>
<td>Existing Twilio stacks</td>
<td>Managed</td>
<td>Custom SDK</td>
<td>$0.004 per participant minute</td>
</tr>
<tr>
<td>10. Jitsi Meet</td>
<td>Open-source meeting stack</td>
<td>Self-hosted or JaaS</td>
<td>Complete meeting UI</td>
<td>No licence fee; infrastructure costs apply</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Pricing was checked on 29 July 2026. Rates exclude taxes, storage, recording, transcription, support, regional charges, and negotiated discounts. Verify every pricing page before purchase or publication.</p><p>The table shows why one headline rate cannot decide the ranking. LiveKit and Jitsi move more operational work to your team, while managed providers charge separately for different media services.</p><h2 id="top-10-dyte-alternatives-for-video-calling">Top 10 Dyte alternatives for video calling</h2><p>These ten Dyte alternatives cover managed video APIs, self-hosted media, prebuilt meeting UI, custom SDKs, recording, and interactive streaming.</p><h3 id="1-videosdk-best-managed-replacement">1. VideoSDK: Best-Managed Replacement</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.29.39-PM-8.png" class="kg-image" alt="Top 10 Dyte Alternatives: Expert Tested & Ranked" loading="lazy" width="2906" height="1660"/></figure><p><strong>Best for:</strong> Teams that want one managed platform for custom video calling, prebuilt meetings, broad client coverage, recording, and interactive live streaming.</p><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> ranks first for a specific condition: you need a managed Dyte replacement that supports both a quick prebuilt path and a programmable custom interface.</p><p>VideoSDK provides 24/7 migration support for teams replacing Dyte, helping them map existing workflows, resolve integration issues, validate feature parity, and manage production cutover with less risk.</p><p>VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">React video</a> calling quickstart uses <code>MeetingProvider</code>, <code>useMeeting</code>, and <code>useParticipant</code> to separate meeting state, controls, and participant media. That structure gives Dyte teams clear migration boundaries.</p><p>VideoSDK also documents <a href="https://docs.videosdk.live/" rel="noreferrer">quickstarts</a> for JavaScript, React Native, Android, iOS, Flutter, Unity, Python, and C++. Teams can prototype with <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">VideoSDK Prebuilt</a>, then move to lower-level SDKs when they need custom layouts or behaviour.</p><p>VideoSDK's main trade-off is deployment control. It is a managed platform, so teams requiring their own media server should evaluate LiveKit or Jitsi before committing.</p><p><strong>Pricing:</strong> The current <a href="https://www.videosdk.live/pricing">VideoSDK pricing page</a> uses pay-as-you-go billing and advertises a one-time $20 starting balance. The pricing is&nbsp;<strong>$0.001</strong>&nbsp;per participant-minute for audio calls,&nbsp;<strong>$0.004</strong>&nbsp;per participant-minute for video calls, and&nbsp;<strong>$0.002</strong>&nbsp;per viewer-minute for live streaming. Model recording, streaming, transcription, and storage separately.</p><p><strong>Verdict:</strong> Choose VideoSDK when managed operations, prebuilt and custom UI paths, and multi-platform video calling matter more than self-hosting.</p><h3 id="2-livekit-best-open-source-option">2. LiveKit: Best Open-Source Option</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.40-PM-8.png" class="kg-image" alt="Top 10 Dyte Alternatives: Expert Tested & Ranked" loading="lazy" width="2920" height="1670"/></figure><p><strong>Best for:</strong> Teams that need an open-source WebRTC SFU, self-hosting, managed cloud, or deeper control over media infrastructure and backend participants.</p><p><a href="https://docs.livekit.io/intro/about/" rel="noreferrer nofollow">LiveKit</a> combines an Apache 2.0 media server with client SDKs, JWT authentication, ingress, egress, SIP, and LiveKit Cloud. Its <a href="https://github.com/livekit/livekit" rel="noreferrer nofollow">open-source repository</a> documents deployment through a single binary, Docker, or Kubernetes.</p><p>The room and participant model maps cleanly to many Dyte concepts. LiveKit also provides modern client SDKs and starter components, but a polished meeting product usually needs more application assembly than a highly opinionated prebuilt UI.</p><p>Self-hosting is not free operations. Your team owns TURN configuration, certificates, multi-region scaling, Redis, observability, upgrades, abuse controls, capacity testing, and recording infrastructure.</p><p><strong>Pricing:</strong> <a href="https://livekit.com/pricing" rel="noreferrer nofollow">LiveKit Cloud pricing</a> currently offers a $0 Build plan, Ship from $50 monthly, and Scale from $500 monthly. WebRTC minutes, downstream data transfer, and egress have plan allowances and overage rates.</p><p><strong>Verdict:</strong> Choose LiveKit when infrastructure control and open-source deployment justify the operational work. Choose a managed alternative when media operations are outside your team's core expertise.</p><h3 id="3-agora-best-for-social-live-apps">3. Agora: Best for Social Live Apps</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.26-PM-8.png" class="kg-image" alt="Top 10 Dyte Alternatives: Expert Tested & Ranked" loading="lazy" width="2920" height="1662"/></figure><p><strong>Best for:</strong> Consumer social, creator, gaming, and interactive live applications that need broad SDK coverage and several real-time engagement products.</p><p><a href="https://www.agora.io/en/products/video-call/" rel="noreferrer nofollow">Agora</a> provides programmable voice, video, interactive live streaming, chat, and cloud recording. Its product breadth is useful when a Dyte replacement must support both multi-party calls and audience-oriented live experiences.</p><p>That breadth creates the main evaluation challenge. Recording, analytics, cloud proxy, moderation, messaging, and support can have different billing rules, so the headline media rate does not represent total cost.</p><p>Dyte teams should map every required feature before estimating spend. Check participant roles, stream subscriptions, event names, recording layouts, RTMP output, firewall handling, and regional requirements.</p><p><strong>Pricing:</strong> Agora's interactive live streaming <a href="https://www.agora.io/en/pricing/interactive-live-streaming/" rel="noreferrer nofollow">pricing</a> lists 10,000 standard minutes, voice at $0.99 per 1,000 participant minutes, and HD video at $3.99 per 1,000.</p><p><strong>Verdict:</strong> Choose Agora when social and interactive live use cases dominate the product. For a simpler managed meeting replacement, compare VideoSDK, Daily, and 100ms first.</p><h3 id="4-daily-best-for-browser-first-products">4. Daily: Best for Browser-First Products</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.02-PM-5.png" class="kg-image" alt="Top 10 Dyte Alternatives: Expert Tested & Ranked" loading="lazy" width="2924" height="1652"/></figure><p><strong>Best for:</strong> Teams building browser-based calls with a quick prebuilt embed, a custom call object, recording, streaming, telephony, or Pipecat-based voice applications.</p><p><a href="https://www.daily.co/products/video-sdk/" rel="noreferrer nofollow">Daily</a> offers Daily Prebuilt alongside lower-level client SDKs. Its pricing FAQ describes Prebuilt as a full video call component embedded through a Daily room URL.</p><p>For Dyte migrations, the managed media layer reduces infrastructure work. Teams still need to validate permissions, active-speaker behaviour, reconnection, recording output, webhooks, and any custom layout assumptions.</p><p>Daily's secondary AI advantage comes from Pipecat, its open-source framework for real-time voice and multimodal agents. That capability should not outweigh video calling fit unless voice agents are on your roadmap.</p><p><strong>Pricing:</strong> <a href="https://www.daily.co/pricing/video-sdk/" rel="noreferrer nofollow">Daily includes</a> 10,000 free participant minutes each month, then charges $0.004 per video participant minute. Recording, RTMP, HLS, telephony, support, and compliance options have separate rates.</p><p><strong>Verdict:</strong> Choose Daily for a browser-first video product with flexible prebuilt and custom paths. Test the complete add-on cost before comparing it with a lower headline rate.</p><h3 id="5-100ms-best-for-role-based-events">5. 100ms: Best for Role-Based Events</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.31.12-PM-9.png" class="kg-image" alt="Top 10 Dyte Alternatives: Expert Tested & Ranked" loading="lazy" width="2910" height="1656"/></figure><p><strong>Best for:</strong> Online classrooms, webinars, audio rooms, and live events where hosts, teachers, speakers, moderators, and viewers need distinct permissions.</p><p><a href="https://www.100ms.live/docs/get-started/v2/get-started/overview" rel="noreferrer nofollow">100ms</a> organises video products around rooms, roles, templates, conferencing, and live streaming. This model maps well to Dyte applications with structured participation rather than identical permissions for every user.</p><p>Its SDKs and prebuilt option let teams choose between faster delivery and deeper interface control. The migration still requires careful testing of role definitions, templates, event semantics, and recording formats.</p><p>The main trade-off is cost composition. Conferencing minutes are only one part of the bill when production also requires recording, transcription, encoding, RTMP output, or large viewer audiences.</p><p><strong>Pricing:</strong> <a href="https://www.100ms.live/pricing" rel="noreferrer nofollow">100ms includes</a> 10,000 monthly conferencing minutes and 10,000 streaming minutes. Conferencing then costs $0.004 per participant minute, with separate viewer and encoding rates.</p><p><strong>Verdict:</strong> Choose 100ms when role design and event workflows drive the application. For general custom video calls, compare its total workflow cost with VideoSDK and Daily.</p><h3 id="6-zoom-video-sdk-best-for-large-sessions">6. Zoom Video SDK: Best for Large Sessions</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.32.46-PM-7.png" class="kg-image" alt="Top 10 Dyte Alternatives: Expert Tested & Ranked" loading="lazy" width="2920" height="1646"/></figure><p><strong>Best for:</strong> Teams that want Zoom's media infrastructure inside a custom application without placing users inside standard Zoom Meetings or Webinars.</p><p>The <a href="https://developers.zoom.us/docs/video-sdk/" rel="noreferrer nofollow">Zoom Video SDK</a> provides video, audio, screen sharing, chat, data streams, cloud recording, live streaming, server APIs, webhooks, and raw media access on supported native platforms.</p><p>Zoom documents SDK support for iOS, Android, macOS, Windows, web, React Native, Linux, Flutter, and Unity. It also states that one Video SDK session can support up to 5,000 users.</p><p>The product boundary matters. Zoom's pricing page confirms that a Video SDK session cannot join a Zoom Meeting, so existing meeting licences and workflows do not automatically transfer.</p><p><strong>Pricing:</strong> Zoom currently bills the Video SDK through minute-based Zoom Build Platform <a href="https://zoom.us/pricing?_ics=1785238426943&amp;irclickid=~59c-eiprxvuklorxvwmukbc58ZXYV20PSXQSUJKJDzvmge91WUQH&amp;_gl=1*16p99m7*_gcl_au*OTM5ODY4NTY4LjE3ODQyNzM1Mzk." rel="noreferrer nofollow">pricing</a>. Confirm the applicable credit package and service rates inside the current account or sales flow.</p><p><strong>Verdict:</strong> Choose Zoom Video SDK for large custom sessions or raw-media workflows. Do not choose it merely because your organisation already uses Zoom Meetings.</p><h3 id="7-zegocloud-best-for-social-experiences">7. ZEGOCLOUD: Best for Social Experiences</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.33.21-PM-5.png" class="kg-image" alt="Top 10 Dyte Alternatives: Expert Tested & Ranked" loading="lazy" width="2926" height="1668"/></figure><p><strong>Best for:</strong> Social, dating, gaming, creator, and mini-app products that need video calls, live streaming, chat, effects, and many ready-made interface patterns.</p><p><a href="https://www.zegocloud.com/product/video-call" rel="noreferrer nofollow">ZEGOCLOUD</a> separates video calling, voice, live streaming, chat, cloud recording, effects, and collaborative products. Its pricing page also advertises more than 20 prebuilt UI Kits.</p><p>This catalogue can shorten delivery for familiar social formats. It can also increase evaluation complexity because the correct SDK, UI Kit, quality tier, and add-ons depend on the exact experience.</p><p>Dyte teams should validate platform coverage, token design, stream-based billing, room limits, event semantics, recording modes, moderation, and regional availability before committing.</p><p><strong>Pricing:</strong> ZEGOCLOUD pricing <a href="https://www.zegocloud.com/pricing?index=0" rel="noreferrer nofollow">calculator</a> lists 10,000 free minutes, video calls at $3.99 per 1,000 participant minutes, and separate rates for live streaming and cloud recording.</p><p><strong>Verdict:</strong> Choose ZEGOCLOUD when social engagement formats and unusual client environments shape the product. A narrower video application may benefit from a simpler service map.</p><h3 id="8-stream-video-best-for-stream-stacks">8. Stream Video: Best for Stream Stacks</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-28-at-4.33.18-PM-1.png" class="kg-image" alt="Top 10 Dyte Alternatives: Expert Tested & Ranked" loading="lazy" width="2890" height="1540"/></figure><p><strong>Best for:</strong> Product teams already using Stream Chat, activity feeds, or moderation and wanting video, audio rooms, or live streaming in the same developer ecosystem.</p><p><a href="https://getstream.io/video/docs/" rel="noreferrer nofollow">Stream Video</a> provides lower-level APIs and ready-made UI components. Existing Stream customers can reduce vendor boundaries across video, chat, feeds, and moderation, which may simplify identity and application state.</p><p>Its pricing model needs careful reading. Stream bills video according to participant minutes and the aggregate resolution each participant receives, rather than one flat video rate for every call.</p><p>That model can be efficient when automatic quality selection keeps small tiles at lower resolutions. Screen sharing and several visible high-resolution tracks can move usage into higher pricing bands.</p><p><strong>Pricing:</strong> <a href="https://getstream.io/video/pricing/" rel="noreferrer nofollow">Stream Video pricing page</a> lists $100 in monthly credit. Current rates include $1.50 per 1,000 participant minutes for HD and $3.00 for Full HD.</p><p><strong>Verdict:</strong> Choose Stream Video when it completes an existing Stream product stack. Model realistic layouts before assuming the published HD rate covers every participant view.</p><h3 id="9-twilio-video-best-for-twilio-stacks">9. Twilio Video: Best for Twilio Stacks</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.53.31-PM-4.png" class="kg-image" alt="Top 10 Dyte Alternatives: Expert Tested & Ranked" loading="lazy" width="2910" height="1638"/></figure><p><strong>Best for:</strong> Organisations already using Twilio Voice, Messaging, phone numbers, Flex, security controls, procurement, and billing across customer communication products.</p><p>Twilio Programmable Video remains an active standalone product. Twilio reversed its earlier retirement <a href="https://www.twilio.com/en-us/changelog/-twilio-video-will-remain-a-standalone-product" rel="noreferrer nofollow">decision</a> in October 2024 and states that new and existing customers can continue using it.</p><p><a href="https://www.twilio.com/docs/video" rel="noreferrer nofollow">Twilio Video</a> supports group rooms, participant recordings, compositions, transcription, voice interoperability, and network quality controls. Existing commercial relationships can reduce organisational adoption work.</p><p>The main limitation is scope. Twilio's current pricing page lists up to 50 participants per room, while the separate Twilio Live product reached end of life.</p><p><strong>Pricing:</strong> Twilio <a href="https://www.twilio.com/en-us/video/pricing" rel="noreferrer nofollow">video pricing</a> starts at $0.004 per participant minute. Recordings, transcription, compositions, storage, voice interoperability, and enterprise editions add separate costs.</p><p><strong>Verdict:</strong> Choose Twilio Video when your communication stack already centres on Twilio and 50-participant rooms meet the requirement. Look elsewhere for a combined conferencing and large-audience replacement.</p><h3 id="10-jitsi-meet-best-complete-open-source-stack">10. Jitsi Meet: Best Complete Open Source Stack</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-29-at-2.08.49-PM.png" class="kg-image" alt="Top 10 Dyte Alternatives: Expert Tested & Ranked" loading="lazy" width="2928" height="1662"/></figure><p><strong>Best for:</strong> Teams that prefer a complete open-source meeting experience, infrastructure control, web and native SDKs, and no software licence charge.</p><p>Jitsi Meet is an Apache 2.0 project with browser and mobile applications, web and native SDKs, HD media, screen sharing, chat, polls, reactions, and virtual backgrounds.</p><p>The <a href="https://github.com/jitsi/jitsi-meet" rel="noreferrer nofollow">Jitsi Meet repository</a> documents self-hosting through Debian packages or Docker. Jitsi as a Service is available for teams wanting managed monitoring, scaling, and updates.</p><p>Self-hosting transfers responsibility for servers, networking, TLS, monitoring, upgrades, security, abuse prevention, recording, and telephony. Jibri and Jigasi introduce additional components for some workflows.</p><p><strong>Pricing:</strong> The open-source software has no licence fee. Infrastructure, bandwidth, storage, operations, recording, support, and any managed JaaS plan form the actual production cost.</p><p><strong>Verdict:</strong> Choose Jitsi when a complete open-source meeting stack matters more than managed analytics and a smaller operational footprint.</p><p>The top ten cover different constraints, which is why the ranking should guide a prototype rather than replace one.</p><h2 id="which-dyte-alternative-should-you-choose">Which Dyte alternative should you choose?</h2><p>Choose the Dyte alternative that removes your largest constraint without transferring unacceptable cost or operational risk elsewhere.</p><ul><li>Choose <strong>VideoSDK</strong> when you need managed video calling, prebuilt and custom UI paths, multi-platform SDKs, recording, and interactive live streaming.</li><li>Choose <strong>LiveKit</strong> when an open-source <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu" rel="noreferrer">SFU</a>, self-hosting, and backend media control are mandatory requirements.</li><li>Choose <strong>Agora</strong> when social, gaming, or interactive live experiences dominate your traffic and feature roadmap.</li><li>Choose <strong>Daily</strong> when browser-first delivery and a flexible prebuilt component matter most.</li><li>Choose <strong>100ms</strong> when roles, room templates, classrooms, webinars, and viewer workflows define the product.</li><li>Choose <strong>Zoom Video SDK</strong> when you need large custom sessions or native raw-media access on Zoom's infrastructure.</li><li>Choose <strong>ZEGOCLOUD</strong> when social UI Kits, effects, chat, and non-standard client environments drive the decision.</li><li>Choose <strong>Stream Video</strong> when video must fit an existing Stream Chat, feed, or moderation stack.</li><li>Choose <strong>Twilio Video</strong> when your communication architecture already uses Twilio and the room limit is acceptable.</li><li>Choose <strong>Jitsi Meet</strong> when infrastructure control and open-source licensing outweigh managed operations.</li></ul><p>The best decision comes from a representative proof of concept, not a feature matrix viewed without your application's traffic and failure conditions.</p><h2 id="how-to-migrate-from-dyte-safely">How to migrate from Dyte safely</h2><p>A safe Dyte migration preserves behaviour through a measured dual run, not a direct package substitution performed under deadline pressure.</p><ol><li><strong>Evaluate RealtimeKit first.</strong> Compare Cloudflare's official package mappings with independent alternatives before accepting the cost and risk of a wider application rewrite.</li><li><strong>Inventory your current contract.</strong> Record authentication, rooms, participants, roles, permissions, device controls, events, webhooks, recording, streaming, analytics, and failure handling.</li><li><strong>Build a translation matrix.</strong> Map each Dyte object and event to the candidate platform, noting changed defaults, missing capabilities, and new server-side responsibilities.</li><li><strong>Create the thinnest vertical slice.</strong> Implement token generation, room creation, joining, camera and microphone controls, participant rendering, leaving, and one reconnection path.</li><li><strong>Test representative conditions.</strong> Cover mobile handoffs, restrictive firewalls, weak bandwidth, packet loss, device switching, backgrounding, reconnection, and bursts of participant joins.</li><li><strong>Run both paths temporarily.</strong> Send internal sessions and a small production cohort through the new stack while keeping rollback, comparable telemetry, and support escalation ready.</li><li><strong>Validate total cost.</strong> Include participant minutes, bandwidth, recording, storage, composition, RTMP or HLS, transcription, support, compliance, and self-hosted engineering time.</li></ol>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Dyte area</th>
<th>Migration question</th>
<th>Acceptance evidence</th>
</tr>
</thead>
<tbody>
<tr>
<td>Authentication</td>
<td>Can tokens preserve room and role restrictions?</td>
<td>Expiry, reuse, and negative tests pass</td>
</tr>
<tr>
<td>Participant state</td>
<td>Are join, leave, mute, metadata, and reconnect events equivalent?</td>
<td>Event traces match expected flows</td>
</tr>
<tr>
<td>Media controls</td>
<td>Do devices, screen share, permissions, and quality policies behave correctly?</td>
<td>Cross-browser and mobile tests pass</td>
</tr>
<tr>
<td>Recording and streaming</td>
<td>Are layouts, formats, latency, and callbacks acceptable?</td>
<td>Output and webhook tests pass</td>
</tr>
<tr>
<td>Operations</td>
<td>Can support diagnose quality, failures, and regional issues?</td>
<td>Dashboards and incident runbooks are ready</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Migration is complete only when the replacement preserves user behaviour, failure recovery, observability, and cost boundaries under production conditions.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Participant minute:</strong> One participant connected for one minute. Ten people connected for a 30-minute call usually create 300 participant minutes.</blockquote><blockquote><strong>Prebuilt UI:</strong> A ready-made meeting interface that speeds up delivery but may expose fewer visual and behavioural controls than lower-level SDKs.</blockquote><blockquote><strong>SFU:</strong> A selective forwarding unit routes selected media streams between participants without combining every stream into one server-generated video.</blockquote><blockquote><strong>Meeting token:</strong> A credential that authorises a participant to join a room. Production tokens should be generated and scoped on a trusted server.</blockquote><blockquote><strong>Interactive live streaming:</strong> A low-latency format separating active hosts or speakers from viewers, often with stage promotion and external RTMP or HLS output.</blockquote><p>Clear definitions prevent billing and architecture terms from hiding important differences between providers.</p><h2 id="key-takeaways">Key takeaways</h2><p>Dyte's lifecycle change makes migration quality, product health, and operating model more important than a simple feature count.</p><ul><li>VideoSDK is the strongest general managed replacement when custom SDKs, prebuilt UI, broad platform support, and interactive streaming must coexist.</li><li>LiveKit is the stronger choice when self-hosting and infrastructure control outweigh the convenience of fully managed media.</li><li>Agora, Daily, and 100ms fit specialised social live, browser-first, and role-based event requirements respectively.</li><li>Public media rates are not total cost because recording, storage, data transfer, transcription, proxy, support, and compliance can price separately.</li><li>Existing Dyte teams should compare Cloudflare RealtimeKit first, then prototype one complete call flow before selecting an independent provider.</li></ul><p>The safest shortlist contains two or three platforms whose operating models fit your team before any detailed feature scoring begins.</p><h2 id="conclusion">Conclusion</h2><p>The leading Dyte alternatives solve different constraints, so the right choice starts with your application's video workflow, deployment model, and real operating cost.<br>VideoSDK is the strongest managed all-rounder, LiveKit leads for open-source control, and Agora suits specialised social and live products. Compare RealtimeKit first, then test difficult networks and full billing paths. You can <a href="https://app.videosdk.live/login">create a VideoSDK account</a> and prototype the managed route. <br>What are you building with VideoSDK?</br></br></p><h2 id="frequently-asked-questions">Frequently asked questions </h2><h3 id="what-is-the-best-dyte-alternative">What is the best Dyte alternative?</h3><p>VideoSDK is the best general managed Dyte alternative when a team needs custom video SDKs, prebuilt UI, multiple client platforms, recording, and interactive live streaming.</p><p>LiveKit is stronger when self-hosting is mandatory. Agora can be stronger for specialised social and high-volume interactive live experiences.</p><h3 id="is-dyte-discontinued">Is Dyte discontinued?</h3><p>Legacy Dyte SDKs are in maintenance mode, according to the official Dyte migration guide. They will not receive feature updates or bug fixes.</p><p>Cloudflare RealtimeKit is the direct successor. Existing Dyte applications should plan a migration even when their current integration continues functioning.</p><h3 id="is-cloudflare-realtimekit-a-dyte-alternative">Is Cloudflare RealtimeKit a Dyte alternative?</h3><p>Cloudflare RealtimeKit is better described as Dyte's successor than as an independent alternative. Cloudflare provides direct package mappings from legacy Dyte SDKs.</p><p>Teams should evaluate RealtimeKit first for migration distance, then compare independent providers when deployment, pricing, support, UI, or platform requirements justify a wider switch.</p><h3 id="can-videosdk-replace-dyte-ui-kit">Can VideoSDK replace Dyte UI Kit?</h3><p>VideoSDK Prebuilt can replace many standard meeting-interface requirements, while VideoSDK's custom SDKs support deeper layout and behaviour control.</p><p>No UI migration is automatically identical. Validate every required control, event, permission, plugin, recording layout, and accessibility behaviour in a representative room.</p><h3 id="what-is-the-best-open-source-dyte-alternative">What is the best open-source Dyte alternative?</h3><p>LiveKit is the strongest modular open-source Dyte alternative for teams wanting an SFU, broad SDK ecosystem, managed-cloud option, and self-hosting.</p><p>Jitsi Meet is stronger when the requirement is a complete open-source meeting application. Both options transfer more operational responsibility than a managed video API.</p><h3 id="which-dyte-alternative-is-cheapest">Which Dyte alternative is cheapest?</h3><p>No provider is cheapest for every workload because billing units and add-ons differ. A low participant-minute rate may exclude data transfer, recording, transcription, or support.</p><p>Price a real workload with call size, duration, quality, recording, storage, streaming, geography, and support requirements before comparing totals.</p><h3 id="which-alternative-is-best-for-live-streaming">Which alternative is best for live streaming?</h3><p>Agora, VideoSDK, 100ms, and ZEGOCLOUD are credible choices when interactive live streaming accompanies video calling.</p><p>Test host and viewer roles, stage promotion, stream fan-out, RTMP or HLS output, recording, reconnection, analytics, and billing with a representative event.</p><p>The FAQ answers support quick comparison, but the production proof of concept remains the final decision tool.</p><h2 id="related-videosdk-resources">Related VideoSDK resources</h2><p>These VideoSDK resources help a Dyte migration team test one complete managed-video path before making a platform commitment.</p><ul><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">Build a React video call with VideoSDK</a></li><li><a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Launch a meeting with VideoSDK Prebuilt</a></li><li><a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples">Review VideoSDK backend token and room examples</a></li><li><a href="https://docs.videosdk.live/code-sample">Browse VideoSDK client code samples</a></li><li><a href="https://www.videosdk.live/pricing">Check current VideoSDK pricing</a></li></ul><p>Use these resources to build a small vertical slice covering authentication, room creation, joining, participant rendering, media controls, and leaving.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 Whereby Embedded Alternatives in 2026: Expert-Tested & Ranked]]></title><description><![CDATA[Compare the top Whereby Embedded alternatives for programmable video calls. See current pricing, SDK coverage, hosting choices, tradeoffs, and migration guidance for VideoSDK, Daily, LiveKit, Agora, and six more APIs.]]></description><link>https://www.videosdk.live/blog/whereby-embedded-alternatives</link><guid isPermaLink="false">6a6873fcb3240feb748c8dc9</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 28 Jul 2026 13:52:55 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-28--2026--03_44_45-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>VideoSDK is the strongest overall Whereby Embedded alternative for teams needing a prebuilt launch path plus custom web, mobile, Unity, C++, Python, and REST workflows. Daily is the closest browser-first managed option. LiveKit leads when an open-source server and self-hosting are non-negotiable. Validate the choice with your actual devices, networks, and add-ons.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-28--2026--03_44_45-PM.png" alt="Top 10 Whereby Embedded Alternatives in 2026: Expert-Tested & Ranked"/><p>Most lists of Whereby Embedded alternatives mix meeting apps, video hosts, virtual offices, and programmable APIs. That does not help a developer replacing Whereby Embedded.</p><p>This ranking covers only video calling APIs and SDKs that can power calls inside your product. It excludes standalone meeting tools such as Zoom Workplace and Google Meet.</p><p>The shortlist balances migration effort, UI control, platform coverage, production operations, and total cost. VideoSDK ranks first for the broadest common migration case, but Daily, LiveKit, and others win under specific requirements.</p><h2 id="what-are-whereby-embedded-alternatives-for-video-calling-apis">What Are Whereby Embedded Alternatives for Video Calling APIs?</h2><p>Whereby embedded alternatives are programmable video APIs or SDKs that embed real-time calls inside an application, rather than sending users to a separate meeting product.</p><p>A genuine alternative should provide room or session APIs, participant controls, media events, authentication, and a supported client integration. Recording, transcription, streaming, moderation, and analytics may be optional services.</p><p>This definition excludes products built mainly for webinars, asynchronous video, or hosted meetings. Current programmable products, including Twilio Video, remain eligible when they expose supported APIs and client SDKs.</p><h2 id="whereby-embedded-the-baseline">Whereby Embedded: The Baseline</h2><p><a href="https://whereby.com/information/embedded" rel="noreferrer nofollow">Whereby Embedded</a> is a managed video platform built for adding calls to web and mobile products without operating <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> infrastructure.</p><p>The fastest route is its prebuilt web component, which can be embedded with a room URL. Whereby also offers a Browser SDK and a lower-level Core SDK for custom web interfaces. Its native iOS SDK is under active development, while its Android SDK loads the Whereby web component through a WebView.</p><p>On the <a href="https://whereby.com/information/embedded/pricing" rel="noreferrer nofollow">current public rate card</a>, Explore includes 2,000 participant minutes monthly. Build costs $9.99 monthly, includes the same allowance, and charges $0.004 per additional participant minute. Rooms support up to 200 participants with 24 active video tiles.</p><p>Staying on Whereby is sensible when a browser-first prebuilt experience meets your product needs, 24 visible videos are enough, and a managed service is preferable to deeper client or infrastructure control.</p><h2 id="how-we-ranked-these-whereby-embedded-alternatives">How We Ranked These Whereby Embedded Alternatives</h2><p>These Whereby Embedded alternatives are ranked for migration fit, not brand popularity or the number of features on a pricing page.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Criterion</th>
<th style="text-align:right">Weight</th>
<th>What we checked</th>
</tr>
</thead>
<tbody>
<tr>
<td>Migration fit</td>
<td style="text-align:right">25%</td>
<td>Room model, tokens, webhooks, moderation, recording, and effort to replace an embedded Whereby flow</td>
</tr>
<tr>
<td>Custom UI control</td>
<td style="text-align:right">20%</td>
<td>Prebuilt option, headless APIs, UI kits, media events, and layout freedom</td>
</tr>
<tr>
<td>SDK coverage</td>
<td style="text-align:right">20%</td>
<td>Publicly documented web, mobile, desktop, game-engine, server, and specialist client paths</td>
</tr>
<tr>
<td>Production readiness</td>
<td style="text-align:right">15%</td>
<td>TURN and firewall support, regional controls, observability, compliance options, and service limits</td>
</tr>
<tr>
<td>Cost clarity</td>
<td style="text-align:right">10%</td>
<td>Participant-minute rates, free allowance, add-ons, fixed fees, and self-hosting costs</td>
</tr>
<tr>
<td>Documentation quality</td>
<td style="text-align:right">10%</td>
<td>Quickstarts, API references, samples, release activity, and migration guidance</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>“Expert tested” means we reviewed current first-party documentation, quickstarts, pricing pages, architecture choices, and the decisions a production proof of concept must cover. We did not run a controlled global network-quality benchmark, so this article does not claim one provider has universally better call quality.</p><p>Pricing was checked on <strong>28 July 2026</strong>. Public plans change, and enterprise contracts may differ by region, volume, compliance requirements, or support level.</p><h2 id="top-10-whereby-embedded-alternatives-ranked-for-2026">Top 10 Whereby Embedded Alternatives Ranked for 2026</h2><p>The strongest Whereby Embedded alternatives serve different priorities: cross-platform depth, a fast browser embed, self-hosting, role-based rooms, or enterprise scale.</p><h3 id="1-videosdk-best-overall-for-prebuilt-to-custom-growth">1. VideoSDK: Best Overall for Prebuilt-to-Custom Growth</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.29.39-PM-6.png" class="kg-image" alt="Top 10 Whereby Embedded Alternatives in 2026: Expert-Tested & Ranked" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://www.videosdk.live/">VideoSDK</a> ranks first because it covers the most common Whereby migration path: launch quickly, then add deeper client and workflow control without changing platforms.</p><p>Its public documentation includes <a href="https://docs.videosdk.live/docs/tutorials/realtime-communication/prebuilt-sdk/quickstart-prebuilt-js" rel="noreferrer">Prebuilt</a>, JavaScript, React, React Native, Android, iOS, Flutter, Unity, IoT, C++, Python, and REST API paths. That menu is useful when a browser-first call later expands into native apps, desktop clients, connected devices, or server-managed workflows.</p><p><strong>Why it ranks first:</strong> VideoSDK combines a prebuilt experience with custom RTC SDKs and APIs for rooms, sessions, recording, transcription, webhooks, and streaming. Teams can preserve a managed infrastructure model while gaining more client choices than Whereby currently documents.</p><p><strong>Best for:</strong> SaaS platforms, telehealth, education, customer support, social products, and teams expecting to add new clients after an initial web launch.</p><p><strong>Pricing:</strong> The <a href="https://www.videosdk.live/pricing">public pricing page</a> offers a $20 starting credit and usage-based billing as <strong>$0.001</strong>&nbsp;per participant-minute for audio calls,&nbsp;<strong>$0.004</strong>&nbsp;per participant-minute for video calls, and&nbsp;<strong>$0.002</strong>&nbsp;per viewer-minute for live streaming. Model recording, transcription, streaming, storage, and support alongside participant minutes.</p><p><strong>Fit among </strong>the <strong>Whereby embedded alternatives:</strong> VideoSDK requires more product decisions when building a custom interface. Whereby remains simpler when its prebuilt browser experience already fits. VideoSDK is also managed, so choose LiveKit or Jitsi if self-hosting the media server is mandatory.</p><h3 id="2-daily-best-for-a-browser-first-managed-migration">2. Daily: Best for a Browser-First Managed Migration</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.02-PM-3.png" class="kg-image" alt="Top 10 Whereby Embedded Alternatives in 2026: Expert-Tested & Ranked" loading="lazy" width="2924" height="1652"/></figure><p><a href="https://www.daily.co/products/video-sdk/" rel="noreferrer nofollow">Daily</a> is the closest fit for teams that like Whereby’s fast web integration but want another mature managed API with prebuilt and custom options.</p><p>Daily Prebuilt provides a quick embed, while its client SDKs support JavaScript, React Native, iOS, Android, Flutter, and Python use cases. The product is especially approachable for browser-led prototypes and standard call layouts.</p><p><strong>Why it ranks second:</strong> Daily offers a low-friction transition from a prebuilt room to a custom call object. Its documentation and sample coverage reduce the time needed to assess devices, tracks, screen sharing, and recording.</p><p><strong>Best for:</strong> Browser-first SaaS, telehealth prototypes, interview products, support tools, and teams that want a managed service with a straightforward developer experience.</p><p><strong>Pricing:</strong> <a href="https://www.daily.co/pricing/video-sdk/" rel="noreferrer nofollow">Daily includes</a> 10,000 free participant minutes monthly, then starts at $0.004 per participant minute with volume discounts. Recording, transcription, HIPAA support, and advanced firewall services add separate costs.</p><p><strong>Fit among the Whereby embedded alternatives:</strong> Daily is a natural choice when the core requirement remains a managed browser call. Check fixed compliance and firewall add-ons if enterprise networks or regulated data are central to the deployment.</p><h3 id="3-livekit-best-open-source-and-self-hosted-option">3. LiveKit: Best Open-Source and Self-Hosted Option</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.40-PM-6.png" class="kg-image" alt="Top 10 Whereby Embedded Alternatives in 2026: Expert-Tested & Ranked" loading="lazy" width="2920" height="1670"/></figure><p><a href="https://docs.livekit.io/intro/about/" rel="noreferrer nofollow">LiveKit</a> is the leading choice when infrastructure ownership, open-source code, or a managed-to-self-hosted path matters more than a minimal embed.</p><p>LiveKit provides an open-source WebRTC SFU, client SDKs, server APIs, and LiveKit Cloud. Teams can use the managed service or run the server on their own infrastructure.</p><p><strong>Why it ranks third:</strong> No other option near the top combines this level of open-source infrastructure control with a managed cloud path. It suits teams that need to choose deployment boundaries rather than accept a managed-only service.</p><p><strong>Best for:</strong> Infrastructure-led teams, AI voice and video applications, regulated environments with custom deployment requirements, and products that need media-server control.</p><p><strong>Pricing:</strong> The <a href="https://livekit.com/pricing" rel="noreferrer nofollow">Build plan</a> is free, with published quotas including 5,000 WebRTC participant minutes and 50 GB of data transfer. Paid Cloud plans start at $50 monthly. Self-hosting replaces vendor usage fees with compute, bandwidth, TURN, monitoring, upgrades, and on-call costs.</p><p><strong>Fit among the Whereby embedded alternatives:</strong> LiveKit offers more deployment freedom but demands more architectural judgment. Whereby is faster for a conventional embedded room; LiveKit is stronger when infrastructure control is part of the product requirement.</p><h3 id="4-agora-best-for-specialized-clients-and-large-scale-interactivity">4. Agora: Best for Specialized Clients and Large-Scale Interactivity</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.26-PM-6.png" class="kg-image" alt="Top 10 Whereby Embedded Alternatives in 2026: Expert-Tested & Ranked" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/en/products/video-call/" rel="noreferrer nofollow">Agora</a> is a strong option for products spanning conventional video calls, mobile-heavy experiences, game engines, and larger interactive audiences.</p><p>Its RTC platform exposes detailed media controls and a broad client ecosystem. Agora is often shortlisted when an application must support varied devices or interactive formats beyond a standard browser room.</p><p><strong>Why it ranks fourth:</strong> Agora combines mature RTC primitives with wide client coverage and adjacent real-time products. This can reduce platform fragmentation for teams serving consumer, gaming, or live-interaction use cases.</p><p><strong>Best for:</strong> Social applications, gaming, mobile-first products, live commerce, and teams needing specialist client support.</p><p><strong>Pricing:</strong> Agora includes <a href="https://www.agora.io/en/pricing/video-calling/" rel="noreferrer nofollow">10,000 free minutes monthly</a>. Public rates list HD video at $3.99 per 1,000 participant minutes and Full HD at $8.99. Analytics, cloud proxy, recording, and support can change the total.</p><p><strong>Fit among the Whereby embedded alternatives:</strong> Agora provides more media and client depth, but its resolution tiers and optional services require a fuller cost model. Whereby is easier when the product needs a compact browser embed and predictable room behavior.</p><h3 id="5-100ms-best-for-role-based-rooms">5. 100ms: Best for Role-Based Rooms</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.31.12-PM-7.png" class="kg-image" alt="Top 10 Whereby Embedded Alternatives in 2026: Expert-Tested & Ranked" loading="lazy" width="2910" height="1656"/></figure><p><a href="https://www.100ms.live/docs/get-started/v2/get-started/overview" rel="noreferrer nofollow">100ms</a> is designed around rooms, roles, and templates, which maps well to classrooms, live communities, and moderated events.</p><p>Developers can start with a prebuilt experience or use SDKs for web, Android, iOS, Flutter, and React Native. Role definitions help express who can publish, subscribe, screen share, or change permissions.</p><p><strong>Why it ranks fifth:</strong> The role-first model makes complex participant behavior easier to configure than a collection of client-side conditionals. It also connects real-time rooms with live-streaming workflows.</p><p><strong>Best for:</strong> Education, webinars with interactive speakers, creator communities, town halls, and products with multiple participant types.</p><p><strong>Pricing:</strong> <a href="https://www.100ms.live/pricing" rel="noreferrer nofollow">100ms includes</a> 10,000 free conferencing minutes, then charges $0.004 per participant minute for conferencing. Recording, transcription, streaming, and encoding have separate allowances and rates.</p><p><strong>Fit among the Whereby embedded alternatives:</strong> 100ms offers stronger role orchestration for structured sessions. Whereby remains simpler when every participant has roughly the same call experience and the prebuilt room already matches the interface.</p><h3 id="6-dyte-best-for-component-level-ui-control">6. Dyte: Best for Component-Level UI Control</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.31.41-PM-1.png" class="kg-image" alt="Top 10 Whereby Embedded Alternatives in 2026: Expert-Tested & Ranked" loading="lazy" width="2914" height="1652"/></figure><p><a href="https://docs.dyte.io/react-ui-kit" rel="noreferrer nofollow">Dyte</a> is a good fit for teams that want prebuilt interface components without accepting a fixed, all-or-nothing call layout.</p><p>Its UI kit and core SDK approach lets developers assemble controls, participant views, notifications, and layouts from composable pieces. Mobile integration paths include React Native, Flutter, Android, and iOS.</p><p><strong>Why it ranks sixth:</strong> Dyte sits between a full prebuilt embed and a completely headless UI. That can shorten development while preserving product-specific layouts and workflows.</p><p><strong>Best for:</strong> Collaboration products, support tools, hiring platforms, and teams that want design-system alignment without building every video control from scratch.</p><p><strong>Pricing:</strong> Dyte’s <a href="https://beta.dyte.io/pricing" rel="noreferrer nofollow">public pricing page</a>lists 10,000 free minutes, then $0.004 per user-minute for video and $0.001 for audio. Recording and RTMP streaming are billed separately. Confirm current terms because the published page remains on a beta subdomain.</p><p><strong>Fit among the Whereby embedded alternatives:</strong> Dyte gives developers more component-level control than a single prebuilt room. That flexibility introduces more interface assembly and state management than Whereby’s fastest embed.</p><h3 id="7-zoom-video-sdk-best-for-enterprise-scale">7. Zoom Video SDK: Best for Enterprise Scale</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.32.46-PM-5.png" class="kg-image" alt="Top 10 Whereby Embedded Alternatives in 2026: Expert-Tested & Ranked" loading="lazy" width="2920" height="1646"/></figure><p><a href="https://developers.zoom.us/docs/video-sdk/" rel="noreferrer nofollow">Zoom Video SDK</a> uses Zoom’s media infrastructure without inserting the Zoom Meetings interface or meeting workflow into the application.</p><p>It supports web, iOS, Android, macOS, Windows, Linux, React Native, Flutter, Unity, and UI Toolkit paths. Zoom documents sessions with up to 5,000 users, subject to plan and platform constraints.</p><p><strong>Why it ranks seventh:</strong> The Video SDK suits organizations that value enterprise procurement, large sessions, desktop clients, and an established communications ecosystem.</p><p><strong>Best for:</strong> Enterprise collaboration, large interactive events, desktop-heavy products, and buyers already working with Zoom.</p><p><strong>Pricing:</strong> Zoom's&nbsp;<a href="https://zoom.us/pricing/developer" rel="noreferrer nofollow">developer pricing page</a>&nbsp;now uses prepaid Build Platform credits and bills Video SDK usage by minutes. Its product page advertises 20 credits per month at no charge, but the exact effective per-minute rate depends on the current credit schedule and selected services.</p><p><strong>Fit among the Whereby embedded alternatives:</strong> Zoom Video SDK supports more platforms and larger sessions, but the integration and account surface can feel heavier than Whereby Embedded. Choose it when enterprise scale or ecosystem fit justifies that complexity.</p><h3 id="8-twilio-video-best-for-twilio-voice-interoperability">8. Twilio Video: Best for Twilio Voice Interoperability</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.53.31-PM-2.png" class="kg-image" alt="Top 10 Whereby Embedded Alternatives in 2026: Expert-Tested & Ranked" loading="lazy" width="2910" height="1638"/></figure><p><a href="https://www.twilio.com/docs/video" rel="noreferrer nofollow">Twilio Video</a> remains an active programmable product for custom video rooms on JavaScript, iOS, and Android clients, with REST APIs and server-side helper libraries.</p><p><strong>Why it ranks eighth:</strong> Twilio combines customizable group rooms, track-level controls, Video Insights, recordings, compositions, transcription, and direct interoperability with Programmable Voice.</p><p><strong>Best for:</strong> Teams already using Twilio, telehealth, customer engagement, support applications, and products that need PSTN or SIP callers inside a video room.</p><p><strong>Pricing:</strong> Twilio Video starts at <a href="https://www.twilio.com/en-us/video/pricing" rel="noreferrer nofollow">$0.004 per participant minute</a>. Participant recording costs another $0.004 per recorded participant minute, composition costs $0.01 per composed minute, and real-time transcription costs $0.027 per room minute.</p><p><strong>Fit among the Whereby embedded alternatives:</strong> Twilio provides mature APIs and communications-channel integration, but its 50-participant room limit and web, iOS, and Android client focus are narrower than several higher-ranked options. It also requires a custom UI rather than a Whereby-style prebuilt room.</p><h3 id="9-vonage-video-api-best-for-broadcast-sip-and-enterprise-workflows">9. Vonage Video API: Best for Broadcast, SIP, and Enterprise Workflows</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.32.16-PM-3.png" class="kg-image" alt="Top 10 Whereby Embedded Alternatives in 2026: Expert-Tested & Ranked" loading="lazy" width="2922" height="1652"/></figure><p><a href="https://developer.vonage.com/en/video/technical-details" rel="noreferrer nofollow">Vonage Video API</a> is the current name for the OpenTok-based programmable video platform, with active documentation for web, iOS, Android, desktop, server, and REST integrations.</p><p>Its platform covers interactive sessions, archives, broadcasts, SIP connections, captions, and enterprise deployment options. The mix is useful when a call must connect with telephony or large broadcast workflows.</p><p><strong>Why it ranks eighth:</strong> Vonage has a deep communications API portfolio and practical options for combining interactive video with recording, broadcast, and SIP.</p><p><strong>Best for:</strong> Enterprise communications, contact-centre workflows, broadcasting, telehealth, and products that need video plus telephony integration.</p><p><strong>Pricing:</strong> Vonage lists a base rate of <a href="https://www.vonage.com/communications-apis/video/pricing/" rel="noreferrer nofollow">$0.00410</a> per participant minute. New customers receive a published 100,000-minute trial allocation split between video and advanced features. Archives, captions, SIP, regional zones, and enterprise features have separate charges.</p><p><strong>Fit among the Whereby embedded alternatives:</strong> Vonage provides more communications depth but exposes more products, options, and legacy OpenTok terminology. Whereby is easier for a small embedded-room surface.</p><h3 id="10-zegocloud-best-for-social-and-gaming-ui-kits">10. ZEGOCLOUD: Best for Social and Gaming UI Kits</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.33.21-PM-4.png" class="kg-image" alt="Top 10 Whereby Embedded Alternatives in 2026: Expert-Tested & Ranked" loading="lazy" width="2926" height="1668"/></figure><p><a href="https://www.zegocloud.com/product/video-call" rel="noreferrer nofollow">ZEGOCLOUD</a> combines RTC SDKs with prebuilt UI kits aimed at social, gaming, live-streaming, and interactive community products.</p><p>Its public catalogue includes numerous UI kits and related real-time services. This can speed up familiar formats such as one-to-one calls, group rooms, live chat, and social audio-video experiences.</p><p><strong>Why it ranks ninth:</strong> ZEGOCLOUD is especially useful when a product resembles an established social or gaming interaction pattern and a matching UI kit reduces design and implementation time.</p><p><strong>Best for:</strong> Social apps, casual gaming, creator products, community rooms, and teams seeking a format-specific starting point.</p><p><strong>Pricing:</strong> The <a href="https://www.zegocloud.com/pricing?index=0" rel="noreferrer nofollow">public calculator</a> lists 10,000 free minutes and video calling from $3.99 per 1,000 participant minutes. Recording, streaming, moderation, and other services are priced separately.</p><p><strong>Fit among the Whereby embedded alternatives:</strong> ZEGOCLOUD offers more format-specific kits, but its documentation spans several product generations and kit types. Confirm the exact SDK and UI kit before estimating migration work.</p><h2 id="whereby-vs-videosdk-direct-comparison">Whereby vs VideoSDK: Direct Comparison</h2><p>Among Whereby embedded alternatives, Whereby favors the shortest route to a browser room, while VideoSDK supports a managed path from prebuilt calls to broader custom clients.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Decision</th>
<th>Whereby Embedded</th>
<th>VideoSDK</th>
<th>Practical choice</th>
</tr>
</thead>
<tbody>
<tr>
<td>Fastest first call</td>
<td>Prebuilt web component with room URL</td>
<td>Prebuilt SDK and sample applications</td>
<td>Whereby for the smallest browser embed</td>
</tr>
<tr>
<td>Custom web UI</td>
<td>Browser SDK and low-level Core SDK</td>
<td>JavaScript and React SDKs plus REST APIs</td>
<td>Test both against your exact UI state model</td>
</tr>
<tr>
<td>Native and specialist clients</td>
<td>iOS SDK in active development; Android uses a WebView integration</td>
<td>Native mobile, Flutter, React Native, Unity, IoT, C++, Python, and web paths</td>
<td>VideoSDK when client expansion is likely</td>
</tr>
<tr>
<td>Infrastructure</td>
<td>Managed</td>
<td>Managed</td>
<td>LiveKit or Jitsi if self-hosting is required</td>
</tr>
<tr>
<td>Public entry price</td>
<td>Free Explore plan; Build at $9.99 monthly plus usage</td>
<td>$20 starting credit; usage-based billing</td>
<td>Compare a complete monthly workload</td>
</tr>
<tr>
<td>Stay or switch</td>
<td>Stay when the prebuilt browser experience and limits fit</td>
<td>Switch when platform breadth or deeper workflow APIs justify migration</td>
<td>Decide through a representative proof of concept</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>VideoSDK is not automatically the right answer. Whereby may deliver the same customer outcome with less application code. LiveKit or Jitsi may be better when media-server ownership is mandatory.</p><h2 id="whereby-embedded-alternative-comparison-table">Whereby Embedded Alternative Comparison Table</h2><p>These whereby embedded alternatives summarize the fastest decision path, but a table cannot replace a proof of concept on your real networks and devices.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th style="text-align:right">Rank</th>
<th>API or SDK</th>
<th>Public starting point</th>
<th>Hosting model</th>
<th>Best for</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">1</td>
<td>VideoSDK</td>
<td>$20 starting credit</td>
<td>Managed</td>
<td>Prebuilt-to-custom growth across many clients</td>
</tr>
<tr>
<td style="text-align:right">2</td>
<td>Daily</td>
<td>10,000 free participant minutes monthly</td>
<td>Managed</td>
<td>Browser-first managed migration</td>
</tr>
<tr>
<td style="text-align:right">3</td>
<td>LiveKit</td>
<td>Free Cloud tier or self-hosting</td>
<td>Managed or self-hosted</td>
<td>Open-source and infrastructure control</td>
</tr>
<tr>
<td style="text-align:right">4</td>
<td>Agora</td>
<td>10,000 free minutes monthly</td>
<td>Managed</td>
<td>Specialist clients and large-scale interactivity</td>
</tr>
<tr>
<td style="text-align:right">5</td>
<td>100ms</td>
<td>10,000 free conferencing minutes</td>
<td>Managed</td>
<td>Role-based classrooms and events</td>
</tr>
<tr>
<td style="text-align:right">6</td>
<td>Dyte</td>
<td>10,000 free minutes</td>
<td>Managed</td>
<td>Component-level UI control</td>
</tr>
<tr>
<td style="text-align:right">7</td>
<td>Zoom Video SDK</td>
<td>10,000 free session minutes monthly</td>
<td>Managed</td>
<td>Enterprise scale and desktop reach</td>
</tr>
<tr>
<td style="text-align:right">8</td>
<td>Twilio Video</td>
<td>Free trial credit; $0.004 per participant minute</td>
<td>Managed</td>
<td>Twilio Voice interoperability and custom rooms</td>
</tr>
<tr>
<td style="text-align:right">9</td>
<td>Vonage Video API</td>
<td>100,000-minute new-customer trial</td>
<td>Managed</td>
<td>Broadcast, SIP, and enterprise communications</td>
</tr>
<tr>
<td style="text-align:right">10</td>
<td>ZEGOCLOUD</td>
<td>10,000 free minutes</td>
<td>Managed</td>
<td>Social, gaming, and format-specific UI kits</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Free allowances are not directly comparable. Some reset monthly, some are introductory credits, and each provider counts recording, streaming, audio, or data transfer differently.</p><h2 id="how-to-migrate-from-whereby-embedded">How to Migrate from Whereby Embedded</h2><p>Migrating between Whereby embedded alternatives is safest when replacing one layer at a time: authentication, rooms, client events, UI, and production operations.</p><ol><li><strong>Inventory the current integration.</strong> List room creation, tokens, webhooks, waiting rooms, recording, transcription, streaming, moderation, analytics, and retention rules.</li><li><strong>Map concepts before code.</strong> Match Whereby rooms, participants, host controls, media events, and recordings to the candidate provider’s session model and permission system.</li><li><strong>Build one representative call.</strong> Include the hardest layout, maximum active publishers, screen sharing, mobile backgrounding, device switching, reconnection, and an enterprise firewall.</li><li><strong>Model total monthly cost.</strong> Use realistic participant minutes, resolution, recording, transcription, storage, egress, support, compliance, and regional requirements.</li><li><strong>Run a staged cutover.</strong> Route a small cohort to the new provider, measure join success and call quality, compare operational alerts, then expand with a rollback path.</li></ol><p>A drop-in replacement is unlikely. Even when two products provide similar rooms, their token claims, event names, webhook ordering, recording assets, and UI state models differ.</p><h2 id="production-checks-before-you-switch">Production Checks Before You Switch</h2><p>Production evaluation of Whereby embedded alternatives must cover network behavior, security, operational recovery, and add-on costs alongside the client SDK.</p><p><strong>Secure token issuance:</strong> Generate credentials on a server, use short expiries, authorize the room and role, rotate keys, and avoid placing API secrets in application bundles.</p><p><strong>HTTPS and permissions:</strong> Camera, microphone, and screen-capture flows require secure origins and careful browser permission handling. Test denial, revocation, device changes, and interrupted prompts.</p><p><strong>TURN and firewalls:</strong> Test restrictive corporate, hospital, and school networks. Managed vendors handle the media edge, but enterprise proxy or firewall services may have separate fees.</p><p><strong>Reconnect and failure states:</strong> Measure time to join, reconnect success, track recovery, device switching, background behavior, duplicate webhooks, and out-of-order events.</p><p><strong>Recording and transcription:</strong> Confirm layout, start and stop behavior, output formats, storage location, retention, access controls, redaction, and the price unit for each add-on.</p><p><strong>Compliance and data boundaries:</strong> Validate contractual terms, region availability, encryption, retention controls, audit requirements, and any BAA or regulated-industry add-on before procurement.</p><h2 id="what-is-the-best-whereby-embedded-alternative">What Is the Best Whereby Embedded Alternative?</h2><p>Among these Whereby embedded alternatives, VideoSDK ranks first for a managed video API that must grow from a fast prebuilt launch into custom, multi-client applications.</p><p>Choose a different provider when another constraint dominates:</p><ul><li>Choose <strong>Daily</strong> for the closest browser-first managed experience.</li><li>Choose <strong>LiveKit</strong> for an open-source server and optional self-hosting.</li><li>Choose <strong>Agora</strong> for specialist clients and large interactive applications.</li><li>Choose <strong>100ms</strong> for structured roles in classrooms or events.</li><li>Choose <strong>Dyte</strong> for composable prebuilt interface components.</li><li>Choose <strong>Zoom Video SDK</strong> for enterprise scale and desktop reach.</li><li>Choose <strong>Twilio Video</strong> for Twilio Voice interoperability and familiar developer tooling.</li><li>Choose <strong>Vonage</strong> for video combined with SIP or broadcasting.</li><li>Choose <strong>ZEGOCLOUD</strong> for social or gaming UI kits.</li></ul><p>The correct decision is the provider that passes your proof of concept at an acceptable total cost, not the one with the longest feature list.</p><h2 id="glossary">Glossary</h2><blockquote><strong>Video calling API:</strong> Server endpoints and real-time services used to create rooms, authorize users, manage sessions, and trigger features such as recording or streaming.</blockquote><blockquote><strong>Video SDK:</strong> Client libraries that manage devices, media tracks, peer connections, participant state, and application events on web, mobile, desktop, or specialist platforms.</blockquote><blockquote><strong>Participant minute:</strong> One participant connected for one minute. A 30-minute call with four connected people usually creates 120 participant minutes.</blockquote><blockquote><strong>SFU:</strong> A Selective Forwarding Unit receives media streams and forwards selected streams to participants without mixing every stream into one composite.</blockquote><blockquote><strong>TURN:</strong> A relay service used when direct WebRTC connectivity fails because of firewalls, NAT behavior, or restrictive network policies.</blockquote><blockquote><strong>Prebuilt:</strong> A ready-made call interface that reduces launch time but usually provides less product-specific control than a headless SDK.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><p>This whereby embedded alternative ranking narrows a crowded search to programmable video products that can genuinely replace an embedded Whereby workflow.</p><ul><li>VideoSDK ranks first for a managed prebuilt-to-custom path across a wide public SDK menu.</li><li>Daily is the closest browser-first managed alternative.</li><li>LiveKit leads when open-source server control or self-hosting is required.</li><li>Whereby remains a good choice when its prebuilt experience, limits, and managed model already fit.</li><li>Headline participant-minute pricing is incomplete without recording, transcription, storage, support, compliance, and network add-ons.</li><li>A representative proof of concept is more reliable than a generic feature matrix.</li></ul><h2 id="conclusion">Conclusion</h2><p>The best Whereby embedded alternatives are not meeting apps. They are programmable video platforms that can reproduce your room, identity, media, and operational workflows inside the product.</p><p>Start by testing <a href="https://app.videosdk.live/login">VideoSDK with its $20 credit</a>, then compare the same workload with Daily and LiveKit. Keep Whereby in the test if its simpler prebuilt model still meets the requirement. Which constraint matters most for your team: browser speed, client reach, self-hosting, roles, or enterprise scale?</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><p>These answers address the main evaluation questions developers ask when comparing Whereby embedded alternatives for an embedded video product.</p><h3 id="what-is-whereby-embedded">What is Whereby Embedded?</h3><p>Whereby Embedded is a managed video calling platform for adding real-time rooms to web and mobile products. It offers a prebuilt web component, Browser SDK, Core SDK, mobile integration paths, room APIs, recording, transcription, and related services.</p><h3 id="is-whereby-embedded-free">Is Whereby Embedded free?</h3><p>Whereby Embedded has an Explore plan costing $0 and including 2,000 participant minutes per month. The Build plan costs $9.99 monthly, includes 2,000 participant minutes, and charges $0.004 for each additional participant minute on the public rate card checked 28 July 2026.</p><h3 id="does-whereby-have-an-api">Does Whereby have an API?</h3><p>Yes. Whereby provides REST APIs for rooms, meetings, recordings, transcriptions, and related workflows, plus a Browser SDK and Core SDK for client-side control. Its fastest integration remains the prebuilt embedded experience.</p><h3 id="how-many-participants-does-whereby-embedded-support">How many participants does Whereby Embedded support?</h3><p>Whereby Embedded supports up to 200 participants in a room, with up to 24 active video tiles. Products needing more visible publishers or larger interactive sessions should test Zoom Video SDK, Agora, Vonage, or another high-scale option.</p><h3 id="what-is-the-best-overall-whereby-embedded-alternative">What is the best overall Whereby Embedded alternative?</h3><p>VideoSDK is the best overall Whereby embedded alternative in this ranking because it combines a prebuilt launch path, custom RTC SDKs, REST APIs, and broad client coverage. Daily is better for the closest browser-first managed migration, while LiveKit is better for self-hosting.</p><h3 id="what-is-the-best-open-source-whereby-embedded-alternative">What is the best open-source Whereby Embedded alternative?</h3><p>LiveKit is the strongest open-source Whereby embedded alternatives for teams wanting a modern SFU with managed Cloud and self-hosted deployment paths. Jitsi is also credible when infrastructure ownership and a conferencing-oriented open-source stack are the priorities.</p><h3 id="is-there-a-drop-in-replacement-for-whereby-embedded">Is there a drop-in replacement for Whereby Embedded?</h3><p>No video API should be treated as a guaranteed drop-in replacement for Whereby Embedded. Room creation, token claims, SDK events, webhooks, recording outputs, UI state, and usage billing differ, so every migration needs a mapping exercise and proof of concept.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 EnableX Alternatives in 2026: Expert Tested & Ranked]]></title><description><![CDATA[Compare the top EnableX alternatives for embedded video calling. See verified pricing, SDK coverage, migration guidance, trade-offs, and conditional recommendations.]]></description><link>https://www.videosdk.live/blog/enablex-alternatives</link><guid isPermaLink="false">6a688af0b3240feb748c8e44</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 28 Jul 2026 12:30:09 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/07/EnableX-Alternatives-2026-thumbnail.png" medium="image"/><content:encoded><![CDATA[<blockquote>Use VideoSDK when you need broad client SDK coverage, prebuilt and custom UI paths, and one platform for video calls and interactive live streaming. Use LiveKit when self-hosting and direct infrastructure control are mandatory. Use Daily when browser-first embedding is the priority. Keep EnableX when its on-premise model or an existing integration removes more risk than switching.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/EnableX-Alternatives-2026-thumbnail.png" alt="Top 10 EnableX Alternatives in 2026: Expert Tested & Ranked"/><p><em>Reviewed July 28, 2026. Pricing and product details can change.</em></p><p>EnableX alternatives are programmable video calling APIs and SDKs that can replace EnableX rooms, client libraries, media infrastructure, recording, and operational tooling.</p><p>The strongest EnableX alternatives solve different constraints. VideoSDK balances cross-platform delivery, Agora leads broad engagement, and Daily suits browser-first implementation.</p><p>This ranking covers video calling APIs only. It excludes ordinary meeting applications and broader CPaaS products that do not provide an embeddable, programmable video layer.</p><h2 id="what-is-enablex">What Is EnableX?</h2><p><a href="https://www.enablex.io/" rel="noreferrer nofollow">EnableX</a> is a communications platform with a programmable Video API for creating rooms, issuing join tokens, managing sessions, and retrieving post-call data.</p><p>Its <a href="https://developer.enablex.io/video/api-reference.html" rel="noreferrer nofollow">Video API</a> uses server-side REST calls for room provisioning and token creation. Client SDKs then connect users to the media session.</p><p>EnableX starts at <a href="https://www.enablex.io/cpaas/pricing/video-call-api-pricing" rel="noreferrer nofollow">$0.004 per participant minute</a> for pay-as-you-go video calls. Its published price includes several features that competitors may bill separately.</p><p>The platform remains a credible choice for regulated or data-sensitive deployments. EnableX documents public cloud, private cloud, and on-premise options for its <a href="https://www.enablex.io/cpaas/video-call-api" rel="noreferrer nofollow">video calling product</a>.</p><p>Developers usually compare EnableX alternatives when they need different client SDK coverage, a faster prebuilt path, open-source infrastructure, clearer usage controls, or another vendor ecosystem.</p><p>In this review, EnableX alternatives must expose programmable video infrastructure. VideoSDK qualifies through ten documented client, server, and API paths plus prebuilt and custom interfaces.</p><p>The right replacement should solve a measurable constraint. A stable EnableX implementation should not be migrated merely because another platform ranks higher in a general comparison.</p><h2 id="how-we-ranked-enablex-alternatives">How We Ranked EnableX Alternatives</h2><p>For this article, "expert tested" means we examined documented setup paths and public product evidence. It does not mean we benchmarked production media performance across every network, device, and region.</p><p>We reviewed official quickstarts, client and server SDK coverage, authentication models, prebuilt UI options, recording controls, operational tooling, deployment choices, and public pricing.</p><p>Each provider received the same weighted rubric. Scores are editorial indicators out of 100, not laboratory measurements or guarantees for a particular production workload.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Evaluation criterion</th>
<th style="text-align:right">Weight</th>
<th>What we checked</th>
</tr>
</thead>
<tbody>
<tr>
<td>Video API and media depth</td>
<td style="text-align:right">25%</td>
<td>Rooms, tracks, recording, streaming, moderation, and media controls</td>
</tr>
<tr>
<td>Client SDK coverage</td>
<td style="text-align:right">20%</td>
<td>Web, native mobile, cross-platform, desktop, game, and backend support</td>
</tr>
<tr>
<td>Developer implementation path</td>
<td style="text-align:right">20%</td>
<td>Quickstarts, prebuilt UI, authentication, samples, and API clarity</td>
</tr>
<tr>
<td>Pricing clarity and value</td>
<td style="text-align:right">15%</td>
<td>Free allowance, participant pricing, metering, and add-on transparency</td>
</tr>
<tr>
<td>Production controls</td>
<td style="text-align:right">15%</td>
<td>Security, diagnostics, webhooks, analytics, and regional controls</td>
</tr>
<tr>
<td>Deployment choice</td>
<td style="text-align:right">5%</td>
<td>Managed cloud, self-hosting, hybrid, and on-premise availability</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The evaluation favours products that reduce implementation and operational risk across several platforms. A specialist can still be the better choice for one non-negotiable requirement.</p><h2 id="enablex-alternatives-comparison-table">EnableX Alternatives Comparison Table</h2><p>VideoSDK ranks first overall under the disclosed rubric, while LiveKit, Daily, Agora, and Whereby Embedded lead specific architectural, ecosystem, or implementation scenarios.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th style="text-align:right">Rank</th>
<th>Platform</th>
<th style="text-align:right">Score</th>
<th>Best for</th>
<th>Public pricing snapshot</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">1</td>
<td>VideoSDK</td>
<td style="text-align:right">92</td>
<td>Cross-platform custom video, prebuilt UI, and interactive live streaming</td>
<td>Pay as you go, with a one-time $20 starting balance</td>
</tr>
<tr>
<td style="text-align:right">2</td>
<td>Agora</td>
<td style="text-align:right">90</td>
<td>Broad global real-time engagement products</td>
<td>Video starts at $3.99 per 1,000 minutes</td>
</tr>
<tr>
<td style="text-align:right">3</td>
<td>Daily</td>
<td style="text-align:right">88</td>
<td>Browser-first calls and fast embedding</td>
<td>10,000 free minutes monthly, then $0.004 per participant minute</td>
</tr>
<tr>
<td style="text-align:right">4</td>
<td>LiveKit</td>
<td style="text-align:right">87</td>
<td>Open-source infrastructure and self-hosting</td>
<td>Cloud pricing meters plan, connection, bandwidth, and transcoding usage</td>
</tr>
<tr>
<td style="text-align:right">5</td>
<td>100ms</td>
<td style="text-align:right">86</td>
<td>Role-based classrooms, communities, and events</td>
<td>10,000 free conferencing minutes, then $0.004 per participant minute</td>
</tr>
<tr>
<td style="text-align:right">6</td>
<td>Stream Video</td>
<td style="text-align:right">84</td>
<td>Polished components and products already using Stream</td>
<td>$100 monthly credit; HD shown at $1.50 per 1,000 participant minutes</td>
</tr>
<tr>
<td style="text-align:right">7</td>
<td>Zoom Video SDK</td>
<td style="text-align:right">83</td>
<td>Custom experiences built on Zoom media technology</td>
<td>Credit-based plans; confirm current account pricing with Zoom</td>
</tr>
<tr>
<td style="text-align:right">8</td>
<td>Twilio Video</td>
<td style="text-align:right">82</td>
<td>Existing Twilio customers and established video workflows</td>
<td>$0.004 per participant minute, with recording and composition charged separately</td>
</tr>
<tr>
<td style="text-align:right">9</td>
<td>Vonage Video API</td>
<td style="text-align:right">81</td>
<td>Mature video, SIP, broadcast, and observability workflows</td>
<td>$0.00410 per participant minute, with separate advanced-feature charges</td>
</tr>
<tr>
<td style="text-align:right">10</td>
<td>Whereby Embedded</td>
<td style="text-align:right">79</td>
<td>Low-code web embedding and smaller product teams</td>
<td>$9.99 monthly, including 2,000 minutes, then $0.004 per participant minute</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>These prices are public US list prices or offer structures viewed on July 28, 2026. Taxes, contracts, recording, streaming, storage, and support can change total cost.</p><h2 id="top-10-enablex-alternatives-for-video-calling">Top 10 EnableX Alternatives for Video Calling</h2><p>These ten products support programmable video experiences inside an application. Each exposes APIs or SDKs instead of merely redirecting users to a separate meeting product.</p><h3 id="1-videosdk-best-overall-alternative">1. VideoSDK: Best Overall Alternative</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.29.39-PM-7.png" class="kg-image" alt="Top 10 EnableX Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://docs.videosdk.live/">VideoSDK</a> ranks first because its documented SDK matrix covers JavaScript, React, React Native, Android, iOS, Flutter, Unity, Python, C++, and REST APIs.</p><p>Teams can start with the <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Prebuilt UI Kit</a>, then move to custom components without replacing the underlying provider or room model.</p><p>The platform also documents recording, transcription, SIP, geo-fencing, end-to-end encryption, and interactive live streaming alongside its core video calling SDKs.</p><p>VideoSDK is best for products serving several client platforms or combining normal video calls with larger interactive sessions. Its managed infrastructure is not a self-hosted <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu" rel="noreferrer">SFU</a>.</p><p>Current <a href="https://www.videosdk.live/pricing">VideoSDK pricing</a> is pay as you go, and new accounts receive a one-time $20 starting balance rather than recurring free minutes.</p><p>Compared with EnableX, VideoSDK provides a broader documented client matrix and a direct prebuilt-to-custom path. EnableX remains stronger when on-premise deployment is mandatory.</p><p><strong>Verdict:</strong> Choose VideoSDK for the strongest all-round balance of platform coverage, implementation flexibility, broad coverage and adjacent real-time video capabilities in this comparison.</p><h3 id="2-agora-best-for-global-engagement">2. Agora: Best for Global Engagement</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.26-PM-7.png" class="kg-image" alt="Top 10 EnableX Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/en/products/video-call/" rel="noreferrer nofollow">Agora</a> Video Calling is designed for real-time engagement products across video, voice, live streaming, chat, signalling, and adjacent media services.</p><p>Agora ranks second for its mature network, wide product surface, extensive media controls, and suitability for social, gaming, education, and high-concurrency engagement patterns.</p><p>Its breadth is useful when a roadmap may expand beyond ordinary calls. That same breadth can increase evaluation work across separate products, add-ons, and pricing dimensions.</p><p>Agora's public pricing lists video calling from $3.99 per 1,000 minutes, with the  <a href="https://www.agora.io/en/pricing/video-calling/" rel="noreferrer nofollow">10,000 free minutes monthly</a>.</p><p>Compared with EnableX, Agora offers a broader real-time engagement ecosystem. Teams should still test target countries, device classes, support terms, and actual publisher or subscriber patterns.</p><p><strong>Verdict:</strong> Choose Agora when global engagement scale and a broad RTC portfolio matter more than a compact product surface or on-premise deployment.</p><h3 id="3-daily-best-for-browser-first-embedding">3. Daily: Best for Browser-First Embedding</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.02-PM-4.png" class="kg-image" alt="Top 10 EnableX Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="2924" height="1652"/></figure><p><a href="https://www.daily.co/products/video-sdk/" rel="noreferrer nofollow">Daily</a> provides a browser-first route through Daily Prebuilt, call objects, client SDKs, and lower-level APIs for teams building custom WebRTC experiences.</p><p>Daily ranks third because its prebuilt component, web documentation, and transparent participant-minute pricing reduce early implementation and cost-modelling work for browser applications.</p><p><a href="https://www.daily.co/pricing/video-sdk/" rel="noreferrer nofollow">Daily includes</a> 10,000 free participant minutes each month and then charges $0.004 per participant minute before applying automatic volume discounts at higher usage.</p><p>Daily also explains that cloud recording is billed by recorded wall-clock minute, not multiplied by participants. That distinction improves production cost estimates.</p><p>Compared with EnableX, Daily offers a particularly clear browser embedding path. Teams with broad native, game-engine, self-hosted, or on-premise requirements should compare other finalists carefully.</p><p><strong>Verdict:</strong> Choose Daily when a browser-based proof of concept, telehealth workflow, or a gradual prebuilt-to-custom web migration is the main requirement.</p><h3 id="4-livekit-best-open-source-alternative">4. LiveKit: Best Open-Source Alternative</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.40-PM-7.png" class="kg-image" alt="Top 10 EnableX Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="2920" height="1670"/></figure><p><a href="https://docs.livekit.io/intro/about/" rel="noreferrer nofollow">LiveKit</a> combines an open-source WebRTC stack with managed cloud services, giving infrastructure teams more control than most fully managed video APIs.</p><p>LiveKit ranks fourth because teams can inspect the stack, self-host core infrastructure, or use LiveKit Cloud while retaining the same room and track concepts.</p><p>Its SDK ecosystem covers web, native mobile, cross-platform frameworks, Unity, C++, and server environments. The platform also extends into ingress, egress, SIP, and agents.</p><p>LiveKit Cloud uses several meters. Its <a href="https://livekit.io/field-guides/guide/estimating-pricing-video-conference-livestream" rel="noreferrer nofollow">pricing documentation</a> separates connection minutes, outbound bandwidth, and transcoding, so accurate estimates require scenario-based modelling.</p><p>Compared with EnableX, LiveKit offers a clearer open-source and self-hosted path. EnableX may require less infrastructure ownership when its vendor-operated private or on-premise model fits.</p><p><strong>Verdict:</strong> Choose LiveKit when source access, self-hosting, infrastructure control, or deep media-server extensibility outweighs the convenience of a simpler managed service.</p><h3 id="5-100ms-best-for-role-based-experiences">5. 100ms: Best for Role-Based Experiences</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.31.12-PM-8.png" class="kg-image" alt="Top 10 EnableX Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="2910" height="1656"/></figure><p><a href="https://www.100ms.live/docs/get-started/v2/get-started/overview" rel="noreferrer nofollow">100ms</a> structures video experiences around rooms, roles, templates, publishing permissions, and subscription permissions. These concepts fit classrooms, interactive events, and communities with distinct participant types.</p><p>It ranks fifth because the role model, prebuilt option, recording, streaming, and client SDKs reduce repeated access-control work in host, speaker, moderator, and audience interfaces.</p><p>Public pricing of <a href="https://www.100ms.live/pricing" rel="noreferrer nofollow">100ms includes</a> 10,000 conferencing minutes each month, then charges $0.004 per participant minute after the included allowance is consumed.</p><p>Recording, transcription, and external streaming use separate allowances and rates. Teams should model those services before treating the base conferencing rate as total cost.</p><p>Compared with EnableX, 100ms provides an opinionated role and template system that may accelerate structured experiences. That model also introduces platform-specific configuration concepts.</p><p><strong>Verdict:</strong> Choose 100ms when predefined participant roles and room templates closely match your product, especially for classrooms, communities, or structured interactive events.</p><h3 id="6-stream-video-best-component-libraries">6. Stream Video: Best Component Libraries</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-28-at-4.33.18-PM.png" class="kg-image" alt="Top 10 EnableX Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="2890" height="1540"/></figure><p><a href="https://getstream.io/video/docs/" rel="noreferrer nofollow">Stream Video</a> offers SDKs and UI component libraries for web, React, iOS, Android, React Native, Flutter, and Unity product teams.</p><p>Stream ranks sixth because its component-led developer experience can reduce interface work, especially when an application already uses Stream Chat or activity feeds.</p><p>The <a href="https://getstream.io/video/pricing/" rel="noreferrer nofollow">Stream Video pricing page</a> gives a $100 monthly credit. Its calculator lists HD video at $1.50 per 1,000 participant minutes.</p><p>Stream prices video by the highest quality a participant publishes or receives. Recording, transcription, <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a>, noise cancellation, and higher resolutions can change total cost.</p><p>Compared with EnableX, Stream provides a stronger component ecosystem for teams already using Stream. EnableX offers more deployment choice, including on-premise configurations.</p><p><strong>Verdict:</strong> Choose Stream when polished client components and an existing Stream stack reduce more development work than a lower headline participant rate.</p><h3 id="7-zoom-video-sdk-best-for-zoom-media">7. Zoom Video SDK: Best for Zoom Media</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.32.46-PM-6.png" class="kg-image" alt="Top 10 EnableX Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="2920" height="1646"/></figure><p><a href="https://developers.zoom.us/docs/video-sdk/" rel="noreferrer nofollow">Zoom Video SDK</a> lets developers use Zoom's media technology while building a custom application interface, separate from the ordinary Zoom Meetings experience.</p><p>Zoom ranks seventh for its platform matrix, media stack, raw media options, webhooks, and support across Android, Flutter, iOS, Linux, macOS, React Native, Web, Windows, and Unity.</p><p>The SDK suits teams that already trust Zoom's media behaviour or need broad desktop and mobile coverage. Zoom also enforces a quarterly minimum SDK version policy.</p><p><a href="https://zoom.us/pricing?_ics=1785238426943&amp;irclickid=~59c-eiprxvuklorxvwmukbc58ZXYV20PSXQSUJKJDzvmge91WUQH&amp;_gl=1*16p99m7*_gcl_au*OTM5ODY4NTY4LjE3ODQyNzM1Mzk." rel="noreferrer nofollow">Public pricing</a> is credit-based and can vary by plan and add-on. Confirm the current Video SDK rate and included credits inside Zoom's official sales flow.</p><p>Compared with EnableX, Zoom provides a familiar global media platform and wide SDK coverage. EnableX offers clearer on-premise and hybrid positioning for regulated deployments.</p><p><strong>Verdict:</strong> Choose Zoom Video SDK for custom products designed specifically around Zoom media, not for recreating Zoom Meetings without product or lifecycle changes.</p><h3 id="8-twilio-video-best-for-twilio-customers">8. Twilio Video: Best for Twilio Customers</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.53.31-PM-3.png" class="kg-image" alt="Top 10 EnableX Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="2910" height="1638"/></figure><p><a href="https://www.twilio.com/docs/video" rel="noreferrer nofollow">Twilio Video</a> uses rooms, participants, and tracks, with supported client SDKs for web, iOS, and Android applications building embedded video experiences.</p><p>Twilio ranks eighth because its established developer tooling, recordings, compositions, quality controls, and integration with other Twilio channels remain useful for existing customers.</p><p>Its <a href="https://www.twilio.com/en-us/video/pricing" rel="noreferrer nofollow">video pricing</a> starts at $0.004 per participant minute. Participant recording, transcription, composition, and storage are metered separately at their published rates.</p><p>Compared with EnableX, Twilio offers strong ecosystem integration but a narrower public client SDK list. EnableX provides more deployment choices for private infrastructure.</p><p><strong>Verdict:</strong> Choose Twilio when existing contracts, identity, messaging, voice, and operational tooling outweigh the need for broader cross-platform client coverage.</p><h3 id="9-vonage-video-api-best-for-mature-workflows">9. Vonage Video API: Best for Mature Workflows</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.32.16-PM-4.png" class="kg-image" alt="Top 10 EnableX Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="2922" height="1652"/></figure><p><a href="https://developer.vonage.com/en/video/technical-details" rel="noreferrer nofollow">Vonage Video API</a>, formerly OpenTok, provides sessions, client and server SDKs, REST APIs, archiving, broadcasting, SIP interconnect, live captions, and diagnostic tooling.</p><p>It ranks ninth because it remains a mature programmable video platform with web, iOS, Android, React Native, Windows, and Linux implementation paths.</p><p>Vonage also documents pre-call testing, Inspector tools, publisher controls, broadcast destinations, Experience Composer, SIP interconnect, and media access for external processing.</p><p>Public Vonage Video pricing starts at <a href="https://www.vonage.com/communications-apis/video/pricing/" rel="noreferrer nofollow">$0.00410</a> per participant minute. Recording, composition, transcription, and other advanced services have separate rates.</p><p>Compared with EnableX, Vonage offers mature SIP, broadcast, observability, and communications workflows. EnableX can be preferable when on-premise deployment is the deciding requirement.</p><p><strong>Verdict:</strong> Choose Vonage when mature video operations, SIP, broadcasting, and diagnostics justify modelling each paid add-on around the final architecture.</p><h3 id="10-whereby-embedded-best-low-code-option">10. Whereby Embedded: Best Low-Code Option</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.34.01-PM-2.png" class="kg-image" alt="Top 10 EnableX Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="2890" height="1624"/></figure><p><a href="https://whereby.com/" rel="noreferrer nofollow">Whereby Embedded</a> is the programmable product in this comparison, not the standalone Whereby Meetings service used for ordinary meeting links.</p><p>It ranks tenth because its web component and prebuilt interface create a short route to embedded browser calls. The browser and core SDKs support deeper customisation.</p><p>Whereby also documents Android, iOS, and a React Native path based on its web component. The broader client matrix remains smaller than several SDK-first vendors.</p><p>Its embedded <a href="https://whereby.com/information/embedded/pricing" rel="noreferrer nofollow">current public</a> pricing offers 2,000 test minutes, then a $9.99 Build plan with 2,000 included minutes and $0.004 overage.</p><p>Compared with EnableX, Whereby Embedded is simpler for common web calls. EnableX provides a wider communications portfolio and more enterprise deployment flexibility.</p><p><strong>Verdict:</strong> Choose Whereby Embedded when browser embedding speed and a prebuilt call experience matter more than deep native, self-hosted, or custom media control.</p><h2 id="what-is-the-best-enablex-alternative">What Is the Best EnableX Alternative?</h2><p>VideoSDK is the best overall EnableX alternative in this review for teams that need several client platforms and both prebuilt and custom implementation paths.</p><p>The answer changes when one requirement becomes non-negotiable:</p><ul><li>Choose LiveKit for open-source infrastructure and self-hosting.</li><li>Choose Daily or Whereby Embedded for the shortest browser-first path.</li><li>Choose Agora for broad global real-time engagement.</li><li>Choose 100ms for strongly role-based classrooms and communities.</li><li>Choose Stream, Zoom, Twilio, or Vonage when an existing vendor ecosystem determines the architecture.</li><li>Keep EnableX when on-premise deployment, current compliance controls, or migration cost outweighs the expected improvement.</li></ul><p>VideoSDK leads the weighted general-purpose score among these EnableX alternatives. Specialist workloads can produce another winner because deployment, region, interface, and operational requirements carry different risks.</p><h2 id="how-to-migrate-from-enablex">How to Migrate From EnableX</h2><p>A controlled migration maps platform concepts before replacing SDK methods, which protects application behaviour and operational evidence during the transition.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Migration layer</th>
<th>What to map</th>
<th>Validation question</th>
</tr>
</thead>
<tbody>
<tr>
<td>Authentication</td>
<td>App credentials, server tokens, roles, and token expiry</td>
<td>Can clients join without receiving a server secret?</td>
</tr>
<tr>
<td>Room lifecycle</td>
<td>Create, join, leave, end, and reconnect behaviour</td>
<td>Who owns room creation and termination?</td>
</tr>
<tr>
<td>Media model</td>
<td>Local tracks, remote tracks, devices, and screen sharing</td>
<td>Do mute and device-switch events match current UI state?</td>
</tr>
<tr>
<td>Participant events</td>
<td>Join, leave, role change, and network quality</td>
<td>Can existing analytics keep stable event meanings?</td>
</tr>
<tr>
<td>Server features</td>
<td>Recording, webhooks, SIP, streaming, and transcription</td>
<td>Which capabilities require separate services or prices?</td>
</tr>
<tr>
<td>Operations</td>
<td>Logs, quality metrics, regions, retention, and support</td>
<td>Can support teams investigate a failed call quickly?</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Run EnableX and the finalists behind a feature flag. Start with two-person calls, then test reconnection, device changes, screen sharing, recording, mobile backgrounding, and poor networks.</p><p>A migration succeeds when user-visible behaviour and operational evidence remain stable. Merely connecting two browsers does not prove production readiness or cost parity.</p><h2 id="how-to-choose-among-enablex-alternatives">How to Choose Among EnableX Alternatives</h2><p>The right EnableX alternative removes the most engineering and operational risk from your specific call pattern, not from an abstract feature checklist.</p><p>Use this decision order:</p><ol><li>Define maximum active speakers, displayed videos, viewers, and total participants.</li><li>List every required client platform, including future mobile, desktop, or game-engine plans.</li><li>Decide whether prebuilt UI, custom UI, or a staged path is required.</li><li>Identify hard requirements such as self-hosting, data residency, SIP, E2EE, or on-premise deployment.</li><li>Model participant minutes alongside recording, streaming, storage, transcription, bandwidth, support, and committed volume.</li><li>Build the same narrow proof of concept with two finalists.</li><li>Test target regions, devices, network conditions, observability, and support response.</li></ol><p>For example, a telehealth product should test consent, waiting rooms, recording policy, low-bandwidth behaviour, device permissions, and investigation workflows before selecting a provider.</p><h2 id="testing-limits-and-pricing-caveats">Testing Limits and Pricing Caveats</h2><p>Official documentation establishes supported paths and public prices, but it cannot reproduce each application's users, networks, devices, compliance obligations, or support experience.</p><p>This review did not run authenticated production calls, regional latency measurements, packet-loss simulations, support tickets, SLA audits, or large-room load tests across all ten vendors.</p><p>Before publishing a procurement decision, recheck:</p><ul><li>Participant-minute rates, free allowances, credits, and volume tiers.</li><li>Recording, transcription, streaming, storage, bandwidth, and support charges.</li><li>Supported SDK versions, operating-system minimums, and feature parity.</li><li>Maximum participants, active publishers, displayed videos, and concurrent rooms.</li><li>Regional hosting, data retention, compliance eligibility, and encryption details.</li><li>Service-level commitments, incident response, and enterprise support terms.</li></ul><p>Treat this ranking as a transparent shortlist rather than a substitute for procurement. A production-representative proof of concept should determine the final selection.</p><h2 id="video-calling-api-glossary">Video Calling API Glossary</h2><p>These definitions clarify how EnableX alternatives describe rooms, media, participant pricing, and infrastructure across SDKs that use different product terminology.</p><blockquote><strong>Participant minute:</strong> One connected participant for one minute. A ten-person call lasting thirty minutes usually creates 300 participant minutes.</blockquote><blockquote><strong>Room:</strong> A logical real-time session that participants join to publish and receive audio, video, screen sharing, messages, and other event data.</blockquote><blockquote><strong>SFU:</strong> A selective forwarding unit receives participant media and forwards selected streams without mixing every stream into a single composite video.</blockquote><blockquote><strong>Prebuilt UI:</strong> A vendor-supplied video call interface that can be embedded quickly, then configured or replaced when deeper product-specific control becomes necessary.</blockquote><blockquote><strong>Client SDK:</strong> A platform library that manages devices, media tracks, call state, participant events, and communication with a vendor's real-time infrastructure.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><p>The best EnableX alternative depends on the workload, deployment model, client matrix, and operational constraints rather than the longest published feature list.</p><ul><li>VideoSDK ranks first overall for its documented cross-platform coverage, prebuilt and custom paths, and combined video calling and interactive live streaming surface.</li><li>Agora is strongest for a broad real-time engagement ecosystem, while Daily offers a particularly clear browser-first implementation and pricing model.</li><li>LiveKit is the clearest specialist for open-source infrastructure and self-hosting, while Whereby Embedded provides the simplest low-code web route.</li><li>EnableX remains valid when its on-premise deployment, included features, or existing integration solves requirements that another provider would reintroduce.</li><li>A two-provider proof of concept is more valuable than treating small editorial score differences as measured call-quality performance.</li></ul><h2 id="conclusion">Conclusion</h2><p>Among EnableX alternatives, VideoSDK leads this review for broad client coverage and flexible UI paths, but it is not correct for every architecture.</p><p>Shortlist two providers, model the complete bill, and build the same production-shaped call on both. Start with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React quickstart</a>, explore its <a href="https://docs.videosdk.live/code-sample">code samples</a>, or claim the <a href="https://app.videosdk.live/login">$20 starting balance</a>.</p><p>The final choice depends on which requirement changes your ranking most: deployment control, client coverage, browser speed, regional performance, or complete production cost.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><p>These answers address common developer questions about selecting, pricing, evaluating, and migrating to EnableX alternatives for programmable video calling inside an application.</p><h3 id="what-is-the-best-enablex-alternative-1">What is the best EnableX alternative?</h3><p>VideoSDK leads the EnableX alternatives in this comparison because it balances client SDK breadth, prebuilt UI, custom UI, calling features, and interactive live streaming.</p><p>LiveKit is better when self-hosting is mandatory, while Daily is stronger when a fast browser-first implementation and transparent participant pricing matter most.</p><h3 id="is-videosdk-a-good-enablex-alternative">Is VideoSDK a good EnableX alternative?</h3><p>Yes, VideoSDK is a strong EnableX alternative for teams supporting web, native mobile, cross-platform frameworks, Unity, or several application surfaces.</p><p>Teams should still compare target regions, support terms, feature parity, and total usage costs through a production-shaped proof of concept.</p><h3 id="which-enablex-alternative-supports-self-hosting">Which EnableX alternative supports self-hosting?</h3><p>LiveKit is the clearest self-hosted option in this list because its media server and SDK ecosystem are open source and documented for independent deployment.</p><p>EnableX also promotes on-premise deployments, while VideoSDK, Daily, Agora, Twilio, and Whereby are primarily managed cloud services for their core video products.</p><h3 id="which-alternative-has-a-prebuilt-video-call-ui">Which alternative has a prebuilt video call UI?</h3><p>VideoSDK, Daily, 100ms, Stream, Zoom, and Whereby Embedded provide prebuilt, toolkit, or drop-in UI paths, but their customisation depth differs.</p><p>Test branding, layout, accessibility, moderation, mobile behaviour, and the path from prebuilt components to a fully custom interface before committing.</p><h3 id="how-much-do-video-calling-apis-cost">How much do video calling APIs cost?</h3><p>Several managed video APIs begin near $0.004 per participant minute, but that headline rate rarely represents the complete production bill for a deployed application.</p><p>Recording, transcription, streaming, storage, bandwidth, support, higher resolution, data residency, and committed volume can materially change the effective cost per successful call.</p><h3 id="can-i-migrate-without-rebuilding-my-interface">Can I migrate without rebuilding my interface?</h3><p>Yes, a compatibility layer can preserve product-level room, participant, media, and event models while vendor-specific SDK adapters and infrastructure change underneath the interface.</p><p>Prebuilt interfaces usually require more visible UI change than custom applications that already isolate SDK methods behind internal services or hooks.</p><h3 id="should-an-existing-enablex-customer-migrate">Should an existing EnableX customer migrate?</h3><p>An existing EnableX customer should migrate only when another platform solves a measurable problem such as missing client coverage, operational visibility, cost, or deployment control.</p><p>Stable EnableX applications may gain more from optimisation than migration, especially when on-premise infrastructure or regulated workflows already meet product requirements.</p><h3 id="why-is-videosdk-ranked-above-agora-and-daily">Why is VideoSDK ranked above Agora and Daily?</h3><p>VideoSDK ranks above Agora and Daily in this rubric because client SDK coverage, prebuilt-to-custom progression, and combined calling plus interactive streaming receive substantial weight.</p><p>Agora can be better for broad engagement scale, while Daily can be better for browser-first products. The ranking changes when those criteria receive greater weight.</p><h2 id="further-readings">Further Readings</h2><ul><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React video calling quickstart</a></li><li><a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">VideoSDK Prebuilt UI quickstart</a></li><li><a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">VideoSDK REST API introduction</a></li><li><a href="https://docs.videosdk.live/code-sample">VideoSDK code samples</a></li><li><a href="https://www.w3.org/TR/webrtc/">W3C WebRTC specification</a></li></ul><h2 id="about-this-review">About This Review</h2><p>The VideoSDK editorial team prepared this comparison from official documentation, public pricing, release notes, and implementation paths reviewed on July 28, 2026.</p><p>VideoSDK publishes the article and ranks first under the disclosed rubric. Readers should use the same proof-of-concept and procurement checks for every shortlisted provider.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 SignalWire Alternatives for Video APIs: Expert Tested & Ranked]]></title><description><![CDATA[We compared ten SignalWire alternatives for programmable video using a transparent 100-point framework. See current pricing, SDK coverage, limitations, lifecycle updates, and the best fit for each use case.]]></description><link>https://www.videosdk.live/blog/signalwire-alternatives</link><guid isPermaLink="false">6a6753cbb3240feb748c8ce9</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 27 Jul 2026 14:38:15 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT_Image_Jul_27-_2026-_202607271946.jpeg" medium="image"/><content:encoded><![CDATA[<blockquote>VideoSDK is the best overall SignalWire alternative for teams that want broad SDK coverage, prebuilt and custom UI options, and transparent usage pricing. Choose LiveKit for open-source control, Daily for the fastest embedded launch, Agora for global RTC depth, or Zoom Video SDK for large branded sessions.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT_Image_Jul_27-_2026-_202607271946.jpeg" alt="Top 10 SignalWire Alternatives for Video APIs: Expert Tested & Ranked"/><p>If you are comparing SignalWire alternatives for programmable video, ignore rankings built around SMS, SIP trunks, or contact-centre software. This guide evaluates video calling APIs only.</p><p>We ranked ten platforms using a documented 100-point framework covering video controls, SDK breadth, UI speed, documentation, pricing, and operations. VideoSDK ranks first for its balanced developer experience. LiveKit and Daily follow for open-source flexibility and fast implementation.</p><p><strong>Scope:</strong> Video calling APIs and SDKs for embedding real-time audio and video into web, mobile, desktop, or game applications.</p><p><strong>Research date:</strong> Pricing, documentation, and product status checked on 27 July 2026.</p><p><strong>Transparency note:</strong> VideoSDK publishes this article and is also a ranked provider. To reduce publisher bias, every score uses the same criteria and each provider includes a clear limitation.</p><p><strong>What "expert tested" means here:</strong> We completed a reproducible desk audit of official documentation, SDK coverage, quickstarts, authentication flows, UI options, production controls, and published pricing. We did not run instrumented network, latency, or quality tests, so this article makes no independent performance claims.</p><h2 id="the-best-signalwire-alternatives-at-a-glance">The best SignalWire alternatives at a glance</h2><p>VideoSDK is the strongest all-round choice, but the right platform depends on how much control, speed, scale, and operational ownership your team wants.</p><ol><li><strong>VideoSDK:</strong> Best overall balance of SDK coverage, customisation, prebuilt UI, and clear participant-minute pricing.</li><li><strong>LiveKit:</strong> Best for open-source infrastructure and teams that want a self-hosting path.</li><li><strong>Daily:</strong> Best for shipping embedded video quickly with a polished prebuilt component.</li><li><strong>Agora:</strong> Best for broad real-time engagement capabilities and extensive platform coverage.</li><li><strong>Zoom Video SDK:</strong> Best for large branded sessions built on Zoom's media stack.</li><li><strong>100ms:</strong> Best for role-based live classes, communities, and interactive events.</li><li><strong>Vonage Video API:</strong> Best for teams already using Vonage communications APIs.</li><li><strong>Twilio Video:</strong> Best for existing Twilio customers that need a maintained, familiar video product.</li><li><strong>ZEGOCLOUD:</strong> Best for teams that want a broad catalogue of video and live-streaming kits.</li><li><strong>Whereby Embedded:</strong> Best for simple browser-based meetings with minimal UI work.</li></ol><h2 id="how-we-ranked-the-best-signalwire-alternatives">How we ranked the best SignalWire alternatives</h2><p>Our ranking measures product fit for programmable video, not overall company size, popularity, or the breadth of each vendor's communications portfolio.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Criterion</th>
<th style="text-align:right">Weight</th>
<th>What we checked</th>
</tr>
</thead>
<tbody>
<tr>
<td>Core video and production controls</td>
<td style="text-align:right">25</td>
<td>Rooms, roles, screen sharing, recording, streaming, moderation, media controls, and session limits</td>
</tr>
<tr>
<td>SDK and platform breadth</td>
<td style="text-align:right">20</td>
<td>Web, Android, iOS, React Native, Flutter, desktop, Unity, and server-side tooling</td>
</tr>
<tr>
<td>UI shipping speed</td>
<td style="text-align:right">15</td>
<td>Prebuilt UI, UI kits, reusable components, and custom UI paths</td>
</tr>
<tr>
<td>Documentation and implementation</td>
<td style="text-align:right">15</td>
<td>Quickstarts, authentication flow, examples, API consistency, and migration guidance</td>
</tr>
<tr>
<td>Pricing transparency and access</td>
<td style="text-align:right">15</td>
<td>Public rates, free allowance, billing clarity, and extra feature charges</td>
</tr>
<tr>
<td>Deployment and operations</td>
<td style="text-align:right">10</td>
<td>Managed service, self-hosting options, observability, regional controls, and enterprise readiness</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Scores are editorial assessments from the documented audit above. A two-point difference should not replace a proof of concept using your actual devices, regions, and call patterns.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th style="text-align:right">Rank</th>
<th>Provider</th>
<th style="text-align:right">Core video /25</th>
<th style="text-align:right">SDK breadth /20</th>
<th style="text-align:right">UI speed /15</th>
<th style="text-align:right">Docs /15</th>
<th style="text-align:right">Pricing /15</th>
<th style="text-align:right">Operations /10</th>
<th style="text-align:right">Total /100</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">1</td>
<td>VideoSDK</td>
<td style="text-align:right">23</td>
<td style="text-align:right">20</td>
<td style="text-align:right">14</td>
<td style="text-align:right">14</td>
<td style="text-align:right">14</td>
<td style="text-align:right">7</td>
<td style="text-align:right"><strong>92</strong></td>
</tr>
<tr>
<td style="text-align:right">2</td>
<td>LiveKit</td>
<td style="text-align:right">24</td>
<td style="text-align:right">19</td>
<td style="text-align:right">12</td>
<td style="text-align:right">14</td>
<td style="text-align:right">11</td>
<td style="text-align:right">9</td>
<td style="text-align:right"><strong>89</strong></td>
</tr>
<tr>
<td style="text-align:right">3</td>
<td>Daily</td>
<td style="text-align:right">22</td>
<td style="text-align:right">17</td>
<td style="text-align:right">15</td>
<td style="text-align:right">14</td>
<td style="text-align:right">13</td>
<td style="text-align:right">6</td>
<td style="text-align:right"><strong>87</strong></td>
</tr>
<tr>
<td style="text-align:right">4</td>
<td>Agora</td>
<td style="text-align:right">24</td>
<td style="text-align:right">20</td>
<td style="text-align:right">11</td>
<td style="text-align:right">13</td>
<td style="text-align:right">10</td>
<td style="text-align:right">8</td>
<td style="text-align:right"><strong>86</strong></td>
</tr>
<tr>
<td style="text-align:right">5</td>
<td>Zoom Video SDK</td>
<td style="text-align:right">23</td>
<td style="text-align:right">19</td>
<td style="text-align:right">14</td>
<td style="text-align:right">13</td>
<td style="text-align:right">8</td>
<td style="text-align:right">7</td>
<td style="text-align:right"><strong>84</strong></td>
</tr>
<tr>
<td style="text-align:right">6</td>
<td>100ms</td>
<td style="text-align:right">22</td>
<td style="text-align:right">17</td>
<td style="text-align:right">13</td>
<td style="text-align:right">13</td>
<td style="text-align:right">11</td>
<td style="text-align:right">6</td>
<td style="text-align:right"><strong>82</strong></td>
</tr>
<tr>
<td style="text-align:right">7</td>
<td>Vonage Video API</td>
<td style="text-align:right">22</td>
<td style="text-align:right">16</td>
<td style="text-align:right">11</td>
<td style="text-align:right">13</td>
<td style="text-align:right">11</td>
<td style="text-align:right">7</td>
<td style="text-align:right"><strong>80</strong></td>
</tr>
<tr>
<td style="text-align:right">8</td>
<td>Twilio Video</td>
<td style="text-align:right">21</td>
<td style="text-align:right">13</td>
<td style="text-align:right">10</td>
<td style="text-align:right">13</td>
<td style="text-align:right">13</td>
<td style="text-align:right">8</td>
<td style="text-align:right"><strong>78</strong></td>
</tr>
<tr>
<td style="text-align:right">9</td>
<td>ZEGOCLOUD</td>
<td style="text-align:right">21</td>
<td style="text-align:right">19</td>
<td style="text-align:right">11</td>
<td style="text-align:right">11</td>
<td style="text-align:right">8</td>
<td style="text-align:right">7</td>
<td style="text-align:right"><strong>77</strong></td>
</tr>
<tr>
<td style="text-align:right">10</td>
<td>Whereby Embedded</td>
<td style="text-align:right">19</td>
<td style="text-align:right">12</td>
<td style="text-align:right">15</td>
<td style="text-align:right">13</td>
<td style="text-align:right">11</td>
<td style="text-align:right">4</td>
<td style="text-align:right"><strong>74</strong></td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h2 id="signalwire-video-pricing-and-architecture-as-the-baseline">SignalWire video pricing and architecture as the baseline</h2><p><a href="https://signalwire.com/" rel="noreferrer nofollow">SignalWire</a> is a strong baseline for teams that value cloud-side media composition, programmable room layouts, recording, and a unified media stream.</p><p>SignalWire's <a href="https://signalwire.com/products/cloud-video/features" rel="noreferrer nofollow">Cloud Video product</a> describes a cloud MCU architecture that mixes participant media before delivery. Its published features include room layouts, recording, streaming, screen sharing, and support for up to 300 interactive participants. The current SDK list emphasises JavaScript, Node.js, and React Native.</p><p>The <a href="https://signalwire.com/pricing/video" rel="noreferrer nofollow">SignalWire video pricing</a> page lists Video API usage from <strong>$0.0045 per participant-minute for standard 720p video</strong>. Full HD, recording, and streaming can add cost. Verify the current rate and resolution tier in your account before modelling a migration.</p><p>That architecture can simplify layout consistency and recording workflows. It can also make SignalWire a different design choice from platforms centred on selective forwarding units, client-side composition, or open-source deployment. The best alternative therefore depends on whether your priority is managed mixing, SDK reach, UI speed, infrastructure control, or a particular event format.</p><h2 id="signalwire-alternatives-pricing-comparison">SignalWire alternatives pricing comparison</h2><p>Headline participant-minute rates are useful for screening, but they are not a complete total-cost comparison.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Provider</th>
<th>Public video entry point checked 27 July 2026</th>
<th>Important billing note</th>
</tr>
</thead>
<tbody>
<tr>
<td>SignalWire</td>
<td>From <strong>$0.0045 per participant-minute</strong> at 720p</td>
<td>Full HD, recording, streaming, and prebuilt products have separate rates</td>
</tr>
<tr>
<td>VideoSDK</td>
<td><strong>$0.004 per participant-minute</strong></td>
<td>Public page includes $20 free credit; recording and streaming are separate</td>
</tr>
<tr>
<td>LiveKit Cloud</td>
<td>Build free; Ship from <strong>$50/month</strong></td>
<td>Connection minutes and downstream data are billed separately after allowances</td>
</tr>
<tr>
<td>Daily</td>
<td>First 10,000 participant-minutes free, then <strong>$0.004 per participant-minute</strong></td>
<td>Recording and streaming add cost</td>
</tr>
<tr>
<td>Agora</td>
<td>First 10,000 minutes free, then from <strong>$3.99 per 1,000 minutes</strong></td>
<td>Resolution and add-on choices can change cost</td>
</tr>
<tr>
<td>Zoom Video SDK</td>
<td>Credit-based usage pricing</td>
<td>Use Zoom's calculator or account quote for the current effective rate</td>
</tr>
<tr>
<td>100ms</td>
<td>First 10,000 conferencing minutes free, then <strong>$0.004 per participant-minute</strong></td>
<td>Recording and streaming are separate</td>
</tr>
<tr>
<td>Vonage Video API</td>
<td><strong>$0.00410 per participant-minute</strong></td>
<td>Archiving, broadcast, and other advanced features can add charges</td>
</tr>
<tr>
<td>Twilio Video</td>
<td><strong>$0.004 per participant-minute</strong> for Group Rooms</td>
<td>Participant recording and compositions are billed separately</td>
</tr>
<tr>
<td>ZEGOCLOUD</td>
<td>First 10,000 minutes free, then from <strong>$3.99 per 1,000 participant-minutes</strong></td>
<td>Pricing varies across its wider product catalogue</td>
</tr>
<tr>
<td>Whereby Embedded</td>
<td>Free Explore tier; Build from <strong>$9.99/month</strong> with 2,000 minutes</td>
<td>Additional usage is $0.004 per participant-minute; add-ons cost extra</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p><strong>Pricing formula:</strong> monthly video cost is usually participant count multiplied by call duration multiplied by monthly sessions, plus recording, streaming, storage, egress, transcription, telephony, and support.</p><p>A 30-minute call with six participants consumes 180 participant-minutes, not 30. Model peak concurrency and add-ons alongside the headline rate.</p><h2 id="1-videosdk-best-overall-signalwire-alternative">1. VideoSDK: Best overall SignalWire alternative</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.29.39-PM-5.png" class="kg-image" alt="Top 10 SignalWire Alternatives for Video APIs: Expert Tested & Ranked" loading="lazy" width="2906" height="1660"/></figure><p>VideoSDK ranks first because it combines broad platform coverage, two UI paths, and a simple public video rate without forcing every team into the same implementation model.</p><p>The <a href="https://docs.videosdk.live/">VideoSDK documentation</a> covers JavaScript, React, React Native, Android, iOS, Flutter, Unity, Python, and C++, among other implementation paths. Teams can use <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">VideoSDK Prebuilt</a> to launch quickly or build a custom interface around lower-level meeting APIs.</p><p>This breadth matters when a SignalWire migration must support both browser and native applications. It reduces the need to evaluate a separate vendor for each client platform. The room, participant, media, recording, streaming, and token concepts are also familiar to developers who have used programmable video APIs.</p><p>VideoSDK's live pricing page lists video calls at <strong>$0.004 per participant-minute</strong> and includes <strong>$20 in free credit</strong>. Separate rates apply to audio-only sessions, recording, streaming, transcription, and other services. Always model the exact feature set rather than multiplying the base rate alone.</p><p><strong>Best for:</strong> SaaS products, telehealth, education, marketplaces, communities, and support applications that need broad SDK reach with both fast and custom UI options.</p><p><strong>Why it placed first:</strong> It has the most balanced score across SDK breadth, implementation speed, documentation, and pricing clarity for the scope of this ranking.</p><p><strong>Limitation:</strong> VideoSDK is the publisher of this comparison. Its first-place position should be validated with a proof of concept, especially if self-hosting or a specialised compliance requirement is central to your decision.</p><h2 id="2-livekit-best-open-source-signalwire-alternative">2. LiveKit: Best open-source SignalWire alternative</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.40-PM-5.png" class="kg-image" alt="Top 10 SignalWire Alternatives for Video APIs: Expert Tested & Ranked" loading="lazy" width="2920" height="1670"/></figure><p><a href="https://livekit.com/" rel="noreferrer nofollow"><u>LiveKit</u></a> is the best option for teams that want an open-source media stack, a managed cloud, and a credible path to deeper infrastructure control.</p><p>The LiveKit connection documentation describes client SDKs for JavaScript, Swift, Android, React Native, Flutter, C++, and Unity, plus server SDKs. That coverage supports products spanning web, mobile, desktop, and spatial or game experiences.</p><p>LiveKit's main differentiator is deployment choice. Teams can use LiveKit Cloud or operate the open-source stack themselves. This can be valuable when infrastructure ownership, regional deployment, or custom media workflows outweigh the simplicity of a fully managed API.</p><p>Pricing is not directly comparable with a flat participant-minute rate. <a href="https://livekit.com/pricing" rel="noreferrer nofollow">LiveKit Cloud pricing</a> combines plans, included WebRTC connection minutes, participant concurrency, and data transfer. The Build tier is free, while paid tiers start at $50 per month. Downstream data can materially affect total cost for video-heavy workloads.</p><p><strong>Best for:</strong> Engineering-led teams that want open-source flexibility, self-hosting potential, or tight control over the media layer.</p><p><strong>Why it placed second:</strong> Its core media and operational flexibility are excellent, but cost modelling and infrastructure choices require more effort than a simple managed rate.</p><p><strong>Limitation:</strong> Self-hosting shifts reliability, upgrades, scaling, observability, and incident response to your team. Managed Cloud pricing also needs a model that includes minutes and data transfer.</p><h2 id="3-daily-best-for-launching-embedded-video-quickly">3. Daily: Best for launching embedded video quickly</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.02-PM-2.png" class="kg-image" alt="Top 10 SignalWire Alternatives for Video APIs: Expert Tested & Ranked" loading="lazy" width="2924" height="1652"/></figure><p>Daily is the strongest choice when your priority is a polished prebuilt experience that can later expand into a custom interface.</p><p><a href="https://docs.daily.co/" rel="noreferrer nofollow">Daily's documentation</a> offers Daily Prebuilt, custom client SDKs, and coverage for JavaScript, React, React Native, Android, iOS, Flutter, and Python. Its prebuilt component is particularly useful for teams that need a credible meeting experience before investing in a dedicated RTC interface.</p><p>Daily also provides lower-level APIs for teams that need custom layouts, media controls, recording, live streaming, or app-specific workflows. This creates a practical progression from prototype to tailored product without changing providers.</p><p><a href="https://www.daily.co/pricing/video-sdk/" rel="noreferrer nofollow">Daily video pricing</a> includes the first 10,000 participant-minutes each month, followed by a published rate of $0.004 per participant-minute in the first paid tier. Recording, streaming, and other services have separate charges.</p><p><strong>Best for:</strong> Startups and product teams that want to embed reliable browser or mobile calls with minimal UI development.</p><p><strong>Why it placed third:</strong> Daily earns the highest UI shipping score, with strong documentation and transparent entry pricing.</p><p><strong>Limitation:</strong> Teams with a strict self-hosting requirement or unusually deep infrastructure customisation may prefer an open-source platform such as LiveKit.</p><h2 id="4-agora-best-for-broad-real-time-engagement-coverage">4. Agora: Best for broad real-time engagement coverage</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.26-PM-5.png" class="kg-image" alt="Top 10 SignalWire Alternatives for Video APIs: Expert Tested & Ranked" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/en/products/interactive-live-streaming/" rel="noreferrer nofollow">Agora</a> is a strong SignalWire alternative for teams that need extensive SDK coverage and a mature catalogue of real-time engagement capabilities.</p><p>The Agora Video Calling product supports programmable video across a broad set of platforms and use cases. Agora also offers adjacent products for interactive live streaming, chat, signalling, and engagement features, which can reduce vendor sprawl for complex real-time applications.</p><p>Agora <a href="https://www.agora.io/en/pricing/interactive-live-streaming/" rel="noreferrer nofollow">pricing</a> starts at $3.99 per 1,000 minutes for video calling, with the first 10,000 minutes free each month. The effective bill depends on resolution, service category, recording, streaming, and selected add-ons. Teams should reproduce their expected usage in Agora's pricing tools before comparing it with a single flat rate.</p><p>Agora is particularly credible for applications that need broad device coverage or expect to grow beyond straightforward meeting rooms. However, its product breadth also means buyers must choose the correct SDK and billing category.</p><p><strong>Best for:</strong> Large consumer, social, education, gaming, and live-engagement products with diverse client platforms.</p><p><strong>Why it placed fourth:</strong> Agora scores highly on core video and SDK breadth, but its wider catalogue creates more pricing and product-selection complexity.</p><p><strong>Limitation:</strong> The number of products, add-ons, and pricing dimensions can slow evaluation. Build a narrow bill of materials before beginning the proof of concept.</p><h2 id="5-zoom-video-sdk-best-for-large-branded-sessions">5. Zoom Video SDK: Best for large branded sessions</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.32.46-PM-4.png" class="kg-image" alt="Top 10 SignalWire Alternatives for Video APIs: Expert Tested & Ranked" loading="lazy" width="2920" height="1646"/></figure><p>The <a href="https://developers.zoom.us/docs/video-sdk/" rel="noreferrer nofollow">Zoom Video SDK</a> is the right comparison point when you want Zoom's media technology inside your own interface rather than a standard Zoom Meeting.</p><p>The Zoom Video SDK documentation lists SDKs for iOS, Android, macOS, Windows, Web, React Native, Linux, Flutter, and Unity. Zoom also provides a UI Toolkit for teams that want reusable meeting components without adopting the familiar Zoom Meeting interface.</p><p>Zoom states that Video SDK sessions can support up to 5,000 users, subject to product configuration and commercial terms. This makes it relevant for large classes, events, customer sessions, and branded collaboration products.</p><p>The important architectural distinction is that a Video SDK session is your application's session. It does not simply embed an ordinary Zoom Meeting, and its feature model differs from the Zoom Meetings product.</p><p><a href="https://zoom.us/pricing/developer" rel="noreferrer nofollow">Zoom developer pricing</a> uses credits and usage-based billing. Because a single public participant-minute rate is not clearly exposed for every scenario, teams should use the calculator or request an account-specific quote.</p><p><strong>Best for:</strong> Enterprises and event products that need large branded sessions and broad native-platform coverage.</p><p><strong>Why it placed fifth:</strong> Zoom combines scale, SDK reach, and a UI toolkit, but pricing is less immediately comparable.</p><p><strong>Limitation:</strong> Buyers sometimes assume Video SDK includes every Zoom Meetings feature. Confirm each required feature, integration, and compliance control in the Video SDK documentation.</p><h2 id="6-100ms-best-for-role-based-classes-and-live-communities">6. 100ms: Best for role-based classes and live communities</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.31.12-PM-6.png" class="kg-image" alt="Top 10 SignalWire Alternatives for Video APIs: Expert Tested & Ranked" loading="lazy" width="2910" height="1656"/></figure><p><a href="https://www.100ms.live/" rel="noreferrer nofollow">100ms</a> is a strong choice for products built around explicit roles, such as host, teacher, learner, speaker, moderator, or viewer.</p><p>The 100ms documentation supports web, Android, iOS, Flutter, and React Native. Its room templates and role model help teams define publishing permissions and stage behaviour without scattering the rules across client applications.</p><p>100ms offers both prebuilt and custom UI paths. That combination suits virtual classrooms, fitness products, live communities, webinars, and audio-video social experiences where participant permissions change during a session.</p><p><a href="https://www.100ms.live/pricing" rel="noreferrer nofollow">100ms pricing</a> includes 10,000 conferencing minutes each month, followed by $0.004 per participant-minute. Recording, live streaming, transcription, and other services are billed separately.</p><p><strong>Best for:</strong> Education, coaching, events, communities, and interactive broadcasts that need clear role and stage logic.</p><p><strong>Why it placed sixth:</strong> The role-based model and UI options are well suited to structured live experiences, with a competitive published entry rate.</p><p><strong>Limitation:</strong> Teams should confirm how templates, roles, recording, and streaming map to their existing SignalWire room model before estimating migration effort.</p><h2 id="7-vonage-video-api-best-for-existing-vonage-customers">7. Vonage Video API: Best for existing Vonage customers</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.32.16-PM-2.png" class="kg-image" alt="Top 10 SignalWire Alternatives for Video APIs: Expert Tested & Ranked" loading="lazy" width="2922" height="1652"/></figure><p><a href="https://developer.vonage.com/en/video/overview" rel="noreferrer nofollow">Vonage Video API</a> is most compelling when video is part of a wider Vonage communications architecture or an existing enterprise relationship.</p><p>The Vonage Video API overview covers sessions, publishers, subscribers, screen sharing, archiving, and broadcast. Client and server tooling supports common web, mobile, and backend environments.</p><p><a href="https://www.vonage.com/communications-apis/video/pricing/" rel="noreferrer nofollow">Vonage video pricing</a> lists $0.00410 per participant-minute. New customers can receive trial minutes, while archiving, broadcast, SIP, and other advanced features may have separate rates.</p><p>Vonage is a proven option for consultation, telehealth, education, and customer-engagement workflows. Its value increases when your team can consolidate video with other Vonage APIs or reuse established security, procurement, and support arrangements.</p><p><strong>Best for:</strong> Enterprises that already use Vonage or want video within a broader communications portfolio.</p><p><strong>Why it placed seventh:</strong> Core video capabilities and public pricing are solid, but the platform is less differentiated for a video-only greenfield project.</p><p><strong>Limitation:</strong> Extra feature charges can change the total. Compare a complete room, recording, broadcast, and support configuration rather than the base participant-minute rate.</p><h2 id="8-twilio-video-best-for-existing-twilio-stacks">8. Twilio Video: Best for existing Twilio stacks</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.53.31-PM-1.png" class="kg-image" alt="Top 10 SignalWire Alternatives for Video APIs: Expert Tested & Ranked" loading="lazy" width="2910" height="1638"/></figure><p>Twilio Video remains a supported standalone product, despite older articles that still claim it is shutting down.</p><p>Twilio initially announced an end-of-life plan, then reversed it. Its October 2024 product update says Twilio Video will remain a standalone product. Any 2026 comparison that repeats the shutdown claim without this correction is stale.</p><p>The <a href="https://www.twilio.com/docs/video/overview" rel="noreferrer nofollow">Twilio Video overview</a> provides official SDK paths for JavaScript, Android, and iOS. The room and participant model is familiar to teams already using Twilio APIs, authentication, logging, and account controls.</p><p><a href="https://help.twilio.com/articles/115004710208" rel="noreferrer nofollow">Twilio Video pricing</a> lists Group Rooms at $0.004 per participant-minute. Participant recording adds another $0.004 per recorded participant-minute, and compositions have a separate charge.</p><p><strong>Best for:</strong> Existing Twilio customers that value account consolidation and do not require the broadest client SDK list.</p><p><strong>Why it placed eighth:</strong> Twilio is maintained, documented, and competitively priced, but its official video SDK breadth is narrower than higher-ranked options.</p><p><strong>Limitation:</strong> Product strategy changed once already. Buyers should verify the current roadmap, SDK maintenance cadence, and long-term fit during procurement.</p><h2 id="9-zegocloud-best-for-a-broad-catalogue-of-engagement-kits">9. ZEGOCLOUD: Best for a broad catalogue of engagement kits</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.33.21-PM-3.png" class="kg-image" alt="Top 10 SignalWire Alternatives for Video APIs: Expert Tested & Ranked" loading="lazy" width="2926" height="1668"/></figure><p>ZEGOCLOUD suits teams that want video calling alongside live streaming, voice, chat, and reusable engagement kits across many client platforms.</p><p>The <a href="https://www.zegocloud.com/api-center" rel="noreferrer nofollow">ZEGOCLOUD API centre</a> lists support for iOS, Android, Web, Flutter, React Native, Electron, Unity, Windows, macOS, Linux, and other environments. This breadth is useful for products spanning consumer mobile, desktop, web, and game clients.</p><p><a href="https://www.zegocloud.com/pricing?index=0" rel="noreferrer nofollow">ZEGOCLOUD pricing</a> lists Video Call from $3.99 per 1,000 participant-minutes, with 10,000 free minutes. Its broader catalogue has additional service categories and rates, so the exact bill depends on the selected kit, resolution, recording, streaming, and messaging features.</p><p><strong>Best for:</strong> Social, live-streaming, gaming, and entertainment applications that need a wide platform matrix and several engagement products.</p><p><strong>Why it placed ninth:</strong> SDK coverage is excellent, but documentation navigation and pricing comparison are more complex than the leaders in this video-only ranking.</p><p><strong>Limitation:</strong> The large product catalogue can make it harder to identify the minimum required stack. Confirm the exact APIs and billing units before implementation.</p><h2 id="10-whereby-embedded-best-for-simple-browser-meetings">10. Whereby Embedded: Best for simple browser meetings</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.34.01-PM-1.png" class="kg-image" alt="Top 10 SignalWire Alternatives for Video APIs: Expert Tested & Ranked" loading="lazy" width="2890" height="1624"/></figure><p><a href="https://whereby.com/" rel="noreferrer nofollow">Whereby Embedded</a> is the easiest option for teams that want a familiar browser meeting experience with very little interface work.</p><p>Whereby's embedded product centres on room URLs and a prebuilt meeting interface. This can be a good fit for appointments, interviews, customer support, remote expertise, and marketplaces where the meeting is important but not the application's main differentiator.</p><p><a href="https://whereby.com/information/embedded/pricing" rel="noreferrer nofollow">Whereby Embedded pricing</a> offers a free Explore tier with up to 2,000 participant-minutes each month. The Build plan starts at $9.99 per month, includes 2,000 minutes, and charges $0.004 per additional participant-minute. Recording, transcription, and HIPAA-related options add cost.</p><p><strong>Best for:</strong> Small teams that want to add clean browser-based meetings without building a complete real-time interface.</p><p><strong>Why it placed tenth:</strong> It leads on UI speed and simplicity, but offers less low-level control and a narrower platform strategy than the other SignalWire alternatives.</p><p><strong>Limitation:</strong> Whereby's opinionated meeting experience is less suitable when video controls, layout, media processing, or native SDK behaviour are core product differentiators.</p><h2 id="video-api-lifecycle-watchlist-for-2026">Video API lifecycle watchlist for 2026</h2><p>Product status changes can invalidate an otherwise accurate SignalWire alternatives list, so verify lifecycle notices before shortlisting a provider.</p><h3 id="twilio-video-is-not-shutting-down">Twilio Video is not shutting down</h3><p>Twilio reversed its earlier end-of-life plan in October 2024 and says Video remains a standalone product. Check the current changelog, not older comparison posts.</p><h3 id="dyte-sdks-are-in-maintenance-mode">Dyte SDKs are in maintenance mode</h3><p>Dyte's RealtimeKit migration guide says its SDKs are in maintenance mode and no longer receive feature updates or bug fixes. New evaluations should focus on Cloudflare RealtimeKit rather than ranking Dyte as a normal standalone alternative.</p><h3 id="cloudflare-realtimekit-is-still-in-beta">Cloudflare RealtimeKit is still in beta</h3><p>Cloudflare's RealtimeKit overview labels the product Beta. Its pricing page says beta usage is free and lists planned general-availability pricing of $0.002 per audio-video participant-minute.</p><p>RealtimeKit is worth monitoring, but beta status keeps it outside this production-focused top ten. Reassess it when Cloudflare announces general availability, final service limits, support terms, and production SLAs.</p><h2 id="how-to-choose-a-signalwire-alternative">How to choose a SignalWire alternative</h2><p>Choose the platform that best fits your product architecture, team, and call profile, not the platform with the highest general score.</p><h3 id="choose-by-implementation-model">Choose by implementation model</h3><ul><li>Choose <strong>VideoSDK</strong> when you want prebuilt and custom UI paths across a wide range of client SDKs.</li><li>Choose <strong>LiveKit</strong> when open source, self-hosting potential, or infrastructure control is a primary requirement.</li><li>Choose <strong>Daily</strong> when launch speed and a polished embedded interface matter most.</li><li>Choose <strong>Whereby</strong> when a simple browser meeting is enough and deep media customisation is unnecessary.</li></ul><h3 id="choose-by-session-format">Choose by session format</h3><ul><li>Choose <strong>100ms</strong> for role-heavy classrooms, stages, and communities.</li><li>Choose <strong>Zoom Video SDK</strong> for large branded sessions and broad native-platform support.</li><li>Choose <strong>Agora</strong> or <strong>ZEGOCLOUD</strong> for consumer engagement products that extend beyond standard meetings.</li><li>Choose <strong>SignalWire</strong> when cloud mixing and server-composed layouts remain central.</li></ul><h3 id="choose-by-existing-vendor-stack">Choose by existing vendor stack</h3><ul><li>Choose <strong>Twilio Video</strong> if your team already depends on Twilio accounts, tooling, and operational processes.</li><li>Choose <strong>Vonage Video API</strong> when video belongs inside a wider Vonage communications deployment.</li><li>Choose <strong>VideoSDK</strong>, <strong>Daily</strong>, or <strong>LiveKit</strong> for a more video-focused greenfield evaluation.</li></ul><h3 id="choose-by-total-cost-not-the-base-rate">Choose by total cost, not the base rate</h3><p>Build a monthly model with:</p><ol><li>Average and peak participants per room.</li><li>Average call duration.</li><li>Calls per month.</li><li>Video resolution and simulcast needs.</li><li>Recording and composition minutes.</li><li>Streaming and viewer minutes.</li><li>Storage, egress, transcription, and telephony.</li><li>Support plan and minimum platform fees.</li><li>Engineering cost for custom UI and operations.</li><li>Expected volume discounts.</li></ol><p>Then run a representative proof of concept in your most important countries, browsers, devices, and network conditions.</p><h2 id="when-should-you-keep-signalwire">When should you keep SignalWire?</h2><p>Keep SignalWire when its cloud MCU, layout controls, recording workflow, and current SDK coverage already match your product better than a migration would.</p><p>Switching providers has real costs: client rewrites, token changes, room mapping, recording migration, analytics changes, compliance review, QA, and operational retraining. A small participant-minute saving may not repay that work.</p><p>SignalWire may remain the better choice when:</p><ul><li>You rely on server-composed layouts or a unified mixed stream.</li><li>JavaScript, Node.js, and React Native cover your client needs.</li><li>Current recording and streaming workflows are stable.</li><li>The 720p and Full HD pricing structure fits your quality targets.</li><li>Your team already has reliable monitoring, support, and operational knowledge.</li><li>No alternative creates a meaningful improvement in product capability or total cost.</li></ul><p>The best SignalWire alternative is sometimes no migration at all. Use the same decision framework to justify staying.</p><h2 id="how-to-migrate-from-signalwire-to-another-video-api">How to migrate from SignalWire to another video API</h2><p>A safe migration separates product behaviour from provider-specific APIs before moving production traffic.</p><ol><li><strong>Inventory the current implementation.</strong> List room creation, token generation, participant roles, screen sharing, device controls, layouts, recording, streaming, webhooks, moderation, analytics, and data retention.</li><li><strong>Define non-negotiable requirements.</strong> Set target platforms, concurrency, regions, quality, accessibility, compliance, support, and recovery objectives.</li><li><strong>Normalise the data model.</strong> Map SignalWire rooms, participants, permissions, tracks, recordings, and callbacks to provider-neutral application concepts.</li><li><strong>Build a server-side adapter.</strong> Keep provider credentials and token generation on the server. Expose a stable internal interface to your clients.</li><li><strong>Recreate the smallest complete call.</strong> Implement join, publish, subscribe, mute, camera switch, leave, and error recovery before advanced features.</li><li><strong>Add production workflows.</strong> Migrate screen sharing, roles, moderation, recording, streaming, layouts, webhooks, and analytics one feature at a time.</li><li><strong>Test representative conditions.</strong> Cover your priority browsers, operating systems, devices, regions, corporate networks, low bandwidth, reconnects, and permission failures.</li><li><strong>Run both providers in parallel.</strong> Route internal users or a small cohort to the new platform while retaining a rollback path.</li><li><strong>Compare complete cost and reliability.</strong> Measure participant minutes, add-ons, failed joins, reconnects, support effort, and engineering time.</li><li><strong>Cut over gradually.</strong> Increase traffic by cohort, monitor each step, and retire SignalWire only after recordings, data, and rollback obligations are complete.</li></ol><p>Do not expose API secrets in browser or mobile code. Generate short-lived meeting tokens on a trusted server, and use the provider's current authentication guide.</p><h2 id="key-video-api-terms">Key video API terms</h2><p>These definitions make pricing and architecture comparisons easier.</p><blockquote><strong>Participant-minute:</strong> One participant connected for one minute. Six people in a 30-minute call use 180 participant-minutes.</blockquote><blockquote><strong>MCU:</strong> A multipoint control unit decodes and mixes media on the server before sending composed output.</blockquote><blockquote><strong>SFU:</strong> A selective forwarding unit routes media tracks between participants without producing one mixed stream for every receiver.</blockquote><blockquote><strong>Prebuilt UI:</strong> A vendor-provided meeting interface that can be embedded with limited code.</blockquote><blockquote><strong>UI kit:</strong> Reusable interface components that can be composed into a branded meeting experience.</blockquote><blockquote><strong>Custom SDK:</strong> Lower-level APIs used to build the interface and interaction model from scratch.</blockquote><blockquote><strong>Simulcast:</strong> Publishing multiple quality layers so the service can select an appropriate stream for each receiver.</blockquote><blockquote><strong>Recording composition:</strong> Processing participant tracks into a viewable output layout.</blockquote><blockquote><strong>Egress:</strong> Media or data transferred out of a provider's network, sometimes billed separately.</blockquote><blockquote><strong>WebRTC:</strong> The browser and native technology foundation used by many real-time audio and video products.</blockquote><h2 id="final-verdict-on-the-best-signalwire-alternatives">Final verdict on the best SignalWire alternatives</h2><p>VideoSDK is the best overall SignalWire alternative in this 2026 video API ranking because it combines broad SDK coverage, prebuilt and custom UI paths, clear participant-minute pricing, and accessible documentation.</p><p>LiveKit is the stronger choice for open-source control. Daily is the fastest route to a polished embedded experience. Agora and Zoom Video SDK suit broad platform or large-session requirements, while 100ms stands out for role-based live formats.</p><p>Do not decide from the ranking alone. Shortlist two or three providers, model your complete bill, and run the same proof of concept against your real call flows. If SignalWire's cloud mixing and current workflows still fit best, keeping it is a valid result.</p><p>To evaluate VideoSDK directly, start with the <a href="https://docs.videosdk.live/">VideoSDK documentation</a> and reproduce one representative room with your required platforms, roles, recording, and network conditions.</p><p><strong>Which requirement is hardest in your SignalWire migration: SDK coverage, media architecture, recording, pricing, or operational control?</strong></p><h2 id="frequently-asked-questions-about-signalwire-alternatives">Frequently asked questions about SignalWire alternatives</h2><h3 id="what-is-the-best-signalwire-alternative-for-video-calling-apis">What is the best SignalWire alternative for video-calling APIs?</h3><p>VideoSDK is the best overall SignalWire alternative for teams that want broad SDK coverage, prebuilt and custom UI options, and transparent participant-minute pricing. LiveKit is better for open-source control, while Daily is better for the fastest prebuilt launch.</p><h3 id="is-videosdk-a-good-alternative-to-signalwire">Is VideoSDK a good alternative to SignalWire?</h3><p>Yes. VideoSDK is a good SignalWire alternative when your product needs video SDKs across web, mobile, Flutter, React Native, Unity, or native platforms. It also supports both prebuilt and custom interfaces. Validate it with your own compliance, region, quality, and support requirements.</p><h3 id="is-livekit-better-than-signalwire">Is LiveKit better than SignalWire?</h3><p>LiveKit is better when open-source infrastructure, self-hosting potential, or SFU-level control matters more than SignalWire's managed cloud mixing. SignalWire may be better when server-composed layouts and its existing operational workflow already fit your product.</p><h3 id="what-is-the-cheapest-signalwire-alternative">What is the cheapest SignalWire alternative?</h3><p>There is no universal cheapest option because providers charge differently for video resolution, data transfer, recording, streaming, storage, and support. Base rates cluster near $0.004 per participant-minute, while Cloudflare lists a lower planned RealtimeKit rate, but the product remains in beta.</p><h3 id="is-twilio-video-shutting-down">Is Twilio Video shutting down?</h3><p>No. Twilio reversed its earlier end-of-life plan. In October 2024, Twilio announced that Video would remain a standalone product. Buyers should still review the latest changelog and roadmap before committing.</p><h3 id="is-dyte-still-a-recommended-signalwire-alternative-in-2026">Is Dyte still a recommended SignalWire alternative in 2026?</h3><p>Dyte is not a recommended new standalone choice in 2026 because its SDKs are in maintenance mode. Dyte directs customers towards Cloudflare RealtimeKit, which remains in beta as of 27 July 2026.</p><h3 id="which-signalwire-alternative-supports-self-hosting">Which SignalWire alternative supports self-hosting?</h3><p>LiveKit is the clearest choice in this ranking for teams that want an open-source, self-hostable media stack. Self-hosting also makes your team responsible for scaling, reliability, upgrades, monitoring, security, and incident response.</p><h3 id="how-long-does-a-signalwire-video-api-migration-take">How long does a SignalWire video API migration take?</h3><p>Migration time depends on client platforms, custom UI depth, recording, streaming, roles, compliance, and test coverage. A basic browser call can be prototyped quickly, but a production migration usually requires phased implementation, parallel traffic, and a rollback plan.</p><h3 id="read-more-similar-resources">Read more similar resources.</h3><ul><li><a href="https://www.videosdk.live/blog/what-is-video-api">Video calling API guide</a></li><li><a href="https://www.videosdk.live/blog/webrtc">WebRTC architecture guide</a></li><li><a href="https://www.videosdk.live/blog/video-conferencing-api-pricing">Video calling API pricing guide</a></li><li><a href="https://docs.videosdk.live/">VideoSDK documentation</a></li><li><a href="https://www.videosdk.live/blog/video-sdk-embed">Prebuilt video calling quickstart</a></li><li><a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-with-react">React video calling tutorial</a></li><li><a href="https://dev.videosdk.live/blog/how-to-make-a-video-calling-app-using-react-native">React Native video calling tutorial</a></li><li><a href="https://dev.videosdk.live/blog/video-calling-in-flutter">Flutter video calling tutoria</a></li></ul><h2 id=""/>]]></content:encoded></item><item><title><![CDATA[Top 10 Mux Alternatives for Live Streaming APIs in 2026]]></title><description><![CDATA[Compare the best Mux alternatives for live streaming in 2026, including VideoSDK, Amazon IVS, Agora, LiveKit, FastPix, and Cloudflare Stream.]]></description><link>https://www.videosdk.live/blog/mux-alternative</link><guid isPermaLink="false">6a6742bbb3240feb748c8c6f</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 27 Jul 2026 13:27:21 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-27--2026--06_05_45-PM-1.png" medium="image"/><content:encoded><![CDATA[<blockquote>The best Mux alternative depends on whether your audience only watches or also participates. VideoSDK ranks first for interactive live streaming with real-time role switching. Amazon IVS suits AWS-native managed broadcast, while FastPix is closest to a Mux-style RTMPS or SRT to LL-HLS workflow. Keep Mux when passive HLS, automatic live-to-VOD, and playback analytics already fit your product.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-27--2026--06_05_45-PM-1.png" alt="Top 10 Mux Alternatives for Live Streaming APIs in 2026"/><p>A useful <strong>Mux alternative</strong> should solve the live video problem your product actually has. Some teams need reliable one-to-many HLS delivery. Others need viewers to become speakers, shoppers, instructors, or guests without leaving the session.</p><p>That distinction drives this ranking. We evaluated live streaming APIs only, not general video hosts, digital asset managers, or image CDNs. The result is a practical shortlist for developers comparing latency, interaction, deployment, pricing, and migration effort in 2026.</p><h2 id="what-is-a-mux-alternative-for-live-streaming">What Is a Mux Alternative for Live Streaming?</h2><p>A <a href="https://www.mux.com/" rel="noreferrer nofollow">Mux</a> alternative for live streaming is an API or platform that can ingest a live feed, process it, and deliver it to viewers. A valid alternative may use <a href="https://www.videosdk.live/developer-hub/rtmp/rtmp-vs-srt" rel="noreferrer">RTMPS</a>, SRT, <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a>, <a href="https://docs.videosdk.live/server-sdk/reference/whip" rel="noreferrer">WHIP</a>, <a href="https://www.videosdk.live/developer-hub/hls/hls-streaming-videosdk" rel="noreferrer">HLS</a>, or a combination of these protocols.</p><p>The phrase does not describe one product category. It covers two different architectures:</p><ol><li><strong>Broadcast streaming:</strong> One or a few publishers send video to a large, mostly passive audience. RTMPS or SRT ingest and HLS playback are common.</li><li><strong>Interactive live streaming:</strong> Hosts and selected viewers exchange media in real time. WebRTC commonly powers the stage, while HLS or receive-only WebRTC may serve the wider audience.</li></ol><p>Mux's Live Streaming API is strongest in the first category. A Mux Live Stream accepts RTMP, RTMPS, or SRT ingest and produces HLS playback through a playback ID. Mux also supports automatic live-to-VOD recording and low-latency playback modes. However, <a href="https://www.mux.com/docs/guides/live-streaming-faqs" rel="noreferrer nofollow">Mux states</a> that its Live Streaming API is not intended for two-way video communication.</p><p>This article therefore asks a more useful question than "Which vendor also handles video?": which platform best matches your live audience, interaction model, infrastructure preference, and cost unit?</p><h2 id="how-we-ranked-each-mux-alternative">How We Ranked Each Mux Alternative</h2><p>We reviewed official product pages, documentation, and public pricing on July 27, 2026. The ranking uses five criteria:</p><ul><li><strong>Live interaction and latency, 30%:</strong> Can viewers become participants? Is the product built around WebRTC, low-latency HLS, or standard HLS?</li><li><strong>API and developer experience, 25%:</strong> Are the core workflows documented clearly? Are SDKs, webhooks, roles, and sample applications available?</li><li><strong>Live workflow completeness, 20%:</strong> Does the platform cover ingest, playback, recording, restreaming, analytics, moderation, and role changes where relevant?</li><li><strong>Deployment flexibility, 15%:</strong> Is the service fully managed, self-hosted, or available in both models?</li><li><strong>Pricing clarity, 10%:</strong> Can a team identify the billing unit and estimate the main cost drivers before contacting sales?</li></ul><p>Latency figures in this article are vendor-documented targets or ranges, not results from a shared network laboratory. Real performance depends on geography, device, network conditions, player configuration, audience size, and the selected protocol.</p><p>The ranking favors interactive live applications because that is the largest functional gap between Mux Live and many products searching for a replacement. If your product is a passive broadcast or live-to-VOD service, FastPix, Cloudflare Stream, api.video, or Mux itself may be a better fit than the overall ranking suggests.</p><h2 id="mux-alternative-comparison-at-a-glance">Mux Alternative Comparison at a Glance</h2>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th style="text-align:right">Rank</th>
<th>Platform</th>
<th>Best for</th>
<th>Primary live path</th>
<th>Audience interaction</th>
<th>Deployment</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">1</td>
<td>VideoSDK</td>
<td>Interactive stages with role switching</td>
<td>WebRTC, HLS, RTMP output</td>
<td>Strong</td>
<td>Managed</td>
</tr>
<tr>
<td style="text-align:right">2</td>
<td>Amazon IVS</td>
<td>AWS-native broadcast and real-time stages</td>
<td>RTMPS, SRT, WebRTC, HLS</td>
<td>Strong with Stages</td>
<td>Managed</td>
</tr>
<tr>
<td style="text-align:right">3</td>
<td>Agora</td>
<td>Global mobile-first real-time engagement</td>
<td>WebRTC and CDN delivery</td>
<td>Strong</td>
<td>Managed</td>
</tr>
<tr>
<td style="text-align:right">4</td>
<td>LiveKit</td>
<td>Open-source WebRTC infrastructure</td>
<td>WebRTC, RTMP, WHIP, SRT, HLS</td>
<td>Strong</td>
<td>Cloud or self-hosted</td>
</tr>
<tr>
<td style="text-align:right">5</td>
<td>FastPix</td>
<td>Mux-like live video API workflows</td>
<td>RTMPS, SRT, LL-HLS</td>
<td>Limited</td>
<td>Managed</td>
</tr>
<tr>
<td style="text-align:right">6</td>
<td>Cloudflare Stream</td>
<td>Simple video delivery on Cloudflare</td>
<td>RTMPS, SRT, HLS, DASH</td>
<td>WebRTC beta is separate</td>
<td>Managed</td>
</tr>
<tr>
<td style="text-align:right">7</td>
<td>Wowza Video</td>
<td>Broad protocol support and broadcast control</td>
<td>RTMP, RTSP, SRT, WebRTC, HLS</td>
<td>Product dependent</td>
<td>Managed or self-managed</td>
</tr>
<tr>
<td style="text-align:right">8</td>
<td>api.video</td>
<td>Straightforward live API and embeds</td>
<td>RTMPS, SRT, LL-HLS</td>
<td>Limited</td>
<td>Managed</td>
</tr>
<tr>
<td style="text-align:right">9</td>
<td>100ms</td>
<td>Role-based live rooms and hybrid audiences</td>
<td>WebRTC and HLS</td>
<td>Strong</td>
<td>Managed</td>
</tr>
<tr>
<td style="text-align:right">10</td>
<td>Ant Media Server</td>
<td>Self-hosted, edge, and private deployments</td>
<td>WebRTC, WHIP, WHEP, RTMP, SRT, HLS</td>
<td>Strong</td>
<td>Cloud or self-hosted</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h2 id="mux-live-streaming-baseline-in-2026">Mux Live Streaming Baseline in 2026</h2><p>Before replacing Mux, document what it already does for your application.</p><p>A typical <a href="https://www.mux.com/docs/guides/start-live-streaming" rel="noreferrer nofollow"><u>Mux live streaming workflow</u></a> looks like this:</p><ol><li>Create a Live Stream object.</li><li>Send a source through RTMP, RTMPS, or SRT using the generated stream key.</li><li>Play the output through HLS using a playback ID.</li><li>Optionally retain the session as an on-demand asset.</li><li>Use webhooks and playback data to track stream state and viewer experience.</li></ol><p>Mux documents three HLS latency tiers. Standard latency is typically 25 to 30 seconds, reduced latency is commonly 12 to 20 seconds, and low latency can be as low as about 5 seconds. These ranges can be appropriate for sports, events, creator broadcasts, and live channels where viewers do not need to speak back.</p><p>Mux remains a strong option when:</p><ul><li>Your audience primarily watches.</li><li>HLS playback across devices matters more than two-way interaction.</li><li>You want live sessions to become VOD assets automatically.</li><li>Playback analytics and video quality monitoring are central to the product.</li><li>Your existing ingest, webhooks, player, and playback IDs already work reliably.</li></ul><p>You should evaluate a replacement when:</p><ul><li>Viewers need to join the stage with audio or video.</li><li>Auctions, classes, interviews, support, or live shopping require faster feedback loops.</li><li>You need open-source or self-hosted infrastructure.</li><li>Your team wants a different billing unit or a simpler cost model.</li><li>You need protocols or deployment controls that do not fit the Mux Live workflow.</li></ul><h2 id="top-10-mux-alternatives-for-live-streaming-apis">Top 10 Mux Alternatives for Live Streaming APIs</h2><h3 id="1-videosdk">1. VideoSDK</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.29.39-PM-4.png" class="kg-image" alt="Top 10 Mux Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2906" height="1660"/></figure><p><strong>Best for:</strong> Interactive live streaming where audience members can become speakers, guests, buyers, students, or co-hosts.</p><p><a href="https://www.videosdk.live/interactive-live-streaming">VideoSDK</a> ranks first because it gives developers an explicit role model for interactive stages. Its <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-react-ils">Interactive Live Streaming documentation</a> separates participants into two modes. Hosts and co-hosts use <code>SEND_AND_RECV</code>, while audience members use <code>RECV_ONLY</code>. That makes the participation model visible in application code instead of hiding it behind a generic "viewer" concept.</p><p>This architecture is useful for town halls, expert sessions, live commerce, auctions, classrooms, and creator events. A viewer can request access to the stage, a host can approve the request, and the application can change the participant's mode without creating a separate meeting flow. VideoSDK also supports RTMP outputs, so a real-time stage can be restreamed to a broadcast destination.</p><p>VideoSDK ranks first here because it addresses the key reason many teams outgrow a passive HLS pipeline: the audience needs to participate. The API surface also covers meetings, recording, HLS, and <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/rtmp-livestream">RTMP livestream outputs</a>, which reduces the need to combine unrelated vendors for the stage and distribution.</p><p><strong>Where Mux is stronger:</strong> Mux provides a mature, focused workflow for ingesting a broadcast, delivering it over HLS, creating an on-demand asset, and analyzing playback. If your viewers never publish media, moving to a WebRTC-first product may add concepts you do not need.</p><p><strong>Pricing:</strong> VideoSDK uses <a href="https://www.videosdk.live/pricing" rel="noreferrer">pay-as-you-go billing</a> as&nbsp;<strong>$0.002</strong>&nbsp;per viewer-minute for live streaming, <strong>$0.001</strong>&nbsp;per participant-minute for audio calls,&nbsp;<strong>$0.004</strong>&nbsp;per participant-minute for video calls and provides a $20 one-time free balance. Interactive streaming charges vary by participant role and media quality. HLS encoding and RTMP restreaming are separate cost units, so model the exact architecture rather than comparing a single headline rate.</p><h3 id="2-amazon-interactive-video-service">2. Amazon Interactive Video Service</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-6.45.51-PM-2.png" class="kg-image" alt="Top 10 Mux Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2922" height="1628"/></figure><p><strong>Best for:</strong> Teams already operating on AWS that want managed broadcast channels, real-time stages, or both.</p><p><a href="https://aws.amazon.com/ivs/" rel="noreferrer nofollow">Amazon Interactive Video Service</a> ranks second because it provides separate managed products for broadcast delivery and real-time participation. Low-Latency Streaming uses channels and HLS playback for one-to-many broadcasting, while Real-Time Streaming uses stages for interactive participants. AWS documents latency of under five seconds for low-latency channels and under 300 milliseconds for real-time stages under normal conditions.</p><p>This separation is practical. A sports app may use a channel for the main feed and a stage for commentators or fan participation. An ecommerce product may use the broadcast path for scale, then bring selected shoppers into a stage. Amazon IVS supports RTMP, RTMPS, and SRT input for channels, while the stage product handles WebRTC-based interaction.</p><p>IVS ranks second because it covers both sides of the live architecture without requiring a team to operate the media network. It is especially compelling when identity, storage, serverless functions, monitoring, and billing already live in AWS.</p><p><strong>Where Mux is stronger:</strong> Mux presents a more video-focused product surface. Teams that do not want to design around AWS services may find its live-to-VOD and playback analytics workflow easier to reason about.</p><p><strong>Pricing:</strong> <a href="https://aws.amazon.com/ivs/pricing/" rel="noreferrer nofollow">Amazon IVS pricing</a>&nbsp;&nbsp;separates channel input, viewer output, and real-time participant hours. Rates vary by region, resolution, and delivery destination. Include CloudWatch, recording, data transfer, and adjacent AWS services in the final estimate where applicable.</p><h3 id="3-agora">3. Agora</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.26-PM-4.png" class="kg-image" alt="Top 10 Mux Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2920" height="1662"/></figure><p><strong>Best for:</strong> Mobile-first applications that need real-time audio, video, chat, and audience participation across regions.</p><p><a href="https://www.agora.io/en/products/interactive-live-streaming/" rel="noreferrer nofollow">Agora</a> ranks third because its interactive live product combines real-time voice, video, chat, and audience promotion. Hosts can invite audience members to become co-hosts. Agora also provides SDKs, UI kits, and an app-building layer, so teams can choose between lower-level control and faster implementation.</p><p>Agora is a strong Mux alternative when the live stream behaves more like a shared room than a television channel. Common examples include creator co-streams, social audio and video, live tutoring, fan engagement, and shopping sessions with on-camera guests.</p><p>The platform ranks below Amazon IVS in this list because AWS offers a particularly clear managed split between large-scale HLS channels and real-time stages. Agora is still one of the strongest choices when global real-time communication is the core product.</p><p><strong>Where Mux is stronger:</strong> Mux is more focused on HTTP video delivery, video assets, and playback quality data. A media library that combines live and on-demand playback may map more naturally to Mux than to a real-time engagement stack.</p><p><strong>Pricing:</strong> Agora bills interactive live streaming primarily by participant minutes, with <a href="https://www.agora.io/en/pricing/interactive-live-streaming/" rel="noreferrer nofollow">pricing</a> that changes by media type and quality. Features such as recording, transcription, or advanced extensions can add separate charges. Agora currently advertises 10,000 free minutes for evaluation.</p><h3 id="4-livekit">4. LiveKit</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.40-PM-4.png" class="kg-image" alt="Top 10 Mux Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2920" height="1670"/></figure><p><strong>Best for:</strong> Engineering teams that want open-source WebRTC infrastructure with a managed cloud option.<br><br><a href="https://livekit.io/" rel="noreferrer nofollow">LiveKit</a> ranks fourth because it combines an open-source real-time media server and SDKs with a managed cloud option. Its room model works well for interactive stages, while ingress and egress services connect the room to broadcast protocols and files. LiveKit Ingress accepts RTMP, WHIP, HTTP media, and SRT, while egress can produce recordings, HLS segments, and RTMP or SRT outputs.</br></br></p><p>This makes LiveKit unusually flexible. A team can bring an OBS feed into a room, let remote guests participate through WebRTC, record a composite layout, and send the program feed to an external platform.</p><p>LiveKit ranks fourth because it offers both source access and a managed path. That is valuable for teams with data residency, network control, or customization requirements. The tradeoff is operational complexity. A self-hosted deployment with ingress, egress, storage, TURN, monitoring, and scaling is not the same as running one media server.</p><p><strong>Where Mux is stronger:</strong> Mux packages ingest, HLS delivery, video assets, and playback analytics into a simpler managed video workflow. It is the easier choice when infrastructure ownership is not a requirement.</p><p><strong>Pricing: </strong><a href="https://livekit.com/pricing" rel="noreferrer nofollow">LiveKit Cloud pricing</a> is usage based and should be modeled against room activity, bandwidth, ingress, egress, recording, and any additional services used. Self-hosting removes the managed service bill but adds compute, bandwidth, storage, observability, and engineering costs.</p><h3 id="5-fastpix">5. FastPix</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-27-at-5.16.15-PM.png" class="kg-image" alt="Top 10 Mux Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2916" height="1470"/></figure><p><strong>Best for:</strong> Teams seeking the closest API-style replacement for Mux's broadcast streaming and live-to-VOD workflow.</p><p><a href="https://fastpix.com/live-streaming" rel="noreferrer nofollow">FastPix</a> ranks fifth because it offers the closest Mux-style workflow in this list for managed broadcast streaming. It accepts RTMP, RTMPS, and SRT ingest, delivers live video through low-latency HLS, and supports DVR, clipping, simulcast, and automatic live-to-VOD. Its official product page documents a target of under eight seconds for its low-latency workflow.</p><p>The product resembles Mux more closely than the WebRTC-first platforms above it. Developers create live streams, use stream keys, receive state changes, and play an HTTP stream. That makes FastPix worth shortlisting when the migration goal is commercial or operational rather than architectural.</p><p>FastPix ranks fifth because this article gives substantial weight to two-way participation. For passive broadcast use cases, it can move much higher. Its WebRTC capability is listed as a roadmap item rather than the foundation of the current live product, so teams needing an interactive stage should evaluate another platform or a hybrid architecture.</p><p><strong>Where Mux is stronger:</strong> Mux has a longer track record, a mature playback analytics product, and a well-established live plus VOD developer workflow. Compare observability, ecosystem integrations, and regional delivery for your exact audience before switching.</p><p><strong>Pricing:</strong> FastPix publicly lists live encoding from $0.0324 per minute and delivery from $0.001 per viewer-minute. Confirm resolution tiers, storage, clipping, and volume pricing on the current FastPix product and <a href="https://fastpix.com/pricing/video-live-stream" rel="noreferrer nofollow">pricing pages</a> before procurement.</p><h3 id="6-cloudflare-stream">6. Cloudflare Stream</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-5.27.25-PM-1.png" class="kg-image" alt="Top 10 Mux Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2924" height="1658"/></figure><p><strong>Best for:</strong> Teams that want a simple managed video service attached to Cloudflare's network and billing model.</p><p><a href="https://developers.cloudflare.com/stream/stream-live/" rel="noreferrer nofollow">Cloudflare Stream</a> ranks sixth because it offers a simple managed broadcast workflow on Cloudflare's network. Stream Live accepts RTMPS or SRT input, records the stream automatically, and delivers HLS or DASH. Its player can request low-latency HLS through the <code>preferLowLatency</code> option, which Cloudflare currently labels beta.</p><p>Cloudflare also offers a separate WebRTC beta using WHIP and WHEP. The important limitation is architectural: the beta WebRTC path must use WHIP ingest with WHEP playback. Cloudflare does not currently bridge RTMP or SRT ingest to WHEP playback, or WHIP ingest to HLS and DASH, and recording and analytics are not supported in that beta path.</p><p>Cloudflare Stream ranks sixth because its standard live product is easy to understand and its pricing has few line items. It is attractive for teams that already use Cloudflare and need broadcast delivery more than participant interaction.</p><p><strong>Where Mux is stronger:</strong> Mux offers a more mature live video workflow, deeper playback analytics, and clearer integration between live streams and on-demand assets. Cloudflare's WebRTC path is still beta and separate from the standard live pipeline.</p><p><strong>Pricing:</strong> Cloudflare <a href="https://developers.cloudflare.com/stream/pricing/" rel="noreferrer nofollow">Stream charges</a> $5 per 1,000 stored minutes and $1 per 1,000 delivered minutes. Ingress, encoding, and bandwidth are included in those units. That simplicity can make early cost estimates easier, although viewer behavior and retained recordings still determine the total.</p><h3 id="7-wowza-video">7. Wowza Video</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-11.44.51-PM-1.png" class="kg-image" alt="Top 10 Mux Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2930" height="1652"/></figure><p><strong>Best for:</strong> Broadcast teams that need broad protocol support, detailed stream control, and hybrid deployment choices.</p><p><a href="https://www.wowza.com/" rel="noreferrer nofollow">Wowza Video</a> ranks seventh because it supports a broad range of streaming protocols and gives broadcast teams detailed control over live workflows. Its published technical specifications cover inputs such as RTMP, RTSP/RTP, SRT, UDP, and WebRTC, with outputs including HLS. The Wowza Video REST API controls live streams, transcoders, sources, and targets.</p><p>That breadth matters when a workflow includes encoders, cameras, contribution feeds, regional origins, or unusual protocol requirements. Wowza can fit established broadcast operations better than a narrow API product.</p><p>The platform ranks seventh because flexibility comes with more configuration. Teams should distinguish between Wowza's managed video service, its streaming engine, and its real-time products before comparing features or prices. The right choice depends heavily on who will operate the pipeline.</p><p><strong>Where Mux is stronger:</strong> Mux usually offers a simpler developer path for standard RTMP or SRT ingest, HLS playback, automatic recording, and playback analytics. A small product team may prefer that narrower surface.</p><p><strong>Pricing:</strong> Wowza Video pay-as-you-go <a href="https://www.wowza.com/pricing" rel="noreferrer nofollow">pricing</a> currently starts with streaming-hour and viewer-hour units. Wowza lists $2.50 per streaming hour and $0.10 per viewer hour for the pay-as-you-go plan, while real-time streaming and larger commitments use separate offers.</p><h3 id="8-apivideo">8. api.video</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-5.27.58-PM-1.png" class="kg-image" alt="Top 10 Mux Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2896" height="1634"/></figure><p><strong>Best for:</strong> Developers who want a straightforward live streaming API, hosted player, recording, and low-latency HLS.</p><p><a href="https://api.video/product/live-stream/" rel="noreferrer nofollow">api.video</a> ranks eighth because it packages live ingest, playback, recording, and analytics behind a focused developer API. It supports RTMPS and SRT ingest, low-latency HLS playback, and a one-hour DVR window. The company publishes an ideal latency target of about three seconds for its live workflow.</p><p>The product has a focused API-led experience. It suits webinars, events, publishers, and embedded live video where participants do not need to exchange media in real time. Recording a stream into an on-demand asset also makes it a plausible Mux alternative for teams that want a familiar live-to-VOD pattern.</p><p>api.video ranks eighth because it does not solve the interactive stage problem that drives the top of this list. For a conventional broadcast, however, its simplicity may matter more than rank.</p><p><strong>Where Mux is stronger:</strong> Mux offers a more established video data and playback quality ecosystem, plus a broad set of tooling around delivery and assets. Compare analytics depth and player requirements, not only ingest and playback.</p><p><strong>Pricing:</strong> <a href="https://api.video/pricing/" rel="noreferrer nofollow">api.video pricing</a> uses storage and delivery units, with live encoding included. Public rates currently show storage from $0.00285 per minute and delivery from $0.0017 per minute, subject to region, volume, and product terms.</p><h3 id="9-100ms">9. 100ms</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.31.12-PM-5.png" class="kg-image" alt="Top 10 Mux Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2910" height="1656"/></figure><p><strong>Best for:</strong> Role-based live experiences that combine an interactive stage with WebRTC or HLS audiences.</p><p><a href="https://www.100ms.live/" rel="noreferrer nofollow">100ms</a> Ranks ninth because its rooms, roles, and templates give developers a structured way to control who can publish, subscribe, or moderate. Its live streaming documentation describes three audience paths: a full-duplex WebRTC stage, receive-only WebRTC viewers, and off-stage HLS viewers. A role change can move a participant from the audience to the stage.</p><p>That model fits webinars, live classes, fan experiences, auctions, and creator events. It also makes the scale and latency tradeoff explicit: use WebRTC where interaction matters, and HLS where audience reach matters more.</p><p>100ms ranks ninth, but it is not a weak product. The ordering reflects this article's weighting of API fit, ecosystem, deployment choice, and price transparency for teams starting from Mux. Product teams already aligned with 100ms roles and templates may reasonably rank it above several broadcast-first services.</p><p><strong>Where Mux is stronger:</strong> Mux is more focused on passive video delivery, live-to-VOD assets, and playback analytics. If no viewer ever becomes a publisher, the room and role model may be unnecessary.</p><p><strong>Pricing:</strong> <a href="https://www.100ms.live/pricing" rel="noreferrer nofollow">100ms pricing</a> currently includes 10,000 streaming minutes per month, followed by viewer-minute billing that starts at $0.0012 for the listed streaming tier. Interactive conferencing, recording, transcription, and other features use additional units.</p><h3 id="10-ant-media-server">10. Ant Media Server</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-5.28.24-PM-1.png" class="kg-image" alt="Top 10 Mux Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2924" height="1660"/></figure><p><strong>Best for:</strong> Teams that need self-hosting, private infrastructure, edge deployment, or a broad protocol gateway.</p><p><a href="https://antmedia.io/" rel="noreferrer nofollow">Ant Media Server</a> ranks tenth because it combines self-hosted deployment with support for WebRTC, WHIP, WHEP, RTMP, RTSP, SRT, HLS, LL-HLS, DASH, and CMAF. Its WebRTC publishing documentation describes approximately 0.5-second real-time streaming under suitable conditions.</p><p>The platform can run in a team's own environment or through marketplace and managed options. That control is valuable for regulated workloads, private networks, custom edge topologies, and teams that need to combine broadcast and real-time protocols.</p><p>Ant Media ranks tenth because self-managed media infrastructure carries operational responsibility. High availability, autoscaling, TURN, certificates, monitoring, storage, upgrades, and incident response must all be assigned to someone. For teams that need this control, those responsibilities may be acceptable.</p><p><strong>Where Mux is stronger:</strong> Mux removes most media infrastructure operations and provides a cohesive managed workflow. It is a better fit when the team wants an API outcome rather than ownership of the streaming stack.</p><p><strong>Pricing:</strong> <a href="https://antmedia.io/pricing/" rel="noreferrer nofollow">Ant Media pricing</a> lists usage-based and monthly self-hosted licence options, including $0.24 per hour and $109 per month on the current page. Infrastructure, bandwidth, storage, support, and marketplace charges may be separate.</p><h2 id="live-streaming-api-pricing-compared">Live Streaming API Pricing Compared</h2><p>Pricing pages rarely use the same unit. One vendor charges per input minute, another per viewer-minute, another per participant hour, and another bundles encoding into delivery. The correct comparison is the estimated cost of one complete event.</p><p>The following figures were reviewed on July 27, 2026. Treat them as a starting point and verify them again before publishing a budget or signing a contract.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Platform</th>
<th>Main public billing model</th>
<th>Useful public reference</th>
<th>Cost often missed</th>
</tr>
</thead>
<tbody>
<tr>
<td>Mux</td>
<td>Live input, delivery, storage, and other usage</td>
<td>$20 monthly usage credit; delivery base from $0.0008 per minute; Plus live input starts at $0.025 per minute at 720p</td>
<td>Resolution, recordings, storage, and delivery volume</td>
</tr>
<tr>
<td>VideoSDK</td>
<td>Participant minutes by role and quality; separate HLS and RTMP units</td>
<td>$20 one-time balance; HD ILS listed at $0.004 per speaker-minute and $0.002 per viewer-minute</td>
<td>HLS encoding, recording, transcription, and restreaming</td>
</tr>
<tr>
<td>Amazon IVS</td>
<td>Channel input, viewer output, or real-time participant hours</td>
<td>Regional and resolution-based rates</td>
<td>Recording, monitoring, data transfer, and adjacent AWS services</td>
</tr>
<tr>
<td>Agora</td>
<td>Participant minutes by media quality</td>
<td>10,000 evaluation minutes currently advertised</td>
<td>Recording, transcription, extensions, and quality tiers</td>
</tr>
<tr>
<td>LiveKit</td>
<td>Managed usage or self-hosted infrastructure</td>
<td>Architecture-specific</td>
<td>Egress, recording, bandwidth, storage, and operations</td>
</tr>
<tr>
<td>FastPix</td>
<td>Live encoding and viewer delivery</td>
<td>$0.0324 per encoding minute; $0.001 per viewer-minute</td>
<td>Storage, DVR, clipping, and volume tiers</td>
</tr>
<tr>
<td>Cloudflare Stream</td>
<td>Stored minutes and delivered minutes</td>
<td>$5 per 1,000 stored minutes; $1 per 1,000 delivered minutes</td>
<td>Long recording retention and high watch time</td>
</tr>
<tr>
<td>Wowza Video</td>
<td>Streaming hours and viewer hours</td>
<td>$2.50 per streaming hour; $0.10 per viewer hour on pay as you go</td>
<td>Transcoding, recording, support, and product edition</td>
</tr>
<tr>
<td>api.video</td>
<td>Storage and delivery</td>
<td>From $0.00285 per stored minute and $0.0017 per delivered minute</td>
<td>Geography, retained recordings, and volume</td>
</tr>
<tr>
<td>100ms</td>
<td>Streaming viewer-minutes plus feature units</td>
<td>10,000 included minutes; then from $0.0012 per viewer-minute</td>
<td>Interactive minutes, recording, and transcription</td>
</tr>
<tr>
<td>Ant Media Server</td>
<td>Usage-based or self-hosted licence</td>
<td>$0.24 per hour or $109 per month on listed options</td>
<td>Compute, bandwidth, storage, scaling, and operations</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>For a realistic estimate, calculate at least these five inputs:</p><ol><li>Publisher minutes by resolution.</li><li>Average and peak concurrent viewers.</li><li>Average watch time, not only event duration.</li><li>Recording, storage, and retention.</li><li>Restreaming, transcription, analytics, and support.</li></ol><p>A platform with a higher media rate can still be cheaper if it replaces a second service or reduces engineering work. A low delivery price can still become expensive when every viewer watches for a long time. Compare the whole system.</p><h2 id="what-is-the-best-mux-alternative-for-live-streaming">What Is the Best Mux Alternative for Live Streaming?</h2><p>The best Mux alternative depends on the interaction model:</p><ul><li><strong>Choose VideoSDK</strong> when viewers need to become hosts or co-hosts and the application needs explicit real-time roles.</li><li><strong>Choose Amazon IVS</strong> when your stack is already on AWS and you want both managed HLS channels and real-time stages.</li><li><strong>Choose Agora</strong> when global mobile real-time engagement is the primary product.</li><li><strong>Choose LiveKit</strong> when open-source infrastructure or self-hosting is a firm requirement.</li><li><strong>Choose FastPix</strong> when you want the closest Mux-like API pattern for RTMPS or SRT ingest, LL-HLS playback, DVR, and live-to-VOD.</li><li><strong>Choose Cloudflare Stream</strong> when simple delivery pricing and the Cloudflare network matter more than an integrated interactive stage.</li><li><strong>Choose Wowza</strong> when protocol breadth and broadcast control outweigh implementation simplicity.</li><li><strong>Choose api.video</strong> when a focused live API, player, recording, and LL-HLS cover the requirement.</li><li><strong>Choose 100ms</strong> when a role-based WebRTC stage and hybrid audience architecture fit your product model.</li><li><strong>Choose Ant Media Server</strong> when deployment control, private infrastructure, or edge operation is non-negotiable.</li><li><strong>Keep Mux</strong> when passive HLS, automatic recording, video asset workflows, and playback analytics already solve the problem.</li></ul><p>The closest feature-for-feature substitute is not always the best business choice. A team leaving Mux because viewers need to speak should compare interactive architectures. A team leaving because of cost should first model its actual input, delivery, storage, and watch-time pattern.</p><h2 id="how-to-migrate-to-a-mux-alternative-safely">How to Migrate to a Mux Alternative Safely</h2><p>Do not begin migration by replacing every API call. Begin by mapping the product responsibilities.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Current Mux concept</th>
<th>Broadcast-oriented replacement</th>
<th>Interactive replacement</th>
</tr>
</thead>
<tbody>
<tr>
<td>Live Stream object</td>
<td>Live stream or channel</td>
<td>Room, stage, or session</td>
</tr>
<tr>
<td>Stream key</td>
<td>Stream key or ingest token</td>
<td>Participant token or publish permission</td>
</tr>
<tr>
<td>RTMPS or SRT ingest</td>
<td>RTMPS, SRT, or protocol-specific ingest</td>
<td>WebRTC SDK, WHIP, or bridged RTMP ingress</td>
</tr>
<tr>
<td>Playback ID</td>
<td>HLS or DASH playback URL</td>
<td>Room ID, subscriber token, or audience playback URL</td>
</tr>
<tr>
<td>Live recording</td>
<td>Automatic live-to-VOD asset</td>
<td>Composite or participant recording</td>
</tr>
<tr>
<td>Webhooks</td>
<td>Stream lifecycle webhooks</td>
<td>Room, participant, role, and recording events</td>
</tr>
<tr>
<td>Playback analytics</td>
<td>Player and QoE analytics</td>
<td>Session, participant, and media quality telemetry</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>Use an eight-step migration:</p><ol><li><strong>Inventory the current workflow.</strong> Record ingest protocols, resolutions, latency settings, signed playback, recordings, webhooks, analytics, players, and downstream jobs.</li><li><strong>Define the required audience behavior.</strong> Separate passive viewers, receive-only real-time viewers, stage participants, moderators, and external restream destinations.</li><li><strong>Build a cost model.</strong> Use real event duration, average watch time, peak concurrency, retention, and feature usage.</li><li><strong>Create a compatibility layer.</strong> Keep vendor-specific identifiers behind your own service interface where practical. This reduces application-wide changes.</li><li><strong>Run the new path in parallel.</strong> Send the same source to both providers where contracts and architecture allow, or mirror representative test events.</li><li><strong>Test failure conditions.</strong> Cover publisher disconnects, reconnect windows, token expiry, region failure, player fallback, recording failure, and webhook retries.</li><li><strong>Move a small audience first.</strong> Use feature flags or traffic allocation to compare startup time, buffering, latency, error rates, and support volume.</li><li><strong>Keep rollback available.</strong> Preserve the Mux path until the new provider has passed production events and all recordings and downstream workflows reconcile.</li></ol><p>If your target is interactive, migration is an architecture change, not a vendor swap. RTMP plus HLS identifiers do not map one-to-one to rooms, participant tokens, publish permissions, and role changes. Plan product and security work accordingly.</p><h2 id="live-streaming-definitions">Live Streaming Definitions</h2><blockquote><strong>WebRTC:</strong> A W3C standard and related protocol stack for real-time audio, video, and data between endpoints. It is commonly used for interactive stages and calls. See the <a href="https://www.w3.org/TR/webrtc/">W3C WebRTC Recommendation</a>.</blockquote><blockquote><strong>HLS:</strong> HTTP Live Streaming, an adaptive bitrate streaming protocol that divides media into HTTP-delivered playlists and segments. The base protocol is defined in <a href="https://www.rfc-editor.org/rfc/rfc8216">RFC 8216</a>.</blockquote><blockquote><strong>LL-HLS:</strong> Low-Latency HLS, an extension of HLS that reduces delay through partial segments, blocking playlist reloads, and related delivery techniques. Apple documents the workflow in its <a href="https://developer.apple.com/documentation/http-live-streaming/enabling-low-latency-http-live-streaming-hls">LL-HLS guidance</a>.</blockquote><blockquote><strong>RTMP and RTMPS:</strong> Common contribution protocols used by encoders to publish a live feed. RTMPS adds TLS encryption.</blockquote><blockquote><strong>SRT:</strong> Secure Reliable Transport, a contribution protocol designed for reliable low-latency transport over unpredictable networks.</blockquote><blockquote><strong>WHIP and WHEP:</strong> HTTP-based signaling protocols used for WebRTC ingest and WebRTC egress. WHIP publishes a feed; WHEP receives one.</blockquote><blockquote><strong>Viewer-minute:</strong> One viewer watching for one minute. A 60-minute event with 1,000 average viewers creates 60,000 viewer-minutes.</blockquote><blockquote><strong>Interactive live streaming:</strong> A live architecture in which selected audience members can publish audio or video, often through role changes and a WebRTC stage.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>There is no universal best Mux alternative. The correct choice depends on whether the audience watches, participates, or does both.</li><li>VideoSDK is the strongest fit in this ranking for an interactive stage with explicit host, co-host, and audience modes.</li><li>FastPix is the closest Mux-style alternative for a managed RTMPS or SRT to LL-HLS and live-to-VOD workflow.</li><li>Amazon IVS provides a useful managed split between low-latency channels and real-time stages.</li><li>LiveKit and Ant Media are the main options here when open-source or self-hosted control matters.</li><li>Cloudflare Stream has a WebRTC beta, but it is currently separate from its standard RTMPS or SRT to HLS pipeline.</li><li>Pricing must be modeled per event because vendors bill different units.</li><li>Staying with Mux is rational when passive HLS, automatic live-to-VOD, and playback analytics already meet the requirement.</li></ul><h2 id="conclusion">Conclusion</h2><p>Choosing a Mux alternative begins with one decision: does your live audience only watch, or must some viewers become participants?</p><p>For passive broadcast, compare FastPix, Cloudflare Stream, api.video, Wowza, and Mux on delivery, recording, analytics, and total event cost. For real-time participation, compare VideoSDK, Amazon IVS Stages, Agora, LiveKit, 100ms, and Ant Media on role control, SDK fit, moderation, scale, and operational responsibility.</p><p>VideoSDK ranks first for the interactive use case because its live model makes stage participation explicit and supports a practical path from viewer to speaker. You can <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-react-ils">review the current React ILS quickstart</a> or <a href="https://app.videosdk.live/login">create a VideoSDK account</a> to test the role flow with the one-time free balance.</p><p>Do not migrate because a comparison table has more checkmarks. Run a production-shaped pilot, measure the metrics your users feel, and keep a rollback path until the new workflow proves itself.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-best-mux-alternative-in-2026">What is the best Mux alternative in 2026?</h3><p>VideoSDK is the best Mux alternative in this ranking when the application needs interactive live streaming and real-time role changes. Amazon IVS is a strong AWS-native option, while FastPix is the closest fit for a Mux-like RTMPS or SRT to LL-HLS workflow. Mux may remain best for passive HLS and live-to-VOD.</p><h3 id="is-there-a-cheaper-alternative-to-mux">Is there a cheaper alternative to Mux?</h3><p>Possibly, but "cheaper" depends on your traffic pattern. Cloudflare Stream has simple stored-minute and delivered-minute pricing. FastPix and api.video publish low delivery rates. Interactive products charge by participant role or quality. Model publishers, average viewers, watch time, recording, storage, and add-ons before deciding.</p><h3 id="is-there-a-free-or-open-source-mux-alternative">Is there a free or open-source Mux alternative?</h3><p>LiveKit provides an open-source real-time media stack, and Ant Media Server offers self-hosted deployment options. Self-hosting does not make streaming free. You still pay for compute, bandwidth, storage, TURN, monitoring, maintenance, and engineering time.</p><h3 id="which-mux-alternative-has-the-lowest-latency">Which Mux alternative has the lowest latency?</h3><p>WebRTC-based products such as VideoSDK, Amazon IVS Real-Time Streaming, Agora, LiveKit, 100ms, and Ant Media are designed for real-time or sub-second interaction. LL-HLS products usually trade more delay for simpler large-scale playback. Vendor latency claims are not directly comparable without testing the same regions, devices, and network conditions.</p><h3 id="can-mux-and-videosdk-be-used-together">Can Mux and VideoSDK be used together?</h3><p>Yes. A team can use VideoSDK for the interactive WebRTC stage and send a composed program feed through VideoSDK's RTMP livestream output to a Mux RTMPS ingest endpoint. Mux can then handle HLS delivery, recording, and playback analytics for the broadcast audience.</p><h3 id="when-should-i-keep-mux-instead-of-switching">When should I keep Mux instead of switching?</h3><p>Keep Mux when your audience is passive, HLS latency is acceptable, automatic live-to-VOD matters, and the existing playback analytics and operational workflow are reliable. Replacing a working pipeline creates migration risk, so switch only when a specific requirement or cost model justifies it.</p><h3 id="how-can-i-migrate-from-mux-without-downtime">How can I migrate from Mux without downtime?</h3><p>Run both providers in parallel for representative events, keep vendor identifiers behind a compatibility layer, move a small share of traffic first, and preserve the Mux path as rollback. Validate playback, webhooks, recordings, security, analytics, and downstream jobs before completing the cutover.</p><h2 id="further-reading">Further Reading</h2><ul><li><a href="https://www.videosdk.live/blog/hls-vs-webrtc">HLS vs WebRTC: What Is the Difference?</a></li><li><a href="https://www.videosdk.live/blog/rtmp-vs-hls">RTMP vs HLS: Which Streaming Protocol Should You Use?</a></li><li><a href="https://www.videosdk.live/blog/integrate-rtmp-livestream-in-react-js">How to Integrate RTMP Livestreaming in React</a></li><li><a href="https://www.videosdk.live/blog/implement-hls-player-in-react-js/">How to Implement an HLS Player in React</a></li><li><a href="https://videosdk.live/developer-hub/hls/live-streaming-api">Live Streaming API Developer Hub</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Top 10 Ant Media Alternatives for Live Streaming APIs in 2026]]></title><description><![CDATA[Compare ten Ant Media alternatives for interactive and broadcast live streaming APIs, with 2026 pricing, trade-offs, rankings, and migration guidance.]]></description><link>https://www.videosdk.live/blog/ant-media-alternatives</link><guid isPermaLink="false">6a63726bb3240feb748c8bc6</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Sat, 25 Jul 2026 10:54:59 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/ChatGPT-Image-Jul-25--2026--01_18_31-AM.webp" medium="image"/><content:encoded><![CDATA[<blockquote>Choose VideoSDK when you need a managed interactive Live Streaming API with dynamic host and viewer roles and no media-server operations. Choose Red5 Pro, Wowza Streaming Engine, or OvenMediaEngine when self-hosting and protocol control are mandatory. Choose Mux for one-way HLS broadcasts. The common mistake is comparing these architectures as though they were interchangeable.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/ChatGPT-Image-Jul-25--2026--01_18_31-AM.webp" alt="Top 10 Ant Media Alternatives for Live Streaming APIs in 2026"/><p>The best <strong>Ant Media alternative</strong> depends on one architectural decision: <br>Do you want to operate a media server, or consume a managed Live Streaming API? VideoSDK ranks first in this guide for managed interactive streams, not as a drop-in server binary.</br></p><p>This comparison evaluates 10 products only for live streaming. Video conferencing, surveillance, IP-camera management, and Ant Media's other verticals are excluded unless a capability directly supports one-to-many or interactive broadcasting.</p><p><strong>Evaluation disclosure:</strong> Every capability and public price in this article was checked against official product pages or documentation on <strong>July 24, 2026</strong>. The ranking is a documentation-based expert evaluation, not a synthetic or hands-on performance benchmark.</p><h2 id="what-is-an-ant-media-alternative">What Is an Ant Media Alternative?</h2><p><strong>An </strong><a href="https://antmedia.io/" rel="noreferrer nofollow"><u>Ant Media</u></a><strong> alternative is defined as a Live Streaming API, SDK, or media server that can replace Ant Media's ingest, real-time delivery, broadcast, recording, or stream-management functions.</strong></p><p>An Ant Media alternative works by receiving live audio and video, routing or transcoding that media, and delivering it through <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC,</a> <a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer">HLS</a>, LL-HLS, or another playback path.</p><p>Ant Media itself supports WebRTC, <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a>, <a href="https://www.videosdk.live/developer-hub/rtmp/implementing-srt-streaming-developers-guide" rel="noreferrer">SRT</a>, <a href="https://www.videosdk.live/blog/what-is-rtsp-protocol" rel="noreferrer">RTSP</a>, <a href="https://docs.videosdk.live/server-sdk/reference/whip" rel="noreferrer">WHIP</a>, HLS, LL-HLS, CMAF, and DASH. Its <a href="https://antmedia.io/pricing/" rel="noreferrer nofollow"><u>pricing page</u></a> lists self-hosted Enterprise licenses alongside public-cloud marketplace deployment.</p><p>Ant Media's documentation describes about 0.5-second WebRTC delivery under standard conditions. Its <a href="https://docs.antmedia.io/faq/" rel="noreferrer nofollow"><u>latency FAQ</u></a> also documents higher latency when HLS replaces WebRTC for audience playback.</p><p>VideoSDK addresses the managed side of this requirement. Its <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/introduction">Interactive Live Streaming documentation</a> separates real-time host and promoted-guest participation from HLS delivery for larger receive-only audiences.</p><p>That distinction prevents an expensive category mistake. A managed API removes server operations, while a self-hosted server provides infrastructure control but leaves capacity, updates, observability, and incident response with your team.</p><h2 id="why-look-for-an-ant-media-alternative">Why Look for an Ant Media Alternative?</h2><p><strong>Teams usually replace Ant Media because their preferred operating model, audience path, or cost structure has changed.</strong></p><p>Common reasons include:</p><ul><li><strong>Reducing media-server operations:</strong> A managed API can remove cluster provisioning, upgrades, autoscaling, <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a> capacity, monitoring, and incident response from the application team's workload.</li><li><strong>Adding in-app interaction faster:</strong> Products such as VideoSDK, Agora, 100ms, and ZEGOCLOUD provide SDK-level roles, stage promotion, chat, and event primitives.</li><li><strong>Changing audience economics:</strong> A WebRTC stage plus an HLS audience can be more practical than routing every passive viewer through the same real-time path.</li><li><strong>Keeping stronger infrastructure control:</strong> Red5 Pro, Wowza Streaming Engine, LiveKit, and OvenMediaEngine fit teams that need private networking, custom deployment, or source-level control.</li><li><strong>Improving broadcast tooling:</strong> Mux, Wowza, Amazon IVS, and Dolby OptiView can be stronger when encoder ingest, playback analytics, large receive-only audiences, or broadcast workflows dominate.</li></ul><p>An alternative is therefore not automatically “better” than Ant Media. It is better only when its deployment model and media path match the workload you are actually building.</p><h2 id="how-we-ranked-these-ant-media-alternatives">How We Ranked These Ant Media Alternatives</h2><p><strong>This ranking scores Live Streaming API fit, not each vendor's wider communication or video portfolio.</strong></p><p>Each product received a weighted editorial score from current documentation. No vendor received points for an unverified latency claim, an unrelated conferencing feature, or a sales-page superlative.</p>
<!--kg-card-begin: html-->
<table><thead><tr><th>Evaluation criterion</th><th align="right">Weight</th><th>What earned a higher score</th></tr></thead><tbody><tr><td>Live latency and interaction</td><td align="right">25%</td><td>WebRTC or comparable real-time delivery, role changes, and audience participation</td></tr><tr><td>API and SDK experience</td><td align="right">20%</td><td>Clear quickstarts, maintained SDKs, server APIs, webhooks, and sample applications</td></tr><tr><td>Deployment and data control</td><td align="right">15%</td><td>Managed availability, self-hosting choice, regional controls, or offline deployment</td></tr><tr><td>Streaming workflow coverage</td><td align="right">15%</td><td>Useful ingest, playback, recording, restreaming, and adaptive delivery options</td></tr><tr><td>Scale and operations</td><td align="right">10%</td><td>Published limits, monitoring, network adaptation, and production support</td></tr><tr><td>Pricing clarity</td><td align="right">10%</td><td>Public rates or understandable billing units with practical trial access</td></tr><tr><td>Migration suitability</td><td align="right">5%</td><td>A credible path from Ant Media's rooms, streams, protocols, and APIs</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>The score is a selection aid, not laboratory data. Before signing a contract, run the same encoded source through shortlisted providers and measure latency, first-frame time, freeze rate, and cost.</p><p>Pricing snapshots use public US-dollar rates available on July 24, 2026. Regional delivery, resolution, recording, support, storage, transcoding, and committed-use charges can change the final bill.</p><h2 id="ant-media-alternatives-comparison">Ant Media Alternatives Comparison</h2><p><strong>The strongest shortlist contains different product types because no managed API, commercial server, or open-source project wins every Ant Media migration.</strong></p>
<!--kg-card-begin: html-->
<table><thead><tr><th align="right">Rank</th><th>Ant Media alternative</th><th>Delivery and deployment</th><th>Best for</th><th align="right">Editorial score</th></tr></thead><tbody><tr><td align="right">1</td><td>VideoSDK</td><td>Managed WebRTC ILS plus HLS and RTMP workflows</td><td>Developer-led interactive streaming</td><td align="right">89/100</td></tr><tr><td align="right">2</td><td>Agora</td><td>Managed real-time network and broadcast extensions</td><td>Global social and commerce apps</td><td align="right">87/100</td></tr><tr><td align="right">3</td><td>LiveKit</td><td>Open-source SFU or managed cloud, with ingress and egress</td><td>Portability and custom media products</td><td align="right">84/100</td></tr><tr><td align="right">4</td><td>Amazon IVS</td><td>Managed real-time stages and low-latency channels</td><td>AWS-native interactive events</td><td align="right">82/100</td></tr><tr><td align="right">5</td><td>Red5 Pro</td><td>Commercial self-hosted WebRTC media server</td><td>Direct server replacement and protocol control</td><td align="right">80/100</td></tr><tr><td align="right">6</td><td>100ms</td><td>Managed WebRTC stage plus HLS audience delivery</td><td>Webinars, classes, and hybrid audiences</td><td align="right">79/100</td></tr><tr><td align="right">7</td><td>ZEGOCLOUD</td><td>Managed interactive and CDN live modes</td><td>Social live, gifting, and co-hosting</td><td align="right">78/100</td></tr><tr><td align="right">8</td><td>Wowza</td><td>Managed cloud or private streaming engine</td><td>Broadcast operations and mixed inputs</td><td align="right">77/100</td></tr><tr><td align="right">9</td><td>Mux</td><td>Managed RTMP ingest and HLS delivery</td><td>API-first one-way broadcasts and analytics</td><td align="right">74/100</td></tr><tr><td align="right">10</td><td>OvenMediaEngine</td><td>Open-source self-hosted WebRTC and LL-HLS server</td><td>Infrastructure teams avoiding commercial server fees</td><td align="right">73/100</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>VideoSDK leads for a managed, in-app interactive experience. Red5 Pro or OvenMediaEngine is a closer architectural match when your requirement is an installable server under your operational control.</p><p>The table also exposes two different latency markets. WebRTC products prioritize interaction, while HLS products prioritize economical, device-compatible distribution to a larger receive-only audience.</p><h2 id="ant-media-vs-alternatives-pricing-comparison">Ant Media vs. Alternatives: Pricing Comparison</h2><p><strong>Ant Media pricing is instance-based, while most managed alternatives meter participants, viewers, stream hours, delivery minutes, or bandwidth.</strong></p>
<!--kg-card-begin: html-->
<table><thead><tr><th>Platform</th><th>Public pricing snapshot checked July 24, 2026</th><th>Primary billing model</th><th>Cost factor teams often miss</th></tr></thead><tbody><tr><td>Ant Media Server</td><td>Enterprise: $109 per instance/month on monthly billing, $89 per instance/month on annual billing, $0.24 per instance-hour, or $2,799 perpetual</td><td>Server license plus infrastructure</td><td>Compute, bandwidth, database, load balancing, monitoring, support, and engineering operations</td></tr><tr><td>VideoSDK</td><td>VideoSDK's pay-as-you-go pricing is $0.001 per participant-minute for audio calls, $0.004 per participant-minute for video calls, and $0.002 per viewer-minute for live streaming and a $20 free credit for new accounts.</td><td>Usage-based managed API</td><td>Real-time participants, passive audience delivery, recording, transcription, and restreaming may use different units</td></tr><tr><td>Agora</td><td>First 10,000 monthly minutes free; audio starts at $0.99 and HD video at $3.99 per 1,000 participant minutes</td><td>Participant minutes plus add-ons</td><td>Recording, analytics, Media Push, and forced cloud proxy can add separate charges</td></tr><tr><td>LiveKit Cloud</td><td>Build includes 5,000 WebRTC minutes and 50 GB downstream; Ship starts at $50/month and includes 150,000 WebRTC minutes</td><td>Connection minutes, downstream transfer, ingress, and egress</td><td>Self-hosting the SFU does not make ingress, egress, recording, global routing, or operations free</td></tr><tr><td>Amazon IVS</td><td>Real-Time Streaming is billed by connected participant hours; Low-Latency Streaming bills input and viewer output by resolution and region</td><td>Participant hours or channel input/output</td><td>Composition, chat, recording, data transfer, and regional viewer mix</td></tr><tr><td>Red5 Pro</td><td>Developer Pro $29.99/month, Startup $119/month, Growth Pro $299/month; enterprise plans are higher</td><td>Software license per deployment tier</td><td>Cloud infrastructure, bandwidth, support, operations, and some mobile SDK costs</td></tr><tr><td>100ms</td><td>10,000 monthly streaming minutes and 1,000 encoding minutes included; additional SD streaming starts at $0.0012 per viewer minute</td><td>Viewer, participant, encoding, recording, and output minutes</td><td>HLS encoding, recording, transcription, and RTMP output are separately metered</td></tr><tr><td>ZEGOCLOUD</td><td>Live Streaming headline rate starts at $0.39 per 1,000 minutes</td><td>Host, co-host, and viewer usage with feature-specific billing</td><td>Interactive mode, recording, messaging, and regional configuration can change the total</td></tr><tr><td>Wowza</td><td>Wowza Video: $2.50 per stream hour and $0.10 per viewer hour; Streaming Engine Basic Monthly: $195 for the first instance</td><td>Cloud usage or self-hosted server license</td><td>Real-time streaming at scale, premium support, CDN, storage, and additional instances</td></tr><tr><td>Mux</td><td>100,000 delivery minutes included monthly; live input starts at $0.025/minute for 720p Plus quality, with delivery from $0.0008/minute after included usage</td><td>Input, storage, delivery, and workflow add-ons</td><td>Simulcasting, DRM, live captions, storage, resolution, and preloaded-but-unwatched segments</td></tr><tr><td>OvenMediaEngine</td><td>AGPL-3.0 community software; commercial licensing available on request</td><td>Open-source software plus infrastructure</td><td>Engineering time, bandwidth, compute, monitoring, security, and on-call ownership</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>Do not compare these headline rates directly. Normalize each platform against the same event:</p><pre><code class="language-text">monthly_cost =
  host_or_participant_usage
  + passive_viewer_delivery
  + encoding_or_composition
  + recording_and_storage
  + restreaming_and_transcription
  + support
  + infrastructure_and_egress
  + estimated_operations_cost
</code></pre><p>For example, price one 60-minute event with one host, five co-hosts, 5,000 viewers, 720p playback, recording, captions, and one RTMP destination. That model exposes whether a low headline rate is actually relevant to your architecture.</p><h2 id="10-best-ant-media-alternatives-in-2026">10 Best Ant Media Alternatives in 2026</h2><p><strong>These ten Ant Media alternatives cover managed interaction, broadcast-scale delivery, commercial self-hosting, and open-source infrastructure.</strong></p><h3 id="1-videosdk-best-overall-managed-ils-api">1. VideoSDK: Best Overall Managed ILS API</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.29.39-PM-3.png" class="kg-image" alt="Top 10 Ant Media Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2906" height="1660"/></figure><p><strong>VideoSDK is the leading choice when developers want embedded interactive live streaming without operating Ant Media clusters, load balancers, databases, and media nodes.</strong></p><p><a href="https://videosdk.live/interactive-live-streaming">VideoSDK Interactive Live Streaming</a> uses room-based WebRTC media with host and receive-only participant permissions. Viewers can be promoted, while chat, polls, reactions, recording, captions, and RTMP restreaming can stay inside one product surface.</p><p>The React documentation identifies <code>SEND_AND_RECV</code> for hosts and <code>RECV_ONLY</code> for audiences. Its <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-react-ils">current ILS quickstart</a> also shows <code>changeMode()</code> for switching participant roles.</p><p><strong>Why it ranks first:</strong> VideoSDK combines a managed media layer, client SDKs, interaction primitives, HLS delivery, and RTMP output without requiring teams to administer a streaming server.</p><p><strong>Best for:</strong> Live shopping, auctions, webinars, social broadcasts, interactive classrooms, expert sessions, and products where selected viewers may join the stage.</p><p><strong>Pricing:</strong> VideoSDK currently provides a prepaid wallet and a $20 starting balance. &nbsp;<a href="https://www.videosdk.live/pricing"><u>VideoSDK's pay-as-you-go pricing</u></a>&nbsp;is&nbsp;<strong>$0.001</strong>&nbsp;per participant-minute for audio calls,&nbsp;<strong>$0.004</strong>&nbsp;per participant-minute for video calls, and&nbsp;<strong>$0.002</strong>&nbsp;per viewer-minute for live streaming.</p><p><strong>Watch out for:</strong> VideoSDK is not an on-premises Ant Media binary replacement. Teams requiring air-gapped deployment, arbitrary server modules, or direct infrastructure tuning should shortlist Red5 Pro, Wowza Streaming Engine, or OvenMediaEngine.</p><p><strong>Migration note:</strong> Replace Ant Media broadcast IDs with VideoSDK room IDs, then map publishers to <code>SEND_AND_RECV</code> and passive WebRTC viewers to <code>RECV_ONLY</code>. Validate HLS audience economics separately.</p><p>Use the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/authentication-and-token">VideoSDK authentication guide</a> to generate tokens server-side. The snippet demonstrates the developer surface without pretending a complete production application fits in one block.</p><h3 id="2-agora-best-for-global-rtc-programs">2. Agora: Best for Global RTC Programs</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.26-PM-3.png" class="kg-image" alt="Top 10 Ant Media Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2920" height="1662"/></figure><p><strong>Agora is a strong Ant Media alternative when a global application needs mature real-time SDKs, network routing, audience role changes, and optional CDN broadcast.</strong></p><p><a href="https://www.agora.io/en/products/interactive-live-streaming/" rel="noreferrer nofollow">Agora</a>'s Interactive Live Streaming product supports multiple hosts, audience promotion, chat, reactions, gifting, extensions, and quality monitoring across its managed real-time network.</p><p><strong>Why it ranks second:</strong> Agora offers broad platform coverage and mature global real-time infrastructure. Its Media Push, Media Pull, recording, analytics, and proxy options cover demanding streaming programs.</p><p><strong>Best for:</strong> International social live apps, creator platforms, live commerce, gaming communities, and organizations already standardized on Agora's RTC and messaging services.</p><p><strong>Pricing:</strong> The <a href="https://www.agora.io/en/pricing/interactive-live-streaming/" rel="noreferrer nofollow"><u>interactive live streaming pricing</u></a> lists 10,000 free monthly minutes, with audio from $0.99 and HD video from $3.99 per 1,000 participant minutes.</p><p><strong>Watch out for:</strong> Add-ons such as recording, advanced analytics, Media Push, and forced cloud proxy carry separate charges. Model a complete stream rather than comparing one headline rate.</p><p><strong>Migration note:</strong> Map Ant Media publishers and players to Agora host and audience roles. If passive audience scale requires a CDN, test Agora Media Push and include its added delay and cost.</p><p>Agora scores below VideoSDK here because the VideoSDK path is more focused for a developer seeking a managed ILS replacement with fewer adjacent services to price separately.</p><h3 id="3-livekit-best-for-open-source-portability">3. LiveKit: Best for Open-Source Portability</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.40-PM-3.png" class="kg-image" alt="Top 10 Ant Media Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2920" height="1670"/></figure><p><a href="https://livekit.com/" rel="noreferrer nofollow"><u>LiveKit</u></a><strong> fits teams wanting one open-source WebRTC foundation that can run independently or move to a managed cloud without redesigning every client.</strong></p><p>LiveKit's Ingress service accepts sources such as RTMP, WHIP, and SRT. Its <a href="https://docs.livekit.io/transport/media/ingress-egress/egress/" rel="noreferrer nofollow"><u>Egress service</u></a> records rooms or sends composed output to RTMP destinations and HLS storage.</p><p><strong>Why it ranks third:</strong> Open-source availability reduces platform lock-in, while LiveKit Cloud provides global media routing, analytics, managed ingress, and managed egress for teams avoiding SFU operations.</p><p><strong>Best for:</strong> Products needing source-code access, custom media processing, cloud-to-self-hosted portability, or one WebRTC platform shared by streaming and real-time application features.</p><p><strong>Pricing:</strong> LiveKit Cloud <a href="https://livekit.com/pricing" rel="noreferrer nofollow"><u>pricing page</u></a> meters WebRTC connection minutes, downstream transfer, ingress, and egress. The Build plan includes 5,000 WebRTC minutes and 50 GB of downstream transfer; the Ship plan starts at $50 per month and includes 150,000 WebRTC minutes.</p><p><strong>Watch out for:</strong> Self-hosting the core SFU does not automatically provide managed ingress, egress, recording, global routing, or support. Those services require separate deployment and capacity planning.</p><p><strong>Migration note:</strong> Ant Media's ingest and restreaming functions map to separate LiveKit Ingress and Egress components. Treat that split as an architecture change, not an endpoint swap.</p><p>LiveKit ranks above other self-hostable choices because its open-source core and managed cloud create a practical staged migration path for engineering teams.</p><h3 id="4-amazon-ivs-best-for-aws-native-events">4. Amazon IVS: Best for AWS-Native Events</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-6.45.51-PM-1.png" class="kg-image" alt="Top 10 Ant Media Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2922" height="1628"/></figure><p><a href="https://aws.amazon.com/ivs/" rel="noreferrer nofollow">Amazon Interactive Video Service</a><strong> is the strongest fit when streaming must integrate with AWS identity, storage, monitoring, networking, and event-driven application services.</strong></p><p>Amazon IVS offers two paths. Real-Time Streaming stages target under 300 milliseconds, while Low-Latency Streaming channels target under five seconds and distribute to broader audiences.</p><p>The Amazon IVS overview documents RTMP, RTMPS, and SRT channel ingest. Real-time stages support SDK publishing plus WHIP and RTMP ingest.</p><p>Amazon's documentation states that IVS stages can deliver video with latency under 300 milliseconds. Treat that figure as a vendor-documented target until your own network tests confirm it.</p><p><strong>Why it ranks fourth:</strong> IVS combines managed media, AWS operational tooling, participant recording, server-side composition, chat, private ingest, redundant ingest, and detailed service quotas.</p><p><strong>Best for:</strong> AWS-based live events, sports companion experiences, commerce, watch parties, creator broadcasts, and workloads that already send recordings and events to S3, Lambda, and CloudWatch.</p><p><strong>Pricing:</strong> Amazon IVS <a href="https://aws.amazon.com/ivs/pricing/"><u>official pricing</u></a> charges Real-Time Streaming by connected participant hours. Low-Latency Streaming bills video input and viewer output by channel, resolution, and delivery region.</p><p><strong>Watch out for:</strong> Real-time stages currently document a 720p participant publishing limit, 12 stage publishers, and regional quotas. Broader broadcasts may need composition into an IVS channel.</p><p><strong>Migration note:</strong> Map interactive Ant Media sessions to stages and large passive audiences to channels. This two-tier design can improve unit economics, but it increases orchestration complexity.</p><p>Amazon IVS ranks below LiveKit because AWS integration is its largest advantage, while teams outside AWS may find the regional model and multi-part billing harder to justify.</p><h3 id="5-red5-pro-best-direct-server-replacement">5. Red5 Pro: Best Direct Server Replacement</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-25-at-12.01.58-AM.png" class="kg-image" alt="Top 10 Ant Media Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2912" height="1626"/></figure><p><a href="https://www.red5.net/" rel="noreferrer nofollow"><strong><u>Red5 Pro</u></strong></a><strong> is the closest commercial Ant Media alternative for teams retaining self-hosted WebRTC infrastructure, multi-protocol ingest, autoscaling, and server-level deployment control.</strong></p><p>Red5 Pro supports WebRTC, RTMP, RTSP, HLS, recording, VOD, adaptive bitrate, and multiple cloud deployment targets. Its WebRTC SDK documentation also includes WHIP and WHEP client examples.</p><p><strong>Why it ranks fifth:</strong> Red5 Pro resembles Ant Media operationally. Your team licenses server software, supplies infrastructure, controls deployment, and can build around browser and mobile SDKs.</p><p><strong>Best for:</strong> Regulated or private-cloud workloads, IP-camera and broadcast inputs, low-latency self-hosting, and migration projects that cannot adopt a fully managed media API.</p><p><strong>Pricing:</strong> The <a href="https://www.red5.net/pricing/" rel="noreferrer nofollow"><strong><u>official pricing page</u></strong></a> lists Developer Pro at $29.99 monthly for 100 connections, Startup at $119 monthly, and Growth Pro at $299 monthly.</p><p><strong>Watch out for:</strong> Infrastructure, bandwidth, operational staffing, and some mobile SDK costs sit outside the base license. Enterprise offline deployment starts far above developer pricing.</p><p><strong>Migration note:</strong> Protocol and deployment similarity can reduce media-workflow changes. REST endpoints, authentication, autoscaling, monitoring, and application code still require explicit remapping and load testing.</p><p>Red5 Pro ranks below managed services for developer speed, but it outranks them when retaining self-hosted control is a non-negotiable requirement.</p><h3 id="6-100ms-best-for-hybrid-webrtc-and-hls">6. 100ms: Best for Hybrid WebRTC and HLS</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.31.12-PM-4.png" class="kg-image" alt="Top 10 Ant Media Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2910" height="1656"/></figure><p><a href="https://www.100ms.live/" rel="noreferrer nofollow"><u>100ms</u></a><strong> suits events where speakers need WebRTC interaction while a larger receive-only audience watches a composed HLS stream.</strong></p><p>The 100ms live-streaming guide defines on-stage WebRTC, off-stage WebRTC, and off-stage HLS roles. It documents sub-second WebRTC and HLS delivery below ten seconds.</p><p><strong>Why it ranks sixth:</strong> Roles, Prebuilt UI, chat, recordings, webhooks, static HLS playback URLs, and viewer promotion make 100ms practical for structured events.</p><p><strong>Best for:</strong> Webinars, virtual classrooms, fitness sessions, community events, town halls, and products that need predictable stage-to-audience role movement.</p><p><strong>Pricing:</strong> The <a href="https://www.100ms.live/pricing" rel="noreferrer nofollow"><u>100ms pricing page</u></a> currently includes 10,000 monthly HLS viewer minutes and 1,000 encoding minutes. Additional SD viewing starts at $0.0012 per viewer minute.</p><p><strong>Watch out for:</strong> HLS viewers receive more delay than WebRTC viewers. Encoding, recording, transcription, and external RTMP output use separate metered units.</p><p><strong>Migration note:</strong> Ant Media publishers map to broadcaster or co-broadcaster roles. Choose WebRTC or HLS viewer roles by interaction need, and retest moderation and playback behavior.</p><p>100ms ranks below Red5 Pro because it changes the operating model completely, but it is a faster product path for teams comfortable with managed infrastructure.</p><h3 id="7-zegocloud-best-for-social-live-features">7. ZEGOCLOUD: Best for Social Live Features</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.33.21-PM-2.png" class="kg-image" alt="Top 10 Ant Media Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2926" height="1668"/></figure><p><a href="https://www.zegocloud.com/product/live-streaming" rel="noreferrer nofollow"><u>ZEGOCLOUD</u></a><strong> is built for social live experiences where co-hosting, gifts, chat, cross-room interaction, and prebuilt interfaces matter alongside low-latency video.</strong></p><p>Its Live Streaming product page separates standard CDN-style streaming from interactive delivery and advertises sub-second interaction for supported modes.</p><p><strong>Why it ranks seventh:</strong> ZEGOCLOUD packages live video with UIKits and social engagement primitives, reducing the application work needed for creator and community products.</p><p><strong>Best for:</strong> Social live, live shopping, multi-guest shows, gaming streams, fitness, classes, virtual gifting, and applications prioritizing fast UI delivery.</p><p><strong>Pricing:</strong> The <a href="https://www.zegocloud.com/pricing?index=0" rel="noreferrer nofollow"><u>public pricing page</u></a> displays Live Streaming from $0.39 per 1,000 minutes. Host, co-host, viewer, recording, and add-on billing can alter the total.</p><p><strong>Watch out for:</strong> The low-latency feature may require account activation. Confirm regional availability, precise concurrency, feature access, and the correct billing mode during evaluation.</p><p><strong>Migration note:</strong> Map Ant Media data-channel interactions to ZEGOCLOUD messaging or application events. Validate whether UIKits provide sufficient customization before committing to them.</p><p>ZEGOCLOUD ranks behind 100ms because some technical and commercial details require support confirmation, although it may rank higher for a social entertainment product.</p><h3 id="8-wowza-best-for-broadcast-workflow-breadth">8. Wowza: Best for Broadcast Workflow Breadth</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-11.44.51-PM.png" class="kg-image" alt="Top 10 Ant Media Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2930" height="1652"/></figure><p><a href="https://www.wowza.com/" rel="noreferrer nofollow"><strong><u>Wowza</u></strong></a><strong> remains relevant when the replacement must support encoder-led broadcasting, managed cloud delivery, private streaming software, and a detailed REST control plane.</strong></p><p>The Wowza Video REST API controls live streams, transcoders, sources, targets, and playback. Wowza Video 2.0 also documents WebRTC live-stream creation through API calls.</p><p><strong>Why it ranks eighth:</strong> Wowza has mature broadcast workflow coverage, mixed encoder support, cloud transcoding, an integrated player, analytics, recording, and private deployment options.</p><p><strong>Best for:</strong> Broadcasters, continuous channels, mixed camera and encoder fleets, enterprise event teams, and organizations already familiar with Wowza Streaming Engine.</p><p><strong>Pricing:</strong> <a href="https://www.wowza.com/pricing/" rel="noreferrer nofollow"><strong><u>Wowza Streaming Engine</u></strong></a> lists a Basic Monthly plan at $195 for the first instance. Real-Time Streaming at Scale uses custom pricing.</p><p><strong>Watch out for:</strong> The public pay-as-you-go rates target general cloud streaming. Sub-500-millisecond real-time scale, 24-hour streaming, support, and private Engine deployment need separate commercial evaluation.</p><p><strong>Migration note:</strong> Wowza offers a familiar server and broadcast vocabulary, but its application configuration, Java extensions, REST resources, and scaling design differ from Ant Media.</p><p>Wowza ranks lower for interactive application development, yet it can outrank every managed RTC platform when legacy encoders and broadcast operations dominate the requirement.</p><h3 id="9-mux-best-for-api-first-one-way-broadcast">9. Mux: Best for API-First One-Way Broadcast</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-5.23.13-PM-1.png" class="kg-image" alt="Top 10 Ant Media Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2918" height="1666"/></figure><p><a href="https://www.mux.com/live" rel="noreferrer nofollow">Mux</a><strong> is an excellent live video API for one-way broadcasts, but it is not a real-time WebRTC replacement for Ant Media's interactive delivery.</strong></p><p>Mux uses RTMP or RTMPS ingest and HLS delivery. Its official live-streaming FAQ states that low-latency mode can reach about five seconds and direct WebRTC ingest is unavailable.</p><p><strong>Why it ranks ninth:</strong> Mux provides concise APIs, webhooks, test streams, automatic live-to-VOD assets, simulcast targets, playback security, player tooling, and detailed quality-of-experience analytics.</p><p><strong>Best for:</strong> Sports streams, concerts, media events, fitness broadcasts, user-generated live video, and products where five-second latency is acceptable.</p><p><strong>Pricing:</strong> Mux pricing documentation separates live input, storage, and delivery. Current public pricing includes 100,000 monthly delivery minutes; 720p Plus live input starts at <a href="https://www.mux.com/live" rel="noreferrer nofollow"><u>$0.025 per minute</u></a>, and delivery starts at $0.0008 per minute after included usage.</p><p><strong>Watch out for:</strong> Mux is unsuitable when viewers must speak on stage with near-instant audio and video. You need a separate real-time system for that interaction.</p><p><strong>Migration note:</strong> Keep an RTMP encoder workflow, replace stream-creation and playback APIs, then redesign Ant Media WebRTC interaction outside Mux rather than forcing HLS into a real-time role.</p><p>Mux ranks below the WebRTC products only because this article prioritizes Ant Media's low-latency interactive use case. For one-way API broadcasts, it can rank near the top.</p><h3 id="10-ovenmediaengine-best-open-source-self-hosting">10. OvenMediaEngine: Best Open-Source Self-Hosting</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-11.44.17-PM.png" class="kg-image" alt="Top 10 Ant Media Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2932" height="1616"/></figure><p><strong>OvenMediaEngine is the strongest open-source option here for teams willing to build and operate their own sub-second WebRTC and LL-HLS streaming stack.</strong></p><p>The <a href="https://github.com/OvenMediaLabs/OvenMediaEngine" rel="noreferrer nofollow"><strong><u>OvenMediaEngine repository</u></strong></a> documents WebRTC, LL-HLS, RTMP, SRT, monitoring, access control, recording, restreaming, and origin-edge clustering. A REST API manages applications and streams.</p><p><strong>Why it ranks tenth:</strong> It offers source access and no commercial license fee while covering many protocols that motivate an Ant Media deployment.</p><p><strong>Best for:</strong> Infrastructure teams, private deployments, high-control streaming products, engineering-led prototypes, and organizations able to own networking, upgrades, capacity, security, and support.</p><p><strong>Pricing:</strong> OvenMediaEngine's community project uses the AGPL-3.0 license, while commercial licenses are also available. Compute, bandwidth, storage, monitoring, engineering, and incident response form the actual cost.</p><p><strong>Watch out for:</strong> Review AGPL obligations with counsel. The <a href="https://docs.ovenmediaengine.com/0.17.1/rest-api" rel="noreferrer nofollow"><strong><u>REST API documentation</u></strong></a> also notes stream disruption when certain application settings restart.</p><p><strong>Migration note:</strong> Protocol similarity helps, but Ant Media application configuration and REST resources do not map directly. Rebuild access control, scaling, dashboards, and operational automation deliberately.</p><p>OvenMediaEngine ranks tenth overall because operational burden reduces its general fit. It ranks first for a narrower requirement: open-source, self-managed live infrastructure with protocol-level control.</p><h2 id="bonus-dolby-optiview-real-time-streaming-formerly-millicast">Bonus: Dolby OptiView Real-Time Streaming (Formerly Millicast)</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-25-at-12.04.21-AM.png" class="kg-image" alt="Top 10 Ant Media Alternatives for Live Streaming APIs in 2026" loading="lazy" width="2910" height="1632"/></figure><p><strong>Dolby OptiView is a credible bonus alternative for broadcast-quality WebRTC delivery where sub-second playback matters more than stage-style participant collaboration.</strong></p><p>The product previously known as Dolby.io Real-Time Streaming or Millicast is now branded <a href="https://optiview.dolby.com/docs/millicast/getting-started/" rel="noreferrer nofollow"><strong><u>Dolby OptiView Real-Time Streaming</u></strong></a>. Its documentation describes globally distributed WebRTC streaming, native mobile SDKs, broadcast-oriented publishing, multi-view experiences, and sub-second delivery.</p><p><strong>Best for:</strong> Sports betting, auctions, remote production, interactive sports, synchronized metadata, and large audiences that need broadcast quality with real-time playback.</p><p><strong>Pricing:</strong> Current <a href="https://optiview.dolby.com/plans/">Dolby OptiView plans</a> use custom pricing.</p><p><strong>Watch out for:</strong> Dolby OptiView is not a direct replacement for Ant Media's full self-hosted server model, and its public pricing is less transparent than the ranked products. It is included as a bonus because it is technically relevant, but the lack of self-service price detail makes normalized buying comparisons harder.</p><p><strong>Migration note:</strong> Treat Ant Media WebRTC broadcasts as publish-and-subscribe streams, then rebuild authentication, metadata, recording, audience interaction, and operational workflows around the OptiView APIs.</p><h2 id="which-ant-media-alternative-should-you-choose">Which Ant Media Alternative Should You Choose?</h2><p><strong>Choose the Ant Media alternative that matches your latency, deployment, and audience architecture before comparing feature counts.</strong></p><ul><li><strong>Choose VideoSDK</strong> when you want a managed interactive Live Streaming API, viewer promotion, application SDKs, HLS audience delivery, and RTMP restreaming.</li><li><strong>Choose Agora</strong> when a global, mature RTC network and a large catalog of media extensions justify more complex product and add-on pricing.</li><li><strong>Choose LiveKit</strong> when open-source portability, custom media applications, and a credible managed-cloud path matter more than a single bundled streaming product.</li><li><strong>Choose Amazon IVS</strong> when your backend, identity, storage, events, monitoring, and commercial commitments already center on AWS.</li><li><strong>Choose Red5 Pro or Wowza</strong> when self-hosting, broadcast protocol breadth, offline deployment, or direct server administration is a hard requirement.</li><li><strong>Choose 100ms or ZEGOCLOUD</strong> when structured stage roles, prebuilt interfaces, and audience engagement features will accelerate a social or event product.</li><li><strong>Choose Mux</strong> when the application is a one-way live broadcast and about five seconds of low-latency HLS is acceptable.</li><li><strong>Choose OvenMediaEngine</strong> when source access and avoiding a commercial server license outweigh the cost of running the full streaming platform yourself.</li><li><strong>Shortlist Dolby OptiView</strong> when broadcast-grade, sub-second WebRTC distribution is the priority and custom enterprise pricing is acceptable.</li></ul><p>The practical answer is conditional. VideoSDK is the best overall managed choice in this ranking, while Red5 Pro offers the closest commercial self-hosted replacement.</p><h2 id="how-to-migrate-from-ant-media">How to Migrate From Ant Media</h2><p><strong>A safe Ant Media migration starts with media-path inventory, not with replacing REST endpoint names.</strong></p><ol><li><strong>Record every ingest path.</strong> List WebRTC, WHIP, RTMP, RTSP, SRT, camera, and encoder sources, including codecs, bitrates, keyframe intervals, and authentication.</li><li><strong>Separate interactive and passive audiences.</strong> Keep speakers and promoted viewers on WebRTC, then evaluate HLS or LL-HLS for receive-only scale and lower delivery cost.</li><li><strong>Map identity and permissions.</strong> Translate Ant Media broadcast, room, token, publisher, and player rules into the target provider's room, stage, role, or stream model.</li><li><strong>Rebuild server-side control.</strong> Replace broadcast creation, recording, webhooks, analytics, stream health, and deletion endpoints with an explicit target API map.</li><li><strong>Test outputs and archives.</strong> Validate recordings, VOD availability, captions, thumbnails, simulcast destinations, retention, and storage ownership before moving live traffic.</li><li><strong>Run a shadow stream.</strong> Send the same encoder output to both platforms, then measure first-frame time, latency, freezes, bitrate changes, recovery, and viewer synchronization.</li><li><strong>Cut over gradually.</strong> Move internal events first, then low-risk customers, and finally high-value production streams with rollback keys and dashboards ready.</li></ol><p>This sequence avoids treating protocol support as product equivalence. Two vendors may accept RTMP while producing different latency, quality ladders, recordings, analytics, and failure behavior.</p><h2 id="a-practical-ant-media-migration-example">A Practical Ant Media Migration Example</h2><p><strong>A fictional live-shopping product shows why workload mapping matters more than copying Ant Media configuration into another provider.</strong></p><p>Imagine FlashCart runs one browser host, three rotating guests, 3,000 passive viewers, cloud recording, chat, and one RTMP output to YouTube. Ant Media currently handles the complete media path.</p><p>With VideoSDK, FlashCart would create one room, assign <code>SEND_AND_RECV</code> to the host and guests, and use <code>RECV_ONLY</code> or HLS for viewers according to latency and cost.</p><p>Its backend would issue short-lived VideoSDK tokens and store the new room ID beside the existing Ant Media broadcast ID. Chat and commerce events would remain application data.</p><p>The team would configure recording and an <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/rtmp-livestream">RTMP livestream destination</a>, then shadow one internal sale across both systems. Visible timestamps would expose the actual latency difference.</p><p>FlashCart would compare join success, first-frame time, freeze duration, audio-video sync, reconnect behavior, recording availability, and total event cost before shifting customer traffic.</p><p>If FlashCart required offline deployment inside a private facility, this design would fail the deployment requirement. Red5 Pro, Wowza, or OvenMediaEngine would become the more credible shortlist.</p><p>The example is fictional and contains no synthetic performance result. Its value is the repeatable mapping between participants, protocols, outputs, measurements, and a conditional platform decision.</p><h2 id="production-checks-most-people-miss">Production Checks Most People miss</h2><p><strong>The right Live Streaming API is the one that survives your worst network, largest event, strictest security review, and most expensive traffic pattern.</strong></p><h3 id="measure-glass-to-glass-latency">Measure Glass-to-Glass Latency</h3><p>Vendor latency describes a mode, not your application. Measure camera capture to rendered playback with visible timecodes across target devices, regions, browsers, and mobile networks.</p><p>Run separate tests for speakers, WebRTC viewers, HLS viewers, and restreamed social destinations. A single average hides long-tail delays that break auctions, quizzes, and commentary.</p><h3 id="price-one-real-event">Price One Real Event</h3><p>Model one host, five co-hosts, 5,000 viewers, 60 minutes, 720p delivery, recording, transcription, RTMP output, storage, and premium support. Include cloud egress for self-hosting.</p><p>Participant-minute, viewer-minute, stream-hour, delivered-minute, and bandwidth pricing are not directly comparable. Convert every vendor into the same event and monthly traffic forecast.</p><h3 id="validate-failure-recovery">Validate Failure Recovery</h3><p>Disconnect the publisher, rotate networks, deny UDP, expire a token, interrupt an encoder, and throttle bandwidth. Measure recovery time and whether viewers need manual refresh.</p><p>For self-hosted products, kill an origin node and an edge node. For managed products, test status webhooks, duplicate events, retry behavior, idempotency, and regional failover assumptions.</p><h3 id="audit-security-and-data-control">Audit Security and Data Control</h3><p>Confirm server-side token generation, role scoping, signed playback, stream-key rotation, encryption, recording access, deletion, audit logs, data residency, and required compliance agreements.</p><p>Do not infer compliance from transport encryption. Your application, storage bucket, analytics export, moderation workflow, and support access can change the complete security boundary.</p><h3 id="check-sdk-and-protocol-gaps">Check SDK and Protocol Gaps</h3><p>Build a feature matrix per platform. A vendor may support live captions on Web but not Flutter, WHIP ingest but not browser SDK ingest, or recording without individual tracks.</p><p>Protocol labels also hide codec constraints. Validate H.264, VP8, AV1, AAC, Opus, B-frames, simulcast, SVC, keyframe requirements, orientation, screen share, and hardware encoders.</p><h2 id="ant-media-alternative-glossary">Ant Media Alternative Glossary</h2><blockquote><strong>Interactive Live Streaming:</strong> A low-latency broadcast in which selected viewers can react, communicate, or become media publishers. VideoSDK models this with host and receive-only permissions inside a room.</blockquote><blockquote><strong>WebRTC:</strong> A real-time browser and application media stack commonly used for sub-second interactive streaming. It needs signaling, NAT traversal, media routing, and network adaptation around the core protocol.</blockquote><blockquote><strong>HLS and LL-HLS:</strong> HTTP Live Streaming delivers segmented media through HTTP infrastructure. LL-HLS reduces segment delay, but WebRTC usually remains the better fit for two-way interaction.</blockquote><blockquote><strong>Ingest:</strong> The path that sends a source into the streaming platform. Common live ingest options include browser WebRTC, WHIP, RTMP, RTSP, SRT, and hardware encoders.</blockquote><blockquote><strong>Egress and restreaming:</strong> The path that exports a live room or stream to recording storage, HLS, RTMP, SRT, YouTube, Twitch, Facebook, or another destination.</blockquote><blockquote><strong>Room or stage:</strong> A logical live session containing hosts, co-hosts, viewers, tracks, roles, and events. VideoSDK uses rooms, while Amazon IVS uses stages for real-time participants.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>VideoSDK is the strongest overall Ant Media alternative here for managed, interactive Live Streaming API development, but it is not an on-premises server replacement.</li><li>Agora, LiveKit, and Amazon IVS are credible managed or hybrid choices when global RTC maturity, open-source portability, or AWS integration drives the decision.</li><li>Red5 Pro, Wowza, and OvenMediaEngine fit teams that prioritize self-hosting, protocol control, private networking, or operational ownership.</li><li>Mux fits one-way API broadcasting better than two-way interaction because its documented low-latency mode is HLS-based and can reach about five seconds.</li><li>Every shortlist needs a shadow-stream test and one normalized event-cost model before production traffic moves away from Ant Media.</li><li>Dolby OptiView deserves a bonus evaluation for high-value, broadcast-grade WebRTC streams, although its custom pricing reduces self-service comparability.</li></ul><h2 id="conclusion">Conclusion</h2><p>The best <strong>Ant Media alternative</strong> is VideoSDK when your product needs a managed, developer-focused Live Streaming API with interactive roles and multiple audience paths. Choose Red5 Pro or OvenMediaEngine when infrastructure control is essential, and Mux when one-way broadcast quality matters more than real-time participation.</p><p>Start with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-react-ils">VideoSDK React ILS quickstart</a>, or create an account with the <a href="https://app.videosdk.live/login">$20 starting balance</a>. What live-streaming experience are you building? Share your audience size, latency target, and deployment constraints in the comments.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-best-ant-media-alternative">What Is the Best Ant Media Alternative?</h3><p>The best Ant Media alternative for a managed interactive Live Streaming API is VideoSDK because it combines room-based WebRTC, host and viewer permissions, audience interaction, HLS, and RTMP workflows. Red5 Pro is a closer choice when you need a commercially supported server installed on your infrastructure.</p><h3 id="is-videosdk-a-direct-ant-media-replacement">Is VideoSDK a Direct Ant Media Replacement?</h3><p>No, VideoSDK is not a direct Ant Media Server binary replacement. VideoSDK provides a managed API and SDK model, so you migrate application roles, tokens, rooms, recordings, and streams rather than replacing one self-hosted package with another.</p><h3 id="which-ant-media-alternative-supports-self-hosting">Which Ant Media Alternative Supports Self-Hosting?</h3><p>LiveKit, Red5 Pro, Wowza Streaming Engine, and OvenMediaEngine support self-managed deployment models. LiveKit and OvenMediaEngine provide open-source foundations, while Red5 Pro and Wowza use commercial products and support structures.</p><h3 id="how-do-webrtc-and-hls-streaming-differ">How Do WebRTC and HLS Streaming Differ?</h3><p>The main difference is interaction latency and delivery architecture. WebRTC supports sub-second, two-way media, while HLS uses HTTP segments for economical, device-compatible delivery to larger receive-only audiences with more delay.</p><h3 id="is-videosdk-suitable-for-interactive-live-streaming">Is VideoSDK Suitable for Interactive Live Streaming?</h3><p>Yes, VideoSDK supports interactive live streaming through send-and-receive host permissions and receive-only audience permissions. Its SDK also supports role changes, chat, polls, reactions, recording, captions, and RTMP destinations.</p><h3 id="how-much-does-an-ant-media-alternative-cost">How Much Does an Ant Media Alternative Cost?</h3><p>An Ant Media alternative can charge by server license, participant minute, viewer minute, stream hour, delivered minute, bandwidth, or transcoding. Compare vendors with one normalized event model that includes recording, storage, restreaming, support, and infrastructure.</p><h3 id="can-i-migrate-from-ant-media-without-downtime">Can I Migrate From Ant Media Without Downtime?</h3><p>Yes, you can reduce migration downtime by shadow-streaming into both platforms, validating playback and recording, moving low-risk events first, and keeping rollback credentials active. Complete zero downtime still depends on your encoder, session, DNS, and client architecture.</p><h2 id="related-videosdk-live-streaming-guides">Related VideoSDK Live Streaming Guides</h2><ul><li><a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/introduction">Interactive Live Streaming introduction</a></li><li><a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/concept-and-architecture">VideoSDK ILS concept and architecture</a></li><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-react-ils">React interactive live-streaming quickstart</a></li><li><a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/authentication-and-token">Authentication and token guide</a></li><li><a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/rtmp-livestream">RTMP livestream documentation</a></li><li><a href="https://github.com/videosdk-live/videosdk-ils-react-sdk-example">Open-source VideoSDK React ILS example</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Top 10 Wowza Alternatives in 2026: Expert-Reviewed & Ranked]]></title><description><![CDATA[Compare the top Wowza alternatives for live streaming APIs in 2026, including latency models, pricing, SDKs, trade-offs, and migration fit.]]></description><link>https://www.videosdk.live/blog/wowza-alternatives</link><guid isPermaLink="false">6a634978b3240feb748c8b51</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Sat, 25 Jul 2026 10:26:04 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-24--2026--11_18_03-PM.png" class="kg-image" alt="Top 10 Wowza Alternatives in 2026" loading="lazy" width="1672" height="941"/></figure><blockquote>The best Wowza alternatives for live streaming APIs are VideoSDK, Amazon IVS, and Agora. VideoSDK ranks first for embedded interactive streams with host and viewer roles. Amazon IVS suits AWS-native stages and large broadcasts, while Agora fits global social-live applications. Mux is stronger when API-first broadcasting and live-to-VOD matter more than two-way interaction.</blockquote><p><a href="https://www.wowza.com/" rel="noreferrer nofollow">Wowza</a> remains a capable platform for teams that need a deployable media server, broad protocol support, and control over streaming infrastructure. Many product teams, however, need a narrower application layer with client SDKs, participant roles, engagement features, recordings, and managed scaling.</p><p>This guide ranks only programmable live streaming APIs and SDKs. It excludes consumer streaming studios, webinar software, OTT storefronts, and video hosting tools without a meaningful developer-facing live API.</p><p>VideoSDK is our best overall choice for embedded interactive streaming. That verdict is conditional. Teams needing on-premises deployment, RTSP camera routing, unusual protocol conversion, or an AWS-native control plane should shortlist a different provider.</p><p><strong>Editorial disclosure:</strong> This is a documentation-verified expert review, not a controlled network benchmark. Published latency and capacity figures can change with geography, devices, network quality, encoder settings, audience mode, and playback configuration.</p><h2 id="what-are-wowza-alternatives-for-live-streaming-apis">What Are Wowza Alternatives for Live Streaming APIs?</h2><p>Wowza alternatives are platforms that replace part or all of a programmable live-video workflow, including ingest, transcoding, real-time delivery, playback, recording, analytics, and stream control.</p><p>Wowza currently offers both a managed cloud platform and the deployable Wowza Streaming Engine. Its <a href="https://www.wowza.com/developer/api-development" rel="noreferrer nofolow">live streaming APIs</a> provide programmatic control over cloud and server workflows.</p><p>No replacement is identical because Wowza spans several architectural jobs. A WebRTC API replaces the interactive application layer, while an <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a>-to-<a href="https://www.videosdk.live/developer-hub/hls" rel="noreferrer">HLS </a>service replaces broadcast processing and delivery.</p><p>VideoSDK covers the interactive category through rooms, host and audience modes, real-time media, recording, analytics, engagement features, and RTMP output. Its <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/concept-and-architecture"><u>interactive live streaming architecture</u></a> also supports dynamic role changes between participants who publish media and viewers who only receive it.</p><p>For this ranking, a provider qualifies only when developers can provision, control, or embed live streams through an API or SDK. A dashboard alone is not enough.</p><h2 id="how-we-ranked-these-wowza-alternatives">How We Ranked These Wowza Alternatives</h2><p>This ranking favours APIs that reduce application work while preserving the latency, control, and observability needed by production live video.</p><p>Each provider was reviewed against official product documentation, API references, pricing pages, deployment options, and publicly documented limits available on July 24, 2026. No provider received credit for an unverified third-party claim.</p><p>We weighted six factors:</p><ul><li><strong>Live API and SDK depth, 25%:</strong> Stream or room lifecycle, authentication, events, webhooks, client SDKs, and custom UI support.</li><li><strong>Latency and interactivity, 25%:</strong> Real-time delivery, host and viewer roles, co-hosting, and audience promotion.</li><li><strong>Broadcast workflow, 15%:</strong> RTMP, RTMPS, SRT, WHIP, HLS, recording, simulcasting, and live-to-VOD.</li><li><strong>Scale and operations, 15%:</strong> Documented concurrency, adaptive delivery, analytics, monitoring, and regional controls.</li><li><strong>Pricing clarity, 10%:</strong> Published billing units, free usage, calculators, and visible add-on costs.</li><li><strong>Deployment fit, 10%:</strong> Managed cloud, self-hosting, private networking, and migration compatibility.</li></ul><p>The order is optimised for a developer replacing Wowza with an embedded live streaming API. It is not a universal ranking for every media-server, broadcast, or surveillance workload.</p><h2 id="top-10-wowza-alternatives-at-a-glance">Top 10 Wowza Alternatives at a Glance</h2><p>The key decision is not which provider has the longest feature list. It is which delivery model matches your latency, interaction, scale, and operating requirements.</p>
<!--kg-card-begin: html-->
<style>
/* Responsive comparison table — safe to paste into a Ghost HTML card */
.vsdk-table-wrap {
  width: 100%;
  max-width: 100%;
  margin: 24px 0;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  background: #0f172a;
  border: 1px solid #334155;
  border-radius: 14px;
}

.vsdk-comparison-table {
  display: table !important;
  width: 100% !important;
  min-width: 880px;
  max-width: none !important;
  margin: 0 !important;
  border: 0;
  border-collapse: collapse;
  table-layout: fixed;
  background: #0f172a;
  color: #f8fafc;
  font-family: inherit;
}

.vsdk-comparison-table col:nth-child(1) { width: 7%; }
.vsdk-comparison-table col:nth-child(2) { width: 15%; }
.vsdk-comparison-table col:nth-child(3) { width: 24%; }
.vsdk-comparison-table col:nth-child(4) { width: 27%; }
.vsdk-comparison-table col:nth-child(5) { width: 27%; }

.vsdk-comparison-table th,
.vsdk-comparison-table td {
  box-sizing: border-box;
  padding: 16px 14px;
  border-right: 1px solid #334155;
  border-bottom: 1px solid #334155;
  vertical-align: middle;
  white-space: normal !important;
  overflow: visible !important;
  overflow-wrap: anywhere;
  word-break: normal;
  line-height: 1.55;
}

.vsdk-comparison-table th:last-child,
.vsdk-comparison-table td:last-child {
  border-right: 0;
}

.vsdk-comparison-table tbody tr:last-child td {
  border-bottom: 0;
}

.vsdk-comparison-table thead th {
  background: #6d28d9;
  color: #ffffff;
  font-size: 15px;
  font-weight: 700;
  text-align: left;
  letter-spacing: 0.01em;
}

.vsdk-comparison-table tbody td {
  background: #0f172a;
  color: #f8fafc;
  font-size: 15px;
  font-weight: 400;
  text-align: left;
}

.vsdk-comparison-table th:nth-child(1),
.vsdk-comparison-table td:nth-child(1),
.vsdk-comparison-table th:nth-child(2),
.vsdk-comparison-table td:nth-child(2) {
  text-align: center;
}

.vsdk-comparison-table tbody tr:hover td {
  background: #111c31;
}

@media (max-width: 767px) {
  .vsdk-table-wrap {
    border-radius: 10px;
  }

  .vsdk-comparison-table {
    width: 880px !important;
    min-width: 880px;
  }

  .vsdk-comparison-table th,
  .vsdk-comparison-table td {
    padding: 13px 12px;
    font-size: 14px;
  }
}
</style>

<div class="vsdk-table-wrap" role="region" aria-label="Live streaming platform comparison" tabindex="0">
  <table class="vsdk-comparison-table">
    <colgroup>
      <col>
      <col>
      <col>
      <col>
      <col>
    </col></col></col></col></col></colgroup>
    <thead>
      <tr>
        <th scope="col">Rank</th>
        <th scope="col">Platform</th>
        <th scope="col">Published delivery model</th>
        <th scope="col">Best for</th>
        <th scope="col">Main trade-off</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td>VideoSDK</td>
        <td>Real-time interactive, plus HLS and RTMP workflows</td>
        <td>Embedded live shopping, events, classes, and communities</td>
        <td>Managed platform, not an on-prem media server</td>
      </tr>
      <tr>
        <td>2</td>
        <td>Amazon IVS</td>
        <td>Under 300 ms stages; under 5 seconds channels</td>
        <td>AWS-native interactive events and large broadcasts</td>
        <td>AWS complexity and separate stage and channel models</td>
      </tr>
      <tr>
        <td>3</td>
        <td>Agora</td>
        <td>Ultra-low-latency interactive streaming</td>
        <td>Global social live, co-hosting, and mobile experiences</td>
        <td>Add-ons and operating modes complicate cost modelling</td>
      </tr>
      <tr>
        <td>4</td>
        <td>Mux</td>
        <td>Low-latency HLS broadcast workflow</td>
        <td>API-first broadcast, analytics, and live-to-VOD</td>
        <td>Not a direct two-way WebRTC stage</td>
      </tr>
      <tr>
        <td>5</td>
        <td>LiveKit</td>
        <td>WebRTC rooms with ingress and egress</td>
        <td>Open-source control and custom real-time products</td>
        <td>Self-hosted broadcast services require planning</td>
      </tr>
      <tr>
        <td>6</td>
        <td>Cloudflare Stream</td>
        <td>LL-HLS, plus WebRTC beta</td>
        <td>Simple global delivery with predictable pricing</td>
        <td>WebRTC recording and analytics remain beta-limited</td>
      </tr>
      <tr>
        <td>7</td>
        <td>ZEGOCLOUD</td>
        <td>Under 300 ms to 3 seconds across three modes</td>
        <td>Social live, gifting, battles, and weak networks</td>
        <td>Some modes require manual activation</td>
      </tr>
      <tr>
        <td>8</td>
        <td>100ms</td>
        <td>WebRTC rooms with HLS audience playback</td>
        <td>Room-to-HLS events, classes, and webinars</td>
        <td>Architecture is tied to rooms and templates</td>
      </tr>
      <tr>
        <td>9</td>
        <td>api.video</td>
        <td>About 3 seconds in favourable conditions</td>
        <td>Straightforward live API, restreaming, and live-to-VOD</td>
        <td>Less suitable for natural two-way conversation</td>
      </tr>
      <tr>
        <td>10</td>
        <td>Ant Media Server</td>
        <td>WebRTC plus broad streaming protocols</td>
        <td>Self-hosted and private-cloud streaming</td>
        <td>Your team operates infrastructure and scaling</td>
      </tr>
    </tbody>
  </table>
</div>
<!--kg-card-end: html-->
<p>The first three options lead for embedded interaction. Mux, Cloudflare Stream, and api.video become stronger when playback scale, processing, and live-to-VOD matter more than participant role switching.</p><h2 id="the-10-best-wowza-alternatives-in-2026">The 10 Best Wowza Alternatives in 2026</h2><p>These Wowza alternatives cover three different jobs: real-time interaction, API-first broadcast delivery, and self-hosted media infrastructure.</p><h3 id="1-videosdk-best-overall-interactive-api">1. VideoSDK: Best Overall Interactive API</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.29.39-PM-2.png" class="kg-image" alt="Videosdk Homepage" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> ranks first for developers who want hosts, co-hosts, and viewers inside a custom application without operating a media server. Its room model separates publishing participants from receive-only audience members.</p><p>The <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/concept-and-architecture"><u>VideoSDK interactive live streaming documentation</u></a> covers participant events, audience management, analytics, recording, geo-fencing, chat, polls, reactions, RTMP output, and custom media sources. The same application can promote a viewer by changing the participant's mode.</p><p><strong>Best for:</strong> Live shopping, creator communities, tutoring, auctions, gaming events, town halls, and webinars where selected viewers may join the stage.</p><p><strong>Why it ranks first:</strong> VideoSDK combines the real-time media layer and interaction primitives within one SDK surface. This reduces the orchestration code needed to synchronise media, participant state, chat, polls, and broadcast output.</p><p><strong>Trade-offs:</strong> VideoSDK does not replace Wowza Streaming Engine for on-premises deployment, air-gapped networks, <a href="https://www.videosdk.live/blog/what-is-rtsp-protocol" rel="noreferrer">RTSP</a> camera ingestion, or unusual protocol conversion. Published capacity also varies by streaming mode, so validate host and viewer limits for your chosen architecture.</p><p><strong>Pricing:</strong> VideoSDK advertises pay-as-you-go pricing and a free $20 starting balance on its <a href="https://www.videosdk.live/pricing"><u>current pricing page</u></a>. Model hosts, interactive viewers, HLS viewers, recording, and RTMP output separately before production.</p><p><strong>Wowza replacement fit:</strong> Choose VideoSDK when your real requirement is an embedded interactive product rather than a general-purpose streaming server.</p><h3 id="2-amazon-ivs-best-for-aws-native-scale">2. Amazon IVS: Best for AWS-Native Scale</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-6.45.51-PM.png" class="kg-image" alt="Amazon IVS Homepage" loading="lazy" width="2922" height="1628"/></figure><p><a href="https://aws.amazon.com/ivs/" rel="noreferrer nofollow">Amazon Interactive Video Service</a> separates real-time stages from low-latency broadcast channels. AWS documents latency under 300 milliseconds for stages and under five seconds for channels.</p><p>A stage supports interactive publishers and subscribers through web and mobile Broadcast SDKs. A channel distributes HLS playback to a larger passive audience, while Amazon IVS Chat adds synchronised messaging.</p><p><strong>Best for:</strong> Sports, auctions, ecommerce events, gaming, and existing AWS workloads needing real-time hosts plus broadcast viewers.</p><p><strong>Why it ranks second:</strong> IVS offers a clear path from real-time stages to large channel audiences, with AWS monitoring, recording, composition, and regional control-plane resources.</p><p><strong>Trade-offs:</strong> Developers must understand IAM, participant tokens, stages, channels, composition, S3, and regional quotas. Stage pricing and channel pricing also use different billing models.</p><p><strong>Pricing:</strong> AWS bills stage participants by connected hours and channel workflows by input plus viewer output. Its <a href="https://aws.amazon.com/ivs/pricing/"><u>official pricing example</u></a> uses $0.072 per real-time video participant-hour in the United States.</p><p><strong>Wowza replacement fit:</strong> Choose IVS when AWS is already your control plane and you need a managed route from interactive hosts to a large passive audience.</p><h3 id="3-agora-best-for-global-social-live">3. Agora: Best for Global Social Live</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.26-PM-2.png" class="kg-image" alt="Agora Homepage" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/en/products/interactive-live-streaming/" rel="noreferrer nofollow">Agora</a> offers Interactive Live Streaming and Broadcast Streaming products on its real-time network. Host, audience, co-hosting, chat, screen sharing, virtual gifting, and adaptive delivery fit social-live applications.</p><p>Agora's official product page documents sub-second channel switching, cross-channel co-hosting, recording options, media push, and broad client-platform support.</p><p><strong>Best for:</strong> Social entertainment, dating, live gaming, watch parties, virtual gifts, and mobile-first creator platforms.</p><p><strong>Why it ranks third:</strong> Agora has a mature real-time feature surface, wide platform coverage, weak-network controls, and several broadcast distribution options.</p><p><strong>Trade-offs:</strong> Media Push, recording, analytics, proxy modes, and other extensions can add separate billing dimensions. Teams should map every required feature before comparing base media rates.</p><p><strong>Pricing:</strong> Agora's <a href="https://www.agora.io/en/pricing/interactive-live-streaming/" rel="noreferrer nofollow"><u>interactive live streaming pricing</u></a> lists $0.99 per 1,000 audio participant minutes and $3.99 per 1,000 HD video participant minutes, with 10,000 free standard minutes.</p><p><strong>Wowza replacement fit:</strong> Choose Agora for interactive social products. Choose Wowza or another broadcast API when deep protocol routing and server-side customisation matter more.</p><h3 id="4-mux-best-broadcast-to-vod-api">4. Mux: Best Broadcast-to-VOD API</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-5.23.13-PM.png" class="kg-image" alt="Mux Homepage" loading="lazy" width="2918" height="1666"/></figure><p><a href="https://www.mux.com/live" rel="noreferrer nofollow">Mux</a> treats a live stream as an API resource with a stream key, playback IDs, webhooks, monitoring, and an automatically created on-demand asset.</p><p>The Mux live workflow supports RTMP ingest, HLS output, public or signed playback, reconnect windows, recordings, simulcast targets, and detailed playback analytics.</p><p><strong>Best for:</strong> Creator platforms, sports, events, fitness, news, and products where each live stream should become a managed VOD asset.</p><p><strong>Why it ranks fourth:</strong> Mux offers a clear developer experience for provisioning streams, securing playback, monitoring input health, and reusing recordings.</p><p><strong>Trade-offs:</strong> Mux is primarily an encoder-to-HLS workflow, not a direct two-way WebRTC stage. A product that promotes viewers into natural conversation will need a separate RTC layer.</p><p><strong>Pricing:</strong> Mux lists <a href="https://www.mux.com/live" rel="noreferrer nofollow"><u>live input from $0.025 per minute</u></a>, storage from $0.0024 per minute, and delivery from $0.0008 per minute. Resolution and quality multipliers apply.</p><p><strong>Wowza replacement fit:</strong> Choose Mux for API-first managed broadcast and live-to-VOD. Do not choose it alone for sub-second, two-way participation.</p><h3 id="5-livekit-best-open-source-webrtc-stack">5. LiveKit: Best Open-Source WebRTC Stack</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.40-PM-2.png" class="kg-image" alt="LiveKit Homepage" loading="lazy" width="2920" height="1670"/></figure><p><a href="https://livekit.com/" rel="noreferrer nofollow"><u>LiveKit</u></a> combines an open-source WebRTC server with managed LiveKit Cloud. Rooms handle real-time participants, while Ingress accepts RTMP, WHIP, and SRT and Egress handles recording and streaming output.</p><p>The LiveKit Cloud comparison documents portability between open source and cloud, global routing, region pinning, webhooks, ingress, egress, and end-to-end encryption.</p><p><strong>Best for:</strong> Engineering teams wanting source access, custom real-time behaviour, self-hosting, or a managed-to-self-hosted path.</p><p><strong>Why it ranks fifth:</strong> LiveKit provides strong SDK ergonomics and deployment flexibility. Application code can remain portable because self-hosted and cloud deployments use the same core APIs.</p><p><strong>Trade-offs:</strong> Self-hosted LiveKit is an RTC stack, not a turnkey broadcast CDN. Ingress, Egress, scaling, storage, observability, and HLS delivery remain architectural responsibilities.</p><p><strong>Pricing:</strong> LiveKit Cloud currently lists Build at $0, Ship from $50 monthly, Scale from $500 monthly, and custom Enterprise plans on its <a href="https://livekit.com/pricing" rel="noreferrer nofollow"><u>pricing page</u></a><u>.</u>.</p><p><strong>Wowza replacement fit:</strong> Choose LiveKit when ownership and WebRTC customisation matter. Ant Media may fit better when traditional streaming protocols dominate.</p><h3 id="6-cloudflare-stream-best-simple-global-delivery">6. Cloudflare Stream: Best Simple Global Delivery</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-5.27.25-PM.png" class="kg-image" alt="Cloudflare Stream Homepage" loading="lazy" width="2924" height="1658"/></figure><p><a href="https://developers.cloudflare.com/stream/" rel="noreferrer nofollow"><u>Cloudflare Stream</u></a> provides an API for live inputs, encoding, storage, delivery, recordings, signed URLs, webhooks, analytics, and playback through its player or HLS and DASH manifests.</p><p>Its stable live path accepts RTMPS and SRT. A separate WebRTC beta uses WHIP ingest and WHEP playback for sub-second delivery.</p><p><strong>Best for:</strong> Developer platforms seeking global delivery, straightforward costs, signed playback, instant recordings, and minimal infrastructure.</p><p><strong>Why it ranks sixth:</strong> Cloudflare includes bandwidth within delivered-minute pricing and exposes clean REST resources. Teams using Workers, R2, or Cloudflare security can keep more of the application stack together.</p><p><strong>Trade-offs:</strong> In the WebRTC beta, recording, restreaming, live viewer counts, analytics, and mixed WebRTC-to-HLS workflows remain unsupported. Standard Stream also lacks a participant role model.</p><p><strong>Pricing:</strong> Cloudflare Stream charges <a href="https://developers.cloudflare.com/stream/pricing/" rel="noreferrer nofollow"><u>$5 per 1,000 stored minutes and $1 per 1,000 delivered minutes</u></a>. Ingest and encoding are included.</p><p><strong>Wowza replacement fit:</strong> Choose Cloudflare Stream for managed delivery simplicity. Pilot the WebRTC path before treating it as equivalent to a mature interactive SDK.</p><h3 id="7-zegocloud-best-for-social-features">7. ZEGOCLOUD: Best for Social Features</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.33.21-PM-1.png" class="kg-image" alt="ZEGOCLOUD Homepage" loading="lazy" width="2926" height="1668"/></figure><p><a href="https://www.zegocloud.com/product/live-streaming" rel="noreferrer nofollow"><u>ZEGOCLOUD</u></a> combines real-time live, interactive live, and high-concurrency live delivery modes. Its SDKs include co-hosting, virtual gifts, streamer battles, chat, effects, recording, mixing, and RTMP forwarding.</p><p>The ZEGOCLOUD Live Streaming Kit documentation publishes under 300 milliseconds for Real-time Live, 600 milliseconds to one second for Interactive Live Streaming, and one to three seconds for high-concurrency Live Streaming.</p><p><strong>Best for:</strong> Social entertainment, cross-room battles, live gifting, ecommerce, gaming, and markets where weak-network handling is critical.</p><p><strong>Why it ranks seventh:</strong> ZEGOCLOUD offers rich social-live primitives and prebuilt UI Kits. Its delivery modes let teams trade interaction quality against audience cost.</p><p><strong>Trade-offs:</strong> Product terminology and billing differ across modes. Interactive and high-concurrency modes require manual activation, and proprietary delivery deserves platform-specific testing.</p><p><strong>Pricing:</strong> ZEGOCLOUD lists <a href="https://www.zegocloud.com/pricing?index=0" rel="noreferrer nofollow"><u>Live Streaming from $0.39 per 1,000 minutes</u></a>. Video calls, recording, effects, and analytics use separate meters.</p><p><strong>Wowza replacement fit:</strong> Choose ZEGOCLOUD when social mechanics are central. VideoSDK is a cleaner fit when developer-controlled stage interaction is the priority.</p><h3 id="8-100ms-best-for-room-to-hls-events">8. 100ms: Best for Room-to-HLS Events</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.31.12-PM-3.png" class="kg-image" alt="100ms Homepage" loading="lazy" width="2910" height="1656"/></figure><p><a href="https://www.100ms.live/" rel="noreferrer nofollow"><u>100ms</u></a> starts with WebRTC rooms and publishes a room composition as HLS. The server API returns an M3U8 playback URL and can generate VOD or layer-specific recordings.</p><p>The 100ms Live Streams API supports server-side lifecycle control, recordings, and HLS-compatible playback.</p><p><strong>Best for:</strong> Virtual events, classrooms, webinars, fitness sessions, and applications that combine an interactive room with a larger HLS audience.</p><p><strong>Why it ranks eighth:</strong> 100ms offers a practical room-to-HLS model, client SDKs, role templates, recording formats, and visible streaming prices.</p><p><strong>Trade-offs:</strong> The live-streaming architecture remains tied to a room and its composition template. Teams wanting a simple encoder-to-HLS resource model may prefer Mux, Cloudflare Stream, or api.video.</p><p><strong>Pricing:</strong> 100ms includes 10,000 streaming viewer minutes monthly, then lists <a href="https://www.100ms.live/pricing" rel="noreferrer nofollow"><u>$0.0012 per viewer-minute</u></a>. Encoding, recording, transcription, and RTMP output are separate.</p><p><strong>Wowza replacement fit:</strong> Choose 100ms when an interactive room is the production source and HLS is the audience output.</p><h3 id="9-apivideo-best-straightforward-live-api">9. api.video: Best Straightforward Live API</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-5.27.58-PM.png" class="kg-image" alt="api.video Homepage" loading="lazy" width="2896" height="1634"/></figure><p><a href="https://api.video/" rel="noreferrer nofollow"><u>api.video</u></a> offers REST resources and client libraries for live streams, recordings, playback, analytics, privacy, and restreaming. Streams can become standard video assets after a broadcast.</p><p>Its pricing and feature page documents RTMPS and SRT ingest, 24/7 streaming, DVR, private live streams, adaptive delivery, restreaming, and about three seconds of latency in favourable conditions.</p><p><strong>Best for:</strong> SaaS products needing a direct live API, branded playback, live-to-VOD, simulcasting, and usage-based delivery pricing.</p><p><strong>Why it ranks ninth:</strong> api.video keeps the live workflow understandable and offers free encoding, which removes one commonly confusing line item.</p><p><strong>Trade-offs:</strong> Three-second latency suits Q&amp;A and broadcast chat but not natural two-way conversation. Its participant and role controls are lighter than RTC-first platforms.</p><p><strong>Pricing:</strong> api.video lists free encoding, hosting from $0.00285 per stored minute, and <a href="https://api.video/pricing/"><u>delivery from $0.0017 per delivered minute</u></a>.</p><p><strong>Wowza replacement fit:</strong> Choose api.video when API clarity and the full video lifecycle matter more than sub-second interactivity or self-hosted control.</p><h3 id="10-ant-media-server-best-self-hosted-alternative">10. Ant Media Server: Best Self-Hosted Alternative</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-24-at-5.28.24-PM.png" class="kg-image" alt="Ant Media Server Homepage" loading="lazy" width="2924" height="1660"/></figure><p><a href="https://antmedia.io/" rel="noreferrer nofollow"><u>Ant Media Server</u></a> is the closest option here to a deployable media server. It supports WebRTC, WHIP, WHEP, RTMP, RTSP, SRT, LL-HLS, HLS, recording, REST APIs, and client SDKs.</p><p>Ant Media can run on-premises, in a private cloud, or through cloud marketplace images. This makes it relevant to surveillance, regulated networks, and custom infrastructure.</p><p><strong>Best for:</strong> Private networks, surveillance, regulated environments, IP cameras, and teams needing broad ingest and output protocols.</p><p><strong>Why it ranks tenth:</strong> This ranking prioritises managed application APIs, so operationally heavier software appears lower. For self-hosted protocol control, Ant Media should move near the top.</p><p><strong>Trade-offs:</strong> Your team owns capacity planning, autoscaling, upgrades, observability, cloud costs, and delivery architecture. This can reproduce the operating burden that motivated the Wowza migration.</p><p><strong>Pricing:</strong> Ant Media lists a $0.24 per instance-hour licence, $109 monthly licence, $89 monthly annual licence, and $2,799 perpetual licence on its <a href="https://antmedia.io/pricing/" rel="noreferrer nofollow"><u>pricing page</u></a>. Infrastructure costs are additional.</p><p><strong>Wowza replacement fit:</strong> Choose Ant Media for self-hosted WebRTC and protocol coverage. Do not choose it merely to reduce infrastructure work.</p><h2 id="wowza-pricing-vs-alternatives">Wowza Pricing vs Alternatives</h2><p>Wowza pricing starts with a software licence, while managed alternatives meter media usage. The amounts below are not direct equivalents because each provider measures a different part of the streaming path.</p>
<!--kg-card-begin: html-->
 <!-- Paste this complete block into a Ghost HTML card. -->

<style>
  .vs-pricing-table-wrap {
    width: 100%;
    max-width: 100%;
    margin: 28px 0;
    overflow-x: auto;
    overflow-y: hidden;
    background: #0b1120;
    border: 1px solid #26354d;
    border-radius: 12px;
    box-sizing: border-box;
    -webkit-overflow-scrolling: touch;
  }

  .vs-pricing-table {
    display: table !important;
    width: 100% !important;
    max-width: none !important;
    min-width: 820px;
    margin: 0 !important;
    border: 0 !important;
    border-collapse: collapse !important;
    border-spacing: 0 !important;
    table-layout: fixed !important;
    background: #0f172a;
    color: #f8fafc;
    font-family: Inter, Arial, sans-serif;
    font-size: 16px;
    line-height: 1.55;
  }

  .vs-pricing-table col:nth-child(1) { width: 16%; }
  .vs-pricing-table col:nth-child(2) { width: 22%; }
  .vs-pricing-table col:nth-child(3) { width: 27%; }
  .vs-pricing-table col:nth-child(4) { width: 35%; }

  .vs-pricing-table th,
  .vs-pricing-table td {
    box-sizing: border-box;
    padding: 16px 14px;
    border: 1px solid #334155;
    vertical-align: top;
    white-space: normal !important;
    overflow: visible !important;
    overflow-wrap: anywhere;
    word-break: normal;
    text-align: left;
    background: #0f172a;
    color: #f8fafc;
  }

  .vs-pricing-table thead th {
    background: #6d28d9;
    color: #ffffff;
    font-weight: 700;
    line-height: 1.35;
    vertical-align: middle;
  }

  .vs-pricing-table tbody th {
    font-weight: 600;
    text-align: center;
    vertical-align: middle;
  }

  .vs-pricing-table tbody tr:hover th,
  .vs-pricing-table tbody tr:hover td {
    background: #111c31;
  }

  .vs-pricing-table-wrap::-webkit-scrollbar {
    height: 10px;
  }

  .vs-pricing-table-wrap::-webkit-scrollbar-track {
    background: #0b1120;
  }

  .vs-pricing-table-wrap::-webkit-scrollbar-thumb {
    background: #475569;
    border: 2px solid #0b1120;
    border-radius: 999px;
  }

  @media (max-width: 900px) {
    .vs-pricing-table {
      width: 820px !important;
      min-width: 820px !important;
      font-size: 15px;
    }

    .vs-pricing-table th,
    .vs-pricing-table td {
      padding: 14px 12px;
    }
  }
</style>

<div class="vs-pricing-table-wrap" role="region" aria-label="Streaming platform pricing comparison" tabindex="0">
  <table class="vs-pricing-table">
    <colgroup>
      <col>
      <col>
      <col>
      <col>
    </col></col></col></col></colgroup>
    <thead>
      <tr>
          <th scope="col">Platform</th>
          <th scope="col">Published starting point</th>
          <th scope="col">What is metered</th>
          <th scope="col">Cost risk to model</th>
      </tr>
    </thead>
    <tbody>
        <tr>
          <th scope="row">Wowza Streaming Engine</th>
          <td>$195 monthly for the first Basic instance</td>
          <td>Server instances and transcoded channels</td>
          <td>Compute, bandwidth, CDN, support, operations, and $25 per extra transcoded channel</td>
        </tr>
        <tr>
          <th scope="row">VideoSDK</th>
          <td>Pay as you go with a free $20 starting balance</td>
          <td>Interactive participants, audience delivery, and optional services</td>
          <td>Host-to-viewer mix, recording, HLS, RTMP output, and regional usage</td>
        </tr>
        <tr>
          <th scope="row">Amazon IVS</th>
          <td>$0.072 per real-time video participant-hour in the US example</td>
          <td>Stage participant hours, channel input, viewer output, chat, and composition</td>
          <td>Region, resolution, active hosts, passive viewers, and composition</td>
        </tr>
        <tr>
          <th scope="row">Mux</th>
          <td>Live input from $0.025 per minute</td>
          <td>Input, storage, delivery, and optional quality tiers</td>
          <td>Resolution multipliers, delivered minutes, recordings, and analytics needs</td>
        </tr>
    </tbody>
  </table>
</div>
<!--kg-card-end: html-->
<p>The Wowza Streaming Engine pricing page lists $195 monthly for one Basic instance with up to 10 concurrent transcoded channels. It also lists a $295 one-month licence and custom Enterprise plans.</p><p>Do not compare only one headline rate. Model a representative event with hosts, co-hosts, passive viewers, session duration, resolution, encoding, recording, storage, egress, support, and engineering operations.</p><p>For an interactive commerce app, participant and viewer mix usually controls cost. For a broadcast product, delivered minutes, bitrate, storage, and CDN output usually matter more than host count.</p><h2 id="what-is-the-best-alternative-to-wowza">What Is the Best Alternative to Wowza?</h2><p>VideoSDK is the best Wowza alternative for embedded interactive streaming, while Amazon IVS, Mux, LiveKit, and Ant Media lead different workload categories.</p><p>Use this decision framework:</p><ul><li><strong>Use VideoSDK</strong> when viewers may become hosts, low-latency participation matters, and you want web or mobile SDKs with interaction features.</li><li><strong>Use Amazon IVS</strong> when AWS is strategic and you need real-time stages plus a path to large broadcast audiences.</li><li><strong>Use Agora</strong> when social-live interaction, mobile reach, and a mature RTC network are the primary requirements.</li><li><strong>Use Mux</strong> when RTMP ingest, HLS playback, analytics, and automatic live-to-VOD matter more than sub-second conversation.</li><li><strong>Use LiveKit</strong> when open-source WebRTC, custom infrastructure, or a future self-hosting path matters.</li><li><strong>Use Cloudflare Stream</strong> when global delivery and simple minute-based pricing outweigh advanced participant controls.</li><li><strong>Use Ant Media</strong> when on-premises deployment, RTSP, SRT, and protocol control are non-negotiable.</li></ul><p>There is no honest universal winner because one Wowza deployment may contain a media server, transcoder, origin, player, API, and delivery network. Replace the workload, not the logo.</p><h2 id="how-to-migrate-from-wowza">How to Migrate From Wowza</h2><p>A safe Wowza migration begins with a workload inventory, then replaces one media path at a time behind your application's own abstraction.</p><ol><li><strong>Inventory ingest and playback.</strong> Record RTMP, RTMPS, RTSP, SRT, WebRTC, HLS, DASH, encoder settings, resolutions, captions, and player requirements.</li><li><strong>Map control-plane calls.</strong> List stream creation, start, stop, reset, recording, webhooks, analytics, authentication, and access-control dependencies.</li><li><strong>Separate interactive and passive viewers.</strong> A host, co-host, WebRTC viewer, and HLS viewer have different latency, bandwidth, and pricing profiles.</li><li><strong>Build a provider adapter.</strong> Keep room IDs, stream IDs, tokens, webhooks, and playback URLs behind your backend rather than throughout the product.</li><li><strong>Run representative pilots.</strong> Test the countries, devices, browsers, corporate firewalls, mobile networks, encoder failures, and audience sizes that matter.</li><li><strong>Dual-publish critical events.</strong> Where protocols allow, send the same production source to Wowza and the shortlisted provider before moving viewers.</li><li><strong>Compare complete cost.</strong> Include host minutes, viewer minutes, encoding, delivery, storage, recording, support, and engineering operations.</li><li><strong>Cut over gradually.</strong> Move internal events first, then a small customer cohort, and retain a rollback route until recordings and analytics reconcile.</li></ol><p>For VideoSDK, begin with the <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start-js-ils"><u>JavaScript interactive live streaming quickstart</u></a>, then review <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/authentication-and-token"><u>authentication and token guidance</u></a>. Generate production tokens only on a trusted server.</p><h3 id="example-migrating-a-live-shopping-app">Example: Migrating a Live-Shopping App</h3><p>Imagine a commerce app with two hosts, 5,000 viewers, chat, product polls, and occasional viewer promotion. Wowza handles ingest and playback, while custom services synchronise interaction.</p><p>VideoSDK could consolidate the interactive stage, participant events, mode switching, polls, and RTMP output. The team should still decide whether all 5,000 viewers need real-time delivery.</p><p>Mux would provide a clean broadcast and automatic replay asset, but promoted viewers would require a separate WebRTC service. Amazon IVS could use a stage for hosts and a channel for the larger audience.</p><p>The correct architecture depends on the percentage of viewers who genuinely need sub-second media. Paying real-time participant rates for passive viewers can erase the simplicity of an all-WebRTC design.</p><h2 id="live-streaming-terms-developers-should-know">Live Streaming Terms Developers Should Know</h2><p>These terms explain the main architectural differences between interactive and broadcast-focused Wowza alternatives.</p><blockquote><strong>Interactive Live Streaming (ILS):</strong> A live-video model where hosts and selected viewers exchange media with sufficiently low delay for natural participation. VideoSDK implements this through host and audience participant modes.</blockquote><blockquote><strong>HLS:</strong> HTTP Live Streaming segments media for scalable playback through CDNs and standard players. It generally trades more latency for reach, stability, and compatibility.</blockquote><blockquote><strong>WHIP and WHEP:</strong> HTTP-based protocols for WebRTC ingest and playback. LiveKit, Cloudflare Stream, and Ant Media support parts of this workflow.</blockquote><blockquote><strong>Room or Stage:</strong> A logical real-time space containing publishers and subscribers. VideoSDK calls it a room, while Amazon IVS uses a stage.</blockquote><blockquote><strong>Live-to-VOD:</strong> A workflow that converts a completed live broadcast into a reusable video asset. Mux and api.video treat this as a central product capability.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>VideoSDK is the strongest overall choice for an embedded interactive live streaming API, especially when viewers can become hosts inside a custom product.</li><li>Amazon IVS fits AWS-native stages and large broadcasts, while Agora remains a strong choice for social-live and mobile interaction.</li><li>Mux, Cloudflare Stream, and api.video favour encoder-to-player workflows, analytics, delivery, and live-to-VOD over natural two-way media.</li><li>LiveKit and Ant Media provide more deployment control, but self-hosting shifts scaling, upgrades, security, and observability back to your team.</li><li>Vendor latency figures are not interchangeable, so test glass-to-glass delay with your encoders, players, devices, countries, and network conditions.</li></ul><h2 id="conclusion">Conclusion</h2><p>The right choice among these Wowza alternatives depends on the media path you are replacing. VideoSDK is our recommendation for custom, interactive live products, not for every Wowza workload.</p><p>Start with the <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start-js-ils"><u>VideoSDK live streaming quickstart</u></a> or <a href="https://app.videosdk.live/login"><u>create an account with the free $20 balance</u></a>. What are you building with VideoSDK? Share your live streaming use case in the comments.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-best-alternative-to-wowza-1">What is the best alternative to Wowza?</h3><p>The best alternative to Wowza for embedded interactive streaming is VideoSDK because it combines real-time media, host and audience modes, role switching, engagement features, and client SDKs. Amazon IVS is better for AWS-native scale, while Ant Media better matches self-hosted protocol control.</p><h3 id="how-much-does-wowza-cost">How much does Wowza cost?</h3><p>Wowza Streaming Engine currently lists a $195 monthly Basic licence for the first instance, a $295 one-month licence, and custom Enterprise pricing. Infrastructure, bandwidth, CDN delivery, support, and additional transcoded channels can increase the total cost.</p><h3 id="is-wowza-free">Is Wowza free?</h3><p>Wowza offers trials, but its production Streaming Engine plans are paid. Developers evaluating alternatives should compare the full production workload, not only whether a temporary trial or starting credit is available.</p><h3 id="why-are-developers-moving-away-from-wowza">Why are developers moving away from Wowza?</h3><p>Developers consider moving away from Wowza when they want managed scaling, client SDKs, built-in participant roles, simpler live-to-VOD workflows, or usage-based billing. Teams that need on-premises control and broad protocol support may still prefer Wowza.</p><h3 id="what-is-the-cheapest-wowza-alternative">What is the cheapest Wowza alternative?</h3><p>The cheapest Wowza alternative depends on the workload. Cloudflare Stream can be economical for passive delivery, while VideoSDK, Agora, and 100ms meter interactive or viewer usage differently. Model one realistic event before choosing.</p><h3 id="is-there-an-open-source-wowza-alternative">Is there an open-source Wowza alternative?</h3><p>Yes. LiveKit is an open-source WebRTC platform with an optional managed cloud service. Ant Media also offers a Community Edition, while its broader enterprise streaming features use commercial licences.</p><h3 id="can-videosdk-replace-wowza-streaming-engine">Can VideoSDK replace Wowza Streaming Engine?</h3><p>VideoSDK can replace the interactive application layer of a Wowza deployment, including host and viewer media, participant roles, recording, engagement, and RTMP output. It does not replace on-premises media-server deployment, RTSP routing, or broad protocol conversion.</p><h3 id="which-wowza-alternative-has-the-lowest-latency">Which Wowza alternative has the lowest latency?</h3><p>The lowest published figures come from real-time WebRTC products such as VideoSDK, Amazon IVS stages, Agora, LiveKit, ZEGOCLOUD, and Ant Media. Compare them under the same device, geography, bitrate, network, and audience conditions.</p><h2 id="about-the-author">About the Author</h2><p>The VideoSDK Editorial Team creates technical resources for developers building real-time audio, video, and interactive live streaming products. Product and pricing claims were checked against official documentation on July 24, 2026.</p><h2 id="further-reading">Further Reading</h2><ul><li><a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/concept-and-architecture"><u>VideoSDK interactive live streaming concepts and architecture</u></a></li><li><a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start-js-ils"><u>VideoSDK JavaScript interactive live streaming quickstart</u></a></li><li><a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/analytics/understanding-analytics-dashboard"><u>VideoSDK live stream analytics</u></a></li><li><a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/rtmp-livestream"><u>VideoSDK RTMP livestream documentation</u></a></li><li><a href="https://docs.videosdk.live/code-sample"><u>VideoSDK code samples</u></a></li></ul>]]></content:encoded></item><item><title><![CDATA[Top 10 MirrorFly Alternatives for Video Calling APIs  in 2026]]></title><description><![CDATA[Compare the top MirrorFly alternatives for embedded video calling in 2026, with pricing, developer experience, trade-offs, and migration guidance.]]></description><link>https://www.videosdk.live/blog/mirrorfly-alternatives</link><guid isPermaLink="false">6a6213f2b3240feb748c8896</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 24 Jul 2026 10:16:28 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Generated-image-1--6-.png" class="kg-image" alt="Top 10 MirrorFly Alternatives for video calling API" loading="lazy" width="1672" height="941"/></figure><blockquote>The strongest MirrorFly alternatives for video calling in 2026 is VideoSDK for balanced multi-platform development, Daily for fast web embedding, and LiveKit for open-source control. Agora is a strong fit for global media delivery, while 100ms suits role-driven classrooms and events. Choose by deployment, client platforms, UI strategy, and total production cost.</blockquote><p><a href="https://www.mirrorfly.com/" rel="noreferrer nofollow">MirrorFly</a> combines chat, voice, video, live streaming, and deployment choices. That breadth is useful when you want a complete communication stack, but it can be unnecessary when your product only needs a programmable video calling API.</p><p>This guide compares ten video-focused options using the same documented criteria. VideoSDK ranks first for the balanced requirements in this rubric, not for every project. Pricing and product status were checked on July 23, 2026.</p><p><strong>Editorial disclosure:</strong> This is a documentation-based product evaluation, not a synthetic latency benchmark or a claim of undisclosed hands-on testing. Run a proof of concept on your real devices, networks, and user regions before signing a production contract.</p><h2 id="mirrorfly-alternatives-at-a-glance">MirrorFly Alternatives at a Glance</h2><p>The leading MirrorFly alternatives split into managed developer platforms, open-source infrastructure, enterprise video networks, and cloud-specific services.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Rank and provider</th>
<th style="text-align:right">Editorial score</th>
<th style="text-align:right">Docs and DX score</th>
<th>Best for</th>
<th>Public pricing signal</th>
</tr>
</thead>
<tbody>
<tr>
<td>1. VideoSDK</td>
<td style="text-align:right">91/100</td>
<td style="text-align:right">4.8/5</td>
<td>Broad multi-platform custom or Prebuilt calls</td>
<td>Pay as you go; one-time $20 new-account balance</td>
</tr>
<tr>
<td>2. Daily</td>
<td style="text-align:right">89/100</td>
<td style="text-align:right">4.7/5</td>
<td>Fast web-first embedding</td>
<td>10,000 free minutes monthly, then $0.004 per participant-minute</td>
</tr>
<tr>
<td>3. LiveKit</td>
<td style="text-align:right">87/100</td>
<td style="text-align:right">4.5/5</td>
<td>Open-source control with a managed option</td>
<td>Free Build plan; Ship starts at $50 monthly, plus usage meters</td>
</tr>
<tr>
<td>4. Agora</td>
<td style="text-align:right">86/100</td>
<td style="text-align:right">4.2/5</td>
<td>Global media delivery and difficult networks</td>
<td>10,000 free minutes monthly; HD starts at $3.99 per 1,000 minutes</td>
</tr>
<tr>
<td>5. 100ms</td>
<td style="text-align:right">84/100</td>
<td style="text-align:right">4.4/5</td>
<td>Classrooms, communities, and role-based sessions</td>
<td>10,000 free minutes monthly, then $0.004 per participant-minute</td>
</tr>
<tr>
<td>6. Zoom Video SDK</td>
<td style="text-align:right">82/100</td>
<td style="text-align:right">4.0/5</td>
<td>Large sessions and raw-media workflows</td>
<td>10,000 free minutes monthly; $0.0035 per session-minute after that</td>
</tr>
<tr>
<td>7. Cloudflare RealtimeKit</td>
<td style="text-align:right">80/100</td>
<td style="text-align:right">4.1/5</td>
<td>Cloudflare-native teams that can accept beta risk</td>
<td>Free during beta; announced GA rate is $0.002 per video participant-minute</td>
</tr>
<tr>
<td>8. Twilio Video</td>
<td style="text-align:right">78/100</td>
<td style="text-align:right">4.0/5</td>
<td>Existing Twilio web and mobile stacks</td>
<td>$0.004 per participant-minute</td>
</tr>
<tr>
<td>9. Vonage Video API</td>
<td style="text-align:right">77/100</td>
<td style="text-align:right">3.8/5</td>
<td>Enterprise controls, broadcast, and media connectors</td>
<td>$0.00410 per participant-minute</td>
</tr>
<tr>
<td>10. Amazon Chime SDK</td>
<td style="text-align:right">75/100</td>
<td style="text-align:right">3.5/5</td>
<td>AWS-native teams optimizing base media cost</td>
<td>$0.0017 per attendee-minute, with separate feature charges</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>VideoSDK leads this balanced rubric because its <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">current documentation</a> combines prebuilt and custom paths with client coverage across web, native mobile, Flutter, Unity, C++, IoT, and Python. LiveKit moves to the front when owning the media server matters more than using a managed platform.</p><p>The pricing column is not a cheapest-to-costliest ranking. Providers bill different units, and recording, data transfer, transcription, support, compliance, and engineering ownership can reverse an apparent base-price advantage.</p><h2 id="what-are-mirrorfly-alternatives">What Are MirrorFly Alternatives?</h2><p>MirrorFly alternatives are <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">video calling APIs or SDKs</a> that can replace MirrorFly's embedded audio-video layer without requiring its broader messaging stack.</p><p>MirrorFly alternatives are defined as programmable services that provide rooms, participants, media tracks, authentication, recording, screen sharing, and related real-time media infrastructure. They work by replacing MirrorFly's client SDK and backend call orchestration with another provider's room, token, and event model.</p><p>This scope matters because MirrorFly covers chat, voice, video, live streaming, SIP, activity feeds, and self-hosted deployment. A video-only buyer should not score SMS, social feeds, or contact-center tools as if they improve call quality.</p><p>The <a href="https://www.w3.org/TR/webrtc/">W3C WebRTC specification</a> standardizes browser APIs for sending media and application data. Production calling still needs signaling, <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a> connectivity, media routing, authentication, observability, recording, and recovery logic. Each provider packages those operational layers differently.</p><p>VideoSDK is one of these MirrorFly alternatives. Its platform menu includes JavaScript, React, React Native, Android, iOS, Flutter, Unity, IoT, C++, Python, and REST APIs. It also offers <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Prebuilt video calling</a> for teams that do not want to build the first meeting interface from scratch.</p><h2 id="mirrorfly-pricing-in-2026">MirrorFly Pricing in 2026</h2><p>MirrorFly pricing is difficult to reduce to one number because its public pages describe more than one commercial model.</p><p>The current <a href="https://www.mirrorfly.com/pricing.php" rel="nofollow">MirrorFly SaaS pricing page</a> says cost changes with monthly active users. Voice and video calling sit in the Premium tier, which lists up to 7,500 minutes. The same page publishes overage rates of $0.001 per minute for 1-to-1 calls and $0.0015 per minute for group calls, but it does not expose a stable base subscription price in accessible page text.</p><p>MirrorFly also markets a self-managed or lifetime-license path with custom pricing, source-code access, and deployment on your own infrastructure. That model is commercially different from a monthly MAU-based SaaS plan, so a one-time license quote should not be compared directly with a participant-minute API rate.</p><p>There is another reason to confirm terms with sales. The pricing table promotes a 21-day trial for paid tiers, while an FAQ on the same page says MirrorFly does not offer a free trial and provides a demo instead.</p><p>For a useful MirrorFly pricing quote, ask for these items in writing:</p><ul><li>The base fee at your projected monthly active users and peak concurrency.</li><li>The included 1-to-1 and group call minutes, plus the exact billing unit for overages.</li><li>Recording, storage, transcription, streaming, and data-transfer charges.</li><li>Dedicated cloud, on-premises, source-code, upgrade, and maintenance costs.</li><li>Support response targets, service-level commitments, and paid compliance requirements.</li></ul><p>Pricing opacity does not automatically make MirrorFly expensive. It does mean that buyers should compare a complete quote against the full production cost of each alternative, not against one advertised per-minute rate.</p><h2 id="how-we-ranked-mirrorfly-alternatives">How We Ranked MirrorFly Alternatives</h2><p>A useful ranking must disclose what it rewards because no video calling API leads on every technical and commercial requirement.</p><p>The ranking uses a 100-point editorial rubric for an intermediate development team shipping embedded calls. Scores reflect public documentation and pricing, not undisclosed commercial relationships or laboratory performance.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Evaluation dimension</th>
<th style="text-align:right">Weight</th>
<th>What received a higher score</th>
</tr>
</thead>
<tbody>
<tr>
<td>Video API and SDK depth</td>
<td style="text-align:right">25</td>
<td>Rooms, tracks, screen sharing, recording, network controls, and production tooling</td>
</tr>
<tr>
<td>Developer experience</td>
<td style="text-align:right">20</td>
<td>Clear quickstarts, secure token flow, runnable samples, Prebuilt or UI Kit, and manageable APIs</td>
</tr>
<tr>
<td>Platform coverage</td>
<td style="text-align:right">20</td>
<td>Web, native mobile, cross-platform, desktop, game-engine, and server options</td>
</tr>
<tr>
<td>Customization and collaboration</td>
<td style="text-align:right">15</td>
<td>Custom UI, roles, chat, captions, whiteboard, polls, and layout control</td>
</tr>
<tr>
<td>Deployment and security</td>
<td style="text-align:right">10</td>
<td>Managed reliability, self-hosting choices, regional controls, encryption, and compliance options</td>
</tr>
<tr>
<td>Pricing clarity</td>
<td style="text-align:right">10</td>
<td>Public rates, free usage, predictable meters, and usable cost documentation</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>The separate Docs and DX score is a reproducible five-point editorial check. Each provider earns up to one point for a clear quickstart, understandable authentication, runnable samples, a UI acceleration path, and consistent platform documentation. It does not measure media quality or network latency.</p><p>Pricing was checked on July 24, 2026. Rates exclude negotiated discounts, taxes, paid support, storage, transcription, and other add-ons unless stated.</p><h2 id="top-10-mirrorfly-alternatives-ranked">Top 10 MirrorFly Alternatives Ranked</h2><p>These ten MirrorFly alternatives cover the strongest video calling API paths for teams replacing only MirrorFly's real-time media layer.</p><p>Each entry uses the same structure: why it ranks, its best-fit project, a meaningful trade-off, its documentation score, and its public pricing signal.</p><h3 id="1-videosdk-best-balanced-video-api">1. VideoSDK: Best Balanced Video API</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.29.39-PM-1.png" class="kg-image" alt="VideoSDK Homepage" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> ranks first for teams that need rapid launch and deep interface control across web, mobile, cross-platform, and specialized clients.</p><p>The <a href="https://docs.videosdk.live/">VideoSDK documentation</a> lists JavaScript, React, React Native, Android, iOS, Flutter, Unity, IoT, C++, Python, REST APIs, and a Prebuilt UI Kit. Its calling documentation covers rooms, participant and track APIs, screen sharing, recording, transcription, collaboration, geo-fencing, proxy controls, and security guidance.</p><p>Teams can begin with Prebuilt, then move to a custom UI while keeping the same managed RTC platform. That path reduces the risk of choosing a quick embed that later blocks product-specific layouts or controls.</p><p><strong>Best for:</strong> Product teams supporting several frameworks, mobile platforms, Unity, C++, or IoT clients while keeping one managed room model.</p><p><strong>Trade-off:</strong> VideoSDK does not replace MirrorFly's self-hosted source-code proposition. If your policy requires operating the media server yourself, evaluate LiveKit before committing.</p><p><strong>Docs and DX score:</strong> 4.8/5. The platform provides a direct React quickstart, room creation flow, token guidance, a prebuilt path, and <a href="https://docs.videosdk.live/code-sample">code samples</a> across its SDK surface.</p><p><strong>Pricing:</strong> <a href="https://www.videosdk.live/pricing"><u>VideoSDK's pay-as-you-go pricing</u></a> is <strong>$0.001</strong> per participant-minute for audio calls, <strong>$0.004</strong> per participant-minute for video calls, and <strong>$0.002</strong> per viewer-minute for live streaming. and a $20 free credit for new accounts. </p><h3 id="2-daily-best-for-fast-web-embedding">2. Daily: Best for Fast Web Embedding</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.02-PM-1.png" class="kg-image" alt="Daily Homepage" loading="lazy" width="2924" height="1652"/></figure><p><a href="https://www.daily.co/" rel="noreferrer nofollow">Daily</a> ranks second because it offers a clear choice between Daily Prebuilt for fast embedding and client SDKs for custom interfaces.</p><p>Daily's platform is especially approachable for browser products. Its documentation covers REST-created rooms, meeting tokens, track subscriptions, recording, <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a>, <a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer">HLS</a>, telephony, and bandwidth management. Prebuilt gives an MVP a complete meeting interface while the product team validates demand.</p><p><strong>Best for:</strong> Web-first SaaS, telehealth, interviews, and support products that value quick embedding and straightforward participant-minute billing.</p><p><strong>Trade-off:</strong> Daily's documented client range is narrower than VideoSDK's coverage of Flutter, Unity, C++, and IoT. Verify every target platform before standardising on one provider.</p><p><strong>Docs and DX score:</strong> 4.7/5. Daily has strong web examples, an understandable room model, Prebuilt, and a pricing calculator that helps teams model early usage.</p><p><strong>Pricing:</strong> <a href="https://www.daily.co/pricing/video-sdk/" rel="noreferrer nofollow">Daily pricing</a> includes 10,000 video and audio participant-minutes each month. The next 90,000 minutes cost $0.004 per participant-minute, with automatic volume discounts at higher tiers. Recording and streaming use separate rates.</p><p>Daily is the strongest alternative when browser deployment speed outranks unusual platform coverage. Its public calculator also makes early budget discussions easier than contact-sales-only pricing.</p><h3 id="3-livekit-best-for-open-source-control">3. LiveKit: Best for Open-Source Control</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.40-PM-1.png" class="kg-image" alt="LiveKit Homepage" loading="lazy" width="2920" height="1670"/></figure><p><a href="https://livekit.com/" rel="noreferrer nofollow">LiveKit</a> ranks third because it offers a compatible API family across its open-source server and managed cloud.</p><p>That portability is valuable when a team wants a managed launch without giving up a future self-hosted path. LiveKit provides WebRTC rooms, tracks, data, ingress, egress, recording, encryption options, <a href="https://www.videosdk.live/developer-hub/sip/mastering-sip-protocol-comprehensive-guide" rel="noreferrer">SIP</a>, and broad client SDKs. The cloud adds a global network, analytics, region controls, and managed operations.</p><p><strong>Best for:</strong> Engineering-heavy teams that want source access, custom media workflows, or the option to move between managed and self-operated infrastructure.</p><p><strong>Trade-off:</strong> Self-hosting moves upgrades, autoscaling, observability, TURN, egress, and incident response onto your team. LiveKit Cloud also meters connection minutes and downstream data, so video costs require bandwidth modeling.</p><p><strong>Docs and DX score:</strong> 4.5/5. The open-source code, coherent concepts, and detailed deployment documentation score well. The number of infrastructure choices adds cognitive load for teams seeking a fully managed path.</p><p><strong>Pricing:</strong> The <a href="https://livekit.io/pricing" rel="noreferrer nofollow">LiveKit pricing page</a> lists a free Build plan. Its published free allowances include 5,000 WebRTC participant-minutes and 50 GB of downstream transfer. Ship starts at $50 monthly, with separate usage meters for media, data transfer, and transcoding.</p><p>LiveKit should move above the managed-first options when infrastructure ownership is non-negotiable.</p><h3 id="4-agora-best-for-global-media-reach">4. Agora: Best for Global Media Reach</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.26-PM-1.png" class="kg-image" alt="Agora Homepage" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/en/" rel="noreferrer nofollow">Agora</a> ranks fourth for its large real-time network, broad client range, mature media controls, and calling plus streaming portfolio. </p><p>Agora supports major web, mobile, desktop, cross-platform, and game-engine clients. The platform also offers recording, analytics, cloud proxy, audio processing, signalling, a whiteboard, and interactive live streaming.</p><p><strong>Best for:</strong> Social, gaming, education, and event products expecting geographically distributed users or difficult network conditions.</p><p><strong>Trade-off:</strong> Agora's product and add-on catalogue can increase integration and billing complexity. Separate essential media features from optional analytics, proxy, whiteboard, transcription, and recording services.</p><p><strong>Docs and DX score:</strong> 4.2/5. The documentation is deep and the platform range is wide, but developers must navigate more products, modes, and pricing dimensions than with a smaller API surface.</p><p><strong>Pricing:</strong> <a href="https://www.agora.io/en/pricing/video-calling/" rel="noreferrer nofollow">Agora video pricing</a> includes 10,000 minutes per month in the free bundle. Published usage rates start at $3.99 per 1,000 HD participant-minutes and rise with aggregate resolution. Cloud proxy, recording, and analytics can add separate costs.</p><p>Agora should move above Daily or LiveKit when verified geographic performance is the primary decision axis. Test representative devices and user regions instead of relying on a vendor-wide latency claim.</p><h3 id="5-100ms-best-for-role-based-sessions">5. 100ms: Best for Role-Based Sessions</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.31.12-PM-2.png" class="kg-image" alt="100ms Homepage" loading="lazy" width="2910" height="1656"/></figure><p><a href="https://www.100ms.live/" rel="noreferrer nofollow">100ms</a> ranks fifth because its rooms, templates, and roles suit products with hosts, guests, speakers, viewers, teachers, and students. </p><p>The platform supports custom and prebuilt experiences across web and mobile frameworks. It also covers conferencing, interactive live streaming, recording, transcription, summaries, whiteboards, RTMP output, and noise cancellation.</p><p><strong>Best for:</strong> Virtual classrooms, fitness, communities, <a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">video KYC</a>, and events with predictable participant permissions and recurring session patterns.</p><p><strong>Trade-off:</strong> A template-first model is useful when roles drive the product, but it can add setup when a team only needs a small 1-to-1 calling flow. Feature support should also be verified per target SDK.</p><p><strong>Docs and DX score:</strong> 4.4/5. The quickstart and role model are clear, Prebuilt shortens the first implementation, and the dashboard makes recurring room permissions easier to reason about.</p><p><strong>Pricing:</strong> <a href="https://www.100ms.live/pricing" rel="noreferrer nofollow">100ms pricing</a> includes 10,000 conferencing minutes monthly. Usage after the allowance is $0.004 per participant-minute. Recording, live transcription, external streaming, and summaries use separate meters.</p><p>100ms is a strong MirrorFly alternative when room roles are part of the product model rather than an afterthought.</p><h3 id="6-zoom-video-sdk-best-for-large-sessions">6. Zoom Video SDK: Best for Large Sessions</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.32.46-PM-1.png" class="kg-image" alt="Zoom Video SDK Homepage" loading="lazy" width="2920" height="1646"/></figure><p><a href="https://www.zoom.com/en/video-sdk/" rel="noreferrer nofollow">Zoom Video SDK</a> places Zoom's underlying media technology inside a custom application instead of putting users into standard Zoom meetings.</p><p>The platform supports web, mobile, desktop, cross-platform, and Unity clients. Zoom documents audio, video, screen sharing, chat, raw data, cloud recording, transcription, translation, PSTN, live streaming, sub-sessions, and a UI toolkit. Its web documentation states that a Video SDK session can support up to 5,000 users.</p><p><strong>Best for:</strong> Enterprise applications that need large sessions, raw-media access, native desktop coverage, or alignment with an existing Zoom commercial relationship.</p><p><strong>Trade-off:</strong> The Video SDK sits inside a larger platform and billing system. Teams should distinguish Video SDK sessions from Zoom Meetings and model credit consumption for recording, transcription, PSTN, and support.</p><p><strong>Docs and DX score:</strong> 4.0/5. Zoom provides detailed lifecycle and event guidance, but developers must navigate account plans, SDK credentials, JWT rules, and a broad platform catalog.</p><p><strong>Pricing:</strong> Zoom's <a href="https://developers.zoom.us/blog/video-sdk-fact-sheet/" rel="noreferrer nofollow">Video SDK fact sheet</a> lists 10,000 free minutes per month and $0.0035 per minute after the allowance, with volume discounts. Confirm current build credit terms for your account.</p><p>The Zoom Video SDK deserves a higher rank when session scale or raw-media access is decisive. It is less direct for teams seeking a small billing and product surface.</p><h3 id="7-cloudflare-realtimekit-best-cloudflare-native-bet">7. Cloudflare RealtimeKit: Best Cloudflare-Native Bet</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.51.09-PM.png" class="kg-image" alt="Cloudflare RealtimeKit Homepage" loading="lazy" width="2918" height="1644"/></figure><p><a href="https://realtime.cloudflare.com/" rel="noreferrer nofollow">Cloudflare RealtimeKit</a> combines web and mobile SDKs, UI components, a managed SFU, recording, transcription, and Cloudflare account integration.</p><p>The team behind Dyte joined Cloudflare to build RealtimeKit. Current Cloudflare documentation covers React, Angular, Web Components, JavaScript, iOS, Android, React Native, and Flutter, plus server APIs for meetings, participants, recordings, and webhooks.</p><p><strong>Best for:</strong> Teams already using Cloudflare Workers, R2, TURN, or edge services that can responsibly adopt a beta product.</p><p><strong>Trade-off:</strong> RealtimeKit remains in beta as of July 23, 2026. Production buyers should validate support, limits, migration commitments, regional behavior, and general-availability terms.</p><p><strong>Docs and DX score:</strong> 4.1/5. Cloudflare provides a current quick start, UI kit, Core SDK, package-specific release notes, and a clear backend token flow. Beta lifecycle risk reduces the overall score.</p><p><strong>Pricing: </strong><a href="https://developers.cloudflare.com/realtime/realtimekit/pricing/" rel="noreferrer nofollow">Cloudflare RealtimeKit pricing</a> states that beta usage is free. The announced GA model lists $0.002 per audio-video participant-minute and $0.010 per export minute.</p><p>RealtimeKit is the most important new entrant in this ranking, but beta status keeps it below mature production platforms.</p><h3 id="8-twilio-video-best-for-twilio-customers">8. Twilio Video: Best for Twilio Customers</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.53.31-PM.png" class="kg-image" alt="Twilio Video Homepage" loading="lazy" width="2910" height="1638"/></figure><p><a href="https://www.twilio.com/en-us/video" rel="noreferrer nofollow">Twilio Video</a> remains an active programmable video product for JavaScript, iOS, and Android.</p><p>Its <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> room model includes screen sharing, recordings, noise cancellation, virtual backgrounds, dominant-speaker detection, network quality controls, and Video Insights. Existing Twilio customers can combine video with Voice, conversations, phone numbers, and one account relationship.</p><p><strong>Best for:</strong> Teams already standardised on Twilio that need video alongside other Twilio communications products.</p><p><strong>Trade-off:</strong> Twilio documents a narrower native client set than the highest-ranked alternatives, and Group Rooms support up to 50 participants. Cross-platform frameworks may require wrappers or a different client strategy.</p><p><strong>Docs and DX score:</strong> 4.0/5. Twilio has mature documentation and samples, but client breadth and a multi-product account surface reduce its fit as a platform-agnostic replacement.</p><p><strong>Pricing:</strong> <a href="https://www.twilio.com/en-us/video/pricing" rel="noreferrer nofollow">Twilio Video pricing</a> starts at $0.004 per participant-minute. Participant recording also costs $0.004 per participant-minute, while composition, transcription, and storage use separate meters.</p><p>One correction matters here: Twilio Video is not scheduled to close in December 2026. Twilio <a href="https://www.twilio.com/en-us/changelog/-twilio-video-will-remain-a-standalone-product" rel="noreferrer nofollow">reversed the retirement decision</a> in October 2024 and continues to accept new video customers.</p><h3 id="9-vonage-video-api-best-enterprise-add-ons">9. Vonage Video API: Best Enterprise Add-Ons</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.32.16-PM-1.png" class="kg-image" alt="Vonage Video API Homepage" loading="lazy" width="2922" height="1652"/></figure><p><a href="https://www.vonage.com/communications-apis/video/" rel="noreferrer nofollow">Vonage Video API</a>, formerly associated with OpenTok and TokBox, provides interactive video, signalling, chat, screen sharing, broadcasting, recording, captions, and media connectors.</p><p>Its current client catalogue covers web and several native platforms. Vonage also sells enterprise environments, regional media zones, firewall controls, advanced insights, encryption options, SIP connectivity, and commercial support.</p><p><strong>Best for:</strong> Enterprises that need broadcast modes, captions, media connectors, regional controls, configurable firewall behaviour, or support around a mature programmable-video stack.</p><p><strong>Trade-off:</strong> Several security and operational controls carry monthly add-on fees. Price regional zones, advanced insights, encrypted recordings, enterprise environments, and support before comparing the base media rate.</p><p><strong>Docs and DX score:</strong> 3.8/5. Vonage has detailed media and enterprise documentation, but the OpenTok heritage and number of optional controls create a steeper evaluation path.</p><p><strong>Pricing:</strong> <a href="https://www.vonage.com/communications-apis/video/pricing/" rel="noreferrer nofollow">Vonage Video API pricing</a> lists $0.00410 per participant-minute and 100,000 free minutes for new Video API customers. Recording, composition, captions, and enterprise controls are separate.</p><p>Vonage becomes more compelling when its paid control plane solves a requirement that a simpler managed API does not.</p><h3 id="10-amazon-chime-sdk-best-for-aws-native-teams">10. Amazon Chime SDK: Best for AWS-Native Teams</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.54.40-PM.png" class="kg-image" alt="Amazon Chime SDK Homepage" loading="lazy" width="2918" height="1632"/></figure><p><a href="https://aws.amazon.com/chime/chime-sdk/" rel="noreferrer nofollow">Amazon Chime SDK</a> adds audio, video, screen sharing, and related real-time components to web and mobile applications.</p><p>AWS provides meeting regions, media pipelines, simulcast, active-speaker handling, content sharing, and integrations with services such as S3, Lambda, Kinesis Video Streams, and Transcribe.</p><p><strong>Best for:</strong> Teams already using AWS identity, compute, storage, streaming, observability, and regional infrastructure.</p><p><strong>Trade-off:</strong> Chime SDK offers fewer client frameworks and less turnkey UI than higher-ranked options. Building the full meeting product and connecting AWS services can require more backend engineering.</p><p><strong>Docs and DX score:</strong> 3.5/5. AWS documentation is detailed and operationally precise, but the experience is infrastructure-orientated and spread across several AWS services.</p><p><strong>Pricing:</strong> <a href="https://aws.amazon.com/chime/chime-sdk/pricing/" rel="noreferrer nofollow">Amazon Chime SDK pricing</a> lists $0.0017 per WebRTC attendee-minute with no upfront fee. Media capture, concatenation, live connectors, transcription, Lambda, Kinesis, and storage can add separate charges.</p><p>Do not confuse the SDK with the discontinued Amazon Chime workplace application. AWS ended support for the application on February 20, 2026, but states that this change does not affect Amazon Chime SDK availability.</p><h2 id="which-mirrorfly-alternative-should-you-choose">Which MirrorFly Alternative Should You Choose?</h2><p>Choose the provider whose strongest condition matches your non-negotiable requirement, then test its weaker dimensions before committing.</p><ul><li><strong>Use VideoSDK</strong> when you need one managed video API across web, native mobile, Flutter, Unity, C++, IoT, custom UI, and Prebuilt experiences.</li><li><strong>Use Daily</strong> when the fastest credible browser embed and transparent participant-minute billing matter more than unusual client targets.</li><li><strong>Use LiveKit</strong> when source access, self-hosting, custom media infrastructure, or a managed-to-self-hosted path is mandatory.</li><li><strong>Use Agora</strong> when verified global reach, difficult networks, game-engine support, or large media operations dominate the decision.</li><li><strong>Use 100ms</strong> when room templates, participant roles, classrooms, communities, or staged events define the product.</li><li><strong>Use Zoom Video SDK</strong> when large sessions, raw media, native desktop support, or an existing Zoom relationship outweigh pricing simplicity.</li><li><strong>Use Cloudflare RealtimeKit</strong> when your application already relies on Cloudflare and your team can accept beta lifecycle risk.</li><li><strong>Use Twilio, Vonage, or Amazon Chime SDK</strong> when an existing communications or cloud ecosystem creates more value than an independent video platform.</li></ul><p>Do not switch solely because another provider advertises a lower media rate. A complete comparison includes participant-minutes, resolution, recording, storage, transcription, egress, support, compliance, and engineering ownership.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Updated-decision-tree.png" class="kg-image" alt="Decision tree for choosing MirrorFly alternatives for video calling APIs, including VideoSDK, Daily, LiveKit, Agora, and 100ms." loading="lazy" width="1600" height="900"/></figure><p><em>Use the decision tree to form a shortlist, then run a two-provider proof of concept on target devices and user regions.</em></p><h2 id="mirrorfly-migration-checklist">MirrorFly Migration Checklist</h2><p>MirrorFly and a replacement API can run side by side during migration, but participants cannot normally share one native room across providers.</p><p>A phased cutover is safer than replacing every room at once. Route new rooms to the replacement while existing scheduled rooms remain on MirrorFly.</p><ol><li><strong>Inventory current call behaviour.</strong> Record room roles, participant limits, waiting-room rules, screen sharing, recording layouts, captions, reconnection behaviour, moderation, and mobile background requirements.</li><li><strong>Map the core objects.</strong> Translate MirrorFly rooms, users, call events, and media tracks to the replacement's room, participant, token, event, and track concepts.</li><li><strong>Build a provider adapter.</strong> Keep join, leave, mute, camera, screen share, participant events, and recording calls behind your own application interface. This prevents vendor-specific methods from spreading through the product.</li><li><strong>Move authentication server-side.</strong> Generate replacement tokens on a trusted backend, apply the minimum required permissions, and test expiry and refresh behavior. Do not copy long-lived credentials into the client.</li><li><strong>Dual-run controlled traffic.</strong> Send internal calls and a small percentage of new rooms to the replacement while preserving an immediate route back to MirrorFly.</li><li><strong>Test real network conditions.</strong> Measure join success, time to first media, packet loss, reconnection, CPU use, battery use, and quality across target devices, browsers, and regions.</li><li><strong>Validate downstream systems.</strong> Confirm recording webhooks, storage, consent, retention, transcription, analytics, moderation, support, and incident procedures before increasing traffic.</li><li><strong>Move scheduled rooms last.</strong> Migrate future bookings only after tokens, notifications, deep links, and mobile call invitations work across released application versions.</li></ol><p>If your migration plan was triggered by the old Twilio retirement announcement, re-check the premise. Twilio Video remains active, so the decision should be based on product fit, not a deadline that no longer exists.</p><h2 id="video-calling-api-cost-model">Video Calling API Cost Model</h2><p>The cheapest headline rate can become expensive when the provider bills bandwidth, recording, composition, transcription, or enterprise controls separately.</p><p>Imagine TutorLoop, a fictional edtech app, runs 10,000 monthly tutoring sessions. Each session has one tutor and one student and lasts 30 minutes. Its billable usage is 600,000 participant-minutes before recording or add-ons.</p><p>At $0.004 per participant-minute, the base media layer costs $2,400 before free allowances or volume discounts. A service charging $0.0017 would cost $1,020 for the same attendee minutes, but capturing pipelines, storage, serverless processing, support, and extra engineering can narrow that gap.</p><p>Use this production formula:</p><pre><code class="language-text">Monthly video cost =
  participant-minutes
  + recording and composition
  + storage and delivery
  + transcription or translation
  + telephony or streaming
  + support and compliance
  + infrastructure engineering
</code></pre><p>For LiveKit, model downstream gigabytes as well as connection minutes. For Zoom, model build credit consumption. For MirrorFly, include the MAU-based base plan or self-hosted licence plus its bundled call allowance.</p><p>For VideoSDK, Daily, Agora, 100ms, Twilio, Vonage, and Amazon Chime SDK, use the current calculator or published metrics with your real participant distribution. Average room size can hide the cost of large sessions.</p><p>The most useful proof of concept measures cost and quality together. A lower unit rate has little value if your team must build missing UI, monitoring, reconnection, or compliance workflows.</p><h2 id="definitions-glossary">Definitions Glossary</h2><p>These terms explain the architecture and billing language used across VideoSDK, MirrorFly, and the other video calling APIs in this ranking.</p><blockquote><strong>Room:</strong> A logical real-time session that participants join to exchange audio, video, screen-share, and data tracks. VideoSDK identifies each room with a unique room ID.</blockquote><blockquote><strong>Participant-minute:</strong> One participant connected for one minute. A 30-minute call with four people usually creates 120 participant-minutes.</blockquote><blockquote><strong>Media track:</strong> An individual audio, camera, screen-share, or custom stream published by a participant. VideoSDK exposes participant streams through client SDK hooks and methods.</blockquote><blockquote><strong>Meeting token:</strong> A server-generated credential that authorizes a participant to join a room and perform allowed actions. API secrets should remain on a trusted server.</blockquote><blockquote><strong>Selective Forwarding Unit:</strong> An SFU receives participant media and forwards selected tracks without composing every call into one stream. This supports multi-party scaling and selective subscriptions.</blockquote><blockquote><strong>Prebuilt UI Kit:</strong> A ready-to-embed calling interface. VideoSDK Prebuilt provides a faster route to production when a fully custom meeting UI is unnecessary.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><p>MirrorFly alternatives become easier to compare when deployment, platform coverage, room model, lifecycle risk, and total cost are evaluated separately.</p><ul><li>VideoSDK is the strongest balanced MirrorFly alternative under this disclosed rubric because it combines broad SDK coverage, prebuilt and custom UIs, collaboration features, and managed infrastructure.</li><li>Daily is the strongest web-first option, while LiveKit deserves priority when open-source control or self-hosting is mandatory.</li><li>Agora and Zoom Video SDK suit scale-sensitive projects, while 100ms suits products organised around participant roles and recurring room templates.</li><li>Twilio Video remains active, Cloudflare RealtimeKit is still beta, and the Amazon Chime SDK remains available after the Chime workplace app ended.</li><li>MirrorFly pricing requires a complete quote because its public materials describe MAU-based SaaS and custom self-managed licensing rather than one comparable base rate.</li></ul><h2 id="conclusion">Conclusion</h2><p>The right MirrorFly alternatives shortlist depends on the video layer you are replacing.</p><p>VideoSDK is the balanced starting point for broad platform coverage, Prebuilt deployment, and custom calling interfaces. LiveKit is stronger for self-hosting, while Daily is stronger for web-first speed. Agora deserves a place in a geography-sensitive proof of concept, and 100ms is a natural fit when participant roles define the product.</p><p>Do not choose from a feature checklist alone. Validate your top two options with real devices, representative traffic, expired-token behavior, reconnection tests, recording workflows, and a complete cost model. Confirm the current billing unit and product status again before publication or procurement because these details change.</p><p>Start with the <a href="https://docs.videosdk.live/">VideoSDK documentation</a> or <a href="https://app.videosdk.live/login">create a free VideoSDK account</a> to build the first comparison room. What video calling use case are you building, and which requirement cannot be compromised?</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><p>These answers address the most common commercial and technical questions about MirrorFly alternatives for embedded video calling.</p><h3 id="what-is-the-best-mirrorfly-alternative-for-video-calling">What is the best MirrorFly alternative for video calling?</h3><p>The best-balanced MirrorFly alternative in this ranking is VideoSDK for teams that need broad client SDK coverage, prebuilt and custom interfaces, recording, collaboration, and managed infrastructure. Daily can be better for a web-first embed, while LiveKit can be better when self-hosting is mandatory.</p><h3 id="how-much-does-mirrorfly-cost-in-2026">How much does MirrorFly cost in 2026?</h3><p>MirrorFly does not publish one stable base price that covers every deployment model. Its SaaS page ties pricing to monthly active users and lists Premium call allowances and overages, while its self-managed offer uses custom license pricing. Ask sales for the base fee, included minutes, overages, hosting, support, and upgrade terms in one quote.</p><h3 id="is-videosdk-better-than-mirrorfly">Is VideoSDK better than MirrorFly?</h3><p>VideoSDK is a better fit when your priority is a focused, managed video calling API with broad SDK coverage and a choice between Prebuilt and custom user interfaces. MirrorFly can be a better fit when you need its bundled messaging stack, source-code access, or on-premises deployment.</p><h3 id="which-mirrorfly-alternative-supports-self-hosting">Which MirrorFly alternative supports self-hosting?</h3><p>LiveKit is the strongest API-focused self-hosting option in this ranking because its open-source server and managed cloud use the same core concepts. MirrorFly itself also markets self-managed deployment and source-code access. Most other providers in this list are managed-service choices.</p><h3 id="is-twilio-video-discontinued-in-2026">Is Twilio Video discontinued in 2026?</h3><p>No, Twilio Video is not discontinued in 2026. Twilio announced an end-of-life plan, then reversed the decision on October 21, 2024. Twilio says Video remains a standalone product for existing and new customers.</p><h3 id="can-mirrorfly-and-videosdk-run-together-during-migration">Can MirrorFly and VideoSDK run together during migration?</h3><p>Yes, MirrorFly and VideoSDK can run side by side at the application level during a phased migration. New rooms can use VideoSDK, while existing scheduled rooms remain on MirrorFly. Participants will not normally share one native room across both providers, so store the provider on each room and load the correct adapter.</p><h2 id="related-videosdk-guides">Related VideoSDK Guides</h2><p>These VideoSDK guides cover the implementation paths referenced in the ranking, including custom React rooms, prebuilt calls, REST APIs, and runnable samples.</p><ul><li><a href="https://docs.videosdk.live/">VideoSDK audio and video calling documentation</a></li><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React video calling quickstart</a></li><li><a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Prebuilt video and audio calling quickstart</a></li><li><a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">Real-time communication REST API reference</a></li><li><a href="https://docs.videosdk.live/code-sample">VideoSDK code samples</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Top 10 CometChat Alternatives in 2026: Expert-Tested & Ranked]]></title><description><![CDATA[Compare ten CometChat alternative video calling APIs using a transparent 2026 framework covering SDK breadth, Prebuilt UI, pricing, deployment, production features, and migration fit.]]></description><link>https://www.videosdk.live/blog/cometchat-alternatives</link><guid isPermaLink="false">6a620df3b3240feb748c8857</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 24 Jul 2026 09:47:03 GMT</pubDate><content:encoded><![CDATA[<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Generated-image-1--7--1.png" class="kg-image" alt="CometChat Alternatives" loading="lazy" width="1672" height="941"/></figure><blockquote>For video-first products, the strongest CometChat alternative in this review is VideoSDK because it combines Prebuilt and custom SDK paths across web, mobile, Unity, C++, Python, and IoT. Daily is better for the fastest browser embed, while LiveKit is better when self-hosting is mandatory. Keep CometChat for persistent chat if messaging remains part of your product.</blockquote><h2 id="what-is-cometchat"><strong>What is CometChat?</strong></h2><p><a href="https://www.cometchat.com/" rel="noreferrer nofollow">CometChat</a> combines messaging, voice, and video. That breadth is useful, but teams building telehealth, tutoring, recruitment, or social video often need deeper RTC controls and clearer media pricing.</p><p>This guide ranks ten <a href="https://www.videosdk.live/blog/10-best-video-calling-apis" rel="noreferrer">video calling APIs</a> using current documentation, public pricing, supported platforms, production features, and migration fit. It explains where VideoSDK leads and where another provider has the stronger case.</p><h2 id="what-is-a-cometchat-alternative-for-video-calling">What Is a CometChat Alternative for Video Calling?</h2><p>A CometChat alternative is defined as an API or SDK that can replace CometChat Calls across web, mobile, desktop, game-engine, or connected-device applications.</p><p>A <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">video calling SDK</a> works by handling authentication, signalling, WebRTC transport, media routing, participant events, network adaptation, and optional recording behind a developer-facing client and server API.</p><p>CometChat remains a valid baseline. Its current Calls documentation describes a WebRTC-based voice and video solution with participant controls, recording, layouts, and calling flows. The platform can support up to 50 participants per call according to its Calls API overview.</p><p>The decision to switch should therefore solve a specific constraint. Common reasons include missing platform coverage, limited media-track control, an unsuitable deployment model, difficult cost forecasting, or the need to operate chat and video as separate services.</p><p>VideoSDK is a strong video-first replacement because its <a href="https://docs.videosdk.live/" rel="noreferrer">documentation</a> lists JavaScript, React, React Native, Android, iOS, Flutter, Unity, IoT, C++, and Python paths. It also provides a prebuilt interface and custom SDKs.</p><p>The limitation is equally important: VideoSDK does not replace every persistent messaging workflow. Teams that need chat history, moderation, reactions, presence, and non-call notifications may keep CometChat Chat or add another messaging provider.</p><h2 id="how-we-ranked-each-cometchat-alternative">How We Ranked Each CometChat Alternative</h2><p>This CometChat alternative ranking measures documented product fit for embedded video. It does not claim that one vendor delivers better call quality in every network, device, or region.</p><p>For this article, "expert-tested" means each provider was checked against the same first-party evidence: integration paths, SDK coverage, public features, production tooling, deployment options, pricing units, and migration boundaries.</p><p>The weighted editorial score uses seven criteria:</p><ul><li><strong>Video calling depth, 25 points:</strong> media controls, group calls, screen sharing, recording, transcription, network handling, and participant management.</li><li><strong>Developer experience, 20 points:</strong> quickstarts, API clarity, Prebuilt availability, examples, token flow, and custom-interface flexibility.</li><li><strong>Platform coverage, 15 points:</strong> web, native mobile, cross-platform mobile, desktop, game engines, backend, and device SDKs.</li><li><strong>Production readiness, 15 points:</strong> analytics, security controls, webhooks, recording, live streaming, and operational tooling.</li><li><strong>Pricing clarity, 10 points:</strong> public billing units, free evaluation allowance, calculators, and visibility into chargeable add-ons.</li><li><strong>Deployment control, 10 points:</strong> managed regions, data controls, self-hosting, or a clearly documented operational model.</li><li><strong>Migration fit, 5 points:</strong> the ability to preserve application identity, chat, and business workflows while replacing only calls.</li></ul><p>The scores are editorial, not laboratory measurements. Before moving production traffic, run an identical regional proof of concept for joint success, time-to-first-media, packet loss, reconnection, background behaviour, and device changes.</p><h2 id="top-10-cometchat-alternatives-at-a-glance">Top 10 CometChat Alternatives at a Glance</h2><p>The strongest video calling APIs serve different engineering priorities. VideoSDK leads this balanced model, but Daily, LiveKit, Agora, or another platform can lead when one requirement becomes non-negotiable.</p>
<!--kg-card-begin: html-->
<table><tbody><tr><th><span>Rank</span></th><th><span>Platform</span></th><th><span>Score</span></th><th><span>Best for</span></th><th><span>Main trade-off</span></th></tr><tr><td><span>1</span></td><td><span>VideoSDK</span></td><td><span>90/100</span></td><td><span>Broad SDK coverage with Prebuilt and custom RTC paths</span></td><td><span>Not a complete persistent chat replacement</span></td></tr><tr><td><span>2</span></td><td><span>Daily</span></td><td><span>87/100</span></td><td><span>Fast browser embedding and clear usage pricing</span></td><td><span>Narrower specialist-device coverage</span></td></tr><tr><td><span>3</span></td><td><span>Agora</span></td><td><span>86/100</span></td><td><span>Global RTC, gaming, and interactive media</span></td><td><span>More resolution and add-on costs to model</span></td></tr><tr><td><span>4</span></td><td><span>LiveKit</span></td><td><span>85/100</span></td><td><span>Open-source infrastructure and self-hosting</span></td><td><span>Self-hosting transfers operations to your team</span></td></tr><tr><td><span>5</span></td><td><span>100ms</span></td><td><span>83/100</span></td><td><span>Role-based rooms, Prebuilt, and live events</span></td><td><span>Templates and roles shape application architecture</span></td></tr><tr><td><span>6</span></td><td><span>Dyte</span></td><td><span>81/100</span></td><td><span>UI kits and collaborative meeting experiences</span></td><td><span>Verify feature parity across target SDKs</span></td></tr><tr><td><span>7</span></td><td><span>Vonage Video API</span></td><td><span>80/100</span></td><td><span>Enterprise video inside a wider CPaaS portfolio</span></td><td><span>Advanced controls can materially change cost</span></td></tr><tr><td><span>8</span></td><td><span>Zoom Video SDK</span></td><td><span>79/100</span></td><td><span>Custom apps using Zoom media technology</span></td><td><span>Sessions do not interoperate with Zoom Meetings</span></td></tr><tr><td><span>9</span></td><td><span>ZEGOCLOUD</span></td><td><span>78/100</span></td><td><span>Social video, effects, and broad device support</span></td><td><span>Multiple SDK families and stream-based billing</span></td></tr><tr><td><span>10</span></td><td><span>Whereby Embedded</span></td><td><span>75/100</span></td><td><span>Low-code browser video rooms</span></td><td><span>Less native media control than headless SDKs</span></td></tr></tbody></table>
<!--kg-card-end: html-->
<p>The pricing below was checked on 24 July 2026. Recalculate recording, transcription, streaming, bandwidth, support, and compliance before signing a contract.</p><h2 id="the-10-best-cometchat-alternatives-for-video">The 10 Best CometChat Alternatives for Video</h2><p>Each CometChat alternative below earned its position through the same framework. Your best option still depends on platforms, call shape, compliance, deployment, and operational ownership.</p><h3 id="1-videosdk-best-overall-video-first-alternative">1. VideoSDK: Best Overall Video-First Alternative</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.29.39-PM.png" class="kg-image" alt="VideoSDK Homepage" loading="lazy" width="2906" height="1660"/></figure><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> ranks first for teams that need one managed RTC layer across an unusually wide set of application platforms.</p><p>Its <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">React quickstart</a> exposes room and participant state through MeetingProvider, useMeeting, and useParticipant. The documentation also provides prebuilt JavaScript, React Native, Android, iOS, Flutter, Unity, IoT, C++, and Python paths.</p><p><strong>Best for:</strong> Telehealth, tutoring, recruitment, support, and social applications that need prebuilt speed today, custom media controls later, and <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">interactive live streaming</a> from the same provider.</p><p><strong>Pricing:</strong> <a href="https://www.videosdk.live/pricing"><u>VideoSDK's pay-as-you-go pricing</u></a> is <strong>$0.001</strong> per participant-minute for audio calls, <strong>$0.004</strong> per participant-minute for video calls, and <strong>$0.002</strong> per viewer-minute for live streaming and a $20 free credit for new accounts. </p><p><strong>Trade-off and migration note:</strong> VideoSDK is not a full persistent chat replacement. Preserve your own user IDs, generate meeting tokens server-side, and move the call action behind a feature flag while keeping existing messaging.</p><h3 id="2-daily-best-for-rapid-browser-embedding">2. Daily: Best for Rapid Browser Embedding</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.02-PM.png" class="kg-image" alt="Daily Homepage" loading="lazy" width="2924" height="1652"/></figure><p><a href="https://www.daily.co/" rel="noreferrer nofollow">Daily</a> is the strongest browser-first alternative when a polished embedded call must reach production quickly.</p><p>Daily Prebuilt supplies a ready-made call component, while Daily's client SDKs expose tracks and events for custom interfaces. Official examples cover browser clients, React Native, Android, iOS, audio-only calls, REST room creation, recording, streaming, and transcription.</p><p><strong>Best for:</strong> SaaS, coaching, telehealth, and customer-facing web products that want a low-friction embed without blocking a later custom UI.</p><p><strong>Pricing:</strong> Daily includes <a href="https://www.daily.co/pricing/" rel="noreferrer nofollow">10,000 free minutes each month</a>, then applies graduated usage pricing. The first paid video tier is currently $0.004 per participant minute, with separate recording and streaming charges.</p><p><strong>Trade-off and migration note:</strong> Daily's most visible path is web-first. Compare Flutter, Unity, C++, IoT, and specialist native needs before migrating. Choose VideoSDK when one broader client matrix matters more than browser integration speed.</p><h3 id="3-agora-best-for-global-rtc-and-gaming">3. Agora: Best for Global RTC and Gaming</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.26-PM.png" class="kg-image" alt="Agora Homepage" loading="lazy" width="2920" height="1662"/></figure><p><a href="https://www.agora.io/en/" rel="noreferrer nofollow">Agora</a> is a strong choice when a large global RTC ecosystem, game-engine support, and media extensions lead the decision.</p><p>The platform combines video calling, voice, interactive live streaming, signalling, recording, analytics, noise suppression, and multi-track media. Agora also supports mainstream mobile, web, desktop, and game development environments.</p><p><strong>Best for:</strong> International social, gaming, live commerce, education, and interactive media products where device diversity and operational analytics matter at scale.</p><p><strong>Pricing:</strong> Agora currently includes <a href="https://www.agora.io/en/pricing/" rel="noreferrer nofollow">10,000 monthly minutes</a>. Video HD starts at $3.99 per 1,000 participant minutes, while Full HD, recording, proxy modes, analytics, and extensions use separate rates.</p><p><strong>Trade-off and migration note:</strong> Agora's breadth creates more configuration and billing dimensions. Model resolution, recording, proxy, analytics, and add-ons. Choose VideoSDK when a more unified prebuilt-to-custom workflow has greater weight.</p><h3 id="4-livekit-best-open-source-option">4. LiveKit: Best Open-Source Option</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.30.40-PM.png" class="kg-image" alt="LiveKit Homepage" loading="lazy" width="2920" height="1670"/></figure><p><a href="https://livekit.com/" rel="noreferrer nofollow">LiveKit</a> is the clearest option when source access, self-hosting, or media-plane control is mandatory.</p><p>LiveKit provides an open-source <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> server and a managed cloud. Its SDKs cover JavaScript, Swift, Android, React Native, Flutter, and Unity, with ingress, egress, SIP, <a href="https://www.videosdk.live/blog/what-is-end-to-end-encryption-e2ee" rel="noreferrer">end-to-end encryption</a>, webhooks, and selective track subscriptions.</p><p><strong>Best for:</strong> Infrastructure-capable teams that need Kubernetes deployment, data-residency control, open APIs, or a shared real-time layer for human video and agent participants.</p><p><strong>Pricing:</strong> Self-hosting moves cost into cloud and operations. <a href="https://livekit.com/pricing" rel="noreferrer nofollow">LiveKit Cloud</a> meters connection minutes, downstream bandwidth, and transcoding. Its free build allowance currently includes 5,000 WebRTC participant minutes, 50 GB downstream transfer, and 60 transcode minutes.</p><p><strong>Trade-off and migration note:</strong> Your team owns capacity, topology, upgrades, <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a>, monitoring, and incidents when self-hosting. Choose VideoSDK when managed delivery and wider specialist SDK coverage matter more than infrastructure control.</p><h3 id="5-100ms-best-for-role-based-rooms">5. 100ms: Best for Role-Based Rooms</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.31.12-PM.png" class="kg-image" alt="100ms Homepage" loading="lazy" width="2910" height="1656"/></figure><p><a href="https://www.100ms.live/" rel="noreferrer nofollow">100ms</a> stands out when participant roles and room templates define the product experience.</p><p>Its model organises users, tracks, permissions, recording, and live streaming around rooms, peers, sessions, templates, and roles. Official quickstarts cover Web, Android, iOS, Flutter, React Native, and Prebuilt.</p><p><strong>Best for:</strong> Classrooms, fitness sessions, communities, webinars, and events that need hosts, viewers, hand-raising, role changes, recording, <a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer">HLS</a>, or RTMP output.</p><p><strong>Pricing:</strong> 100ms currently includes <a href="https://www.100ms.live/pricing" rel="noreferrer nofollow">10,000 monthly conferencing minutes</a>, then charges $0.004 per participant minute. Streaming, encoding, recording, transcription, summaries, and support use separate allowances or rates.</p><p><strong>Trade-off and migration note:</strong> Templates and roles become part of application architecture. Define permission transitions before migration. Choose VideoSDK when platform breadth and a rooms-based prebuilt-to-custom path carry more weight.</p><h3 id="6-dyte-best-for-collaborative-ui-kits">6. Dyte: Best for Collaborative UI Kits</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.31.41-PM.png" class="kg-image" alt="Dyte Homepage" loading="lazy" width="2914" height="1652"/></figure><p><a href="https://dyte.io/" rel="noreferrer nofollow">Dyte</a> is compelling when in-call collaboration and ready-made UI components reduce the frontend backlog.</p><p>Its documentation lists core SDKs and UI kits for web, React Native, Flutter, Android, and iOS. Product features include recording, HLS, <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a>, roles, host controls, <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">adaptive bitrate</a>, reconnection, analytics, and troubleshooting.</p><p><strong>Best for:</strong> Education, community, internal collaboration, and event products that need UI kits, meeting controls, and live experiences without building every component.</p><p><strong>Pricing:</strong> <a href="https://dyte.io/" rel="noreferrer nofollow">Dyte's</a> public page currently includes 10,000 free minutes monthly, then lists video at $0.004 per user minute. Recording and RTMP output have separate rates.</p><p><strong>Trade-off and migration note:</strong> Verify parity for recording, screen sharing, background behaviour, device controls, and UI components across every target SDK. Choose VideoSDK when the documented client surface is the deciding factor.</p><h3 id="7-vonage-video-api-best-enterprise-cpaas-fit">7. Vonage Video API: Best Enterprise CPaaS Fit</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.32.16-PM.png" class="kg-image" alt="Vonage Home page" loading="lazy" width="2922" height="1652"/></figure><p><a href="https://www.vonage.com/communications-apis/video/features/" rel="noreferrer nofollow">Vonage Video API</a> fits enterprises that want programmable video beside messaging, voice, SIP, and other communications APIs.</p><p>The platform provides web, mobile, desktop, and server SDKs for sessions, tokens, publishing, screen sharing, signalling, recording, broadcast, <a href="https://www.videosdk.live/developer-hub/sip/sip-protocol-architecture-guide" rel="noreferrer">SIP</a> interconnect, captions, media processing, <a href="https://www.videosdk.live/developer-hub/websocket/webhook-vs-websocket#what-are-webhooks" rel="noreferrer">webhooks</a>, and analytics.</p><p><strong>Best for:</strong> Organisations already using Vonage, or teams needing video alongside telephony, regional controls, compliance options, formal support, and a broader CPaaS relationship.</p><p><strong>Pricing:</strong> Vonage <a href="https://www.vonage.com/communications-apis/video/pricing/" rel="noreferrer nofollow">currently lists</a> $0.00410 per participant minute and a new-customer allowance of 100,000 minutes split between video and advanced features. Recording, composition, streaming, AI connectors, SIP, regional media, and security options add cost.</p><p><strong>Trade-off and migration note:</strong> The base rate does not represent the full production bill. Choose VideoSDK when the decision is embedded video developer experience rather than CPaaS consolidation.</p><h3 id="8-zoom-video-sdk-best-for-zoom-media-technology">8. Zoom Video SDK: Best for Zoom Media Technology</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.32.46-PM.png" class="kg-image" alt="Zoom Video SDK Homepage" loading="lazy" width="2920" height="1646"/></figure><p><a href="https://www.zoom.com/en/video-sdk/" rel="noreferrer nofollow">Zoom Video SDK</a> provides Zoom's media technology for fully branded sessions with custom user interfaces.</p><p>It is different from the Meeting SDK. Video SDK developers create their own sessions, authentication, controls, branding, and workflows. Zoom documents web, mobile, desktop, Linux, Flutter, React Native, and Unity paths.</p><p><strong>Best for:</strong> Teams that trust Zoom's media stack but need a custom product experience instead of embedding a Zoom meeting.</p><p><strong>Pricing:</strong> Zoom's developer material currently <a href="https://zoom.us/pricing/developer" rel="noreferrer nofollow">states 10,000 free Video SDK minutes each month</a>, followed by per-minute usage pricing, with volume discounts available.</p><p><strong>Trade-off and migration note:</strong> Zoom states that Video SDK sessions are not compatible with Zoom Meetings or webinars. Choose the Meeting SDK if interoperability is required. Choose VideoSDK for an RTC-focused prebuilt and custom development path.</p><h3 id="9-zegocloud-best-for-social-video">9. ZEGOCLOUD: Best for Social Video</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.33.21-PM.png" class="kg-image" alt="ZEGOCLOUD Homepage" loading="lazy" width="2926" height="1668"/></figure><p><a href="https://www.zegocloud.com/" rel="noreferrer nofollow">ZEGOCLOUD</a> suits social and entertainment products that need calling, effects, streaming, and a broad device matrix.</p><p>It offers low-level video SDKs plus scenario-based UI kits for Android, iOS, Web, React Native, Flutter, and additional desktop or game environments through its Express SDK family.</p><p><strong>Best for:</strong> Dating, creator, entertainment, gaming, and <a href="https://www.videosdk.live/solutions/live-shopping" rel="noreferrer">live commerce</a> applications that need call invitations, effects, live rooms, desktop clients, or game engine support.</p><p><strong>Pricing:</strong> <a href="https://www.zegocloud.com/pricing" rel="noreferrer nofollow">ZEGOCLOUD</a> advertises 10,000 free minutes and video calling from $3.99 per 1,000 minutes. Detailed documentation explains stream-playing and resolution-based billing, so model multi-stream rooms carefully.</p><p><strong>Trade-off and migration note:</strong> Several SDK and product families increase selection work. Confirm the exact UI kit, Express SDK, platform package, analytics, effects, and billing method before replacing CometChat Calls.</p><h3 id="10-whereby-embedded-best-low-code-browser-option">10. Whereby Embedded: Best Low-Code Browser Option</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-23-at-6.34.01-PM.png" class="kg-image" alt="Whereby Embedded Homepage" loading="lazy" width="2890" height="1624"/></figure><p><a href="https://whereby.com/information/embedded" rel="noreferrer nofollow">Whereby Embedded</a> provides the shortest conceptual path from a server-created room to a branded browser call.</p><p>The Embedded API creates rooms programmatically and renders calls in a web component or iframe. Current plans include screen sharing, chat, waiting rooms, breakouts, recording, transcription, streaming, and insights.</p><p><strong>Best for:</strong> Telehealth, coaching, recruitment, education, and marketplace workflows that prioritise browser access, straightforward room creation, and minimal client code.</p><p><strong>Pricing:</strong> The free <a href="https://whereby.com/information/embedded/pricing" rel="noreferrer nofollow">Explore plan</a> includes 2,000 participant minutes. Build currently costs $9.99 monthly, includes 2,000 minutes, and charges $0.004 per additional participant minute. Premium features are separate.</p><p><strong>Trade-off and migration note:</strong> Whereby lists 200 participants and 24 active videos. Choose VideoSDK when native SDKs, media-track control, specialist platforms, and custom layouts matter more than a browser embed.</p><h2 id="which-cometchat-alternative-should-you-choose">Which CometChat Alternative Should You Choose?</h2><p>The right CometChat alternative changes when one constraint becomes non-negotiable. Use these conditional verdicts before comparing every feature or negotiating an enterprise contract.</p><ul><li>Choose <strong>VideoSDK</strong> when you need Prebuilt and custom video across web, mobile, Unity, C++, Python, or IoT, with recording and interactive streaming.</li><li>Choose <strong>Daily</strong> when a polished browser embed, transparent participant-minute billing, and the quickest web proof of concept matter most.</li><li>Choose <strong>Agora</strong> when global RTC, game engines, interactive media extensions, and a large real-time product ecosystem lead the decision.</li><li>Choose <strong>LiveKit</strong> when open-source infrastructure, self-hosting, Kubernetes, or direct control over the media plane is mandatory.</li><li>Choose <strong>100ms</strong> when roles, room templates, classrooms, webinars, or viewer-to-speaker workflows define the product.</li><li>Choose <strong>Dyte</strong> when collaborative UI components and meeting controls can reduce your frontend workload.</li><li>Choose <strong>Vonage</strong> when video must sit inside a broader enterprise communications and telephony portfolio.</li><li>Choose <strong>Zoom Video SDK</strong> when Zoom media technology and desktop support matter, but Zoom Meeting interoperability does not.</li><li>Choose <strong>ZEGOCLOUD</strong> when social-video effects, games, and a wide device matrix are central.</li><li>Choose <strong>Whereby Embedded</strong> when an iframe or web component is sufficient and low-code delivery outranks native media control.</li></ul><p>The common mistake is selecting a chat-first platform and assuming its video layer has the same flexibility as a dedicated RTC product. Start from your hardest media requirement, not the longest feature list.</p><h2 id="cometchat-vs-videosdk-for-video-calling">CometChat vs VideoSDK for Video Calling</h2><p>CometChat and VideoSDK overlap in voice and video, but they start from different product scopes. CometChat packages persistent messaging, moderation, notifications, UI kits, and calling. VideoSDK starts with real-time media and provides Prebuilt and custom SDK paths for embedded video experiences.</p>
<!--kg-card-begin: html-->
<table><tbody><tr><th><span>Decision area</span></th><th><span>CometChat</span></th><th><span>VideoSDK</span></th></tr><tr><td><span>Primary fit</span></td><td><span>A wider chat, voice, and video communications layer</span></td><td><span>A video-first RTC layer with Prebuilt and custom integration</span></td></tr><tr><td><span>Video implementation</span></td><td><span>Calling inside the CometChat product model</span></td><td><span>Dedicated rooms, participants, tracks, tokens, recording, and streaming</span></td></tr><tr><td><span>Messaging boundary</span></td><td><span>Persistent messaging is part of the platform</span></td><td><span>In-meeting chat does not replace a full messaging product</span></td></tr><tr><td><span>Migration approach</span></td><td><span>Keep the existing communications suite</span></td><td><span>Replace only calls, or pair with CometChat Chat</span></td></tr></tbody></table>
<!--kg-card-end: html-->
<p><strong>Choose CometChat when:</strong> The product needs one vendor for persistent chat, message history, moderation, push notifications, presence, UI kits, and calling, and its current Calls capabilities meet the media requirements.</p><p><strong>Choose VideoSDK when:</strong> Video is a primary product surface and the team needs broader documented SDK coverage, a Prebuilt-to-custom path, server-controlled meeting tokens, interactive streaming, or a separate media roadmap.</p><p><strong>Use both when:</strong> Existing CometChat messaging works well but the video layer needs a different platform, interface, device target, or billing model. Keep application identity in your backend and map a CometChat conversation or business object to a VideoSDK room.</p><p>The decision should not rest on a universal quality claim. Run the same call script on target browsers, native applications, regions, networks, participant counts, and devices. Compare join success, time-to-first-media, reconnection, device switching, background behaviour, recording delivery, moderation flows, and the complete usage bill.</p><p>For most migrations, the lowest-risk boundary is the call button. Leave conversations and notifications unchanged, route a controlled cohort to VideoSDK, and keep a rollback flag until operational metrics and support workflows are stable.</p><h2 id="can-cometchat-and-videosdk-work-together">Can CometChat and VideoSDK Work Together?</h2><p>Yes. CometChat and VideoSDK can coexist at the application layer without a dedicated connector. Keep CometChat for persistent messaging while routing video rooms through VideoSDK.</p><p>This phased architecture reduces risk because chat history, moderation, notifications, and non-call workflows remain unchanged during the first video rollout.</p><ol><li><strong>Own identity in your backend.</strong> Use one internal user ID across CometChat users and VideoSDK participant metadata. Do not make either vendor's identifier your permanent business identity.</li><li><strong>Generate video tokens server-side.</strong> Create <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token" rel="noreferrer">VideoSDK JWTs</a> and room IDs on trusted infrastructure. Never place the VideoSDK secret key in browser or mobile application code.</li><li><strong>Replace the call action.</strong> Route a CometChat call button, or your own application action, to a VideoSDK room behind a feature flag.</li><li><strong>Preserve business context.</strong> Store the conversation ID, appointment ID, support case, or order ID beside the VideoSDK room ID.</li><li><strong>Migrate by cohort.</strong> Test internal users, one region, and one call type before moving recordings, native applications, or compliance-sensitive traffic.</li></ol><p>There is no technical requirement to replace chat and calls simultaneously. Treat the change as an application integration and validate the operational boundary with both vendors.<br>Try this <a href="https://www.videosdk.live/blog/1-to-1-video-chat-app-on-android-using-videosdk" rel="noreferrer">video chat app tutorial</a> yourself!</br></p><h2 id="how-to-compare-video-calling-api-pricing">How to Compare Video Calling API Pricing</h2><p>Video API prices become comparable only after each provider's billing unit is converted into the same monthly scenario.</p><p>Use participant minutes as the base where possible. A 30-minute call with four connected people usually consumes 120 participant minutes, even if only two people publish video.</p><p>LiveKit adds downstream bandwidth and transcoding. ZEGOCLOUD documents stream-playing units. Zoom uses Video SDK session minutes. Recording, transcription, streaming, storage, support, and compliance may use different units again.</p><p>Use this normalised estimate:</p><pre><code class="language-text">Monthly video cost =
  participant-minutes
  + recording and composition
  + storage and delivery
  + transcription or translation
  + telephony or streaming
  + support and compliance
  + infrastructure engineering
</code></pre><p>Run expected usage, twice expected usage, and a launch spike. The cheapest headline rate can become expensive after required add-ons, while a higher base rate can remain easier to forecast.</p><h2 id="migration-risks-most-comparisons-miss">Migration Risks Most Comparisons Miss</h2><p>A successful CometChat alternative migration depends more on application boundaries than SDK installation. Document behavioural parity before routing real users to a new media provider.</p><ul><li><strong>Incoming-call behaviour:</strong> Compare push notifications, CallKit, Android foreground services, ringtone states, rejection, timeout, missed calls, and multi-device handling.</li><li><strong>Token and room lifetime:</strong> Define expiry, refresh, replay protection, roles, waiting-room rules, and reconnect behaviour.</li><li><strong>Recording ownership:</strong> Map consent, start permissions, layouts, individual tracks, encryption, storage region, webhooks, retention, and deletion.</li><li><strong>Network fallback:</strong> Test UDP, TCP, TURN, corporate firewalls, VPNs, low bandwidth, background transitions, device switching, and reconnection.</li><li><strong>SDK feature parity:</strong> Confirm that JavaScript, Flutter, React Native, iOS, and Android implement required features consistently.</li><li><strong>Observability:</strong> Capture join failures, time-to-first-media, reconnections, packet loss, device errors, and a support-friendly session ID.</li></ul><p>A sensible production pattern is a shadow pilot. Send internal calls through the new provider, compare operational metrics, then expand by region and application version.</p><h2 id="definitions-for-video-calling-api-buyers">Definitions for Video Calling API Buyers</h2><blockquote><strong>Participant minute:</strong> One participant connected to a call for one minute. Four people connected for 30 minutes usually consume 120 participant minutes.</blockquote><blockquote><strong>Room:</strong> A logical real-time session where participants publish and subscribe to audio, video, screen-share, or data tracks. VideoSDK uses room IDs to identify sessions.</blockquote><blockquote><strong>Prebuilt UI:</strong> A ready-made calling interface that reduces launch time. VideoSDK, Daily, 100ms, and Whereby provide different forms of Prebuilt experience.</blockquote><blockquote><strong>SFU:</strong> A selective forwarding unit receives participant media and forwards selected tracks without composing every stream, supporting efficient multiparty WebRTC rooms.</blockquote><blockquote><strong>Meeting token:</strong> A short-lived credential authorising a participant to join a room with specific permissions. Generate production tokens on a trusted server.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>VideoSDK leads this video-first CometChat alternative ranking because it balances platform breadth, Prebuilt delivery, custom media control, recording, and interactive streaming.</li><li>Daily is stronger for rapid browser embedding, while LiveKit is stronger when open-source infrastructure or self-hosting is mandatory.</li><li>Every other ranked provider leads under a specific scale, event, collaboration, CPaaS, device, or low-code requirement.</li><li>Documentation can verify capabilities and integration surfaces, but only a regional proof of concept can test your actual call quality.</li><li>You can keep CometChat Chat while replacing only video, provided your backend owns identity, tokens, room mapping, and rollout controls.</li></ul><h2 id="conclusion">Conclusion</h2><p>The right CometChat alternative depends on what your video product must do better. VideoSDK offers the strongest overall balance in this documentation-backed ranking, while Daily, LiveKit, Agora, and others lead under narrower conditions.</p><p>Start with the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start"><u>VideoSDK React quickstart</u></a> or <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start"><u>Prebuilt quickstart</u></a>, then test real regions, devices, and call patterns. What kind of video experience are you building?</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="which-cometchat-alternative-is-best-for-video-calling">Which CometChat alternative is best for video calling?</h3><p>The best CometChat alternative for broad, video-first development is VideoSDK under this weighted editorial model. It combines Prebuilt and custom SDK paths across web, mobile, Unity, C++, Python, and IoT.</p><p>Daily can be better for a browser-first embed, while LiveKit can be better for self-hosting. Confirm the final choice with a regional proof of concept.</p><h3 id="is-videosdk-a-complete-replacement-for-cometchat">Is VideoSDK a complete replacement for CometChat?</h3><p>No. VideoSDK is not a complete replacement for every CometChat product. It focuses on real-time video, audio, interactive streaming, recording, transcription, and related RTC workflows.</p><p>Keep CometChat or another provider when the product needs persistent messaging history, moderation, reactions, presence, and non-call notifications beyond in-meeting chat.</p><h3 id="can-i-replace-cometchat-calls-without-replacing-chat">Can I replace CometChat Calls without replacing chat?</h3><p>Yes. You can replace CometChat Calls while retaining CometChat Chat by integrating a specialist video SDK at the application layer.</p><p>Use internal user IDs, server-generated video tokens, conversation-to-room mappings, feature flags, and a staged rollout so the two infrastructure changes remain independent.</p><h3 id="which-cometchat-alternative-supports-self-hosting">Which CometChat alternative supports self-hosting?</h3><p>LiveKit provides the clearest self-hosting option in this ranking through its open-source WebRTC server, deployment guidance, client SDKs, TURN configuration, ingress, egress, and Kubernetes-compatible architecture.</p><p>Self-hosting increases control but transfers capacity, upgrades, routing, monitoring, security, and incident response to your own engineering and operations teams.</p><h3 id="which-alternative-has-the-fastest-browser-integration">Which alternative has the fastest browser integration?</h3><p>Daily and Whereby Embedded provide the most direct browser-first integration paths in this shortlist. Both offer ready-made video experiences without requiring every participant control to be built first.</p><p>VideoSDK Prebuilt becomes more attractive when the same roadmap later needs custom React controls, native SDKs, Unity, C++, Python, or IoT clients.</p><h3 id="how-should-i-test-a-video-calling-api">How should I test a video calling API?</h3><p>Test each video calling API with identical devices, regions, networks, participant counts, and call scripts. Record join success, time-to-first-media, reconnections, packet loss, and device failures.</p><p>Also test mobile interruptions, browser backgrounding, Bluetooth changes, corporate firewalls, expired tokens, participant removal, recording webhooks, and regional data requirements.</p><h3 id="is-cometchat-still-a-good-option-in-2026">Is CometChat still a good option in 2026?</h3><p>Yes. CometChat remains reasonable when one platform must provide persistent chat, voice, video, UI kits, moderation, notifications, and wider messaging workflows.</p><p>A specialist CometChat alternative becomes more compelling when video is the primary product, self-hosting matters, a platform gap exists, or the billing and media-control model no longer fits.</p><h1 id=""/><h2 id="-1"/>]]></content:encoded></item><item><title><![CDATA[How to Build an Open-Source Zoom Clone with Claude Code + VideoSDK]]></title><description><![CDATA[Build an open-source Zoom clone in about 10 minutes. Clone an MIT repo, add free VideoSDK keys, customize it with Claude Code, and deploy. ]]></description><link>https://www.videosdk.live/blog/zoom-clone</link><guid isPermaLink="false">6a5dc46eb3240feb748c5758</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 23 Jul 2026 10:04:11 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/07/Clone-of-Zoom.png" medium="image"/><content:encoded><![CDATA[<blockquote>An open-source Zoom clone is a self-hosted video conferencing app you fully control, built from a public repository instead of a paid product. The MIT-licensed&nbsp;<a href="https://github.com/videosdk-community/zoom-clone"><code>videosdk-community/zoom-clone</code></a>&nbsp;repo ships a React 18 client on VideoSDK's React SDK, and two environment variables turn it into live multi-participant video in about ten minutes.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Clone-of-Zoom.png" alt="How to Build an Open-Source Zoom Clone with Claude Code + VideoSDK"/><p>You can have a working Zoom clone running on your machine in about ten minutes, and you don't have to write the hard parts yourself. You start from a free, MIT-licensed repository, add two VideoSDK keys, and use Claude Code to run and customize it. This guide walks through every step, from an empty terminal to a live meeting you can share with a friend and deploy to the internet.</p><p>No WebRTC knowledge is required. If you can run a command and copy a key, you can finish this.</p>
<!--kg-card-begin: html-->
<iframe width="560" height="315" src="https://www.youtube.com/embed/j_biymyP5iw?si=wkE3_8AsOuVhkxP0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<h2 id="what-is-an-open-source-zoom-clone">What Is an Open-Source Zoom Clone?</h2><p>An open-source Zoom clone is defined as a video conferencing application whose full source code is public and modifiable, replicating Zoom's meeting experience without Zoom's hosted product or per-seat licensing.</p><p>It works by pairing a client application you own with a real-time media backend you rent. The client renders the join screen, the participant grid, chat, and host controls. The media backend captures, encodes, routes, and fans out live audio and video to every participant.</p><p>VideoSDK provides that backend through its&nbsp;<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React video calling SDK</a>, which handles&nbsp;<a href="https://www.w3.org/TR/webrtc/">WebRTC</a>&nbsp;transport, an SFU media server, and server-side enforcement of host decisions. The&nbsp;<code>videosdk-community/zoom-clone</code>&nbsp;repository is the client: React 18, TypeScript 5, Vite 6, Tailwind CSS v4, Zustand 5, and VideoSDK's React SDK v0.13.</p><p>That split is the reason a beginner can finish this in one sitting. Nobody in this tutorial writes signaling code, negotiates ICE candidates, or stands up a TURN server. You clone a working app, hand it credentials, and start changing the parts you actually care about. If you would rather wire VideoSDK into an app you already have, the&nbsp;<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React quick start</a>&nbsp;covers the same SDK from an empty project.</p><h2 id="what-you-will-build-with-videosdk">What You Will Build with VideoSDK</h2><p>You will end up with a real video meeting app that looks and feels like Zoom, complete with a join screen, a video grid, screen sharing, chat, reactions, raise-hand, polls, a whiteboard, and host controls like mute-all and a waiting room.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/demo-meeting.png" class="kg-image" alt="How to Build an Open-Source Zoom Clone with Claude Code + VideoSDK" loading="lazy" width="1440" height="810"><figcaption><i><em class="italic" style="white-space: pre-wrap;">The finished open-source Zoom clone: gallery view, active-speaker ring, reactions, raise-hand, and the full control bar, all built with VideoSDK.</em></i></figcaption></img></figure><p>The first time you run it, everything works with no setup at all. That keyless run is&nbsp;<em>demo mode</em>: a local, single-browser mock meeting that lets you click through the real interface without a media server behind it. To have two people actually see and hear each other, you add free VideoSDK keys in Step 3.</p><h2 id="prerequisites-for-this-zoom-clone-tutorial">Prerequisites for This Zoom Clone Tutorial</h2><p>You need four things to build it, and all of them are free:</p><ul><li><strong>Node.js 18 or newer</strong>&nbsp;(20+ recommended), which you can confirm by running&nbsp;<code>node -v</code>.</li><li><strong>pnpm</strong>, the package manager this repo uses, installed with&nbsp;<code>npm install -g pnpm</code>.</li><li><strong>A free VideoSDK account</strong>&nbsp;for real meetings, available from the&nbsp;<a href="https://dub.sh/X5Fn46e">VideoSDK dashboard</a>. You can skip this until Step 3.</li><li><a href="https://docs.claude.com/en/docs/claude-code/overview"><strong>Claude Code</strong></a>, Anthropic's terminal coding agent, so you can customize the app by describing what you want.</li></ul><p>That is the entire list. No database to configure, no backend to stand up, and no video infrastructure to wire together. VideoSDK's&nbsp;<a href="https://videosdk.live/pricing">free tier</a>&nbsp;covers the video minutes you will burn while building and testing.</p><h2 id="step-1-clone-the-zoom-clone-repository">Step 1: Clone the Zoom Clone Repository</h2><p>Getting the code is one command, and the repository is MIT licensed, so anything you build on top of it is yours.</p><pre><code class="language-bash">git clone https://github.com/videosdk-community/zoom-clone.git
cd zoom-clone
</code></pre><p>If you would rather deploy first and read the code later, the repo's README has a&nbsp;<strong>Deploy with Vercel</strong>&nbsp;button that forks the project and wires up hosting in a single click, asking only for the two keys you'll get in Step 3.</p><p>Either path works. For this guide we'll run it locally first so you can watch it come to life, then deploy at the end.</p><h2 id="step-2-run-it-instantly-in-demo-mode">Step 2: Run It Instantly in Demo Mode</h2><p>Demo mode lets you explore the entire meeting interface with zero credentials and zero signup.</p><p>Install the dependencies and start the dev server:</p><pre><code class="language-bash">pnpm install
pnpm dev
</code></pre><p>Open&nbsp;<a href="http://localhost:5173">http://localhost:5173</a>&nbsp;and you'll land on the home screen. Starting a meeting drops you straight into a working Zoom-style room, control bar and all.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/home-screen.png" class="kg-image" alt="How to Build an Open-Source Zoom Clone with Claude Code + VideoSDK" loading="lazy" width="1440" height="600"><figcaption><i><em class="italic" style="white-space: pre-wrap;">the home screen at localhost:5173, running in demo mode with zero configuration.</em></i></figcaption></img></figure><p>The reason it runs with nothing configured is that the app checks whether real VideoSDK credentials exist and, if they don't, falls back to demo mode:</p><pre><code class="language-ts">// src/routes/MeetingRoom.tsx
const isLive = hasToken() &amp;&amp; !roomId.startsWith("demo-");
</code></pre><p>When there's no token,&nbsp;<code>isLive</code>&nbsp;is&nbsp;<code>false</code>, so the app renders a fully interactive mock meeting instead of a live one. This is perfect for a first look, letting you click every button, open the chat, and try the reactions before you commit to anything.</p><p>Just keep in mind what demo mode is not: it's a single-browser mock, so you can't call a friend yet. That is exactly what the next step unlocks.</p><h2 id="step-3-add-real-video-with-videosdk-keys">Step 3: Add Real Video with VideoSDK Keys</h2><p>Real meetings need real credentials, and getting them takes about two minutes.</p><ol><li>Open the&nbsp;<a href="https://dub.sh/X5Fn46e">VideoSDK dashboard</a>&nbsp;and sign up.</li><li>Copy your&nbsp;<strong>API key</strong>&nbsp;and&nbsp;<strong>secret</strong>.</li><li>Create your env file so you can paste them in:</li></ol><pre><code class="language-bash">cp .env.example .env
</code></pre><p>Open the new&nbsp;<code>.env</code>&nbsp;file and fill in exactly two values:</p><pre><code class="language-bash">VIDEOSDK_API_KEY=your_api_key_here
VIDEOSDK_SECRET=your_secret_here
</code></pre><p>Restart the dev server with&nbsp;<code>pnpm dev</code>&nbsp;and you are now running in live mode. Open the meeting link on a second device or send it to a friend, and you'll see and hear each other for real.</p><p>What matters most here is what you did&nbsp;<em>not</em>&nbsp;have to do. There is no manual token step, no JWT signing by hand, and no auth server to run. The next section explains how that works, because it is the step most video calling tutorials skip.</p><h2 id="how-do-i-generate-a-videosdk-token">How Do I Generate a VideoSDK Token?</h2><p>VideoSDK authenticates every participant with a short-lived JWT called a meeting token, signed server-side with your API key and secret. In this repo, the Vite build does that signing for you at build time, so you never write the code yourself.</p><p>Two tokens are minted from your key pair:</p><table>
<thead>
<tr>
<th>Token</th>
<th>Role</th>
<th>What it authorizes</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>VITE_VIDEOSDK_TOKEN</code></td>
<td><code>rtc</code></td>
<td>Joining rooms, publishing and subscribing to audio and video</td>
</tr>
<tr>
<td><code>VITE_VIDEOSDK_API_TOKEN</code></td>
<td><code>crawler</code></td>
<td>Room management calls against the VideoSDK REST API</td>
</tr>
</tbody>
</table>
<p>The secret is read only inside the Node build process and is never shipped to the client, which is the property that makes this safe to deploy publicly. Token expiry defaults to 365 days and is configurable with&nbsp;<code>VIDEOSDK_TOKEN_EXPIRY</code>. You can also mint one by hand with&nbsp;<code>pnpm mint-token</code>.</p><p>If you are wiring VideoSDK into your own app rather than this repo, the equivalent server-side signing looks like this:</p><pre><code class="language-javascript">const jwt = require("jsonwebtoken");

const API_KEY = process.env.VIDEOSDK_API_KEY;
const SECRET_KEY = process.env.VIDEOSDK_SECRET;

const options = {
  expiresIn: "120m",
  algorithm: "HS256",
};

const payload = {
  apikey: API_KEY,
  permissions: ["allow_join"],
};

const token = jwt.sign(payload, SECRET_KEY, options);
</code></pre><p>Never expose your VideoSDK secret in frontend code or commit it to git. Always sign tokens in a build step or on a server you control. The&nbsp;<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token">VideoSDK authentication and token guide</a>&nbsp;documents every available permission scope and how to shorten token lifetime per participant.</p><h2 id="step-4-customize-the-app-with-claude-code">Step 4: Customize the App with Claude Code</h2><p>Instead of hunting through files to change things by hand, you describe what you want and let Claude Code make the edit.</p><p>Start Claude Code in the project folder:</p><pre><code class="language-bash">claude
</code></pre><p>From there you talk to it in plain English. The prompts below are examples of the kind of request you'd make, so adapt them to whatever you actually want to build.</p><p><strong>Rebrand it:</strong></p><blockquote>"Change the app name and logo from Zoom to MyMeet, and swap the accent color from blue to purple across the UI."</blockquote><p><strong>Tweak the meeting UI:</strong></p><blockquote>"In the control bar, move the Reactions button next to the Chat button, and add a tooltip to each control."</blockquote><p><strong>Add a small feature:</strong></p><blockquote>"Add a 'copy meeting link' button to the top bar that copies the current room URL and shows a 'Copied!' toast."</blockquote><p>The loop is always the same and it's easy to trust: you describe the change, Claude Code finds the right files and edits them, you review the diff it shows you, and the dev server hot-reloads so you see the result immediately.</p><p>Because the project already runs, you're never starting from a blank page, and steering a working app is exactly the situation where a coding agent shines. Start small with a color or a label, watch it work, and grow from there.</p><p>One practical tip: the repo ships Playwright end-to-end specs and a typecheck script, so ask Claude Code to run&nbsp;<code>pnpm typecheck</code>&nbsp;and&nbsp;<code>pnpm test:e2e</code>&nbsp;after a non-trivial edit. Those tests need valid VideoSDK credentials in&nbsp;<code>.env</code>.</p><h2 id="step-5-deploy-your-zoom-clone-to-vercel">Step 5: Deploy Your Zoom Clone to Vercel</h2><p>Putting the app online takes a few minutes and the same two environment variables you already have.</p><p>The fastest path is the&nbsp;<strong>Deploy with Vercel</strong>&nbsp;button in the README, which imports the repo, prompts you for&nbsp;<code>VIDEOSDK_API_KEY</code>&nbsp;and&nbsp;<code>VIDEOSDK_SECRET</code>, and then builds and hosts it for you.</p><p>Deep links like&nbsp;<code>/meeting/abc-123</code>&nbsp;already work in production because the repo ships a&nbsp;<code>vercel.json</code>&nbsp;that routes every path back to the app. If you deploy somewhere else, the build command is&nbsp;<code>pnpm build</code>&nbsp;and you serve the generated&nbsp;<code>dist/</code>&nbsp;folder, with an equivalent catch-all rewrite (a&nbsp;<a href="https://docs.netlify.com/routing/redirects/"><code>_redirects</code>&nbsp;rule on Netlify</a>, for example) so shared meeting links don't 404.</p><p>Either way, you end up with a real, shareable Zoom clone on the internet, built from an empty terminal in a single sitting.</p><h2 id="inside-the-app-architecture-in-five-parts">Inside the App: Architecture in Five Parts</h2><p>You don't need to understand the internals to use the app, but knowing the five moving parts makes every customization faster.</p><ul><li><strong>Rooms and joining</strong>&nbsp;handle every meeting as a room with a shareable link, created and validated for you through VideoSDK's REST API.</li><li><strong>The participant grid</strong>&nbsp;shows who's in the call, in speaker or gallery view, updating as people come and go via the SDK's participant events.</li><li><strong>The video stage</strong>&nbsp;carries the actual camera and screen-share streams, delivered by VideoSDK's SFU media server.</li><li><strong>Chat, reactions, polls, and raise-hand</strong>&nbsp;ride on VideoSDK's PubSub layer rather than the media path, with persistent history so late joiners see what they missed.</li><li><strong>Host controls</strong>&nbsp;cover mute-all, remove, lock, and the waiting room, and they're enforced server-side through SDK commands rather than by hiding buttons in the UI.</li></ul><p>Application state lives in four Zustand stores covering session role, display names, scheduled meetings, and device preferences. Only meeting controls reset between sessions, which is what prevents one meeting's host state from leaking into the next.</p><p>The complete working code for everything above lives in the&nbsp;<a href="https://github.com/videosdk-community/zoom-clone"><code>videosdk-community/zoom-clone</code>&nbsp;repository</a>, and more integration starters are in the&nbsp;<a href="https://docs.videosdk.live/code-sample">VideoSDK code samples</a>.</p><h2 id="common-errors-and-how-to-fix-them">Common Errors and How to Fix Them</h2><p>Most failures in a first VideoSDK integration come from three places, and all three have quick fixes.</p><p><strong>"Invalid token" or an immediate disconnect on join.</strong>&nbsp;Your token expired or was signed with a mismatched key pair. Token expiry defaults to 365 days here, so this usually means a mismatched key pair rather than an expired token, but a year-old deployment needs a fresh mint via&nbsp;<code>pnpm mint-token</code>. Confirm&nbsp;<code>VIDEOSDK_API_KEY</code>&nbsp;and&nbsp;<code>VIDEOSDK_SECRET</code>&nbsp;come from the same project in the dashboard.</p><p><strong>Camera or microphone permission denied.</strong>&nbsp;Browsers only grant&nbsp;<a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia"><code>getUserMedia</code></a>&nbsp;on secure origins.&nbsp;<code>localhost</code>&nbsp;counts as secure, but a LAN IP like&nbsp;<code>192.168.1.20:5173</code>&nbsp;does not, so test on&nbsp;<code>localhost</code>&nbsp;or put HTTPS in front of it.</p><p><strong>The meeting works locally but a shared link 404s in production.</strong>&nbsp;Your host is serving the path instead of the SPA. Add the catch-all rewrite described in Step 5.</p><p><strong>You joined but nobody can hear anyone.</strong>&nbsp;Check that you are in live mode rather than demo mode. A room ID starting with&nbsp;<code>demo-</code>&nbsp;never touches the media server, no matter how valid your keys are.</p><h2 id="production-considerations-most-tutorials-skip">Production Considerations Most Tutorials Skip</h2><p>Shipping this app to real users involves four things localhost never forces you to think about.</p><p><strong>There is no backend.</strong>&nbsp;Roles in this repo are application-local, meaning a determined user can claim host in their own client. Host actions are still enforced by VideoSDK's media server, so a fake host cannot mute someone else, but if you need cryptographically trustworthy roles, issue per-participant tokens with scoped permissions from a server you control.</p><p><strong>Token lifetime is a deployment decision.</strong>&nbsp;The 365-day default is convenient for a demo and generous for production: anyone who pulls that token out of your JavaScript bundle can join rooms on your account for a year. Shorten&nbsp;<code>VIDEOSDK_TOKEN_EXPIRY</code>, or move token minting to a small server endpoint that issues short-lived, per-participant tokens on join.</p><p><strong>HTTPS is mandatory.</strong>&nbsp;Media capture, screen share, and clipboard access all require a secure context in production browsers.</p><p><strong>Cost scales with participant minutes, not with users.</strong>&nbsp;A 4-person 30-minute meeting bills roughly 120 participant minutes, not 30. Model your usage that way before launch against&nbsp;<a href="https://videosdk.live/pricing">VideoSDK's pricing tiers</a>.</p><p>For server-issued tokens and programmatic room control, work from the&nbsp;<a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">VideoSDK REST API reference</a>, which covers room creation, participant listing, and recording endpoints.</p><h2 id="definitions-glossary">Definitions Glossary</h2><blockquote><strong>Room:</strong>&nbsp;A VideoSDK meeting space that participants join and share media streams within, identified by a unique room ID. In this repo, every meeting link maps to one room.</blockquote><blockquote><strong>Meeting Token:</strong>&nbsp;A JWT authenticating a participant's access to a room, signed server-side with your API key and secret. This repo signs it during the Vite build so the secret never reaches the browser.</blockquote><blockquote><strong>SFU (Selective Forwarding Unit):</strong>&nbsp;The media server that receives each participant's stream once and forwards it to everyone else, which is what keeps a six-person gallery view from melting a laptop.</blockquote><blockquote><strong>PubSub:</strong>&nbsp;VideoSDK's real-time messaging layer for non-media state. Chat, reactions, polls, and host commands travel here, with persistent history for late joiners.</blockquote><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="is-this-repo-free-to-use">Is this repo free to use?</h3><p>Yes, this open-source Zoom clone is free to use commercially. The&nbsp;<a href="https://github.com/videosdk-community/zoom-clone"><code>videosdk-community/zoom-clone</code></a>&nbsp;repository is MIT licensed, so you can use, modify, and ship it freely, including in commercial projects. VideoSDK's&nbsp;<a href="https://videosdk.live/pricing">free tier</a>&nbsp;covers the video minutes you will use while building and testing.</p><h3 id="do-i-need-to-know-webrtc">Do I need to know WebRTC?</h3><p>No, you do not need to know WebRTC for this build. The real-time engineering, meaning media capture, encoding, transport, and server-side fan-out, is handled by VideoSDK's React SDK. You work in ordinary React and TypeScript, and Claude Code can make most edits for you when you describe them in plain English.</p><h3 id="can-i-run-it-without-signup">Can I run it without signup?</h3><p>Yes, in demo mode. With no keys configured, the app runs a local mock meeting so you can explore the full UI, including the control bar, chat, and reactions. For real meetings between two or more people, you add a free VideoSDK API key and secret in Step 3.</p><h3 id="where-do-the-tokens-come-from">Where do the tokens come from?</h3><p>VideoSDK tokens are JWTs signed with your API key and secret. This repository signs two of them automatically during the Vite build, an&nbsp;<code>rtc</code>&nbsp;token for joining meetings and a&nbsp;<code>crawler</code>&nbsp;token for room management, using only&nbsp;<code>VIDEOSDK_API_KEY</code>&nbsp;and&nbsp;<code>VIDEOSDK_SECRET</code>&nbsp;from your&nbsp;<code>.env</code>&nbsp;file. Expiry defaults to 365 days and is configurable with&nbsp;<code>VIDEOSDK_TOKEN_EXPIRY</code>.</p><h3 id="can-claude-code-build-it-from-scratch">Can Claude Code build it from scratch?</h3><p>You don't need it to. Start from this runnable repo, which already contains a complete Zoom-style app, and use Claude Code to understand, customize, and extend it. Steering a working codebase gets you a usable result far quicker than prompting one into existence from nothing.</p><h3 id="how-is-this-different-from-real-zoom">How is this different from real Zoom?</h3><p>The main difference is ownership. This is an open-source app you fully control rather than a hosted product, covering video, screen share, chat, reactions, polls, and host controls. Enterprise extras like large webinars, admin consoles, and billing aren't part of the starter, though VideoSDK offers building blocks for several of them.</p><h3 id="how-long-does-this-take">How long does this take?</h3><p>About ten minutes to a running app in demo mode, plus a few more to add VideoSDK keys and go live. Deployment to Vercel adds roughly five minutes. Customizing is open-ended, but with Claude Code doing the edits, common changes like rebranding or moving a control take minutes rather than hours.</p><h2 id="key-takeaways">Key Takeaways</h2><ul><li>The MIT-licensed&nbsp;<a href="https://github.com/videosdk-community/zoom-clone"><code>videosdk-community/zoom-clone</code></a>&nbsp;repository is a complete React 18 meeting app you can fork and ship commercially today.</li><li>Demo mode runs the full interface with zero keys, so you can evaluate the UI before creating any account.</li><li>Real multi-person video needs exactly two environment variables,&nbsp;<code>VIDEOSDK_API_KEY</code>&nbsp;and&nbsp;<code>VIDEOSDK_SECRET</code>.</li><li>The Vite build signs both meeting tokens for you, an&nbsp;<code>rtc</code>&nbsp;token for joining and a&nbsp;<code>crawler</code>&nbsp;token for room management, so your secret never reaches the browser.</li><li>VideoSDK's SFU media server enforces host controls like mute-all, lock, and the waiting room server-side, which is why hiding a button in the UI is not the security boundary.</li><li>Claude Code handles the edits: describe the change in plain English, review the diff, and watch the dev server hot-reload.</li></ul><h2 id="conclusion-ship-your-own-meeting-app">Conclusion: Ship Your Own Meeting App</h2><p>You now have everything needed to run, customize, and ship an open-source Zoom clone: an MIT-licensed React codebase, two VideoSDK environment variables that unlock real multi-participant video, and a coding agent that edits the app while you describe what you want.</p><ul><li><strong>Try it live:</strong>&nbsp;<a href="https://zoom-clone-by-videosdk.vercel.app/">zoom-clone-by-videosdk.vercel.app</a></li><li><strong>The repo:</strong>&nbsp;<a href="https://github.com/videosdk-community/zoom-clone"><code>videosdk-community/zoom-clone</code></a>, MIT licensed and one-click deployable</li><li><strong>Free API keys:</strong>&nbsp;<a href="https://dub.sh/X5Fn46e">VideoSDK dashboard</a></li><li><strong>React SDK docs:</strong>&nbsp;<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start</a></li><li><strong>Community:</strong>&nbsp;the VideoSDK&nbsp;<a href="https://discord.gg/Gpmj6eCq5u">Discord</a>, where 3,000+ developers are building on the same SDK</li></ul><p>Fork the repo, run&nbsp;<code>pnpm dev</code>, and you'll be looking at your own Zoom clone before your coffee's cold.</p><p>What are you building with VideoSDK? Drop a comment with the meeting feature you would add first, since that is usually where the interesting product decisions start.</p>]]></content:encoded></item><item><title><![CDATA[How to Build an Open-Source Google Meet Clone with Claude Code + VideoSDK]]></title><description><![CDATA[Build an open-source Google Meet clone in about 10 minutes. Clone an MIT repo, add free VideoSDK keys, customize it with Claude Code, and deploy. Beginner friendly.]]></description><link>https://www.videosdk.live/blog/google-meet-clone</link><guid isPermaLink="false">6a5dd028b3240feb748c57bb</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 22 Jul 2026 13:35:18 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/07/Clone-of-Google-Meet-1.png" medium="image"/><content:encoded><![CDATA[<blockquote>To build a Google Meet clone, clone the MIT-licensed&nbsp;<code>videosdk-community/google-meet-clone</code>&nbsp;repo, run&nbsp;<code>npm install</code>&nbsp;and&nbsp;<code>npm run dev</code>, then add a free&nbsp;<code>VIDEOSDK_API_KEY</code>&nbsp;and&nbsp;<code>VIDEOSDK_SECRET</code>&nbsp;to&nbsp;<code>.env</code>&nbsp;for real WebRTC video over VideoSDK's SFU. Claude Code handles the customizing.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Clone-of-Google-Meet-1.png" alt="How to Build an Open-Source Google Meet Clone with Claude Code + VideoSDK"/><p>That is the whole path, and it takes about ten minutes. You start from a complete React video call app: a pixel-accurate Google Meet UI sitting on top of VideoSDK's real WebRTC infrastructure. You clone it, you run it, you make it yours. No real-time video experience needed, no signaling server to write, no TURN infrastructure to rent</p><h3 id="key-takeaways">Key Takeaways</h3><ul><li><strong>The repo is free and MIT-licensed.</strong>&nbsp;Clone&nbsp;<code>videosdk-community/google-meet-clone</code>, run&nbsp;<code>npm install</code>, and you have the full codebase.</li><li><strong>Preview the UI with zero keys.</strong>&nbsp;A built-in fake mode renders the interface locally so you can click around before signing up for anything.</li><li><strong>Two keys unlock real video.</strong>&nbsp;A free&nbsp;<code>VIDEOSDK_API_KEY</code>&nbsp;and&nbsp;<code>VIDEOSDK_SECRET</code>&nbsp;turn it into genuine multi-participant meetings. The server mints tokens for you.</li><li><strong>Claude Code does the customizing.</strong>&nbsp;Ask it to rebrand, add features, or change behavior in plain English.</li><li><strong>One click to deploy.</strong>&nbsp;A Vercel button ships it to the internet with the two env vars pre-filled.</li></ul>
<!--kg-card-begin: html-->
<iframe width="560" height="315" src="https://www.youtube.com/embed/HpAa3eld-bc?si=YWsmm9xQd9fR0d2T" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<h2 id="what-is-a-google-meet-clone">What is a Google Meet clone?</h2><p>A Google Meet clone is defined as a self-hosted video conferencing app that reproduces Google Meet's interface and meeting mechanics on infrastructure you control. It works by pairing a Meet-styled front end with a WebRTC media backend that routes audio and video between participants.</p><p>The hard part was never the UI. It is the media layer: peer negotiation, an SFU to route streams so a five-person call does not melt a laptop, TURN relays for participants behind restrictive firewalls, and signed tokens so a guest cannot grant themselves host powers.</p><p>The&nbsp;<code>videosdk-community/google-meet-clone</code>&nbsp;repo hands you the UI and delegates that media layer to VideoSDK's SFU, which is why the whole thing fits in one afternoon instead of one quarter. Real-time transport follows the&nbsp;<a href="https://www.w3.org/TR/webrtc/">W3C WebRTC specification</a>, so the browser side is standards-based rather than proprietary.</p><p>Most of the competing tutorials in this space stop before that line. The&nbsp;<a href="https://strapi.io/blog/build-a-google-meet-clone-with-strapi5-and-nextjs-part-1">Strapi 5 and Next.js series</a>&nbsp;and the popular&nbsp;<a href="http://WebRTC-plus-Socket.io">WebRTC-plus-Socket.io</a>&nbsp;courses have you hand-roll signaling with peer-to-peer connections, which works for two people and degrades badly past four. This guide starts from an SFU, so scaling is not a rewrite.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/in-call-grid.png" class="kg-image" alt="How to Build an Open-Source Google Meet Clone with Claude Code + VideoSDK" loading="lazy" width="1512" height="900"/></figure><h2 id="features-the-repo-ships-with">Features the repo ships with</h2><p>The repo ships the feature set that actually matters in a meeting app, not a video-chat demo with two tiles.</p><ul><li>Real-time HD video and audio over VideoSDK's SFU, so calls scale past two people.</li><li>A grid / gallery view with tiles that resize themselves as the room fills up.</li><li>A pre-join green room with a mirrored camera preview and device pickers.</li><li>Chat with saved history, floating emoji reactions, and raise hand, all synced to late joiners.</li><li>Screen sharing and cloud recording.</li><li>Host controls with a real waiting room: guests knock, and the host admits or removes them.</li></ul><p>It looks like Google Meet because the UI is built from a Figma reference, down to the icons and fonts. It works like Google Meet because the media is real.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/landing.png" class="kg-image" alt="How to Build an Open-Source Google Meet Clone with Claude Code + VideoSDK" loading="lazy" width="1512" height="900"/></figure><h2 id="prerequisites-for-building-the-clone">Prerequisites for building the clone</h2><p>You need very little to start:</p><ul><li><strong>Node.js 18 or newer</strong>&nbsp;(20+ recommended). Check with&nbsp;<code>node -v</code>.</li><li><strong>git</strong>, to clone the repo.</li><li><strong>A free VideoSDK account</strong>&nbsp;for live video. You'll grab the keys in Step 3, so you can skip this until then.</li><li><strong>Claude Code</strong>&nbsp;(optional, but it's the star of Step 4). It's Anthropic's terminal coding agent, documented at&nbsp;<a href="https://docs.claude.com/en/docs/claude-code/overview">docs.claude.com</a>.</li></ul><p>That's it. No database, no backend to stand up, no accounts system to wire in.</p><h2 id="step-1clone-the-google-meet-clone-repo">Step 1 - Clone the Google Meet clone repo</h2><p>Getting the code is two commands and one install, and the lockfile pins every dependency for you.</p><pre><code class="language-bash">git clone https://github.com/videosdk-community/google-meet-clone
cd google-meet-clone
npm install
</code></pre><p>This project uses&nbsp;<strong>npm</strong>&nbsp;as its package manager, so&nbsp;<code>npm install</code>&nbsp;reads the committed lockfile and pulls everything down: React 19, TypeScript, Vite, and the&nbsp;<code>@videosdk.live/react-sdk</code>. Give it a minute.</p><p>While that runs, here's the shape of what you cloned. Feature components live under&nbsp;<code>src/routes/</code>&nbsp;(the landing page, the green room, and the in-call screen). Every call into VideoSDK is hidden behind a single hook layer in&nbsp;<code>src/meeting/</code>, and the token-signing serverless functions sit in&nbsp;<code>api/</code>. You rarely need to touch the SDK directly, which is exactly why customizing this is pleasant. If you do want the raw surface, it is the same one documented in the&nbsp;<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React quickstart</a>.</p><h2 id="step-2preview-the-ui-in-fake-mode">Step 2 - Preview the UI in fake mode</h2><p>You don't need any keys to see the interface. The project ships a&nbsp;<strong>fake mode</strong>&nbsp;that renders the full UI against a local mock, no camera and no network required.</p><p>Start the dev server:</p><pre><code class="language-bash">npm run dev
</code></pre><p>It serves the app on&nbsp;<code>http://localhost:5173</code>. Now open a meeting URL with the&nbsp;<code>?fake=ok</code>&nbsp;switch appended:</p><pre><code class="language-text">http://localhost:5173/abc-defg-hij?fake=ok
</code></pre><p>You'll first land in the green room, then join into a fully rendered meeting: participant tiles, the control bar, chat, reactions, the works. It's perfect for exploring the layout, tweaking styles, and getting your bearings.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/green-room.png" class="kg-image" alt="How to Build an Open-Source Google Meet Clone with Claude Code + VideoSDK" loading="lazy" width="1512" height="900"/></figure><p>One honest caveat:&nbsp;<strong>fake mode is a UI preview, not a real call.</strong>&nbsp;It uses a built-in fake client with fabricated participants, so nothing goes over the network and no one else can join. It's a developer convenience that's compiled out of production builds entirely. For actual meetings with real people, you need keys, which is the next step.</p><h2 id="step-3add-real-video-with-videosdk-keys">Step 3 - Add real video with VideoSDK keys</h2><p>Two environment variables turn the UI preview into genuine multi-participant meetings, and neither one ever reaches the browser.</p><p>Head to the&nbsp;<a href="https://dub.sh/X5Fn46e" rel="noreferrer">VideoSDK dashboard</a>&nbsp;and create a free account. You'll get an&nbsp;<strong>API key</strong>&nbsp;and a&nbsp;<strong>secret</strong>.&nbsp;</p><p>Copy the example env file and paste your credentials in:</p><pre><code class="language-bash">cp .env.example .env
</code></pre><p>Open the new&nbsp;<code>.env</code>&nbsp;and fill in the two values:</p><pre><code class="language-text">VIDEOSDK_API_KEY=your_key
VIDEOSDK_SECRET=your_secret
</code></pre><p>Those are the only two variables that matter. Restart the dev server (<code>npm run dev</code>) and you're live. Click&nbsp;<strong>New meeting</strong>&nbsp;on the landing page and it creates a real VideoSDK room and makes you its host. Open the meeting link in a second browser or device to join as a guest.</p><p>Two things are worth knowing about how this stays safe. First,&nbsp;<strong>the secret never reaches the browser.</strong>&nbsp;It's read only by the functions in&nbsp;<code>api/</code>, and the project deliberately keeps it out of any&nbsp;<code>VITE_</code>-prefixed variable so it can't get bundled into the client.</p><p>Second,&nbsp;<strong>there's no manual token step.</strong>&nbsp;When a client joins, the server mints the right meeting token on the spot: a host token if the client holds a valid grant for that room, a guest token otherwise. You paste your key and secret once, and token signing is automatic from then on. The token format and its permission claims are described in the&nbsp;<a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">VideoSDK authentication docs</a>.</p><h2 id="step-4customize-the-clone-with-claude-code">Step 4 - Customize the clone with Claude Code</h2><p>Claude Code turns customization into a conversation, because every VideoSDK call in this repo already sits behind one hook layer.</p><p>Instead of hunting through files, you describe what you want and let the agent make the change. Run&nbsp;<code>claude</code>&nbsp;in the project root and try prompts like these. (These are illustrative examples of what you'd ask, not magic incantations. Phrase them however feels natural.)</p><p><strong>Rebrand the colors:</strong></p><blockquote>"The app uses design tokens generated from Figma. Change the primary accent color to a deep purple across the UI, and show me which files you touched."</blockquote><p><strong>Add a reaction:</strong></p><blockquote>"The reactions picker in the control bar has a set of emoji. Add a fire emoji to the list so participants can react with it, and make sure it floats up on the tiles like the others."</blockquote><p><strong>Tweak the meeting controls:</strong></p><blockquote>"In the in-call control bar, add a keyboard shortcut that toggles the People panel, and show it in the button's tooltip."</blockquote><p><strong>Understand before you change:</strong></p><blockquote>"Explain how a guest goes from clicking a meeting link to appearing in the host's waiting room. Trace the path through the code."</blockquote><p>Point Claude Code at&nbsp;<code>src/routes/</code>&nbsp;for anything visual and&nbsp;<code>src/meeting/</code>&nbsp;for anything media-related, and it'll follow the existing patterns rather than reinventing them. Ask, review the diff, run the app, repeat. That loop is the whole workflow.</p><h2 id="step-5deploy-to-vercel">Step 5 - Deploy to Vercel</h2><p>Deployment is one button because the repo ships nothing that needs configuring, only the two secrets.</p><p>When you're ready to share it, the fastest path is the one-click Vercel button in the repo's README. It clones the project into your own Vercel account and prompts you for the two environment variables (<code>VIDEOSDK_API_KEY</code>&nbsp;and&nbsp;<code>VIDEOSDK_SECRET</code>), with a link straight to your API keys.</p><p>Prefer to do it yourself? Build and deploy:</p><pre><code class="language-bash">npm run build
</code></pre><p>Then deploy to any host that runs the&nbsp;<code>api/</code>&nbsp;serverless functions. On Vercel it's zero-config: there's no&nbsp;<code>vercel.json</code>&nbsp;to write, the functions become endpoints automatically, and the single-page app is served statically. Set the same two env vars in your host's dashboard, and tokens get minted at request time. Nothing is baked into the client, and there's nothing to paste per meeting.</p><h2 id="tour-of-the-running-meeting-app">Tour of the running meeting app</h2><p>Three surfaces make up the whole app: a landing page, a green room, and the call itself.</p><p>The&nbsp;<strong>landing page</strong>&nbsp;(<code>/</code>) is where you start a meeting or join by code. Click&nbsp;<strong>New meeting</strong>&nbsp;and it spins up a real room and hands you the host role.</p><p>Every meeting lives at&nbsp;<code>/:meetingId</code>, and that one route covers both stages. First you hit the&nbsp;<strong>green room</strong>: type your name, check yourself in the mirrored camera preview, pick your mic and camera, and hit&nbsp;<strong>Join now</strong>. Then the view swaps in place to the&nbsp;<strong>call itself</strong>, and the URL never changes, exactly like real Meet.</p><p>Inside the call you get the grid of participant tiles that size themselves to the room, a control bar for mic, camera, screen share, reactions, and raise hand, plus a chat panel that keeps its history so late joiners catch up.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/in-call-chat.png" class="kg-image" alt="How to Build an Open-Source Google Meet Clone with Claude Code + VideoSDK" loading="lazy" width="1512" height="900"/></figure><p>Open the&nbsp;<strong>People</strong>&nbsp;panel to see who's in, and if you're the host, you get the controls that make it real: a waiting room where guests knock for admission, the ability to mute at the media server, and cloud recording with a live indicator. Host power isn't a hidden button either. It's a server-signed grant, so a guest's client simply doesn't hold the capability.</p><h2 id="taking-your-google-meet-clone-to-production">Taking your Google Meet clone to production</h2><p>Five things change between&nbsp;<code>localhost:5173</code>&nbsp;and a meeting your users trust, and most clone tutorials never mention any of them.</p><p><strong>HTTPS is not optional.</strong>&nbsp;Browsers only expose&nbsp;<code>getUserMedia</code>&nbsp;on secure origins, with&nbsp;<code>localhost</code>&nbsp;as the single exemption. Deploy behind TLS or the camera never turns on.</p><p><strong>NAT traversal is already handled, and that is the point.</strong>&nbsp;Roughly one in five WebRTC connections cannot be established peer-to-peer and needs a TURN relay. Because media here goes through VideoSDK's SFU, you inherit its ICE and relay infrastructure instead of standing up and paying for&nbsp;<code>coturn</code>.&nbsp;</p><p><strong>Token lifetime needs a decision.</strong>&nbsp;The functions in&nbsp;<code>api/</code>&nbsp;mint short-lived meeting tokens per join. If you extend the app with long meetings or reconnect flows, decide what happens when a token expires mid-call, and refresh rather than dropping the participant.</p><p><strong>Recordings need a home.</strong>&nbsp;Cloud recording writes to VideoSDK storage by default. For anything with a retention or residency requirement, wire the recording webhook to your own bucket and record where that data may legally live.</p><p><strong>SPA fallback breaks deep links if you forget it.</strong>&nbsp;Meeting URLs are client-side routes. On Vercel this is automatic; on Nginx, S3, or any static host, add a catch-all rewrite to&nbsp;<code>index.html</code>&nbsp;or&nbsp;<code>/:meetingId</code>&nbsp;returns a 404 to every invited guest.</p><h2 id="how-does-this-google-meet-clone-compare-to-google-meet">How does this Google Meet clone compare to Google Meet?</h2><p>This clone matches Google Meet's UI and meeting mechanics, and deliberately skips the accounts-and-history backend behind it.</p><table>
<thead>
<tr>
<th>Capability</th>
<th>This clone</th>
<th>Google Meet</th>
</tr>
</thead>
<tbody>
<tr>
<td>HD video, audio, screen share</td>
<td>Yes, over VideoSDK's SFU</td>
<td>Yes</td>
</tr>
<tr>
<td>Chat, reactions, raise hand</td>
<td>Yes, synced to late joiners</td>
<td>Yes</td>
</tr>
<tr>
<td>Waiting room and host controls</td>
<td>Yes, server-signed grants</td>
<td>Yes</td>
</tr>
<tr>
<td>Cloud recording</td>
<td>Yes</td>
<td>Yes, on paid Workspace tiers</td>
</tr>
<tr>
<td>Identity and accounts</td>
<td>A name you type</td>
<td>Google account</td>
</tr>
<tr>
<td>Calendar and meeting history</td>
<td>Not included</td>
<td>Yes</td>
</tr>
<tr>
<td>Source code and self-hosting</td>
<td>MIT, fully yours</td>
<td>Closed, hosted only</td>
</tr>
</tbody>
</table>
<p>The verdict is conditional. Use Google Meet when you want meetings to just exist for a team that already lives in Google Workspace. Build on this clone when video needs to sit inside your own product, carry your branding, and follow your own permission model. It is a starting point for a product, not a replacement for a hosted meeting service.</p><h2 id="definitions-glossary-for-meeting-apps">Definitions glossary for meeting apps</h2><ul><li><strong>Room</strong>&nbsp;- the VideoSDK unit a meeting happens in. Participants join a room by ID, and every media stream is scoped to it. Here, the room ID is the&nbsp;<code>/:meetingId</code>&nbsp;in the URL.</li><li><strong>Participant</strong>&nbsp;- one connected client in a room, carrying its own audio, video, and screen-share tracks plus a role that decides what it may do.</li><li><strong>Meeting token</strong>&nbsp;- a short-lived signed credential granting a client permission to join a specific room, minted server-side in&nbsp;<code>api/</code>&nbsp;from your API key and secret.</li><li><strong>SFU (Selective Forwarding Unit)</strong>&nbsp;- a media server that receives each participant's stream once and forwards it to the others, so upload cost stays flat as the room grows.</li><li><strong>Prebuilt UI Kit</strong>&nbsp;- VideoSDK's drop-in meeting interface, embeddable as an iframe or React component when you want a working call without building the UI at all.</li></ul><h2 id="frequently-asked-questions-about-google-meet-clones">Frequently asked questions about Google Meet clones</h2><p><strong>Do I need a VideoSDK account to build a Google Meet clone with this repo?</strong><br>For real meetings, yes, and it's free. You need a&nbsp;<code>VIDEOSDK_API_KEY</code>&nbsp;and&nbsp;<code>VIDEOSDK_SECRET</code>&nbsp;from the&nbsp;<a href="https://dub.sh/X5Fn46e" rel="noreferrer">dashboard</a>. To just explore the UI, no: fake mode (<code>?fake=ok</code>) runs with no keys at all.</br></p><p><strong>Is the keyless run a real call?</strong><br>No, the keyless run is not a real call. Fake mode is a local UI preview using a built-in mock client. It's great for design work and clicking through the interface, but nobody can actually join and nothing goes over the network. Add the two keys for genuine multi-participant video.</br></p><p><strong>Is this Google Meet clone really free and open source?</strong><br>Yes, it is genuinely free and open source. The repo is released under the&nbsp;<a href="https://opensource.org/license/mit">MIT License</a>, so you're free to use, modify, self-host, and build a commercial product on top of it.</br></p><p><strong>Can I self-host it instead of using Vercel?</strong><br>Yes, you can self-host it anywhere that runs Node functions. Set&nbsp;<code>VIDEOSDK_API_KEY</code>&nbsp;and&nbsp;<code>VIDEOSDK_SECRET</code>&nbsp;as environment variables, run&nbsp;<code>npm run build</code>, and deploy the&nbsp;<code>api/</code>&nbsp;functions alongside the static build. On static-only hosts, add an SPA fallback so meeting deep-links load instead of 404ing.</br></p><p><strong>Do I have to write token-minting code?</strong><br>No, you do not write any token-minting code. The server mints host and guest tokens per request from your key and secret. There's nothing to sign by hand and no token script to run.</br></p><p><strong>How many participants can a meeting hold?</strong><br>Capacity is set by VideoSDK's SFU rather than the UI, so the grid layout is the practical limit long before the media layer is. Check your plan's concurrency limits before promising a number.&nbsp;</br></p><p><strong>Can I build a Zoom clone the same way?</strong><br>Yes, the same architecture applies. Swap the Meet-styled components in&nbsp;<code>src/routes/</code>&nbsp;for your own layout and keep the&nbsp;<code>src/meeting/</code>&nbsp;hook layer untouched, since the media logic is UI-agnostic.</br></p><h2 id="conclusion-and-next-steps">Conclusion and next steps</h2><p>You're a few commands away from your own open-source Google Meet clone, running on real WebRTC infrastructure rather than a demo signaling server.</p><ol><li><strong>Try it live</strong>&nbsp;on&nbsp;<a href="https://google-meet-clone-by-videosdk.vercel.app/">google-meet-clone-by-videosdk.vercel.app</a>, the deployed demo you can open right now.</li><li><strong>Fork</strong>&nbsp;<a href="https://dub.sh/pn12llc?utm_source=blog" rel="noreferrer"><code>videosdk-community/google-meet-clone</code></a>&nbsp;and&nbsp;<code>npm install</code>.</li><li><strong>Grab free keys</strong>&nbsp;from the&nbsp;<a href="https://dub.sh/X5Fn46e" rel="noreferrer">VideoSDK dashboard</a>&nbsp;and drop them in&nbsp;<code>.env</code>.</li><li><strong>Open Claude Code</strong>&nbsp;and start shaping it into your product.</li></ol><p>From there, the natural next steps are the&nbsp;<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK React quickstart</a>&nbsp;if you want to understand the hook layer, the&nbsp;<a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Prebuilt UI Kit</a>&nbsp;if you'd rather skip UI work entirely on your next app, and&nbsp;<a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/quick-start">interactive live streaming</a>&nbsp;if your product needs an audience larger than a meeting.</p><p>Real video, a polished UI, and an AI agent to do the heavy lifting. What are you building on top of it?</p>]]></content:encoded></item><item><title><![CDATA[Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026]]></title><description><![CDATA[Compare the top GetStream alternatives for video and voice APIs using verified 2026 documentation, pricing anchors, deployment choices, honest limitations, proof-of-concept steps, and a production migration checklist.]]></description><link>https://www.videosdk.live/blog/getstream-alternatives</link><guid isPermaLink="false">6a5dc146b3240feb748c5724</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 20 Jul 2026 09:54:44 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/07/getstream-alternatives-hero--1-.png" medium="image"/><content:encoded><![CDATA[<blockquote>GetStream alternatives for video and voice APIs include VideoSDK, LiveKit, Agora, Daily, 100ms, Twilio Video, Vonage Video API, Zoom Video SDK, Sendbird Calls, and MirrorFly. The right choice depends on media requirements, deployment control, supported clients, adjacent messaging needs, and total production cost.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/getstream-alternatives-hero--1-.png" alt="Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026"/><p>Stream, often searched as GetStream, provides APIs and SDKs for chat, activity feeds, moderation, and real-time video. Its integrated product suite can simplify communication features, but not every application needs the same mix of persistent messaging and real-time media.</p><p>This guide compares 10 GetStream alternatives for video and voice using six practical criteria: media depth, client coverage, build speed, infrastructure control, economics, and adjacent capabilities. Product information and public pricing were reviewed on 20 July 2026.</p><p>The ranking uses public documentation and pricing rather than paid placements, private benchmarks, or synthetic first-hand testing, and each provider is given a clear scenario where it may be the better fit.</p><h3 id="what-is-getstream">What Is GetStream?</h3><p><a href="https://getstream.io/" rel="nofollow noreferrer">GetStream</a>, now branded as Stream, is a developer platform for adding in-app communication. Its product suite includes chat, activity feeds, moderation, and <a href="https://getstream.io/video/docs/" rel="noreferrer nofollow">video and audio APIs</a>, so teams can combine persistent conversation data with real-time media under one vendor.</p><p>For video and voice, Stream provides client SDKs for web, iOS, Android, React Native, Flutter, and Unity. Its managed infrastructure handles signalling and media delivery, while applications control identity, permissions, layouts, and product logic.</p><p><a href="https://getstream.io/video/docs/javascript/pricing-guide/" rel="nofollow noreferrer">Stream's video pricing guide</a> bills real-time media in participant minutes, with video rates based on the aggregated resolution received by each participant. That model can be practical for an integrated stream stack, but it should be compared against recording, transcription, egress, support, and migration costs.</p><h2 id="why-seek-an-alternative"><strong>Why Seek an Alternative?</strong></h2><p>Teams usually evaluate GetStream alternatives when the communication layer no longer matches their technical, operational, or commercial requirements. Common reasons include:</p><ul><li><strong>Broader client coverage:</strong> Support for specialised desktop, game-engine, backend, or embedded-device SDKs.</li><li><strong>More infrastructure control:</strong> Self-hosting, on-premises deployment, private cloud, regional routing, or full source access.</li><li><strong>A different build path:</strong> Faster prebuilt UI, deeper media controls, role-based rooms, large interactive events, SIP, or AI-agent media workflows.</li><li><strong>A better workload cost fit:</strong> Pricing that better matches audio-only usage, participant counts, resolution, recording, streaming, data transfer, or support requirements.</li><li><strong>A partial migration strategy:</strong> Replacing Stream Video while keeping Stream Chat, Feeds, or Moderation in place.</li></ul><p>The right alternative depends on which stream layers must move. Treat chat history, feeds, moderation, push notifications, recordings, and webhooks as separate migration decisions instead of assuming that a new RTC provider replaces the full stream stack.</p><h2 id="how-we-evaluated-getstream-alternatives">How We Evaluated GetStream Alternatives</h2><p><strong>A useful GetStream comparison begins with workload fit, not the longest feature page.</strong> The RTC Replacement Fit Test makes the shortlist transparent and repeatable.</p><ol><li><strong>Media depth:</strong> Support for one-to-one calls, group rooms, audio-only sessions, screen sharing, recording, transcription, real-time broadcasting, and interactive live streaming.</li><li><strong>Client surface:</strong> Maintained SDKs for browsers, iOS, Android, React Native, Flutter, desktop, game engines, backends, and embedded devices where relevant.</li><li><strong>Build speed:</strong> Prebuilt UI, composable components, sample applications, secure authentication guidance, device testing, and production observability.</li><li><strong>Infrastructure control:</strong> Managed cloud, region selection, private networking, self-hosting, on-premises deployment, or full source-code access.</li><li><strong>Economics:</strong> Participant-minute rules, resolution tiers, recording, egress, transcription, support, compliance add-ons, and minimum commitments.</li><li><strong>Adjacent capabilities:</strong> Persistent chat, activity feeds, SIP or PSTN, moderation, interactive streaming, and real-time AI agent support.</li></ol><p>The order reflects overall fit for embedded video and voice, not a universal performance benchmark. A lower-ranked provider can be the correct choice when its deployment model, ecosystem, or media workflow better matches the application.</p><p>VideoSDK appears first because it scores strongly across these combined RTC criteria, particularly client coverage, custom and prebuilt development paths, and interactive streaming. The ranking is not universal: each entry states a trade-off and a scenario where another provider may fit better.</p><h2 id="getstream-alternatives-compared-at-a-glance">GetStream Alternatives Compared at a Glance</h2><p><strong>The leading GetStream alternatives divide into managed RTC, open-source infrastructure, broad CPaaS, and communication suites.</strong> Choose the category before comparing individual features.</p><table>
<thead>
<tr>
<th>Platform</th>
<th>Best fit</th>
<th>Deployment</th>
<th>Fast UI path</th>
<th>Public pricing anchor checked 17 July 2026</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td>Multi-platform RTC, prebuilt calls, and interactive streaming</td>
<td>Managed platform</td>
<td>Prebuilt UI Kit plus custom SDKs</td>
<td>Pay as you go with $20 free account credit</td>
</tr>
<tr>
<td>LiveKit</td>
<td>Open-source media infrastructure, self-hosting, and agents</td>
<td>Self-hosted or LiveKit Cloud</td>
<td>Components and starter apps</td>
<td>Usage-based connection minutes, transfer, and transcoding</td>
</tr>
<tr>
<td>Agora</td>
<td>Global RTC, gaming, native platforms, and media extensions</td>
<td>Managed platform</td>
<td>App Builder, extensions, and SDKs</td>
<td>10,000 free minutes; $0.99 audio and $3.99 HD video per 1,000 participant minutes</td>
</tr>
<tr>
<td>Daily</td>
<td>Browser-led products, embeddable calls, and Pipecat</td>
<td>Managed platform</td>
<td>Daily Prebuilt plus client SDKs</td>
<td>10,000 free minutes; $0.004 video and $0.00099 audio-only base rates</td>
</tr>
<tr>
<td>100ms</td>
<td>Role-based rooms, classrooms, audio rooms, and live events</td>
<td>Managed platform</td>
<td>Prebuilt links, components, and SDKs</td>
<td>10,000 free conferencing minutes; $0.004 afterwards</td>
</tr>
<tr>
<td>Twilio Video</td>
<td>Teams already using Twilio Voice, Messaging, or Flex</td>
<td>Managed CPaaS</td>
<td>Reference apps and SDKs</td>
<td>$0.004 per video participant minute</td>
</tr>
<tr>
<td>Vonage Video API</td>
<td>Enterprise media workflows, broadcasting, and OpenTok continuity</td>
<td>Managed platform</td>
<td>Reference apps and Video Playground</td>
<td>$0.00410 per participant minute after new-customer trial allowance</td>
</tr>
<tr>
<td>Zoom Video SDK</td>
<td>Custom sessions using Zoom media infrastructure</td>
<td>Managed platform</td>
<td>UI Toolkit or custom SDK</td>
<td>Prepaid credits metered by participant session minutes</td>
</tr>
<tr>
<td>Sendbird Calls</td>
<td>Persistent chat combined with direct or smaller group calls</td>
<td>Managed communication suite</td>
<td>Calls SDKs plus Chat integration</td>
<td>Relayed voice $0.0015 and video $0.0035 per user minute</td>
</tr>
<tr>
<td>MirrorFly</td>
<td>Full source, on-premises, white-label chat, calls, and feeds</td>
<td>Cloud, private cloud, or on-premises</td>
<td>UI Kit with sales-assisted implementation</td>
<td>MAU plans, included call minutes, and custom enterprise terms</td>
</tr>
</tbody>
</table>
<p>These pricing units are not directly interchangeable. Some vendors bill resolution, some bill connected users, and others add data transfer, recording, egress, compliance, or support charges.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-20--2026--02_23_37-PM.png" class="kg-image" alt="Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026" loading="lazy" width="1536" height="1024"/></figure><h2 id="best-getstream-alternatives-for-video-and-voice">Best GetStream Alternatives for Video and Voice</h2><p><strong>VideoSDK leads this RTC-focused shortlist, while every other provider wins under a different deployment, ecosystem, scale, or workflow condition.</strong></p><h3 id="1-videosdk-best-overall-rtc-fit">1. VideoSDK: Best Overall RTC Fit</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-130930-1.png" class="kg-image" alt="Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026" loading="lazy" width="1523" height="727"/></figure><p><strong>Best for:</strong> Teams needing custom <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">video calls</a>, audio calls, and <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">interactive live streaming</a> across the web, native mobile integrations, or embedded video calls on your website.</p><p><strong>Why it ranks first:</strong> <a href="https://docs.videosdk.live/" rel="noreferrer">VideoSDK documentation</a> lists JavaScript, React, React Native, Android XML and Compose, iOS UIKit and SwiftUI, Flutter, Unity, Python, C++, IoT, and the prebuilt SDK. The same documentation covers all features: recording, transcription, SIP connectivity, end-to-end encryption, geo-fencing, network-aware interfaces, custom video tracks, and collaboration features.</p><p>Teams can begin with the <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start" rel="noreferrer">Prebuilt UI Kit</a> or use custom SDK hooks and events. Separate quickstarts cover audio or video calls and interactive live streaming, which reduces the need to assemble different media vendors.</p><p><strong>Pricing:</strong> <a href="https://videosdk.live/pricing" rel="noreferrer">VideoSDK's pay-as-you-go pricing</a> is <strong>$0.001</strong> per participant-minute for audio calls, <strong>$0.004</strong> per participant-minute for video calls, and <strong>$0.002</strong> per viewer-minute for live streaming. VideoSDK provides <strong>$20 in free credits</strong>.</p><p><strong>Trade-off: </strong>VideoSDK is RTC-first, so it can replace Stream’s real-time video and audio layer, but not its persistent chat or activity feeds. A stream may be simpler when chat, messaging, identity, moderation, and stored data are already tightly integrated in production.</p><h3 id="2-livekit-best-for-self-hosting">2. LiveKit: Best for Self-Hosting</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131109-1.png" class="kg-image" alt="Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026" loading="lazy" width="1532" height="697"/></figure><p><strong>Best for:</strong> Engineering teams that value open-source media infrastructure, self-hosting, SIP, data control, and programmable voice or video agents.</p><p><strong>Why it ranks here:</strong> <a href="https://docs.livekit.io/intro/cloud/" rel="nofollow noreferrer">LiveKit Cloud and self-hosted documentation</a> describe an open-source WebRTC server with managed global infrastructure or self-managed deployment. The ecosystem includes ingress, egress, SIP, encryption, agents, and observability.</p><p>Self-hosting gives teams control over regions and infrastructure, but it also transfers responsibility for <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a>, <a href="https://www.videosdk.live/developer-hub/sip/sip-tls" rel="noreferrer">TLS</a>, capacity planning, upgrades, monitoring, scaling, and incident response. LiveKit Cloud replaces those duties with a managed global mesh.</p><p><strong>Pricing:</strong> LiveKit Cloud meters real-time media by connection time and data transfer, while ingress and egress can add transcoding or export usage. Included allowances vary by plan, so estimate bandwidth as well as participant minutes.</p><p><strong>Trade-off:</strong> LiveKit does not replace Stream Chat or activity feeds. It fits teams prepared to assemble persistent messaging, moderation, and feed functionality as separate application services.</p><h3 id="3-agora-best-for-global-and-game-engine-reach">3. Agora: Best for Global and Game-Engine Reach</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131023-1.png" class="kg-image" alt="Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026" loading="lazy" width="1525" height="715"/></figure><p><strong>Best for:</strong> Products that need a mature global RTC network, native desktop support, Unity or Unreal Engine, media extensions, or large interactive deployments.</p><p><strong>Why it ranks here:</strong> Agora's <a href="https://www.agora.io/en/products/video-call/" rel="nofollow noreferrer">Video Calling product page</a> lists Android, iOS, Web, Windows, Electron, Flutter, React Native, Unity, and Unreal Engine. It also covers recording, whiteboards, noise suppression, speech-to-text, analytics, multi-track media, and App Builder.</p><p>Agora reports 80 billion monthly real-time voice and video minutes across more than 200 countries and regions. This is a vendor-published scale statement, not an independent latency or reliability benchmark.</p><p><strong>Pricing:</strong> <a href="https://www.agora.io/en/pricing/video-calling/" rel="noreferrer">Agora Video Calling pricing</a> currently includes 10,000 free minutes, then $0.99 per 1,000 audio minutes and $3.99 per 1,000 HD video minutes before add-ons.</p><p><strong>Trade-off:</strong> Agora's broad product, extension, analytics, and billing metrics require careful architecture review. It is strongest when specialised platform reach or media tooling justifies that complexity.</p><h3 id="4-daily-best-for-browser-first-products">4. Daily: Best for Browser-First Products</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131144-1.png" class="kg-image" alt="Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026" loading="lazy" width="1508" height="717"/></figure><p><strong>Best for:</strong> Browser-led applications that value rapid embedding, transparent participant-minute pricing, daily prebuilt, SIP, and access to the open-source Pipecat agent ecosystem.</p><p><strong>Why it ranks here:</strong> <a href="https://www.daily.co/pricing/video-sdk/" rel=" nofollow noreferrer">Daily pricing and product documentation</a> cover custom video and audio calls, pre-built, recording, <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a>, <a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer">HLS</a>, telephony, transcription, and Pipecat. Daily does not add resolution surcharges to its base call rate.</p><p>Daily Prebuilt supplies a full call component, while the client SDKs support custom layouts and track control. This makes Daily a practical choice for web collaboration, telehealth, support, and agent media projects.</p><p><strong>Pricing:</strong> Daily includes 10,000 participant minutes monthly, then lists $0.004 for video and audio calls or $0.00099 for audio-only calls at the first paid tier. Recording, streaming, transcription, HIPAA, and advanced firewall control cost extra.</p><p><strong>Trade-off:</strong> Daily is strongest in RTC and agent media. Teams leaving Stream Chat, Feeds, or Moderation still need another service or application data model for those persistent layers.</p><h3 id="5-100ms-best-for-role-based-live-experiences">5. 100ms: Best for Role-Based Live Experiences</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131222-1.png" class="kg-image" alt="Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026" loading="lazy" width="1503" height="667"/></figure><p><strong>Best for:</strong> Classrooms, communities, audio rooms, webinars, and live events where teachers, students, hosts, speakers, and viewers need different permissions.</p><p><strong>Why it ranks here:</strong> The <a href="https://www.100ms.live/docs/get-started/v2/get-started/overview" rel="noreferrer nofolllow">100ms overview</a> combines WebRTC conferencing, HLS live streaming, rooms, roles, and client SDKs for web, Android, iOS, Flutter, and React Native. Prebuilt links and components offer a faster launch path.</p><p>Room templates define what each role can publish, subscribe to, record, or stream. That model maps cleanly to classrooms, <a href="https://www.videosdk.live/solutions/social" rel="noreferrer">social audio</a>,<a href="https://www.videosdk.live/solutions/live-shopping" rel="noreferrer"> live shopping</a>, and stage-audience applications without hard-coding every permission branch.</p><p><strong>Pricing:</strong> <a href="https://www.100ms.live/pricing" rel="noreferrer nofollow">100ms pricing</a> includes 10,000 conferencing minutes, followed by $0.004 per participant minute. Audio-only use cases receive a published discount, while recording, transcription, encoding, and RTMP output use separate units.</p><p><strong>Trade-off:</strong> 100ms focuses on media experiences rather than a full stream-style feed and moderation suite. Persistent community data still requires separate architecture.</p><h3 id="6-twilio-video-best-for-existing-twilio-stacks">6. Twilio Video: Best for Existing Twilio Stacks</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-20-130858.png" class="kg-image" alt="Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026" loading="lazy" width="1517" height="728"/></figure><p><strong>Best for:</strong> Teams already using Twilio Voice, Messaging, Conversations, or Flex and wanting video under the same commercial and operational relationship.</p><p><strong>Why it ranks here: </strong><a href="https://www.twilio.com/docs/video/overview" rel="nofollow noreferrer">Twilio Video</a> supports programmable WebRTC rooms, screen sharing, participant recordings, compositions, transcription, noise cancellation, virtual backgrounds, network quality controls, and voice interoperability.</p><p>Older comparison pages may incorrectly describe Twilio Video as retired. Twilio reversed its earlier 2026 end-of-life decision and states, <strong>"Twilio Video will remain a standalone product."</strong></p><p><strong>Pricing:</strong> <a href="https://www.twilio.com/en-us/video/pricing" rel="noreferrer nofollow">Twilio Video pricing</a> starts at $0.004 per participant minute and documents up to 50 participants. Recordings, compositions, transcriptions, storage, and programmable voice call legs add separate charges.</p><p><strong>Trade-off:</strong> Twilio's video client surface is narrower than VideoSDK, Agora, or Zoom Video SDK. Choose it for CPaaS consolidation, not for the widest framework coverage.</p><h3 id="7-vonage-video-api-best-for-media-workflows">7. Vonage Video API: Best for Media Workflows</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131437-1.png" class="kg-image" alt="Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026" loading="lazy" width="1515" height="722"/></figure><p><strong>Best for:</strong> Enterprise teams needing OpenTok continuity, broadcasting, captions, media processing, SIP interconnect, audio connector, or branded composition workflows.</p><p><strong>Why it ranks here:</strong> <a href="https://developer.vonage.com/en/video/overview" rel="noreferrer nofollow">Vonage Video API documentation</a> covers real-time video, messaging, screen sharing, recording, encryption, live captions, Experience Composer, audio connector, broadcasting, and reference applications.</p><p>Experience Composer can publish a web-rendered layout into a session for recording or broadcast. Audio Connector streams raw audio to server-side processing, which suits transcription, translation, compliance, or agent pipelines.</p><p><strong>Pricing:</strong> <a href="https://www.vonage.com/communications-apis/video/pricing/" rel="noreferrer nofollow">Vonage pricing</a> lists $0.00410 per participant minute after its new-customer trial allowance. Advanced recording, broadcasting, AI connectors, <a href="https://www.videosdk.live/developer-hub/sip/sip-protocol-architecture-guide" rel="noreferrer">SIP</a>, security, and regional features use separate rates.</p><p><strong>Trade-off:</strong> Existing TokBox users are being directed towards the newer Vonage dashboard. Test account, migration, and operational workflows early instead of treating the change as a simple SDK swap.</p><h3 id="8-zoom-video-sdk-best-for-zoom-infrastructure">8. Zoom Video SDK: Best for Zoom Infrastructure</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131606-1.png" class="kg-image" alt="Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026" loading="lazy" width="1526" height="681"/></figure><p><strong>Best for:</strong> Products wanting Zoom's media infrastructure, desktop and mobile SDKs, raw media access, a prebuilt UI Toolkit, or large custom sessions.</p><p><strong>Why it ranks here:</strong> <a href="https://developers.zoom.us/docs/video-sdk/" rel="noreferrer nofollow">Zoom Video SDK documentation</a> lists iOS, Android, macOS, Windows, Web, React Native, Linux, Flutter, and Unity. It covers audio, video, screen sharing, chat, raw data, <a href="https://en.wikipedia.org/wiki/Public_switched_telephone_network" rel="noreferrer">PSTN</a>, transcription, recording, subsessions, and live streaming.</p><p>Current Video SDK documentation states that sessions are created on demand and can support up to 5,000 users, with an unlimited view-only audience available through RTMP streaming.</p><p><strong>Pricing:</strong> Zoom's Build Platform uses prepaid credits and meters Video SDK usage by participant session minutes. Recording, storage, transcription, translation, summaries, and PSTN consume additional credits or rates.</p><p><strong>Trade-off:</strong> Zoom Video SDK sessions cannot join ordinary Zoom meetings or webinars. Choose Meeting SDK when embedded access to standard Zoom meetings is the real requirement.</p><h3 id="9-sendbird-calls-best-for-chat-plus-calls">9. Sendbird Calls: Best for Chat Plus Calls</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-20-140841-1.png" class="kg-image" alt="Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026" loading="lazy" width="1512" height="727"/></figure><p><strong>Best for:</strong> Messaging-led products where persistent chat identity is central and direct or smaller group voice and video calls are secondary features.</p><p><strong>Why it ranks here:</strong> <a href="https://sendbird.com/docs/calls" rel="nofollow noreferrer">Sendbird Calls documentation</a> lists iOS, Android, JavaScript, React Native, and Unity SDKs. It supports direct calls, group rooms, auto-reconnect, call history, <a href="https://www.videosdk.live/developer-hub/websocket/webhook-vs-websocket#what-are-webhooks" rel="noreferrer">webhooks</a>, recording, screen share, and integrated Chat identities.</p><p>Capacity deserves a target-SDK check. Sendbird's pricing page advertises group voice calls up to 1,000 users and video calls up to 10 users, while some SDK-specific room types document lower limits.</p><p><strong>Pricing:</strong> <a href="https://sendbird.com/pricing/calls" rel="noreferrer nofollow">Sendbird Calls pricing</a> lists server-relayed voice at $0.0015 and video at $0.0035 per minute per user, with separate peer-to-peer and recording rates.</p><p><strong>Trade-off:</strong> Sendbird can replace Stream Chat and smaller Calls together, but its video room limits make it less suitable for large classes, events, or conferencing.</p><h3 id="10-mirrorfly-best-for-full-source-and-on-premises">10. MirrorFly: Best for Full Source and On-Premises</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-20-141140.png" class="kg-image" alt="Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026" loading="lazy" width="1503" height="690"/></figure><p><strong>Best for:</strong> Procurement-led organisations requiring full source access, white labelling, on-premises or private-cloud deployment, chat, calls, activity feeds, and data ownership.</p><p><strong>Why it ranks here:</strong> <a href="https://www.mirrorfly.com/video-call-solution.php" rel="noreferrer nofollow">MirrorFly's video product</a> lists one-to-one and group calls, live streaming, recording, screen sharing, <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">adaptive bitrate</a>, auto-reconnect, and web or mobile SDKs. Its wider suite also covers chat, activity feeds, SIP, and <a href="https://www.videosdk.live/developer-hub/sip/voip" rel="noreferrer">VoIP</a>.</p><p>MirrorFly offers managed cloud, private infrastructure, and on-premises paths. That scope can reduce the number of services required when a team needs to replace more than Stream Video.</p><p><strong>Pricing:</strong> <a href="https://www.mirrorfly.com/pricing.php" rel="noreferrer nofollow">MirrorFly pricing</a> uses MAU-led plans with included call minutes, overage rates, and custom enterprise terms. Full-source and on-premises deployments are sales-assisted.</p><p><strong>Trade-off:</strong> MirrorFly is less self-service than cloud-first SDKs. It fits ownership and customisation requirements better than a quick developer proof of concept.</p><h2 id="other-getstream-alternatives-worth-considering">Other GetStream Alternatives Worth Considering</h2><h3 id="zegocloud">ZEGOCLOUD</h3><p><a href="https://www.zegocloud.com/product/video-call" rel="noreferrer nofollow">ZEGOCLOUD</a> offers video calling, voice calling, live streaming, in-app chat, cloud recording, transcription, effects, and more than twenty prebuilt UI Kits. Its public pricing currently starts at $0.99 per 1,000 voice participant minutes and $3.99 per 1,000 video participant minutes after 10,000 free minutes.</p><p>ZEGOCLOUD is worth testing for social, live, and entertainment products that benefit from UI Kits and media effects. It did not enter the top ten because this ranking gives more weight to migration scope, self-hosting, and enterprise workflow differentiation.</p><h3 id="whereby-embedded">Whereby Embedded</h3><p><a href="https://whereby.com/information/embedded/pricing" rel="nofollow noreferrer">Whereby Embedded</a> provides programmatic rooms, a prebuilt web component or iframe, React hooks for custom interfaces, mobile paths, recordings, live streaming, transcription, and browser-focused collaboration features.</p><p>Its Build plan lists a $9.99 monthly fee, 2,000 included participant minutes, and $0.004 per additional participant minute. Whereby is a strong browser-first embedding option, but it covers less of Stream's wider chat and feed stack.</p><h2 id="what-is-the-best-getstream-alternative">What Is the Best GetStream Alternative?</h2><p><strong>VideoSDK is the best GetStream alternative under this article's combined RTC criteria, but deployment and ecosystem requirements can change the result.</strong></p><ul><li><strong>Choose VideoSDK</strong> for broad client coverage, custom or prebuilt video calls, audio rooms, and interactive live streaming from one managed RTC platform.</li><li><strong>Choose LiveKit</strong> when open-source infrastructure, self-hosting, SIP, and agent development matter more than bundled feeds or persistent chat.</li><li><strong>Choose Agora</strong> for specialised native platforms, Unity or Unreal Engine, vendor-reported global scale, and a large catalogue of media extensions.</li><li><strong>Choose Daily</strong> for browser-first embedding, straightforward base media rates, and projects connected to the Pipecat agent ecosystem.</li><li><strong>Choose 100ms</strong> for role-driven classrooms, social audio, and live experiences moving between real-time rooms and HLS audiences.</li><li><strong>Choose Twilio</strong> when Voice, Messaging, Conversations, or Flex already defines the communication architecture and vendor consolidation reduces operational cost.</li><li><strong>Choose Vonage</strong> for OpenTok continuity, broadcasting, captions, Audio Connector workflows, and enterprise media composition.</li><li><strong>Choose Zoom Video SDK</strong> for custom sessions on Zoom infrastructure, especially when desktop support, raw media access, or very large rooms matter.</li><li><strong>Choose Sendbird</strong> when persistent chat is primary and group video remains within the target SDK's documented limits.</li><li><strong>Choose MirrorFly</strong> when full source, on-premises deployment, white labelling, and data ownership justify a sales-assisted implementation.</li></ul><p>GetStream can still be the better option when Chat, Activity Feeds, Moderation, and Video already operate as one production application layer. Migration cost can exceed any headline media-rate saving.</p><h2 id="how-to-compare-getstream-alternative-costs">How to Compare GetStream Alternative Costs</h2><p><strong>A fair GetStream cost comparison includes every production service, not only the lowest participant-minute price.</strong> Resolution, recording, support, and compliance can reverse the result.</p><p>Use this normalised formula:</p><blockquote>Monthly RTC cost = call media + recording and composition + transcription + streaming or egress + telephony + support and compliance + migration operations.</blockquote><p>A provider charging $0.004 per participant minute bills a 30-minute call with eight connected users as 240 participant minutes, or $0.96 before recording and transcription.</p><p>Stream differs because received video tracks are grouped into an aggregated resolution tier. LiveKit adds data transfer and transcoding. MirrorFly uses MAU and negotiated plans. Zoom uses credits. These models need a workload sheet, not a single rate comparison.</p><p>Model at least three traffic shapes: one-to-one calls, an eight-person gallery room, and a host-to-viewer live session. Include muted users, screen sharing, recording, transcription, peak concurrency, and support requirements.</p><h2 id="how-to-test-a-getstream-alternative">How to Test a GetStream Alternative</h2><p><strong>A short proof of concept should test identity, media, network failure, and real billing before the team commits to a migration.</strong></p><ol><li><strong>Rebuild one representative room:</strong> Match the existing participant count, roles, permissions, camera layout, screen sharing, and recording behaviour.</li><li><strong>Generate scoped credentials:</strong> Keep provider secrets on the server. Issue short-lived room or participant tokens with only the permissions required by the client.</li><li><strong>Test production networks:</strong> Validate TURN fallback, TCP or TLS port 443, poor bandwidth, device permission denial, reconnect behaviour, and mobile background states.</li><li><strong>Measure the full bill:</strong> Capture participant minutes, resolution rules, recording, composition, transcription, data transfer, support, and compliance costs during the test.</li><li><strong>Score developer work:</strong> Record implementation time, documentation gaps, debugging quality, SDK parity, release cadence, and the operational effort required after launch.</li></ol><h2 id="getstream-migration-checklist">GetStream Migration Checklist</h2><p><strong>A safe GetStream migration separates product scope, identity, media, stored data, and rollout controls before any client SDK is replaced.</strong></p><ol><li><strong>Inventory Stream products:</strong> Record whether the application uses Video, Chat, Feeds, Moderation, push notifications, recording, transcription, or custom webhooks.</li><li><strong>Map media objects:</strong> Translate Stream calls, call types, roles, permissions, and members into the destination provider's rooms, sessions, templates, or roles.</li><li><strong>Rebuild authentication:</strong> Keep API secrets server-side and issue short-lived tokens with the smallest practical permissions.</li><li><strong>Create a provider adapter:</strong> Hide join, leave, publish, subscribe, device, and event methods behind an application interface before switching vendors.</li><li><strong>Plan stored-data migration:</strong> Decide whether chat history, feed activity, call records, recordings, and transcripts should move, remain archived, or expire.</li><li><strong>Re-test production networks:</strong> Validate TURN fallback, port 443, device permissions, reconnect behaviour, poor bandwidth, and mobile background states.</li><li><strong>Run a canary rollout:</strong> Route internal users and a small customer cohort to the new provider while preserving a tested fallback path.</li><li><strong>Compare real bills:</strong> Measure media, recording, egress, support, compliance, and engineering overhead during the overlap period.</li><li><strong>Retire Stream carefully:</strong> Revoke old credentials, remove unused webhooks, export required records, and watch for clients using older application versions.</li></ol><p>This staged pattern prevents a common failure: replacing the media SDK while silently breaking chat identity, push notifications, stored records, or compliance workflows.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-20--2026--04_15_32-PM.png" class="kg-image" alt="Top 10 Best GetStream Alternatives for Video & Voice APIs in 2026" loading="lazy" width="1725" height="912"/></figure><h2 id="definitions-glossary">Definitions Glossary</h2><p><strong>These RTC definitions make GetStream alternatives easier to compare because vendors often use different names for the same architectural role.</strong></p><p><strong>Participant minute:</strong> One connected participant using a session for one minute. Eight people in a 30-minute call create 240 participant minutes.</p><p><strong>Room or session:</strong> The real-time space where participants publish and receive audio, video, screen-share, and data tracks. Providers use different object names.</p><p><strong>SFU:</strong> A Selective Forwarding Unit receives media tracks and forwards selected versions to subscribers without composing every participant into one fixed video.</p><p><strong>Prebuilt UI Kit:</strong> A ready interface for device setup, joining, participant layouts, and call controls. VideoSDK provides a <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start" rel="noreferrer">prebuilt quickstart</a>.</p><p><strong>Interactive live streaming:</strong> A low-latency format where viewers can react or become speakers, unlike higher-latency one-way HLS delivery.</p><p><strong>Meeting token:</strong> A server-generated credential that authorises a participant to join a room without exposing the provider's API secret.</p><h2 id="key-takeaways">Key Takeaways</h2><p><strong>The best GetStream alternative is the provider whose media, client, deployment, and cost model match the application you operate.</strong></p><ul><li>VideoSDK ranks first under this article's combined criteria for SDK breadth, custom and prebuilt RTC, audio rooms, and interactive live streaming.</li><li>LiveKit is the clearest open-source and self-hosted choice, while MirrorFly targets full-source and on-premises ownership across a wider communication suite.</li><li>Agora, Daily, 100ms, Twilio, Vonage, Zoom, and Sendbird become stronger under specific platform, ecosystem, room, or workflow conditions.</li><li>ZEGOCLOUD and Whereby Embedded deserve a proof of concept when UI Kits, effects, or browser-first embedding carry more weight than migration scope.</li><li>GetStream may remain preferable when Chat, Feeds, Moderation, and Video already share identity, data, and operational tooling in production.</li><li>Pricing must include media, resolution rules, recording, transcription, egress, support, compliance, and migration engineering before a vendor is labelled cheaper.</li></ul><h2 id="conclusion">Conclusion</h2><p>The right GetStream alternatives shortlist should begin with architecture, not brand popularity. VideoSDK is a strong RTC-first starting point when platform coverage, prebuilt calling, custom media, and interactive streaming matter together.</p><p>Review the <a href="https://docs.videosdk.live/"><u>VideoSDK documentation</u></a> or create a <a href="https://app.videosdk.live/login"><u>free VideoSDK account</u></a> to test your real workload before committing. What are you building with VideoSDK? Share the video or voice use case you are evaluating.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><p><strong>These direct answers address the most common questions about GetStream alternatives, migration, pricing, self-hosting, and provider scope.</strong></p><h3 id="is-getstream-the-same-as-stream">Is GetStream the same as Stream?</h3><p>Yes, GetStream commonly refers to Stream, the company and platform at getstream.io. Searchers use both names for its chat, activity feeds, moderation, and video products.</p><h3 id="what-is-the-best-getstream-alternative-in-2026">What is the best GetStream alternative in 2026?</h3><p>The best GetStream alternative for broad managed video and voice development is VideoSDK under this article's RTC replacement fit test. LiveKit is stronger for self-hosting, while Agora fits specialised global and game-engine deployments.</p><h3 id="which-getstream-alternatives-support-self-hosting">Which GetStream alternatives support self-hosting?</h3><p>LiveKit supports an open-source, self-hosted WebRTC server with separate ingress, egress, and SIP services. MirrorFly sells full-source and on-premises options for organisations wanting chat, calls, and wider deployment control.</p><h3 id="which-alternative-is-closest-to-stream-chat-and-video-together">Which alternative is closest to stream chat and video together?</h3><p>Sendbird closely combines persistent chat identity with direct and group calls, although video capacity varies by target SDK and room type. MirrorFly also bundles chat, calls, feeds, SIP, and deployment control.</p><h3 id="are-getstream-alternatives-cheaper">Are GetStream alternatives cheaper?</h3><p>Some GetStream alternatives can cost less for a specific traffic pattern, but headline rates are insufficient. Compare media, resolution, recording, transcription, egress, support, compliance, and migration costs.</p><h3 id="does-twilio-video-still-exist-in-2026">Does Twilio Video still exist in 2026?</h3><p>Yes, Twilio Video remains available in 2026. Twilio reversed its earlier retirement plan, maintains current documentation, and continues to offer pay-as-you-go pricing.</p><h3 id="can-i-migrate-from-getstream-without-downtime">Can I migrate from GetStream without downtime?</h3><p>Yes, a low-downtime migration uses a provider adapter, parallel authentication, canary traffic, feature flags, and an operational fallback. Stored chat, feed, recording, and compliance data need separate migration plans.</p><h3 id="does-videosdk-replace-streamchat-and-activity-feeds">Does VideoSDK replace StreamChat and activity feeds?</h3><p>VideoSDK primarily replaces the real-time video, audio, room, and interactive streaming layer. Persistent chat and activity feeds may require another service or an application-owned data model.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 ZEGOCLOUD Alternatives in 2026: Expert Tested & Ranked]]></title><description><![CDATA[A developer-focused, pricing-verified comparison of the top 10 ZEGOCLOUD alternatives for real-time video, voice, and interactive live streaming SDKs.]]></description><link>https://www.videosdk.live/blog/zegocloud-alternatives</link><guid isPermaLink="false">6a54bf3eb3240feb748c5611</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 14 Jul 2026 08:53:17 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-14--2026--02_20_50-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>The strongest ZEGOCLOUD alternatives in 2026 are VideoSDK, Agora, and LiveKit. Choose VideoSDK for broad managed RTC coverage and transparent usage pricing, Agora for a mature global engagement stack, and LiveKit for open-source deployment control. Your final choice should follow platform support, streaming architecture, compliance, cost, and operational ownership.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/ChatGPT-Image-Jul-14--2026--02_20_50-PM.png" alt="Top 10 ZEGOCLOUD Alternatives in 2026: Expert Tested & Ranked"/><p>A $0.001 difference per participant-minute becomes $1,000 at one million minutes, but price alone should not drive an RTC migration.</p><p>This review ranks ten ZEGOCLOUD alternatives for developers building embedded video, voice, and interactive live streaming. VideoSDK ranks first for the managed, multi-platform replacement scenario evaluated here. Agora is stronger for some large-scale specialized deployments, while LiveKit and Jitsi offer more infrastructure control.</p><p>"Expert tested" means we inspected current official documentation, public pricing, SDK coverage, quickstarts, code samples, and migration fit on July 14, 2026. We did not run identical network or load benchmarks, so this article does not invent latency, call-success, or uptime results.</p><h2 id="what-is-zegocloud">What Is ZEGOCLOUD?</h2><p><a href="https://www.zegocloud.com/" rel="nofollow noreferrer">ZEGOCLOUD</a> is defined as a managed real-time engagement platform for embedding video calls, voice calls, live streaming, in-app chat, recording, whiteboards, and visual effects into applications. ZEGOCLOUD works by routing media through its cloud infrastructure while client SDKs and UIKits manage rooms, participants, tracks, and user interaction.</p><p>Its current&nbsp;<a href="https://www.zegocloud.com/docs/uikit/video-conference-kit-android/overview" rel="noreferrer nofollow">Video Conference Kit</a>&nbsp;supports Android, iOS, Flutter, React Native, and web. The lower-level live-streaming SDK also covers native desktop, Linux, Electron, Unity, and C++ environments. This breadth makes ZEGOCLOUD a credible option, particularly for social, entertainment, education, and interactive-streaming products.</p><p>As of July 14, 2026, ZEGOCLOUD's&nbsp;<a href="https://www.zegocloud.com/pricing" rel="noreferrer nofollow">public pricing page</a>&nbsp;lists voice at $0.99 per 1,000 participant-minutes, HD video at $3.99 per 1,000 participant-minutes, and live streaming at $0.39 per 1,000 minutes. It also advertises 10,000 free minutes.</p><p>Teams should therefore evaluate alternatives because their requirements changed, not because ZEGOCLOUD is inherently unsuitable. A different provider may offer a better billing model, self-hosting, embedded-device support, a faster prebuilt path, tighter chat integration, or a product roadmap that better matches the application.</p><h2 id="how-we-ranked-zegocloud-alternatives">How We Ranked ZEGOCLOUD Alternatives</h2><p>This <a href="https://www.videosdk.live/alternative/zegocloud-vs-videosdk" rel="noreferrer">ZEGOCLOUD alternatives</a> ranking measures replacement fit for a team that wants programmable video, audio, and interactive streaming without building an <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu" rel="noreferrer">SFU</a>, signalling layer, <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN</a> network, recording pipeline, and cross-platform SDKs from scratch.</p><p>Disclosure matters: this article is published for VideoSDK. To limit publisher bias, each score uses the same public criteria, links to official evidence, names a real trade-off, and identifies scenarios where another provider is the better choice. You should still run a proof of concept with your own devices, regions, codecs, and traffic.</p><table>
<thead>
<tr>
<th>Criterion</th>
<th style="text-align:right">Weight</th>
<th>What was checked</th>
</tr>
</thead>
<tbody>
<tr>
<td>ZEGOCLOUD replacement fit</td>
<td style="text-align:right">25%</td>
<td>Video, audio, rooms, roles, live streaming, recording, and prebuilt UI</td>
</tr>
<tr>
<td>Developer experience</td>
<td style="text-align:right">20%</td>
<td>Quickstart clarity, authentication, sample code, SDK ergonomics, and debugging resources</td>
</tr>
<tr>
<td>Platform coverage</td>
<td style="text-align:right">15%</td>
<td>Web, mobile, native desktop, cross-platform, game engines, and embedded devices</td>
</tr>
<tr>
<td>Product flexibility</td>
<td style="text-align:right">15%</td>
<td>Custom UI, media controls, streaming, observability, telephony, chat, and AI extensions</td>
</tr>
<tr>
<td>Pricing and commercial fit</td>
<td style="text-align:right">15%</td>
<td>Public rates, free allowance, billing clarity, add-ons, and support model</td>
</tr>
<tr>
<td>Deployment control</td>
<td style="text-align:right">10%</td>
<td>Managed cloud, self-hosting, data-path control, and operational burden</td>
</tr>
</tbody>
</table>
<p>Scores are editorial evidence scores, not media-quality benchmarks. No provider receives points for an unverified superlative or vendor-reported latency number.</p><p>The grouped score breakdown below makes the final rank auditable. Developer experience and platform coverage are combined into 35 points; product flexibility and commercial fit are combined into 30.</p><table>
<thead>
<tr>
<th>Provider</th>
<th style="text-align:right">Replacement fit /25</th>
<th style="text-align:right">DX and platforms /35</th>
<th style="text-align:right">Product and commercial /30</th>
<th style="text-align:right">Deployment /10</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td style="text-align:right">24</td>
<td style="text-align:right">33</td>
<td style="text-align:right">28</td>
<td style="text-align:right">7</td>
</tr>
<tr>
<td>Agora</td>
<td style="text-align:right">24</td>
<td style="text-align:right">31</td>
<td style="text-align:right">27</td>
<td style="text-align:right">7</td>
</tr>
<tr>
<td>LiveKit</td>
<td style="text-align:right">21</td>
<td style="text-align:right">30</td>
<td style="text-align:right">27</td>
<td style="text-align:right">10</td>
</tr>
<tr>
<td>Daily</td>
<td style="text-align:right">22</td>
<td style="text-align:right">30</td>
<td style="text-align:right">28</td>
<td style="text-align:right">6</td>
</tr>
<tr>
<td>100ms</td>
<td style="text-align:right">22</td>
<td style="text-align:right">29</td>
<td style="text-align:right">27</td>
<td style="text-align:right">7</td>
</tr>
<tr>
<td>Stream</td>
<td style="text-align:right">21</td>
<td style="text-align:right">30</td>
<td style="text-align:right">27</td>
<td style="text-align:right">6</td>
</tr>
<tr>
<td>Amazon Chime SDK</td>
<td style="text-align:right">20</td>
<td style="text-align:right">28</td>
<td style="text-align:right">26</td>
<td style="text-align:right">8</td>
</tr>
<tr>
<td>Vonage Video API</td>
<td style="text-align:right">21</td>
<td style="text-align:right">26</td>
<td style="text-align:right">26</td>
<td style="text-align:right">7</td>
</tr>
<tr>
<td>Zoom Video SDK</td>
<td style="text-align:right">20</td>
<td style="text-align:right">28</td>
<td style="text-align:right">25</td>
<td style="text-align:right">6</td>
</tr>
<tr>
<td>Jitsi</td>
<td style="text-align:right">16</td>
<td style="text-align:right">24</td>
<td style="text-align:right">26</td>
<td style="text-align:right">10</td>
</tr>
</tbody>
</table>
<h2 id="top-10-zegocloud-alternatives-at-a-glance">Top 10 ZEGOCLOUD Alternatives at a Glance</h2><p>VideoSDK leads this shortlist because it combines managed RTC, a prebuilt option, interactive live streaming, broad client coverage, and public participant-minute pricing. The table also shows why it is not the automatic answer for every workload.</p><table>
<thead>
<tr>
<th style="text-align:right">Rank</th>
<th>Alternative</th>
<th style="text-align:right">Score</th>
<th>Best for</th>
<th>Main trade-off</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:right">1</td>
<td>VideoSDK</td>
<td style="text-align:right">92/100</td>
<td>Managed RTC across web, mobile, Unity, C++, and IoT</td>
<td>No open-source media server for self-hosting</td>
</tr>
<tr>
<td style="text-align:right">2</td>
<td>Agora</td>
<td style="text-align:right">89/100</td>
<td>Mature global RTC and specialized engagement features</td>
<td>Resolution tiers and add-ons increase cost-model complexity</td>
</tr>
<tr>
<td style="text-align:right">3</td>
<td>LiveKit</td>
<td style="text-align:right">88/100</td>
<td>Open-source control, managed cloud, and voice AI</td>
<td>Self-hosting transfers reliability and networking work to your team</td>
</tr>
<tr>
<td style="text-align:right">4</td>
<td>Daily</td>
<td style="text-align:right">86/100</td>
<td>Fast browser-first and prebuilt video deployment</td>
<td>Prebuilt is web-focused and not supported inside its React Native SDK</td>
</tr>
<tr>
<td style="text-align:right">5</td>
<td>100ms</td>
<td style="text-align:right">85/100</td>
<td>Role-driven classrooms, webinars, and live events</td>
<td>Narrower desktop and embedded coverage than the leaders</td>
</tr>
<tr>
<td style="text-align:right">6</td>
<td>Stream</td>
<td style="text-align:right">84/100</td>
<td>Products combining video, chat, feeds, and moderation</td>
<td>A broader engagement stack can be unnecessary for RTC-only apps</td>
</tr>
<tr>
<td style="text-align:right">7</td>
<td>Amazon Chime SDK</td>
<td style="text-align:right">82/100</td>
<td>AWS-native RTC, recording, analytics, and telephony</td>
<td>Requires more AWS integration work and has narrower client SDK coverage</td>
</tr>
<tr>
<td style="text-align:right">8</td>
<td>Vonage Video API</td>
<td style="text-align:right">80/100</td>
<td>Enterprises already using Vonage communications APIs</td>
<td>Less attractive for teams seeking an open stack or modern prebuilt-first workflow</td>
</tr>
<tr>
<td style="text-align:right">9</td>
<td>Zoom Video SDK</td>
<td style="text-align:right">79/100</td>
<td>Zoom's media stack with native desktop support</td>
<td>Video SDK sessions cannot join regular Zoom Meetings</td>
</tr>
<tr>
<td style="text-align:right">10</td>
<td>Jitsi</td>
<td style="text-align:right">76/100</td>
<td>Open-source self-hosting and infrastructure ownership</td>
<td>Your team owns scaling, upgrades, monitoring, and incident response</td>
</tr>
</tbody>
</table>
<p>The top three illustrate the core decision. VideoSDK optimises for a managed balance, Agora prioritises the depth of a long-running commercial RTC stack, and LiveKit gives engineering teams the most infrastructure choice.</p><h2 id="top-10-zegocloud-alternatives-ranked">Top 10 ZEGOCLOUD Alternatives Ranked</h2><p>Each alternative below includes its strongest use case, current pricing evidence, and a limitation that should influence a production shortlist.</p><h3 id="1-videosdk-best-overall">1. VideoSDK: Best Overall</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-130930.png" class="kg-image" alt="Top 10 ZEGOCLOUD Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="1523" height="727"/></figure><p><a href="https://www.videosdk.live/">VideoSDK</a>&nbsp;is the best overall ZEGOCLOUD alternative for teams that want a managed <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">real-time video and audio</a> stack across conventional apps and less common targets. Its current documentation lists Prebuilt, JavaScript, React, React Native, Android, iOS, Flutter, Unity, Python, C++, and IoT paths.</p><p>The product covers custom video and audio rooms, recording, transcription, RTMP output, <a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer">HLS</a>, and&nbsp;<a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">interactive live streaming</a>. Its ILS documentation lists host, co-host, and audience modes with chat, polls, virtual gifts, and hand raising. The same room model can also connect SIP endpoints and <a href="https://www.videosdk.live/voice-agents" rel="noreferrer">AI voice agents</a> when the application expands beyond human-to-human calls.</p><p>VideoSDK's&nbsp;<a href="https://docs.videosdk.live/help_docs/pricing" rel="noreferrer">conferencing pricing docs</a>&nbsp;list $20 free credit, audio at $0.001 per participant-minute, HD video at $0.004, and Full HD or higher aggregate tiers at $0.009. Public rates should be rechecked at publication.</p><p><strong>Best for:</strong>&nbsp;teams replacing ZEGOCLOUD in telehealth, edtech, social, customer support, interactive events, or embedded-device applications.</p><p><strong>Trade-off:</strong>&nbsp;VideoSDK is a managed service. The free plan does not cover compliance; for compliance, you have to upgrad to the Pay-as-you-go or Enterprise Plan. </p><h3 id="2-agora-best-for-global-rtc">2. Agora: Best for Global RTC</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131023.png" class="kg-image" alt="Top 10 ZEGOCLOUD Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="1525" height="715"/></figure><p><a href="https://www.agora.io/en/" rel="noreferrer nofollow">Agora</a>&nbsp;is the strongest ZEGOCLOUD alternative for teams that prioritize a mature commercial RTC portfolio. Its platform covers video and voice calling, interactive and broadcast streaming, signaling, recording, analytics, transcription, translation, noise suppression, spatial audio, and media gateways.</p><p>Agora also supports a wide range of web, mobile, desktop, game-engine, and IoT environments. That breadth makes it a serious candidate for gaming, social audio, live commerce, and large international products with specialized media requirements.</p><p>As of July 2026, Agora's&nbsp;<a href="https://www.agora.io/en/pricing/" rel="noreferrer nofollow">official pricing</a>&nbsp;starts at $3.99 per 1,000 HD video minutes and $0.99 per 1,000 voice minutes, with the first 10,000 minutes free each month. Higher aggregate resolutions and add-on services use separate rates.</p><p><strong>Best for:</strong>&nbsp;teams that need a deep catalog of RTC extensions, broad platform support, and an established global commercial provider.</p><p><strong>Trade-off:</strong>&nbsp;the product catalog gives teams many options, but it also creates more SKUs and configuration decisions. VideoSDK is easier to model when the application mainly needs managed conferencing, <a href="https://www.videosdk.live/developer-hub/ils/interactive-live-streaming-guide" rel="noreferrer">ILS</a>, and broad SDK coverage at a lower listed HD rate.</p><h3 id="3-livekit-best-open-source-stack">3. LiveKit: Best Open-Source Stack</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131109.png" class="kg-image" alt="Top 10 ZEGOCLOUD Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="1532" height="697"/></figure><p><a href="https://livekit.com/" rel="noreferrer nofollow">LiveKit</a>&nbsp;is the best ZEGOCLOUD alternative when open-source infrastructure control is a first-class requirement. Its Apache-2.0&nbsp;<a href="https://github.com/livekit/livekit">server repository</a>&nbsp;provides an SFU-based real-time media foundation, while LiveKit Cloud offers a managed deployment.</p><p>LiveKit is also strong for voice and multimodal agents. Its current cloud documentation combines real-time audio, video, data, agent hosting, inference, telephony, and observability. Developers can keep the managed service, self-host the media stack, or use a mixed architecture.</p><p>The&nbsp;<a href="https://livekit.com/pricing" rel="noreferrer nofollow">LiveKit Cloud pricing page</a>&nbsp;lists a free Build plan with 5,000 WebRTC minutes and 50 GB of downstream transfer. The Ship plan includes 150,000 WebRTC minutes, then charges $0.0005 per minute, with data transfer and media processing metered separately.</p><p><strong>Best for:</strong>&nbsp;engineering teams that want source-level visibility, deployment choice, or a shared foundation for human calls and AI agents.</p><p><strong>Trade-off:</strong>&nbsp;self-hosting is not free operations. LiveKit's own deployment guide requires a trusted TLS certificate, domain, and load balancer or reverse proxy. Your team must also own scaling, TURN reachability, monitoring, upgrades, and incident response.</p><h3 id="4-daily-best-prebuilt-web-path">4. Daily: Best Prebuilt Web Path</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131144.png" class="kg-image" alt="Top 10 ZEGOCLOUD Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="1508" height="717"/></figure><p><a href="https://www.daily.co/" rel="noreferrer nofollow">Daily</a>&nbsp;is a strong ZEGOCLOUD alternative for browser-first products that need a working call interface quickly. Daily Prebuilt embeds a complete video call component, while daily-js and Daily React support custom layouts and call logic.</p><p>Daily also documents React Native, Android, iOS, Flutter, and Python SDKs. Its REST API covers room creation, access control, recording, and other server-side operations. The product is particularly well suited to telehealth, interviews, remote consultations, and SaaS features where the browser is the primary client.</p><p>Daily's&nbsp;<a href="https://www.daily.co/pricing/video-sdk/" rel="noreferrer nofollow">Video SDK pricing</a>&nbsp;starts with 10,000 free minutes per month. Public video pricing ranges from $0.004 down to $0.0015 per participant-minute as automatic volume discounts apply. Audio-only sessions use a lower rate.</p><p><strong>Best for:</strong>&nbsp;teams that value a fast web integration, a polished prebuilt call, and simple REST-driven room creation.</p><p><strong>Trade-off:</strong>&nbsp;Daily's React Native documentation states that Daily Prebuilt is not supported inside react-native-daily-js. VideoSDK is a better fit when one prebuilt/custom strategy must span more mobile, game-engine, C++, or embedded targets.</p><h3 id="5-100ms-best-role-based-rooms">5. 100ms: Best Role-Based Rooms</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131222.png" class="kg-image" alt="Top 10 ZEGOCLOUD Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="1503" height="667"/></figure><p><a href="https://www.100ms.live/" rel="noreferrer nofollow">100ms</a>&nbsp;is a strong alternative to ZEGOCLOUD for applications built around explicit roles and permissions. Its templates model hosts, guests, viewers, waiting-room participants, and broadcasters, which maps well to classrooms, webinars, telehealth queues, and staged events.</p><p>The platform offers custom SDKs and Prebuilt across web, Android, iOS, React Native, and Flutter. Its documentation also covers <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">adaptive bitrate</a>, live transcription, recording, HLS, RTMP output, whiteboards, and role-specific chat.</p><p>The current&nbsp;<a href="https://www.100ms.live/pricing" rel="noreferrer nofollow">100ms pricing page</a>&nbsp;includes 10,000 conferencing minutes and 10,000 streaming minutes per month. Conferencing costs $0.004 per participant-minute after the allowance, with a stated 75% discount for audio-only use cases.</p><p><strong>Best for:</strong>&nbsp;edtech, webinars, audio rooms, telehealth waiting rooms, and applications where role changes drive the user experience.</p><p><strong>Trade-off:</strong>&nbsp;100ms does not match VideoSDK, Agora, or Stream for Unity, C++, IoT, and broader desktop coverage. It can still be the better choice when templates and roles matter more than unusual client platforms.</p><h3 id="6-getstream-best-unified-engagement-stack">6. GetStream: Best Unified Engagement Stack</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131305.png" class="kg-image" alt="Top 10 ZEGOCLOUD Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="1521" height="665"/></figure><p><a href="https://getstream.io/video/" rel="noreferrer nofollow">GetStream</a>&nbsp;combines video and audio with mature chat, activity feeds, and moderation products. That makes it a practical ZEGOCLOUD alternative for social networks, marketplaces, communities, gaming, live commerce, and applications that would otherwise integrate several vendors.</p><p>Its Video SDK documentation covers React, JavaScript, React Native, Android, iOS, Flutter, Unity, and ESP32. It includes composable UI components, call types, recording, broadcasting, HLS, <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a>, SIP, quality statistics, and low-bandwidth controls.</p><p>GetStream's&nbsp;<a href="https://getstream.io/video/docs/api/pricing-guide/#video-calling-pricing" rel="noreferrer nofollow">pricing guide</a>&nbsp;lists audio at $0.30 per 1,000 participant-minutes, HD video at $1.50, Full HD at $3.00, and $100 in monthly Audio/Video API usage credit. Charges use each participant's aggregate received resolution.</p><p><strong>Best for:</strong>&nbsp;products that need video, voice, chat, feeds, and moderation on one vendor stack.</p><p><strong>Trade-off:</strong>&nbsp;an RTC-only application may not benefit from the broader engagement platform. VideoSDK offers a more RTC-centered product surface, while GetStream is stronger when chat and social primitives are central to the roadmap.</p><h3 id="7-amazon-chime-sdk-best-for-aws-native-applications">7. Amazon Chime SDK: Best for AWS-Native Applications</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131356.png" class="kg-image" alt="Top 10 ZEGOCLOUD Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="1523" height="723"/></figure><p><a href="https://aws.amazon.com/chime/chime-sdk/" rel="noreferrer nofollow">Amazon Chime SDK</a> is a strong ZEGOCLOUD alternative for development teams already operating on AWS. It provides programmable components for adding real-time video, audio, screen sharing, messaging, recording, <a href="https://www.videosdk.live/developer-hub/social/live-audio-transcription" rel="noreferrer">live transcription</a>, and telephony to web and mobile applications.</p><p>Its <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> media service uses an SFU architecture and supports JavaScript, iOS, Android, and Windows client libraries. A standard meeting can contain up to 25 simultaneously published video streams. Media replication can connect multiple sessions to support interactive events with audiences of up to 10,000 people. Developers can also capture meeting media to Amazon S3 or stream audio into Amazon Kinesis Video Streams for real-time analysis.</p><p>Amazon Chime SDK uses pay-as-you-go pricing without an upfront commitment. Its <a href="https://aws.amazon.com/chime/chime-sdk/pricing/" rel="noreferrer nofollow">official pricing page</a> lists standard WebRTC sessions at $0.0017 per attendee-minute, covering audio, video, and screen sharing under one rate. Recording, compositing, transcription, <a href="https://learn.microsoft.com/en-us/microsoftteams/pstn-connectivity" rel="noreferrer">PSTN connectivity</a>, media replication, and live streaming introduce separate usage charges.</p><p><strong>Best for:</strong> AWS-based products that require programmable meetings, regional media placement, S3 recording, analytics integrations, or telephony capabilities.</p><p><strong>Trade-off:</strong> Amazon Chime SDK requires more backend and AWS infrastructure knowledge than providers offering an all-in-one prebuilt experience. Its client SDK coverage is also narrower than <a href="https://www.videosdk.live/alternative/agora-vs-videosdk" rel="noreferrer">VideoSDK or Agora</a>, particularly for Flutter, React Native, Unity, C++, and embedded-device applications. Teams should also model the additional charges for media capture, storage, transcription, replication, and streaming before comparing total costs.</p><h3 id="8-vonage-video-api-best-enterprise-cpaas">8. Vonage Video API: Best Enterprise CPaaS</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131437.png" class="kg-image" alt="Top 10 ZEGOCLOUD Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="1515" height="722"/></figure><p><a href="https://www.vonage.com/communications-apis/video/" rel="noreferrer nofollow">Vonage Video API</a>&nbsp;is a suitable ZEGOCLOUD alternative for enterprises already using Vonage voice, messaging, verification, or contact-center services. The former TokBox/OpenTok product provides programmable sessions, publishing and subscribing, recording, broadcasting, SIP, and enterprise support.</p><p>Vonage remains an active API product in 2026. Its communications portfolio is a differentiator when video is one channel in a broader customer-communication system rather than a standalone feature.</p><p>Vonage's&nbsp;<a href="https://www.vonage.com/communications-apis/pricing/" rel="noreferrer nofollow">communications API pricing page</a>&nbsp;lists Video API rates as low as $0.0041 per minute. Final cost depends on geography, volume, recording, broadcasting, SIP, and commercial terms.</p><p><strong>Best for:</strong>&nbsp;regulated or enterprise teams that want video inside an existing Vonage communications relationship.</p><p><strong>Trade-off:</strong>&nbsp;teams prioritizing an open media server may prefer LiveKit, while those seeking a modern prebuilt-first workflow may prefer Daily or VideoSDK. Amazon Chime SDK is a stronger fit for AWS-native applications. Vonage becomes more compelling when enterprise procurement and communications-channel consolidation matter.</p><h3 id="9-zoom-video-sdk-best-zoom-infrastructure">9. Zoom Video SDK: Best Zoom Infrastructure</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131606.png" class="kg-image" alt="Top 10 ZEGOCLOUD Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="1526" height="681"/></figure><p><a href="https://developers.zoom.us/docs/video-sdk/" rel="noreferrer nofollow">Zoom Video SDK</a>&nbsp;exposes Zoom's core audio and video technology for custom applications. It includes video, audio, screen sharing, chat, data streams, server-side APIs, webhooks, cloud recording, transcription, translation, PSTN, and live streaming.</p><p>Platform coverage is a major strength. Zoom documents web, Android, iOS, Linux, macOS, Windows, Flutter, and React Native support, plus low-code UI toolkits.</p><p>Zoom's&nbsp;<a href="https://zoom.us/pricing/developer" rel="noreferrer nofollow">developer pricing page</a>&nbsp;now uses prepaid Build Platform credits and bills Video SDK usage by minutes. Its product page advertises 20 credits per month at no charge, but the exact effective per-minute rate depends on the current credit schedule and selected services.</p><p><strong>Best for:</strong>&nbsp;teams that trust Zoom's media stack, need native desktop coverage, or want Zoom's transcription, translation, and PSTN extensions.</p><p><strong>Trade-off:</strong>&nbsp;the Video SDK is not Zoom Meetings. Zoom's own FAQ states that a Video SDK session cannot connect through the standard Zoom clients or join a Zoom Meeting. Use the Meeting SDK when that interoperability is the actual requirement.</p><h3 id="10-jitsi-best-self-hosted-meetings">10. Jitsi: Best Self-Hosted Meetings</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/07/Screenshot-2026-07-14-131704.png" class="kg-image" alt="Top 10 ZEGOCLOUD Alternatives in 2026: Expert Tested & Ranked" loading="lazy" width="1505" height="727"/></figure><p><a href="https://jitsi.org/jitsi-meet/" rel="noreferrer nofollow">Jitsi Meet</a>&nbsp;is the best ZEGOCLOUD alternative for teams that want a mature open-source meeting application and accept infrastructure ownership. The stack includes a React and React Native client, XMPP signaling components, Jicofo, Jitsi Videobridge, recording and streaming components, and iframe/mobile integration options.</p><p>The software is free and open source. A self-hosted deployment still creates cloud compute, bandwidth, TURN, recording, monitoring, security, upgrade, and staffing costs. Jitsi's&nbsp;<a href="https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-quickstart/" rel="noreferrer nofollow">self-hosting guide</a>&nbsp;supports current Debian and Ubuntu releases and expects administrator access.</p><p><strong>Best for:</strong>&nbsp;privacy-sensitive teams, internal platforms, public-sector deployments, and organizations with WebRTC operations expertise.</p><p><strong>Trade-off:</strong>&nbsp;Jitsi provides control rather than a turnkey SLA. VideoSDK, Agora, Daily, 100ms, and Vonage remove much of that operational burden. LiveKit is often the closer open-source choice for teams that want a lower-level programmable media platform rather than a meeting application.</p><h2 id="zegocloud-alternatives-pricing-compared">ZEGOCLOUD Alternatives Pricing Compared</h2><p>Public list prices help narrow ZEGOCLOUD alternatives, but they are not directly interchangeable. Vendors meter by participant time, received resolution, bandwidth, plan allowance, preset type, recording output, or a combination of these units.</p><p>Prices below were checked on July 14, 2026. They exclude negotiated discounts, taxes, support, compliance add-ons, recording, transcription, storage, egress, and streaming unless stated.</p><table>
<thead>
<tr>
<th>Provider</th>
<th style="text-align:right">Public entry point for video</th>
<th>Free starting allowance</th>
<th>Billing caveat</th>
</tr>
</thead>
<tbody>
<tr>
<td>ZEGOCLOUD</td>
<td style="text-align:right">$3.99 per 1,000 HD participant-minutes</td>
<td>10,000 minutes/month</td>
<td>Resolution and product-specific add-ons</td>
</tr>
<tr>
<td>VideoSDK</td>
<td style="text-align:right">$3.00 per 1,000 HD participant-minutes</td>
<td>$20 Free</td>
<td>Aggregate received resolution</td>
</tr>
<tr>
<td>Agora</td>
<td style="text-align:right">$3.99 per 1,000 HD minutes</td>
<td>10,000 minutes/month</td>
<td>Resolution tiers and separate extensions</td>
</tr>
<tr>
<td>LiveKit Cloud</td>
<td style="text-align:right">Plan-based; Ship overage $0.50 per 1,000 WebRTC minutes</td>
<td>5,000 WebRTC minutes on Build</td>
<td>Downstream data and processing also apply</td>
</tr>
<tr>
<td>Daily</td>
<td style="text-align:right">Up to $4.00 per 1,000 video participant-minutes</td>
<td>10,000 minutes/month</td>
<td>Automatic volume rate can fall to $1.50</td>
</tr>
<tr>
<td>100ms</td>
<td style="text-align:right">$4.00 per 1,000 conferencing participant-minutes</td>
<td>10,000 minutes/month</td>
<td>Separate streaming and encoding meters</td>
</tr>
<tr>
<td>Stream</td>
<td style="text-align:right">$1.50 per 1,000 HD participant-minutes</td>
<td>$100 monthly usage credit</td>
<td>Aggregate received resolution</td>
</tr>
<tr>
<td>Amazon Chime SDK</td>
<td style="text-align:right">$1.70 per 1,000 attendee-minutes</td>
<td>No free allowance listed</td>
<td>Recording, transcription, media replication, storage, and live streaming cost extra</td>
</tr>
<tr>
<td>Vonage Video API</td>
<td style="text-align:right">As low as $4.10 per 1,000 minutes</td>
<td>Trial credit may vary</td>
<td>Volume, region, and add-ons affect cost</td>
</tr>
<tr>
<td>Zoom Video SDK</td>
<td style="text-align:right">Credit and minute based</td>
<td>20 Build Platform credits/month</td>
<td>Convert credits using the current service schedule</td>
</tr>
<tr>
<td>Jitsi</td>
<td style="text-align:right">Open-source software</td>
<td>Not applicable</td>
<td>Infrastructure, bandwidth, and operations are yours</td>
</tr>
</tbody>
</table>
<p>For a simple list-price example, one million HD participant-minutes cost $3,000 on VideoSDK and $3,990 on ZEGOCLOUD, a $990 difference before add-ons or discounts. That calculation is useful for screening, not procurement. A realistic model must replay your participant mix, received tile resolutions, audio-only time, recordings, live-stream viewers, and regional requirements against each provider's calculator.</p><h2 id="which-zegocloud-alternative-should-you-choose">Which ZEGOCLOUD Alternative Should You Choose?</h2><p>The right ZEGOCLOUD alternative follows the constraint your product cannot compromise on.</p><ul><li><strong>Choose VideoSDK</strong>&nbsp;when you want managed video, audio, prebuilt UI, interactive live streaming, and unusually broad client coverage under one RTC-focused product.</li><li><strong>Choose Agora</strong>&nbsp;when global commercial RTC depth, gaming, spatial audio, or a large extension catalog matters more than pricing simplicity.</li><li><strong>Choose LiveKit</strong>&nbsp;when open-source deployment control or a shared human-call and voice-agent foundation is mandatory.</li><li><strong>Choose Daily</strong>&nbsp;when the browser and a fast prebuilt experience are your primary delivery path.</li><li><strong>Choose 100ms</strong>&nbsp;when roles, templates, waiting rooms, classrooms, and webinars define the product.</li><li><strong>Choose Stream</strong>&nbsp;when video must share identity, moderation, chat, and activity feeds.</li><li><strong>Choose Amazon Chime SDK</strong> when your application already runs on AWS and requires regional media placement, S3-based media capture, Kinesis integrations, or programmable telephony.</li><li><strong>Choose Vonage</strong>&nbsp;when video is one part of an enterprise CPaaS strategy.</li><li><strong>Choose Zoom Video SDK</strong>&nbsp;when Zoom's media infrastructure and desktop support matter, but standard Zoom Meeting interoperability does not.</li><li><strong>Choose Jitsi</strong>&nbsp;when self-hosting, source access, and data-path control justify the operational work.</li></ul><p>Staying with ZEGOCLOUD is also a valid decision. Keep it when the current integration meets your call-quality targets, AI effects and social features matter, required platforms are covered, and the migration cost exceeds the measurable benefit.</p><h2 id="definitions-glossary">Definitions Glossary</h2><blockquote><strong>Participant-minute:</strong>&nbsp;One participant connected for one minute. VideoSDK, ZEGOCLOUD, Daily, and several other managed providers use this unit, sometimes with resolution tiers.</blockquote><blockquote><strong>SFU:</strong>&nbsp;A Selective Forwarding Unit receives media streams and forwards selected layers to participants. Managed VideoSDK rooms, LiveKit, Amazon Chime SDK meetings, and Jitsi Videobridge use SFU-style media routing.</blockquote><blockquote><strong>Prebuilt UI Kit:</strong>&nbsp;A drop-in meeting interface that handles the common call lifecycle and controls. VideoSDK Prebuilt targets fast deployment, while the programmable SDK supports a custom interface.</blockquote><blockquote><strong>Interactive Live Streaming:</strong>&nbsp;A low-latency broadcast model where audience members can interact or become speakers. VideoSDK ILS uses host and audience modes inside its RTC architecture.</blockquote><blockquote><strong>Provider adapter:</strong>&nbsp;An application-owned interface that isolates room, participant, and track logic from one vendor SDK. It reduces migration risk and keeps rollback possible.</blockquote><h2 id="related-videosdk-guides">Related VideoSDK Guides</h2><ul><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React video and audio quickstart</a></li><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token">Authentication and token guide</a></li><li><a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">Prebuilt video and audio quickstart</a></li><li><a href="https://docs.videosdk.live/flutter/guide/interactive-live-streaming/introduction" rel="noreferrer">Interactive live streaming overview</a></li><li><a href="https://docs.videosdk.live/code-sample">VideoSDK code samples</a></li></ul><h2 id="key-takeaways">Key Takeaways</h2><ul><li>VideoSDK is the best overall ZEGOCLOUD alternative for the managed, cross-platform RTC scenario scored in this review.</li><li>Agora is the stronger conditional choice for teams that prioritize a mature extension catalog and specialized global engagement features.</li><li>LiveKit and Jitsi are better choices when source access or self-hosting outweighs operational simplicity.</li><li>Public per-minute rates are screening inputs, not final cost models, because vendors meter resolution, bandwidth, presets, and add-ons differently.</li><li>A provider adapter, production scorecard, canary release, and rollback window reduce the risk of replacing a live RTC stack.</li></ul><h2 id="conclusion">Conclusion</h2><p>The best ZEGOCLOUD alternatives solve different constraints. VideoSDK offers the strongest managed balance for broad client coverage, programmable video and audio, Prebuilt, and interactive streaming. Agora favors commercial RTC depth, while LiveKit and Jitsi favor infrastructure control. Validate the shortlist with your traffic and migration scorecard, then&nbsp;<a href="https://app.videosdk.live/login">start a VideoSDK account</a>&nbsp;or follow the React quickstart. What kind of real-time experience are you building?</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-best-zegocloud-alternative">What Is the Best ZEGOCLOUD Alternative?</h3><p>The best ZEGOCLOUD alternative for a managed, multi-platform RTC application is VideoSDK because it covers custom and prebuilt calls, interactive live streaming, mobile SDKs, Unity, C++, and IoT. Agora can be better for specialized engagement features, while LiveKit is better when open-source deployment control is mandatory.</p><h3 id="is-videosdk-cheaper-than-zegocloud">Is VideoSDK Cheaper Than ZEGOCLOUD?</h3><p>VideoSDK's listed HD rate is lower than ZEGOCLOUD's as of July 14, 2026: $3.00 versus $3.99 per 1,000 participant-minutes. Actual cost depends on received resolution, audio-only usage, recording, streaming, support, discounts, and taxes, so model a representative month before deciding.</p><h3 id="is-zegocloud-free-to-use">Is ZEGOCLOUD Free to Use?</h3><p>Yes, ZEGOCLOUD offers a free starting allowance. Its public pricing page advertises 10,000 free minutes, after which product-specific voice, video, streaming, chat, recording, and other rates apply.</p><h3 id="which-zegocloud-alternatives-are-open-source">Which ZEGOCLOUD Alternatives Are Open Source?</h3><p>LiveKit and Jitsi are the main open-source ZEGOCLOUD alternatives in this list. LiveKit provides a programmable real-time media server plus managed cloud, while Jitsi provides a complete meeting stack; self-hosting either option transfers infrastructure and reliability work to your team.</p><h3 id="does-videosdk-support-zegocloud-migration">Does VideoSDK Support ZEGOCLOUD Migration?</h3><p>VideoSDK supports the building blocks needed for a ZEGOCLOUD migration, including server-side tokens, REST room creation, participant and track events, recording, streaming, and SDKs across web and mobile. There is no universal one-click migration, so use a provider adapter and port features in controlled stages.</p><h3 id="which-alternative-is-best-for-live-streaming">Which Alternative Is Best for Live Streaming?</h3><p>The best live-streaming alternative depends on the interaction model. VideoSDK, Agora, and 100ms suit low-latency events where viewers can interact or join the stage. LiveKit offers a programmable WebRTC path, while Amazon Chime SDK can send meeting video to third-party streaming platforms through its Media Live Connector. Conventional one-way broadcasts may be cheaper on an HLS-focused service.</p><h3 id="what-should-i-test-before-switching">What Should I Test Before Switching?</h3><p>Before switching, test join success, time to first frame, audio continuity, video freezes, reconnection, packet loss, jitter, round-trip time, screen sharing, recording, webhooks, mobile background behavior, and cost per completed call. Run the same test matrix across representative devices, browsers, networks, and regions.</p>]]></content:encoded></item><item><title><![CDATA[Echo Models: Linguistic Turn Detection for Voice Agents]]></title><description><![CDATA[Echo Turn Detection is a real-time timing layer that transitions voice agents from rigid, walkie-talkie-like interfaces to natural, human-like dialogue. By analysing linguistic patterns rather than simple silence timeouts, Echo delivers up to 96.2% turn-taking accuracy and 25x fewer missed turn endings, allowing users to pause, hesitate, interrupt, and backchannel naturally.


The Turn-Taking Challenge

In a voice agent pipeline, speech recognition gets most of the attention. But knowing what th]]></description><link>https://www.videosdk.live/blog/echo-turn-detection</link><guid isPermaLink="false">6a3121ffb3240feb748bf66d</guid><category><![CDATA[ANNOUNCEMENT]]></category><category><![CDATA[AI voice agent]]></category><category><![CDATA[ai agents]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 23 Jun 2026 07:14:31 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/06/4-3.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/06/4-3.png" alt="Echo Models: Linguistic Turn Detection for Voice Agents"/><p><strong>Echo Turn Detection</strong>&nbsp;is a real-time timing layer that transitions voice agents from rigid, walkie-talkie-like interfaces to natural, human-like dialogue. By analysing linguistic patterns rather than simple silence timeouts, Echo delivers up to&nbsp;<strong>96.2% turn-taking accuracy</strong>&nbsp;and&nbsp;<strong>25x fewer missed turn endings, </strong>allowing users to pause, hesitate, interrupt, and backchannel naturally.</p><h2 id="the-turn-taking-challenge">The Turn-Taking Challenge</h2><p>In a voice agent pipeline, speech recognition gets most of the attention. But knowing&nbsp;<em>what</em>&nbsp;the user said is only half the problem. The harder real-time question is: should the agent speak now, keep listening, ignore a short backchannel, or stop talking?</p><p>A bad turn detector relies on a simple silence threshold (e.g., waiting 700ms after audio stops). This approach creates four classic failure modes:</p><ol><li><strong>Responding too early</strong>: The user pauses mid-sentence and the agent cuts them off.</li><li><strong>Waiting too long</strong>: The user is finished, but the agent leaves an awkward silence.</li><li><strong>Misreading backchannels</strong>: The user says “yeah” or “uh-huh” as a listening cue, and the agent treats it as a new command.</li><li><strong>Failing to stop</strong>: The user says “stop” or “wait” while the agent is speaking, but the agent keeps monologuing.</li></ol><p>To transition to true natural interaction, we need a dedicated timing layer that reasons over speech transcripts and linguistic intent.</p><h2 id="introducing-echo-turn">Introducing Echo Turn</h2><p>Echo Turn is a turn-taking detector designed for real-time voice agents. Instead of treating turn detection as a simple silence timeout, Echo predicts the conversational state of the user by analysing the linguistic patterns in the streaming speech transcript:</p><ul><li><strong>Linguistic intent</strong>: Analysing semantic structure to distinguish between incomplete statements and completed thoughts.</li><li><strong>Hesitation and filler patterns</strong>: Detecting words like “um”, “uh”, “yeah”, and “wait” to infer speaker state.</li><li><strong>Transcript punctuation</strong>: Using STT-generated markers for pauses and hesitations.</li><li><strong>Real-time constraints</strong>: Ultra-low latency inference for production.</li></ul><p>By analysing these cues, Echo can tell when a user saying "yeah" means&nbsp;<em>"Yes, that is my answer"</em>&nbsp;(Complete) versus&nbsp;<em>"I am listening, keep going"</em>&nbsp;(Backchannel).</p><h3 id="core-prediction-states">Core Prediction States</h3><p>Echo classifies streaming transcripts into four distinct conversational states to orchestrate agent behaviour. While identifying completion states is standard practice, Echo's true breakthrough lies in its ability to natively handle complex conversational signals like backchannels and pause requests.</p><h4 id="1-standard-industry-states">1. Standard Industry States</h4><ul><li><strong>Complete</strong>&nbsp;(<code>complete</code>): The user has finished speaking and is expecting a response.<ul><li><em>Agent Action</em>: Immediately triggers response generation.</li><li><em>Example</em>:&nbsp;<em>"What's the weather like in New York?"</em></li></ul></li><li><strong>Incomplete</strong>&nbsp;(<code>incomplete</code>): The user has paused mid-thought to think or catch their breath, but is not done.<ul><li><em>Agent Action</em>: Remains silent and continues listening, ignoring the brief silence.</li><li><em>Example</em>:&nbsp;<em>"I would like to order a..."</em>&nbsp;(pause)&nbsp;<em>"...pepperoni pizza."</em></li></ul></li></ul><h4 id="2-videosdks-innovations">2. VideoSDK's Innovations</h4><p>Unlike traditional turn detectors that only distinguish between complete and incomplete turns, Echo introduces support for human-like conversational dynamics:</p><ul><li><strong>Backchannel</strong>&nbsp;(<code>backchannel</code>): The user provides short verbal acknowledgments (e.g.,&nbsp;<em>"uh-huh"</em>,&nbsp;<em>"yeah"</em>,&nbsp;<em>"right"</em>,&nbsp;<em>"okay okay"</em>) to signal they are listening while the agent is speaking.<ul><li><em>Agent Action</em>: The agent continues speaking uninterrupted, rather than treating these verbal cues as interruptions or new command inputs. This solves the classic issue where voice assistants cut themselves off the moment a user shows active listening.</li></ul></li><li><strong>Wait</strong>&nbsp;(<code>wait</code>): The user explicitly requests the agent to hold (e.g.,&nbsp;<em>"wait a second"</em>,&nbsp;<em>"hold on"</em>,&nbsp;<em>"give me a moment"</em>).<ul><li><em>Agent Action</em>: The agent pauses its response generation or playback and waits patiently, keeping the session active without timing out or interpreting the pause as completion.</li></ul></li></ul><h3 id="model-family">Model Family</h3><p>We offer Echo Turn in two distinct variants so you can tune for your use case:</p><ul><li><strong>Echo Small</strong>: The default, lowest-latency model optimized for the fastest possible turn detection. Best when responsiveness matters most.</li><li><strong>Echo Large</strong>: A higher-accuracy model that trades a little latency for better classification. Best when accuracy matters more than raw speed.</li></ul><h3 id="model-architecture">Model Architecture</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/echo_turn_detector_architecture.png" class="kg-image" alt="Echo Models: Linguistic Turn Detection for Voice Agents" loading="lazy" width="1619" height="972"/></figure><h2 id="supported-languages">Supported Languages</h2><p>Echo Turn supports 12 languages across both model sizes: English, French, German, Italian, Spanish, Hindi, Gujarati, Marathi, Tamil, Telugu, Urdu, and Bengali.</p><h2 id="benchmark-turns2k-dataset">Benchmark: Turns2k Dataset</h2><p>We evaluated both Echo model variants on the English TURNS2K dataset for turn completion detection (classifying Incomplete vs. Complete turns):</p><h3 id="overall-comparative-metrics">Overall Comparative Metrics</h3>
<!--kg-card-begin: html-->
<table>
  <thead>
    <tr>
      <th>Metric</th>
      <th>Echo-Small</th>
      <th>Echo-Large</th>
      <th>Baseline</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><strong>Accuracy</strong></td>
      <td>93.60%</td>
      <td>96.20%</td>
      <td>61.13%</td>
    </tr>
    <tr>
      <td><strong>Recall (Complete)</strong></td>
      <td>97.31%</td>
      <td>96.50%</td>
      <td>32.83%</td>
    </tr>
    <tr>
      <td><strong>Specificity</strong></td>
      <td>88.91%</td>
      <td>95.81%</td>
      <td>96.83%</td>
    </tr>
    <tr>
      <td><strong>F1 Score (Complete)</strong></td>
      <td>0.9443</td>
      <td>0.9659</td>
      <td>0.4851</td>
    </tr>
  </tbody>
</table>
<!--kg-card-end: html-->
<h3 id="echo-large">Echo-Large</h3><p>On 2,000 English conversational samples, Echo-Large achieved 96.2% accuracy in detecting whether a speaker had finished their turn, substantially outperforming the Baseline under the same conditions. The largest difference was in turn-completion detection: Echo-Large correctly identified 96.5% of completed turns versus 32.8% for the Baseline, resulting in far fewer missed responses.</p><p>For every 100 times a user finished speaking, Echo-Large responded correctly approximately 97 times, missing only ~3.5 turn completions; the Baseline responded correctly about 33 times.</p><h3 id="echo-small">Echo-Small</h3><p>Echo-Small is optimized for responsive voice interactions where recognizing completed speech quickly is critical.</p><p>For every 100 times a user finished speaking, Echo-Small responded correctly 97.3 times versus 32.8 for the Baseline, about 25× fewer missed turn endings in this benchmark. Echo-Small is designed for applications where fast conversational turn-taking is a priority, while maintaining strong overall classification performance.</p><h2 id="how-it-is-hosted">How it is Hosted</h2><p>Echo Turn is server-hosted on the&nbsp;<strong>VideoSDK Inference Gateway</strong>&nbsp;and exposed through the&nbsp;<code>TurnV2</code>&nbsp;class, so there is no model to download or run on your machine.</p><h2 id="integration-guidelines">Integration Guidelines</h2><p>Echo Turn acts as the real-time timing layer in a voice pipeline. As the user speaks, VAD detects the speech and STT produces a transcript. After each user utterance, the latest transcript is sent to the Inference Gateway, where the selected Echo model (echo-small or echo-large) classifies the turn.</p><h3 id="python-sdk-implementation">Python SDK Implementation</h3><p>Echo Turn is server-hosted on the VideoSDK Inference Gateway and exposed through the&nbsp;<code>TurnV2</code>&nbsp;class in the&nbsp;<code>videosdk-agents</code>&nbsp;library. No local model download is required.</p><p>To use Echo Turn in your voice pipeline:</p><p><strong>Initialise the detector</strong>&nbsp;in your Python code:</p><pre><code class="language-python">from videosdk.agents.inference import TurnV2

# Initialize the default, lowest-latency model
turn_detector = TurnV2.echo_small()

# Or, initialize the higher-accuracy model
# turn_detector = TurnV2.echo_large()

pipeline = Pipeline(
       stt=DeepgramSTT(),
       llm=OpenAILLM(),
       tts=ElevenLabsTTS(),
       vad=SileroVAD(),
       turn_detector=turn_detector
   )</code></pre><p><strong>Set your authentication token</strong>:</p><pre><code class="language-bash">export VIDEOSDK_AUTH_TOKEN="your-videosdk-auth-token"
</code></pre><p><strong>Install the package</strong>&nbsp;(version&nbsp;<code>1.0.18</code>&nbsp;or higher is required):</p><pre><code class="language-bash">pip install "videosdk-agents&gt;=1.0.18"
</code></pre><h3 id="impact">Impact</h3><p>Reliable turn detection improves core voice metrics:</p><ul><li><strong>Reduced Latency</strong>: Agents respond immediately when the user is finished, eliminating fixed timeouts.</li><li><strong>Conversation Naturalness</strong>: Fewer awkward silences and false interruptions make conversation feel human.</li><li><strong>Infrastructure Efficiency</strong>: Reduces unnecessary LLM API calls triggered by misclassified partial turns.</li></ul><h2 id="try-echo-turn">Try Echo Turn</h2><p>Echo Turn is now available across our Agent Cloud and Runtime.</p><ul><li><strong>Quick Start Demo</strong>: Clone and run our&nbsp;<a href="https://github.com/videosdk-community/echo-turn-detector-example" rel="noreferrer">GitHub Quickstart Example</a>&nbsp;to see Echo's real-time turn-taking pipeline in action locally within minutes.</li><li><strong>Documentation</strong>:&nbsp;<a href="https://docs.videosdk.live/ai_agents/core-components/turn-detection">Read the Docs</a>&nbsp;to learn more, or check out the&nbsp;<a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference">Inference Plugin Docs</a>&nbsp;for integration details.</li><li><strong>Join the Community</strong>: Have questions or want to discuss integration?&nbsp;<a href="https://discord.gg/f2WsNDN9S5">Join our Discord</a>.</li></ul>]]></content:encoded></item><item><title><![CDATA[Introducing VideoSDK Warm Transfer: Escalate to a Human -     Briefed, Before They Take the Call]]></title><description><![CDATA[Escalate from your AI voice agent to a human the right way with VideoSDK Warm Transfer—brief the supervisor with an AI summary before the caller connects.]]></description><link>https://www.videosdk.live/blog/introducing-videosdk-warm-transfer</link><guid isPermaLink="false">6a339327b3240feb748bf70d</guid><category><![CDATA[ANNOUNCEMENT]]></category><category><![CDATA[New Features]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 18 Jun 2026 12:11:48 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/06/Introducing-Warm-Transfer-Brief-a-Human-Supervisor-Before-the-Handoff--1-.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/Introducing-Warm-Transfer-Brief-a-Human-Supervisor-Before-the-Handoff--1-.jpg" alt="Introducing VideoSDK Warm Transfer: Escalate to a Human -     Briefed, Before They Take the Call"/><p>Here's everything this guide covers. When an AI voice agent needs to escalate to a human, forwarding the call cold means the supervisor opens with "what's this about?" and the caller has to start over. VideoSDK Warm Transfer fixes that: it brings the supervisor up to speed <em>before</em> they take the call. We'll walk through what Warm Transfer does, the phase-by-phase state machine behind it, how to trigger it from a function tool, how to listen for phase events, how to customize the briefing (summary LLM, prompt, and consultation pipeline), what the result object gives you back, and how it differs from a basic Call Transfer.</p><h2 id="a-cold-handoff-makes-the-caller-start-all-over-again">A cold handoff makes the caller start all over again</h2><p>Plenty of calls reach a point where the best move is to bring in a human - a refund that needs approval, an angry customer who wants a manager, an edge case the agent wasn't built for. The escalation itself isn't the hard part. The <em>context</em> is.</p><p>With a plain transfer, the human inherits a live caller and zero background. They have to ask who they're talking to, what the issue is, and what's already been tried - while the caller, who has explained all of this once already, repeats themselves with rising frustration. The handoff works mechanically but fails as an experience.</p><p>At VideoSDK, we think the human should walk into the conversation already informed. The caller shouldn't have to re-explain anything, and the supervisor shouldn't have to guess.</p><p>That's what <strong>Warm Transfer</strong> does.</p><h2 id="what-warm-transfer-does">What Warm Transfer does</h2><p>Warm Transfer hands off an ongoing SIP call to a human supervisor <strong>after</strong> the agent has briefed them on what the caller wants. The caller is placed on hold, a private consultation room is created, the supervisor is dialed in over SIP, the agent delivers an LLM-generated summary of the call so far, and only then is the caller switched over. The supervisor never has to ask "what's this about?"</p><p>This is the key difference from the basic <a href="https://docs.videosdk.live/ai_agents/core-components/call-transfer">Call Transfer</a>, which forwards the call directly with no handoff context. Warm Transfer trades a little extra orchestration for a supervisor who is ready the moment they connect.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/warm-transfer-flow-2.png" class="kg-image" alt="Introducing VideoSDK Warm Transfer: Escalate to a Human -     Briefed, Before They Take the Call" loading="lazy" width="3000" height="1640"/></figure><p><em>The caller is held while the agent and the human supervisor meet in a private consultation room. The agent reads an LLM summary of the conversation, the supervisor acknowledges, and only then is the caller moved in - and the agent steps out.</em></p><h2 id="how-warm-transfer-works">How Warm Transfer works</h2><p>Under the hood, a Warm Transfer runs as a <strong>state machine</strong>, and you can observe every phase through <strong>@session.on_warm_transfer(...)</strong>. Here's the full sequence, in order:</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/warm-transfer-phases.png" class="kg-image" alt="Introducing VideoSDK Warm Transfer: Escalate to a Human -     Briefed, Before They Take the Call" loading="lazy" width="3000" height="2160"/></figure><ol><li><strong>The agent triggers it.</strong> From inside a function tool, the agent calls <strong>session.warm_transfer(config)</strong>.</li><li><strong>A summary is generated.</strong> An LLM produces a summary of the conversation so far, built from the agent's chat history.</li><li><strong>The caller goes on hold.</strong> While the caller waits, a private consultation room is created.</li><li><strong>The supervisor is dialed in.</strong> The supervisor is called over SIP and joins the consultation room.</li><li><strong>The agent briefs the supervisor.</strong> A built-in <strong>WarmTransferAgent</strong> reads the summary out to the supervisor and waits for them to acknowledge it.</li><li><strong>The caller is brought in.</strong> The caller is moved into the consultation room and is now talking to the supervisor.</li><li><strong>The agent bows out.</strong> The transfer completes and the agent leaves the call.</li></ol><p>The important detail: the summary briefing (steps 2–5) all happens <em>off to the side</em>, in a consultation room the caller never hears, before the caller is connected in step 6.</p><h2 id="triggering-a-warm-transfer">Triggering a Warm Transfer</h2><p>You expose the escalation as a @function_tool and call <strong>session.warm_transfer() </strong>inside it, so the <strong>agent decides</strong> when to escalate based on the conversation. Describe when to escalate in the agent's instructions, and the LLM handles the trigger.</p><p>python</p><pre><code class="language-python">from videosdk.agents import Agent, function_tool
from videosdk.agents.warm_transfer import SIPDestination, WarmTransferConfig

class CustomerServiceAgent(Agent):
    def __init__(self) -&gt; None:
        super().__init__(
            instructions=(
                "You are a helpful customer service agent. "
                "If the caller asks for a manager or needs a human, "
                "call escalate_to_human."
            )
        )

    @function_tool
    async def escalate_to_human(self, reason: str) -&gt; str:
        """Escalate this call to a human supervisor with a warm transfer.

        Args:
            reason: Short description of why the escalation is happening.
        """
        config = WarmTransferConfig(
            destination=SIPDestination(
                routing_rule_id="rr_xxxxxxxx",
                sip_call_to="+1XXXXXXXXXX",     # Supervisor's number (E.164)
                sip_call_from="+1XXXXXXXXXX",   # Caller-ID to present
            ),
        )
        result = await self.session.warm_transfer(config)
        if result.success:
            return "Connected to a supervisor."
        return "I couldn't reach a supervisor right now. Let me keep h</code></pre><h3 id="what-each-piece-is-doing">What each piece is doing</h3><ul><li>instructions — Tell the agent when to escalate. Here, any time the caller asks for a manager or a human, the LLM calls escalate_to_human on its own.</li><li>@function_tool escalate_to_human(reason) — The escalation tool. The reason argument lets the model record <em>why</em> it's escalating, which is useful for logging and analytics.</li><li>WarmTransferConfig — The configuration object for the transfer. At minimum it carries the destination.</li><li>SIPDestination — Where the supervisor is reached:<ul><li>routing_rule_id — The routing rule that governs the outbound SIP call.</li><li>sip_call_to — The supervisor's phone number, in E.164 format.</li><li>sip_call_from — The caller-ID presented on the outbound leg.</li></ul></li><li>await self.session.warm_transfer(config) — Kicks off the whole state machine and returns a result once it settles.</li><li>result.success — Lets the agent respond naturally: confirm the connection on success, or gracefully keep helping the caller if a supervisor couldn't be reached.</li></ul><blockquote><strong>Heads-up on caller-ID.</strong> sip_call_from must be a number your routing rule or trunk is authorized to send. If it isn't, carriers may reject or drop the call.</blockquote><h2 id="listening-for-phase-events">Listening for phase events</h2><p>Because Warm Transfer is a state machine, you can subscribe to its phase changes with @session.on_warm_transfer(). An <strong>undecorated</strong> handler receives <em>every</em> phase; pass a <strong>phase name</strong> to filter for just one.</p><p>python</p><pre><code class="language-python">@session.on_warm_transfer()
def on_any_phase(payload):
    # payload = {"phase": WarmTransferPhase, "data": {...},
    #            "timestamp": float, "consultation_room_id": Optional[str]}
    print(f"[WARM TRANSFER] phase={payload['phase'].value}")

@session.on_warm_transfer("transfer_complete")
def on_done(payload):
    print("Caller is now talking to a supervisor.")</code></pre><p>Each event hands you a payload with the current phase, any phase-specific data, a timestamp, and the consultation_room_id once one exists. The first handler above logs every transition; the second fires only on transfer_complete, the moment the caller is connected to the supervisor. This is where you'd hook in your own logging, dashboards, or analytics for each step of the handoff.</p><h2 id="customizing-the-briefing">Customizing the briefing</h2><p>Out of the box, the SDK keeps things simple: it generates the summary using your <strong>session's own LLM</strong> with a default <strong>150-word briefing prompt</strong>, and it builds the consultation room's pipeline by re-instantiating your STT, LLM, TTS, VAD, and turn-detector classes <strong>with no arguments</strong> — which works as long as those providers read their credentials from the environment.</p><p>When you need more control, every part of that is overridable through optional WarmTransferConfig fields:</p><p>python</p><pre><code class="language-python">from videosdk.agents import Pipeline
from videosdk.agents.plugins import AnthropicLLM, DeepgramSTT, CartesiaTTS, SileroVAD, TurnDetector

config = WarmTransferConfig(
    destination=SIPDestination(routing_rule_id="rr_xxx", sip_call_to="+1...", sip_call_from="+1..."),
    summary_llm=AnthropicLLM(model="claude-3-5-sonnet"),
    summary_prompt="Summarize the call for a supervisor in under 100 words.",
    # Pass briefing_pipeline_factory if your providers need constructor args
    # (model ids, voice ids, keys not in env) instead of relying on defaults.
    briefing_pipeline_factory=lambda: Pipeline(
        stt=DeepgramSTT(model="nova-3"),
        llm=AnthropicLLM(model="claude-3-5-sonnet"),
        tts=CartesiaTTS(voice="..."),
        vad=SileroVAD(),
        turn_detector=TurnDetector(),
    ),
)</code></pre><ul><li><strong>summary_llm</strong> — Use a specific model to write the briefing (for example, a stronger model just for summarization), instead of the session's default LLM.</li><li><strong>summary_prompt</strong> — Replace the default 150-word prompt with your own instructions — shorter, longer, or focused on the details your supervisors care about.</li><li><strong>briefing_pipeline_factory</strong> — A factory that builds the consultation room's Pipeline explicitly. Reach for this when your providers need constructor arguments — model IDs, voice IDs, or keys that aren't in the environment — rather than relying on the no-argument defaults.</li></ul><h2 id="what-you-get-backand-what-happens-if-the-caller-hangs-up">What you get back - and what happens if the caller hangs up</h2><p>session.warm_transfer() returns a WarmTransferResult. It tells you whether the transfer succeeded (success), the terminal phase it ended on, the consultation room and SIP call IDs, the generated summary, and an optional errorif something went wrong.</p><p>There's one more behavior worth calling out: the transfer is <strong>shielded from cancellation</strong>. If the function tool that triggered it gets cancelled — say the caller interrupts mid-escalation — the transfer doesn't abort. It keeps running to completion in the background; the only thing that changes is that its result is no longer awaited. In other words, once a warm transfer is in motion, it finishes cleanly rather than leaving a half-connected call.</p><h2 id="try-it-yourself">Try it yourself</h2><p>A complete, runnable warm-transfer agent with supervisor escalation is on GitHub: <a href="https://github.com/videosdk-live/agents/blob/main/examples/warm_transfer.py" rel="noreferrer"><strong>examples/warm_transfer.py</strong></a>. It's the fastest way to see the full phase sequence in action.</p><h2 id="warm-transfer-vs-call-transfer-which-one-do-you-need">Warm Transfer vs. Call Transfer: which one do you need?</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/call-transfer-vs-warm-transfer-3.png" class="kg-image" alt="Introducing VideoSDK Warm Transfer: Escalate to a Human -     Briefed, Before They Take the Call" loading="lazy" width="3000" height="2160"/></figure><p>Both move a live SIP call somewhere else without making the caller redial — the difference is <strong>context</strong>.</p><ul><li>Use <a href="https://docs.videosdk.live/ai_agents/core-components/call-transfer"><strong>Call Transfer</strong></a> when the destination just needs the call: routing to another department, an external line, or any number that doesn't need a briefing. It forwards the call directly and instantly.</li><li>Use <strong>Warm Transfer</strong> when the person receiving the call needs to <em>know what's going on first</em>: escalating to a human supervisor, a specialist, or a manager who should never have to ask the caller to repeat themselves.</li></ul><p>A simple rule of thumb: <strong>Call Transfer moves the call; Warm Transfer moves the call <em>and</em> the context.</strong></p><h2 id="ship-it">Ship it</h2><p>Warm Transfer turns a jarring "let me transfer you" into a smooth, briefed handoff. Your agent decides when to escalate, summarizes the conversation, gets the supervisor up to speed in a private room, and only then connects the caller — all from a single function tool, with full visibility into every phase and a result object you can act on.</p><p>Read the full docs: <a href="https://docs.videosdk.live/ai_agents/core-components/warm-transfer">Warm Transfer — VideoSDK AI Agents</a>.</p><p><strong>Have feedback or questions?</strong> Join our <a href="https://discord.gg/Gpmj6eCq5u">Discord community</a> and tell us what you're building.</p><p><em>Ready to give your AI agents context-aware human escalation? </em><a href="https://dub.sh/new_signup" rel="noreferrer"><em>Sign in to the VideoSDK Dashboard </em></a><em>and get started — it's free.</em></p>]]></content:encoded></item><item><title><![CDATA[Introducing VideoSDK Call Transfer: Let Your AI Agent Hand Off Live Calls - No Hang-Up, No Redial]]></title><description><![CDATA[Add human escalation to your AI voice agent with VideoSDK Call Transfer—forward a live SIP call to any number with no disconnect and no redial.]]></description><link>https://www.videosdk.live/blog/introducing-videosdk-call-transfer</link><guid isPermaLink="false">6a338b81b3240feb748bf6e9</guid><category><![CDATA[ANNOUNCEMENT]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[New Features]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 18 Jun 2026 11:55:15 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/06/7.png" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/7.png" alt="Introducing VideoSDK Call Transfer: Let Your AI Agent Hand Off Live Calls - No Hang-Up, No Redial"/><p>Here's everything this guide covers. AI phone agents are great at handling the first mile of a conversation, but some calls need to reach a human or a different department — and making the caller hang up and redial is the fastest way to lose them. VideoSDK Call Transfer fixes that: the agent detects intent, triggers a function tool, and the live SIP call is forwarded to a new number instantly, without disconnecting or redialing. We'll cover how Call Transfer works, the code that drives it, how the agent decides when to transfer, a runnable example, and how it differs from Warm Transfer for human escalations.</p><h2 id="when-the-best-thing-your-agent-can-do-is-pass-the-call-along">When the best thing your agent can do is pass the call along</h2><p>A good voice agent knows its limits. It can answer questions, take details, and resolve the routine cases - but eventually a caller asks for billing, or sales, or a human, and the agent's job becomes getting them to the right place quickly.</p><p>The old way to do that is painful: "Please hang up and call this other number." Every one of those handoffs is a chance for the caller to drop off, mis-dial, or land back in a queue from the start. The context is gone, the momentum is gone, and the experience feels broken.</p><p>At VideoSDK, we think a handoff should be invisible to the caller. The agent should be able to move a live call somewhere else the moment it's the right thing to do — and the caller should just hear the next person pick up.</p><p>Today, we're introducing <strong>Call Transfer</strong> - a built-in capability that lets your AI agent move an ongoing SIP call to another phone number without ending the current session.</p><h2 id="what-call-transfer-does">What Call Transfer does</h2><p>Call Transfer lets your AI Agent move an ongoing SIP call to another phone number without ending the current session. Instead of making the caller hang up and dial a new number, the agent can automatically route the call.</p><p>The key idea: the call is <strong>forwarded in place</strong>. There's no disconnect and no redial — the existing SIP call is handed to the new destination instantly, so the caller stays on the line the whole time.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/call-transfer-flow-1.png" class="kg-image" alt="Introducing VideoSDK Call Transfer: Let Your AI Agent Hand Off Live Calls - No Hang-Up, No Redial" loading="lazy" width="3000" height="1800"/></figure><p><em>The caller is on a live SIP call with the AI agent. When the agent decides a transfer is needed, it triggers a function tool, which calls </em>session.call_transfer(...)<em>. The platform forwards the ongoing SIP call to the new phone number - the caller is never disconnected.</em></p><h2 id="how-call-transfer-works">How Call Transfer works</h2><p>Under the hood, the flow is refreshingly simple — three steps, driven entirely by the agent's own decision-making:</p><ol><li><strong>The agent evaluates intent.</strong> As the conversation unfolds, the agent determines when a call transfer is required and then triggers the function tool.</li><li><strong>The function tool fires.</strong> When triggered, it tells the system to move the call to another phone number.</li><li><strong>The call is forwarded instantly.</strong> The ongoing SIP call is forwarded to the new number immediately — without disconnecting or redialing.</li></ol><p>Because the transfer is initiated as a <strong>function tool</strong>, the <em>agent</em> decides when to call it, based on what the caller actually says. You describe the tool and when to use it in the agent's instructions, and the LLM handles the rest — no rigid menu trees, no DTMF mazes</p><h2 id="triggering-a-call-transfer">Triggering a Call Transfer</h2><p>Here's the core of it. You define an agent with a transfer_call function tool, and inside that tool you call self.session.call_transfer(transfer_to) with the destination number. The agent's instructions tell it to use that tool whenever the caller needs to be moved.</p><pre><code class="language-python">import os
from videosdk.agents import Agent, function_tool

class CallTransferAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions="You are the Call Transfer Agent Which Help and provide to transfer on going call to new number. use transfer_call tool to transfer the call to new number.",
        )

    async def on_enter(self) -&gt; None:
        await self.session.say("Hello Buddy, How can I help you today?")

    async def on_exit(self) -&gt; None:
        await self.session.say("Goodbye Buddy, Thank you for calling!")

    @function_tool
    async def transfer_call(self) -&gt; dict:
        """Transfer the call to Provided number"""
        transfer_to = os.getenv("VIDEOSDK_CALL_TRANSFER_TO")
        if not transfer_to:
            return {"status": "error", "message": "No transfer destination configured."}
        result = await self.session.call_transfer(transfer_to)
        return {"status": "transferred", "result": result}</code></pre><h3 id="what-each-piece-is-doing">What each piece is doing</h3><ul><li>instructions — This is where you tell the agent who it is and when to transfer. The LLM reads these instructions and decides, on its own, when to call transfer_call based on the conversation.</li><li>on_enter — A lifecycle hook that runs when the agent joins the call. Here it greets the caller: "Hello Buddy, How can I help you today?"</li><li>on_exit — Runs as the agent leaves, delivering a closing line: "Goodbye Buddy, Thank you for calling!"</li><li>@function_tool — Marks transfer_call as a tool the agent can invoke. This is the bridge between the LLM's decision and the actual transfer.</li><li>transfer_to — The destination number, read here from the VIDEOSDK_CALL_TRANSFER_TO environment variable. If it isn't set, the tool returns an error status instead of attempting the transfer.</li><li>self.session.call_transfer(transfer_to) — The call that does the work. It forwards the live SIP call to the destination and returns a result, which the tool passes back as {"status": "transferred", "result": result}.</li></ul><p>That status dictionary matters: returning a clear result lets the agent know the transfer succeeded (or didn't) and respond naturally to the caller.</p><blockquote><strong>Setting up the phone side.</strong> Call Transfer works on top of your telephony setup. To configure incoming call handling, outbound calling, and routing rules, follow the <a href="https://docs.videosdk.live/telephony/ai-telephony-agent-quick-start#part-2-connect-your-agent-to-the-phone-network">AI Telephony Agent Quick Start</a>.</blockquote><h2 id="try-it-yourself">Try it yourself</h2><p>Two complete, runnable examples are on GitHub:</p><ul><li><strong>Call Transfer example</strong> — the minimal agent above, end to end: <a href="https://github.com/videosdk-live/agents/blob/main/examples/call_transfer.py"><code>examples/call_transfer.py</code></a>.</li><li><strong>Call Center Agent</strong> — a fuller use case that connects a telephony customer-care agent with human-agent handoff via call_transfer: <a href="https://github.com/videosdk-live/agents/blob/main/use_case_examples/call_center_agent.py"><code>use_case_examples/call_center_agent.py</code></a>.</li></ul><h2 id="call-transfer-vs-warm-transfer-which-one-do-you-need">Call Transfer vs. Warm Transfer: which one do you need?</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/call-transfer-vs-warm-transfer-2.png" class="kg-image" alt="Introducing VideoSDK Call Transfer: Let Your AI Agent Hand Off Live Calls - No Hang-Up, No Redial" loading="lazy" width="3000" height="2160"/></figure><p>Call Transfer is a <strong>direct</strong> hand-off - it forwards the call straight to the new number without any handoff context. That's exactly what you want for routing to another department, an external line, or a number that doesn't need a briefing.</p><p>When you're escalating to a <strong>human supervisor</strong> and want them to know what's going on before they take over, reach for <a href="https://docs.videosdk.live/ai_agents/core-components/warm-transfer">Warm Transfer</a> instead. Warm Transfer places the caller on hold, spins up a private consultation room, dials the supervisor over SIP, and has the agent read out an <strong>LLM-generated summary</strong> of the call so far — so the supervisor never has to ask "what's this about?" - before the caller is switched over.</p><p>A simple rule of thumb: use <strong>Call Transfer</strong> when the destination just needs the call, and <strong>Warm Transfer</strong> when the person receiving the call needs the context.</p><h2 id="ship-it">Ship it</h2><p>Call Transfer turns "please hang up and dial this number" into a single function the agent can call on its own. Define the tool, point it at a destination, describe when to use it — and your agent can move callers to the right place the instant the conversation calls for it, without ever dropping the line.</p><p>Read the full docs: <a href="https://docs.videosdk.live/ai_agents/core-components/call-transfer">Call Transfer - VideoSDK AI Agents</a>.</p><p><strong>Have feedback or ideas?</strong> Join our <a href="https://discord.gg/Gpmj6eCq5u">Discord community</a> and tell us what you're building.</p><p><em>Want to give your AI agents the power to route calls? </em><a href="https://dub.sh/new_signup" rel="noreferrer"><em>Sign in to the VideoSDK Dashboard </em></a><em>and get started - it's free.</em></p>]]></content:encoded></item><item><title><![CDATA[Introducing the VideoSDK Fallback Adapter: Keep Voice Agents Talking When Providers Fail]]></title><description><![CDATA[Keep AI voice agents talking when a provider fails. The Fallback Adapter adds automatic STT, LLM, and TTS failover—on error or latency—with mid-session recovery.]]></description><link>https://www.videosdk.live/blog/introducing-the-videosdk-fallback-adapter</link><guid isPermaLink="false">6a2fb9f3b3240feb748bf5a5</guid><category><![CDATA[AI voice agent]]></category><category><![CDATA[ANNOUNCEMENT]]></category><category><![CDATA[New Features]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 16 Jun 2026 11:35:33 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/06/6.png" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/6.png" alt="Introducing the VideoSDK Fallback Adapter: Keep Voice Agents Talking When Providers Fail"/><p>Here's everything this guide covers. AI voice agents in production depend on external STT, LLM, and TTS providers, and any of them can fail or slow down mid-call. The VideoSDK Fallback Adapter fixes that by automatically failing over to backup providers — on both errors and latency — without interrupting the session. We'll look at why that matters, walk through its features (automatic and latency-based fallback, cooldown-based retry, auto-recovery, and permanent disable), and show how to configure it in code (temporary_disable_sec, permanent_disable_after_attempts, latency_threshold_ms, and consecutive_latency_hits). Then we trace the full failover-and-recovery lifecycle and link a runnable example you can try yourself.</p><h2 id="production-doesnt-wait-for-your-provider-to-come-back"><strong>Production doesn't wait for your provider to come back</strong></h2><p>AI voice agents feel effortless in a demo. Then they hit production, and a different set of problems shows up — problems that have nothing to do with how smart your agent is.</p><p>A speech-to-text provider rate-limits you at peak. An LLM endpoint times out for ninety seconds. A text-to-speech voice that was snappy yesterday is suddenly crawling. None of these are model problems. They’re reliability problems. And in a live voice conversation, there’s no room to retry quietly in the background - every second of dead air is a user wondering if anyone is still there.</p><p>At VideoSDK, we believe a single provider hiccup shouldn’t take down a live conversation. Your agent should degrade gracefully, recover automatically, and keep talking.</p><p>Today, we’re introducing the Fallback Adapter - automatic failover and recovery built directly into the VideoSDK Agents pipeline. It switches providers the moment one fails or slows down, mid-session, without interrupting the conversation, and switches back the moment the healthy provider returns.</p><h2 id="what-the-fallback-adapter-does"><strong>What the Fallback Adapter does</strong></h2><p>The Fallback Adapter provides automatic failover across multiple STT, LLM, or TTS providers. You give each component an ordered list of providers, and the adapter handles the rest.</p><p>It switches providers on two conditions:</p><ol><li><strong>On Errors </strong>— when a provider fails or becomes unavailable.</li><li><strong>On Latency </strong>— when a provider stays slower than its configured budget.</li></ol><p>In both cases, the system automatically moves to the next configured provider without interrupting the session. The caller never knows a provider just dropped out from under them.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/fallback-adapter-architecture-1.png" class="kg-image" alt="Introducing the VideoSDK Fallback Adapter: Keep Voice Agents Talking When Providers Fail" loading="lazy" width="2960" height="1960"/></figure><p><em>Each stage of the voice pipeline (STT → LLM → TTS) is wrapped in a Fallback Adapter holding a primary and one or more standby providers. A health-and-latency monitor watches every stage; an auto-recovery and cooldown controller decides when to fail over and when to switch back.</em></p><h2 id="why-it-matters-enterprise-grade-reliability-zero-extra-plumbing"><strong>Why it matters: enterprise-grade reliability, zero extra plumbing</strong></h2><p>Imagine a financial-services team running thousands of AI-powered onboarding and support calls a day. Traffic spikes. Providers throttle. A regional TTS endpoint degrades for a few minutes during a deploy on the vendor's side.</p><p>Without fallback, every one of those moments is a failed call — a frustrated customer, a broken workflow, a support ticket. Building resilience by hand means writing retry logic, health checks, cooldown timers, and recovery state machines around every provider, then maintaining all of it.</p><p>The Fallback Adapter collapses that entire layer into a few lines of configuration. Your team keeps focusing on the conversation. The platform keeps the conversation alive.</p><h2 id="features-at-a-glance"><strong>Features at a glance</strong></h2><p>• <strong>Automatic Fallback</strong> — Switches to lower-priority providers if the primary provider fails.<br>• <strong>Latency-based Fallback</strong> — Optionally switches providers when a component stays above its latency budget for several consecutive turns.<br>• <strong>Cooldown-based Retry</strong> — Applies a cooldown period before retrying a failed provider, preventing immediate repeated failures.<br>• <strong>Auto-Recovery </strong>— Automatically switches back to a higher-priority provider once it becomes healthy again.<br>• <strong>Permanent Disable </strong>— Permanently disables a provider after a configured number of failed recovery attempts.</br></br></br></br></p><h3 id="error-based-fallback"><strong>Error-based Fallback</strong></h3><p>This is the baseline behavior: when a provider fails or becomes unavailable, the adapter switches to the next provider in your list. Wrap each component with FallbackSTT, FallbackLLM, or FallbackTTS and pass an ordered list of providers.</p><p>from videosdk.agents import FallbackSTT, FallbackLLM, FallbackTTS<br>from videosdk.agents.plugins import OpenAISTT, OpenAILLM, OpenAITTS, DeepgramSTT</br></p><h3 id="configure-fallback-stt"><strong>Configure Fallback STT</strong></h3><pre><code class="language-js">stt_provider = FallbackSTT(
       [OpenAISTT(), DeepgramSTT()],
       temporary_disable_sec=30.0,
       permanent_disable_after_attempts=3,
)
Configure Fallback LLM
llm_provider = FallbackLLM(
        [OpenAILLM(model="gpt-4o-mini"), CerebrasLLM()],
        temporary_disable_sec=30.0,
        permanent_disable_after_attempts=3,
)
Configure Fallback TTS
tts_provider = FallbackTTS(
       [OpenAITTS(voice="alloy"), CartesiaTTS()],
       temporary_disable_sec=30.0,
       permanent_disable_after_attempts=3,
)
</code></pre><h3 id="configuration-options"><strong>Configuration Options</strong></h3>
<!--kg-card-begin: html-->
<table>
  <thead>
    <tr>
      <th>Parameter</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>temporary_disable_sec</code></td>
      <td>
        The duration (in seconds) to wait before trying
        a failed provider again.
      </td>
    </tr>
    <tr>
      <td><code>permanent_disable_after_attempts</code></td>
      <td>
        The maximum number of recovery attempts allowed
        before a provider is permanently disabled.
      </td>
    </tr>
  </tbody>
</table>
<!--kg-card-end: html-->
<h2 id="latency-based-fallback"><strong>Latency-based Fallback</strong></h2><p>Hard failures are the obvious case. The subtler one is a provider that never errors out — it just gets slow. A model that takes two seconds to start streaming turns a natural conversation into an awkward one.</p><p>The Fallback Adapter handles this too. It can switch providers when a healthy provider becomes too slow, keeping conversations responsive even when a vendor degrades without ever returning an error.</p><p>A few things worth knowing about how it works:</p><p>• <strong>It’s off by default</strong>. Set latency_threshold_ms on a component to enable it.<br>• <strong>Each component measures the latency metric that matters for it.</strong> STT uses stt_latency, LLM uses llm_ttft (time to first token), and TTS uses ttfb (time to first byte).<br>• <strong>It won’t overreact to a single slow turn.</strong> A provider is only switched after it stays above the threshold for consecutive_latency_hits turns in a row.<br>• <strong>Recovery works the same way as the error path.</strong> Cooldown and recovery for a latency-disabled provider reuse the same temporary_disable_sec and permanent_disable_after_attempts settings.</br></br></br></p><p>To enable it, add <strong>latency_threshold_ms</strong> (and optionally <strong>consecutive_latency_hits</strong>) on top of your error-based configuration:</p><p>from videosdk.agents import FallbackSTT, FallbackLLM, FallbackTTS<br>from videosdk.agents.plugins import OpenAISTT, OpenAILLM, OpenAITTS, DeepgramSTT</br></p><h3 id="configure-fallback-stt-1"><strong>Configure Fallback STT</strong></h3><pre><code class="language-js">stt_provider = FallbackSTT(
        [OpenAISTT(), DeepgramSTT()],
        temporary_disable_sec=30.0,
        permanent_disable_after_attempts=3,
        latency_threshold_ms=350,
        consecutive_latency_hits=3,
)
Configure Fallback LLM
llm_provider = FallbackLLM(
         [OpenAILLM(model="gpt-4o-mini"), CerebrasLLM()],
         temporary_disable_sec=30.0,
         permanent_disable_after_attempts=3,
         latency_threshold_ms=800,
        consecutive_latency_hits=3,
)
Configure Fallback TTS
tts_provider = FallbackTTS(
       [OpenAITTS(voice="alloy"), CartesiaTTS()],
       temporary_disable_sec=30.0,
       permanent_disable_after_attempts=3,
       latency_threshold_ms=250,
       consecutive_latency_hits=3,
)</code></pre><h3 id="configuration-options-1"><strong>Configuration Options</strong></h3>
<!--kg-card-begin: html-->
<table>
  <thead>
    <tr>
      <th>Parameter</th>
      <th>Description</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td><code>latency_threshold_ms</code></td>
      <td>
        Per-component latency budget in milliseconds
        (<code>STT stt_latency</code>, <code>LLM llm_ttft</code>,
        <code>TTS ttfb</code>). Disabled by default.
        Pass a value to enable latency-based fallback.
      </td>
    </tr>
    <tr>
      <td><code>consecutive_latency_hits</code></td>
      <td>
        The number of consecutive turns that must exceed
        <code>latency_threshold_ms</code> before switching
        providers. Defaults to <code>3</code>.
      </td>
    </tr>
  </tbody>
</table>
<!--kg-card-end: html-->
<h2 id="how-failover-and-recovery-actually-flow"><strong>How failover and recovery actually flow</strong></h2><p>Fallback isn't just "switch and forget." The adapter runs a full lifecycle for every provider, so a temporary outage doesn't permanently downgrade your stack — and a truly dead provider doesn't keep getting hammered.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/fallback-recovery-lifecycle.png" class="kg-image" alt="Introducing the VideoSDK Fallback Adapter: Keep Voice Agents Talking When Providers Fail" loading="lazy" width="3000" height="2080"/></figure><p>Here's the loop, end to end:</p><p>1. <strong>Primary Active.</strong> The highest-priority healthy provider handles the turn.</p><p>2. <strong>Detection.</strong> On every turn the adapter checks two things: did the provider error, and has it exceeded its latency budget for consecutive_latency_hits turns in a row?</p><p>3. <strong>Switch. </strong>If either is true, the session immediately moves to the next configured provider — the conversation never pauses.</p><p>4. <strong>Cooldown. </strong>The failed provider enters a cooldown for temporary_disable_sec seconds before it's eligible to be retried, which prevents a flapping provider from failing over and over in a tight loop.</p><p>5. <strong>Retry &amp; Auto-Recovery. </strong>Once the cooldown elapses, the adapter retries the provider. If it’s healthy again, the adapter automatically recovers it and returns to the higher-priority provider.</p><p>6. <strong>Permanent Disable. </strong>If the provider keeps failing, after <strong>permanent_disable_after_attempts</strong> recovery attempts it’s permanently disabled — the adapter stops wasting turns on a provider that isn’t coming back.</p><p>The result: graceful degradation when things go wrong, automatic restoration when they recover, and a hard stop for providers that are genuinely down.</p><p>Resilience used to be the hardest part of shipping a voice agent — the retry logic, the health checks, the recovery state machines you had to build and babysit around every provider. With the Fallback Adapter, it's a few lines of configuration that ship with your pipeline.</p><p>Start with error-based fallback. Add latency budgets when you're ready. Tune cooldown and recovery to your SLA. Your agents stay up; your team stays focused on the conversation.</p><p>Read the full docs: <a href="https://docs.videosdk.live/ai_agents/core-components/fallback-adapter">Fallback Adapter — VideoSDK AI Agents</a>.</p><p><strong>Have feedback or ideas?</strong> Join our <a href="https://discord.com/invite/Gpmj6eCq5u" rel="noreferrer">Discord community</a> and tell us what you're building.</p><p>Want to ship resilient voice agents today? Sign in to the <a href="https://dub.sh/new_signup" rel="noreferrer">VideoSDK Dashboard</a> and get started - it’s free.</p>]]></content:encoded></item><item><title><![CDATA[Top AI Voice Agent Platforms for Developers in 2026]]></title><description><![CDATA[The global voice AI market crossed $22B in 2026. We compare VideoSDK, Vapi, LiveKit Agents, Retell AI, ElevenLabs, Deepgram, and Bland AI across latency, pricing, managed inference, and real-world developer use cases.]]></description><link>https://www.videosdk.live/blog/top-ai-voice-agent-platforms-developers</link><guid isPermaLink="false">6a214eab55831517a5a9fe01</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 04 Jun 2026 12:35:46 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-4--2026--05_58_44-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>The best AI voice agent platforms for developers in 2026 are <strong>VideoSDK</strong>, Vapi, LiveKit Agents, Retell AI, ElevenLabs Conversational AI, Deepgram Voice Agent API, Synthflow and Bland AI. VideoSDK leads for developers who need a unified voice-plus-video infrastructure with fully managed inference, while Vapi offers maximum component flexibility, LiveKit suits infrastructure-owning teams, and ElevenLabs wins on voice quality. The right platform depends on your latency budget, compliance requirements, and whether you want a managed pipeline or a bring-your-own-stack approach.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-4--2026--05_58_44-PM.png" alt="Top AI Voice Agent Platforms for Developers in 2026"/><p>Voice AI is no longer a prototype experiment. The global voice AI agents market crossed <strong>$22 billion in 2026</strong>, growing at a <a href="https://market.us/report/voice-ai-agents-market/" rel="noreferrer nofollow">34.8% CAGR</a>, and Gartner projects <a href="https://www.gartner.com/en/newsroom/press-releases/2022-08-31-gartner-predicts-conversational-ai-will-reduce-contac" rel="nofollow noreferrer">contact centers will save $80 billion</a> this year from conversational AI alone. If you are building an app that needs to listen, reason, and respond, the platform you choose will determine your latency, your cost structure, and how fast you ship to production.</p><p>This guide evaluates seven leading AI voice agent platforms, with detailed coverage of features, pipeline architecture, pricing, and real-world developer considerations for 2026.</p><h2 id="what-is-an-ai-voice-agent-platform">What Is an AI Voice Agent &amp; Platform?</h2><p>An&nbsp;<a href="https://www.videosdk.live/voice-agents" rel="noreferrer"><strong>AI voice agent</strong></a>&nbsp;is a software application powered by artificial intelligence that can converse with humans using spoken language. Unlike traditional robotic phone systems, where you have to say specific keywords or "Press 1 for customer service," modern AI voice agents allow you to speak naturally, just as you would to another person.</p><p>An AI voice agent platform is defined as an infrastructure layer that connects speech recognition, language model reasoning, and voice synthesis into a real-time conversational pipeline. It works by accepting raw audio from a user, transcribing it to text (STT), processing the text through a large language model (LLM), and converting the response back to spoken audio (TTS), all within a latency window that keeps the conversation feeling human.</p><p>The core technical stack inside every AI voice agent platform includes:</p><ul><li><a href="https://www.videosdk.live/developer-hub/stt/speech-to-text" rel="noreferrer"><strong>Speech-to-Text (STT)</strong></a><strong>:</strong> Converts live audio to text for LLM processing</li><li><a href="https://www.videosdk.live/developer-hub/llm/what-is-a-llm" rel="noreferrer"><strong>Large Language Model (LLM)</strong></a><strong>:</strong> Reasons over the transcript and generates a response</li><li><a href="https://www.videosdk.live/developer-hub/tts/what-is-text-to-speech" rel="noreferrer"><strong>Text-to-Speech (TTS)</strong></a><strong>:</strong> Synthesizes the response into natural-sounding audio</li><li><a href="https://www.videosdk.live/industry-hub/blogs/what-is-vad" rel="noreferrer"><strong>Voice Activity Detection (VAD)</strong></a><strong>:</strong> Determines when the user has finished speaking</li><li><a href="https://www.videosdk.live/industry-hub/blogs/what-is-voice-turn-detector" rel="noreferrer"><strong>Turn Detection</strong></a><strong>:</strong> Manages interruptions and conversational flow</li><li><a href="https://www.videosdk.live/developer-hub/webtransport/webrtc-vs-webtransport" rel="noreferrer"><strong>Transport Layer</strong></a><strong>:</strong> Delivers audio in real time, typically over WebRTC</li></ul><p>The fundamental distinction between platforms is whether they provide a <strong>managed, integrated stack</strong> (you get one API, they manage each component) or an <strong>orchestration layer</strong> (you bring your own STT, LLM, and TTS providers and the platform wires them together). Each approach trades control against operational simplicity.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-4--2026--04_16_44-PM.png" class="kg-image" alt="Top AI Voice Agent Platforms for Developers in 2026" loading="lazy" width="1693" height="929"><figcaption><span style="white-space: pre-wrap;">AI voice agent pipeline overview</span></figcaption></img></figure><h2 id="why-latency-is-the-only-metric-that-matters">Why Latency Is the Only Metric That Matters</h2><p>Sub-500ms perceived <a href="https://www.videosdk.live/developer-hub/webtransport/low-latency" rel="noreferrer">latency</a> separates a voice agent from an IVR. Below 300ms feels human. Between 300ms and 600ms is sluggish but acceptable. Above 600ms, users revert to press-key mental models and start tapping buttons.</p><p>According to production data published by <a href="https://hamming.ai/resources/best-voice-agent-stack" rel="nfollow onoreferrer">Hamming AI</a>, which analyzed over 4 million voice agent calls across 10,000+ agents in 2025–2026, published industry medians sit around 1.4–1.7 seconds, and p99 runs 3–5 seconds. The 500ms benchmark is achievable, but only with streaming at every component, co-located infrastructure, and a disciplined model selection strategy.</p><p>Every platform review below includes latency benchmarks drawn from 2026 production data.</p><h2 id="the-7-best-ai-voice-agent-platforms-for-developers-in-2026">The 7 Best AI Voice Agent Platforms for Developers in 2026</h2><h3 id="1-videosdk-%E2%80%94-best-for-developers">1. VideoSDK — Best for Developers </h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/Screenshot-2026-06-04-163523.png" class="kg-image" alt="Top AI Voice Agent Platforms for Developers in 2026" loading="lazy" width="1522" height="727"/></figure><p><strong>VideoSDK is the most complete real-time AI communication infrastructure for developers who want managed inference, full pipeline flexibility, and native video support in a single SDK.</strong></p><p>VideoSDK launched its&nbsp;<a href="https://github.com/videosdk-live/agents/commit/main" rel="noreferrer"><strong>Agents SDK</strong></a><strong> v1.0.0</strong>&nbsp;in March 2026, marking a complete architectural shift for the platform. The release unified two previously separate execution models,&nbsp;<code>CascadingPipeline</code>&nbsp;(STT → LLM → TTS) and&nbsp;<code>RealtimePipeline</code>&nbsp;(speech-to-speech), into a single&nbsp;<code>Pipeline</code>&nbsp;class that automatically detects the optimal execution mode based on the components you provide.</p><h4 id="three-pipeline-modes-one-unified-api">Three Pipeline Modes, One Unified API</h4><p>This is what separates VideoSDK from every other platform on this list. You do not choose between a managed pipeline and a custom stack, you configure what you need, and VideoSDK selects the mode:</p><ul><li><strong>Cascade Mode:</strong>&nbsp;Full STT → LLM → TTS control. Bring any combination of Deepgram, OpenAI Whisper, Google, or custom STT models; wire in any LLM including OpenAI GPT, Anthropic Claude, Google Gemini, AWS Nova, or xAI Grok; choose ElevenLabs, Cartesia Sonic, or Deepgram TTS for voice output. You own every component selection.</li><li><strong>Realtime Mode:</strong>&nbsp;Provide a speech-to-speech model (OpenAI Realtime API, Google Gemini Live, AWS Nova Sonic) and the pipeline collapses to its lowest-latency configuration automatically.</li><li><strong>Hybrid Mode:</strong>&nbsp;Combine a realtime model with a custom external STT or TTS, a use case that was architecturally impossible on the previous framework. For example: use Google Gemini Live as the LLM but swap in a custom ElevenLabs voice instead of the model's built-in TTS.</li></ul><h4 id="managed-inference-the-infrastructure-differentiator">Managed Inference: The Infrastructure Differentiator</h4><p>In January 2026, VideoSDK launched&nbsp;<a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference" rel="noreferrer"><strong>managed inference</strong></a>, allowing developers to run complete voice agent pipelines through the VideoSDK Gateway without managing multiple AI provider accounts, API keys, or rate limits. You can now run STT, LLM, TTS, and realtime models directly inside your pipeline through a single dashboard, the&nbsp;<a href="https://docs.videosdk.live/ai_agents/agent-runtime/build-agent" rel="noreferrer"><strong>Agent Runtime</strong></a><strong> Dashboard,</strong> eliminating the multi-vendor billing overhead that affects Vapi and LiveKit deployments.</p><p>Managed inference also includes:</p><ul><li><strong>Built-in </strong><a href="https://docs.videosdk.live/ai_agents/core-components/de-noise" rel="noreferrer"><strong>denoising</strong></a>&nbsp;via Krisp, ai-coustics, and Sanas</li><li><a href="https://docs.videosdk.live/ai_agents/core-components/voice-mail-detection" rel="noreferrer"><strong>Voicemail Detection</strong></a>&nbsp;for outbound calls, so agents leave messages instead of speaking into silence</li><li><a href="https://docs.videosdk.live/ai_agents/core-components/fallback-adapter" rel="noreferrer"><strong>Provider Fallback</strong></a>&nbsp;for production resilience (if your primary LLM endpoint goes down, the agent automatically switches to a fallback)</li><li><a href="https://docs.videosdk.live/conversational_graph/introduction" rel="noreferrer"><strong>Conversational Graphs</strong></a>&nbsp;for multi-step dialogue flows with state management</li><li><strong>First-party phone numbers</strong>&nbsp;via VideoSDK Phone Numbers, connecting agents directly to the PSTN without a separate Twilio or Vonage account</li></ul><h4 id="agent-participant-sdk-real-time-agent-state-in-your-ui">Agent Participant SDK: Real-Time Agent State in Your UI</h4><p>VideoSDK is the only platform that ships native&nbsp;<strong>AgentParticipant</strong>&nbsp;support across every client SDK, React, React Native, JavaScript, iOS, Flutter. When an agent joins a VideoSDK room, it registers as a distinct participant type. Your application can track agent lifecycle state (IDLE, LISTENING, THINKING, SPEAKING) in real time via the&nbsp;<code>AgentState</code>&nbsp;enum and receive live transcription with timestamps.</p><p>This is what makes VideoSDK the right choice when you are building a customer-facing product with a visual interface, not just an IVR replacement. Your front-end can show a speaking indicator, display transcripts inline, or trigger UI state changes when the agent finishes reasoning.</p><h4 id="videosdk-for-existing-video-applications">VideoSDK for Existing Video Applications</h4><p>No other platform on this list natively embeds voice agents into a video call. If you are already using VideoSDK for WebRTC video healthcare telemedicine, HR interviewing tools, fintech KYC, edtech tutoring adding an AI voice agent requires one additional SDK module, not a separate infrastructure vendor.</p><h4 id="developer-experience-and-pricing">Developer Experience and Pricing</h4><p>VideoSDK's open-source Python agents framework is available at&nbsp;<a href="https://github.com/videosdk-live/agents">github.com/videosdk-live/agents</a>. New accounts receive&nbsp;<strong>$20 in free credits</strong>&nbsp;to test voice agents without a credit card. The platform supports LangChain and LangGraph integration for multi-step reasoning workflows and ships <a href="https://docs.videosdk.live/ai_agents/a2a/overview" rel="noreferrer">Agent-to-Agent (A2A)</a> multi-agent routing out of the box.</p><p>Enterprise customers receive dedicated infrastructure, custom SLA guarantees, and on-premises deployment options.</p><p><strong>Best for:</strong>&nbsp;Development teams building customer-facing AI voice applications that need video, voice, and AI in a single SDK; teams who want managed inference without multi-vendor billing; products that combine WebRTC calls with AI agent participants.</p><p><strong>Start building:</strong>&nbsp;<a href="https://app.videosdk.live/signup" rel="noreferrer"><strong>Sign up now</strong></a>.</p><h3 id="2-vapi-%E2%80%94-best-for-maximum-developer-configurability">2. Vapi — Best for Maximum Developer Configurability</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/Screenshot-2026-06-04-163932.png" class="kg-image" alt="Top AI Voice Agent Platforms for Developers in 2026" loading="lazy" width="1517" height="687"/></figure><p><strong>Vapi is the most developer-configurable voice orchestration platform, ideal for engineering teams that want to swap every component in the pipeline independently.</strong></p><p>Vapi acts as a pure orchestration middleware. You provide your own API keys for STT (Deepgram, AssemblyAI, Whisper), LLM (any OpenAI-compatible endpoint, Anthropic Claude, Gemini), and TTS (ElevenLabs, <a href="https://docs.videosdk.live/ai_agents/plugins/tts/cartesia-tts" rel="noreferrer">Cartesia</a>, OpenAI TTS). Vapi routes audio through the pipeline and handles turn detection, interruption logic, and telephony.</p><p>Its&nbsp;<strong>Squads</strong>&nbsp;feature lets you chain multiple specialized agents within a single call — a greeting agent hands off to a qualification agent, which hands off to a booking agent — without the user experiencing a call transfer.</p><p><strong>Latency:</strong>&nbsp;700–1,500ms depending on the component stack. With the optimized configuration (Deepgram Nova-3 STT + GPT-4o mini + ElevenLabs Flash), published benchmarks show ~550ms consistently.</p><p><strong>Pricing:</strong>&nbsp;$0.05/min platform fee. Total all-in cost (including STT + LLM + TTS) typically lands between $0.13 and $0.31/min in production, depending on model selections.</p><p><strong>Best for:</strong>&nbsp;Engineering teams with dedicated DevOps resources who want maximum control over cost optimization through model swapping; multi-agent orchestration use cases.</p><p><strong>Limitation:</strong>&nbsp;Multi-vendor billing overhead and integration complexity increase as you add providers. Production monitoring is self-managed.</p><h3 id="3-livekit-agents-%E2%80%94-best-for-open-source-infrastructure-owners">3. LiveKit Agents — Best for Open-Source Infrastructure Owners</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/Screenshot-2026-06-04-164047.png" class="kg-image" alt="Top AI Voice Agent Platforms for Developers in 2026" loading="lazy" width="1516" height="695"/></figure><p><strong>LiveKit Agents is the infrastructure-first choice: an open-source, WebRTC-native agent framework used by OpenAI for ChatGPT Voice Mode and by tens of thousands of developers worldwide.</strong></p><p>LiveKit is defined as an open-source real-time communication platform built on WebRTC, with the Agents framework providing an orchestration layer for AI-powered voice and video agents. It handles media routing through a <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu" rel="noreferrer">Selective Forwarding Unit (SFU)</a>, which routes audio between participants without requiring peer-to-peer connections at scale.</p><p>According to Fora Soft's 2026 production analysis, <a href="https://www.forasoft.com/blog/article/livekit-ai-agents-guide#:~:text=at%20roughly%205%E2%80%9310%25%20of%20the%20cost%20of%20a%20human%2Dstaffed%20call%20centre" rel="nofollow noreferrer">LiveKit handles roughly 5–10% of the cost of a human-staffed call center</a> at sub-second latency for properly configured stacks. The platform has over 12,000 GitHub stars and 1,000+ forks.</p><p><strong>Latency:</strong>&nbsp;450ms achievable with streaming at every layer, co-located infrastructure, and optimized model selection. Industry-published p50 sits at approximately 500–700ms in production.</p><p><strong>Pricing:</strong>&nbsp;LiveKit Cloud Agents charges approximately $0.01/min platform fee, with model costs passed through at vendor rates, the lowest platform overhead on this list.</p><p><strong>Best for:</strong>&nbsp;Teams who want to self-host and own the entire infrastructure stack; developers comfortable managing SFU servers on AWS or GCP; open-source community projects.</p><p><strong>Limitation:</strong>&nbsp;Requires significant DevOps investment to operate at scale. No managed inference or built-in telephony, you wire up Twilio or similar yourself.</p><h3 id="4-retell-ai-%E2%80%94-best-for-production-call-center-replacement">4. Retell AI — Best for Production Call Center Replacement</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/Screenshot-2026-06-04-164124.png" class="kg-image" alt="Top AI Voice Agent Platforms for Developers in 2026" loading="lazy" width="1520" height="732"/></figure><p><strong>Retell AI is the strongest end-to-end platform for developers building production inbound voice agents focused on call center automation, with industry-leading turn-taking quality and enterprise monitoring.</strong></p><p>Retell AI provides an integrated platform with structured conversation flow builders, warm call transfers, auto-synced knowledge bases, and multilingual support. Its <a href="https://www.g2.com/products/retell-ai/reviews" rel="nofollow noreferrer">G2 rating of 4.8/5 from over 2,400 verified reviews</a> (named G2's 2026 Best Agentic AI Software) reflects deployment success across healthcare, financial services, and customer support.</p><p>Medical Data Systems processes approximately 30,000 calls per month using Retell AI's analytics platform, demonstrating production viability at scale.</p><p><strong>Latency:</strong>&nbsp;600–800ms in 2026 benchmarks, with consistent turn-taking quality on long conversations that outperforms Vapi on multi-minute calls.</p><p><strong>Pricing:</strong>&nbsp;Hybrid model combining subscription tiers with per-minute usage. STT/ASR starts at approximately $0.008/min, with LLM costs on top at approximately $0.0001 per 1,000 tokens.</p><p><strong>Best for:</strong>&nbsp;Healthcare and financial services developers who need compliance monitoring and call analytics; teams replacing legacy IVR systems with conversational AI.</p><p><strong>Limitation:</strong>&nbsp;Less flexibility than Vapi for custom component swapping; fewer templates for non-call-center use cases.</p><h3 id="5-elevenlabs-conversational-ai-%E2%80%94-best-for-voice-quality-first-applications">5. ElevenLabs Conversational AI — Best for Voice Quality-First Applications</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/Screenshot-2026-06-04-164204.png" class="kg-image" alt="Top AI Voice Agent Platforms for Developers in 2026" loading="lazy" width="1517" height="726"/></figure><p><strong>ElevenLabs Conversational AI delivers the most realistic, emotionally expressive synthetic voices available in 2026, built on the company's industry-leading TTS platform.</strong></p><p><a href="https://elevenlabs.io/blog/series-d" rel="nofollow noreferrer">ElevenLabs raised $500 million in its Series D</a> in February 2026 at an $11 billion valuation, signaling investor confidence in its voice synthesis dominance. The Conversational AI product adds turn-taking, interruption handling, RAG against custom documents, and bring-your-own-LLM support on top of the core TTS engine.</p><p>In multilingual use cases, French, Spanish, Arabic, and 26 additional languages, ElevenLabs voices are noticeably more natural than what competing platforms ship by default.</p><p><strong>Latency:</strong>&nbsp;Flash v2.5 TTS delivers 75ms latency, among the lowest on this list. End-to-end measured latency runs 620–840ms depending on configuration.</p><p><strong>Pricing:</strong>&nbsp;$0.08–$0.24/min for Conversational AI, depending on plan tier. Starter plans begin at $22/month. Enterprise plans required for production concurrency limits.</p><p><strong>Best for:</strong>&nbsp;Premium customer experiences, concierge agents, brand-forward interfaces, and multilingual deployments where voice realism is the primary differentiator.</p><p><strong>Limitation:</strong>&nbsp;The conversation management tooling is less mature than Retell or Vapi for complex multi-step agent workflows. Telephony integration is functional but less battle-tested.</p><h4 id="6-synthflow-%E2%80%94-best-for-non-technical-teams-and-agencies">6. Synthflow — Best for Non-Technical Teams and Agencies</h4><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/Screenshot-2026-06-04-170723.png" class="kg-image" alt="Top AI Voice Agent Platforms for Developers in 2026" loading="lazy" width="1516" height="728"/></figure><p><strong>Synthflow is the fastest path from zero to a live voice agent for teams without engineering resources, combining a no-code drag-and-drop builder with bundled premium AI components and white-label agency tooling.</strong></p><p>Synthflow AI is a scalable voice AI platform that combines a no-code workflow builder, real-time personalization, and strong CRM integrations. It supports HIPAA compliance, inbound routing, and multi-tenant setups, making it especially attractive for agencies and teams running multiple clients on a single system.</p><p><strong>Latency:</strong>&nbsp;500–800ms in production, driven by the bundled pipeline architecture.</p><p><strong>Pricing:</strong>&nbsp;$0.050–$0.163/min for the Voice Agent API bundle, with concurrency-metered billing at scale.</p><p><strong>Best for:</strong>&nbsp;Marketing teams, agencies, and SMBs that need a production voice agent live in hours without writing code; multi-client agency deployments that require white-label branding and subaccount billing.</p><p><strong>Limitation:</strong>&nbsp;Less customizable than Vapi, VideoSDK, or LiveKit for developers who need to swap model components or build custom pipeline logic. The free trial is limited to 10–20 minutes of calls, which is too short to fully stress-test an agent before committing to a paid plan.</p><h3 id="7-deepgram-voice-agent-api-%E2%80%94-best-for-noisy-environment-accuracy">7. Deepgram Voice Agent API — Best for Noisy Environment Accuracy</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/Screenshot-2026-06-04-170756.png" class="kg-image" alt="Top AI Voice Agent Platforms for Developers in 2026" loading="lazy" width="1517" height="723"/></figure><p><strong>Deepgram's Voice Agent API bundles the Nova-3 STT engine, the industry leader for real-time accuracy in noisy environments, with full agent functionality at a predictable all-in rate.</strong></p><p>Deepgram <a href="https://deepgram.com/learn/introducing-nova-3-speech-to-text-api#boosting-streaming-accuracy-with-nova-3" rel="nofollow noreferrer">Nova-3 achieves 6.84% word error rate (WER)</a> in independent benchmarks from Hamming AI's analysis of 4M+ production calls, and supports 36 languages with excellent noise robustness. The bundled Voice Agent API pricing eliminates the LLM pass-through surprise cost that Vapi and LiveKit deployments frequently encounter.</p><p><strong>Latency:</strong> Under 300ms for STT alone; end-to-end varies by LLM selection.</p><p><strong>Pricing:</strong> $0.050–$0.163/min for the Voice Agent API bundle, with concurrency-metered billing at scale.</p><p><strong>Best for:</strong> Contact centers handling calls from noisy environments (warehouses, retail floors, outdoor); developers requiring on-premises deployment for data sovereignty; healthcare teams needing HIPAA-compliant infrastructure with a verified BAA.</p><p><strong>Limitation:</strong> Concurrency-metered billing requires committed capacity planning, which changes cost economics compared to pure pay-as-you-go alternatives.</p><h3 id="8-bland-ai-%E2%80%94-best-for-cost-optimized-outbound-at-scale">8. Bland AI — Best for Cost-Optimized Outbound at Scale</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/Screenshot-2026-06-04-170836.png" class="kg-image" alt="Top AI Voice Agent Platforms for Developers in 2026" loading="lazy" width="1517" height="728"/></figure><p><strong>Bland AI is purpose-built for outbound voice campaigns at the lowest per-minute all-in pricing on this list, with bundled telephony included.</strong></p><p>Bland AI bundles STT, LLM, TTS, and telephony into a single per-minute rate, eliminating the multi-vendor billing complexity that plagues assembled stacks. On-premises deployment is available for organizations with strict data residency requirements.</p><p><strong>Latency:</strong>&nbsp;Sub-second for standard configurations; the bundled architecture avoids inter-component network hops that inflate latency on separated stacks.</p><p><strong>Pricing:</strong>&nbsp;$0.11–$0.14/min all-in, including telephony. No separate LLM or TTS provider accounts needed.</p><p><strong>Best for:</strong>&nbsp;Outbound sales campaigns, appointment reminder pipelines, and lead qualification at volume where cost-per-minute economics drive platform selection.</p><p><strong>Limitation:</strong>&nbsp;Less customizable than Vapi or VideoSDK for complex agent behaviors; voice quality is below ElevenLabs-tier for premium use cases.</p><h2 id="platform-comparison-table">Platform Comparison Table</h2><table>
<thead>
<tr>
<th>Feature</th>
<th>VideoSDK</th>
<th>Vapi</th>
<th>LiveKit Agents</th>
<th>Retell AI</th>
<th>ElevenLabs Conv. AI</th>
<th>Synthflow</th>
<th>Deepgram</th>
<th>Bland AI</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Pipeline Type</strong></td>
<td>Managed + BYOK</td>
<td>BYOK orchestration</td>
<td>Open-source BYOK</td>
<td>Managed</td>
<td>Managed</td>
<td>Managed bundle (no-code)</td>
<td>Managed bundle</td>
<td>Managed bundle</td>
</tr>
<tr>
<td><strong>Latency (P50)</strong></td>
<td>~500ms</td>
<td>700–1,500ms</td>
<td>450–700ms</td>
<td>600–800ms</td>
<td>620–840ms</td>
<td>500–800ms</td>
<td>&lt;300ms STT</td>
<td>Sub-1s</td>
</tr>
<tr>
<td><strong>Managed Inference</strong></td>
<td>Yes</td>
<td>No</td>
<td>No</td>
<td>Partial</td>
<td>Yes</td>
<td>Yes (bundled)</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<td><strong>Video + Voice</strong></td>
<td>Yes (native)</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td><strong>Open Source</strong></td>
<td>Framework only</td>
<td>No</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td><strong>Agent Participants UI</strong></td>
<td>Yes (all SDKs)</td>
<td>No</td>
<td>Partial</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td><strong>Hybrid Pipeline Mode</strong></td>
<td>Yes</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td><strong>Native Telephony</strong></td>
<td>Yes (VideoSDK Numbers)</td>
<td>Via Twilio/Vonage</td>
<td>Via Twilio/Vonage</td>
<td>Yes</td>
<td>Partial</td>
<td>Yes (included + BYOC)</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td><strong>Multilingual Support</strong></td>
<td>Yes</td>
<td>Depends on providers</td>
<td>Depends on providers</td>
<td>Yes</td>
<td>29+ languages</td>
<td>Via ElevenLabs</td>
<td>36 languages</td>
<td>Limited</td>
</tr>
<tr>
<td><strong>HIPAA / Compliance</strong></td>
<td>Enterprise</td>
<td>Enterprise</td>
<td>Self-hosted</td>
<td>Enterprise</td>
<td>Enterprise only</td>
<td>Yes</td>
<td>Yes, BAA available</td>
<td>On-prem option</td>
</tr>
<tr>
<td><strong>Free Tier / Trial</strong></td>
<td>$20 free credits</td>
<td>1,000 free min/mo</td>
<td>Open-source</td>
<td>Available</td>
<td>10,000 chars/mo</td>
<td>10–20 min trial</td>
<td>$200 credits</td>
<td>Available</td>
</tr>
<tr>
<td><strong>Pricing (platform fee)</strong></td>
<td>Usage-based</td>
<td>$0.05/min</td>
<td>$0.01/min</td>
<td>Hybrid</td>
<td>$0.08–0.24/min</td>
<td>$0.08/min PAYG; plans from $29/mo</td>
<td>$0.05–0.163/min</td>
<td>$0.11–0.14/min</td>
</tr>
<tr>
<td><strong>Best For</strong></td>
<td>Voice + Video + AI</td>
<td>Max flexibility</td>
<td>Infra owners</td>
<td>Call centers</td>
<td>Voice quality</td>
<td>Agencies, non-technical teams</td>
<td>Noisy environments</td>
<td>Outbound scale</td>
</tr>
</tbody>
</table>
<p><strong>Table note:</strong>&nbsp;Latency benchmarks reflect production P50 from 2026 independent data. All-in costs include STT + LLM + TTS on BYOK platforms; bundled platforms include these in the listed rate. Verify pricing at each vendor's current pricing page before production commitment, as rates evolve frequently.</p><h2 id="how-to-choose-an-ai-voice-agent-platform-in-2026">How to Choose an AI Voice Agent Platform in 2026</h2><p><strong>The right AI voice agent platform is determined by three variables: your latency budget, your compliance requirements, and whether you want to own the infrastructure or delegate it.</strong></p><p>Use this decision framework:</p><h3 id="step-1-define-your-latency-budget">Step 1: Define Your Latency Budget</h3><p>Below 500ms perceived latency is the production standard in 2026. If your use case involves emotional conversations (mental health, patient care, premium sales) where every pause registers, target under 300ms and evaluate VideoSDK's Realtime Mode or LiveKit with co-located infrastructure. For standard customer service automation, 500–800ms is acceptable and gives you more model flexibility.</p><h3 id="step-2-assess-compliance-requirements">Step 2: Assess Compliance Requirements</h3><p>Healthcare and financial services teams should shortlist VideoSDK (Enterprise), Deepgram (BAA available), and Retell AI (monitoring capabilities) as primary options. Teams needing on-premises deployment for data residency should evaluate Deepgram, Bland AI, or self-hosted LiveKit.</p><h3 id="step-3-match-platform-architecture-to-your-team-shape">Step 3: Match Platform Architecture to Your Team Shape</h3><ul><li><strong>Small engineering team, fast shipping:</strong>&nbsp;VideoSDK managed inference or ElevenLabs Conversational AI</li><li><strong>Large engineering team, maximum control:</strong>&nbsp;Vapi or LiveKit Agents with self-managed STT/LLM/TTS</li><li><strong>Call center replacement, enterprise monitoring:</strong>&nbsp;Retell AI</li><li><strong>Outbound campaigns at scale:</strong>&nbsp;Bland AI</li><li><strong>Accuracy-critical environments:</strong>&nbsp;Deepgram Voice Agent API</li></ul><h3 id="step-4-calculate-total-cost-not-platform-fee">Step 4: Calculate Total Cost, Not Platform Fee</h3><p>Platform fees are the smallest part of your per-minute cost. Add STT (approximately $0.005–$0.012/min), LLM (varies widely), TTS (approximately $0.005–$0.04/min), and telephony (approximately $0.01–$0.02/min). For assembled stacks, total production cost typically runs $0.13–$0.31/min. Bundled platforms like Bland AI and managed platforms like VideoSDK eliminate the accounting overhead of reconciling four separate provider bills.</p><h2 id="real-world-example-building-a-telecom-support-agent-with-videosdk">Real-World Example: Building a Telecom Support Agent with VideoSDK</h2><p>A mid-sized telecom operator deploying an AI support agent with VideoSDK typically follows this implementation path:</p><ol><li><strong>Initialize the Agent Session</strong>&nbsp;using VideoSDK's Python SDK, connecting a Pipeline in Cascade Mode with Deepgram Nova-3 for STT, Anthropic Claude Haiku for the LLM, and ElevenLabs Flash for TTS</li><li><strong>Configure Pipeline Hooks</strong>&nbsp;using the decorator-based&nbsp;<code>@pipeline.on(...)</code>&nbsp;system to intercept transcripts before LLM inference, enabling custom intent classification or PII redaction</li><li><strong>Enable Voicemail Detection</strong>&nbsp;for outbound callbacks so the agent leaves structured messages instead of silent hang-ups</li><li><strong>Deploy using VideoSDK's YAML-based cloud deployment</strong>&nbsp;(<code>deploy: cloud: true</code>), which handles container orchestration and scaling without Kubernetes management</li><li><strong>Track agent state</strong>&nbsp;in the front-end using&nbsp;<code>onAgentStateChange</code>&nbsp;events to display a speaking indicator and live transcript to support supervisors monitoring calls</li></ol><p>The same agent, once deployed, handles common inquiries, assists with troubleshooting, and escalates complex cases to human agents, with the STT, LLM, and TTS components upgradeable independently as model performance improves, without rebuilding the agent from scratch.</p><h2 id="key-statistics-on-ai-voice-agent-platforms-in-2026">Key Statistics on AI Voice Agent Platforms in 2026</h2><ul><li>The global voice AI agents market is valued at <a href="https://market.us/press-release/voice-ai-agents-market/#:~:text=USD%202.4%20billion%20in%202024" rel="noreferrer nofollow">$2.4 billion in 2024</a> and projected to reach $47.5 billion by 2034 at a 34.8% CAGR (<a href="https://market.us/press-release/voice-ai-agents-market/" rel="noreferrer">Market.us, 2024</a>)</li><li>Gartner forecasts conversational AI will reduce contact center agent labor costs by $80 billion in 2026 (<a href="https://www.gartner.com/en/newsroom/press-releases/2022-08-31-gartner-predicts-conversational-ai-will-reduce-contac" rel="noreferrer">Gartner, 2026</a>)</li><li>Voice AI costs approximately $0.40 per call compared to $7–$12 per call for human agents, a 90–95% cost reduction per automated interaction (<a href="https://www.teneo.ai/blog/voice-ai-reduce-costs" rel="nofollow noreferrer">Teneo.ai, 2026</a>)</li><li><a href="https://hamming.ai/resources/voice-agent-evaluation-metrics-guide" rel="noreferrer nofollow">Hamming AI's</a> analysis of 4M+ production calls shows industry median latency at 1.4–1.7 seconds P50, with P99 at 3–5 seconds, underscoring why platform and infrastructure selection directly determines user experience quality</li><li>80% of businesses plan to integrate AI-driven voice technology into customer service by 2026 (<a href="https://www.nextiva.com/blog/conversational-ai-statistics.html#:~:text=81%25%20of%20businesses%20say%20they%20plan%20to%20invest%20in%20AI%20technologies%20for%20customer%20experience%20in%202025%20and%20beyond.%20(Nextiva)" rel="noreferrer nofollow">Nextiva, 2025</a>)</li><li>Voice AI agent deployments grew 340% year-over-year across production environments (<a href="https://aivoiceresearch.com/voice-agents-2026/" rel="nofollow noreferrer">Forrester, 2026</a>)</li><li>Companies using voice AI report a 3-year ROI between 331% and 391% (<a href="https://aivoiceresearch.com/voice-agents-2026/" rel="nofollow noreferrer">Forrester Consulting / PolyAI, 2026</a>)</li></ul><h2 id="definitions-glossary">Definitions Glossary</h2><p><a href="https://www.videosdk.live/developer-hub/stt/speech-to-text" rel="noreferrer"><strong>STT (Speech-to-Text)</strong></a><strong>:</strong>&nbsp;A machine learning model that converts live audio input into text transcripts in real time, serving as the first processing stage in an AI voice agent pipeline.</p><p><a href="https://www.videosdk.live/industry-hub/blogs/what-is-vad" rel="noreferrer"><strong>VAD (Voice Activity Detection)</strong></a><strong>:</strong>&nbsp;A signal processing algorithm that detects when a user has started or stopped speaking, enabling the pipeline to trigger STT transcription and manage conversational turn-taking.</p><p><a href="https://www.videosdk.live/developer-hub/tts/what-is-text-to-speech" rel="noreferrer"><strong>TTS (Text-to-Speech)</strong></a><strong>:</strong>&nbsp;A neural synthesis model that converts text output from an LLM into natural-sounding spoken audio, representing the final output stage of a voice agent pipeline.</p><p><a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu" rel="noreferrer"><strong>SFU (Selective Forwarding Unit)</strong></a><strong>:</strong>&nbsp;A server-side WebRTC component that routes media streams between participants without requiring peer-to-peer connections, enabling multi-participant voice and video at scale.</p><p><a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference" rel="noreferrer"><strong>Managed Inference</strong></a><strong>:</strong>&nbsp;A platform capability that runs STT, LLM, and TTS models through a single provider gateway, eliminating the need for developers to manage separate API keys, rate limits, and billing accounts for each AI component.</p><p><a href="https://docs.videosdk.live/ai_agents/core-components/pipeline-hooks" rel="noreferrer"><strong>Pipeline Hooks</strong></a><strong>:</strong>&nbsp;A middleware system in agent frameworks that allows developers to intercept, inspect, and transform data at specific stages of the voice processing pipeline without modifying the core architecture.</p><h2 id="key-takeaways">Key Takeaways</h2><ul><li><strong>VideoSDK is the only platform on this list that natively unifies voice AI agents with video calls</strong>, making it the clear choice for any product that combines WebRTC communication with conversational AI.</li><li><strong>Managed inference is the 2026 differentiator</strong>: platforms that handle STT, LLM, and TTS through a single gateway (VideoSDK, ElevenLabs, Deepgram) eliminate the multi-vendor billing complexity that compounds operational overhead on assembled stacks.</li><li><strong>Latency is a deployment problem, not a model problem</strong>: the same models perform differently depending on infrastructure co-location, streaming implementation, and VAD configuration. Published benchmarks require verification against your specific production audio before platform commitment.</li><li><strong>Compliance requirements narrow the field quickly</strong>: for HIPAA-covered entities, shortlist VideoSDK Enterprise, Deepgram (BAA available), or self-hosted LiveKit as the viable options; evaluate carefully before choosing a platform that does not have documented compliance pathways.</li><li><strong>The cheapest-per-minute platform is rarely the cheapest platform</strong>: assembled BYOK stacks like Vapi carry multi-vendor DevOps overhead, integration maintenance, and billing reconciliation costs that bundled or managed platforms absorb. Factor total engineering cost, not just API rates, into your build-vs-buy calculation.</li></ul><h2 id="conclusion">Conclusion</h2><p>The AI voice agent platforms available to developers in 2026 have matured from experimental SDKs to production infrastructure trusted by enterprise contact centers, healthcare networks, and consumer apps at scale. The right platform depends on what you are building.</p><p>For developers who want managed inference, a unified voice-and-video experience, and native agent participant tracking across every client SDK,&nbsp;<a href="https://www.videosdk.live/" rel="noreferrer"><strong>VideoSDK</strong></a>&nbsp;delivers the most complete developer infrastructure on the market. Start with the <a href="https://app.videosdk.live/login" rel="noreferrer">free $20 credit</a> tier, explore the open-source agents framework on GitHub, and deploy your first voice agent in under a day.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-best-ai-voice-agent-platform-for-developers-in-2026">What is the best AI voice agent platform for developers in 2026?</h3><p>The best AI voice agent platform for developers in 2026 depends on your use case. VideoSDK leads for teams that need voice, video, and AI agent infrastructure in a single SDK with managed inference. Vapi is best for engineering teams who want maximum component flexibility. Retell AI is strongest for call-center replacement with built-in monitoring. ElevenLabs Conversational AI delivers the highest voice quality for premium customer experiences. For most development teams shipping to production, VideoSDK's combination of managed inference, multi-pipeline support, and native UI integration provides the fastest path from prototype to production.</p><h3 id="how-do-ai-voice-agent-platforms-handle-latency">How do AI voice agent platforms handle latency?</h3><p>AI voice agent platforms reduce latency by streaming data at every processing stage, co-locating infrastructure, and selecting models with low time-to-first-token. In 2026, production P50 latency across platforms ranges from approximately 450ms (LiveKit, optimized configurations) to 700–1,500ms (Vapi, depending on component stack). VideoSDK's Realtime Mode, using speech-to-speech models like <a href="https://docs.videosdk.live/ai_agents/plugins/realtime/openai" rel="noreferrer">OpenAI Realtime</a> or <a href="https://docs.videosdk.live/ai_agents/plugins/realtime/google-live-api" rel="noreferrer">Google Gemini Live</a>, achieves the lowest latency by eliminating the separate STT and TTS hops. Sub-300ms latency feels human; anything above 1.5 seconds causes users to disengage.</p><h3 id="what-is-the-difference-between-vapi-and-videosdk">What is the difference between Vapi and VideoSDK?</h3><p>Vapi is a pure orchestration middleware that requires developers to bring their own STT, LLM, and TTS API keys and manage each vendor relationship independently. VideoSDK provides both managed inference (a single gateway for all AI components) and bring-your-own-key flexibility in the same unified SDK. VideoSDK also natively supports video calls alongside <a href="https://docs.videosdk.live/ai_agents/introduction" rel="noreferrer">voice agents</a>, something Vapi does not offer, and ships AgentParticipant support across all client SDKs so your front-end can track agent state in real time. Vapi's $0.05/min platform fee appears lower, but total all-in cost typically reaches $0.13–$0.31/min once STT, LLM, and TTS providers are added.</p><h3 id="how-much-do-ai-voice-agent-platforms-cost-per-minute-in-2026">How much do AI voice agent platforms cost per minute in 2026?</h3><p>AI voice agent platform costs in 2026 range from approximately $0.05/min (platform fee on Vapi, before STT/LLM/TTS) to $0.14/min all-in (Bland AI, bundled). Total all-in costs on BYOK orchestration platforms like Vapi typically land between $0.13 and $0.31/min once all components are included. Bundled platforms including Bland AI ($0.11–$0.14/min) and ElevenLabs Conversational AI ($0.08–$0.24/min) provide more predictable per-minute billing. Enterprise AI voice agents (high concurrency, SLA guarantees, custom deployments) typically involve annual commitments in the $40,000–$200,000+ range depending on volume.</p><h3 id="what-is-a-managed-inference-voice-agent-platform">What is a managed inference voice agent platform?</h3><p>A managed inference voice agent platform is one that runs STT, LLM, and TTS models through a single provider gateway, eliminating the need for developers to manage separate API keys, rate limits, billing accounts, and provider outages for each AI component. VideoSDK launched managed inference in January 2026, allowing developers to configure a complete voice pipeline through the Agent Runtime Dashboard without integrating Deepgram, OpenAI, and ElevenLabs as separate vendor accounts. This reduces both the operational complexity and the time-to-production for teams without dedicated AI infrastructure engineers.</p><h3 id="can-i-use-videosdk-for-both-voice-ai-agents-and-video-calls">Can I use VideoSDK for both voice AI agents and video calls?</h3><p>Yes. VideoSDK is the only platform on the 2026 market that natively integrates AI voice agents with WebRTC video calls. When an agent joins a VideoSDK room, it registers as an&nbsp;<code>AgentParticipant</code> a distinct participant type that your front-end can track, display transcripts for, and react to via real-time state events. This makes VideoSDK the natural choice for use cases where AI agents participate in video-enabled sessions: telemedicine appointments, HR interviews, financial advisory calls, and customer onboarding flows where a human-AI hybrid experience is the target.</p><h3 id="which-ai-voice-agent-platform-is-best-for-hipaa-compliance">Which AI voice agent platform is best for HIPAA compliance?</h3><p>For <a href="https://www.videosdk.live/blog/best-ai-voice-agents" rel="noreferrer">HIPAA-compliant voice AI agent</a> deployments, the shortlist includes VideoSDK Enterprise (with custom compliance configurations), Deepgram (BAA available, self-hosted deployment option), and self-hosted LiveKit (infrastructure fully under your control). Retell AI and Vapi both offer enterprise plans with compliance features, but HIPAA BAA availability should be verified directly with each vendor before production deployment. ElevenLabs restricts HIPAA compliance to the Agents platform on the Enterprise tier only. Healthcare teams should validate current BAA terms with any vendor, as compliance offerings evolve with regulatory guidance.</p>]]></content:encoded></item><item><title><![CDATA[Best AI Voice Agents & Platforms in 2026 | Tested & Ranked]]></title><description><![CDATA[The AI voice agent market hit $2.54B in 2025 and is growing at 39% CAGR. This guide ranks the 10 best platforms in 2026 by latency, pricing, and compliance.]]></description><link>https://www.videosdk.live/blog/best-ai-voice-agents</link><guid isPermaLink="false">6899d5cd64df6f042b4d4164</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 01 Jun 2026 12:06:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-11--2026--04_02_36-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TLDR: </strong><br>An <strong>AI voice agent</strong> is software that conducts spoken conversations autonomously by combining speech recognition, a language model, and voice synthesis.<strong> </strong><br>2026 marks the shift from pilot programs to full production deployments: LLM quality, telephony APIs, and compliance infrastructure have all matured to enterprise-grade standards.<br>This article covers definitions, an architecture diagram, platform-by-platform analysis, a full comparison table, 13 use case patterns, a selection decision framework, and an FAQ section.</br></br></br></blockquote><h2 id="introduction"><strong>Introduction</strong></h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-11--2026--04_02_36-PM.png" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked"/><p>Businesses that route customer calls through human agents for every routine inquiry face a structural cost problem: staffing scales linearly with call volume, while customer expectations for response speed continue to rise. AI voice agents address this by handling spoken interactions autonomously, answering questions, qualifying leads, booking appointments, and escalating to humans only when required.</p><p>The scale of adoption makes the business case clear. The <a href="https://www.grandviewresearch.com/industry-analysis/ai-voice-agents-market-report#:~:text=The%20global%20AI%20voice%20agents%20market%20size%20was%20estimated%20at%20USD%202.54%20billion%20in%202025%20and%20is%20projected%20to%20reach%20USD%2035.24%20billion%20by%202033%2C%20growing%20at%20a%20CAGR%20of%2039.0%25%20from%202026%20to%202033.%20The%20market%20is%20growing%20rapidly%20as%20voice%2Denabled%20technologies%20the%20increasingly%20adopted%20across%20industries." rel="noreferrer nofollow">global AI voice agents market was estimated at $2.54 billion in 2025</a> and is projected to reach $35.24 billion by 2033, growing at a compound annual growth rate of 39.0% (Grand View Research, 2025). Gartner projects that conversational AI will cut contact centre agent labour costs by <a href="https://ciosea.economictimes.indiatimes.com/news/next-gen-technologies/conversational-ai-will-reduce-contact-center-agent-labor-costs-by-80-bn-in-2026-gartner/93948390" rel="noreferrer nofollow">$80 billion in 2026</a>. In parallel, production voice agent deployments across organisations grew 340% year-over-year between 2023 and 2026 (AI Voice Research, cited in multiple 2026 market analyses).</p>
<!--kg-card-begin: html-->
<div style="position:relative;width:100%;overflow:hidden;border-radius:16px;
            background-image:linear-gradient(to right,#CDB6FF,#9333EA,#7E22CE);
            padding:32px;text-align:center;box-shadow:0 25px 50px -12px rgba(0,0,0,0.25);
            margin:20px;">
  
  <!-- Gradient Heading -->
  <h3 style="margin:0 auto;max-width:672px;font-size:32px;line-height:1.2;font-weight:800;
             letter-spacing:-0.02em;background:linear-gradient(to right,#ffffff,#E9D5FF);
             -webkit-background-clip:text;-webkit-text-fill-color:transparent;">
    Launch Your AI Voice Agent in <span style="color:#fff;">5 Minutes</span>
  </h3>
  
  <!-- Subheading -->
  <p style="margin-top:12px;margin-bottom:0;font-size:17px;line-height:1.6;color:#F3F4F6;">
    Build, customize, and scale AI voice agents with VideoSDK’s developer-friendly APIs and SDKs.
  </p>
  
  <!-- Button -->
  <div style="margin-top:24px;">
    <div style="display:inline-block;">
      <a href="https://docs.videosdk.live/ai_agents/voice-agent-quick-start" target="_blank" rel="noopener noreferrer" style="display:inline-block;font-size:16px;font-weight:600;text-decoration:none;">
        <span style="background:linear-gradient(to right,#ffffff,#E9D5FF);
                     padding:14px 36px;color:#111827;border-radius:12px;
                     box-shadow:0 4px 10px rgba(0,0,0,0.15);transition:all 0.3s ease;
                     display:inline-block;cursor:pointer;" onmouseover="this.style.boxShadow='0 0 20px rgba(205,182,255,0.9),0 0 40px rgba(147,51,234,0.7)'; 
                           this.style.transform='scale(1.05)'" onmouseout="this.style.boxShadow='0 4px 10px rgba(0,0,0,0.15)'; 
                          this.style.transform='scale(1)'">
          🚀 Get Started Now
        </span>
      </a>
    </div>
  </div>
</div> 

<!--kg-card-end: html-->
<h2 id="what-is-an-ai-voice-agent">What Is an AI Voice Agent?</h2><p>An <a href="https://www.videosdk.live/voice-agents" rel="noreferrer"><strong>AI voice agent</strong></a> is a software system that conducts real-time spoken conversations with humans by integrating four core technical layers: speech recognition, language understanding, response generation, and speech synthesis.</p><p><a href="https://www.videosdk.live/developer-hub/stt/what-is-automatic-speech-recognition" rel="noreferrer"><strong>Automatic speech recognition (ASR)</strong></a>, also called <a href="https://www.videosdk.live/developer-hub/stt/speech-to-text" rel="noreferrer"><strong>speech-to-text (STT)</strong></a>, converts incoming audio from the user into a text transcript. That transcript is passed to a <a href="https://www.ibm.com/think/topics/natural-language-processing" rel="noreferrer nofollow"><strong>natural language processing (NLP)</strong></a> module, which parses intent and context. A <a href="https://www.videosdk.live/developer-hub/llm/what-is-a-llm" rel="noreferrer"><strong>large language model (LLM)</strong></a> then generates a contextually appropriate response, often consulting external data through <a href="https://docs.videosdk.live/ai_agents/core-components/rag" rel="noreferrer"><strong>retrieval-augmented generation (RAG)</strong></a><strong>,</strong> a technique where the model queries a knowledge base in real time to ground its answers in factual information rather than relying on parametric memory alone. Finally, a <a href="https://www.videosdk.live/developer-hub/tts/what-is-text-to-speech" rel="noreferrer"><strong>text-to-speech (TTS)</strong></a> engine converts the generated text into audio and streams it back to the user.</p><p>The result is a system that can understand conversational speech, maintain multi-turn context, access live business data, and respond in a natural voice, all within a latency budget that makes the interaction feel fluid rather than mechanical.</p><table>
<thead>
<tr>
<th>Dimension</th>
<th>AI Voice Agent</th>
<th>Traditional IVR</th>
<th>Text Chatbot</th>
</tr>
</thead>
<tbody>
<tr>
<td>Interaction type</td>
<td>Free-form spoken conversation</td>
<td>Touch-tone or keyword menu navigation</td>
<td>Text input and output</td>
</tr>
<tr>
<td>Latency</td>
<td>Sub-second (300–800ms typical)</td>
<td>Near-instant for menu responses</td>
<td>Variable; not real-time</td>
</tr>
<tr>
<td>Context retention</td>
<td>Multi-turn, session-persistent</td>
<td>None (each keypress is stateless)</td>
<td>Session-dependent; often limited</td>
</tr>
<tr>
<td>Integration complexity</td>
<td>High (STT + LLM + TTS + telephony)</td>
<td>Low (audio files + routing logic)</td>
<td>Medium (NLP + API connectors)</td>
</tr>
<tr>
<td>Best for</td>
<td>Complex, dynamic conversations at scale</td>
<td>Simple routing and data capture</td>
<td>Asynchronous support and FAQ resolution</td>
</tr>
</tbody>
</table>
<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-11--2026--04_32_10-PM.png" class="kg-image" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked" loading="lazy" width="1692" height="930"><figcaption><span style="white-space: pre-wrap;">How AI Voice Agent Works</span></figcaption></img></figure><h2 id="why-2026-is-the-maturity-phase-for-voice-ai">Why 2026 Is the Maturity Phase for Voice AI</h2><p>Three developments have converged in 2026 to move AI voice agents from experimental technology to production infrastructure.</p><p><strong>LLM quality and latency.</strong> Models like GPT-4o and Claude 3.5 Sonnet deliver coherent, contextually accurate responses with end-to-end pipeline latencies that routinely fall below 800ms. This crosses the threshold where most callers perceive the interaction as responsive rather than delayed. Purpose-built models, <a href="https://openai.com/index/introducing-the-realtime-api/" rel="noreferrer">OpenAI's Realtime API</a>,&nbsp;<a href="https://elevenlabs.io/docs/overview/models#flash-v25" rel="noreferrer nofollow">ElevenLabs Eleven Flash v2.5</a>&nbsp;(75ms synthesis latency), and&nbsp;<a href="https://cartesia.ai/sonic" rel="nofollow noreferrer">Cartesia Sonic 3</a> (40–90ms time-to-first-audio) have further compressed the audio generation layer.</p><p><a href="https://docs.videosdk.live/telephony/ai-telephony-agent-quick-start" rel="noreferrer"><strong>Telephony API</strong></a><strong> commoditisation.</strong> <a href="https://en.wikipedia.org/wiki/Public_switched_telephone_network" rel="noreferrer">PSTN</a> and <a href="https://videosdk.live/developer-hub/sip/what-is-session-initiation-protocol-sip" rel="noreferrer">SIP</a> connectivity, previously the province of enterprise telecoms contracts, is now available as a programmable API layer through VideoSDK, Vapi, Bland, Retell AI, and others. A startup can provision a phone number, attach an AI agent, and handle inbound calls without a carrier contract.</p><p><strong>Multimodal and agentic architectures.</strong> Voice agents in 2026 are not limited to audio. Platforms including ElevenLabs (ElevenAgents), OpenAI (Realtime API), and VideoSDK support agents that combine voice with real-time tool calling, updating CRM records, querying databases, and triggering external workflows mid-conversation. According to Gartner, 40% of enterprise applications will be integrated with task-specific AI agents by the end of 2026, up from less than 5% in 2025 (Gartner, 2025).</p><p><strong>Enterprise compliance infrastructure.</strong> SOC 2 Type II certification, HIPAA Business Associate Agreements, and GDPR data residency controls are now standard or near-standard across leading platforms. This removes the compliance barrier that previously blocked regulated industries from production deployment. Healthcare, banking, and insurance sectors, collectively representing over 50% of enterprise voice AI spend, have moved from pilots to at-scale rollouts as a result.</p><p>The measurable shift: 78% of the top 50 global banks had deployed production voice agents for at least one customer-facing use case by early 2026, up from 34% in 2024 (AI Voice Research, 2026).</p><h2 id="top-10-ai-voice-agent-platforms-in-2026">Top 10 AI Voice Agent Platforms in 2026</h2><h3 id="videosdk-best-for-real-time-ai-voice-agent-infrastructure"><strong>VideoSDK: </strong>Best for Real-Time AI Voice Agent Infrastructure</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/Screenshot-2026-05-11-181803.png" class="kg-image" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked" loading="lazy" width="1536" height="693"/></figure><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> provides the foundational infrastructure layer for building, deploying, and scaling <a href="https://www.videosdk.live/voice-agents" rel="noreferrer">AI voice agents</a> in production environments. Founded as a real-time communications platform, VideoSDK has evolved its architecture specifically for AI agent workloads: low-latency audio transport, modular AI pipeline components, PSTN/SIP telephony integration, and deployment options ranging from fully managed cloud to self-hosted on-premises. In 2026, it occupies a distinct position as the only platform in this list that combines a <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> media layer with a fully interchangeable STT/LLM/TTS pipeline under a single SDK surface, without locking developers into any specific AI provider. Teams building custom, high-performance voice agents for healthcare, fintech, logistics, and enterprise SaaS choose VideoSDK when they need production-grade infrastructure they can fully control.</p><h4 id="architecture-deep-dive">Architecture Deep-Dive</h4><p>VideoSDK operates a geo-distributed WebRTC mesh that routes audio through the nearest server node to maintain sub-80ms transport latency globally. The AI pipeline is modular by design: the STT layer accepts Google Speech, Deepgram Nova-3, or OpenAI Whisper interchangeably and can switch models mid-session based on caller language or environment. The LLM layer supports GPT-4o, Claude, Mistral, and self-hosted fine-tuned models via a standard API interface. The TTS layer plugs in ElevenLabs, Amazon Polly, Azure Neural Voice, or any streaming synthesis endpoint. Built-in <a href="https://docs.videosdk.live/ai_agents/core-components/rag" rel="noreferrer">RAG</a> capabilities allow agents to query external knowledge bases in real time, reducing hallucinations and enabling dynamic data access. Deployment is offered in two modes: a managed <strong>Agent Cloud</strong> that handles provisioning and auto-scaling and a fully <a href="https://github.com/videosdk-live/agents" rel="noreferrer"><strong>self-hosted</strong></a> option for enterprises with data residency or security requirements. PSTN and SIP integration allows the same agent to handle web, mobile, and traditional telephony from a single codebase.</p><p><strong>Key Features:</strong></p><ul><li><strong>Sub-80ms global WebRTC transport:</strong> Geo-distributed media routing ensures audio latency stays below 80ms regardless of caller location, which is the critical threshold for natural conversational pacing.</li><li><strong>Modular STT/LLM/TTS pipeline:</strong> Each layer of the AI pipeline is independently replaceable. Developers can swap the transcription engine, language model, or voice synthesis provider without rebuilding the agent. This architecture supports cost optimisation (use cheaper models for simple queries, premium models for complex ones) and vendor risk management.</li><li><strong>PSTN and SIP telephony:</strong> VideoSDK supports <a href="https://www.videosdk.live/blog/ai-telephony-agent-inbound-outbound-calls" rel="noreferrer">inbound and outbound calls</a> over traditional phone networks via PSTN and enterprise telephony via <a href="https://videosdk.live/developer-hub/sip/sip-communication-protocol" rel="noreferrer">SIP protocol</a>, enabling agents to operate on any channel, app, browser, or phone.</li><li><strong>No-Code Agent Runtime:</strong> VideoSDK's dashboard includes a no-code/low-code Agent Runtime interface where non-technical users can create a voice agent, configure its persona, system prompt, welcome message, and pipeline (Realtime or Cascading STT → LLM → TTS) entirely through a visual UI, without writing any code. Both pipeline modes are configurable from the same interface, with API key integrations for Gemini, OpenAI, ElevenLabs, and others managed through the dashboard.</li><li><strong>Built-in RAG and multi-turn memory:</strong> Native <a href="https://videosdk.live/developer-hub/ai_agent/retrieval-augmented-generation-rag" rel="noreferrer">retrieval-augmented generation</a> allows agents to query product databases, CRM systems, or documentation in real time. Integrated session memory ensures callers do not need to repeat context across turns.</li><li><strong>Enterprise compliance (SOC 2 Type II, HIPAA, GDPR):</strong> VideoSDK is certified for regulated industries, with documented support for <a href="https://docs.videosdk.live/help_docs/security-and-privacy/hipaa" rel="noreferrer">HIPAA</a> BAAs and <a href="https://docs.videosdk.live/help_docs/security-and-privacy/gdpr" rel="noreferrer">GDPR</a> data processing agreements.</li><li><strong>Advanced audio processing:</strong> Built-in echo cancellation and noise suppression improve STT accuracy in noisy environments, call centres, mobile, and drive-through contexts without requiring external preprocessing.</li><li><strong>Managed Agent Cloud and self-hosting:</strong> Teams can deploy on VideoSDK's managed infrastructure for rapid launch or run the entire stack on their own cloud or on-premise servers for full data sovereignty.</li></ul><p><strong>Ideal For:</strong> Developer and engineering teams building custom, production-grade AI voice agents — and non-technical teams who want to configure and launch agents through VideoSDK's no-code <a href="https://docs.videosdk.live/ai_agents/agent-runtime/build-agent" rel="noreferrer">Agent Runtime</a> dashboard without writing code.</p><p><strong>Pricing (as of May 2026):</strong></p><table>
<thead>
<tr>
<th style="text-align:left">Plan</th>
<th style="text-align:left">Free</th>
<th style="text-align:left">Pay-As-You-Go</th>
<th style="text-align:left">Enterprise</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left"><strong>Included</strong></td>
<td style="text-align:left">$20 credit included</td>
<td style="text-align:left">Usage-based prepaid billing</td>
<td style="text-align:left">Custom pricing (High-volume)</td>
</tr>
<tr>
<td style="text-align:left"><strong>Agent Session</strong></td>
<td style="text-align:left">Free (up to $20 credit)</td>
<td style="text-align:left">$0.01/minute</td>
<td style="text-align:left">Discounted at volume</td>
</tr>
<tr>
<td style="text-align:left"><strong>Audio Pricing</strong></td>
<td style="text-align:left">Free (up to $20 credit)</td>
<td style="text-align:left">$0.001/participant-minute</td>
<td style="text-align:left">Discounted at volume</td>
</tr>
<tr>
<td style="text-align:left"><strong>Video Pricing</strong></td>
<td style="text-align:left">Free (up to $20 credit)</td>
<td style="text-align:left">$0.004/participant-minute</td>
<td style="text-align:left">Discounted at volume</td>
</tr>
<tr>
<td style="text-align:left"><strong>Live Streaming</strong></td>
<td style="text-align:left">Free (up to $20 credit)</td>
<td style="text-align:left">$0.002/viewer-minute</td>
<td style="text-align:left">Discounted at volume</td>
</tr>
<tr>
<td style="text-align:left"><strong>Latency</strong></td>
<td style="text-align:left">&lt;80ms globally</td>
<td style="text-align:left">&lt;80ms globally</td>
<td style="text-align:left">&lt;80ms globally</td>
</tr>
<tr>
<td style="text-align:left"><strong>Deployment</strong></td>
<td style="text-align:left">Global edge network</td>
<td style="text-align:left">Global edge network</td>
<td style="text-align:left">Private Cloud (VPC) options</td>
</tr>
<tr>
<td style="text-align:left"><strong>Credit Card</strong></td>
<td style="text-align:left">Not required</td>
<td style="text-align:left">Required (Prepaid)</td>
<td style="text-align:left">Not required (custom contract)</td>
</tr>
</tbody>
</table>
<p>Pricing is subject to change; verify at the <a href="https://www.videosdk.live/pricing" rel="noreferrer">VideoSDK Pricing Page</a>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-11--2026--05_09_16-PM.png" class="kg-image" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked" loading="lazy" width="1484" height="1060"><figcaption><span style="white-space: pre-wrap;">VideoSDK AI Voice Agent — Modular Pipeline</span></figcaption></img></figure><h3 id="vapi-best-for-omnichannel-developer-deployment"><strong>Vapi:</strong> Best for Omnichannel Developer Deployment</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/Screenshot-2026-05-11-181855.png" class="kg-image" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked" loading="lazy" width="1531" height="693"/></figure><p><strong>Key Features:</strong></p><ul><li><strong>Provider-agnostic model selection:</strong> Developers can pair any combination of STT providers (Deepgram, AssemblyAI, and Whisper), LLMs (GPT-4o, Claude, Groq, and Mistral), and TTS (ElevenLabs, Cartesia, Azure, and Deepgram Aura) within a single Vapi agent configuration. LLM and TTS costs are passed through at provider rates without Vapi markup.</li><li><strong>Omnichannel deployment:</strong> A single agent configuration deploys to PSTN telephony (via Twilio, Vonage, or other carriers), web browsers (WebRTC), and mobile SDKs, eliminating the need to maintain separate codebases per channel.</li><li><strong>Real-time tool calling and function execution:</strong> Agents can invoke external APIs mid-conversation, querying CRM records, checking inventory, or triggering booking flows, using a structured function-calling interface compatible with OpenAI's function schema.</li><li><strong>Sub-second turn latency:</strong> Vapi's orchestration layer adds approximately 50ms overhead; total end-to-end latency in well-configured stacks typically falls in the 500–800ms range depending on provider selection.</li><li><strong>Active developer ecosystem:</strong> Extensive documentation, REST and WebSocket APIs, a dashboard for call analytics, and an active Discord community reduce time-to-prototype for new teams.</li><li><strong>HIPAA zero-retention option:</strong> HIPAA-compliant zero-data-retention mode is available as an add-on at $1,000/month.</li></ul><p><strong>Ideal For:</strong> Developer teams who want maximum flexibility to select best-in-class components for each pipeline layer and deploy across web, mobile, and telephony channels.</p><p><strong>Pricing (as of May 2026):</strong> <a href="https://www.videosdk.live/industry-hub/blogs/vapi-ai-review" rel="noreferrer">Vapi</a> charges $0.05/minute for orchestration (the platform fee). Total production cost adds provider fees: STT approximately $0.004–0.01/minute (Deepgram), LLM approximately $0.02–0.08/minute (GPT-4o), and TTS approximately $0.04–0.07/minute (ElevenLabs). Realistic all-in cost ranges from $0.15 to $0.40/minute depending on model selection. A free trial with $10 in credits is available. Pricing is subject to change; verify at the <a href="https://vapi.ai/pricing" rel="noreferrer nofollow">Vapi Pricing page</a>.</p><p><strong>Limitations:</strong></p><ul><li>True cost is significantly higher than the $0.05/minute headline rate once all provider layers are included. Budget planning requires tracking four separate billing relationships.</li><li>HIPAA compliance requires a $1,000/month add-on, which makes it cost-prohibitive for small teams in regulated industries.</li><li>No native no-code visual builder; requires developer comfort with APIs and JSON configuration.</li></ul><h3 id="elevenlabs-best-for-expressive-voice-quality"><strong>ElevenLabs: </strong>Best for Expressive Voice Quality</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/Screenshot-2026-05-11-181926.png" class="kg-image" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked" loading="lazy" width="1517" height="692"/></figure><p><a href="https://elevenlabs.io/" rel="noreferrer nofollow">ElevenLabs</a> began as a <a href="https://www.videosdk.live/developer-hub/tts/elevenlabs-text-to-speech-review" rel="noreferrer">text-to-speech</a> provider and has expanded in 2026 into a full conversational AI platform under the <strong>ElevenAgents</strong> product line. Its core differentiation remains voice expressiveness: the Eleven v3 model (generally available as of early 2026) supports 70+ languages and Audio Tags, bracketed instructions like <code>[whispers]</code> or <code>[shouts]</code> that direct emotional delivery. The Eleven Flash v2.5 model is optimised for real-time agents, delivering 75ms synthesis latency. In February 2026, ElevenLabs completed a <a href="https://elevenlabs.io/blog/series-d" rel="noreferrer nofollow">$500M Series D at an $11 billion valuation</a>, reflecting over $330M in annual recurring revenue at the close of 2025 (TechCrunch, 2026).</p><p><strong>Key Features:</strong></p><ul><li><strong>Eleven v3 and Flash v2.5 models:</strong> The v3 flagship supports emotionally directed speech via Audio Tags and handles complex text (chemical formulas, phone numbers) with a reported 68% reduction in pronunciation errors versus v2. Flash v2.5 delivers 75ms model latency for real-time agent use cases.</li><li><strong>Eleven Agents Conversational AI 2.0:</strong> A complete conversational platform with <a href="https://videosdk.live/developer-hub/ai_agent/retrieval-augmented-generation-rag" rel="noreferrer">RAG</a> knowledge base support (text, URL, and file ingestion), a custom turn-taking model that goes beyond silence-based endpointing, batch calling APIs for outbound campaigns, and OAuth2/API key authentication for server-side tool calling.</li><li><strong>Voice cloning:</strong> Zero-shot voice cloning from a short audio sample preserves timbre, accent, and pacing. Custom voice library supports thousands of voices organised by purpose (support, announcement, narration).</li><li><strong>70+ language support:</strong> Multilingual voice synthesis with automatic language detection and mid-conversation language switching.</li><li><strong>MCP tool support:</strong> Agents can connect to external services via Model Context Protocol, enabling mid-conversation actions such as CRM lookups and appointment booking.</li><li><strong>Multimodal message support:</strong> The 2026 ElevenAgents SDK supports sending files and images during conversations, enabling multimodal agent interactions.</li></ul><p><strong>Ideal For:</strong> Product teams building customer-facing agents where voice quality and emotional expressiveness directly affect user experience, or content teams integrating voice into media workflows.</p><p><strong>Pricing (as of May 2026):</strong> Conversational AI is billed at approximately $0.10/minute on Creator and Pro tiers and $0.08/minute on the annual Business tier, approximately 50% cheaper than 2025 rates following a February 2026 price cut. TTS-only pricing follows a character-based credit model: Creator tier at $22/month, the Pro tier at $99/month, and the Business/Scale tier at $330/month. Pricing is subject to change; verify at the <a href="https://elevenlabs.io/pricing" rel="noreferrer nofollow">Elvenlabs Pricing page</a>.</p><p><strong>Limitations:</strong></p><ul><li><a href="https://docs.videosdk.live/help_docs/security-and-privacy/hipaa" rel="noreferrer">HIPAA compliance</a> is restricted to the Enterprise subscription tier on the Agents platform; it is not available on standard plans.</li><li>No true on-premises deployment; enterprise options are limited to private cloud configurations.</li><li>ElevenLabs STT (Scribe v2 Realtime) lacks published quantitative benchmarks for false interruption rates and telephony noise environments, making independent validation difficult.</li></ul><h3 id="deepgram-best-for-high-accuracy-speech-recognition"><strong>Deepgram: </strong>Best for High-Accuracy Speech Recognition</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/Screenshot-2026-05-11-182221.png" class="kg-image" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked" loading="lazy" width="1521" height="690"/></figure><p><a href="https://deepgram.com/" rel="noreferrer nofollow">Deepgram</a> is an AI speech platform built around its Nova-3 speech-to-text model, which in independent testing achieves a 54.2% lower word error rate on noisy audio compared to competing STT services (Deepgram, 2026). In 2026, Deepgram raised <a href="https://deepgram.com/learn/press-release-deepgram-raises-series-c" rel="noreferrer nofollow">$130M at a $1.3 billion valuation</a> and launched its bundled <strong>Voice Agent API,</strong> a complete real-time agent stack that includes Nova-3 STT, the Aura-2 TTS engine, and LLM orchestration with optional third-party model integration. The Flux Multilingual model, added in 2026, extends transcription coverage to additional language markets.</p><p><strong>Key Features:</strong></p><ul><li><strong>Nova-3 STT with noise robustness:</strong> The flagship transcription model achieves 54.2% lower WER than competitors on noisy call centre audio, which is the most common real-world deployment environment.</li><li><strong>Aura-2 TTS for contact centres:</strong> A domain-tuned TTS engine trained on real call centre recordings, optimised for accurate pronunciation of medical, financial, and technical terminology.</li><li><strong>Bundled Voice Agent API:</strong> Integrates STT, LLM, and TTS into a single pricing line, eliminating the unpredictable cost stacking that affects component-based platforms.</li><li><strong>Sub-300ms end-to-end latency:</strong> Deepgram's 99.9% uptime SLA and multi-region infrastructure deliver consistent latency well within the ITU-T G.114 300ms threshold for high-quality real-time voice.</li><li><strong>Audio Intelligence APIs:</strong> Sentiment analysis, topic detection, speaker diarisation, and summarisation APIs enable post-call analytics without additional third-party services.</li><li><strong>Custom model training:</strong> Organisations can train speech models on domain-specific audio data to improve accuracy for specialised vocabulary, accents, or industry terms.</li></ul><p><strong>Ideal For:</strong> Teams building real-time transcription pipelines, post-call analytics platforms, or contact centre AI in healthcare and finance where terminology accuracy is critical.</p><p><strong>Pricing (as of May 2026):</strong> Pay-as-you-go with $200 in free credits for new users. Nova-3 STT starts at approximately $0.0043/minute for streaming. Aura-2 TTS at approximately $0.015 per 1,000 characters. Bundled Voice Agent API pricing varies by configuration; verify at the <a href="https://deepgram.com/pricing" rel="noreferrer nofollow">Deepgram Pricing page</a>. Growth and Enterprise plans are available at volume discounts. Pricing is subject to change.</p><p><strong>Limitations:</strong></p><ul><li>Aura-2 TTS voice quality, while optimized for accuracy, does not match ElevenLabs or Cartesia for emotional expressiveness and naturalness in consumer-facing contexts.</li><li>Custom model training requires a data preparation investment and Deepgram's enterprise tier; it is not available on self-serve plans.</li><li>The bundled <a href="https://docs.videosdk.live/ai_agents/voice-agent-quick-start" rel="noreferrer">Voice Agent API</a> limits LLM model selection compared to fully modular platforms like Vapi or VideoSDK.</li></ul><h3 id="openai-best-for-llm-native-voice-agent-development"><strong>OpenAI: </strong>Best for LLM-Native Voice Agent Development</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/08/Screenshot-2025-08-08-154218.png" class="kg-image" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked" loading="lazy" width="1608" height="913"/></figure><p>OpenAI does not offer a pre-built voice agent platform but provides the model primitives, Whisper for STT, GPT-4o and the <a href="https://developers.openai.com/api/docs/guides/realtime" rel="noreferrer">Real-time API</a> for multimodal voice processing, and TTS models for synthesis, that serve as building blocks for custom agents. The <strong>Realtime API</strong>, introduced in 2024 and refined through 2025–2026, processes audio input and output within a single model pass rather than routing through separate STT, LLM, and TTS stages, reducing latency and preserving acoustic nuance (tone, pacing, and hesitation) that cascaded pipelines discard.</p><p><strong>Key Features:</strong></p><ul><li><strong>Realtime API (native multimodal):</strong> Processes speech input and generates spoken output within a single model, eliminating pipeline stitching overhead and preserving prosodic information that separate STT/TTS layers lose.</li><li><strong>Whisper STT:</strong> An open-source speech recognition model available both via API and for self-hosting, supporting 99 languages and performing well on accented speech and noisy environments.</li><li><strong>Function calling and tool use:</strong> GPT-4o supports structured function calling, allowing voice agents to execute real-world actions (database lookups, form submissions, API calls) during conversations.</li><li><strong>GPT-4o and GPT-4.1 model family:</strong> Current flagship GPT-5.4 and cost-efficient GPT-4.1 Nano ($0.10/$0.40 per million tokens input/output) give developers fine-grained control over cost vs. capability tradeoffs.</li><li><strong>Agents SDK:</strong> OpenAI's Agents SDK for TypeScript and Python simplifies building multi-turn, stateful voice agents with built-in session management.</li></ul><p><strong>Ideal For:</strong> Development teams already invested in the OpenAI ecosystem who want a native multimodal pipeline, or teams where LLM reasoning quality is the primary constraint.</p><p><strong>Pricing (as of May 2026):</strong> Real-time API audio pricing varies by model, verify current rates at the <a href="https://developers.openai.com/api/docs/pricing" rel="noreferrer">OpenAI pricing page</a>. GPT-5.4 input/output: $2.50/$15.00 per million tokens. GPT-4.1 Nano: $0.10/$0.40 per million tokens. Whisper STT via API: $0.006/minute. TTS API: varies by model. Pricing is subject to change.</p><p><strong>Limitations:</strong></p><ul><li>Using OpenAI for LLM locks the agent to OpenAI's pricing and availability; there is no easy path to swap to a different LLM provider without rebuilding the orchestration layer.</li><li>The Realtime API is not a complete voice agent platform; telephony, RAG, memory, and deployment infrastructure must be assembled separately or via a platform like Vapi or VideoSDK.</li><li>No built-in PSTN/SIP telephony; requires integration with a separate telephony provider.</li></ul><h3 id="bland-best-for-generating-custom-ai-voices"><strong>Bland: Best for Generating Custom AI Voices</strong></h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/Screenshot-2026-05-11-174207.png" class="kg-image" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked" loading="lazy" width="1512" height="691"/></figure><p><a href="https://www.bland.ai/" rel="noreferrer nofollow">Bland</a> is a programmable voice AI platform purpose-built for enterprise organisations running high volumes of outbound phone calls. Its architecture centres on <strong>Pathways,</strong> a visual graph-based call flow builder, combined with an API that gives developers granular control over call logic, branching, and mid-call integrations. Bland's self-hosted infrastructure model allocates dedicated GPUs to enterprise customers, enabling predictable performance under high-concurrency workloads of up to 20,000 concurrent calls per hour.</p><p><strong>Key Features:</strong></p><ul><li><strong>Pathways visual builder:</strong> A graph-based tool for mapping call flows, decision branches, validation rules, and API integrations. Non-engineers can design flows; engineers can extend them with custom logic via webhooks.</li><li><strong>All-inclusive per-minute pricing:</strong> Bland's base rate includes LLM, STT, TTS, and telephony in a single charge, eliminating the multi-vendor billing complexity of modular platforms.</li><li><strong>Dedicated GPU infrastructure for enterprise:</strong> Enterprise contracts provision dedicated servers, providing consistent latency and isolation from multi-tenant resource contention.</li><li><strong>Voice cloning from short audio samples:</strong> Custom voices can be cloned from 1–2 audio samples without model fine-tuning; voice cloning is an add-on at additional cost.</li><li><strong>CRM and ERP integrations:</strong> Bland connects natively with Salesforce, HubSpot, Slack, and custom endpoints, enabling agents to update records and trigger workflows during calls.</li><li><strong>Memory across calls:</strong> Agents can identify callers by phone number and access prior interaction data, enabling personalized repeat-caller experiences.</li></ul><p><strong>Ideal For:</strong> Enterprise sales, collections, and operations teams running high-volume outbound calling campaigns where call flow control and predictable per-minute pricing matter more than model flexibility.</p><p><strong>Pricing (as of May 2026):</strong> Tiered subscription plus usage: Start (free, $0.14/minute connected); Build ($299/month, $0.12/minute); Scale ($499/month, $0.11/minute); Enterprise (custom). Transfer time billed separately; $0.015 minimum per outbound attempt. Pricing is subject to change, verify at the <a href="https://www.bland.ai/pricing" rel="noreferrer">Bland pricing page</a>.</p><p><strong>Limitations:</strong></p><ul><li>HIPAA compliance requires direct confirmation and a BAA from Bland's sales team; it is not available as a self-serve add-on.</li><li>English is the only language fully supported in production use cases; multilingual capabilities are limited or in beta.</li><li>The platform is API and developer-first; non-technical teams will require significant engineering support to deploy and maintain agents.</li></ul><h3 id="synthflow-best-no-code-platform-for-phone-agents"><strong>Synthflow: </strong>Best No-Code Platform for Phone Agents</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/Screenshot-2026-05-11-174112.png" class="kg-image" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked" loading="lazy" width="1516" height="696"/></figure><p><a href="https://synthflow.ai/" rel="noreferrer nofollow">Synthflow</a> is a <a href="https://docs.videosdk.live/ai_agents/agent-runtime/build-agent" rel="noreferrer">no-code AI voice agent</a> platform designed for business and marketing teams who need to deploy phone agents without engineering resources. Its visual builder enables agent creation in under 30 minutes, with ElevenLabs voices bundled on paid plans. In 2026, Synthflow achieved SOC 2, GDPR, and ISO 27001 certifications and migrated from fixed minute-bucket pricing to usage-based billing, improving cost predictability for variable-volume deployments. The platform has automated over 45 million calls across its customer base.</p><p><strong>Key Features:</strong></p><ul><li><strong>No-code visual flow builder:</strong> Drag-and-drop interface for designing conversation flows, questions, conditional branches, and follow-up actions without writing code. Synthflow is consistently rated as the fastest path from zero to a working phone agent demo.</li><li><strong>ElevenLabs voices bundled:</strong> High-quality ElevenLabs voice synthesis is included on paid plans without requiring a separate ElevenLabs subscription.</li><li><strong>CRM and automation integrations:</strong> Native connectors for HubSpot, Salesforce, and Zapier enable post-call record updates and workflow triggers without custom development.</li><li><strong>Multilingual support:</strong> Agents can handle calls in multiple languages with automatic detection and routing.</li><li><strong>24/7 inbound and outbound automation:</strong> Supports both call types with SMS follow-up capabilities included.</li><li><strong>Global Low Latency Edge (add-on):</strong> An optional $0.04/minute add-on delivers consistent sub-600ms latency under load; base configuration latency measures approximately 400–500ms.</li></ul><p><strong>Ideal For:</strong> Small to mid-sized businesses, marketing teams, and non-technical operators who need to launch AI phone agents for lead qualification, appointment booking, or customer support without developer involvement.</p><p><strong>Pricing (as of May 2026):</strong> Usage-based pricing replaced prior minute-bucket tiers in 2026. Voice engine: approximately $0.09/minute base, with LLM costs adding $0.02–0.05/minute. Enterprise contracts available. A 14-day unlimited trial is available for rapid evaluation. Pricing is subject to change; verify at the <a href="https://synthflow.ai/pricing" rel="noreferrer nofollow">Synthflow pricing page</a>.</p><p><strong>Limitations:</strong></p><ul><li>Costs run higher than the base voice engine rate once LLM and optional add-ons (Global Low Latency Edge, white-label) are included; expect $0.15–$0.24/minute all-in.</li><li>Less model flexibility than developer platforms; LLM and TTS options are more constrained than Vapi or VideoSDK.</li><li>Recent user reviews on G2 note response time issues with customer support and occasional call quality instability (G2, 2026 reviews).</li></ul><h3 id="retell-ai-best-for-regulated-industries-with-predictable-pricing"><strong>Retell AI: </strong>Best for Regulated Industries with Predictable Pricing</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/Screenshot-2026-05-11-174016.png" class="kg-image" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked" loading="lazy" width="1507" height="696"/></figure><p><a href="https://www.retellai.com/" rel="noreferrer nofollow">Retell AI</a> is a developer-focused platform for building highly responsive, human-like voice agents. Its standout feature is its proprietary conversation engine, which excels at handling conversational nuances like turn-taking and interruptions, making it ideal for dynamic support interactions. Retell AI is designed for production environments where conversational fluidity is paramount.</p><p><strong>Key Features:</strong></p><ul><li><strong>Advanced Conversational Engine:</strong> Enables agents to handle interruptions and detect end-of-turn with less than 800ms latency, creating a more natural flow.</li><li><strong>Flexible AI Integration:</strong> Allows you to use your preferred LLM, including models from GPT and Claude, to power your agent's intelligence.</li><li><strong>Multi-Platform Deployment:</strong> Deploy voice agents across web applications, mobile apps, and telephony services like Twilio.</li><li><strong>Comprehensive Monitoring:</strong> Provides post-call analysis, sentiment tracking, and task completion data to monitor and improve agent performance.</li><li><strong>Security and Compliance:</strong> Supports SOC 2, HIPAA, and GDPR compliance, making it suitable for regulated industries.</li></ul><p><strong>Use Cases:</strong></p><ul><li>Building AI-powered customer service agents that can handle complex and unscripted inquiries.</li><li>Creating interactive voice assistants for technical support and troubleshooting.</li><li>Developing AI agents for booking and scheduling that require natural conversation.</li><li>Prototyping and deploying sophisticated voice AI applications.</li></ul><p><strong>Pricing: </strong>Retell AI uses a pay-as-you-go pricing model with separate charges for each component (voice engine, LLM, telephony). Voice engine costs start at $0.07/minute. There are no platform fees, and users get $10 in free credits to start. Enterprise plans with volume discounts are also available.</p><p><strong>Limitations:</strong></p><ul><li>Production costs run 30–60% above the advertised $0.07/minute base rate once LLM and telephony are included, which surprises teams that budget based on the headline figure.</li><li>No true visual flow builder comparable to Synthflow or Voiceflow; the no-code interface is template-based rather than full-canvas.</li><li>Some user reviews cite unresponsiveness to feature requests and occasional platform instability (G2, 2025–2026 reviews).</li></ul><h3 id="voiceflow-best-for-multi-channel-conversational-design-teams"><strong>Voiceflow: </strong>Best for Multi-Channel Conversational Design Teams</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/Screenshot-2026-05-11-182320.png" class="kg-image" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked" loading="lazy" width="1517" height="688"/></figure><p><a href="https://www.voiceflow.com/" rel="noreferrer nofollow">Voiceflow</a> is a collaborative AI agent design platform built for product and design teams that need to build, version, and deploy conversational experiences across both voice and chat channels. Its canvas-based visual editor supports multi-editor workflows and is best-in-class for teams where conversation design is a dedicated function. In 2026, Voiceflow positions itself as a design and orchestration layer rather than a voice infrastructure provider: telephony still requires Twilio or Vonage separately, and the credit-based billing model introduces cost unpredictability at high voice volumes.</p><p><strong>Key Features:</strong></p><ul><li><strong>Collaborative canvas editor:</strong> Best-in-class visual flow builder for multi-editor teams, with version history, shared workspaces, role permissions, and prototyping tools.</li><li><strong>LLM integration:</strong> Works with GPT-4.1, Claude, and other major models. BYO LLM (bring your own API key) is available on Enterprise plans only.</li><li><strong>Multi-channel deployment:</strong> Agents deploy to voice (via Twilio/Vonage), web chat, and mobile from a single design. Chat is the primary surface; voice is a secondary channel.</li><li><strong>Built-in analytics and observability:</strong> Conversation analytics, intent resolution rates, and fallback tracking give teams the data to iterate on agent behavior.</li><li><strong>Multi-agent architecture:</strong> Voiceflow supports routing between multiple specialized agents within a single workflow.</li></ul><p><strong>Ideal For:</strong> Product teams at mid-to-large organizations that need cross-functional agent design tools, version control, and multi-channel deployment where chat is the dominant interaction surface.</p><p><strong>Pricing (as of May 2026):</strong> Starter (free, limited credits); Pro ($60/month for 1 editor, 10,000 credits/month); Business ($150/month for 1 editor, 30,000 credits/month); Enterprise (custom, typically $1,000–$2,000/month). Additional editor seats: $50/month each. External telephony fees (Twilio/Vonage): $0.01–0.03/minute billed separately. Credits do not roll over; agents stop immediately when credits are exhausted. Pricing is subject to change, verify at the <a href="https://www.voiceflow.com/pricing" rel="noreferrer nofollow">voiceflow pricing page</a>.</p><p><strong>Limitations:</strong></p><ul><li>Not purpose-built for high-volume phone agents; telephony requires a separate Twilio or Vonage account and is not native to the platform.</li><li>Credit-based billing creates cost unpredictability for voice-heavy workloads; unused credits expire monthly with no rollover.</li><li>BYO LLM (using your own OpenAI/Anthropic API keys) is Enterprise-only, which means standard plan users pay Voiceflow's LLM pass-through rates.</li></ul><h3 id="murf-ai-best-for-studio-quality-ai-voiceovers"><strong>Murf AI: </strong>Best for Studio-Quality AI Voiceovers</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/Screenshot-2026-05-11-182411.png" class="kg-image" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked" loading="lazy" width="1521" height="692"/></figure><p><a href="https://murf.ai/" rel="noreferrer nofollow">Murf AI</a> is a <a href="https://www.videosdk.live/developer-hub/tts/what-is-text-to-speech" rel="noreferrer">text-to-speech</a> platform serving over 1 million users across 100+ countries, offering 200+ AI voices in 35+ languages. While not a conversational agent platform, Murf occupies an important position in voice AI workflows: teams use it for producing narrated training content, IVR audio, explainer videos, and branded voiceovers that accompany or supplement live agent interactions. In November 2025, Murf launched <strong>Falcon</strong>, a real-time TTS model built for voice agent applications, reporting 55ms model latency and 130ms time-to-first-audio, competitive with ElevenLabs Flash v2.5 in latency tests. As of early 2026, Murf holds ISO 42001 certification for AI management systems alongside SOC 2 Type II, ISO 27001, HIPAA, and GDPR.</p><p><strong>Key Features:</strong></p><ul><li><strong>Falcon model for real-time agents:</strong> 55ms model latency, 130ms time-to-first-audio across 33 global edge locations, positioned for voice agent synthesis use cases.</li><li><strong>200+ voices in 35+ languages:</strong> Broad language coverage with the ability to customize voice parameters (pitch, pace, emphasis) via an in-browser studio.</li><li><strong>Voice cloning:</strong> Custom voice cloning from audio samples; available on Business and Enterprise plans.</li><li><strong>Team collaboration tools:</strong> Multi-user project management, asset libraries, and role-based access on Business and Enterprise tiers.</li><li><strong>Enterprise compliance suite:</strong> SOC 2 Type II, ISO 27001, ISO 42001, HIPAA, and GDPR certifications, a broader compliance portfolio than most platforms in this list.</li><li><strong>API access:</strong> Full API integration available on Business and Enterprise plans for programmatic voice generation workflows.</li></ul><p><strong>Ideal For:</strong> Content production teams, L&amp;D departments, and enterprises that need studio-quality AI voiceovers for training materials, IVR prompts, and branded media, not for real-time conversational agents.</p><p><strong>Pricing (as of May 2026):</strong> Free plan (limited); Creator ($29/month billed monthly, $19/month billed annually, 24 hours voice generation/year); Business ($99/month, team features, API access, voice cloning); Enterprise (custom). Enterprise total cost can run 50–140% above base subscription once voice cloning, API usage, and custom integrations are factored in (user reports, review platforms, 2026). Pricing is subject to change, verify at the <a href="https://murf.ai/pricing" rel="noreferrer">Murf pricing page</a>.</p><p><strong>Limitations:</strong></p><ul><li>Murf is a content production tool, not a conversational agent platform. It does not support real-time dialogue, multi-turn context, or telephony natively.</li><li>Falcon model performance claims have not been independently benchmarked in production telephony environments as of this writing.</li><li>API access is gated behind Business and Enterprise tiers, limiting developer access on lower plans.</li></ul><h2 id="ai-voice-agent-platform-comparison-2026">AI Voice Agent Platform Comparison (2026)</h2><table>
<thead>
<tr>
<th style="text-align:left">Platform</th>
<th style="text-align:left">Primary Use Case</th>
<th style="text-align:left">STT Support</th>
<th style="text-align:left">LLM Support</th>
<th style="text-align:left">TTS Support</th>
<th style="text-align:left">Telephony / PSTN</th>
<th style="text-align:left">Pricing Model</th>
<th style="text-align:left">Free Tier / Trial</th>
<th style="text-align:left">HIPAA</th>
<th style="text-align:left">2026 Notable Update</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left"><strong>VideoSDK</strong></td>
<td style="text-align:left">Full-stack AI voice infrastructure</td>
<td style="text-align:left">Pluggable (Google, Deepgram, Whisper)</td>
<td style="text-align:left">Pluggable (any API)</td>
<td style="text-align:left">Pluggable (ElevenLabs, Polly, Azure)</td>
<td style="text-align:left">Yes (PSTN + SIP)</td>
<td style="text-align:left">Usage-based + Enterprise</td>
<td style="text-align:left">Yes ($20)</td>
<td style="text-align:left">Yes</td>
<td style="text-align:left">Expanded Agent Cloud managed deployment; self-hosting GA; no-code Agent Runtime  launched in dashboard</td>
</tr>
<tr>
<td style="text-align:left"><strong>Vapi</strong></td>
<td style="text-align:left">Developer orchestration</td>
<td style="text-align:left">Pluggable (Deepgram, Whisper, AssemblyAI)</td>
<td style="text-align:left">Pluggable (any API)</td>
<td style="text-align:left">Pluggable (ElevenLabs, Cartesia, Azure)</td>
<td style="text-align:left">Via integration (Twilio/Vonage)</td>
<td style="text-align:left">Usage-based</td>
<td style="text-align:left">$10 free credits</td>
<td style="text-align:left">Add-on ($1K/mo)</td>
<td style="text-align:left">Adaptive Interruption Handling model (86% precision/100% recall)</td>
</tr>
<tr>
<td style="text-align:left"><strong>ElevenLabs</strong></td>
<td style="text-align:left">Expressive voice + conversational AI</td>
<td style="text-align:left">Scribe v2 Realtime (own)</td>
<td style="text-align:left">Pluggable (GPT-4, Claude, Gemini)</td>
<td style="text-align:left">Eleven v3 / Flash v2.5 (own)</td>
<td style="text-align:left">Yes (via Twilio + SIP)</td>
<td style="text-align:left">Credit-based + per-minute</td>
<td style="text-align:left">Free tier</td>
<td style="text-align:left">Enterprise only</td>
<td style="text-align:left">Conversational AI 2.0; $500M Series D; ~50% price cut on Conversational AI</td>
</tr>
<tr>
<td style="text-align:left"><strong>Deepgram</strong></td>
<td style="text-align:left">High-accuracy STT + bundled agent API</td>
<td style="text-align:left">Nova-3 (own, best-in-class)</td>
<td style="text-align:left">Bundled or pluggable</td>
<td style="text-align:left">Aura-2 (own)</td>
<td style="text-align:left">Via bundled Agent API</td>
<td style="text-align:left">Usage-based</td>
<td style="text-align:left">$200 free credits</td>
<td style="text-align:left">Yes (BAA available)</td>
<td style="text-align:left">Nova-3 model GA; Flux Multilingual; $130M raise</td>
</tr>
<tr>
<td style="text-align:left"><strong>OpenAI</strong></td>
<td style="text-align:left">LLM-native voice / Realtime API</td>
<td style="text-align:left">Whisper (own + open-source)</td>
<td style="text-align:left">GPT-4o / GPT-5.4 (own)</td>
<td style="text-align:left">TTS API (own)</td>
<td style="text-align:left">No (requires integration)</td>
<td style="text-align:left">Usage-based (tokens + per-minute)</td>
<td style="text-align:left">API trial credits</td>
<td style="text-align:left">Verify</td>
<td style="text-align:left">Realtime API matured; GPT-5.4 flagship; GPT-4.1 Nano cost tier</td>
</tr>
<tr>
<td style="text-align:left"><strong>Bland</strong></td>
<td style="text-align:left">High-volume outbound enterprise calling</td>
<td style="text-align:left">Bundled</td>
<td style="text-align:left">Bundled (GPT-4 class)</td>
<td style="text-align:left">Bundled</td>
<td style="text-align:left">Yes (PSTN native)</td>
<td style="text-align:left">Subscription + per-minute</td>
<td style="text-align:left">Free (2 credits)</td>
<td style="text-align:left">Verify</td>
<td style="text-align:left">Tiered subscription model introduced; Pathways builder expanded</td>
</tr>
<tr>
<td style="text-align:left"><strong>Synthflow</strong></td>
<td style="text-align:left">No-code phone agents</td>
<td style="text-align:left">Bundled</td>
<td style="text-align:left">Bundled</td>
<td style="text-align:left">ElevenLabs bundled</td>
<td style="text-align:left">Yes (PSTN native)</td>
<td style="text-align:left">Usage-based</td>
<td style="text-align:left">14-day unlimited trial</td>
<td style="text-align:left">Yes (SOC 2, ISO 27001)</td>
<td style="text-align:left">Migrated from minute-bucket to usage-based; SOC 2 + ISO 27001 certified</td>
</tr>
<tr>
<td style="text-align:left"><strong>Retell AI</strong></td>
<td style="text-align:left">Regulated industry voice agents</td>
<td style="text-align:left">Bundled + pluggable</td>
<td style="text-align:left">Pass-through (any provider)</td>
<td style="text-align:left">ElevenLabs + others</td>
<td style="text-align:left">Yes (PSTN native)</td>
<td style="text-align:left">Usage-based (no platform fee)</td>
<td style="text-align:left">$10 free credits</td>
<td style="text-align:left">Yes (standard plans)</td>
<td style="text-align:left">Powering 30M+ calls/month; proprietary turn-taking model</td>
</tr>
<tr>
<td style="text-align:left"><strong>Voiceflow</strong></td>
<td style="text-align:left">Multi-channel conversational design</td>
<td style="text-align:left">Via Deepgram (external)</td>
<td style="text-align:left">GPT-4.1, Claude, pluggable</td>
<td style="text-align:left">Via ElevenLabs (external)</td>
<td style="text-align:left">Via integration (Twilio/Vonage)</td>
<td style="text-align:left">Subscription + credits</td>
<td style="text-align:left">Free tier</td>
<td style="text-align:left">Enterprise tier</td>
<td style="text-align:left">Credit-based billing updated; BYO LLM limited to Enterprise</td>
</tr>
<tr>
<td style="text-align:left"><strong>Murf.ai</strong></td>
<td style="text-align:left">Studio voiceovers + TTS production</td>
<td style="text-align:left">N/A (TTS-only platform)</td>
<td style="text-align:left">N/A</td>
<td style="text-align:left">Falcon (own, 55ms latency)</td>
<td style="text-align:left">No</td>
<td style="text-align:left">Subscription</td>
<td style="text-align:left">Free tier</td>
<td style="text-align:left">Yes</td>
<td style="text-align:left">Falcon model for real-time agents launched Nov 2025; ISO 42001 certified</td>
</tr>
</tbody>
</table>
<blockquote>All pricing and features subject to change. Verify current information at each platform's official pricing page before purchasing.</blockquote><h2 id="use-case-patterns-in-2026">Use Case Patterns in 2026</h2><h3 id="1-inbound-customer-support-automation">1. Inbound Customer Support Automation</h3><p><strong>Pain Point:</strong> High inbound call volumes for routine queries (order status, password reset, billing questions) consume agent capacity and create queue wait times.</p><p><strong>Solution:</strong> An AI voice agent authenticates callers via account ID or phone number, queries the relevant backend system via API, and resolves the inquiry in the same interaction. Calls requiring human judgment are transferred with full context attached.</p><p><strong>Example:</strong> A telecom provider deploys an inbound agent that handles billing inquiries, plan changes, and service outage updates, transferring only complaints and complex technical issues to human agents.</p><p><strong>Relevant Platforms:</strong> VideoSDK, Retell AI, Bland</p><h3 id="2-outbound-lead-qualification">2. Outbound Lead Qualification</h3><p><strong>Pain Point:</strong> Sales teams spend a large portion of time on outbound dials that reach voicemail, unqualified leads, or calls requiring only basic qualification questions.</p><p><strong>Solution:</strong> An AI voice agent places outbound calls, delivers a qualification script, records responses, scores leads against defined criteria, and schedules follow-up calls with qualified prospects into the sales team's calendar.</p><p><strong>Example:</strong> A B2B software company uses an outbound agent to qualify 500 leads/day, filtering to the 15–20% that meet budget, authority, need, and timeline criteria before passing them to account executives.</p><p><strong>Relevant Platforms:</strong> Bland, Retell AI, Vapi</p><h3 id="3-healthcare-appointment-scheduling">3. Healthcare Appointment Scheduling</h3><p><strong>Pain Point:</strong> Clinic staff spend significant time on inbound scheduling calls that follow predictable, repeatable patterns (check availability, confirm patient details, book slot, send confirmation).</p><p><strong>Solution:</strong> A HIPAA-compliant voice agent authenticates the patient, checks real-time availability via calendar API integration, books the appointment, and sends a confirmation text or email, without human involvement for routine scheduling.</p><p><strong>Example:</strong> A multi-location dental practice handles 80% of appointment booking calls through a voice agent, with human staff handling new patient onboarding, referrals, and complex rescheduling.</p><p><strong>Relevant Platforms:</strong> VideoSDK, Retell AI, Synthflow</p><h3 id="4-e-commerce-order-management">4. E-Commerce Order Management</h3><p><strong>Pain Point:</strong> Post-purchase inquiries (shipping status, returns, exchanges) create high call volume that scales linearly with order volume but delivers low differentiated value from human handling.</p><p><strong>Solution:</strong> A voice agent queries the order management system in real time, provides status updates, initiates return or exchange workflows, and escalates to a human only when a policy exception or complaint requires judgment.</p><p><strong>Example:</strong> An apparel retailer deploys an inbound agent that handles order tracking, returns initiation, and exchange requests, integrating with their Shopify backend via API for real-time inventory and order data.</p><p><strong>Relevant Platforms:</strong> VideoSDK, Vapi, Retell AI</p><h3 id="5-real-estate-lead-engagement">5. Real Estate Lead Engagement</h3><p><strong>Pain Point:</strong> Real estate agents cannot manually respond to every inquiry at the speed that online listing portals generate them. Delayed follow-up reduces conversion rates.</p><p><strong>Solution:</strong> An outbound voice agent calls leads within minutes of form submission, qualifies interest level, collects property preferences, and schedules a showing appointment with the human agent.</p><p><strong>Example:</strong> A residential brokerage uses an outbound agent to call web form leads, qualify buyer readiness and budget range, and schedule calendar appointments, all before a human agent has seen the inquiry.</p><p><strong>Relevant Platforms:</strong> Bland, Retell AI, Synthflow</p><h3 id="6-financial-services-customer-authentication-and-support">6. Financial Services Customer Authentication and Support</h3><p><strong>Pain Point:</strong> Inbound bank support calls require secure identity verification before any account information can be accessed, creating friction when handled manually.</p><p><strong>Solution:</strong> A voice agent guides callers through a multi-step authentication process (account number, security questions, or voice biometric), then handles account inquiries, card management, and payment processing for authenticated users.</p><p><strong>Example:</strong> A digital bank's inbound support line authenticates callers via voice biometric and knowledge-based questions, then allows self-service for balance checks, recent transaction review, and card lock/unlock.</p><p><strong>Relevant Platforms:</strong> VideoSDK, Bland, Vapi</p><h3 id="7-logistics-and-dispatch-operations">7. Logistics and Dispatch Operations</h3><p><strong>Pain Point:</strong> Logistics operations require constant status updates between dispatch, drivers, and customers, volume that strains human dispatcher capacity.</p><p><strong>Solution:</strong> A voice agent handles inbound calls from drivers for delivery status updates and assignment requests, and places outbound calls to customers with ETA updates, pulling real-time data from the logistics platform.</p><p><strong>Example:</strong> A last-mile delivery company deploys a voice agent that drivers call to log deliveries, report exceptions, and receive next-assignment instructions, reducing radio and manual dispatch workload.</p><p><strong>Relevant Platforms:</strong> VideoSDK, Vapi, Bland</p><h3 id="8-hospitality-guest-services">8. Hospitality Guest Services</h3><p><strong>Pain Point:</strong> Hotel front desk staff handling peak periods cannot respond immediately to every guest request for room service, local recommendations, or service bookings.</p><p><strong>Solution:</strong> A voice agent handles in-room calls for standard requests (housekeeping, wake-up calls, room service orders), routes to front desk only for requests requiring human judgment, and provides 24/7 coverage without staffing cost.</p><p><strong>Example:</strong> A hotel chain deploys a voice agent as the primary contact for in-room service requests, with integration to the property management system for real-time room status and service queuing.</p><p><strong>Relevant Platforms:</strong> VideoSDK, Retell AI, Synthflow</p><h3 id="9-saas-user-onboarding">9. SaaS User Onboarding</h3><p><strong>Pain Point:</strong> New users in complex SaaS products churn in the first session when they cannot find setup guidance quickly enough through documentation.</p><p><strong>Solution:</strong> An in-app voice assistant answers natural language questions about the product, walks users through setup steps verbally, and routes to a live customer success manager when activation is at risk.</p><p><strong>Example:</strong> A project management platform embeds a voice assistant that new users can ask questions like "How do I invite my team?", the agent pulls answers from product documentation via RAG and guides the user through the UI flow.</p><p><strong>Relevant Platforms:</strong> VideoSDK, Vapi, ElevenLabs</p><h3 id="10-insurance-claims-first-notice-of-loss">10. Insurance Claims First Notice of Loss</h3><p><strong>Pain Point:</strong> The first notice of loss (FNOL) call is high volume, highly structured, and emotionally sensitive, a combination that creates inefficiency for human agents handling high call loads.</p><p><strong>Solution:</strong> A voice agent guides claimants through FNOL data collection, validates policy information, assigns a claim number, and provides next steps, logging the interaction in the claims management system.</p><p><strong>Example:</strong> An auto insurer deploys an inbound FNOL agent that collects accident details, validates coverage, opens a claim record, and schedules adjuster callbacks, handling the structured first-step entirely before escalation.</p><p><strong>Relevant Platforms:</strong> Retell AI, VideoSDK, Bland</p><h3 id="11-recruiting-and-hr-screening">11. Recruiting and HR Screening</h3><p><strong>Pain Point:</strong> High-volume hiring pipelines require initial screening of hundreds of applicants for basic qualification criteria before a human recruiter engages.</p><p><strong>Solution:</strong> An outbound voice agent contacts applicants, conducts a structured screening call covering availability, compensation expectations, and role-specific qualifications, and passes only meeting criteria to the recruiter pipeline.</p><p><strong>Example:</strong> A staffing agency uses an outbound screening agent to conduct first-round qualification calls for warehouse and logistics roles, reducing recruiter time spent on unqualified candidates.</p><p><strong>Relevant Platforms:</strong> Bland, Retell AI, Vapi</p><h3 id="12-emergency-and-utility-outage-notifications">12. Emergency and Utility Outage Notifications</h3><p><strong>Pain Point:</strong> Utility providers need to notify thousands of affected customers during outages and collect restoration preference data without adequate staffing for manual outbound calling at scale.</p><p><strong>Solution:</strong> An outbound voice agent places mass notification calls, delivers outage status and estimated restoration times, and collects customer preferences (callback when restored, text update, no contact), all within minutes of an event trigger.</p><p><strong>Example:</strong> An electric utility runs automated outbound calling to affected customers within 10 minutes of a detected outage, providing estimated restoration time and collecting preferences, without manual operator involvement.</p><p><strong>Relevant Platforms:</strong> Bland, Vapi, Retell AI</p><h3 id="13-multimodal-voice-screen-agents-for-enterprise-workflows">13. Multimodal Voice + Screen Agents for Enterprise Workflows</h3><p><strong>Pain Point:</strong> Enterprise SaaS environments contain complex multi-step workflows, expense approvals, procurement requests, HR processes, that employees initiate and monitor through voice but need to reference or control on-screen elements to complete.</p><p><strong>Solution:</strong> Multimodal agents combine voice input with screen reading or UI action capabilities, allowing an employee to speak a command ("Approve the three pending invoices from last week") while the agent navigates the ERP interface, identifies the correct records, and executes the action, providing verbal confirmation of each step.</p><p><strong>Example:</strong> A finance team uses a multimodal voice + screen agent within their ERP to approve purchase orders, generate expense reports, and query budget allocations by speaking commands, with the agent providing real-time narration of each action taken.</p><p><strong>Relevant Platforms:</strong> VideoSDK, ElevenLabs (ElevenAgents multimodal), OpenAI (Realtime API + screen context)</p><h2 id="how-to-choose-an-ai-voice-agent-platform-in-2026">How to Choose an AI Voice Agent Platform in 2026</h2><p>The right platform depends on five criteria that have different weights for different teams. This decision framework maps each criterion to the platforms best positioned to satisfy it.</p><p><strong>1. Latency requirements.</strong> Real-time telephony requires end-to-end pipeline latency below 800ms for conversations to feel natural; sub-500ms is optimal for consumer-facing use cases. Asynchronous use cases (post-call summarization, voicemail handling) have no latency constraint. For sub-500ms real-time telephony, VideoSDK (transport &lt;80ms), ElevenLabs Flash v2.5 (75ms synthesis), Cartesia Sonic 3 (40–90ms synthesis), and Deepgram (sub-300ms end-to-end) are the primary options.</p><p><strong>2. Deployment model.</strong> Teams with strict data residency, sovereignty requirements, or security policies that prohibit third-party cloud processing need self-hosting or private cloud. VideoSDK and Bland (dedicated GPU infrastructure for enterprise) are the only platforms in this list with documented self-hosting options. Teams without those constraints can use any managed-cloud platform.</p><p><strong>3. Modularity needs.</strong> Teams that want to select best-in-class components independently, choosing Deepgram for STT accuracy, Claude for reasoning, and Cartesia for synthesis latency, need VideoSDK or Vapi, which support fully pluggable pipelines. Teams that prioritize simplicity over component optimization should use ElevenLabs (integrated stack), Retell AI (bundled pricing), or Synthflow (no-code, bundled).</p><p><strong>4. Compliance requirements.</strong> HIPAA with a Business Associate Agreement is required for any use case involving protected health information. Retell AI includes HIPAA on standard plans. VideoSDK supports HIPAA with enterprise configuration. ElevenLabs and Synthflow gate HIPAA behind their Enterprise tiers. Bland requires direct confirmation from sales. For GDPR and data residency, VideoSDK (self-hosting option) and ElevenLabs (EU zero-retention mode) provide documented paths.</p><p><strong>5. Team technical capability.</strong> Developer API-first platforms (VideoSDK, Vapi, Bland, OpenAI) require engineering resources for integration, pipeline configuration, and ongoing maintenance. No-code platforms (Synthflow, Voiceflow, and VideoSDK's Agent Runtime) enable deployment without engineering support, <a href="https://docs.videosdk.live/ai_agents/agent-runtime/build-agent" rel="noreferrer">VideoSDK's Agent Runtime</a> is notable because it gives non-technical users the same infrastructure used by developers, with no capability ceiling when engineering resources become available.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-11--2026--06_09_58-PM.png" class="kg-image" alt="Best AI Voice Agents & Platforms in 2026 | Tested & Ranked" loading="lazy" width="1678" height="937"><figcaption><span style="white-space: pre-wrap;">Which AI Voice Agent Platform Is Right for You?</span></figcaption></img></figure><h2 id="notable-mentions-2026">Notable Mentions (2026)</h2><p>Three platforms have gained meaningful traction since the original version of this article and merit attention for specific use cases.</p><p><a href="https://cartesia.ai/sonic" rel="noreferrer nofollow"><strong>Cartesia</strong></a> is a latency-first voice AI company whose Sonic 3 TTS model delivers 40–90 ms time-to-first-audio via a state-space model (SSM) architecture, which is meaningfully faster than transformer-based competitors. In 2026, Cartesia expanded beyond TTS with Ink (streaming STT) and Line (a development platform combining voice input and output). It is increasingly used as the synthesis layer in low-latency modular stacks (often paired with Deepgram for STT and Vapi for orchestration). Credit-based pricing starts from a free tier; paid plans from $4/month. Best for: engineering teams where sub-100ms TTS latency is the primary constraint.</p><p><a href="https://www.hume.ai/" rel="noreferrer nofollow"><strong>Hume AI</strong></a> provides the Empathic Voice Interface (EVI), the only platform in the market that analyzes tone, prosody, and timbre in real time to adapt agent responses to the caller's emotional state. In March 2026, Hume open-sourced the <a href="https://www.hume.ai/blog/opensource-tada" rel="noreferrer nofollow">Text-Acoustic Dual Alignment</a> (TADA) framework that powers EVI's emotional detection. Production latency is approximately 1.2 seconds end-to-end, higher than latency-optimized alternatives, but this reflects a deliberate architectural choice to compute full emotional context before responding. Enterprise pricing drops below $0.02/minute at volume. Best for: mental health applications, digital companions, interview simulations, and customer support scenarios where caller frustration detection reduces escalations.</p><h2 id="conclusion"><strong>Conclusion</strong></h2><p>The voice AI market in 2026 is defined by three structural shifts: LLM quality has reached the threshold where agents handle nuanced, multi-turn conversations without degradation; compliance infrastructure (HIPAA, SOC 2, GDPR) is available at standard plan pricing on leading platforms; and multimodal agentic architectures are moving from demo to production in enterprise workflows. The three enterprise use cases driving the largest share of deployment investment are customer support automation, healthcare appointment and triage workflows, and outbound sales and lead qualification.</p><p>For different reader profiles, three recommendations follow:</p><p><strong>Solo developer prototyping:</strong> Start with VideoSDK's $20 free credit or Vapi's $10 free credits. Both offer API-first access to full pipeline control with minimal upfront cost, and either can be running a prototype within hours.</p><p><strong>Enterprise team deploying at scale:</strong> Evaluate VideoSDK for full infrastructure control and self-hosting, or Retell AI if HIPAA compliance without an enterprise contract is the primary requirement. In both cases, benchmark end-to-end latency and test accuracy under realistic noise conditions before committing to annual contracts.</p><p><strong>Non-technical business owner:</strong> Synthflow provides the fastest path from zero to a working AI phone agent without developer involvement. Use the 14-day unlimited trial to validate the use case before committing to a paid plan.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><p><strong>Q1. What is an AI voice agent and how does it work?</strong></p><p>An AI voice agent is a software system that conducts spoken conversations with humans by combining four technical layers: a speech-to-text (STT) engine that converts the user's spoken words into text, a large language model (LLM) that processes that text and generates a response, an optional retrieval-augmented generation (RAG) module that queries external knowledge bases to ground the response in real data, and a text-to-speech (TTS) engine that converts the generated response back into audio and plays it to the user. The entire cycle, from the user finishing speaking to the agent beginning its response, takes between 300ms and 800ms in well-configured production systems. The agent maintains memory of previous turns in the conversation, so users do not need to repeat context. Unlike traditional IVR systems, which rely on pre-recorded menu options and touch-tone input, AI voice agents understand free-form speech and can handle open-ended questions, multi-step tasks, and dynamic data lookups in real time.</p><p><strong>Q2. What is the difference between an AI voice agent and a traditional IVR system?</strong></p><p>A traditional interactive voice response (IVR) system routes callers through a menu of pre-recorded options, responding to touch-tone keypresses or a limited set of spoken keywords. It cannot understand natural language, maintain conversational context, or handle requests that fall outside its programmed menu tree. An AI voice agent, by contrast, understands free-form speech, can interpret intent regardless of how the caller phrases a request, retains context across the entire conversation, and can query live business data, CRM records, inventory systems, appointment calendars, to complete tasks in a single call. IVR systems are inexpensive to deploy and maintain for simple routing scenarios. AI voice agents require more infrastructure investment but can resolve a substantially higher proportion of calls without human involvement, and do so in a conversational manner that users experience as more satisfying than menu navigation.</p><p><strong>Q3. Which AI voice agent platform has the lowest latency in 2026?</strong></p><p>Latency in a voice agent pipeline is the sum of STT processing time, LLM inference time, TTS synthesis time, and network transport time. No single platform dominates all four layers. For TTS synthesis specifically, Cartesia Sonic 3 delivers 40–90ms time-to-first-audio, and ElevenLabs Flash v2.5 delivers 75ms model latency, both the fastest in the category. Murf's Falcon model reports 130ms time-to-first-audio across 33 edge locations. For STT, Deepgram Nova-3 consistently delivers sub-300ms processing with high accuracy on noisy audio. For full end-to-end pipeline latency with telephony, VideoSDK's WebRTC transport layer operates below 80ms globally, and Retell AI reports approximately 620ms end-to-end with low jitter. For developers assembling a latency-optimized stack, the combination of VideoSDK transport + Deepgram STT + a fast LLM + Cartesia TTS represents the current lowest-latency modular architecture available.</p><p><strong>Q4. Can AI voice agents be HIPAA compliant?</strong></p><p>Yes. HIPAA compliance for an AI voice agent requires a signed Business Associate Agreement (BAA) with the platform provider and proper configuration to prevent unauthorized storage or processing of protected health information (PHI). In 2026, the platforms with documented HIPAA compliance and BAA availability include VideoSDK, Retell AI (on standard plans), Deepgram, Bland (requires direct sales confirmation), and Synthflow (Enterprise tier). ElevenLabs provides HIPAA compliance on the Enterprise Agents tier only. Voiceflow's HIPAA status applies to the Enterprise tier; verify current certification status with the sales team. Any platform that uses third-party STT, LLM, or TTS providers also requires that those providers' data processing agreements are HIPAA-compatible, a detail that teams assembling modular stacks on Vapi or VideoSDK need to evaluate for each component.</p><p><strong>Q5. How much does it cost to build an AI voice agent in 2026?</strong></p><p>Production costs vary significantly by architecture choice. A modular stack on Vapi combining Deepgram STT ($0.004/min), GPT-4o mini LLM ($0.02/min), ElevenLabs Turbo TTS ($0.036/min), and Vapi orchestration ($0.05/min) runs approximately $0.15/minute, plus telephony. A premium stack with GPT-4o and ElevenLabs multilingual voice can reach $0.35–0.40/minute. Retell AI in a standard configuration costs $0.11–0.15/minute all-in. Synthflow all-in ranges from $0.15 to $0.24/minute. Bland's Scale plan ($499/month) bills $0.11/minute for connected time plus transfer and SMS fees. For a small business handling 1,000 calls per month at an average 3-minute call duration, total costs range from approximately $330 (Retell AI at $0.11/min) to $1,200 (premium Vapi stack at $0.40/min). Enterprise platforms with dedicated infrastructure, custom compliance configurations, and high-volume discounts typically negotiate rates below $0.05/minute at scale.</p><p><strong>Q6. What is the best no-code AI voice agent platform?</strong></p><p><strong>Synthflow</strong> and <a href="https://docs.videosdk.live/ai_agents/agent-runtime/build-agent" rel="noreferrer">VideoSDK Agent runtime</a> is the strongest no-code option for teams building AI phone agents. Its visual drag-and-drop builder allows non-technical users to design, test, and deploy outbound and inbound phone agents without writing code, typically within 30 minutes for a standard configuration. ElevenLabs voices are bundled on paid plans, and CRM integrations with HubSpot and Salesforce are native. The 14-day unlimited trial enables rapid evaluation before commitment. <strong>Voiceflow</strong> is the alternative for teams where chat is the primary interaction surface and voice is secondary, its canvas editor and collaboration tools are best-in-class for design-led teams, but it is not optimized for high-volume telephony. <strong>Retell AI</strong> occupies a middle position: its template-based dashboard is accessible to non-technical operators, but its full capabilities require developer SDK access.</p><p><strong>Q7. Can I use my own LLM with an AI voice agent platform?</strong></p><p>Yes, with most developer-focused platforms in 2026. <strong>VideoSDK</strong> and <strong>Vapi</strong> both support bring-your-own-LLM (BYO LLM), any model accessible via a standard API can be configured as the intelligence layer of the agent. Vapi passes LLM costs through at provider rates without markup. <strong>Retell AI</strong> supports LLM pass-through at provider cost across a wide range of models, including GPT-class, Claude, and Groq. <strong>Voiceflow</strong> supports BYO LLM on Enterprise plans only. <strong>Synthflow</strong> has more limited LLM flexibility, with a smaller set of supported models compared to fully modular platforms. For teams with fine-tuned or proprietary models hosted on custom infrastructure, VideoSDK's self-hosted pipeline architecture is the only option in this list that supports connecting to an LLM endpoint outside of a major commercial provider, provided the model exposes a standard chat completions API.</p><p><strong>Q8. What is VideoSDK used for in AI voice agents?</strong></p><p>VideoSDK functions as the infrastructure layer of an AI voice agent stack: it provides the audio transport (WebRTC mesh with sub-80ms global latency), the telephony interface (PSTN inbound/outbound and SIP for enterprise phone systems), and the modular pipeline orchestration that connects STT, LLM, and TTS components. Teams use VideoSDK when they need to build a custom agent that runs on their own choice of AI models, for example, Deepgram for STT accuracy, Claude for reasoning, and ElevenLabs for voice quality, without being locked into a specific provider's full stack. VideoSDK's self-hosting option makes it the choice for enterprises with data residency requirements, and its SOC 2 Type II, HIPAA, and GDPR certifications make it viable for healthcare, fintech, and government deployments. Unlike Retell AI or Synthflow, which are opinionated about component selection, VideoSDK functions more like a programmable infrastructure layer, analogous to what AWS provides for compute, where the developer assembles the agent from first principles using VideoSDK's transport, telephony, and pipeline APIs as the foundation.</p>]]></content:encoded></item><item><title><![CDATA[Comprehensive Comparison: Agora, Twilio, Vonage, Zoom, and VideoSDK]]></title><description><![CDATA[VideoSDK, Agora, Twilio, Vonage, and Zoom Video SDK compared on pricing, AI features, latency, interactive features, and developer support. Find the best video SDK for your 2026 project in under 5 minutes.]]></description><link>https://www.videosdk.live/blog/agora-vs-twilio-vs-vonage-vs-zoom-vs-video-sdk-comparison</link><guid isPermaLink="false">63a5439bbd44f53bde5ce4f9</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Sun, 31 May 2026 12:00:00 GMT</pubDate><media:content url="http://assets.videosdk.live/static-assets/ghost/2022/12/indepth-comparison1--1-.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://assets.videosdk.live/static-assets/ghost/2022/12/indepth-comparison1--1-.jpg" alt="Comprehensive Comparison: Agora, Twilio, Vonage, Zoom, and VideoSDK"/><p>VideoSDK is the best video SDK for developers who need a fast, affordable, and fully customizable real-time communication platform. Agora, Twilio, Vonage, and Zoom each serve specific use cases, but VideoSDK delivers the strongest combination of pricing, developer experience, and built-in AI features in 2026.</p><p>Picking the wrong video SDK costs your team weeks of rework. Five platforms dominate this space: VideoSDK, Agora, Twilio, Vonage, and Zoom Video SDK. Each targets a different buyer. This article breaks down pricing, features, audio/video quality, and support so you can choose the right one without guessing.</p><p><a href="https://www.marketsandmarkets.com/Market-Reports/video-conferencing-market-99384414.html">Source</a></p><h2 id="the-verticalization-of-zoom">The 'Verticalization' of Zoom</h2><figure class="kg-card kg-image-card"><img src="http://assets.videosdk.live/static-assets/ghost/2022/12/1_mAa1Q3jHZ8ZggUBLmhsPZA.webp" class="kg-image" alt="Comprehensive Comparison: Agora, Twilio, Vonage, Zoom, and VideoSDK" loading="lazy" width="1400" height="600"/></figure><p><br><a href="https://medium.com/swlh/the-verticalization-of-zoom-eb61a79d1cad">Source</a></br></p><p>The number of 5G subscribers globally is expected to reach 5 billion by 2028.</p><p>According to the latest edition of the <a href="https://www.ericsson.com/4ae28d/assets/local/reports-papers/mobility-report/documents/2022/ericsson-mobility-report-november-2022.pdf">Ericsson Mobility Report</a>, 65% of the world's population would have 5G coverage, with networks handling 45% of global mobile data traffic.</p><p>Video traffic in mobile networks is expected to increase by around 30% per year until 2025. It will account for nearly 75% of mobile data traffic, up from a little more than 60% in 2019.</p><blockquote>This article will evaluate solutions based on six criteria:</blockquote><ul><li><a href="https://www.videosdk.live/blog/agora-vs-twilio-vs-vonage-vs-zoom-vs-video-sdk-comparison#agora-real-time-voice-and-video-engagement">Company Brief Introduction</a></li><li><a href="https://www.videosdk.live/blog/agora-vs-twilio-vs-vonage-vs-zoom-vs-video-sdk-comparison#audio-video-agora-vs-twilio-vs-vonage-vs-zoom-vs-videosdk">Audio/Video</a></li><li><a href="https://www.videosdk.live/blog/agora-vs-twilio-vs-vonage-vs-zoom-vs-video-sdk-comparison#features-agora-vs-twilio-vs-vonage-vs-zoom-vs-videosdk">Features</a></li><li><a href="https://www.videosdk.live/blog/agora-vs-twilio-vs-vonage-vs-zoom-vs-video-sdk-comparison#interactive-features-agora-vs-twilio-vs-vonage-vs-zoom-vs-videosdk">Interactive Features</a></li><li><a href="https://www.videosdk.live/blog/agora-vs-twilio-vs-vonage-vs-zoom-vs-video-sdk-comparison#pricing-agora-vs-twilio-vs-vonage-vs-zoom-vs-videosdk">Pricing</a></li><li><a href="https://www.videosdk.live/blog/agora-vs-twilio-vs-vonage-vs-zoom-vs-video-sdk-comparison#support-agora-vs-twilio-vs-vonage-vs-zoom-vs-videosdk">Support</a></li></ul><h2 id="agora-pioneering-real-time-communication">Agora: Pioneering Real-Time Communication</h2><h3 id="what-is-agoraio">What is Agora.io?</h3><p>Agora is a company that offers a real-time video and audio communication platform. The Agora platform makes it simple for developers to create interactive speech and video apps by offering APIs that allow them to quickly add real-time voice and video features to their applications.</p><p>The Agora platform may be used to create applications for a wide range of use cases, such as real-time video conferencing, live streaming, online education, and customer support. The technology is built to serve huge numbers of users and can offer high-quality audio and video even in low-bandwidth conditions.</p><p>Agora is based in China and has offices in USA. Since its inception in 2012, the firm has grown to become a major provider of real-time communication solutions for businesses and organizations.</p><h2 id="twilio-enhancing-real-time-engagement-within-apps">Twilio: Enhancing Real-Time Engagement within Apps</h2><h3 id="what-is-twilio-and-twilio-video">What is Twilio and Twilio Video?</h3><p>Twilio is a cloud communications platform that allows developers to create, grow, and manage communication solutions through the use of a set of APIs. Twilio's APIs enable developers to add voice, text, and messaging capabilities to their apps, allowing them to communicate in real time with their users.</p><p><a href="https://www.videosdk.live/alternative/twilio-vs-videosdk">Twilio Video</a> may be used to create apps for a wide range of applications, including video conferencing, live streaming, online education, and customer care to making it a valuable tool for the <a href="https://www.surveysensum.com/blog/best-companies-for-customer-experience">best companies for customer experience</a>. The technology is built to serve huge numbers of users and can give better video even in reflects the common.</p><p>Twilio was formed in 2008 and is located in San Francisco, California. It has now grown to become a global provider of cloud communication solutions, servicing customers all over the world.</p><h2 id="vonage-video-seamless-integration-of-communication-apis">Vonage Video: Seamless Integration of Communication APIs</h2><h3 id="what-is-vonage-and-vonage-video">What is Vonage and Vonage Video?</h3><p>Vonage is a cloud communications platform provider that enables businesses and organizations to design, scale, and run communication solutions using a set of APIs (Application Programming Interfaces). Vonage's platform enables developers to integrate phone, message, and video capabilities into their apps, allowing them to engage with their consumers in real time.</p><p><a href="https://www.videosdk.live/alternative/vonage-vs-videosdk">Vonage Video</a> is a cloud communications APIS for real-time video communication platform. Vonage Video makes it simple for developers to develop interactive voice and video apps by providing APIs that allow them to rapidly add real-time video capabilities to their applications.</p><p>Vonage was founded in 1998 in Holmdel, New Jersey. It has now evolved into a global provider of cloud communication solutions, serving customers worldwide.</p><h2 id="zoom-simplifying-video-conferencing">Zoom: Simplifying Video Conferencing</h2><h3 id="what-is-zoom-video-sdk">What is Zoom Video SDK?</h3><p>Zoom Video SDK is a collection of software development frameworks and tools made available by Zoom that enable developers to create unique video-based apps that interface with Zoom's platform. Zoom is a firm that offers a cloud-based videoconferencing and collaboration platform that allows users to connect and speak with one another in real time via the internet.</p><p>The Zoom SDK contains a number of APIs (Application Programming Interfaces) and SDKs (Software Development Kits) that allow developers to integrate video, audio, and messaging capabilities into their applications. Engineers may utilize the <a href="https://videosdk.live/alternative/zoom-vs-videosdk">Zoom SDK</a> to create unique video-based apps for a range of purposes such as videoconferencing, online education, and video broadcasts.</p><p>Zoom Video Communications, Inc. (or simply Zoom) is a San Jose, California-based American communications technology company.</p><h2 id="videosdk-developer-friendly-live-audio-video-integration">VideoSDK: Developer-Friendly Live Audio &amp; Video Integration</h2><h3 id="what-is-videosdk">What is VideoSDK?</h3><p>VideoSDK provides an API that allows developers to easily add powerful, extensible, scalable, and resilient audio-video features to their apps with just a few lines of code. Add live audio and video experiences to any platform in minutes. It abstracts the business logic of the conference room in <a href="https://www.videosdk.live/examples"><em>templates</em></a>. Client-side SDKs include all edge cases within the SDK rather than leaving it to the application.</p><h2 id="audio-video-agora-vs-twilio-vs-vonage-vs-zoom-vs-videosdk">Audio-Video: Agora vs Twilio vs Vonage vs Zoom vs VideoSDK</h2><table>
	<thead>
            <tr><th>
            </th>
			<th>
				<strong>Agora</strong>
			</th>
			<th>
				<strong>Twilio</strong>
			</th>
			<th>
				<strong>Vonage</strong>
			</th>
			<th>
				<strong>Zoom</strong>
			</th>
			<th>
				<strong>VideoSDK</strong>
			</th>
	</tr></thead>
	<tbody>
			<tr>
				<td>Audio Calling</td>
				<td>✔ Built using the SDK</td>
				<td>✔ Built using the SDK</td>
				<td>✔ Built using the SDK</td>
				<td>✔ Built using the SDK</td>
				<td>✔ Built using the SDK</td>
			</tr>
		<tr>
			<td>Video Calling</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
		</tr>
		<tr>
			<td>✔ Interactive Livestreaming</td>
			<td>✔ Built with Agora's Live Streaming SDK</td>
			<td>✔ Built with Twilio Live</td>
			<td>✔ Built with Vonage Live</td>
			<td>✘ No explicit mention in Zoom documentation</td>
			<td>✔ Built using the Video SDK</td>
		</tr>
	</tbody>
</table><h2 id="features-agora-vs-twilio-vs-vonage-vs-zoom-vs-videosdk">Features: Agora vs Twilio vs Vonage vs Zoom vs VideoSDK</h2><table>
	<thead>
<tr>
            <td>
                &nbsp;
            </td>
            <td>
                <strong>Agora</strong>
            </td>
            <td>
                <strong>Twilio</strong>
            </td>
            <td>
                <strong>Vonage</strong>
            </td>
            <td>
                <strong>Zoom</strong>
            </td>
            <td>
                <strong>VideoSDK</strong>
            </td>
        </tr>
	</thead>
	<tbody>
        <tr>
			<td>Recording</td>
			<td>✔ Enabled using the dashboard and API</td>
			<td>✔ Enabled using the dashboard and API</td>
			<td>✔ Enabled using the dashboard and API</td>
			<td>✔ Enabled using the dashboard and API</td>
			<td>✔ Enabled using the dashboard and API</td>
		</tr>
        <tr>
			<td>External Streaming (RTMP Output)</td>
			<td>✔ Built using the Agora SDK</td>
			<td>✘ No direct support for RTMP</td>
			<td>✔ Built using the Vonage SDK</td>
			<td>✔ Built using the Zoom SDK</td>
			<td>✔ Built using the Video SDK</td>
		</tr>
		<tr>
			<td>Screen share</td>
			<td>✔ Built using the SDK.</td>
			<td>✔ Built using getDisplayMedia API</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
		</tr>
		<tr>
			<td>Remote mute</td>
			<td>✔ Built using the Agora RTM SDK.</td>
			<td>✔ Built using the Twilio Live SDK</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
		</tr>
		<tr>
			<td>Active Speaker detection</td>
			<td>✔ Built using the SDK.</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
		</tr>
		<tr>
			<td>Noise reduction</td>
			<td>✔ Built using the third party integration</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Available, currently in Beta.</td>
		</tr>
	</tbody>
</table><h2 id="interactive-features-agora-vs-twilio-vs-vonage-vs-zoom-vs-videosdk">Interactive Features: Agora vs Twilio vs Vonage vs Zoom vs VideoSDK</h2><table>
	<thead>
</thead></table><table>
	<thead>
<tr>
            <td>
                &nbsp;
            </td>
            <td>
                <strong>Agora</strong>
            </td>
            <td>
                <strong>Twilio</strong>
            </td>
            <td>
                <strong>Vonage</strong>
            </td>
            <td>
                <strong>Zoom</strong>
            </td>
            <td>
                <strong>VideoSDK</strong>
            </td>
        </tr>
	</thead>
	<tbody>
		<tr>
			<td>Chat</td>
			<td>✔ Built using the RTM SDK</td>
			<td>✔ Built using Twilio Conversations API.</td>
			<td>✔ Built using the Separate SDK</td>
			<td>✔ Built using the Separate SDK</td>
			<td>✔ Built using Pub/Sub API</td>
		</tr>
			<tr>
				<td>Whiteboard</td>
				<td>✔ Built using the SDK</td>
				<td>✔ Built using the DataTrack API/SDK.</td>
				<td>✘ Unavailable</td>
				<td>✘ No explicit mention in Zoom docs</td>
				<td>✔ Built using Pub/Sub API</td>
			</tr>
			<tr>
				<td>Live polls, Q&amp;A, Quizzes</td>
				<td>✔ Built using the Separate SDK</td>
				<td>✔ Built using the DataTrack API/SDK.</td>
				<td>✘ Unavailable </td>
				<td>✘ No explicit mention in Zoom docs</td>
				<td>✔ Built using Pub/Sub API</td>
			</tr>
		<tr>
			<td>Raise hand</td>
			<td>✔ Built using the agora RTM SDK</td>
			<td>✔ Built using the DataTrack API.</td>
			<td>✘ No explicit mention in Vonage docs</td>
			<td>✘ No explicit mention in Zoom docs</td>
			<td>✔ Built using Pub/Sub API</td>
		</tr>
		<tr>
			<td>Emoji</td>
			<td>✔ Built using the Agora RTM SDK</td>
			<td>✔ Built using the DataTrack API</td>
			<td>✘ No explicit mention in Vonage docs</td>
			<td>✘ Unavailable</td>
			<td>✔ Built using Pub/Sub API</td>
		</tr>
		<tr>
			<td>Notifications</td>
			<td>✔ Built using the Agora RTM SDK.</td>
			<td>✘ No explicit mention in Twilio Video docs</td>
			<td>✔ Built using the SDK </td>
			<td>✘ No explicit mention in Zoom docs</td>
			<td>✔ Built using Pub/Sub API</td>
		</tr>
		<tr>
			<td>Background</td>
			<td>✔ Virtual Background extension available</td>
			<td>✔ Built using the Twilio video processor SDK</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using the SDK</td>
			<td>✔ Built using Custom Video Track</td>
		</tr>
	</tbody>
	</table><p>Resources:  <a href="https://docs.agora.io/en" rel="noopener noreferrer">Agora Docs</a>, <a href="https://www.twilio.com/docs" rel="noopener noreferrer">Twilio Docs</a>, <a href="https://marketplace.zoom.us/docs/sdk/video/introduction/" rel="noopener noreferrer">Zoom Video SDK Docs</a>, <a href="https://developer.vonage.com/documentation" rel="noopener noreferrer">Vonage Docs</a>, <a href="https://docs.videosdk.live/" rel="noopener noreferrer">Video SDK Docs</a></p><h2 id="pricing-agora-vs-twilio-vs-vonage-vs-zoom-vs-videosdk">Pricing: Agora vs Twilio vs Vonage vs Zoom vs VideoSDK</h2><table>
	<thead>
		<tr><td>
		</td>
		<td>
			<strong>Agora</strong>
		</td>
		<td>
			<strong>Twilio</strong>
		</td>
		<td>
			<strong>Vonage</strong>
		</td>
		<td>
			<strong>Zoom</strong>
		</td>
		<td>
			<strong>VideoSDK</strong>
		</td>
	</tr></thead>
	
	<tbody><tr>
		<td>
			Pricing Model
		</td>
		<td>
			On the basis of usage
		</td>
		<td>
			On the basis of usage
		</td>
		<td>
			On the basis of usage + fixed cost
		</td>
		<td>
		On the basis of usage
		</td>
		<td>
		On the basis of usage
		</td>
	</tr>
	<tr>
		<td>Audio-Video Conferencing</td>
		<td>
			Price per 1,000 minutes depending on aggregate resolution <br>Audio: $0.99<br>Video HD: $3.99<br>Video Full HD: $8.99<br>Video 2K: $15.99<br>
Video 2K+: $35.99
</br></br></br></br></br></td>
		<td>Twilio P2P: $1.5 per participant per minute 1,000 minutes<br>Twilio Video Groups: $4.00 per participant minute 1,000 minutes</br></td>
		<td>Vonage Video Groups: $4 per participant minute 1,000 minutes +($9.99 par month)</td>
		<td>Zoom Video Groups: $3.5 per participant minute 1,000 minutes<br>
				 — $1,000/ year with 30,000 free minutes included per month. Priced at $0.003/min after free minutes
		</br></td>
		<td>Video SDK Video Groups:Audio: $0.60<br>Video SD: $2.00<br>Video HD: $3.00<br>Video Full HD: $7.00<br>
		</br></br></br></br></td></tr>
</tbody></table><table>
	<thead>
		<tr><td>
		</td>
		<td>
			<strong>Agora</strong>
		</td>
		<td>
			<strong>Twilio</strong>
		</td>
		<td>
			<strong>Vonage</strong>
		</td>
		<td>
			<strong>Zoom</strong>
		</td>
		<td>
			<strong>VideoSDK</strong>
		</td>
	</tr></thead>
	
	<tbody><tr>
		<td>
			Streaming
		</td>
		<td>
			The <a href="https://docs.agora.io/en/Interactive%20Broadcast/product_live?platform=Android">price</a> of interactive live streaming is determined by the number of participant minutes for the host and audience, as
			well as the latency. <a href="https://docs.agora.io/en/Interactive%20Broadcast/product_live?platform=Android"> Details can be
				found here.</a>.
		</td>
		<td>
			Twilio Live—Video streaming: <br>Broadcaster: $0.004/min<br>Viewer: $0.0025/min<br>Encoding: $0.010/min
	</br></br></br></td>
		<td>
			The Vonage <a href="https://www.vonage.com/communications-apis/video/pricing/">price</a> of interactive live streaming is determined by the number of participant minutes for the host and audience, as well as the
			latency. <a href="https://video-api.support.vonage.com/hc/en-us/articles/360060601492-How-does-participant-based-video-pricing-work-">
				Details can be found here.</a>. </td>
		<td>Zoom Video SDK: Streaming is allowed, but information on pricing is unavailable.
		</td>
		<td>
10,000 free minutes per month.<br>Broadcaster: $0.002/min<br>Viewer: <br>$0.0015/min
			Encoding: $0.04/min
		</br></br></br></td>
	</tr>
  </tbody></table><table>
	<thead>
		<tr><td>
		</td>
		<td>
			<strong>Agora</strong>
		</td>
		<td>
			<strong>Twilio</strong>
		</td>
		<td>
			<strong>Vonage</strong>
		</td>
		<td>
			<strong>Zoom</strong>
		</td>
		<td>
			<strong>Video SDK</strong>
		</td>
	</tr></thead>
	
<tbody><tr><td>
	Recording
</td>
<td>
	Agora charge per participant minute: 
		Per 1000 Per participant minute: : <br>Voice: $1.49 <br>HD: $5.99 <br>Full HD: $13.49 <br>2K: $23.99 <br>2K+: $53.99
		<br>
		Web Page Recording:  <br> HD $14.00 <br> FHD $28.00
			</br></br></br></br></br></br></br></br></td>
<td>
	Twilio charge per Recording participant minute:  $0.0125 <br>Per composed minute <br>$0.04</br></br></td>
<td>
	Vonage charge per Recording participant minute:  $0.0125 <br>Per composed minute <br>SD: $1.49 <br>HD: $0.035
				<br>Full HD: $0.045</br></br></br></br></td>
<td>
Zoom Video SDK:Recording available with a Video SDK account and a Cloud Recording
		Storage Plan. Information on pricing is unavailable.</td>
<td>
	Web Page Recording:<br>$0.015/min
				</br></td>
		</tr>
 </tbody></table><h2 id="support-agora-vs-twilio-vs-vonage-vs-zoom-vs-videosdk">Support: Agora vs Twilio vs Vonage vs Zoom vs VideoSDK</h2><table>
	<tbody>
		<tr>
			<td>
			</td>
			<td>
				<strong>Agora</strong>
			</td>
			<td>
				<strong>Twilio</strong>
			</td>
			<td>
				<strong>Vonage</strong>
			</td>
			<td>
				<strong>Zoom</strong>
			</td>
			<td>
				<strong>VideoSDK</strong>
			</td>
		</tr>
		<tr>
			<td>
			  Support plan monthly cost
			</td>
			<td>
		<strong>Standard Plan: </strong>$1200/month<br><strong>Premium Plan: </strong>$2900/month<br><strong>Enterprise Plan: </strong>$4900/month
			</br></br></td>
			<td>
				<strong>Production Plan: </strong>4% of monthly spend (or $250 minimum)
				<br>
				<strong>Business Plan: </strong>6% of monthly spend (or $1,500 minimum)
				<br>
				<strong>Personalized Plan: </strong>8% of monthly spend (or $5,000 minimum)
			</br></br></td>
			<td>
				<strong>Priority: </strong>$750/month
				<br>
				<strong>Premium: </strong>$1,500/month
				<br>
				<strong>Premier: </strong>$3,000/month
				<br>
			</br></br></br></td><td>
				<strong>Premier Developer Support:-</strong>
				<br>
				<br>
				<strong>Bronze - </strong>$675/month
				<br>
				<strong>Silver - </strong>$1,300/month
				<br>
				<strong>Gold - </strong>$1,900/month
			</br></br></br></br></td>
			<td>
				<strong>FREE for everyone</strong>
			</td>
		</tr>
	</tbody>
</table><table>
	<tbody>
		<tr>
			<td>
			</td>
			<td>
				<strong>Agora</strong>
			</td>
			<td>
				<strong>Twilio</strong>
			</td>
			<td>
				<strong>Vonage</strong>
			</td>
			<td>
				<strong>Zoom</strong>
			</td>
			<td>
				<strong>VideoSDK</strong>
			</td>
		</tr>
		<tr>
	<td>
		Access to TAM / CS Engineer
	</td>
	<td>
		<strong>Premium plan:</strong>
		- Access to CS enginee
		- Code Review
		<br>
		<strong>Enterprise plan</strong>
		- Everything in the Premium plan plus access to SA Engineer &amp; Live Developer Consultation and Training.
	</br></td>
	<td>
		Only available in the Personalized plan. The plan also provides a support escalation line and quarterly status review.
	</td>
	<td>
		Available for Premier customers.
	</td>
	<td>
		Premier Developer Support provides developer enablement, onboarding, training, and architectural consultations.
	</td>
	<td>
		All paying customers have access to a dedicated CS manager and a solutions engineer.
	</td>
	</tr>
	<tr>
	</tr></tbody>
</table><table>
	<tbody>
		<tr>
			<td>
			</td>
			<td>
				<strong>Agora</strong>
			</td>
			<td>
				<strong>Twilio</strong>
			</td>
			<td>
				<strong>Vonage</strong>
			</td>
			<td>
				<strong>Zoom</strong>
			</td>
			<td>
				<strong>VideoSDK</strong>
			</td>
		</tr>
	<tr>
		<td>
		SLAs
		</td>
		<td>
			<strong>Standard Plan:</strong>
			P1 – 4 Business hours
			P2 – 16 business hours
			P3 – 24 business hours
			<br>
			<strong>Premium Plan:</strong>
			P1 – 3 hours(24/7)
			P2 – 8 business hours
			P3 – 16 business hours
			<br>
			<strong>Enterprise Plan:</strong>
			P1 – 2 hours (24/7)
			P2 – 5 business hours
			P3 – 9 business hours
		</br></br></td>
		<td>
			<strong>Production Plan:</strong>
			P1 - 3 business hours
			P2 - 6 business hours
			P3 - 9 business hours
			<br>
			<strong>Business Plan:</strong>
			P1 - 1 hour (24/7)
			P2 - 2 business hours
			P3 - 3 business hour
			<br>
			<strong>Personalized Plan:</strong>
			P1 - 1 hour (24/7)
			P2 - 2 business hours
			P3 - 3 business hours
		</br></br></td>
		<td>
			<strong>Service Level Targets (SLT) for the initial response for Premium Plus:</strong>
			<br>
							S1: 30 minutes
							S2: 2 hours
						  S3: 4 hours
				</br></td>
		<td>
			<strong>Premier Developer Support:-</strong>
			<br>
			<strong>Developer:</strong>
			P1 - N/A
			P2 - N/A
			P3 - N/A
			<br>
			<strong>Bronze:</strong>
			P1 - 24 hours
			P2 - 48 hours
			P3 - 72 hours
			<br>
			<strong>Silver:</strong>
			P1 - 6 hours
			P2 - 12 hours
			P3 - 24 hours
			<br>
			<strong>Gold:</strong>
			P1 - 4 hours
			P2 - 8 hours
			P3 - 16 hours
		</br></br></br></br></td>
		<td>
			Critical - 8 hours
			Major - 72 hours
			Minor - Mutually aligned timeline
		</td>
	</tr>
	</tbody>
</table><table>
	<tbody>
		<tr>
			<td>
			</td>
			<td>
				<strong>Agora</strong>
			</td>
			<td>
				<strong>Twilio</strong>
			</td>
			<td>
				<strong>Vonage</strong>
			</td>
			<td>
				<strong>Zoom</strong>
			</td>
			<td>
				<strong>Video SDK</strong>
			</td>
		</tr>
	<tr><td>
		Channels
	</td>
	<td>
	Submit a ticket directly through the Agora Console.
<br>All support plans offer Ticket/Email support. Premium Enterprise plans to offer Emergency
							Phone Number Access.</br></td>
	<td>Production, Business, and Personalize plans provide live support options with live chat on all three, and phone support on the latter two.<br>Only email support on the Developer plan.
	</br></td>
	<td>
Premier users:
		<br>- Email support
	  <br>- Chat support
		<br>- Phone support
    </br></br></br></td>
	<td>
    No specific communication channels are explicitly mentioned in the Premier Developer Support doc.
	</td>
	<td>
	Interact with support directly on Slack, Discord.<br>Paying customers can access dedicated Slack support.
	</br></td></tr><tr>
	</tr></tbody>
</table><table>
	<tbody>
		<tr>
			<td>
			</td>
			<td>
				<strong>Agora</strong>
			</td>
			<td>
				<strong>Twilio</strong>
			</td>
			<td>
				<strong>Vonage</strong>
			</td>
			<td>
				<strong>Zoom</strong>
			</td>
			<td>
				<strong>Video SDK</strong>
			</td>
		</tr>
	<tr>
		<td>
			Access to Testing
		</td>
		<td>
			Testing is not expressly supported.
		</td>
		<td>
			Testing is not expressly supported.
		</td>
		<td>
			Testing is not expressly supported.
		</td>
		<td>
			Testing is not expressly supported.
		</td>
		<td>
			All paid accounts get access to testing support from Video SDK.
		</td>
	</tr>
	<tr>
	</tr></tbody>
</table><table>
	<tbody>
		<tr>
			<td>
				&nbsp;
			</td>
			<td>
				<strong>Agora</strong>
			</td>
			<td>
				<strong>Twilio</strong>
			</td>
			<td>
				<strong>Vonage</strong>
			</td>
			<td>
				<strong>Zoom</strong>
			</td>
			<td>
				<strong>VideoSDK</strong>
			</td>
		</tr>
    <tr>
			<td>
				Community Support
			</td>
			<td>
				Agora’s Stack Overflow and Community Slack Channel
			</td>
			<td>
				Twilio Forum now largely shifted to Stack Overflow as Twilio Collective.
			</td>
			<td>
				Vonage'S Slack Community
			</td>
			<td>
				Zoom Community
			</td>
			<td>
				VideoSDK has an active <a href="https://discord.gg/Gpmj6eCq5u">Discord Community</a>
			</td>
		</tr>
	</tbody>
</table><p>Resources: <a href="https://www.agora.io/en/pricing/">Agora Pricing</a>, <a href="https://www.twilio.com/video/pricing">Twilio Pricing</a>, <a href="https://zoom.us/buy/videosdk">Zoom Video SDK Pricing</a>, <a href="https://www.vonage.com/communications-apis/video/pricing/">Vonage Video API Pricing</a>, <a href="https://www.videosdk.live/pricing">Video SDK Pricing</a></p><h2 id="definitions-glossary">Definitions Glossary</h2><p><a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer"><strong>WebRTC</strong></a><strong>:</strong>&nbsp;Web Real-Time Communication is defined as an open-source project and W3C/IETF standard that enables browser and mobile applications to exchange audio, video, and data peer-to-peer without plugins.</p><p><strong>SD-RTN:</strong>&nbsp;Software Defined Real-time Network is defined as Agora's proprietary global media routing network that selects optimal transmission paths for real-time media based on live network conditions.</p><p><strong>Video SDK:</strong>&nbsp;A Video SDK is defined as a software development kit that provides APIs, client libraries, and cloud media server access enabling developers to add real-time audio and video communication to applications.</p><p><a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer"><strong>TURN Server</strong></a><strong>:</strong>&nbsp;Traversal Using Relays around NAT is defined as a network relay server used in WebRTC deployments to route media when direct peer-to-peer connections are blocked by firewalls or NAT devices.</p><p><a href="https://www.videosdk.live/blog/cloud-recording-and-rtmp-pricing" rel="noreferrer"><strong>Cloud Recording</strong></a><strong>:</strong>&nbsp;Cloud recording is defined as a feature offered by real-time communication platforms that captures and stores video sessions on the provider's cloud storage without requiring local device resources.</p><h2 id="key-takeaways">Key Takeaways</h2><ul><li>VideoSDK is the strongest all-around choice for new development projects, offering native AI transcription, usage-based pricing with a free tier, and pre-built UI components for all major platforms.</li><li>Agora's SD-RTN network gives it a genuine latency advantage for users in Southeast Asia, China, and other markets where proprietary routing outperforms standard cloud infrastructure.</li><li>Twilio's video product has been sunset for new customers; teams evaluating Twilio for video should confirm current availability and plan a migration path if needed.</li><li>Vonage offers a capable video API built on the OpenTok platform, but the Ericsson acquisition introduced disruptions to developer support that teams should factor into their evaluation.</li><li>Zoom Video SDK is best suited for applications that extend the Zoom ecosystem; its host-based pricing model is costly for apps with many concurrent hosts and low per-host participant counts.</li></ul><h2 id="conclusion">Conclusion</h2><p>The Agora vs Twilio vs Vonage vs Zoom vs VideoSDK comparison comes down to a simple question: what does your use case actually require? For most developer teams building new products in 2026, VideoSDK delivers the fastest path to production, the most transparent pricing, and the only native AI feature set in this category. Sign up for VideoSDK's free tier today and ship your first real-time video experience in under an hour.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="which-video-sdk-is-best-for-developers-in-2026">Which video SDK is best for developers in 2026?</h3><p>VideoSDK is the best video SDK for developers in 2026 for most use cases. VideoSDK offers a $20 free credit, usage-based pricing that scales predictably, native AI transcription and noise cancellation, and pre-built UI components for React, React Native, Flutter, Android, and iOS. Teams that need low latency in Asian markets should also evaluate Agora's SD-RTN network.</p><h3 id="is-agora-or-videosdk-better-for-real-time-applications">Is Agora or VideoSDK better for real-time applications?</h3><p>Both Agora and VideoSDK deliver sub-300ms latency for most global markets. Agora's SD-RTN proprietary network has an edge in Southeast Asia and China. VideoSDK matches Agora's latency performance in North America, Europe, and South Asia while offering a simpler pricing model and native AI features that Agora requires extensions to replicate. The best option for a given team depends on their primary user geography.</p><h3 id="does-twilio-still-offer-a-video-sdk">Does Twilio still offer a video SDK?</h3><p>Twilio announced in 2023 that it was sunsetting Twilio Video for new customers. Existing customers should contact Twilio directly to understand their support timeline. Teams starting new video projects should evaluate VideoSDK, Agora, or Vonage instead.</p><h3 id="how-does-zoom-video-sdk-pricing-compare-to-videosdk">How does Zoom Video SDK pricing compare to VideoSDK?</h3><p>Zoom Video SDK uses a per-host monthly licensing model, which means costs scale with the number of hosts rather than the number of minutes consumed. VideoSDK uses a usage-based model where you pay per minute of audio or video streamed, with a free tier of 10,000 minutes per month [UPDATE: verify current pricing from both vendor pricing pages]. For apps with many concurrent hosts but short session durations, VideoSDK is typically significantly cheaper.</p><h3 id="what-is-the-difference-between-vonage-video-api-and-videosdk">What is the difference between Vonage Video API and VideoSDK?</h3><p>Vonage Video API is built on the OpenTok platform (originally from TokBox, acquired by Vonage, then Ericsson) and uses WebRTC with Vonage's cloud infrastructure. VideoSDK is a purpose-built real-time communication platform with native AI features including transcription and noise cancellation. Vonage requires a Vonage Communications API account as a parent account; VideoSDK does not. VideoSDK's onboarding is faster and its pricing is more transparent for video-only use cases.</p><h3 id="can-i-build-a-telehealth-app-with-videosdk">Can I build a telehealth app with VideoSDK?</h3><p>Yes, VideoSDK is a strong choice for telehealth applications. VideoSDK supports one-on-one video calls, group sessions with up to 100,000 participants in interactive streaming mode, native AI transcription suitable for clinical note generation, and HIPAA-compliant infrastructure configurations [UPDATE: verify current HIPAA compliance status from VideoSDK documentation]. Pre-built UI components for React and React Native reduce frontend development time significantly compared to building from scratch on a raw WebRTC stack.</p><h3 id="is-videosdk-open-source">Is VideoSDK open source?</h3><p>VideoSDK's client-side SDKs are available on GitHub with open-source examples and starter templates. The core media infrastructure is a managed cloud service. VideoSDK's approach differs from Jitsi (fully self-hostable) and from proprietary black-box SDKs like Zoom Video SDK in that developers have full visibility into the client-side code while benefiting from managed cloud media infrastructure.&nbsp;</p>]]></content:encoded></item><item><title><![CDATA[API Key vs API Token: Understanding the Differences]]></title><description><![CDATA[API keys are static app identifiers. API tokens are short-lived, user-specific credentials with scopes and expiry. Learn which to use and how VideoSDK combines both in a secure real-time architecture.]]></description><link>https://www.videosdk.live/blog/api-key-vs-api-token</link><guid isPermaLink="false">66767f5820fab018df10efdb</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 26 May 2026 11:12:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/06/api-key-vs-api-token.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>An API key is a static, long-lived credential that identifies the calling application. An API token is a short-lived, user-specific credential that both identifies and authorizes the caller. Use an API key when you need simple application-level access. Use an API token when you need user-level authentication, session management, or fine-grained permission control.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2024/06/api-key-vs-api-token.jpg" alt="API Key vs API Token: Understanding the Differences"/><p>Two strings of characters. One wrong choice. And your entire authentication layer is either over-engineered or dangerously exposed. API keys and API tokens look similar on the surface, but they solve fundamentally different problems. Pick the wrong one and you either leave sensitive user data under-protected or waste weeks building session management you never needed.</p><p>This article explains exactly what each credential does, how they differ across security, scope, and implementation, and which one to use for your specific use case. You will also see how VideoSDK uses both in a production real-time communication system.</p><h2 id="introduction">Introduction</h2>
<p>In the digital age, secure and efficient management of API interactions is crucial for the development and operation of modern software applications. API keys and tokens are foundational components in this landscape, enabling secure communication between software services. While they both serve to facilitate access control, their functions, implications, and best practices differ significantly. API keys are primarily used to identify the calling application, making them suitable for simpler authentication tasks. On the other hand, API tokens provide a robust mechanism for authenticating and authorizing individual users, offering a deeper level of security and control. This article explores the definitions, uses, and security measures associated with API keys and tokens, providing essential insights into choosing the right method for different scenarios.</p><h2 id="what-is-api-key">What is API Key?</h2>
<p>An API key is a simple yet crucial component in the realm of software development, acting primarily as a unique identifier for application traffic. It does not authenticate individual users but rather serves to recognize the application or the project making a call to an API. This identifier enables external services and applications to interact securely by ensuring that only registered users with valid API keys can access specific functionalities.</p><h3 id="how-api-keys-work">How API Keys Work?</h3>
<p>The operation of an API key is straightforward. When an application makes a request to an API, it must include its API key, typically in the request header. The API server then validates this key against a list of authorized keys. If the key is valid, the server processes the request and returns the desired response. This system not only confirms the authenticity of the requestor but also helps manage and track each request's origin, which can be critical for analyzing usage patterns and enforcing security measures.</p><p>Moreover, API keys are often associated with specific access rights or permissions. For instance, one key might allow a developer to retrieve data, while another could enable the addition or deletion of data. This allows API providers to offer different levels of access to various users, which can be particularly useful for services that charge based on usage levels or that offer premium features.</p><h3 id="security-considerations">Security Considerations</h3>
<p>While API keys are effective for managing access, they are not without security risks. If an API key is exposed, it can be used by unauthorized individuals to access the API, potentially leading to data breaches or service disruptions. Thus, securing API keys is paramount. Best practices for API key security include transmitting keys over HTTPS to prevent interception by third parties, rotating keys regularly to limit the duration of any exposure, and never embedding keys directly in code, where they can be easily extracted by malicious actors.</p><p>API providers must also implement rate limiting to prevent abuse. Rate limiting restricts the number of requests a given API key can make in a certain period, thus protecting the API from overuse and helping to maintain service availability for all users. o further strengthen API security in blockchain-based applications, businesses often <a href="https://www.tecla.io/network/hire-solidity-developers" rel="noreferrer">hire Solidity developers</a> who can implement secure smart contracts and manage authentication processes that protect data integrity and prevent unauthorized access.</p><h2 id="what-is-an-api-token">What is an API Token?</h2>
<p>API tokens are sophisticated credentials that do much more than just identify the source of an API request—they also authenticate and authorize it. Unlike API keys, which are static and somewhat straightforward, tokens such as JSON Web Tokens (JWTs) are rich in structure and information. A typical token contains encoded data that includes details about the user, the token's expiration time, and the permissions granted to the user. This makes tokens particularly suited for scenarios where security and fine-grained access control are paramount.</p><h3 id="security-and-scope">Security and Scope</h3>
<p>The dynamic nature of API tokens allows for more secure interactions. Tokens are generated upon successful user authentication and have a limited lifespan, which reduces the risk of misuse if they are intercepted or exposed. Once a token expires, it must be renewed, often requiring user re-authentication, which adds an additional layer of security.</p><p>The scope of permissions associated with a token can be precisely controlled. For example, a token may grant a user read-only access to certain data while restricting access to other sensitive information. This is in stark contrast to API keys, which generally provide a fixed set of permissions and do not adapt to different user roles or contexts.</p><h3 id="use-cases">Use Cases</h3>
<p>Tokens excel in environments where user-specific authentication is crucial. They are extensively used in web and mobile applications where each user's identity and permissions need to be verified and maintained across sessions. Here are a few typical scenarios where tokens are preferred:</p><h4 id="user-authentication">User Authentication</h4>
<p>In web applications, tokens authenticate users and maintain their sessions, providing a continuous, secure user experience without requiring re-authentication for each request.</p><h4 id="fine-grained-access-control">Fine-Grained Access Control</h4>
<p>For applications that handle sensitive or personal data, tokens can enforce detailed access controls based on the user’s role within the organization or specific permissions granted to them.</p><h4 id="stateful-operations">Stateful Operations</h4>
<p>Applications that need to remember user information across multiple sessions use tokens to manage the state without compromising security. This capability is vital for personalized user experiences in complex applications.</p><h2 id="comparing-api-keys-and-tokens">Comparing API Keys and Tokens</h2>
<h3 id="key-differences">Key Differences</h3>
<p>While API keys and tokens may seem similar at a glance, they serve distinctly different purposes and offer different levels of security and functionality. The primary distinction lies in their scope and security implications:</p><h3 id="scope-of-use">Scope of Use</h3>
<p>API keys are essentially used for identifying the application making the API request, not the user. They are suited for scenarios where the identity of the application is sufficient to grant access to the API. Conversely, API tokens are designed to authenticate and authorize individual users, providing a more granular level of access control. This includes detailed information about user permissions and roles, which is critical in personalized user services.</p><h3 id="security">Security</h3>
<p>API keys are static, which means they do not change unless manually updated or rotated. This can pose a security risk if the key is exposed, as it remains valid until revoked. Tokens, on the other hand, are dynamic and often expire after a short duration, requiring re-authentication to renew, thus providing a more secure framework. Tokens also include additional security layers, such as encoding and potentially encrypting the contents, which are not typical features of API keys.</p><h4 id="implementation-complexity">Implementation Complexity</h4>
<p>API keys are easier to implement and manage as they require less infrastructure and management overhead compared to tokens. Tokens, with their complex structures and requirements for handling expiration and renewal, demand a more sophisticated system to manage.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-4--2026--01_18_16-PM.png" class="kg-image" alt="API Key vs API Token: Understanding the Differences" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">api key vs api token</span></figcaption></img></figure><h2 id="choosing-the-right-one">Choosing the Right One</h2>
<p>Deciding whether to use an API key or a token depends largely on the specific requirements of your application and the level of security you need:</p><h3 id="use-api-keys-when">Use API Keys When</h3>
<ul><li>You need a simple identifier for accessing APIs that do not contain sensitive or personal information.</li><li>Your application interacts with less critical external services where complex authentication is unnecessary.</li><li>You require a method for quick and simple rate limiting or access monitoring without detailed user-level controls.</li></ul><h3 id="use-tokens-when">Use Tokens When</h3>
<ul><li>User authentication is crucial, and you need to securely manage individual user sessions across requests.</li><li>Your application demands detailed access control based on user roles or permissions, especially when dealing with sensitive or personal information.</li><li>You require a system that can dynamically adjust permissions and access rights based on real-time analysis of user actions or attributes.</li></ul><h2 id="api-key-vs-api-token-key-differences">API Key vs API Token: Key Differences</h2><p>The difference between an API key and an API token determines your entire authentication architecture, so these distinctions are worth understanding precisely.</p><table>
<thead>
<tr>
<th>Feature</th>
<th>API Key</th>
<th>API Token (JWT)</th>
<th>Winner</th>
</tr>
</thead>
<tbody>
<tr>
<td>Identifies</td>
<td>Application</td>
<td>User or session</td>
<td>Token (for user-level apps)</td>
</tr>
<tr>
<td>Lifespan</td>
<td>Indefinite (until revoked)</td>
<td>Short-lived (15 min to 24 hours)</td>
<td>Token (lower risk on compromise)</td>
</tr>
<tr>
<td>Contains user data</td>
<td>No</td>
<td>Yes (encoded in payload)</td>
<td>Token (for personalized access)</td>
</tr>
<tr>
<td>Expiration</td>
<td>Manual rotation required</td>
<td>Automatic via expiry claim</td>
<td>Token</td>
</tr>
<tr>
<td>Permission scopes</td>
<td>Fixed per key</td>
<td>Granular per token</td>
<td>Token</td>
</tr>
<tr>
<td>Implementation complexity</td>
<td>Low</td>
<td>Medium-high</td>
<td>API Key</td>
</tr>
<tr>
<td>Server-side lookup required</td>
<td>Yes (every request)</td>
<td>No (self-contained)</td>
<td>Token (for performance at scale)</td>
</tr>
<tr>
<td>Revocation</td>
<td>Instant (delete from registry)</td>
<td>Complex (requires blocklist)</td>
<td>API Key</td>
</tr>
<tr>
<td>Best For</td>
<td>App-to-app integrations, public APIs</td>
<td>User authentication, session management</td>
<td>Context-dependent</td>
</tr>
</tbody>
</table>
<h2 id="conclusion">Conclusion</h2>
<p>Understanding the differences between API keys and tokens is fundamental for developers and IT security professionals tasked with safeguarding digital interactions. While API keys offer a straightforward solution for identifying applications, they fall short in environments where user-specific authentication and fine-grained access controls are necessary. API tokens, with their dynamic and detailed approach to user permissions, are better suited for these more complex scenarios. By employing the appropriate authentication method—be it API keys for basic access control or tokens for advanced user-specific permissions—organizations can enhance the security and functionality of their digital platforms. As technology evolves and security demands intensify, the strategic implementation of these tools will continue to play a critical role in the development of secure and efficient software ecosystems.</p><h2 id="faqs-on-api-keys-and-api-tokens">FAQs on API Keys and API Tokens</h2>
<h3 id="1-what-is-an-api-key-and-how-is-it-used">1. What is an API key and how is it used?</h3>
<p>An API key is a unique identifier used to authenticate a calling application or project when making requests to an API. It helps manage access and track how the API is being used, but does not provide information about the user. API keys are typically used for simpler authentication tasks where user-specific security is not critical.</p><h3 id="2-how-do-api-tokens-differ-from-api-keys">2. How do API tokens differ from API keys?</h3>
<p>Unlike API keys, which only identify the application making the request, API tokens authenticate and authorize individual users, providing more detailed access control. API tokens contain encoded data about the user, their permissions, and the token's validity, making them suitable for scenarios that require stringent security measures and fine-grained access control.</p><h3 id="3-what-are-the-best-practices-for-securing-api-keys">3. What are the best practices for securing API keys?</h3>
<p>To secure API keys, it is recommended to transmit them only over HTTPS, rotate them regularly, and avoid hard-coding them in the application's source code. Additionally, implementing rate limiting and monitoring usage can help prevent abuse and detect potential security breaches.</p><h3 id="4-why-might-an-organization-choose-to-use-api-tokens-over-api-keys">4. Why might an organization choose to use API tokens over API keys?</h3>
<p>Organizations might prefer API tokens when they need robust user authentication, dynamic permissions management, and secure, personalized user interactions. Tokens are ideal in environments where access needs to be tightly controlled based on user roles or specific actions within an application.</p><h3 id="5-can-api-tokens-be-used-for-stateful-operations">5. Can API tokens be used for stateful operations?</h3>
<p>Yes, API tokens are well-suited for stateful operations as they can maintain user information across sessions. This is beneficial for applications that require a seamless user experience, where the user's identity and permissions need to be persistently managed without repeatedly asking for authentication.</p><h3 id="6-what-are-common-use-cases-for-api-keys">6. What are common use cases for API keys?</h3>
<p>Common use cases for API keys include third-party service integrations, simple authentication processes, and situations where detailed user-specific permissions are not necessary. They are often used in server-to-server communications, accessing public data, and rate limiting.</p><h3 id="7-are-api-tokens-more-secure-than-api-keys">7. Are API tokens more secure than API keys?</h3>
<p>Generally, API tokens are considered more secure than API keys because they offer more comprehensive security features, such as expiration, encoding, and potentially encryption. They also provide more granular control over what actions can be performed by the authenticated user, reducing the risk of unauthorized access.</p><h3 id="8-how-can-developers-manage-and-monitor-the-usage-of-api-keys-and-tokens-effectively">8. How can developers manage and monitor the usage of API keys and tokens effectively?</h3>
<p>Developers can manage and monitor API keys and tokens by using dedicated API management tools that provide features like key and token generation, expiration settings, activity logs, and security alerts. These tools help ensure that keys and tokens are used safely and according to organizational policies.</p><h3 id="9-what-should-an-organization-do-if-an-api-key-or-token-is-exposed">9. What should an organization do if an API key or token is exposed?</h3>
<p>If an API key or token is exposed, the organization should immediately revoke the compromised key or token, audit all recent API activity to check for unauthorized access, and implement stricter security measures to prevent future exposures.</p>]]></content:encoded></item><item><title><![CDATA[How to Add a Voice AI Agent to Your iOS App with VideoSDK]]></title><description><![CDATA[Build a real-time Voice AI agent for iOS without managing WebRTC, speech-to-text, or real-time audio pipelines yourself. With VideoSDK, you can configure your agent, run the iOS starter app, and launch a voice AI experience in minutes.]]></description><link>https://www.videosdk.live/blog/how-to-add-a-voice-ai-agent-to-your-ios-app-with-videosdk</link><guid isPermaLink="false">69f9d87655831517a5a9f708</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 11 May 2026 13:31:53 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/2564--2-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/05/2564--2-.png" alt="How to Add a Voice AI Agent to Your iOS App with VideoSDK"/><p>Building a voice AI agent sounds complex. WebRTC, speech-to-text, text-to-speech, real-time audio pipelines  it's a lot to figure out before you even open Xcode.</p><p>VideoSDK takes all of that off your plate. You configure your agent from a dashboard, clone a starter app, add your credentials, and run it on your device. That's the whole process. This guide walks you through each step so you can go from zero to a working voice AI iOS app in one sitting.</p><h2 id="what-youre-building">What You're Building</h2><p>By the end of this tutorial, you'll have an iOS app where:</p><ul><li>A user opens the app and joins a meeting room</li><li>A deployed AI agent automatically joins that same room</li><li>The user speaks, the agent listens, and responds in real time</li><li>Live transcription shows up on screen as the conversation happens</li></ul><h2 id="before-you-start">Before You Start</h2><p>Here's what you need before writing a single line of code:</p><ul><li><strong>A VideoSDK account</strong> — Sign up at <a href="https://app.videosdk.live/">app.videosdk.live</a> if you haven't already.</li><li><strong>A deployed AI agent</strong> — VideoSDK has a Low-Code Deployment UI in the dashboard. You configure your agent's persona and pipeline (Realtime or Cascading) directly from there, no code required. Once it's deployed, grab your <strong>Agent ID</strong> and <strong>Version ID</strong> from the dashboard.</li><li><strong>Your Auth Token</strong> — Head to the <a href="https://app.videosdk.live" rel="noreferrer">API Keys section of the VideoSDK </a>Dashboard. For development, you can generate a temporary token right there. In production, generate this from your own backend to keep your credentials safe.</li><li><strong>Xcode 16.4 or later</strong> — Check your version in Xcode under About Xcode. The app targets iOS 18 or later, so make sure your simulator or physical device is on iOS 18.</li></ul><h2 id="step-1-create-your-agent">Step 1: Create Your Agent</h2><p>Before touching any code, you need an agent deployed on VideoSDK. This is done entirely from the dashboard, no coding required.</p><h3 id="11-build-your-agent">1.1 Build Your Agent</h3><p>Head to the VideoSDK Dashboard and follow the <a href="https://docs.videosdk.live/ai_agents/agent-runtime/build-agent">Build a Custom Voice AI Agent</a> guide. Here you'll set up your agent's persona, give it a name and personality, and choose its pipeline type:</p><ul><li><strong>Realtime pipeline</strong> — lower latency, better for fast back-and-forth conversations</li><li><strong>Cascading pipeline</strong> — more control over each stage (STT, LLM, TTS) separately</li></ul><p>You can also test your agent directly from the dashboard before deploying it.</p><h3 id="12-deploy-your-agent">1.2 Deploy Your Agent</h3><p>Once you're happy with the configuration, hit Deploy. VideoSDK builds and hosts your agent on its Agent Cloud infrastructure.</p><h3 id="13-get-your-agent-id-and-version-id">1.3 Get Your Agent ID and Version ID</h3><p>You'll need two identifiers to connect your iOS app to the agent:</p><p><strong>Agent ID</strong> — After creating your agent, open its page and find the JSON editor on the right side. Copy the <code>agentId</code> from there.</p><p><strong>Version ID</strong> — Click the three dots next to the Deploy button and select "Version History". Each time you deploy, a new version is created. Copy the version ID for the version you want to use. If you skip this, the app will automatically pick the latest deployed version.</p><figure class="kg-card kg-image-card"><img src="https://strapi.videosdk.live/uploads/agent_version_id_0f8b59830a.png" class="kg-image" alt="How to Add a Voice AI Agent to Your iOS App with VideoSDK" loading="lazy" width="3756" height="2155"/></figure><p>Keep both of these handy. You'll need them in Step 4 when configuring your credentials.</p><h2 id="step-2-clone-the-starter-app">Step 2: Clone the Starter App</h2><p>VideoSDK provides a ready-to-go iOS starter app. Clone it and navigate into the project folder:</p><pre><code class="language-bash">git clone https://github.com/videosdk-live/agent-starter-app-ios.git
cd agent-starter-ios
</code></pre><h2 id="step-3-open-the-project-in-xcode">Step 3: Open the Project in Xcode</h2><p>Open the project file in Xcode:</p><pre><code class="language-bash">open agent-starter-ios.xcodeproj
</code></pre><p>Or double-click <code>agent-starter-ios.xcodeproj</code> from Finder. Xcode will load the project and index the files.</p><h2 id="step-4-set-up-your-credentials">Step 4: Set Up Your Credentials</h2><p>Instead of an <code>.env</code> file, the iOS app uses a Swift constants file. Open <code>agent-starter-ios/Constants/MeetingConfig.swift</code> in Xcode and fill in your values:</p><pre><code class="language-swift">AUTH_TOKEN: &lt;VideoSDK authorization token&gt;
AGENT_ID: &lt;The ID of the Agent on VideoSDK&gt;
MEETING_ID: &lt;VideoSDK Meeting ID | Optional&gt;
VERSION_ID: &lt;VideoSDK Agent's Version ID | Optional&gt;
</code></pre><p>A quick note on each:</p><ul><li><strong>AUTH_TOKEN</strong> — your VideoSDK token from the dashboard</li><li><strong>AGENT_ID</strong> — the ID of the agent you deployed from the dashboard</li><li><strong>MEETING_ID</strong> — optional. If you leave this blank, the app will create a new meeting room automatically</li><li><strong>VERSION_ID</strong> — optional. If you leave this blank, the app will fetch the latest deployed version of your agent</li></ul><h2 id="step-5-build-and-run">Step 5: Build and Run</h2><p>Select your target device or simulator from the device picker in Xcode, then click the Run button or press <code>Cmd + R</code>.</p><p>Once the app launches, allow microphone access when prompted, and start talking. The app uses VideoSDK's Dispatch API to send your deployed agent into the meeting room. You'll see transcription appear on screen in real time as you speak and as the agent responds.</p><h2 id="whats-happening-under-the-hood">What's Happening Under the Hood</h2><p>When the app starts, a few things happen in sequence:</p><ol><li>The app calls VideoSDK's API to create (or join) a meeting room</li><li>It uses the <strong>Dispatch API</strong> to summon your deployed agent into that room, passing it the <code>AGENT_ID</code> and <code>VERSION_ID</code></li><li>The agent joins as a participant, listens through the room's audio channel, and responds using its configured pipeline</li><li>The SDK streams transcription back to the iOS frontend in real time</li></ol><p>You don't manage any of that manually. The SDK and your dashboard-deployed agent handle it.</p><h2 id="real-world-use-cases">Real-World Use Cases</h2><p>Once you have this running, you're one agent config away from building any of these:</p><ul><li><strong>Customer Support Bots</strong> Replace your static FAQ chatbot with a voice-first support agent. Users speak their issue, the agent understands context, and responds instantly.</li><li><strong>AI Interview Practice Tools</strong> Build a mock interview app where the AI agent asks questions, listens to answers, and gives feedback. Great for job seekers, students, or sales training.</li><li><strong>Voice-Enabled Coding Assistants</strong> Let developers describe what they want to build, and the agent helps them think through solutions, hands-free while they're heads-down in their editor.</li><li><strong>Interactive Learning and Tutoring</strong> Build a language learning app, a math tutor, or an onboarding guide that actually talks back. Learners engage better when they can have a real conversation.</li><li><strong>Accessibility-First Interfaces</strong> For users who struggle with keyboards or touchscreens, a voice AI agent makes your product genuinely usable, not just technically compliant.</li></ul><h2 id="troubleshooting">Troubleshooting</h2><p>A few things to check if something isn't working:</p><ul><li><strong>Agent isn't joining the room</strong> Double-check your <code>AGENT_ID</code> and <code>VERSION_ID</code> in <code>MeetingConfig.swift</code>. A single wrong character here is the most common culprit. Also verify your VideoSDK token is valid and has the necessary permissions.</li><li><strong>Audio isn't working</strong> Check that the app has microphone permissions on your device. Go to Settings, find the app, and make sure microphone access is enabled.</li><li><strong>"Failed to connect agent" error</strong> Verify your <code>AGENT_ID</code> and <code>VERSION_ID</code> are correct. Open the Xcode debug console and look for network errors, they usually point to exactly what's wrong.</li></ul><h2 id="wrapping-up">Wrapping Up</h2><p>Adding a voice AI agent to an iOS app used to mean stitching together STT, TTS, WebRTC, and a custom backend. With VideoSDK, you configure your agent from a dashboard, clone a starter app, fill in a config file, and run it from Xcode.</p><p>The Dispatch API does the heavy lifting. Your agent shows up in the room, listens, and responds. You just build the experience around it.</p><p>If you haven't deployed your agent yet, start there. The Low-Code Deployment UI on the VideoSDK Dashboard walks you through it without touching code. Once it's deployed, come back here and you'll be live in under 10 minutes.</p><p><strong>Ready to build?</strong></p><ul><li>VideoSDK Dashboard link - <a href="https://app.videosdk.live/">Sign up for VideoSDK</a></li><li>Github link to <a href="https://github.com/videosdk-live/agent-starter-app-ios">Clone the iOS Starter App</a></li><li>Explore and <a href="https://docs.videosdk.live/">Read the full docs</a> here.</li><li>Connect with our <a href="https://www.videosdk.live/contact" rel="noreferrer">support team</a> for guidance and enterprise use cases.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[Add a Voice AI Agent to Your Android App in Minutes]]></title><description><![CDATA[Build a real-time Voice AI agent for Android without handling WebRTC, speech-to-text, or audio pipeline complexity. With VideoSDK, you can configure your agent, integrate the Android starter app, and launch a voice AI experience in minutes.]]></description><link>https://www.videosdk.live/blog/add-a-voice-ai-agent-to-your-android-app-in-minutes</link><guid isPermaLink="false">69f9d6c955831517a5a9f6ed</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 11 May 2026 13:30:59 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/android.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/05/android.png" alt="Add a Voice AI Agent to Your Android App in Minutes"/><p>Adding a conversational AI agent to a mobile app used to take weeks. With VideoSDK, you can have a voice-enabled AI agent talking to your users in a live Android session in just a few steps.</p><p>No separate backend. No model wiring. Just your Android app and a deployed agent.</p><h2 id="what-youll-build">What You'll Build</h2><p>By the end of this guide, your Android app will:</p><ul><li>Join a real-time meeting room</li><li>Automatically invite an AI agent into that room</li><li>Let users talk to the agent using their microphone</li><li>Show live transcriptions of the conversation</li></ul><h2 id="prerequisites">Prerequisites</h2><p>Before you start, make sure you have:</p><ul><li>An <strong>Android device or emulator</strong> running Android 8.0 (API 26+)</li><li><strong>Android Studio</strong> with JDK 17</li><li>A <strong>VideoSDK account</strong> (<a href="https://app.videosdk.live/">sign up free</a>)</li></ul><h2 id="step-1-create-your-ai-agent-on-the-dashboard">Step 1: Create Your AI Agent on the Dashboard</h2><p>You don't need to write any agent code. Head to the <a href="https://app.videosdk.live/agents/agents">VideoSDK Agents Dashboard</a> and:</p><ol><li>Click <strong>Create Agent</strong></li><li>Give it a name and set its instructions (personality, tone, what it should do)</li><li>Choose a pipeline (<strong>Realtime</strong> for low-latency voice)</li><li>Hit <strong>Deploy</strong></li></ol><p>Once deployed, copy the <strong>Agent ID</strong> from the JSON editor on the agent's page. You'll need it shortly.</p><h2 id="step-2-clone-the-starter-app">Step 2: Clone the Starter App</h2><pre><code class="language-bash">git clone https://github.com/videosdk-live/agent-starter-app-android.git
cd agent-starter-app-android
</code></pre><p>Open the folder in Android Studio and let Gradle sync finish.</p><h2 id="step-3-add-your-credentials">Step 3: Add Your Credentials</h2><p>Copy the example config file:</p><pre><code class="language-bash">cp local.properties.example local.properties
</code></pre><p>Open <code>local.properties</code> and fill in your values:</p><pre><code class="language-properties">authToken=your_videosdk_auth_token
agentId=your_agent_id
meetingId=        # optional, leave blank to auto-create
versionId=        # optional, leave blank to use the latest version
</code></pre><p>You can get your <code>authToken</code> from the <a href="https://app.videosdk.live/api-keys">VideoSDK Dashboard</a>.</p><h2 id="step-4-run-the-app">Step 4: Run the App</h2><p>Connect a physical device or start an emulator (API 26+), then hit <strong>Run</strong> in Android Studio or run:</p><pre><code class="language-bash">./gradlew installDebug
</code></pre><p>Grant microphone permissions when prompted. Your AI agent will join the meeting room automatically and start the conversation.</p><h2 id="what-happens-under-the-hood">What Happens Under the Hood</h2><p>When the app starts, it calls VideoSDK's <strong>Dispatch API</strong> with your <code>agentId</code>. VideoSDK spins up the agent and drops it into the same meeting room as your user. From there it's a live voice conversation: the agent listens, responds, and the app shows a real-time transcript.</p><h2 id="use-cases">Use Cases</h2><p>This pattern works well for a range of Android apps:</p><ul><li><strong>Customer support</strong> - Let users speak to an AI assistant instead of filling out forms</li><li><strong>Voice-first interfaces</strong> - Build apps where users navigate entirely by talking</li><li><strong>Interview or quiz tools</strong> - An agent can ask questions and evaluate responses in real time</li><li><strong>Language learning</strong> - Conversational practice with an AI partner</li><li><strong>Accessibility tools</strong> - Give users with limited motor control a hands-free way to interact</li></ul><h2 id="conclusion">Conclusion</h2><p>With VideoSDK, adding a voice AI agent to your Android app comes down to four steps: create an agent on the dashboard, clone the starter repo, drop in your credentials, and run. No model hosting, no audio pipeline setup, no extra infrastructure.</p><p>The starter app gives you voice, live transcription, screen sharing, and device controls out of the box so you can focus on building the experience, not the plumbing.</p><h2 id="next-steps-and-resources">Next Steps and Resources</h2><ul><li><a href="http://blogs.videosdk.live/ai_agents/agent-runtime/connect-agent/mobile-integrations/agent-starter-android">Android Agent Starter - Full Quickstart Guide</a></li><li>VideoSDK Dashboard link - <a href="https://app.videosdk.live/">Sign up for VideoSDK</a></li><li>Explore and <a href="https://docs.videosdk.live/">Read the full docs</a> here.</li><li>Connect with our <a href="https://www.videosdk.live/contact" rel="noreferrer">support team</a> for guidance and enterprise use cases.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[How to Add a Voice AI Agent to Your Flutter App with VideoSDK]]></title><description><![CDATA[Build a real-time Voice AI agent in Flutter without dealing with WebRTC, speech-to-text, or audio streaming complexity. With VideoSDK, you can configure your agent, run a starter app, and launch a working voice AI experience across Android, iOS, and desktop in minutes.]]></description><link>https://www.videosdk.live/blog/how-to-add-a-voice-ai-agent-to-your-flutter-app-with-videosdk</link><guid isPermaLink="false">69f9d7ec55831517a5a9f6fc</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 11 May 2026 13:29:29 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/2564--3-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/05/2564--3-.png" alt="How to Add a Voice AI Agent to Your Flutter App with VideoSDK"/><p>Building a voice AI agent sounds complex. WebRTC, speech-to-text, text-to-speech, real-time audio pipelines  it's a lot to figure out before you even write your first Flutter widget.</p><p>VideoSDK takes all of that off your plate. You configure your agent from a dashboard, clone a starter app, add your credentials, and run it. That's the whole process. This guide walks you through each step so you can go from zero to a working voice AI app in one sitting on both Android and iOS.</p><h2 id="what-youre-building">What You're Building</h2><p>By the end of this tutorial, you'll have a Flutter app where:</p><ul><li>A user opens the app and joins a meeting room</li><li>A deployed AI agent automatically joins that same room</li><li>The user speaks, the agent listens, and responds in real time</li><li>Live transcription shows up on screen as the conversation happens</li></ul><h2 id="before-you-start">Before You Start</h2><p>Here's what you need before writing a single line of code:</p><p><strong>1) A VideoSDK account</strong> — Sign up at <a href="https://app.videosdk.live/">app.videosdk.live</a> if you haven't already.</p><p><strong>2) A deployed AI agent</strong> — VideoSDK has a Low-Code Deployment UI in the dashboard. You configure your agent's persona and pipeline (Realtime or Cascading) directly from there, no code required. Once it's deployed, grab your <strong>Agent ID</strong> and <strong>Version ID</strong> from the dashboard.</p><p><strong>3) Your Auth Token</strong> — Head to the <a href="https://app.videosdk.live" rel="noreferrer">API Keys section of the VideoSDK</a> Dashboard. For development, you can generate a temporary token right there. In production, generate this from your own backend to keep your credentials safe.</p><p><strong>4) Flutter 3.8.0 or later</strong> — Required if you're targeting iOS. Check with <code>flutter --version</code> if you're unsure. Also make sure you're on Dart 3.x or later.</p><h2 id="step-1-create-your-agent">Step 1: Create Your Agent</h2><p>Before touching any code, you need an agent deployed on VideoSDK. This is done entirely from the dashboard, no coding required.</p><h3 id="11-build-your-agent">1.1 Build Your Agent</h3><p>Head to the VideoSDK Dashboard and follow the <a href="https://docs.videosdk.live/ai_agents/agent-runtime/build-agent">Build a Custom Voice AI Agent</a> guide. Here you'll set up your agent's persona, give it a name and personality, and choose its pipeline type:</p><ul><li><strong>Realtime pipeline</strong> — lower latency, better for fast back-and-forth conversations</li><li><strong>Cascading pipeline</strong> — more control over each stage (STT, LLM, TTS) separately</li></ul><p>You can also test your agent directly from the dashboard before deploying it.</p><h3 id="12-deploy-your-agent">1.2 Deploy Your Agent</h3><p>Once you're happy with the configuration, hit Deploy. VideoSDK builds and hosts your agent on its Agent Cloud infrastructure.</p><h3 id="13-get-your-agent-id-and-version-id">1.3 Get Your Agent ID and Version ID</h3><p>You'll need two identifiers to connect your Flutter app to the agent:</p><p><strong>Agent ID</strong> — After creating your agent, open its page and find the JSON editor on the right side. Copy the <code>agentId</code> from there.</p><p><strong>Version ID</strong> — Click the three dots next to the Deploy button and select "Version History". Each time you deploy, a new version is created. Copy the version ID for the version you want to use.</p><figure class="kg-card kg-image-card"><img src="https://strapi.videosdk.live/uploads/agent_version_id_0f8b59830a.png" class="kg-image" alt="How to Add a Voice AI Agent to Your Flutter App with VideoSDK" loading="lazy" width="3756" height="2155"/></figure><p>Keep both of these handy. You'll need them in Step 4 when setting up your environment variables.</p><h2 id="step-2-clone-the-starter-app">Step 2: Clone the Starter App</h2><p>VideoSDK provides a ready-to-go Flutter starter app. Clone it and navigate into the project folder:</p><pre><code class="language-bash">git clone https://github.com/videosdk-live/agent-starter-app-flutter.git
cd agent-starter-flutter
</code></pre><h2 id="step-3-install-dependencies">Step 3: Install Dependencies</h2><pre><code class="language-bash">flutter pub get
</code></pre><p>This fetches all the packages your app needs, including the VideoSDK Flutter SDK and everything else in the pubspec.</p><h2 id="step-4-set-up-your-environment-variables">Step 4: Set Up Your Environment Variables</h2><p>Copy the example env file:</p><pre><code class="language-bash">cp .env.example .env
</code></pre><p>Now open <code>.env</code> and fill in your credentials:</p><pre><code class="language-env">AUTH_TOKEN=your_videosdk_auth_token
AGENT_ID=your_agent_id
VERSION_ID=your_version_id
MEETING_ID=your_meeting_id
</code></pre><p>A quick note on each:</p><ul><li><strong>AUTH_TOKEN</strong> — your VideoSDK token from the dashboard</li><li><strong>AGENT_ID</strong> — the ID of the agent you deployed from the dashboard</li><li><strong>VERSION_ID</strong> — the specific version of your agent you want to run (find this under "Version History" on your agent's page)</li><li><strong>MEETING_ID</strong> — optional. If you leave this blank, the app will create a new meeting room automatically</li></ul><h2 id="step-5-run-the-app">Step 5: Run the App</h2><p><strong>On Android:</strong></p><pre><code class="language-bash">flutter run
</code></pre><p><strong>On iOS:</strong></p><pre><code class="language-bash">cd ios &amp;&amp; pod install &amp;&amp; cd ..
flutter run -d ios
</code></pre><p>Open the app on your device or simulator, allow microphone access, and start talking. The app uses VideoSDK's Dispatch API to send your deployed agent into the meeting room. You'll see transcription appear on screen in real time as you speak and as the agent responds.</p><h2 id="whats-happening-under-the-hood">What's Happening Under the Hood</h2><p>When the app starts, a few things happen in sequence:</p><ol><li>The app calls VideoSDK's API to create (or join) a meeting room</li><li>It uses the <strong>Dispatch API</strong> to summon your deployed agent into that room, passing it the <code>AGENT_ID</code> and <code>VERSION_ID</code></li><li>The agent joins as a participant, listens through the room's audio channel, and responds using its configured pipeline</li><li>The SDK streams transcription back to the Flutter frontend in real time</li></ol><p>You don't manage any of that manually. The SDK and your dashboard-deployed agent handle it.</p><h2 id="real-world-use-cases">Real-World Use Cases</h2><p>Once you have this running, you're one agent config away from building any of these:</p><ul><li><strong>Customer Support Bots</strong> Replace your static FAQ chatbot with a voice-first support agent. Users speak their issue, the agent understands context, and responds instantly.</li><li><strong>AI Interview Practice Tools</strong> Build a mock interview app where the AI agent asks questions, listens to answers, and gives feedback. Great for job seekers, students, or sales training.</li><li><strong>Voice-Enabled Coding Assistants</strong> Let developers describe what they want to build, and the agent helps them think through solutions, hands-free while they're heads-down in their editor.</li><li><strong>Interactive Learning and Tutoring</strong> Build a language learning app, a math tutor, or an onboarding guide that actually talks back. Learners engage better when they can have a real conversation.</li><li><strong>Accessibility-First Interfaces</strong> For users who struggle with keyboards or touchscreens, a voice AI agent makes your product genuinely usable, not just technically compliant.</li></ul><h2 id="troubleshooting">Troubleshooting</h2><p>A few things to check if something isn't working:</p><ul><li><strong>Agent isn't joining the room</strong> Double-check your <code>AGENT_ID</code> and <code>VERSION_ID</code> in <code>.env</code>. A single wrong character here is the most common culprit.</li><li><strong>Audio isn't working</strong> Check that your device has microphone permissions enabled for the app. On iOS and Android both, you may need to grant this manually in system settings.</li><li><strong>"Failed to connect agent" error</strong> Verify your token is still valid and hasn't expired. Check the debug console for network errors, they usually point to exactly what's wrong.</li><li><strong>Flutter build issues</strong> Make sure you're on Flutter 3.8.0 or later (required for iOS). If you're running into dependency issues, try these in order:</li></ul><pre><code class="language-bash">flutter clean
</code></pre><p>Then delete <code>pubspec.lock</code> and run:</p><pre><code class="language-bash">flutter pub get
</code></pre><p>For iOS specifically, always run pod install before launching:</p><pre><code class="language-bash">cd ios &amp;&amp; pod install
flutter run -d ios
</code></pre><h2 id="wrapping-up">Wrapping Up</h2><p>Adding a voice AI agent to a Flutter app used to mean stitching together STT, TTS, WebRTC, and a custom backend. With VideoSDK, you configure your agent from a dashboard, clone a starter app, fill in a few env vars, and run it on Android or iOS.</p><p>The Dispatch API does the heavy lifting. Your agent shows up in the room, listens, and responds. You just build the experience around it.</p><p>If you haven't deployed your agent yet, start there. The Low-Code Deployment UI on the VideoSDK Dashboard walks you through it without touching code. Once it's deployed, come back here and you'll be live in under 10 minutes.</p><h2 id="ready-to-build"><strong>Ready to build?</strong></h2><ul><li>VideoSDK Dashboard link - <a href="https://app.videosdk.live/">Sign up for VideoSDK</a></li><li>Github link to <a href="https://github.com/videosdk-live/agent-starter-app-flutter">Clone the Flutter Starter App</a></li><li>Explore and <a href="https://docs.videosdk.live/">Read the full docs</a> here.</li><li>Connect with our <a href="https://www.videosdk.live/contact" rel="noreferrer">support team</a> for guidance and enterprise use cases.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[How to Add a Voice AI Agent to Your React App with VideoSDK]]></title><description><![CDATA[Learn how to build a real-time Voice AI agent in React without handling WebRTC, speech-to-text, or audio pipelines yourself. With VideoSDK, you can configure your agent, run a starter app, and launch a working voice AI experience in minutes.]]></description><link>https://www.videosdk.live/blog/how-to-add-a-voice-ai-agent-to-your-react-app-with-videosdk</link><guid isPermaLink="false">69f9b25e55831517a5a9f6d6</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 11 May 2026 13:27:55 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/2564.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/05/2564.png" alt="How to Add a Voice AI Agent to Your React App with VideoSDK"/><p>Building a voice AI agent sounds complex. WebRTC, speech-to-text, text-to-speech, real-time audio pipelines - it's a lot to figure out before you even write your first React component.</p><p>VideoSDK takes all of that off your plate. You configure your agent from a dashboard, clone a starter app, add your credentials, and run it. That's the whole process. This guide walks you through each step so you can go from zero to a working voice AI app in one sitting.</p><h2 id="what-youre-building">What You're Building</h2><p>By the end of this tutorial, you'll have a React app where:</p><ul><li>A user opens the app and joins a meeting room</li><li>A deployed AI agent automatically joins that same room</li><li>The user speaks, the agent listens, and responds in real time</li><li>Live transcription shows up on screen as the conversation happens</li></ul><h2 id="before-you-start">Before You Start</h2><p>Here's what you need before writing a single line of code:</p><ul><li><strong>A VideoSDK account</strong> — Sign up at <a href="https://app.videosdk.live/signup" rel="noreferrer">app.videosdk.live</a> if you haven't already.</li><li><strong>A deployed AI agent</strong> — VideoSDK has a Low-Code Deployment UI in the dashboard. You configure your agent's persona and pipeline (Realtime or Cascading) directly from there, no code required. Once it's deployed, grab your <strong>Agent ID</strong> and <strong>Version ID</strong> from the dashboard.</li><li><strong>Your Auth Token</strong> — Follow this <a href="https://docs.videosdk.live/ai_agents/authentication-and-token" rel="noreferrer">docs for creating a auth token</a><ul><li> For development, you can generate a temporary token right there. In production, generate this from your own backend to keep your credentials safe.</li></ul></li><li><strong>Node.js v18 or later</strong> — Check with <code>node -v</code> if you're unsure.</li></ul><h2 id="step-1-create-your-agent">Step 1: Create Your Agent</h2><p>Before touching any code, you need an agent deployed on VideoSDK. This is done entirely from the dashboard, no coding required.</p><h3 id="11-build-your-agent">1.1 Build Your Agent</h3><p>Head to the VideoSDK Dashboard and follow the <a href="https://docs.videosdk.live/ai_agents/agent-runtime/build-agent">Build a Custom Voice AI Agent</a> guide. Here you'll set up your agent's persona, give it a name and personality, and choose its pipeline type:</p><ul><li><strong>Realtime pipeline</strong> — lower latency, better for fast back-and-forth conversations</li><li><strong>Cascading pipeline</strong> — more control over each stage (STT, LLM, TTS) separately</li></ul><p>You can also test your agent directly from the dashboard before deploying it.</p><h3 id="12-deploy-your-agent">1.2 Deploy Your Agent</h3><p>Once you're happy with the configuration, hit Deploy. VideoSDK builds and hosts your agent on its Agent Cloud infrastructure.</p><h3 id="13-get-your-agent-id-and-version-id">1.3 Get Your Agent ID and Version ID</h3><p>You'll need two identifiers to connect your React app to the agent:</p><p><strong>Agent ID</strong> — After creating your agent, open its page and find the JSON editor on the right side. Copy the <code>agentId</code> from there.</p><p><strong>Version ID</strong> — Click the three dots next to the Deploy button and select "Version History". Each time you deploy, a new version is created. Copy the version ID for the version you want to use.</p><figure class="kg-card kg-image-card"><img src="https://strapi.videosdk.live/uploads/agent_version_id_0f8b59830a.png" class="kg-image" alt="How to Add a Voice AI Agent to Your React App with VideoSDK" loading="lazy" width="3756" height="2155"/></figure><p>Keep both of these handy. You'll need them in Step 4 when setting up your environment variables.</p><h2 id="step-2-clone-the-starter-app">Step 2: Clone the Starter App</h2><p>VideoSDK provides a ready-to-go React starter app. Clone it and navigate into the project folder:</p><pre><code class="language-bash">git clone https://github.com/videosdk-live/agent-starter-app-react.git
cd agent-starter-react
</code></pre><h2 id="step-3-install-dependencies">Step 3: Install Dependencies</h2><pre><code class="language-bash">npm install
# or
yarn install
</code></pre><p>This pulls in everything the app needs: the VideoSDK SDK, React, and all the supporting packages.</p><h2 id="step-4-set-up-your-environment-variables">Step 4: Set Up Your Environment Variables</h2><p>Copy the example env file:</p><pre><code class="language-bash">cp .env.example .env
</code></pre><p>Now open <code>.env</code> and fill in your credentials:</p><pre><code class="language-env">AUTH_TOKEN=your_videosdk_auth_token
AGENT_ID=your_agent_id
VERSION_ID=your_version_id
MEETING_ID=your_meeting_id
</code></pre><p>A quick note on each:</p><ul><li><strong>AUTH_TOKEN</strong> — your VideoSDK token from the dashboard</li><li><strong>AGENT_ID</strong> — the ID of the agent you deployed from the dashboard</li><li><strong>VERSION_ID</strong> — the specific version of your agent you want to run (find this under "Version History" on your agent's page)</li><li><strong>MEETING_ID</strong> — optional. If you leave this blank, the app will create a new meeting room automatically</li></ul><h2 id="step-5-run-the-app">Step 5: Run the App</h2><pre><code class="language-bash">npm run dev
# or
yarn dev
</code></pre><p>Open your browser, allow microphone access, and start talking. The app uses VideoSDK's Dispatch API to send your deployed agent into the meeting room. You'll see transcription appear on screen in real time as you speak and as the agent responds.</p><h2 id="whats-happening-under-the-hood">What's Happening Under the Hood</h2><p>When you hit run, a few things happen in sequence:</p><ol><li>The app calls VideoSDK's API to create (or join) a meeting room</li><li>It uses the <strong>Dispatch API</strong> to summon your deployed agent into that room, passing it the <code>AGENT_ID</code> and <code>VERSION_ID</code></li><li>The agent joins as a participant, listens through the room's audio channel, and responds using its configured pipeline</li><li>The SDK streams transcription back to the frontend in real time</li></ol><p>You don't manage any of that manually. The SDK and your dashboard-deployed agent handle it.</p><h2 id="real-world-use-cases">Real-World Use Cases</h2><p>Once you have this running, you're one agent config away from building any of these:</p><p><strong>1) Customer Support Bots</strong> Replace your static FAQ chatbot with a voice-first support agent. Users speak their issue, the agent understands context, and responds instantly.</p><p><strong>2) AI Interview Practice Tools</strong> Build a mock interview app where the AI agent asks questions, listens to answers, and gives feedback. Great for job seekers, students, or sales training.</p><p><strong>3) Voice-Enabled Coding Assistants</strong> Let developers describe what they want to build, and the agent helps them think through solutions, hands-free while they're heads-down in their editor.</p><p><strong>4) Interactive Learning and Tutoring</strong> Build a language learning app, a math tutor, or an onboarding guide that actually talks back. Learners engage better when they can have a real conversation.</p><p><strong>5) Accessibility-First Interfaces</strong> For users who struggle with keyboards or touchscreens, a voice AI agent makes your product genuinely usable, not just technically compliant.</p><h2 id="troubleshooting">Troubleshooting</h2><p>A few things to check if something isn't working:</p><ul><li><strong>Agent isn't joining the room</strong> Double-check your <code>AGENT_ID</code> and <code>VERSION_ID</code> in <code>.env</code>. A single wrong character here is the most common culprit.</li><li><strong>Audio isn't working</strong> Check that your browser has microphone permissions. Most browsers will prompt you, but it's worth checking in your system settings too.</li><li><strong>"Failed to connect agent" error</strong> Verify your token is still valid and hasn't expired. Check the browser console for network errors, they usually point to exactly what's wrong.</li><li><strong>React build issues</strong> Make sure you're on Node.js 18 or higher. If you're seeing weird dependency errors, try a clean install:</li></ul><pre><code class="language-bash">rm -rf node_modules
npm install
</code></pre><h2 id="conslusion">Conslusion</h2><p>Adding a voice AI agent to a React app used to mean stitching together STT, TTS, WebRTC, and a custom backend. With VideoSDK, you configure your agent from a dashboard, clone a starter app, fill in a few env vars, and run it.</p><p>The Dispatch API does the heavy lifting. Your agent shows up in the room, listens, and responds. You just build the experience around it.</p><p>If you haven't deployed your agent yet, start there. The Low-Code Deployment UI on the VideoSDK Dashboard walks you through it without touching code. Once it's deployed, come back here and you'll be live in under 10 minutes.</p><h2 id="ready-to-build"><strong>Ready to build?</strong></h2><ul><li>VideoSDK Dashboard link - <a href="https://app.videosdk.live/signup" rel="noreferrer">Sign up for VideoSDK</a></li><li>Github link to <a href="https://github.com/videosdk-live/agent-starter-app-react">Clone the React Starter App</a></li><li>Explore and <a href="https://docs.videosdk.live/">Read the full docs</a> here.</li><li>Connect with our <a href="https://www.videosdk.live/contact" rel="noreferrer">support team</a> for guidance and enterprise use cases.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[How to Build an LGPD-Compliant Telehealth App in Brazil]]></title><description><![CDATA[A step-by-step developer guide to building a telehealth app that complies with Brazil's LGPD and CFM Resolution 2.314/2022, using VideoSDK Flutter and React SDKs with verified E2EE and geo-fencing setup.]]></description><link>https://www.videosdk.live/blog/lgpd-compliant-telehealth-app-brazil</link><guid isPermaLink="false">69fd957055831517a5a9fc1a</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 08 May 2026 08:31:47 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-8--2026--01_25_50-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>Building a telehealth app in Brazil requires LGPD-compliant data handling for health data, adherence to CFM Resolution 2.314/2022 for telemedicine practice, and a real-time video infrastructure that keeps sensitive patient data secure. This guide uses VideoSDK's Flutter and React SDKs, with verified API methods, E2EE, geo-fencing, and cloud recording, to walk you through a production-ready architecture.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-8--2026--01_25_50-PM.png" alt="How to Build an LGPD-Compliant Telehealth App in Brazil"/><p>Building an LGPD-compliant <a href="https://www.videosdk.live/blog/build-compliant-telemedicine-app-react" rel="noreferrer">telehealth app</a> in Brazil requires encrypting all session media, collecting explicit patient consent before any data is processed, and using a video infrastructure that can route traffic through Brazilian or regional servers. <a href="https://www.gov.br/esporte/pt-br/acesso-a-informacao/lgpd" rel="noreferrer"><strong>LGPD</strong> (Lei Geral de Proteção de Dados</a>, Brazil's comprehensive data protection law, enacted in 2020) classifies health data as sensitive data, which carries stricter processing rules than ordinary personal data. VideoSDK provides the <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/flutter-sdk" rel="noreferrer">Flutter SDK</a>, <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">React SDK</a>, <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/security/E2EE" rel="noreferrer">E2EE</a>, <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/geo-fencing-and-proxy-controls/geo-fencing" rel="noreferrer">geo-fencing</a>, and <a href="https://www.videosdk.live/blog/cloud-recording-and-rtmp-pricing" rel="noreferrer">cloud recording</a> needed to meet these requirements in a single integration.</p><h2 id="lgpd-and-cfm-requirements-for-telehealth">LGPD and CFM requirements for telehealth</h2><h3 id="what-lgpd-requires-for-health-data">What LGPD requires for health data</h3><p><a href="https://lgpd-brazil.info/chapter_02/article_11" rel="noreferrer nofollow"><strong>Sensitive data</strong>&nbsp;under LGPD (Article 11)</a> includes health and biometric data. Processing this category requires one of two legal bases: explicit and specific consent from the data subject, or a health necessity carried out by a qualified professional bound by professional secrecy.</p><p>For a telehealth app, this translates into three concrete obligations:</p><p><strong>Data minimisation:</strong> Collect only the data that is strictly necessary for the consultation. Do not store video frames beyond the legally required retention period. Do not share identifiable health data with analytics or advertising services.</p><p><strong>Explicit consent:</strong> The patient must give free, informed, and unambiguous consent before the video session starts. The consent must state what data is collected, why it is collected, how long it will be retained, and who will have access. A pre-ticked checkbox does not satisfy this requirement.</p><p><strong>Data subject rights:</strong> Patients may request access, correction, deletion, or portability of their data at any time (Articles 18-20). Your app must provide a documented mechanism to respond to these requests within 15 days.</p><p>The <a href="https://www.gov.br/anpd/pt-br" rel="noreferrer nofollow"><strong>ANPD</strong>&nbsp;(Autoridade Nacional de Proteção de Dados, Brazil's data protection authority)</a> can impose fines of up to 2% of a company's Brazilian revenue in the prior fiscal year, capped at R$50 million per infraction (Article 52).</p><h3 id="cfm-resolution-23142022-requirements">CFM Resolution 2.314/2022 requirements</h3><p><a href="https://pmc.ncbi.nlm.nih.gov/articles/PMC9838663/" rel="noreferrer nofollow"><strong>CFM Resolution 2.314/2022</strong></a> is the Brazilian Federal Council of Medicine regulation that governs telemedicine practice. It replaced the temporary rules from the COVID-19 period and establishes permanent requirements for remote consultations.</p><p>The resolution requires that any <a href="https://www.videosdk.live/blog/webrtc-vs-zoom-sdk-vs-videosdk-for-telehealth" rel="noreferrer">telemedicine session</a> use a secure channel, meaning a channel that protects the privacy and confidentiality of the doctor-patient relationship. A simple video call over an unencrypted or third-party public platform does not satisfy this requirement. The regulation also requires that the consultation be documented in a medical record, and that digital prescriptions issued during the session comply with CFM's digital signature and tracking requirements.</p><p>Key practical requirements for your application:</p><ul><li>The video channel must provide confidentiality equivalent to a physical consultation.</li><li>A medical record entry must be created for each teleconsultation.</li><li>The patient must give informed consent to the teleconsultation modality before the session.</li><li>Prescriptions issued remotely must use a certified digital signature system.</li></ul><p>The <a href="https://www.videosdk.live/" rel="noreferrer">video infrastructure</a> itself only covers the secure channel requirement. Your application layer must implement the medical record and prescription components.</p><h2 id="why-videosdk-for-brazilian-telehealth">Why VideoSDK for Brazilian telehealth</h2><p>VideoSDK provides three features that are directly relevant to LGPD and CFM compliance.</p><p><strong>Geo-fencing:</strong> VideoSDK's Flutter SDK includes a Geo Fencing and Proxy Controls feature (documented at <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/geo-fencing-and-proxy-controls/geo-fencing" rel="noreferrer">Geo Fencing - Flutter</a>). This allows you to restrict or prefer media routing to specific geographic regions, which supports the goal of keeping patient data within defined jurisdictions. Contact VideoSDK support for region-specific server configuration for Brazil.</p><p><a href="https://www.videosdk.live/blog/what-is-end-to-end-encryption-e2ee" rel="noreferrer"><strong>End-to-end encryption (E2EE)</strong></a><strong>:</strong> VideoSDK supports E2EE for media streams in the Flutter SDK starting from version <code>2.1.0</code>. Encryption is handled entirely on the client device. VideoSDK servers never receive, store, or transfer your encryption keys. This directly satisfies the CFM requirement for a confidential channel. Note: cloud recording is not available when E2EE is enabled, because recording requires server-side media access. You must choose between E2EE and cloud recording for each session type, or design your architecture to use E2EE only and implement local recording separately.</p><p><strong>Cloud recording:</strong> VideoSDK's REST API provides a <code>POST https://api.videosdk.live/v2/recordings/start</code> endpoint that starts cloud recording for a session. Recordings can be pushed to a custom <a href="https://aws.amazon.com/s3/" rel="noreferrer nofollow">AWS S3 bucket</a> via the <code>awsDirPath</code> parameter, or to any pre-signed cloud URL. This supports LGPD's medical record retention requirement for non-E2EE sessions.</p><p>VideoSDK does not publish a Brazil-specific data processing agreement (DPA) or list specific server regions in its public documentation. Before going to production, obtain a data processing agreement from VideoSDK that covers your obligations as a data controller under LGPD, and confirm the specific server regions that will process your Brazilian patient data.</p><h2 id="architecture">Architecture</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-8--2026--01_32_30-PM.png" class="kg-image" alt="How to Build an LGPD-Compliant Telehealth App in Brazil" loading="lazy" width="1693" height="929"><figcaption><span style="white-space: pre-wrap;">Telehealth app architecture for Brazil</span></figcaption></img></figure><p>The architecture has five components:</p><p><strong>Patient Mobile App (Flutter):</strong> Captures consent before room creation. Passes the consent record ID to the backend. Initialises the VideoSDK room only after consent is confirmed.</p><p><strong>Doctor Dashboard (React):</strong> Joins the same room as a host. Controls recording. Provides a UI-level prescription button that triggers your own medical record service.</p><p><strong>Backend / Token Server:</strong> Generates VideoSDK JWT tokens. Creates room IDs via the VideoSDK create-room API. Stores consent records. Starts and stops cloud recording via the VideoSDK REST API.</p><p><strong>Medical Record Service:</strong> Owned entirely by you, not VideoSDK. Stores the structured consultation record, prescription data, and links to the recording file.</p><p><strong>Encrypted Recording Storage:</strong> An <a href="https://aws.amazon.com/s3/" rel="noreferrer nofollow">AWS S3-compatible bucket</a> in a Brazilian region (e.g., <code>sa-east-1</code>). VideoSDK pushes recordings here via <code>awsDirPath</code>. You control access, retention, and deletion.</p><h2 id="building-the-patient-app-with-flutter">Building the patient app with Flutter</h2><h3 id="step-1-install-the-sdk">Step 1: Install the SDK</h3><p>Add the <code>videosdk</code> package to your Flutter project:</p><pre><code class="language-bash">flutter pub add videosdk</code></pre><p>This adds the following to your <code>pubspec.yaml</code>:</p><pre><code class="language-yaml">dependencies:
  videosdk: ^2.0.0</code></pre><p>Import the SDK in your Dart files:</p><pre><code class="language-dart">import "package:videosdk/videosdk.dart";</code></pre><p>For Android, set <code>minSdkVersion</code> to <code>23</code> in <code>android/app/build.gradle</code> and add the required permissions to <code>AndroidManifest.xml</code>:</p><pre><code class="language-xml">&lt;uses-permission android:name="android.permission.CAMERA" /&gt;
&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
&lt;uses-permission android:name="android.permission.FOREGROUND_SERVICE" /&gt;</code></pre><p>For iOS, add <code>NSCameraUsageDescription</code> and <code>NSMicrophoneUsageDescription</code> to <code>Info.plist</code>, and set the minimum platform version to <code>13.0</code> in your Podfile.</p><h3 id="step-2-capture-consent-before-joining">Step 2: Capture consent before joining</h3><p>Under LGPD, you must not process health data before explicit consent is recorded. In the Flutter app, block room entry until the patient has accepted a clearly worded consent form.</p><pre><code class="language-dart">// consent_screen.dart
import 'package:flutter/material.dart';

class ConsentScreen extends StatefulWidget {
  final VoidCallback onConsentGiven;
  const ConsentScreen({super.key, required this.onConsentGiven});

  @override
  State&lt;ConsentScreen&gt; createState() =&gt; _ConsentScreenState();
}

class _ConsentScreenState extends State&lt;ConsentScreen&gt; {
  bool _accepted = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Consentimento LGPD')),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text(
              'Esta teleconsulta será realizada por meio de um canal seguro. '
              'Seus dados de saúde serão processados exclusivamente para fins '
              'de atendimento médico, conforme a LGPD (Lei 13.709/2018) e a '
              'Resolução CFM 2.314/2022. Você pode revogar este consentimento '
              'a qualquer momento.',
              style: TextStyle(fontSize: 16),
            ),
            const SizedBox(height: 24),
            CheckboxListTile(
              value: _accepted,
              onChanged: (v) =&gt; setState(() =&gt; _accepted = v ?? false),
              title: const Text('Eu li e aceito os termos acima.'),
            ),
            const SizedBox(height: 24),
            ElevatedButton(
              onPressed: _accepted ? widget.onConsentGiven : null,
              child: const Text('Entrar na consulta'),
            ),
          ],
        ),
      ),
    );
  }
}</code></pre><p>After the patient accepts, post the consent record to your backend and receive a <code>consentId</code>. Include this in your room creation request metadata.</p><h3 id="step-3-create-and-join-the-videosdk-room">Step 3: Create and join the VideoSDK room</h3><pre><code class="language-dart">// meeting_screen.dart
import 'package:videosdk/videosdk.dart';
import 'package:flutter/material.dart';

class MeetingScreen extends StatefulWidget {
  final String meetingId;
  final String token;
  final String displayName;

  const MeetingScreen({
    super.key,
    required this.meetingId,
    required this.token,
    required this.displayName,
  });

  @override
  State&lt;MeetingScreen&gt; createState() =&gt; _MeetingScreenState();
}

class _MeetingScreenState extends State&lt;MeetingScreen&gt; {
  late Room _room;
  bool _joined = false;

  @override
  void initState() {
    super.initState();

    // Create the room — consent must already be recorded before this point
    _room = VideoSDK.createRoom(
      roomId: widget.meetingId,
      token: widget.token,
      displayName: widget.displayName,
      micEnabled: true,
      camEnabled: true,
    );

    _registerRoomEvents();
  }

  void _registerRoomEvents() {
    _room.on(Events.roomJoined, () {
      setState(() =&gt; _joined = true);
    });

    _room.on(Events.roomLeft, () {
      Navigator.pop(context);
    });
  }

  void _joinRoom() {
    _room.join();
  }

  void _leaveRoom() {
    _room.leave();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Teleconsulta')),
      body: Center(
        child: _joined
            ? Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  const Text('Sessão em andamento'),
                  const SizedBox(height: 24),
                  ElevatedButton(
                    onPressed: _leaveRoom,
                    child: const Text('Encerrar consulta'),
                  ),
                ],
              )
            : ElevatedButton(
                onPressed: _joinRoom,
                child: const Text('Entrar na sala'),
              ),
      ),
    );
  }
}</code></pre><p>The <code>VideoSDK.createRoom()</code> method takes <code>roomId</code>, <code>token</code>, <code>displayName</code>, <code>micEnabled</code>, and <code>camEnabled</code> as parameters, as documented in the Flutter quick-start guide. Call <code>room.join()</code> to connect to the session and <code>room.leave()</code> to disconnect.</p><h2 id="building-the-doctor-dashboard-with-react">Building the doctor dashboard with React</h2><p><strong>Install the React SDK</strong></p><pre><code class="language-bash">npm install @videosdk.live/react-sdk</code></pre><h3 id="meetingprovider-and-hooks">MeetingProvider and hooks</h3><p>The React SDK exports <code>MeetingProvider</code>, <code>useMeeting</code>, and <code>useParticipant</code> from <code>@videosdk.live/react-sdk</code>. <code>MeetingProvider</code> is a React context provider that accepts meeting configuration. <code>useMeeting</code> gives access to the meeting state and controls. <code>useParticipant</code> gives access to individual participant streams.</p><pre><code class="language-jsx">// DoctorDashboard.jsx
import { MeetingProvider, useMeeting, useParticipant } from "@videosdk.live/react-sdk";

const ConsultationView = ({ onStartRecording, onStopRecording }) =&gt; {
  const { join, leave, participants, startRecording, stopRecording } = useMeeting({
    onMeetingJoined: () =&gt; {
      console.log("Doctor joined the consultation");
    },
    onParticipantJoined: (participant) =&gt; {
      console.log("Participant joined:", participant.id);
    },
  });

  return (
    &lt;div className="consultation-dashboard"&gt;
      &lt;div className="controls"&gt;
        &lt;button onClick={join}&gt;Entrar na sala&lt;/button&gt;
        &lt;button onClick={leave}&gt;Encerrar&lt;/button&gt;

        {/* Recording controls — recording is managed via your backend 
            calling the VideoSDK REST API. The startRecording() method 
            available in useMeeting triggers server-side recording. */}
        &lt;button onClick={() =&gt; startRecording()}&gt;Iniciar gravação&lt;/button&gt;
        &lt;button onClick={() =&gt; stopRecording()}&gt;Parar gravação&lt;/button&gt;

        {/* Prescription button — this calls your own medical record service,
            not a VideoSDK feature */}
        &lt;button onClick={() =&gt; alert("Abrir sistema de prescrição")}&gt;
          Emitir receita
        &lt;/button&gt;
      &lt;/div&gt;

      &lt;div className="participants"&gt;
        {[...participants.values()].map((p) =&gt; (
          &lt;ParticipantView key={p.id} participantId={p.id} /&gt;
        ))}
      &lt;/div&gt;
    &lt;/div&gt;
  );
};

const ParticipantView = ({ participantId }) =&gt; {
  const { displayName, isAudioOn, isVideoOn } = useParticipant(participantId);
  return (
    &lt;div&gt;
      &lt;p&gt;{displayName} — Áudio: {isAudioOn ? "on" : "off"} / Vídeo: {isVideoOn ? "on" : "off"}&lt;/p&gt;
    &lt;/div&gt;
  );
};

export const DoctorDashboard = ({ meetingId, token }) =&gt; (
  &lt;MeetingProvider
    config={{
      meetingId,
      name: "Médico",
      micEnabled: true,
      webcamEnabled: true,
    }}
    token={token}
  &gt;
    &lt;ConsultationView /&gt;
  &lt;/MeetingProvider&gt;
);</code></pre><p>The prescription button in this dashboard is a UI placeholder. It should call your own medical record service, not VideoSDK. VideoSDK has no built-in prescription or medical record capability.</p><h2 id="enabling-e2ee-and-geo-fencing">Enabling E2EE and geo-fencing</h2><h3 id="e2ee-setup-in-flutter">E2EE setup in Flutter</h3><p>E2EE requires <code>videosdk</code> version <code>2.1.0</code> or higher. Upgrade your dependency in <code>pubspec.yaml</code>:</p><pre><code class="language-yaml">dependencies:
  videosdk: ^2.1.0</code></pre><p>VideoSDK supports two E2EE modes: a shared key for all participants, and per-participant keys. For a two-person teleconsultation, the shared key mode is simpler.</p><pre><code class="language-dart">// e2ee_setup.dart
import 'package:videosdk/videosdk.dart';

class E2EEMeetingScreen extends StatefulWidget {
  final String meetingId;
  final String token;
  final String displayName;

  const E2EEMeetingScreen({
    super.key,
    required this.meetingId,
    required this.token,
    required this.displayName,
  });

  @override
  State&lt;E2EEMeetingScreen&gt; createState() =&gt; _E2EEMeetingScreenState();
}

class _E2EEMeetingScreenState extends State&lt;E2EEMeetingScreen&gt; {
  late Room _room;

  @override
  void initState() {
    super.initState();

    // E2EE must be configured before createRoom() is called
    _setupE2EE();

    _room = VideoSDK.createRoom(
      roomId: widget.meetingId,
      token: widget.token,
      displayName: widget.displayName,
    );
  }

  Future&lt;void&gt; _setupE2EE() async {
    try {
      var baseKeyProvider = BaseKeyProvider();

      // Fetch this key from your server over HTTPS — never hardcode it
      await baseKeyProvider.setSharedKey('&lt;encryption-key-from-your-server&gt;');

      // setSharedKey() must be called before setKeyProvider()
      VideoSDK.setKeyProvider(baseKeyProvider);
    } catch (e) {
      print("Error setting encryption key: ${e.toString()}");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Teleconsulta (E2EE)')),
      body: const Center(child: Text('Sessão criptografada em andamento')),
    );
  }
}</code></pre><p>You can verify that E2EE is active at runtime:</p><pre><code class="language-dart">bool isE2EEEnabled = _room.e2eeEnabled;
print("Is E2EE Enabled: $isE2EEEnabled");</code></pre><p>Monitor the encryption state per participant:</p><pre><code class="language-dart">participant.on(Events.e2eeStateChanged, (E2EEState state, Stream stream) {
  print("E2EE state: $state for stream: ${stream.kind}");
});</code></pre><p>Possible state values are <code>EncryptionSuccess</code>, <code>DecryptionSuccess</code>, <code>EncryptionFailed</code>, <code>DecryptionFailed</code>, and <code>InternalError</code>.</p><h3 id="geo-fencing">Geo-fencing</h3><p>VideoSDK's <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/geo-fencing-and-proxy-controls/geo-fencing" rel="noreferrer">Flutter SDK includes a Geo Fencing and Proxy Controls</a> section in its documentation, confirming that the feature exists. The geo-fencing feature allows you to control which VideoSDK infrastructure regions handle media routing for a session. To configure geo-fencing for a Brazil-region deployment, consult VideoSDK's support team or your account representative. The specific API parameters for region selection are not exposed in the public documentation at the time this guide was written; contact VideoSDK directly for the current configuration method.</p><h2 id="recording-and-retention">Recording and retention</h2><p>For sessions where E2EE is not enabled, VideoSDK cloud recording is available via the REST API. Start a recording from your backend server:</p><pre><code class="language-javascript">// Node.js — backend only, never call this from the client
const fetch = require('node-fetch');

async function startConsultationRecording(roomId, s3BucketPath, token) {
  const response = await fetch('https://api.videosdk.live/v2/recordings/start', {
    method: 'POST',
    headers: {
      'Authorization': token,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      roomId: roomId,
      config: {
        quality: 'high',      // Full HD
        mode: 'video-and-audio',
      },
      awsDirPath: s3BucketPath,   // e.g. 's3://your-bucket/recordings/'
      webhookUrl: 'https://your-backend.com/webhooks/recording',
    }),
  });

  const data = await response.json();
  return data;
}</code></pre><p>The <code>awsDirPath</code> parameter pushes the finished recording directly to an S3-compatible bucket. Use a bucket in the <code>sa-east-1</code> AWS region (São Paulo) to keep data within Brazil. Set bucket policies to restrict access to your backend service only.</p><p>To stop recording:</p><pre><code class="language-bash">POST https://api.videosdk.live/v2/recordings/stop
Authorization: YOUR_TOKEN
Content-Type: application/json

{ "roomId": "your-room-id" }</code></pre><p>You can also retrieve recordings via the API at <code>GET https://api.videosdk.live/v2/recordings</code> and delete them at <code>DELETE https://api.videosdk.live/v2/recordings/{recordingId}</code>. Use the delete endpoint to fulfil patient data deletion requests under LGPD Article 18.</p><p>For LGPD-compliant retention, document your retention policy and enforce it programmatically. A common approach is a scheduled job that calls the delete endpoint after the retention period expires.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li>LGPD classifies health data as sensitive, requiring explicit patient consent before any video session processing begins. Implement a consent gate in your Flutter app before <code>VideoSDK.createRoom()</code> is called.</li><li>CFM Resolution 2.314/2022 requires a secure channel for teleconsultations. VideoSDK's E2EE (using <code>BaseKeyProvider</code>, <code>setSharedKey()</code>, and <code>VideoSDK.setKeyProvider()</code>) satisfies this at the media layer, but you are responsible for key generation and distribution.</li><li>E2EE and cloud recording are mutually exclusive in VideoSDK. Design your session types accordingly: use E2EE for sessions where you do not need a server-side recording, or use TLS-only sessions with cloud recording pushed to a Brazilian S3 bucket.</li><li>The doctor dashboard uses <code>MeetingProvider</code>, <code>useMeeting</code>, and <code>useParticipant</code> from <code>@videosdk.live/react-sdk</code>. Prescription and medical record features are outside VideoSDK's scope and must be built in your own service layer.</li><li>Before production, obtain a data processing agreement from VideoSDK that covers your obligations as an LGPD data controller, and confirm the Brazilian server regions that will handle your patient data.</li></ul><h2 id="faq">FAQ</h2><p><strong>Q1. Does VideoSDK process data in Brazilian servers?</strong></p><p>VideoSDK documents a <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/geo-fencing-and-proxy-controls/geo-fencing" rel="noreferrer">Geo Fencing and Proxy Controls</a> feature in its Flutter SDK that allows you to influence media routing regions. However, VideoSDK's public documentation does not currently publish a list of specific server locations or a Brazil-region SLA. Before deploying a production telehealth app, request a data processing agreement (DPA) and server region confirmation from VideoSDK directly. Under LGPD, as the data controller, you are responsible for knowing where your patient data is processed.</p><p><strong>Q2. What constitutes valid consent under LGPD for telehealth?</strong></p><p>Valid consent under LGPD Article 8 must be free, informed, unambiguous, and specific to a defined purpose. For telehealth, the consent form must state: what health data will be collected during the session, the purpose (medical consultation), who will access it (the attending physician and your platform), how long it will be retained, and how the patient can withdraw consent. A pre-ticked checkbox is not valid. The consent record must be stored with a timestamp and a version reference to the consent text shown to the patient, and must be retrievable if the ANPD requests it.</p><p><strong>Q3. Can a patient download the session recording?</strong></p><p>LGPD Article 18 gives patients the right to data portability, which includes access to recordings of their consultations. You should implement a patient-facing download endpoint in your own backend that retrieves the recording from your S3 bucket using a time-limited pre-signed URL. Do not expose S3 credentials or bucket paths to the client. VideoSDK's <code>GET /v2/recordings</code> endpoint retrieves recording metadata, but the actual download access is controlled by your bucket policy.</p><p><strong>Q4. How do you delete data on a patient deletion request?</strong></p><p>Respond to patient deletion requests (LGPD Article 18, item VI) by calling <code>DELETE https://api.videosdk.live/v2/recordings/{recordingId}</code> for any VideoSDK-stored recordings, deleting the corresponding file from your S3 bucket, and removing the patient's records from your medical record service and consent store. You have 15 days to respond to the request. Document each deletion step with a timestamp for audit purposes. Note that VideoSDK may retain server-side logs for its own operational purposes; your DPA should address this.</p><p><strong>Q5. Is VideoSDK HIPAA-compliant as well?</strong></p><p>VideoSDK does not list <a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api" rel="noreferrer">HIPAA compliance</a> certification in its public documentation as of the time this guide was written. HIPAA applies to US-based covered entities and their business associates. If you are building a product for both the Brazilian and US markets, verify VideoSDK's compliance status directly with their team and obtain a Business Associate Agreement (BAA) if required. For Brazilian operations, LGPD and the CFM resolution are the applicable frameworks, not HIPAA.</p><h2 id="conclusion">Conclusion</h2><p>Building an <strong>LGPD-compliant telehealth app in Brazil</strong> requires more than a secure video call. It requires explicit consent capture before any data processing, a video channel that protects the confidentiality of the doctor-patient relationship as required by CFM 2.314/2022, and a data retention and deletion workflow that satisfies LGPD's patient rights provisions.</p><p>VideoSDK's Flutter SDK (package: <code>videosdk</code>, installed via <code>flutter pub add videosdk</code>) provides the core video infrastructure with <code>VideoSDK.createRoom()</code>, E2EE via <code>BaseKeyProvider</code> and <code>VideoSDK.setKeyProvider()</code>, and cloud recording via <code>POST https://api.videosdk.live/v2/recordings/start</code>. The React SDK provides <code>MeetingProvider</code>, <code>useMeeting</code>, and <code>useParticipant</code> for the doctor dashboard.</p><p>The components VideoSDK does not provide, consent management, medical records, prescriptions, and LGPD rights fulfillment, must be built in your own service layer. Treat VideoSDK as the secure transport for your LGPD-compliant telehealth app in Brazil, and build your compliance workflows around it.</p><p>For the full VideoSDK Flutter documentation, visit the <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">Flutter SDK Quick Start</a>. For the React SDK, visit <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">React SDK Quick Start</a></p>]]></content:encoded></item><item><title><![CDATA[How to scale multi-host live streaming for collaborative rooms]]></title><description><![CDATA[Build a panel live stream where multiple hosts broadcast together via VideoSDK's Interactive Live Streaming. This guide covers SEND_AND_RECV mode, startHls(), RTMP simulcast, layout config, and graceful host drop-off handling.]]></description><link>https://www.videosdk.live/blog/multi-host-live-streaming-collaborative-rooms</link><guid isPermaLink="false">69fd891355831517a5a9fbdd</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 08 May 2026 07:32:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-8--2026--12_33_51-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> VideoSDK's Interactive Live Streaming lets multiple hosts join a room in <code>SEND_AND_RECV</code> mode and broadcast a single composited HLS stream to thousands of viewers. Hosts share audio and video in real time; viewers receive a low-latency HLS feed. RTMP simulcast to YouTube or Twitch runs in parallel via <code>startLivestream()</code>.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-8--2026--12_33_51-PM.png" alt="How to scale multi-host live streaming for collaborative rooms"/><p>Multi-host live streaming collaborative rooms let several presenters broadcast together from a single session while a large audience watches an <a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer">HLS stream</a>. VideoSDK's Interactive Live Streaming (ILS) is the infrastructure layer that makes this work: hosts join as active participants, VideoSDK composes their feeds, and viewers receive a scalable HLS output without joining the room as senders.</p><h3 id="videosdk-interactive-live-streaming-architecture">VideoSDK interactive live streaming architecture</h3><p><a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer"><strong>Interactive Live Streaming (ILS)</strong></a><strong>:</strong> ILS is VideoSDK's feature set for rooms where some participants send audio and video (hosts) while others only receive a composed stream (viewers).</p><p>Each participant in a VideoSDK room joins with one of two modes:</p><ul><li><code>SEND_AND_RECV</code>: the participant can publish audio and video and receive other participants' feeds. Use this for every host on the panel.</li><li><code>RECV_ONLY</code>: the participant receives streams but cannot publish. Use this for audience members who join the room directly.</li></ul><p>For the majority of viewers, VideoSDK recommends a different path: they never join the room at all. Instead, they receive a composed <a href="https://www.videosdk.live/developer-hub/hls/hls-live-streaming" rel="noreferrer"><strong>HLS (HTTP Live Streaming)</strong></a> stream generated by <code>startHls()</code>. HLS: HLS is an <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">adaptive streaming</a> protocol that serves media as small <code>.ts</code> segments over HTTP, enabling CDN-scale distribution to thousands of concurrent viewers.</p><p>The flow is: hosts in <code>SEND_AND_RECV</code> publish to a VideoSDK room, VideoSDK composes their feeds, <code>startHls()</code> encodes and segments the composition, and viewers play back the resulting <code>playbackHlsUrl</code>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-8--2026--12_30_48-PM.png" class="kg-image" alt="How to scale multi-host live streaming for collaborative rooms" loading="lazy" width="1693" height="929"><figcaption><span style="white-space: pre-wrap;">Multi-host Collaborative Streaming Diagram</span></figcaption></img></figure><h3 id="setting-up-multi-host-rooms">Setting up multi-host rooms</h3><p>Install the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">React SDK</a> first:</p><pre><code class="language-bash">npm install @videosdk.live/react-sdk</code></pre><p>Create a room using the VideoSDK REST API and obtain a <code>meetingId</code>. Then initialize the room with <code>MeetingProvider</code> and join every host with <code>mode: "SEND_AND_RECV"</code>. The <code>mode</code> value is passed when calling <code>joinMeeting</code> inside the provider config.</p><pre><code class="language-js">import { MeetingProvider } from "@videosdk.live/react-sdk";

function App() {
  return (
    &lt;MeetingProvider
      config={{
        meetingId: "&lt;MEETING_ID&gt;",
        micEnabled: true,
        webcamEnabled: true,
        name: "Host Name",
        // Hosts join in SEND_AND_RECV mode
        mode: "SEND_AND_RECV",
      }}
      token="&lt;VIDEOSDK_TOKEN&gt;"
      joinWithoutUserInteraction={true}
    &gt;
      &lt;HostMeetingView /&gt;
    &lt;/MeetingProvider&gt;
  );
}</code></pre><p>For viewer clients that join the room directly (rather than via HLS), pass <code>mode: "RECV_ONLY"</code>. Viewers who watch via HLS do not join the room at all and use a standard HLS player instead.</p><h3 id="managing-host-permissions">Managing host permissions</h3><p>The <code>useParticipant</code> hook exposes a <code>mode</code> field for each participant. You can read this to build a host roster or conditionally render controls.</p><pre><code class="language-js">import { useParticipant } from "@videosdk.live/react-sdk";

function ParticipantTile({ participantId }) {
  const { displayName, webcamStream, mode } = useParticipant(participantId);

  // Only render a video tile for hosts
  if (mode !== "SEND_AND_RECV") return null;

  return (
    &lt;div&gt;
      &lt;p&gt;{displayName}&lt;/p&gt;
      {/* Attach webcamStream to a video element */}
    &lt;/div&gt;
  );
}</code></pre><p>To promote a <code>RECV_ONLY</code> audience member to host during the show, use <code>changeMode()</code> from <code>useMeeting</code>. The recommended pattern from the docs is a PubSub-based invite: the host publishes a topic-specific message, and the audience member's client calls <code>changeMode("SEND_AND_RECV")</code> on receiving it.</p><pre><code class="language-js">import { useMeeting, usePubSub } from "@videosdk.live/react-sdk";

// On the audience member's client
const ChangeModeListener = () =&gt; {
  const { changeMode, localParticipant } = useMeeting();

  usePubSub(`REQUEST_TO_JOIN_AS_HOST_${localParticipant?.id}`, {
    onMessageReceived: async ({ message }) =&gt; {
      changeMode(message.mode); // "SEND_AND_RECV"
    },
  });

  return &lt;&gt;&lt;/&gt;;
};</code></pre><p>There is no direct server-side API to forcibly change another participant's mode. The <code>changeMode()</code> call always runs on the participant's own client. The invite approach via <code>usePubSub</code> is the documented pattern.</p><h3 id="starting-hls-for-the-audience">Starting HLS for the audience</h3><p>Once all hosts have joined, any host (or your server) calls <code>startHls()</code> from the <code>useMeeting</code> hook. This triggers VideoSDK to compose the room and begin producing the HLS stream.</p><pre><code class="language-js">import { useMeeting } from "@videosdk.live/react-sdk";

const MeetingView = () =&gt; {
  const { startHls, stopHls } = useMeeting();

  const handleStartHls = () =&gt; {
    startHls({
      layout: {
        type: "GRID",       // "SPOTLIGHT" | "SIDEBAR"
        priority: "SPEAKER", // "PIN"
        gridSize: 4,        // MAX: 25
      },
      theme: "DARK",        // "LIGHT" | "DEFAULT"
      mode: "video-and-audio", // "audio"
      quality: "high",      // "low" (SD) | "med" (HD) | "high" (FHD)
      orientation: "landscape", // "portrait"
    });
  };

  return &lt;button onClick={handleStartHls}&gt;Start HLS&lt;/button&gt;;
};</code></pre><p>The <code>onHlsStateChanged</code> event fires as the stream transitions through states. When the state reaches <code>Constants.hlsEvents.HLS_PLAYABLE</code>, the <code>playbackHlsUrl</code> is available. Pass this URL to any <a href="https://www.videosdk.live/blog/implement-hls-player-in-react-js" rel="noreferrer">HLS-compatible player</a> (hls.js, Video.js, native Safari) on the viewer side.</p><pre><code class="language-js">import { Constants, useMeeting } from "@videosdk.live/react-sdk";

function onHlsStateChanged(data) {
  const { status } = data;
  if (status === Constants.hlsEvents.HLS_PLAYABLE) {
    const { playbackHlsUrl } = data;
    console.log("Stream ready:", playbackHlsUrl);
  }
}

const { meetingId } = useMeeting({ onHlsStateChanged });</code></pre><p>Note: <code>downstreamUrl</code> is deprecated. Use <code>playbackHlsUrl</code> (supports DVR playback) or <code>livestreamUrl</code> (live-only, no playback seek) in all new implementations.</p><h3 id="layout-management-for-multiple-hosts">Layout management for multiple hosts</h3><p>The <code>startHls()</code> config object gives you direct control over how the VideoSDK compositor arranges host tiles. Three layout types are documented:</p><p><strong>GRID:</strong> Default. All participants visible in a grid. When a participant is pinned, they appear prominently at the top; unpinned participants fill the remaining cells. Maximum <code>gridSize</code> is 25.</p><p><strong>SIDEBAR:</strong> One main screen (the first pinned participant) with a sidebar for additional pinned participants. Unpinned participants are hidden.</p><p><strong>SPOTLIGHT:</strong> Only pinned participants are visible, filling the main screen. No sidebar grid.</p><p>For a panel stream with four co-hosts, <code>GRID</code> with <code>gridSize: 4</code> and <code>priority: "SPEAKER"</code> is the most natural choice. It keeps all hosts visible and automatically promotes the active speaker to the most prominent position.</p><p>To switch layouts mid-stream without stopping, call <code>startHls()</code> again with the new config. The docs do not document a dedicated mid-stream layout switch endpoint separate from <code>startHls()</code>.</p><h3 id="rtmp-simulcast-to-youtube-and-twitch">RTMP simulcast to YouTube and Twitch</h3><p>VideoSDK supports <a href="https://www.videosdk.live/blog/rtmp-out-how-live-streaming-really-works" rel="noreferrer">RTMP simulcast</a> via <code>startLivestream()</code> from the <code>useMeeting</code> hook. This runs independently of HLS: you can have both active simultaneously.</p><pre><code class="language-js">import { useMeeting } from "@videosdk.live/react-sdk";

const MeetingView = () =&gt; {
  const { startLivestream, stopLivestream } = useMeeting();

  const handleStartLivestream = () =&gt; {
    startLivestream(
      [
        {
          // YouTube Live RTMP endpoint + stream key
          url: "rtmp://a.rtmp.youtube.com/live2",
          streamKey: "&lt;YOUR_YOUTUBE_STREAM_KEY&gt;",
        },
        {
          // Twitch RTMP endpoint + stream key
          url: "rtmp://live.twitch.tv/app",
          streamKey: "&lt;YOUR_TWITCH_STREAM_KEY&gt;",
        },
      ],
      {
        layout: {
          type: "GRID",
          priority: "SPEAKER",
          gridSize: 4,
        },
        theme: "DARK",
      }
    );
  };

  const handleStopLivestream = () =&gt; {
    stopLivestream();
  };

  return (
    &lt;&gt;
      &lt;button onClick={handleStartLivestream}&gt;Go Live on YouTube/Twitch&lt;/button&gt;
      &lt;button onClick={handleStopLivestream}&gt;Stop Simulcast&lt;/button&gt;
    &lt;/&gt;
  );
};</code></pre><p>The <code>outputs</code> array accepts multiple objects, so you can push to YouTube and Twitch in a single call. For each platform: find the <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a> ingest URL in the platform's live dashboard, copy the stream key, and plug both values in. The <code>onLivestreamStateChanged</code> callback fires through <code>LIVESTREAM_STARTING</code>, <code>LIVESTREAM_STARTED</code>, <code>LIVESTREAM_STOPPING</code>, and <code>LIVESTREAM_STOPPED</code> states.</p><h3 id="handling-host-drop-offs">Handling host drop-offs</h3><p>When a host closes their tab, loses connectivity, or deliberately leaves, VideoSDK fires the <code>onParticipantLeft</code> event on all remaining clients. Use this to remove the departed host's tile from your local UI state.</p><pre><code class="language-js">import { useMeeting } from "@videosdk.live/react-sdk";
import { useState } from "react";

const MeetingView = () =&gt; {
  const [hostIds, setHostIds] = useState([]);

  const onParticipantJoined = (participant) =&gt; {
    if (participant.mode === "SEND_AND_RECV") {
      setHostIds((prev) =&gt; [...prev, participant.id]);
    }
  };

  const onParticipantLeft = (participant) =&gt; {
    setHostIds((prev) =&gt; prev.filter((id) =&gt; id !== participant.id));
  };

  useMeeting({ onParticipantJoined, onParticipantLeft });

  return (
    &lt;div&gt;
      {hostIds.map((id) =&gt; (
        &lt;HostTile key={id} participantId={id} /&gt;
      ))}
    &lt;/div&gt;
  );
};</code></pre><p>The <code>onParticipantLeft</code> callback receives the participant object. Filtering the departed participant's ID from your state removes the tile immediately. The HLS compositor on VideoSDK's side automatically reflows the grid when a participant leaves: no manual recomposition call is required.</p><p>If the departing participant was the only one who called <code>startHls()</code>, the HLS stream continues running. The session owner or a remaining host is responsible for calling <code>stopHls()</code> when the event ends.</p><h3 id="key-takeaways">Key takeaways</h3><ul><li>Hosts join a VideoSDK room in <code>SEND_AND_RECV</code> mode; mass viewers consume the output via <code>playbackHlsUrl</code> from <code>startHls()</code> without joining the room at all.</li><li>Layout types <code>GRID</code>, <code>SIDEBAR</code>, and <code>SPOTLIGHT</code> control how the compositor arranges host tiles in the HLS output; <code>gridSize</code> goes up to 25 in GRID mode.</li><li>RTMP simulcast to YouTube, Twitch, or any RTMP-compatible platform runs via <code>startLivestream()</code> and can run simultaneously with HLS.</li><li>Mode promotion (audience member to host) happens via <code>changeMode("SEND_AND_RECV")</code> on the participant's own client, triggered by a PubSub invite from the host.</li><li><code>onParticipantLeft</code> gives you the hook to remove a dropped host from your UI; the HLS compositor reflows automatically.</li></ul><h3 id="faq">FAQ</h3><p><strong>Q1. How many simultaneous hosts can a VideoSDK room support in SEND_AND_RECV mode?</strong></p><p>The <code>startHls()</code> config accepts a <code>gridSize</code> of up to 25 for the GRID layout. This is the maximum number of participants whose video tiles will appear in the HLS output grid at one time. The room itself can contain additional <code>SEND_AND_RECV</code> participants beyond 25, but the compositor will only surface up to <code>gridSize</code> tiles in the HLS stream. For panel formats with 2 to 6 hosts, any of the three layout types works well.</p><p><strong>Q2. What is the HLS stream latency that viewers experience?</strong></p><p>VideoSDK's HLS implementation produces a <code>playbackHlsUrl</code> and a <code>livestreamUrl</code>. The <code>livestreamUrl</code> targets <a href="https://www.videosdk.live/blog/what-is-low-latency-http-live-streaming" rel="noreferrer">lower latency</a> for live-only playback without DVR support. The <code>playbackHlsUrl</code> adds playback seek support, which typically introduces a few additional seconds of buffering. Exact latency figures depend on player buffer settings, CDN edge proximity, and network conditions. VideoSDK does not publish a fixed latency SLA in its public documentation as of the time of writing.</p><p><strong>Q3. Can a host join the multi-host live streaming collaborative room from a mobile device?</strong></p><p>Yes. VideoSDK's <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">React Native SDK</a> supports ILS with the same <code>SEND_AND_RECV</code> and <code>RECV_ONLY</code> modes. A host on a React Native mobile app can publish their camera and microphone into the same room as desktop hosts, and VideoSDK will composite their feed into the HLS output the same way. The <code>orientation: "portrait"</code> option in <code>startHls()</code> config is specifically documented for <a href="https://www.videosdk.live/blog/react-native-live-streaming" rel="noreferrer">mobile-first vertical stream layouts</a>.</p><p><strong>Q4. How do you switch between different HLS stream layouts during a live multi-speaker live stream?</strong></p><p>Call <code>startHls()</code> again with the updated <code>layout</code> config object. For example, to switch from <code>GRID</code> to <code>SPOTLIGHT</code> during a keynote segment: call <code>startHls({ layout: { type: "SPOTLIGHT", priority: "PIN" }, ... })</code>. The VideoSDK docs also document a <code>pin()</code> method on participants via the <code>useParticipant</code> hook, which works with the <code>PIN</code> priority to control which host appears in the SPOTLIGHT or SIDEBAR main view. For a custom composed layout beyond the three prebuilt types, VideoSDK supports a <code>templateURL</code> parameter via the REST API to specify a custom template hosted by your infrastructure.</p><h3 id="conclusion">Conclusion</h3><p>Multi-host live streaming collaborative rooms require two distinct things to work well: a reliable real-time room for hosts in <code>SEND_AND_RECV</code> mode, and a scalable delivery path for viewers. VideoSDK's Interactive Live Streaming handles both in a single SDK. Hosts join the room, <code>startHls()</code> starts the composition and delivery, and <code>startLivestream()</code> extends reach to YouTube and Twitch simultaneously.</p><p>The primary keyword here is multi-host live streaming collaborative rooms, and the architecture described above is the current documented pattern in the VideoSDK React SDK as of January 2026. All method names, event names, and parameter values in this guide were verified directly against the VideoSDK documentation.</p><p>For the full SDK reference, see the <a href="https://docs.videosdk.live/react-sdk-reference/">VideoSDK React SDK API reference</a> and the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-ILS">Interactive Live Streaming quickstart</a>.</p>]]></content:encoded></item><item><title><![CDATA[How to Build an Online Doctor Consultation Platform]]></title><description><![CDATA[A step-by-step guide for full-stack developers to build an online doctor consultation platform using VideoSDK. Covers appointment UI, encrypted video sessions, PubSub chat, cloud recording, and real-time transcription with verified React code.]]></description><link>https://www.videosdk.live/blog/build-online-doctor-consultation-platform</link><guid isPermaLink="false">69fd79b855831517a5a9fb81</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 08 May 2026 06:26:17 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-8--2026--11_31_54-AM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> To build an online doctor consultation platform, you need five core layers: appointment scheduling (external), a secure video session, in-session chat, session recording, and post-session transcription. This guide implements the last four using VideoSDK's React SDK (<code>@videosdk.live/react-sdk</code>), with verified code for every hook and method.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-8--2026--11_31_54-AM.png" alt="How to Build an Online Doctor Consultation Platform"/><p>To build an <a href="https://www.videosdk.live/solutions/video-mer" rel="noreferrer">online doctor consultation platform</a>, you combine an appointment scheduling system with a real-time video layer that handles the actual clinical interaction. The video layer must support encrypted <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-p2p" rel="noreferrer">peer-to-peer communication</a>, in-call messaging, server-side recording, and automatic transcription so the session can feed downstream workflows like prescriptions and <a href="https://en.wikipedia.org/wiki/Electronic_health_record" rel="noreferrer nofollow">EHR</a> entries. </p><h2 id="core-features-of-a-doctor-consultation-platform">Core features of a doctor consultation platform</h2><p>A functional <a href="https://www.videosdk.live/blog/build-compliant-telemedicine-app-react" rel="noreferrer">telemedicine</a> MVP requires several distinct modules. Not all of them fall inside the VideoSDK boundary, so this section draws a clear line between what the SDK handles and what your backend must own.</p><h3 id="appointment-scheduling">Appointment scheduling</h3><p><a href="https://www.videosdk.live/industry-hub/healthcare/conversational-ai-for-appointment-booking" rel="noreferrer"><strong>Appointment scheduling</strong></a> is the process of matching a patient with an available doctor for a specific time slot. This is outside the VideoSDK scope. You need a calendar-aware booking system, whether that's a custom service, a third-party API like <a href="https://developer.calendly.com/" rel="noreferrer nofollow">Calendly Embed</a>, or a module inside your EHR. What VideoSDK provides is the room that the appointment links to.</p><p>Your booking service should generate a <code>meetingId</code> (room ID) at the time of booking confirmation and store it alongside the appointment record. Both the patient and the doctor receive a secure link containing that ID.</p><h3 id="video-session">Video session</h3><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> provides the encrypted media transport. A <strong>VideoSDK room</strong> is a WebRTC-based session where participants exchange audio and video streams via VideoSDK's media servers. Each room is identified by a <code>meetingId</code> and controlled through short-lived JWT tokens.</p><h3 id="in-session-chat">In-session chat</h3><p>VideoSDK includes a PubSub (publish-subscribe) messaging layer that lets participants exchange typed messages within a room without any additional <a href="https://www.videosdk.live/blog/what-is-a-websocket" rel="noreferrer">WebSocket</a> server on your end. This is sufficient for clinical messages during a session, such as the doctor sharing a link to a lab report portal.</p><h3 id="session-recording">Session recording</h3><p>Any participant can trigger <a href="https://www.videosdk.live/blog/cloud-recording-and-rtmp-pricing" rel="noreferrer">cloud recording</a> of the session. Recordings are stored in VideoSDK's infrastructure and are accessible from the developer dashboard. You can also redirect them to an <a href="https://aws.amazon.com/s3/" rel="noreferrer nofollow">S3-compatible path</a> using the <code>awsDirPath</code> parameter.</p><h3 id="real-time-transcription-and-post-session-transcription">Real-time transcription and post-session transcription</h3><p>VideoSDK offers two distinct transcription modes. The first is <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/transcription-and-summary/realtime-transcribe-meeting" rel="noreferrer"><strong>real-time transcription</strong></a>, which uses the <code>useTranscription</code> hook to stream spoken words as text during the session, with an optional AI summary delivered to a webhook after stopping. The second is <a href="https://www.videosdk.live/blog/react-transcription-blog" rel="noreferrer"><strong>post-session transcription</strong></a>, which runs after the recording ends and produces structured transcript files in JSON, SRT, TXT, TSV, and VTT formats, retrievable via the <code>fetchPostTranscriptions</code> REST API. Both modes support summary generation via a configurable <code>prompt</code>. A telemedicine platform would typically use post-session transcription for permanent clinical records, since the output is more structured and complete.</p><h2 id="architecture">Architecture</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-8--2026--11_25_49-AM.png" class="kg-image" alt="How to Build an Online Doctor Consultation Platform" loading="lazy" width="1717" height="916"><figcaption><span style="white-space: pre-wrap;">Telemedicine Platform Architecture Diagram</span></figcaption></img></figure><p>The architecture has four distinct layers. The <strong>client layer</strong> consists of the patient web or mobile app and the doctor dashboard, both built in React. The <strong>VideoSDK layer</strong> handles all media routing, PubSub messaging, recording, and transcription inside a secure room. The <strong>application backend</strong> generates tokens, stores appointment records, and receives webhook payloads from VideoSDK after a session ends. The <strong>data layer</strong> includes an EHR system and a notification service that consume structured data your backend derives from the webhook payloads.</p><p>The VideoSDK room itself does not connect directly to your EHR. Your backend webhook endpoint receives the transcription and recording metadata, then writes to whatever storage layer your platform uses.</p><h2 id="setting-up-videosdk">Setting up VideoSDK</h2><h3 id="install-the-package">Install the package</h3><p>Install the React SDK using npm or yarn:</p><pre><code class="language-bash">npm install @videosdk.live/react-sdk</code></pre><p>Or with yarn:</p><pre><code class="language-bash">yarn add @videosdk.live/react-sdk</code></pre><p>The package name is <code>@videosdk.live/react-sdk</code>. This is the verified package name from the official VideoSDK documentation.</p><h3 id="generate-an-api-key">Generate an API key</h3><p>Sign up at <a href="https://app.videosdk.live">app.videosdk.live</a>, create a project, and copy your <a href="https://www.videosdk.live/blog/api-key-vs-api-token" rel="noreferrer">API key and secret</a>. These credentials stay on your server only. Never embed them in client-side code.</p><h3 id="generate-a-token">Generate a token</h3><p>VideoSDK uses short-lived <a href="https://www.jwt.io/introduction#what-is-json-web-token" rel="noreferrer nofollow">JWT</a> tokens for room access. Generate tokens on your server using your API key and secret. A minimal Node.js example:</p><pre><code class="language-js">const jwt = require("jsonwebtoken");

function generateToken() {
  const payload = {
    apikey: process.env.VIDEOSDK_API_KEY,
    permissions: ["allow_join"],
    version: 2,
  };
  return jwt.sign(payload, process.env.VIDEOSDK_SECRET_KEY, {
    expiresIn: "1h",
    algorithm: "HS256",
  });
}</code></pre><p>Your frontend fetches this token from your own API endpoint before joining a room.</p><h3 id="create-a-room">Create a room</h3><p>Call the VideoSDK REST API to create a room (meeting) before the session starts:</p><pre><code class="language-js">const response = await fetch("https://api.videosdk.live/v2/rooms", {
  method: "POST",
  headers: {
    Authorization: token,
    "Content-Type": "application/json",
  },
});
const { roomId } = await response.json();</code></pre><p>Store the returned <code>roomId</code> in your appointment record. Pass it to both the patient and the doctor as the <code>meetingId</code> for their join flow.</p><h2 id="patient-interface-react">Patient interface (React)</h2><p>The patient interface needs three things: the ability to join a room, camera and microphone controls, and access to the in-session chat. All three are available through <code>MeetingProvider</code>, <code>useMeeting</code>, and <code>useParticipant</code> from <code>@videosdk.live/react-sdk</code>.</p><h3 id="wrapping-the-app-with-meetingprovider">Wrapping the app with MeetingProvider</h3><p><strong><code>MeetingProvider</code></strong> is the React context provider that supplies meeting state to all child components. Wrap your session view with it before rendering any hooks:</p><pre><code class="language-jsx">import {
  MeetingProvider,
  useMeeting,
  useParticipant,
} from "@videosdk.live/react-sdk";

function PatientApp({ meetingId, token, patientName }) {
  return (
    &lt;MeetingProvider
      config={{
        meetingId,
        micEnabled: true,
        webcamEnabled: true,
        name: patientName,
      }}
      token={token}
    &gt;
      &lt;PatientView /&gt;
    &lt;/MeetingProvider&gt;
  );
}</code></pre><h3 id="joining-the-meeting-and-controlling-media">Joining the meeting and controlling media</h3><p>Inside <code>PatientView</code>, use the <code>useMeeting</code> hook to get the <code>join</code>, <code>leave</code>, <code>toggleMic</code>, and <code>toggleWebcam</code> methods:</p><pre><code class="language-jsx">function PatientView() {
  const { join, leave, toggleMic, toggleWebcam, participants } = useMeeting({
    onMeetingJoined: () =&gt; console.log("Patient joined"),
    onMeetingLeft: () =&gt; console.log("Patient left"),
  });

  return (
    &lt;div&gt;
      &lt;button onClick={join}&gt;Join Consultation&lt;/button&gt;
      &lt;button onClick={toggleMic}&gt;Toggle Mic&lt;/button&gt;
      &lt;button onClick={toggleWebcam}&gt;Toggle Camera&lt;/button&gt;
      &lt;button onClick={leave}&gt;End Session&lt;/button&gt;

      {[...participants.keys()].map((participantId) =&gt; (
        &lt;ParticipantTile key={participantId} participantId={participantId} /&gt;
      ))}
    &lt;/div&gt;
  );
}</code></pre><h3 id="rendering-a-participants-video-stream">Rendering a participant's video stream</h3><p><code><strong>useParticipant</strong></code> takes a <code>participantId</code> and returns that participant's stream objects. Attach the webcam stream to a <code>&lt;video&gt;</code> element using a ref:</p><pre><code class="language-jsx">import { useParticipant } from "@videosdk.live/react-sdk";
import { useEffect, useRef } from "react";

function ParticipantTile({ participantId }) {
  const videoRef = useRef(null);
  const { webcamStream, webcamOn, displayName } = useParticipant(participantId);

  useEffect(() =&gt; {
    if (videoRef.current &amp;&amp; webcamStream) {
      const mediaStream = new MediaStream();
      mediaStream.addTrack(webcamStream.track);
      videoRef.current.srcObject = mediaStream;
    }
  }, [webcamStream, webcamOn]);

  return (
    &lt;div&gt;
      &lt;p&gt;{displayName}&lt;/p&gt;
      {webcamOn ? (
        &lt;video ref={videoRef} autoPlay muted /&gt;
      ) : (
        &lt;p&gt;Camera off&lt;/p&gt;
      )}
    &lt;/div&gt;
  );
}</code></pre><h2 id="doctor-interface-react">Doctor interface (React)</h2><p>The doctor view uses the same <code>useMeeting</code> and <code>useParticipant</code> hooks, with the addition of recording controls.</p><h3 id="doctor-view-with-recording">Doctor view with recording</h3><pre><code class="language-jsx">import {
  MeetingProvider,
  useMeeting,
  Constants,
} from "@videosdk.live/react-sdk";

function DoctorSession() {
  const {
    join,
    leave,
    toggleMic,
    toggleWebcam,
    startRecording,
    stopRecording,
    participants,
  } = useMeeting({
    onRecordingStateChanged: (data) =&gt; {
      const { status } = data;
      if (status === Constants.recordingEvents.RECORDING_STARTED) {
        console.log("Recording started");
      } else if (status === Constants.recordingEvents.RECORDING_STOPPED) {
        console.log("Recording stopped");
      }
    },
  });

  const handleStartRecording = () =&gt; {
    // startRecording(webhookUrl, awsDirPath, config, transcription)
    // Pass null for unused parameters
    startRecording("https://your-backend.com/webhooks/recording", null, null, null);
  };

  return (
    &lt;div&gt;
      &lt;button onClick={join}&gt;Join as Doctor&lt;/button&gt;
      &lt;button onClick={toggleMic}&gt;Mic&lt;/button&gt;
      &lt;button onClick={toggleWebcam}&gt;Camera&lt;/button&gt;
      &lt;button onClick={handleStartRecording}&gt;Start Recording&lt;/button&gt;
      &lt;button onClick={stopRecording}&gt;Stop Recording&lt;/button&gt;
      &lt;button onClick={leave}&gt;End Consultation&lt;/button&gt;

      {[...participants.keys()].map((id) =&gt; (
        &lt;ParticipantTile key={id} participantId={id} /&gt;
      ))}
    &lt;/div&gt;
  );
}</code></pre><p>The <code>startRecording</code> method accepts a <code>webhookUrl</code> as its first argument. VideoSDK calls this URL after the recording is ready, passing a download link. The second argument, <code>awsDirPath</code>, lets you specify a custom S3 path. Pass <code>null</code> to use VideoSDK's default storage.</p><h2 id="in-session-chat-1">In-session chat</h2><p>The PubSub feature in VideoSDK lets participants send and receive typed messages keyed to a topic string. You can use any topic string; <code>"CHAT"</code> is a common convention.</p><p><code><strong>usePubSub</strong></code> is the hook that returns a <code>publish</code> function and a <code>messages</code> array. The <code>publish</code> function takes the message text and an options object. Setting <code>persist: true</code> means participants who join late still see the message history.</p><pre><code class="language-jsx">import { usePubSub } from "@videosdk.live/react-sdk";
import { useState } from "react";

function SessionChat() {
  const [input, setInput] = useState("");
  const { publish, messages } = usePubSub("CHAT");

  const sendMessage = () =&gt; {
    if (input.trim()) {
      publish(input, { persist: true });
      setInput("");
    }
  };

  return (
    &lt;div&gt;
      &lt;div className="messages"&gt;
        {messages.map((msg, i) =&gt; (
          &lt;p key={i}&gt;
            &lt;strong&gt;{msg.senderName}:&lt;/strong&gt; {msg.message}
          &lt;/p&gt;
        ))}
      &lt;/div&gt;
      &lt;input
        value={input}
        onChange={(e) =&gt; setInput(e.target.value)}
        placeholder="Type a message..."
      /&gt;
      &lt;button onClick={sendMessage}&gt;Send&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><p>Each message in the <code>messages</code> array contains <code>message</code> (the text), <code>senderName</code>, <code>senderId</code>, and <code>timestamp</code>. No additional WebSocket server is required.</p><h2 id="session-transcription">Session transcription</h2><p>VideoSDK provides real-time transcription through the <code>useTranscription</code> hook. This is a verified API from the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">VideoSDK React SDK documentation</a>. It streams live transcript text through callbacks as the session runs and delivers an optional AI summary to a webhook URL after transcription stops.</p><p><strong>Starting and consuming transcription</strong></p><pre><code class="language-jsx">import { useTranscription, Constants } from "@videosdk.live/react-sdk";
import { useState } from "react";

function TranscriptionPanel() {
  const [transcriptLines, setTranscriptLines] = useState([]);

  function onTranscriptionStateChanged(data) {
    const { status, id } = data;
    if (status === Constants.transcriptionEvents.TRANSCRIPTION_STARTED) {
      console.log("Transcription started, session id:", id);
    } else if (status === Constants.transcriptionEvents.TRANSCRIPTION_STOPPED) {
      console.log("Transcription stopped, summary will be delivered via webhook");
    }
  }

  function onTranscriptionText(data) {
    const { participantName, text, timestamp } = data;
    setTranscriptLines((prev) =&gt; [
      ...prev,
      { participantName, text, timestamp },
    ]);
  }

  const { startTranscription, stopTranscription } = useTranscription({
    onTranscriptionStateChanged,
    onTranscriptionText,
  });

  const handleStart = async () =&gt; {
    await startTranscription({
      webhookUrl: "https://your-backend.com/webhooks/transcription",
      summary: {
        enabled: true,
        prompt:
          "Write a clinical summary with sections: Chief Complaint, Doctor's Assessment, Prescription Notes, Follow-up Actions",
      },
    });
  };

  return (
    &lt;div&gt;
      &lt;button onClick={handleStart}&gt;Start Transcription&lt;/button&gt;
      &lt;button onClick={stopTranscription}&gt;Stop Transcription&lt;/button&gt;
      &lt;div className="transcript"&gt;
        {transcriptLines.map((line, i) =&gt; (
          &lt;p key={i}&gt;
            &lt;strong&gt;{line.participantName}:&lt;/strong&gt; {line.text}
          &lt;/p&gt;
        ))}
      &lt;/div&gt;
    &lt;/div&gt;
  );
}</code></pre><h3 id="storing-the-transcript">Storing the transcript</h3><p>When <code>stopTranscription()</code> is called and <code>summary.enabled</code> is <code>true</code>, VideoSDK posts the final transcript and summary to your <code>webhookUrl</code>. Your backend webhook handler receives the payload, parses it, and writes the structured text to the patient's EHR record or your consultation notes database.</p><p>There is no separate REST API for retrieving real-time transcripts by session ID in the VideoSDK React SDK docs. The webhook delivery is the correct retrieval path for real-time transcription data. Store the payload on receipt.</p><h2 id="post-session-transcription">Post-session transcription</h2><p><a href="https://docs.videosdk.live/tutorials/transcription-and-summary" rel="noreferrer"><strong>Post-session transcription</strong></a> is a separate feature from real-time transcription. It runs after the session recording has stopped. VideoSDK transcribes the recorded audio file and optionally generates a structured AI summary. The output is available in multiple formats: JSON, SRT, TXT, TSV, and VTT.</p><p>This is particularly useful in a telemedicine context because the doctor does not need to start a separate transcription stream during the call. They simply enable it on <code>startRecording</code>, and the full transcript is available once the recording is processed.</p><h3 id="enabling-post-transcription-via-startrecording">Enabling post-transcription via startRecording</h3><p>Pass a <code>transcription</code> configuration object as the fourth argument to <code>startRecording</code>:</p><pre><code class="language-jsx">import { useMeeting } from "@videosdk.live/react-sdk";

function DoctorRecordingWithTranscription() {
  const { startRecording, stopRecording } = useMeeting();

  const handleStartRecording = () =&gt; {
    const webhookUrl = "https://your-backend.com/webhooks/recording";

    const transcription = {
      enabled: true, // enables post-session transcription
      summary: {
        enabled: true, // generates an AI summary after transcription
        prompt:
          "Write a clinical summary with sections: Chief Complaint, Doctor's Assessment, Prescription Notes, Follow-up Actions",
      },
    };

    // startRecording(webhookUrl, awsDirPath, config, transcription)
    startRecording(webhookUrl, null, null, transcription);
  };

  return (
    &lt;&gt;
      &lt;button onClick={handleStartRecording}&gt;Start Recording&lt;/button&gt;
      &lt;button onClick={stopRecording}&gt;Stop Recording&lt;/button&gt;
    &lt;/&gt;
  );
}</code></pre><h3 id="retrieving-the-transcript-after-the-session">Retrieving the transcript after the session</h3><p>Once the recording stops, VideoSDK processes the audio and triggers a webhook to your configured URL. After processing completes, you can also retrieve transcription data using the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/transcription-and-summary/post-transcribe-meeting" rel="noreferrer">VideoSDK Post Transcription API </a>(<code>fetchPostTranscriptions</code>). The response includes file paths in all supported formats:</p><pre><code class="language-json">{
  "id": "40b0a4ed-9842-40c9-a288-e4b1bf98a90a",
  "status": "completed",
  "roomId": "abc-xyzw-lmno",
  "sessionId": "621497578bea0d0404c35c4c",
  "recordingId": "65d303d6d2c373dfd71b38a2",
  "transcriptionFilePaths": {
    "json": "https://cdn.videosdk.live/transcriptions/dummy/dummy.json",
    "srt": "https://cdn.videosdk.live/transcriptions/dummy/dummy.srt",
    "txt": "https://cdn.videosdk.live/transcriptions/dummy/dummy.txt",
    "tsv": "https://cdn.videosdk.live/transcriptions/dummy/dummy.tsv",
    "vtt": "https://cdn.videosdk.live/transcriptions/dummy/dummy.vtt"
  },
  "summarizedFilePaths": {
    "txt": "https://cdn.videosdk.live/transcriptions/dummy/dummy-summary.txt"
  }
}</code></pre><p>Note that there may be a delay between when <code>stopRecording</code> is called and when the transcript is ready. The delay depends on server load and the duration of the session. Do not assume the transcript is immediately available after the recording stops; poll the status field or rely on the webhook trigger.</p><p>The <code>.txt</code> file in <code>transcriptionFilePaths</code> is suitable for storing in a plain EHR notes field. The <code>.json</code> file is better for structured data pipelines that need speaker attribution and timestamps. The <code>summarizedFilePaths.txt</code> contains the AI-generated summary text.</p><h2 id="cloud-recording">Cloud recording</h2><p>Recording is exposed through the <code>startRecording</code> and <code>stopRecording</code> methods from <code>useMeeting</code>, Any participant can start or stop recording at any time during a session.</p><h3 id="start-stop-and-retrieve-recordings">Start, stop, and retrieve recordings</h3><pre><code class="language-jsx">import { useMeeting, Constants } from "@videosdk.live/react-sdk";

function RecordingControls() {
  const { startRecording, stopRecording } = useMeeting({
    onRecordingStateChanged: ({ status }) =&gt; {
      switch (status) {
        case Constants.recordingEvents.RECORDING_STARTING:
          console.log("Recording is starting...");
          break;
        case Constants.recordingEvents.RECORDING_STARTED:
          console.log("Recording is active");
          break;
        case Constants.recordingEvents.RECORDING_STOPPING:
          console.log("Recording is stopping...");
          break;
        case Constants.recordingEvents.RECORDING_STOPPED:
          console.log("Recording stopped. File available in dashboard.");
          break;
        default:
          break;
      }
    },
  });

  return (
    &lt;&gt;
      &lt;button
        onClick={() =&gt;
          startRecording(
            "https://your-backend.com/webhooks/recording",
            null,  // awsDirPath — replace with S3 path to use your own storage
            null,  // config
            null   // transcription — see post-transcription section below
          )
        }
      &gt;
        Record Session
      &lt;/button&gt;
      &lt;button onClick={stopRecording}&gt;Stop Recording&lt;/button&gt;
    &lt;/&gt;
  );
}</code></pre><p>After the recording is processed, VideoSDK posts a webhook to the URL you passed in <code>startRecording</code>. The payload includes the file URL. Your backend stores this URL in the patient's appointment record, from where it can be surfaced on the doctor's dashboard or sent to the patient via email.</p><p>There is no dedicated client-side "retrieve" method in the React SDK. Retrieval is via the webhook payload or the VideoSDK developer dashboard.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li>To build an online doctor consultation platform, you need an external appointment scheduler and a VideoSDK room as the session layer. They connect through a shared <code>meetingId</code>.</li><li>VideoSDK's React SDK exposes four verified hooks for telemedicine: <code>useMeeting</code> (join, leave, mic, camera, recording), <code>useParticipant</code> (per-user streams), <code>usePubSub</code> (in-session chat), and <code>useTranscription</code> (real-time speech-to-text with AI summary).</li><li>VideoSDK supports two transcription modes. <code>useTranscription</code> streams live text during the session. Post-session transcription runs after the recording ends and is enabled by passing a <code>transcription</code> config object as the fourth argument to <code>startRecording(webhookUrl, awsDirPath, config, transcription)</code>. The post-session output includes structured files in JSON, SRT, TXT, TSV, and VTT formats, retrievable via the <code>fetchPostTranscriptions</code> API.</li><li>Appointment scheduling, EHR integration, and prescription workflows are outside VideoSDK's scope. Your backend must own those and consume VideoSDK webhook payloads to feed them.</li><li>Token generation must happen on your server. Never expose your VideoSDK API secret on the client.</li></ul><h2 id="faq">FAQ</h2><p><strong>Q1. How many participants can join a VideoSDK room?</strong></p><p>VideoSDK's documentation for the React SDK does not specify a hard room participant limit in the public feature guides. For production deployments, check your plan limits in the VideoSDK dashboard at <a href="https://app.videosdk.live">app.videosdk.live</a> or contact their support for exact capacity numbers relevant to your use case.</p><p><strong>Q2. Can the doctor share their screen during a consultation?</strong></p><p>Screen sharing is part of the VideoSDK feature set. The React SDK documentation lists it under advanced features. It is accessible via stream controls within the <code>useMeeting</code> and <code>useParticipant</code> hooks. The exact method names should be verified against the <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/device-management/screen-share" rel="noreferrer">VideoSDK screen sharing guide</a> before implementation.</p><p><strong>Q3. How accurate is the VideoSDK real-time transcription?</strong></p><p>The transcription is powered by an AI speech-to-text engine exposed through <code>useTranscription</code>. VideoSDK's documentation does not publish a word error rate benchmark. Accuracy will vary with audio quality, speaker accent, and medical terminology. For clinical documentation, treat the transcript as a draft that the doctor reviews and edits before storing in the EHR.</p><p><strong>Q4. Can recordings be sent to the patient automatically?</strong></p><p>VideoSDK does not send recordings to patients directly. When <code>stopRecording</code> is called, VideoSDK posts a webhook to the URL you configured in <code>startRecording</code>. Your backend receives that webhook, extracts the file URL, and can then trigger any delivery mechanism: an email with the link, a patient portal notification, or a write to the patient's EHR timeline.</p><p><strong>Q5. What is the cost model for VideoSDK?</strong></p><p>VideoSDK operates on a <a href="https://www.videosdk.live/pricing" rel="noreferrer">usage-based pricing model</a>. Charges are based on participant minutes, recording minutes, and other feature usage. A free tier is available for development. Always verify current rates on their pricing page before estimating costs for a production deployment, as plans may have changed.</p><h2 id="conclusion">Conclusion</h2><p>Building an online doctor consultation platform requires pairing a booking system you control with a real-time video layer built for low-latency, secure sessions. VideoSDK handles the media transport, chat, recording, and transcription through four well-documented React hooks: <code>useMeeting</code>, <code>useParticipant</code>, <code>usePubSub</code>, and <code>useTranscription</code>. Each hook has a clear responsibility, and all code in this guide uses verified method names from the VideoSDK React SDK documentation.</p><p>The appointment scheduling, EHR integration, and prescription workflow remain your application's responsibility. VideoSDK delivers the session data to your backend via webhooks, and from there your platform decides how to store and surface it.</p><p>If you are starting a telemedicine app development project, the fastest path to a working MVP is to implement the sections in this guide in order: environment setup, patient join flow, doctor controls with recording, PubSub chat, real-time transcription, and post-session transcription. The post-session transcription is the most EHR-friendly output, as it gives you structured files with speaker attribution that you can parse and store against the appointment record.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Live Video Cam Room App with WebRTC]]></title><description><![CDATA[A step-by-step guide to building a multi-participant live video cam room app using WebRTC and VideoSDK. Covers setup, video grids, audio, chat, screen sharing, and scalability.]]></description><link>https://www.videosdk.live/blog/build-live-video-cam-room-app-webrtc</link><guid isPermaLink="false">69fc8eaa55831517a5a9fb41</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 07 May 2026 13:26:01 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--06_47_40-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> You can build a fully functional multi-participant video cam room using VideoSDK's React SDK in a single afternoon. VideoSDK wraps WebRTC's signalling, ICE negotiation, and media routing into clean React hooks, so you focus on product features instead of transport-layer code.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--06_47_40-PM.png" alt="How to Build a Live Video Cam Room App with WebRTC"/><p>To build a live video cam room app with <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a>, you need a signalling layer, a media server or peer-to-peer mesh, and a set of SDK primitives for rooms, participants, and media streams. <a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> provides all three through a unified API that abstracts raw WebRTC so you can render a multi-participant video grid, control audio, add in-room chat, and share screens with minimal boilerplate.</p><h2 id="how-videosdk-uses-webrtc">How VideoSDK uses WebRTC</h2><p><strong>WebRTC:</strong> WebRTC is an open standard that enables real-time audio and video communication directly between browsers and native apps without a plugin.</p><p>VideoSDK uses WebRTC as its transport layer. Rather than exposing raw <code>RTCPeerConnection</code> objects, VideoSDK models a session around three core abstractions documented on the <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/concept-and-architecture">Concept and Architecture page</a>:</p><p><strong>Meeting / Room</strong> is a virtual place where participants interact in real-time voice, video, and screen-sharing sessions. Every room is uniquely identified by a <code>meetingId</code> or <code>roomId</code>. A single room can host multiple sessions over its lifetime, each identified by a <code>sessionId</code>.</p><p><strong>Participant</strong> represents each user in the room. The local participant controls their own microphone and camera. Remote participants receive audio and video streams from the local participant and from each other. Every participant has a unique <code>participantId</code>.</p><p><strong>MediaStream and Track</strong> are the WebRTC primitives VideoSDK exposes when needed. A <code>MediaStream</code> is a collection of audio and video tracks. A track is a continuous flow of audio or video data. VideoSDK manages track negotiation internally but surfaces <code>micStream</code> and <code>webcamStream</code> on each participant so you can attach them to HTML <code>&lt;video&gt;</code> and <code>&lt;audio&gt;</code> elements.</p><p>Events and notifications round out the model. The SDK fires callbacks when participants join or leave, when media state changes, and when SDK-level errors occur. These callbacks are the primary mechanism for keeping your UI in sync with the room state.</p><h2 id="setting-up-the-project">Setting up the project</h2><h3 id="installing-the-sdk">Installing the SDK</h3><p>VideoSDK publishes two web SDKs: a plain JavaScript SDK (<code>@videosdk.live/js-sdk</code>) and a React SDK (<code>@videosdk.live/react-sdk</code>). This guide uses the React SDK because its hooks eliminate most imperative setup code.</p><pre><code class="language-bash">npm install "@videosdk.live/react-sdk"</code></pre><p>For the plain JavaScript SDK:</p><pre><code class="language-bash">npm install "@videosdk.live/js-sdk"</code></pre><h3 id="getting-a-token-and-creating-a-room">Getting a token and creating a room</h3><p>You need two things before joining a room: an auth token and a <code>meetingId</code>. Generate a temporary token from the <a href="https://app.videosdk.live">VideoSDK dashboard</a>. In production, generate tokens server-side and never expose your API secret to the client.</p><pre><code class="language-js">const authToken = "&lt;Generated-from-dashboard&gt;";

async function createMeeting() {
  const res = await fetch("https://api.videosdk.live/v2/rooms", {
    method: "POST",
    headers: {
      authorization: authToken,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({}),
  });
  const { roomId } = await res.json();
  return roomId;
}</code></pre><h3 id="wrapping-your-app-with-meetingprovider">Wrapping your app with MeetingProvider</h3><p>The React SDK exposes <code>MeetingProvider</code>, which is a context provider that makes meeting state available to all child components. Wrap your room UI with it:</p><pre><code class="language-jsx">import { MeetingProvider } from "@videosdk.live/react-sdk";

function App() {
  const meetingId = "&lt;roomId-from-API&gt;";

  return (
    &lt;MeetingProvider
      config={{
        meetingId,
        micEnabled: true,
        webcamEnabled: true,
        name: "Participant Name",
      }}
      token={authToken}
    &gt;
      &lt;MeetingView /&gt;
    &lt;/MeetingProvider&gt;
  );
}</code></pre><p>Inside <code>MeetingView</code>, call <code>useMeeting</code> to access the <code>join</code> method and start the session:</p><pre><code class="language-jsx">import { useMeeting } from "@videosdk.live/react-sdk";

function MeetingView() {
  const { join, participants } = useMeeting({
    onMeetingJoined: () =&gt; {
      console.log("Joined the meeting");
    },
  });

  return (
    &lt;&gt;
      &lt;button onClick={join}&gt;Join Room&lt;/button&gt;
      &lt;ParticipantGrid participants={participants} /&gt;
    &lt;/&gt;
  );
}</code></pre><h2 id="building-the-video-grid">Building the video grid</h2><p>A <strong>cam room</strong> is a multi-participant real-time video space with a grid layout where every connected participant appears in their own video tile. The <code>useMeeting</code> hook returns a <code>participants</code> Map, where keys are <code>participantId</code> strings and values are participant objects.</p><p>Iterate over this Map to render one tile per participant:</p><pre><code class="language-jsx">import { useParticipant } from "@videosdk.live/react-sdk";
import { useEffect, useRef } from "react";

function ParticipantGrid({ participants }) {
  return (
    &lt;div style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: 8 }}&gt;
      {[...participants.keys()].map((participantId) =&gt; (
        &lt;ParticipantTile key={participantId} participantId={participantId} /&gt;
      ))}
    &lt;/div&gt;
  );
}

function ParticipantTile({ participantId }) {
  const { displayName, webcamStream, micOn, webcamOn } = useParticipant(participantId);
  const videoRef = useRef(null);

  useEffect(() =&gt; {
    if (videoRef.current &amp;&amp; webcamStream) {
      videoRef.current.srcObject = new MediaStream([webcamStream.track]);
    }
  }, [webcamStream]);

  return (
    &lt;div style={{ position: "relative", background: "#111", borderRadius: 8 }}&gt;
      &lt;video
        ref={videoRef}
        autoPlay
        playsInline
        muted
        style={{ width: "100%", borderRadius: 8, display: webcamOn ? "block" : "none" }}
      /&gt;
      {!webcamOn &amp;&amp; (
        &lt;div style={{ color: "#fff", textAlign: "center", padding: 24 }}&gt;
          Camera off
        &lt;/div&gt;
      )}
      &lt;div style={{ position: "absolute", bottom: 8, left: 8, color: "#fff" }}&gt;
        {displayName} {!micOn &amp;&amp; "(muted)"}
      &lt;/div&gt;
    &lt;/div&gt;
  );
}</code></pre><p>The <code>useParticipant</code> hook exposes <code>webcamOn</code> and <code>micOn</code> as booleans that update reactively whenever a participant enables or disables their camera or microphone. No polling or manual event subscriptions required.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--06_45_09-PM.png" class="kg-image" alt="How to Build a Live Video Cam Room App with WebRTC" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Modern Video Conference UI</span></figcaption></img></figure><h2 id="audio-controls">Audio controls</h2><h3 id="local-mute-and-unmute">Local mute and unmute</h3><p>The <code>useMeeting</code> hook provides three mic methods, all verified from the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/handling-media/mute-unmute-mic">Mute / Unmute Mic documentation</a>:</p><ul><li><code>muteMic()</code> stops publishing audio to other participants.</li><li><code>unmuteMic()</code> starts publishing audio.</li><li><code>toggleMic()</code> switches based on the current state.</li></ul><pre><code class="language-jsx">import { useMeeting } from "@videosdk.live/react-sdk";

function AudioControls() {
  const { muteMic, unmuteMic, toggleMic, localMicOn } = useMeeting();

  return (
    &lt;button onClick={toggleMic}&gt;
      {localMicOn ? "Mute" : "Unmute"}
    &lt;/button&gt;
  );
}</code></pre><p><code>localMicOn</code> is a boolean from <code>useMeeting</code> that reflects the local participant's current mic state.</p><h3 id="detecting-audio-state-changes-on-remote-participants">Detecting audio state changes on remote participants</h3><p>To show a mute indicator on each tile, read the <code>micOn</code> property from <code>useParticipant</code>. To respond to stream lifecycle events, pass callbacks to <code>useParticipant</code>:</p><pre><code class="language-js">const { micOn } = useParticipant(participantId, {
  onStreamEnabled(stream) {
    if (stream.kind === "audio") {
      console.log("Audio stream on:", stream);
    }
  },
  onStreamDisabled(stream) {
    if (stream.kind === "audio") {
      console.log("Audio stream off:", stream);
    }
  },
  onMediaStatusChanged({ kind, newStatus }) {
    console.log("Media kind:", kind, "new status:", newStatus);
  },
});</code></pre><p>The docs do not document an <code>onSpeakerChanged</code> or audio level event on <code>useParticipant</code> in the React SDK. Use the <code>onStreamEnabled</code> / <code>onStreamDisabled</code> / <code>onMediaStatusChanged</code> callbacks for audio state tracking.</p><h2 id="chat-in-the-room">Chat in the room</h2><p>VideoSDK implements in-room messaging through a publish-subscribe mechanism called <strong>PubSub</strong>. PubSub: PubSub is a pattern where publishers send messages to a named topic and subscribers receive them in real time.</p><p>The React SDK exposes <code>usePubSub</code>, verified from the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/pubsub">PubSub documentation</a>:</p><pre><code class="language-jsx">import { usePubSub } from "@videosdk.live/react-sdk";

function ChatView() {
  const { publish, messages } = usePubSub("CHAT", {
    onMessageReceived: (message) =&gt; {
      console.log("New message:", message);
    },
    onOldMessagesReceived: (messages) =&gt; {
      console.log("Persisted messages:", messages);
    },
  });

  const sendMessage = async () =&gt; {
    try {
      await publish("Hello everyone!", { persist: true });
    } catch (e) {
      console.error("PubSub error:", e);
    }
  };

  return (
    &lt;&gt;
      &lt;button onClick={sendMessage}&gt;Send&lt;/button&gt;
      {messages.map((msg, i) =&gt; (
        &lt;p key={i}&gt;
          &lt;strong&gt;{msg.senderName}:&lt;/strong&gt; {msg.message}
        &lt;/p&gt;
      ))}
    &lt;/&gt;
  );
}</code></pre><p>Setting <code>persist: true</code> stores the message for the session duration. Late-joining participants receive these stored messages through the <code>onOldMessagesReceived</code> callback. This solves one of the common cam room development problems: participants who join mid-session miss earlier context.</p><p>You can also target specific participants using the <code>sendOnly</code> option, passing an array of <code>participantId</code> strings. PubSub works for any topic name, so you can use it for raise-hand signals, layout switches, and polls in addition to chat.</p><h2 id="screen-sharing">Screen sharing</h2><p><a href="https://www.videosdk.live/blog/integrate-screen-share-in-react-js" rel="noreferrer"><strong>Screen sharing</strong></a> in VideoSDK is enabled by calling <code>enableScreenShare()</code> and disabled by calling <code>disableScreenShare()</code>, both available from <code>useMeeting</code>. The docs also provide a <code>toggleScreenShare()</code> shorthand.</p><pre><code class="language-jsx">import { useMeeting } from "@videosdk.live/react-sdk";

function ScreenShareButton() {
  const { enableScreenShare, disableScreenShare, localScreenShareOn } = useMeeting();

  return (
    &lt;button onClick={localScreenShareOn ? disableScreenShare : enableScreenShare}&gt;
      {localScreenShareOn ? "Stop sharing" : "Share screen"}
    &lt;/button&gt;
  );
}</code></pre><p>When a participant starts sharing, the <code>screenShareStream</code> property becomes available on that participant's <code>useParticipant</code> hook. Attach it to a <code>&lt;video&gt;</code> element the same way you attach <code>webcamStream</code>. The VideoSDK docs also expose a <code>screenshareEnabled</code> boolean on <code>useParticipant</code> to conditionally render the screen share tile.</p><h2 id="scaling-the-room">Scaling the room</h2><p>The VideoSDK <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/scalability/scalability-guide-large-meetings">Scalability Guide</a> documents two features for large multi-participant meetings.</p><h3 id="player-component-and-adaptive-subscriptions">Player component and adaptive subscriptions</h3><p>The <code>VideoPlayer</code> component (currently in BETA, requires SDK version 0.2.2 or later) automatically pauses off-screen video streams and adjusts stream quality to match the container size when <code>maxQuality: "auto"</code> is set.</p><pre><code class="language-jsx">import { VideoPlayer } from "@videosdk.live/react-sdk";

function ParticipantTile({ participantId }) {
  return (
    &lt;VideoPlayer
      participantId={participantId}
      type="video"
      containerStyle={{ height: "100%", width: "100%" }}
    /&gt;
  );
}</code></pre><p><strong>Adaptive Subscriptions</strong> (also BETA) prioritize the dominant speaker and pinned participants when bandwidth is constrained. Muted participants' video is paused first, followed by least-dominant speakers.</p><p>Enable adaptive subscriptions when the meeting is joined:</p><pre><code class="language-js">const { join, enableAdaptiveSubscriptions } = useMeeting({
  onMeetingJoined: () =&gt; {
    enableAdaptiveSubscriptions();
  },
});</code></pre><p>Listen for stream pause and resume events on <code>useParticipant</code> to update your UI:</p><pre><code class="language-js">useParticipant("participantId", {
  onStreamPaused: ({ kind, reason }) =&gt; {
    console.log(reason); // "muted" or "leastDominance"
  },
  onStreamResumed: ({ kind, reason }) =&gt; {
    console.log(reason); // "adaptiveSubscriptionsDisabled" or "networkStable"
  },
});</code></pre><h3 id="participant-limits">Participant limits</h3><p>The VideoSDK docs do not publish a hard participant ceiling in the scalability guide. For rooms with very large participant counts, the docs recommend combining the Player Component, Adaptive Subscriptions, and UI-level pagination to reduce active stream subscriptions. Contact VideoSDK support for production capacity guidance specific to your plan.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li>VideoSDK wraps <a href="https://www.videosdk.live/blog/what-is-webrtc-signaling" rel="noreferrer">WebRTC signalling</a>, ICE negotiation, and media routing, so you write React hooks rather than transport-layer code.</li><li>The <code>useMeeting</code> hook gives you room-level controls: join, leave, mute, screen share, and adaptive subscriptions.</li><li>The <code>useParticipant</code> hook gives you per-participant state: media streams, mic/webcam status, and stream lifecycle callbacks.</li><li>PubSub (<code>usePubSub</code>) handles in-room chat and any custom signalling your product needs.</li><li>The Player Component and Adaptive Subscriptions reduce bandwidth consumption in rooms with 10 or more participants, though both are currently in BETA.</li></ul><h2 id="faq">FAQ</h2><p><strong>Q1. What is the maximum number of participants in a VideoSDK room?</strong></p><p>The VideoSDK documentation does not specify a hard maximum participant count for conference rooms. The scalability guide addresses rooms with 10 or more participants and recommends the Player Component and Adaptive Subscriptions to manage bandwidth at scale. For specific capacity limits and enterprise-grade room sizes, check the <a href="https://www.videosdk.live/pricing" rel="noreferrer">VideoSDK pricing page</a> or contact their support team.</p><p><strong>Q2. How do you handle participants joining late?</strong></p><p>When a participant joins an existing session, the <code>useMeeting</code> hook's <code>participants</code> Map already contains all currently connected participants. For chat history, use PubSub with <code>persist: true</code> when publishing messages. Late joiners receive persisted messages through the <code>onOldMessagesReceived</code> callback when they subscribe to that PubSub topic.</p><p><strong>Q3. Can the room be password-protected?</strong></p><p>The VideoSDK React SDK and JavaScript SDK documentation do not describe a built-in password field on the room or <code>MeetingProvider</code>. You can implement access control at the token level by generating tokens server-side only after verifying the user's credentials. This means an unauthorized user can never obtain a valid token for the room and cannot join.</p><p><strong>Q4. How do you record the entire session?</strong></p><p>VideoSDK supports <a href="https://www.videosdk.live/blog/cloud-recording-and-rtmp-pricing" rel="noreferrer">cloud recording</a>. The docs list cloud recording as a supported feature under the "Recording" section of the sidebar. To start recording, use the <code>startRecording()</code> method available from <code>useMeeting</code>. Recordings are stored on VideoSDK servers and are accessible through the VideoSDK Session Dashboard and the Sessions API. Recording details and storage options vary by plan.</p><h2 id="conclusion">Conclusion</h2><p>Building a live video cam room app with WebRTC no longer requires deep knowledge of ICE servers, DTLS handshakes, or SDP negotiation. VideoSDK abstracts these layers through the <code>MeetingProvider</code>, <code>useMeeting</code>, and <code>useParticipant</code> hooks, giving you a reliable foundation for multi-participant video room development.</p><p>The pattern is consistent: use <code>useMeeting</code> for room-level actions and <code>useParticipant</code> for per-tile state. Add <code>usePubSub</code> for chat, call <code>enableScreenShare()</code> for screen sharing, and enable <code>enableAdaptiveSubscriptions()</code> to handle bandwidth constraints as your cam room grows.</p><p>Start with the React SDK quickstart at <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">docs.videosdk.live</a>, get a token from the dashboard, and you can have your first WebRTC video room rendering in minutes.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Social Live Streaming App Like TikTok Live]]></title><description><![CDATA[A step-by-step guide to building a host-viewer live streaming app with VideoSDK's Interactive Live Streaming (ILS/HLS), real-time reactions via PubSub, and CDN delivery that scales to thousands of concurrent viewers.]]></description><link>https://www.videosdk.live/blog/build-social-live-streaming-app-like-tiktok-live</link><guid isPermaLink="false">69fc7c6555831517a5a9fafe</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 07 May 2026 12:12:20 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--05_29_11-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> You can build a social live streaming app like TikTok Live using VideoSDK's Interactive Live Streaming (ILS) mode. The host broadcasts via WebRTC, VideoSDK converts the feed to HLS for CDN delivery to viewers, and <code>usePubSub</code> handles real-time reactions and chat. This guide walks through every step in React with verified API methods.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--05_29_11-PM.png" alt="How to Build a Social Live Streaming App Like TikTok Live"/><p>Building a social live streaming app like TikTok Live means handling two fundamentally different participant types at once: a host who produces high-quality <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> video and an audience of potentially thousands who consume a low-latency HLS stream. VideoSDK's <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">Interactive Live Streaming</a> (ILS) mode handles both sides from a single SDK.</p><p>This guide walks through a host-viewer architecture with real-time emoji reactions, live chat, and CDN-backed HLS delivery.</p><h3 id="interactive-live-streaming-vs-plain-broadcast">Interactive live streaming vs plain broadcast</h3><p><strong>Interactive Live Streaming (ILS):</strong> <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">ILS</a> is a streaming model where one or more host participants produce audio and video over WebRTC, and that feed is simultaneously converted to <a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer">HLS</a> for consumption by a large viewer audience. Unlike a plain <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a> broadcast, ILS keeps a signaling channel open between hosts and viewers, which enables real-time features such as chat, reactions, and audience elevation.</p><p>In VideoSDK, ILS is the term for this architecture. The SDK exposes it through a participant mode system and the <code>startHls()</code> / <code>stopHls()</code> methods on the <code>useMeeting</code> hook.</p><h4 id="host-participant-vs-viewer-participant">Host participant vs viewer participant</h4><p>VideoSDK uses a <code>mode</code> parameter to distinguish participant roles (as of React SDK v0.2.0):</p><ul><li><strong><code>SEND_AND_RECV</code></strong>: The participant produces audio and video streams and consumes others. This is the host mode.</li><li><strong><code>RECV_ONLY</code></strong>: The participant consumes streams without producing any. Suitable for viewers who want a low-overhead WebRTC connection with signaling.</li><li><strong><code>SIGNALLING_ONLY</code></strong>: No audio or video streams are produced or consumed. Used only for signaling.</li></ul><p>Note: In SDK versions before v0.2.0, <code>CONFERENCE</code> and <code>VIEWER</code> were used instead of <code>SEND_AND_RECV</code> and <code>SIGNALLING_ONLY</code>. Do not mix SDK versions across participants.</p><p>A large HLS audience does not join the VideoSDK meeting as participants at all. They consume the <code>playbackHlsUrl</code> from a standard video player, entirely outside the WebRTC session.</p><h3 id="architecture">Architecture</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--05_25_27-PM.png" class="kg-image" alt="How to Build a Social Live Streaming App Like TikTok Live" loading="lazy" width="1693" height="929"><figcaption><span style="white-space: pre-wrap;">Live Streaming System Architecture </span></figcaption></img></figure><p>The host joins the VideoSDK meeting with <code>SEND_AND_RECV</code> mode. The host calls <code>startHls()</code> on the <code>useMeeting</code> hook, which triggers VideoSDK's server-side transcoder to generate an HLS stream. That stream is distributed via CDN. Viewers pull the <code>playbackHlsUrl</code> from <code>hlsUrls</code> (a property on <code>useMeeting</code>) and play it in any HLS-compatible video player. Real-time reactions and chat flow over <code>usePubSub</code>, which works for both meeting participants and, if you join viewers as <code>SIGNALLING_ONLY</code>, for the audience too.</p><h3 id="setting-up-the-host-stream-react">Setting up the host stream (React)</h3><p>Install the SDK first:</p><pre><code class="language-bash">npm install @videosdk.live/react-sdk</code></pre><p>Wrap your app in <code>MeetingProvider</code> with the host's token and meeting ID. Set the participant mode to <code>SEND_AND_RECV</code>:</p><pre><code class="language-jsx">import { MeetingProvider } from "@videosdk.live/react-sdk";

function App() {
  return (
    &lt;MeetingProvider
      config={{
        meetingId: "your-meeting-id",
        micEnabled: true,
        webcamEnabled: true,
        name: "Host Name",
        mode: "SEND_AND_RECV",
      }}
      token="your-videosdk-token"
      joinWithoutUserInteraction={false}
    &gt;
      &lt;HostView /&gt;
    &lt;/MeetingProvider&gt;
  );
}</code></pre><h4 id="starting-hls-from-the-host">Starting HLS from the host</h4><p>Use the <code>startHls()</code> method from <code>useMeeting</code>. It accepts a <code>config</code> object and an optional <code>transcription</code> object. The <code>config.layout.type</code> can be <code>"GRID"</code>, <code>"SPOTLIGHT"</code>, or <code>"SIDEBAR"</code>. For a TikTok-style single-creator stream, <code>"SPOTLIGHT"</code> with <code>priority: "PIN"</code> is the correct choice.</p><pre><code class="language-jsx">import { useMeeting } from "@videosdk.live/react-sdk";

function HostView() {
  const {
    join,
    startHls,
    stopHls,
    toggleMic,
    toggleWebcam,
    localMicOn,
    localWebcamOn,
  } = useMeeting();

  const handleStartStream = () =&gt; {
    startHls(
      {
        layout: {
          type: "SPOTLIGHT",
          priority: "PIN",
          gridSize: 1,
        },
        theme: "DARK",
        mode: "video-and-audio",
        quality: "high",
        recording: {
          enabled: true,
        },
      },
      {
        enabled: false,
      }
    );
  };

  return (
    &lt;div&gt;
      &lt;button onClick={join}&gt;Go Live&lt;/button&gt;
      &lt;button onClick={handleStartStream}&gt;Start HLS&lt;/button&gt;
      &lt;button onClick={stopHls}&gt;End Stream&lt;/button&gt;
      &lt;button onClick={toggleMic}&gt;{localMicOn ? "Mute" : "Unmute"}&lt;/button&gt;
      &lt;button onClick={toggleWebcam}&gt;
        {localWebcamOn ? "Camera Off" : "Camera On"}
      &lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><p>The <code>startHls()</code> call triggers the <code>onHlsStarted()</code> event on all participants. The <code>stopHls()</code> call triggers <code>onHlsStopped()</code>. Both are confirmed in the <code>useMeeting</code> methods documentation.</p><p><code>startRecording()</code> is also available separately if you want <a href="https://www.videosdk.live/blog/cloud-recording-and-rtmp-pricing" rel="noreferrer">cloud recording</a> independent of the HLS stream.</p><h3 id="viewer-interface-react">Viewer interface (React)</h3><p>Viewers who join the VideoSDK meeting use <code>RECV_ONLY</code> mode. They receive the signaling channel but produce no media streams, keeping bandwidth and compute low.</p><pre><code class="language-jsx">import { MeetingProvider, useMeeting } from "@videosdk.live/react-sdk";

// Viewer wrapper
function ViewerApp() {
  return (
    &lt;MeetingProvider
      config={{
        meetingId: "your-meeting-id",
        micEnabled: false,
        webcamEnabled: false,
        name: "Viewer Name",
        mode: "RECV_ONLY",
      }}
      token="your-viewer-token"
      joinWithoutUserInteraction={true}
    &gt;
      &lt;ViewerScreen /&gt;
    &lt;/MeetingProvider&gt;
  );
}</code></pre><h4 id="playing-the-hls-stream">Playing the HLS stream</h4><p>The <code>hlsUrls</code> property on <code>useMeeting</code> provides two URLs once HLS is active: <code>playbackHlsUrl</code> and <code>livestreamUrl</code>. Use <code>playbackHlsUrl</code> for viewer playback. Feed it to any HLS player. The example below uses <code>hls.js</code>:</p><pre><code class="language-bash">npm install hls.js</code></pre><pre><code class="language-jsx">import { useMeeting } from "@videosdk.live/react-sdk";
import Hls from "hls.js";
import { useEffect, useRef } from "react";

function ViewerScreen() {
  const { hlsUrls, isHls } = useMeeting();
  const videoRef = useRef(null);

  useEffect(() =&gt; {
    if (isHls &amp;&amp; hlsUrls?.playbackHlsUrl &amp;&amp; videoRef.current) {
      if (Hls.isSupported()) {
        const hls = new Hls();
        hls.loadSource(hlsUrls.playbackHlsUrl);
        hls.attachMedia(videoRef.current);
        hls.on(Hls.Events.MANIFEST_PARSED, () =&gt; {
          videoRef.current.play();
        });
        return () =&gt; hls.destroy();
      } else if (videoRef.current.canPlayType("application/vnd.apple.mpegurl")) {
        // Safari native HLS
        videoRef.current.src = hlsUrls.playbackHlsUrl;
        videoRef.current.play();
      }
    }
  }, [isHls, hlsUrls]);

  return (
    &lt;div&gt;
      {isHls ? (
        &lt;video ref={videoRef} controls style={{ width: "100%" }} /&gt;
      ) : (
        &lt;p&gt;Stream is not live yet.&lt;/p&gt;
      )}
    &lt;/div&gt;
  );
}</code></pre><p><code>isHls</code> is a boolean on <code>useMeeting</code> that is <code>true</code> when HLS is running. <code>hlsUrls</code> is an object with <code>playbackHlsUrl</code> and <code>livestreamUrl</code>, confirmed in the <code>useMeeting</code> properties documentation.</p><h3 id="real-time-reactions-and-chat">Real-time reactions and chat</h3><p><strong><code>usePubSub</code>:</strong> <code>usePubSub</code> is VideoSDK's publish-subscribe hook that delivers string messages across all participants subscribed to the same topic. It works inside the <code>MeetingProvider</code> context and delivers messages to both <code>SEND_AND_RECV</code> and <code>RECV_ONLY</code> participants.</p><p>Each topic is a string you define. Use separate topics to separate reactions from chat messages.</p><p><strong>Emoji reactions:</strong></p><pre><code class="language-jsx">import { usePubSub } from "@videosdk.live/react-sdk";
import { useState } from "react";

function ReactionBar() {
  const [reactions, setReactions] = useState([]);

  const { publish } = usePubSub("REACTIONS", {
    onMessageReceived: (message) =&gt; {
      setReactions((prev) =&gt; [
        ...prev,
        { emoji: message.message, id: message.id },
      ]);
      // Remove after animation completes
      setTimeout(() =&gt; {
        setReactions((prev) =&gt; prev.filter((r) =&gt; r.id !== message.id));
      }, 2000);
    },
  });

  const sendReaction = (emoji) =&gt; {
    publish(emoji, { persist: false });
  };

  return (
    &lt;div&gt;
      {["❤️", "🔥", "👏", "😂"].map((emoji) =&gt; (
        &lt;button key={emoji} onClick={() =&gt; sendReaction(emoji)}&gt;
          {emoji}
        &lt;/button&gt;
      ))}
      &lt;div className="reaction-overlay"&gt;
        {reactions.map((r) =&gt; (
          &lt;span key={r.id} className="floating-reaction"&gt;
            {r.emoji}
          &lt;/span&gt;
        ))}
      &lt;/div&gt;
    &lt;/div&gt;
  );
}</code></pre><p><strong>Live chat</strong></p><pre><code class="language-jsx">import { usePubSub } from "@videosdk.live/react-sdk";
import { useState } from "react";

function ChatPanel() {
  const [text, setText] = useState("");
  const { publish, messages } = usePubSub("CHAT", {
    onOldMessagesReceived: (oldMessages) =&gt; {
      // oldMessages is the persisted history
      console.log("Chat history loaded:", oldMessages);
    },
  });

  const sendMessage = async () =&gt; {
    if (!text.trim()) return;
    await publish(text, { persist: true });
    setText("");
  };

  return (
    &lt;div&gt;
      &lt;div className="chat-messages"&gt;
        {messages.map((msg) =&gt; (
          &lt;div key={msg.id}&gt;
            &lt;strong&gt;{msg.senderName}:&lt;/strong&gt; {msg.message}
          &lt;/div&gt;
        ))}
      &lt;/div&gt;
      &lt;input
        value={text}
        onChange={(e) =&gt; setText(e.target.value)}
        placeholder="Say something..."
      /&gt;
      &lt;button onClick={sendMessage}&gt;Send&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><p>Setting <code>persist: true</code> means late-joining viewers receive the message history through the <code>onOldMessagesReceived</code> callback, verified from the <code>usePubSub</code> documentation.</p><h3 id="qa-and-viewer-participation">Q&amp;A and viewer participation</h3><h4 id="elevating-a-viewer-to-co-host">Elevating a viewer to co-host</h4><p>VideoSDK supports a <code>changeMode()</code> method on <code>useMeeting</code> that switches a participant's mode between <code>SEND_AND_RECV</code>, <code>RECV_ONLY</code>, and <code>SIGNALLING_ONLY</code>. A viewer currently joined as <code>RECV_ONLY</code> can call <code>changeMode("SEND_AND_RECV")</code> to begin sending audio and video, effectively becoming a co-host.</p><pre><code class="language-jsx">import { useMeeting } from "@videosdk.live/react-sdk";

function ViewerControls() {
  const { changeMode } = useMeeting();

  const requestToSpeak = () =&gt; {
    changeMode("SEND_AND_RECV");
  };

  return &lt;button onClick={requestToSpeak}&gt;Request to speak&lt;/button&gt;;
}</code></pre><p>The host can coordinate this elevation through a separate <code>usePubSub</code> topic (for example, <code>"RAISE_HAND"</code>), where a viewer publishes a raise-hand event and the host acknowledges it. The viewer then calls <code>changeMode("SEND_AND_RECV")</code> on confirmation.</p><p>This pattern is composable using the documented <code>changeMode()</code> and <code>usePubSub</code> APIs without any undocumented features.</p><h3 id="scaling-to-thousands-of-viewers">Scaling to thousands of viewers</h3><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK's</a> HLS streaming uses a server-side transcoder that converts the host's WebRTC feed into an HLS manifest. That manifest is served from a <a href="https://www.cloudflare.com/learning/cdn/what-is-a-cdn/" rel="noreferrer nofollow">CDN</a>. Viewers do not connect to the VideoSDK media servers at all. They connect to CDN edge nodes closest to their location.</p><p>This is the same delivery model used by large-scale video platforms. The WebRTC session between the host and VideoSDK's servers remains a small, fixed-size connection regardless of audience size.</p><h4 id="latency-expectations">Latency expectations</h4><p>Two latency values are relevant here:</p><p><a href="https://www.videosdk.live/blog/what-is-latency-in-webrtc" rel="noreferrer"><strong>WebRTC latency</strong></a><strong> (host to VideoSDK):</strong> Approximately 200 to 400 milliseconds. This is the round-trip between the host device and the server.</p><p><strong>HLS latency (VideoSDK to viewer):</strong> HLS introduces buffering by design. Typical HLS latency is 10 to 20 seconds with standard segment sizes. <a href="https://www.videosdk.live/blog/what-is-low-latency-http-live-streaming" rel="noreferrer">Low-Latency HLS (LL-HLS)</a> can reduce this to 2 to 5 seconds, but depends on player support and CDN configuration. VideoSDK generates the HLS stream from the host's feed, and the actual playback delay depends on the player's buffer settings and CDN propagation.</p><p>For features like live chat and reactions, use <code>usePubSub</code> for near-instant delivery. Do not depend on the HLS video delay for synchronizing interactive elements.</p><h3 id="key-takeaways">Key takeaways</h3><ul><li>VideoSDK's HLS mode (<code>startHls()</code>) handles transcoding and CDN delivery from a single method call on the host side.</li><li>Participant modes <code>SEND_AND_RECV</code> and <code>RECV_ONLY</code> (verified in <code>changeMode()</code> docs) control who produces vs. consumes media in the meeting.</li><li>Viewer HLS playback uses the <code>playbackHlsUrl</code> field from the <code>hlsUrls</code> property on <code>useMeeting</code>, fed into any HLS-compatible player.</li><li><code>usePubSub</code> is the correct mechanism for real-time reactions and chat, available to all participant modes.</li><li>Viewer-to-co-host elevation is achievable using <code>changeMode("SEND_AND_RECV")</code>, coordinated through a <code>usePubSub</code> topic for signaling.</li></ul><h3 id="faq">FAQ</h3><p><strong>Q1. What is the maximum viewer count for VideoSDK HLS?</strong></p><p>VideoSDK's HLS delivery uses CDN distribution. Because viewers pull the stream from CDN edge nodes rather than from VideoSDK's media servers directly, the architecture is horizontally scalable. VideoSDK does not publish a hard viewer ceiling in its current documentation. For production limits, check the <a href="https://www.videosdk.live/pricing" rel="noreferrer">VideoSDK pricing page</a> or contact their support team, as limits are plan-dependent.</p><p><strong>Q2. How long can a live stream last?</strong></p><p>VideoSDK does not document a hard maximum stream duration in the React SDK reference. In practice, stream length is constrained by your plan's usage limits (billed per minute of media processing). For exact session length caps, consult the VideoSDK pricing page or contact support.</p><p><strong>Q3. Can the stream be recorded?</strong></p><p>Yes. The <code>startHls()</code> method accepts a <code>config.recording.enabled</code> boolean. Setting it to <code>true</code> enables cloud recording of the HLS stream. Alternatively, <code>startRecording()</code> is a separate method on <code>useMeeting</code> that records the meeting independently, with options for layout, theme, quality, and post-session transcription.</p><p><strong>Q4. What is the end-to-end latency for HLS viewers?</strong></p><p>HLS latency from host capture to viewer playback is typically 10 to 20 seconds with standard segment sizes, due to HLS's chunk-based buffering model. The actual delay depends on segment duration, CDN propagation time, and the HLS player's buffer configuration. WebRTC-to-server latency (host side) is in the range of 200 to 400 milliseconds and is separate from the HLS delivery delay.</p><h3 id="conclusion">Conclusion</h3><p>Building a social live streaming app like TikTok Live requires solving three distinct problems: reliable host media capture, scalable viewer delivery, and real-time audience interaction. VideoSDK's Interactive Live Streaming mode addresses all three in a single SDK. The host joins with <code>SEND_AND_RECV</code>, calls <code>startHls()</code> to trigger CDN distribution, and the audience consumes <code>playbackHlsUrl</code> from any HLS player. Chat and reactions run over <code>usePubSub</code>, independent of the video stream's latency. With <code>changeMode()</code>, a viewer can be elevated to co-host without dropping and rejoining the session. All methods and properties referenced in this article are confirmed from the VideoSDK React SDK documentation at <code>docs.videosdk.live</code>.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Mental Health Video Consultation App: Developer Guide & Compliance Checklist]]></title><description><![CDATA[A step-by-step guide for developers building a mental health video consultation app using VideoSDK. Covers HIPAA psychotherapy notes, 42 CFR Part 2 compliance, waiting rooms, E2EE, AI noise suppression, and cloud recording controls.]]></description><link>https://www.videosdk.live/blog/mental-health-video-consultation-app</link><guid isPermaLink="false">69fc71fc55831517a5a9fab3</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 07 May 2026 11:44:46 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--04_49_05-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> Building a mental health video consultation app requires more than standard HIPAA compliance. You need to handle psychotherapy note protections, substance use disorder record rules under 42 CFR Part 2, token-controlled waiting rooms, end-to-end encrypted sessions, AI-powered noise suppression, and explicit recording consent. This guide walks through each requirement and the VideoSDK React code to implement them correctly.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--04_49_05-PM.png" alt="How to Build a Mental Health Video Consultation App: Developer Guide & Compliance Checklist"/><p>A mental health video consultation app carries stricter privacy obligations than a general telehealth platform. Psychotherapy session notes receive separate legal protection from other <a href="https://en.wikipedia.org/wiki/Protected_health_information" rel="noreferrer nofollow">protected health information</a> (PHI) under <a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api" rel="noreferrer">HIPAA</a>, and <a href="https://en.wikipedia.org/wiki/Substance_use_disorder" rel="noreferrer nofollow">substance use disorder</a> (SUD) treatment records fall under an entirely distinct federal framework called 42 CFR Part 2. </p><h3 id="unique-compliance-requirements-for-mental-health">Unique compliance requirements for mental health</h3><p>Mental health data is not treated the same as other medical data under US federal law. Developers building in this space need to understand three distinct compliance layers.</p><h4 id="hipaa-psychotherapy-notes">HIPAA psychotherapy notes</h4><p><strong>Psychotherapy notes</strong> are notes a mental health provider records in the process of a session, separated from the rest of the medical record. Under the <a href="https://www.ecfr.gov/current/title-45/subtitle-A/subchapter-C/part-164/subpart-E/section-164.524" rel="noreferrer nofollow">HIPAA Privacy Rule (45 CFR 164.524)</a>, these notes receive extra protection beyond general PHI. A covered entity generally cannot use or disclose psychotherapy notes without an authorization that is separate from any other authorization. This means your platform cannot treat session content like a general medical record: you need explicit, documented patient consent before storing, sharing, or processing session data beyond treatment purposes.</p><p>The practical implication for developers: do not log session transcripts or enable auto-transcription without a separate, auditable consent capture in your application layer.</p><h4 id="42-cfr-part-2-for-substance-use-disorder-treatment">42 CFR Part 2 for substance use disorder treatment</h4><p><a href="https://www.ecfr.gov/current/title-42/chapter-I/subchapter-A/part-2" rel="noreferrer"><strong>42 CFR Part 2</strong></a> is a federal regulation that governs records related to substance use disorder treatment at federally assisted programs. It is stricter than HIPAA in several ways. It prohibits disclosure of SUD patient records to third parties, including other healthcare providers, without explicit written consent from the patient, with very narrow exceptions. This regulation applies even if the patient has already signed a general HIPAA authorization.</p><p>For a telehealth developer: if your platform serves SUD treatment programs, you cannot share session recordings, transcripts, or even the fact of treatment without compliant written consent. Recording such sessions by default violates the regulation.</p><h4 id="state-mandated-reporting-and-involuntary-commitment">State mandated reporting and involuntary commitment</h4><p>Most US states require mental health providers to report credible threats of harm to self or others (Tarasoff duties) and to initiate involuntary hold processes when a patient presents imminent risk. Your platform's architecture needs to support this: a therapist must be able to take action outside the video session, and your crisis response flow must not depend on the session remaining active.</p><p>The practical approach is to build a parallel communication channel, covered in the session implementation section below.</p><h3 id="recommended-videosdk-features-for-a-mental-health-video-consultation-app">Recommended VideoSDK features for a mental health video consultation app</h3><p><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">VideoSDK's React SDK</a> provides several documented features that directly address telemental health platform requirements.</p><h4 id="end-to-end-encryption-with-externale2eekeyprovider">End-to-end encryption with <code>ExternalE2EEKeyProvider</code></h4><p><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/security/E2EE" rel="noreferrer"><strong>E2EE (end-to-end encryption)</strong></a> is a documented feature in VideoSDK's React SDK from version 0.3.5 onwards. It encrypts media on the sender's device and decrypts it only on the receiver's device. VideoSDK servers never access or store the encryption keys.</p><p>You enable it by importing <code>ExternalE2EEKeyProvider</code> from <code>@videosdk.live/react-sdk</code>, calling <code>setSharedKey()</code> with your session key, and passing the provider instance as the <code>keyProvider</code> prop to <code>MeetingProvider</code>. Your server is responsible for generating and distributing the key to all session participants over HTTPS before they join.</p><pre><code class="language-jsx">import {
  MeetingProvider,
  ExternalE2EEKeyProvider,
} from "@videosdk.live/react-sdk";
import { useMemo } from "react";

function SecureTherapyApp({ meetingId, token, encryptionKey }) {
  const keyProvider = useMemo(() =&gt; {
    const _keyProvider = new ExternalE2EEKeyProvider();
    // Key must be set before passing to MeetingProvider
    _keyProvider.setSharedKey(encryptionKey);
    return _keyProvider;
  }, [encryptionKey]);

  return (
    &lt;MeetingProvider
      config={{
        meetingId,
        micEnabled: true,
        webcamEnabled: true,
        name: "Patient",
      }}
      token={token}
      keyProvider={keyProvider} // enables E2EE
    &gt;
      &lt;TherapySession /&gt;
    &lt;/MeetingProvider&gt;
  );
}</code></pre><p>You can verify E2EE status at runtime using <code>isE2EEEnabled</code> from <code>useMeeting()</code>. The <code>onE2EEStateChanged</code> callback in <code>useParticipant()</code> reports per-stream encryption state (audio, video, share) with values such as <code>EncryptionSuccess</code>, <code>DecryptionFailed</code>, or <code>MissingKey</code>.</p><p>One critical limitation from the docs: recording and transcription are not supported when E2EE is enabled. This is actually aligned with mental health compliance requirements for SUD sessions, where recording should be off by default anyway. For sessions where recording is clinically justified and consented to, you would not enable E2EE.</p><h4 id="waiting-room-with-onentryrequested">Waiting room with <code>onEntryRequested</code></h4><p>A <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/setup-call/waiting-lobby" rel="noreferrer">waiting room</a> pattern prevents a patient from joining a live session without the therapist explicitly approving. <a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> supports this through token-based permissions. When a patient token includes the <code>ask_join</code> permission, calling <code>join()</code> does not immediately place the patient in the meeting. Instead, it fires an <code>onEntryRequested</code> event to any participant holding the <code>allow_join</code> permission (the therapist).</p><pre><code class="language-javascript">// Therapist token payload (server-side, before signing)
const therapistToken = { permissions: ["allow_join", "allow_mod"] };

// Patient token payload
const patientToken = { permissions: ["ask_join"] };</code></pre><h4 id="cloud-recording-with-startrecording-and-stoprecording">Cloud recording with <code>startRecording()</code> and <code>stopRecording()</code></h4><p>VideoSDK's <code>useMeeting</code> hook exposes <code>startRecording()</code> and <code>stopRecording()</code>. <code>startRecording()</code> accepts a <code>webhookUrl</code>, an <code>awsDirPath</code> for S3 storage, a layout config object, and an optional transcription config. For mental health use cases, call <code>startRecording()</code> only after capturing explicit patient consent in your application layer. Note that recording is incompatible with E2EE: if you have <code>keyProvider</code> set, <code>startRecording()</code> will not function.</p><h4 id="usepubsub-for-in-session-messaging"><code>usePubSub</code> for in-session messaging</h4><p><code><strong>usePubSub</strong></code> is VideoSDK's publish-subscribe hook for real-time in-session messaging. You subscribe to a topic string and receive a <code>publish()</code> function and a <code>messages</code> array. For a therapy platform, use a dedicated <code>CRISIS_ALERT</code> topic to let a therapist trigger an internal alert without interrupting the session UI.</p><pre><code class="language-javascript">import { usePubSub } from "@videosdk.live/react-sdk";

const { publish } = usePubSub("CRISIS_ALERT", {
  onMessageReceived: (message) =&gt; {
    if (message.message === "CRISIS") {
      triggerCrisisProtocol(message.senderId);
    }
  },
});

const sendCrisisAlert = () =&gt; {
  publish("CRISIS", { persist: false });
};</code></pre><h3 id="building-the-therapy-session-app">Building the therapy session app</h3><p><strong>Installation and setup</strong></p><pre><code class="language-bash">npm install @videosdk.live/react-sdk
npm install --save "@videosdk.live/videosdk-media-processor-web"</code></pre><p>Wrap your application in <code>MeetingProvider</code> with <code>joinWithoutUserInteraction</code> set to <code>false</code> so the patient does not join until they explicitly accept the consent screen. Pass the <code>keyProvider</code> instance to enable E2EE.</p><h4 id="pre-session-consent-screen">Pre-session consent screen</h4><p>Before calling <code>join()</code>, render a consent screen that displays the purpose of the session, whether the session may be recorded, the patient's right to withdraw consent, and crisis resources. Only call <code>join()</code> when the patient explicitly clicks "I understand and agree."</p><pre><code class="language-jsx">function ConsentGate({ onConsent }) {
  return (
    &lt;div className="consent-screen"&gt;
      &lt;h2&gt;Before your session&lt;/h2&gt;
      &lt;p&gt;
        This session uses end-to-end encryption. Your video and audio cannot be
        accessed by any server. Recording will only occur with your separate
        written consent.
      &lt;/p&gt;
      &lt;p&gt;
        Crisis resources: National Crisis Hotline: 988 | Crisis Text Line: Text
        HOME to 741741
      &lt;/p&gt;
      &lt;button onClick={onConsent}&gt;I understand and agree to join&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><p><strong>Session component with <code>useMeeting</code> and <code>useParticipant</code></strong></p><pre><code class="language-jsx">function TherapySession() {
  const [consentGiven, setConsentGiven] = React.useState(false);

  const { join, leave, localParticipant, participants, isE2EEEnabled } =
    useMeeting({
      onMeetingJoined: () =&gt; console.log("Session joined"),
      onMeetingLeft: () =&gt; console.log("Session ended"),
      onEntryRequested: ({ participantId, allow, deny }) =&gt; {
        const approved = window.confirm(`Patient requesting entry. Allow?`);
        approved ? allow() : deny();
      },
    });

  if (!consentGiven) {
    return (
      &lt;ConsentGate onConsent={() =&gt; { setConsentGiven(true); join(); }} /&gt;
    );
  }

  return (
    &lt;div className="therapy-session"&gt;
      &lt;div&gt;E2EE active: {isE2EEEnabled ? "Yes" : "No"}&lt;/div&gt;
      {[...participants.keys()].map((id) =&gt; (
        &lt;ParticipantView key={id} participantId={id} /&gt;
      ))}
      &lt;button onClick={leave}&gt;Leave session&lt;/button&gt;
    &lt;/div&gt;
  );
}

function ParticipantView({ participantId }) {
  const { displayName, webcamStream, webcamOn } = useParticipant(
    participantId,
    {
      onE2EEStateChanged: (stateInfo) =&gt; {
        console.log(`E2EE ${stateInfo.state} for ${stateInfo.kind}`);
      },
    }
  );

  const videoRef = React.useRef(null);

  React.useEffect(() =&gt; {
    if (videoRef.current &amp;&amp; webcamStream) {
      const mediaStream = new MediaStream([webcamStream.track]);
      videoRef.current.srcObject = mediaStream;
    }
  }, [webcamStream]);

  return (
    &lt;div&gt;
      &lt;p&gt;{displayName}&lt;/p&gt;
      {webcamOn &amp;&amp; &lt;video ref={videoRef} autoPlay muted /&gt;}
    &lt;/div&gt;
  );
}</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--04_46_03-PM.png" class="kg-image" alt="How to Build a Mental Health Video Consultation App: Developer Guide & Compliance Checklist" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Video Therapy Session Flow with crisis alerts</span></figcaption></img></figure><h3 id="ensuring-audio-and-video-quality">Ensuring audio and video quality</h3><h4 id="ai-noise-suppression-with-videosdknoisesuppressor">AI noise suppression with <code>VideoSDKNoiseSuppressor</code></h4><p><strong>AI noise suppression</strong> is available through the <code>@videosdk.live/videosdk-media-processor-web</code> package. The <code>VideoSDKNoiseSuppressor</code> class takes a raw <code>MediaStream</code> from <code>createMicrophoneAudioTrack()</code> and returns a noise-suppressed stream via <code>getNoiseSuppressedAudioStream()</code>. You then pass that processed stream to <code>changeMic()</code> to replace the active microphone input mid-session.</p><p>This is clinically relevant: a patient calling from a noisy environment may feel self-conscious about ambient sound. Enabling noise suppression reduces that barrier and ensures the therapist hears speech clearly.</p><pre><code class="language-javascript">import {
  useMeeting,
  createMicrophoneAudioTrack,
} from "@videosdk.live/react-sdk";
import { VideoSDKNoiseSuppressor } from "@videosdk.live/videosdk-media-processor-web";

function NoiseSuppressorControl() {
  const noiseProcessor = new VideoSDKNoiseSuppressor();
  const { changeMic } = useMeeting({});

  const handleStartNoiseSuppression = async () =&gt; {
    // Get raw mic stream
    const stream = await createMicrophoneAudioTrack({});
    // Process through AI suppressor
    const processedStream =
      await noiseProcessor.getNoiseSuppressedAudioStream(stream);
    // Swap the active mic track
    changeMic(processedStream);
  };

  const handleStopNoiseSuppression = async () =&gt; {
    // Restore unprocessed mic stream
    const stream = await createMicrophoneAudioTrack({});
    changeMic(stream);
  };

  return (
    &lt;&gt;
      &lt;button onClick={handleStartNoiseSuppression}&gt;
        Enable noise suppression
      &lt;/button&gt;
      &lt;button onClick={handleStopNoiseSuppression}&gt;
        Disable noise suppression
      &lt;/button&gt;
    &lt;/&gt;
  );
}</code></pre><p>To enable noise suppression from session start, pass the processed stream via the <code>customMicrophoneAudioTrack</code> config option in <code>MeetingProvider</code> before joining.</p><h4 id="network-quality-indicators">Network quality indicators</h4><p>The <code>useMeeting</code> hook exposes an <code>onQualityLimitation</code> event callback. This event fires when the SDK detects quality limitations in the session. Listen to this event and surface a clear warning in the session UI. A degraded network warning is especially important in a mental health context: a patient in distress should not be confused by a frozen screen without explanation.</p><pre><code class="language-javascript">const { join } = useMeeting({
  onQualityLimitation: ({ participantId, reason }) =&gt; {
    setNetworkWarning(`Connection quality reduced: ${reason}`);
  },
});</code></pre><h3 id="compliance-checklist-for-a-mental-health-video-consultation-app">Compliance checklist for a mental health video consultation app</h3><table>
<thead>
<tr>
<th style="text-align:left">Requirement</th>
<th style="text-align:left">VideoSDK feature</th>
<th style="text-align:left">Implementation step</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">End-to-end media encryption</td>
<td style="text-align:left"><code>ExternalE2EEKeyProvider</code> passed as <code>keyProvider</code> to <code>MeetingProvider</code></td>
<td style="text-align:left">Generate key server-side, distribute over HTTPS, call <code>setSharedKey()</code> before joining</td>
</tr>
<tr>
<td style="text-align:left">Verify E2EE is active</td>
<td style="text-align:left"><code>isE2EEEnabled</code> from <code>useMeeting()</code></td>
<td style="text-align:left">Assert <code>isE2EEEnabled === true</code> before allowing session to proceed</td>
</tr>
<tr>
<td style="text-align:left">Monitor per-stream encryption state</td>
<td style="text-align:left"><code>onE2EEStateChanged</code> in <code>useParticipant()</code></td>
<td style="text-align:left">Log or alert on <code>DecryptionFailed</code> or <code>MissingKey</code> states</td>
</tr>
<tr>
<td style="text-align:left">Waiting room before therapist joins</td>
<td style="text-align:left"><code>ask_join</code> in patient token; <code>onEntryRequested</code> event</td>
<td style="text-align:left">Issue separate token types server-side per role</td>
</tr>
<tr>
<td style="text-align:left">Recording consent capture</td>
<td style="text-align:left">Conditional <code>startRecording()</code> call</td>
<td style="text-align:left">Block <code>startRecording()</code> behind documented patient authorization</td>
</tr>
<tr>
<td style="text-align:left">Recording disabled when E2EE is on</td>
<td style="text-align:left">E2EE and recording are mutually exclusive per docs</td>
<td style="text-align:left">Do not call <code>startRecording()</code> when <code>keyProvider</code> is set</td>
</tr>
<tr>
<td style="text-align:left">SUD session: no recording</td>
<td style="text-align:left">Never call <code>startRecording()</code> for 42 CFR Part 2 patients</td>
<td style="text-align:left">Tag session type in backend; gate recording at API level</td>
</tr>
<tr>
<td style="text-align:left">Background noise isolation</td>
<td style="text-align:left"><code>VideoSDKNoiseSuppressor</code> from <code>videosdk-media-processor-web</code></td>
<td style="text-align:left">Call <code>getNoiseSuppressedAudioStream()</code> and pipe into <code>changeMic()</code></td>
</tr>
<tr>
<td style="text-align:left">In-session crisis escalation</td>
<td style="text-align:left"><code>usePubSub</code> with <code>CRISIS_ALERT</code> topic</td>
<td style="text-align:left">Therapist publishes event; backend triggers external response</td>
</tr>
<tr>
<td style="text-align:left">Screen sharing for patient materials</td>
<td style="text-align:left"><code>enableScreenShare()</code> / <code>disableScreenShare()</code></td>
<td style="text-align:left">Expose toggle in patient UI; inform patient content is visible to therapist</td>
</tr>
<tr>
<td style="text-align:left">Audit log of session events</td>
<td style="text-align:left"><code>onMeetingJoined</code>, <code>onMeetingLeft</code>, <code>onRecordingStarted</code> callbacks</td>
<td style="text-align:left">Log to database from server-side webhook and client callbacks</td>
</tr>
<tr>
<td style="text-align:left">Data deletion</td>
<td style="text-align:left">S3 lifecycle policies on <code>awsDirPath</code> bucket</td>
<td style="text-align:left">Configure bucket retention aligned with your HIPAA BAA</td>
</tr>
</tbody>
</table>
<h3 id="session-recording-considerations">Session recording considerations</h3><p>Recording a mental health session is a legal decision, not a default behavior. HIPAA requires a separate, specific authorization to record psychotherapy sessions. For SUD programs covered by 42 CFR Part 2, recordings carry strict re-disclosure restrictions even after creation. The safest default is recording off.</p><p>There is also a hard technical constraint: VideoSDK's E2EE and recording features are mutually exclusive. When <code>keyProvider</code> is active, <code>startRecording()</code> is not supported per the docs. This means your session architecture has two distinct modes: E2EE sessions (no recording, maximum privacy), and non-E2EE sessions (recording possible with consent, relying on DTLS-SRTP transport encryption and S3 server-side encryption at rest).</p><pre><code class="language-javascript">// Server sets this flag based on session type and consent status
const sessionMode = sessionConfig.recordingConsentSigned &amp;&amp;
                    sessionConfig.sessionType !== "SUD_TREATMENT"
                    ? "recordable"
                    : "e2ee";

// In session initialization:
// E2EE mode: pass keyProvider, never call startRecording()
// Recordable mode: no keyProvider, startRecording() after consent confirmed</code></pre><p>When recording completes, VideoSDK triggers the <code>webhookUrl</code> you provided. Use that webhook to log the recording event, associate the file reference with the patient record, and trigger any required patient notification.</p><h3 id="key-takeaways">Key takeaways</h3><ul><li>A mental health video consultation app must comply with both HIPAA (separate psychotherapy note protections) and, for SUD programs, 42 CFR Part 2, which is stricter than HIPAA on disclosure.</li><li>VideoSDK's <code>ExternalE2EEKeyProvider</code> enables true end-to-end encryption from React SDK v0.3.5+, with client-side key management and an <code>onE2EEStateChanged</code> event for per-stream monitoring.</li><li>E2EE and recording are mutually exclusive in VideoSDK: use E2EE for maximum-privacy sessions and non-E2EE for sessions where recording is clinically justified and explicitly consented to.</li><li>AI noise suppression via <code>VideoSDKNoiseSuppressor</code> from the <code>videosdk-media-processor-web</code> package processes microphone audio before it reaches the session, improving clarity without modifying the <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> pipeline manually.</li><li>The token permission system (<code>ask_join</code> / <code>allow_join</code>) implements a waiting room natively, and <code>usePubSub</code> provides a parallel crisis escalation channel that does not depend on the video connection remaining stable.</li></ul><h3 id="faq">FAQ</h3><p><strong>Q1. Should mental health sessions be recorded at all?</strong></p><p>Recording is not required and is often inadvisable without clear legal justification. HIPAA requires a separate, specific authorization to record psychotherapy sessions, beyond a general consent form. For SUD programs covered by 42 CFR Part 2, recordings create identifiable records with strict re-disclosure restrictions. The safest default is no recording. When clinical or supervisory needs justify it, obtain documented written consent, use VideoSDK's non-E2EE mode with server-side S3 encryption at rest, restrict access via role-based controls, and define a retention and deletion policy in your HIPAA BAA.</p><p><strong>Q2. How do you build a no-recording mode in VideoSDK?</strong></p><p>Simply do not call <code>startRecording()</code>. VideoSDK sessions do not record by default. If you also enable E2EE by passing <code>keyProvider</code> to <code>MeetingProvider</code>, the SDK additionally makes recording technically unavailable. This double safeguard works well for SUD sessions: set <code>keyProvider</code> server-side for those session types and never surface a recording UI. For sessions where recording is possible, gate <code>startRecording()</code> behind a server-side flag that confirms both consent status and session type before allowing the call.</p><p><strong>Q3. Can a patient share their screen with the therapist?</strong></p><p>Yes. VideoSDK's <code>useMeeting</code> hook exposes <code>enableScreenShare()</code> and <code>disableScreenShare()</code>. When a participant calls <code>enableScreenShare()</code>, all other participants receive an <code>onStreamEnabled()</code> callback from <code>useParticipant()</code>, and the <code>onPresenterChanged()</code> event fires with the <code>presenterId</code>. Useful for reviewing worksheets, mood tracking tools, or journal entries together. Inform the patient at session start that screen sharing is voluntary and that any shared content will be visible to the therapist.</p><p><strong>Q4. How do you handle a patient in crisis during a session?</strong></p><p>Build a parallel escalation path that does not depend on the video session continuing. In the therapist UI, a crisis escalation button calls <code>publish("CRISIS", { persist: false })</code> via <code>usePubSub</code> on a dedicated <code>CRISIS_ALERT</code> topic. Your backend subscribes to this topic and triggers a defined workflow: alerting on-call staff, pre-filling emergency contact forms, or logging the event with a timestamp. The video session continues in parallel so the therapist maintains contact. Display crisis line information (988 in the US, or a localized equivalent) persistently in the patient-facing UI rather than only at the pre-session consent screen.</p><h3 id="conclusion">Conclusion</h3><p>Building a compliant mental health video consultation app requires treating privacy as a design constraint from day one. The legal requirements around psychotherapy notes, SUD records under 42 CFR Part 2, and state mandated reporting obligations go beyond what generic HIPAA tooling covers. VideoSDK gives you the concrete building blocks: <code>ExternalE2EEKeyProvider</code> for end-to-end encrypted sessions, the <code>ask_join</code> token system for waiting rooms, <code>VideoSDKNoiseSuppressor</code> for clean audio, conditional <code>startRecording()</code> for consent-gated recordings, and <code>usePubSub</code> for crisis escalation. The architecture decision that matters most is the E2EE vs. recording tradeoff: design your session types around that constraint early, and your compliance posture becomes significantly easier to defend.</p>]]></content:encoded></item><item><title><![CDATA[How to Add Secure 1:1 Video Chat to a React Native Dating App]]></title><description><![CDATA[A step-by-step guide to building a dating app video call feature in React Native using VideoSDK. Covers SDK setup, private room creation, E2EE, anonymous mode, and call UI with real code.]]></description><link>https://www.videosdk.live/blog/secure-video-chat-react-native-dating-app</link><guid isPermaLink="false">69fc67c655831517a5a9fa5b</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 07 May 2026 10:44:53 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--04_06_28-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> You can add 1:1 video chat to a React Native dating app by installing <code>@videosdk.live/react-native-sdk</code>, creating a private room per match via the VideoSDK REST API, and rendering a two-participant call UI using the <code>useMeeting</code> and <code>useParticipant</code> hooks. Layer on end-to-end encryption using the <code>useKeyProvider</code> hook for user privacy.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--04_06_28-PM.png" alt="How to Add Secure 1:1 Video Chat to a React Native Dating App"/><p>Adding a dating app video call feature to your React Native app increases match-to-conversation conversion rates and lets users verify identity before meeting in person. The <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer"><strong>VideoSDK React Native SDK</strong></a> provides the <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">real-time video infrastructure</a> so you can focus on your app logic rather than <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> internals.</p><p>This guide covers every step: SDK installation, private room creation, building the call UI, end-to-end encryption, anonymous mode, and handling call invitations.</p><h2 id="react-native-sdk-setup">React Native SDK setup</h2><p>To add 1:1 video chat in a React Native dating app, start by installing the SDK and its companion in-call manager package.</p><p><strong>Installing the packages</strong></p><pre><code class="language-bash">npm install "@videosdk.live/react-native-sdk" "@videosdk.live/react-native-incallmanager"</code></pre><p>Or with Yarn:</p><pre><code class="language-bash">yarn add "@videosdk.live/react-native-sdk" "@videosdk.live/react-native-incallmanager"</code></pre><blockquote>Note: On Windows, always include double quotes around package names.</blockquote><h3 id="android-permissions-and-native-setup">Android permissions and native setup</h3><p>Add the following to <code>android/app/build.gradle</code>:</p><pre><code class="language-groovy">dependencies {
  implementation project(':rnwebrtc')
}</code></pre><p>Add to <code>android/settings.gradle</code>:</p><pre><code class="language-groovy">include ':rnwebrtc'
project(':rnwebrtc').projectDir = new File(rootProject.projectDir, '../node_modules/@videosdk.live/react-native-webrtc/android')</code></pre><p>Add to <code>android/gradle.properties</code>:</p><pre><code class="language-properties"># Fixes a WebRTC runtime problem on some devices
android.enableDexingArtifactTransform.desugaring=false</code></pre><p>Update <code>MainApplication.java</code>:</p><pre><code class="language-java">import live.videosdk.rnwebrtc.WebRTCModulePackage;

public class MainApplication extends Application implements ReactApplication {
  private static List&lt;ReactPackage&gt; getPackages() {
    List&lt;ReactPackage&gt; packages = new PackageList(this).getPackages();
    packages.add(new WebRTCModulePackage());
    return packages;
  }
}</code></pre><p>Add the required permissions to <code>AndroidManifest.xml</code>:</p><pre><code class="language-xml">&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
&lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
&lt;uses-permission android:name="android.permission.CAMERA" /&gt;
&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /&gt;
&lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;
&lt;uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /&gt;
&lt;uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /&gt;</code></pre><p>Set <code>minSdkVersion</code> to <code>23</code> in <code>build.gradle</code>.</p><h3 id="ios-setup">iOS setup</h3><p>For iOS, follow the <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/react-native-ios-sdk">React Native iOS integration guide</a> to add camera and microphone usage descriptions to <code>Info.plist</code> and link the native modules.</p><h3 id="register-services">Register services</h3><p>In your <code>index.js</code> (or <code>index.ts</code>), call <code>register()</code> before <code>AppRegistry.registerComponent</code>:</p><pre><code class="language-js">import { register } from '@videosdk.live/react-native-sdk';
import { AppRegistry } from 'react-native';
import { name as appName } from './app.json';
import App from './src/App.js';

register();
AppRegistry.registerComponent(appName, () =&gt; App);</code></pre><h2 id="creating-a-private-11-room">Creating a private 1:1 room</h2><p>A <strong>room</strong> in VideoSDK is a scoped session identified by a <code>roomId</code>. For a dating app, you create one room per match. You can use the match ID from your own database as a <code>customRoomId</code>, so each matched pair maps to exactly one room.</p><h3 id="room-creation-via-the-rest-api">Room creation via the REST API</h3><p>The endpoint for room creation is:</p><pre><code class="language-bash">POST https://api.videosdk.live/v2/rooms</code></pre><p>Headers required: <code>Authorization: YOUR_JWT_TOKEN</code> and <code>Content-Type: application/json</code>.</p><pre><code class="language-js">// Server-side: create a room when two users match
const response = await fetch('https://api.videosdk.live/v2/rooms', {
  method: 'POST',
  headers: {
    Authorization: process.env.VIDEOSDK_TOKEN,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    customRoomId: `match-${matchId}`, // link to your match record
  }),
});
const { roomId } = await response.json();
// Store roomId alongside the match record in your database</code></pre><p>The response returns a <code>roomId</code> (e.g. <code>"abc-xyzw-lmno"</code>) that both participants will use to join the call.</p><h3 id="token-generation-per-user">Token generation per user</h3><p>Each participant needs a short-lived JWT token generated from your VideoSDK <a href="https://www.videosdk.live/blog/api-key-vs-api-token" rel="noreferrer">API key and secret</a>. Generate this token server-side and send it to the client along with the <code>roomId</code>. The token must be passed raw, with no <code>Bearer</code> or <code>Basic</code> prefix, when used in the SDK.</p><p>For token generation details, see the <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/authentication-and-token">VideoSDK authentication guide</a>.</p><h2 id="building-the-call-ui">Building the call UI</h2><p>The call UI for a 1:1 dating app video call needs two video tiles, a mic toggle, a camera flip button, and an end-call button.</p><h3 id="initializing-the-meeting-provider">Initializing the meeting provider</h3><p><code><strong>MeetingProvider</strong></code> is the context provider that wraps your call screen. Pass the <code>meetingId</code>, <code>token</code>, participant <code>name</code>, and initial media state:</p><pre><code class="language-jsx">import { MeetingProvider } from '@videosdk.live/react-native-sdk';

function CallScreen({ roomId, token, displayName }) {
  return (
    &lt;MeetingProvider
      config={{
        meetingId: roomId,
        micEnabled: true,
        webcamEnabled: true,
        name: displayName,
      }}
      token={token}
    &gt;
      &lt;VideoCallView /&gt;
    &lt;/MeetingProvider&gt;
  );
}</code></pre><h3 id="rendering-participants-with-usemeeting-and-useparticipant">Rendering participants with <code>useMeeting</code> and <code>useParticipant</code></h3><p><strong><code>useMeeting</code></strong> is a hook that returns meeting-level controls and state. <strong><code>useParticipant</code></strong> returns per-participant media streams and metadata.</p><pre><code class="language-jsx">import { useMeeting, useParticipant, RTCView } from '@videosdk.live/react-native-sdk';
import { View, TouchableOpacity, Text, StyleSheet } from 'react-native';

function VideoCallView() {
  const {
    participants,
    localWebcamOn,
    toggleWebcam,
    localMicOn,
    toggleMic,
    changeWebcam,
    leave,
  } = useMeeting();

  const participantIds = [...participants.keys()];

  return (
    &lt;View style={styles.container}&gt;
      {participantIds.map((id) =&gt; (
        &lt;ParticipantTile key={id} participantId={id} /&gt;
      ))}
      &lt;View style={styles.controls}&gt;
        &lt;TouchableOpacity onPress={() =&gt; changeWebcam()}&gt;
          &lt;Text&gt;Flip Camera&lt;/Text&gt;
        &lt;/TouchableOpacity&gt;
        &lt;TouchableOpacity onPress={() =&gt; toggleMic()}&gt;
          &lt;Text&gt;{localMicOn ? 'Mute' : 'Unmute'}&lt;/Text&gt;
        &lt;/TouchableOpacity&gt;
        &lt;TouchableOpacity onPress={() =&gt; leave()}&gt;
          &lt;Text&gt;End Call&lt;/Text&gt;
        &lt;/TouchableOpacity&gt;
      &lt;/View&gt;
    &lt;/View&gt;
  );
}

function ParticipantTile({ participantId }) {
  const { displayName, webcamStream, webcamOn } = useParticipant(participantId);

  return (
    &lt;View style={styles.tile}&gt;
      &lt;Text style={styles.name}&gt;{displayName}&lt;/Text&gt;
      {webcamOn &amp;&amp; webcamStream ? (
        &lt;RTCView
          streamURL={webcamStream.toURL()}
          style={styles.video}
          objectFit="cover"
        /&gt;
      ) : (
        &lt;View style={styles.noVideo} /&gt;
      )}
    &lt;/View&gt;
  );
}

const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: '#1a1a1a' },
  tile: { flex: 1, position: 'relative' },
  video: { flex: 1 },
  noVideo: { flex: 1, backgroundColor: '#333' },
  name: { position: 'absolute', top: 8, left: 8, color: '#fff', zIndex: 1 },
  controls: {
    flexDirection: 'row',
    justifyContent: 'space-evenly',
    padding: 16,
    backgroundColor: '#000',
  },
});</code></pre><h3 id="flipping-the-camera">Flipping the camera</h3><p>The <code>changeWebcam()</code> method from <code>useMeeting</code> switches between front and rear cameras, as confirmed by the docs. Call it without arguments to toggle to the next available camera.</p><h3 id="muting-and-unmuting">Muting and unmuting</h3><p><code>toggleMic()</code> from <code>useMeeting</code> mutes or unmutes the local microphone. The current state is available via <code>localMicOn</code>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--04_04_26-PM.png" class="kg-image" alt="How to Add Secure 1:1 Video Chat to a React Native Dating App" loading="lazy" width="1448" height="1086"><figcaption><span style="white-space: pre-wrap;">React Native dating app video call screen mockup</span></figcaption></img></figure><h2 id="end-to-end-encryption-for-user-privacy">End-to-end encryption for user privacy</h2><p><strong>End-to-end encryption (E2EE)</strong>: <a href="https://www.videosdk.live/blog/what-is-end-to-end-encryption-e2ee" rel="noreferrer">E2EE</a> is a security model where media is encrypted on the sender's device and decrypted only on the receiver's device. No intermediate server, including VideoSDK's infrastructure, can access the content.</p><p>E2EE is documented and supported in the VideoSDK React Native SDK starting from version 0.2.1.</p><h3 id="why-e2ee-matters-in-dating-apps">Why E2EE matters in dating apps</h3><p>Users on dating platforms share personal video with strangers. Without E2EE, video frames pass through relay servers in decryptable form. With E2EE enabled, a leaked server-side recording would contain only ciphertext. This is a trust signal that differentiates your product.</p><h3 id="enabling-e2ee">Enabling E2EE</h3><p>Use the <code>useKeyProvider</code> hook to generate a key provider, set a shared key, and pass it to <code>MeetingProvider</code>:</p><pre><code class="language-jsx">import { MeetingProvider, useKeyProvider } from '@videosdk.live/react-native-sdk';

export default function SecureCallScreen({ roomId, token, sharedKey }) {
  const keyProvider = useKeyProvider({ discardFrameWhenCryptorNotReady: true });
  keyProvider?.setSharedKey(sharedKey);

  return (
    &lt;MeetingProvider
      config={{
        meetingId: roomId,
        micEnabled: true,
        webcamEnabled: true,
        name: 'User',
      }}
      token={token}
      keyProvider={keyProvider || null}
    &gt;
      &lt;VideoCallView /&gt;
    &lt;/MeetingProvider&gt;
  );
}</code></pre><p>Set <code>sharedKey</code> before passing <code>keyProvider</code> to the provider. The key itself must be distributed to both participants through your own secure channel: for example, an HTTPS API call that returns the key alongside the room token when a match is accepted.</p><p>You can verify E2EE is active with <code>e2eeEnabled</code> from <code>useMeeting</code>:</p><pre><code>const { e2eeEnabled } = useMeeting();
console.log('E2EE active:', e2eeEnabled);</code></pre><p>Note: E2EE applies only to media streams. Chat messages and signaling data are protected by TLS but are not end-to-end encrypted. Recording and transcription features are also not supported when E2EE is enabled.</p><h2 id="preventing-inappropriate-content">Preventing inappropriate content</h2><p>VideoSDK does not include a built-in content moderation layer. If your dating app needs to detect and block inappropriate video, you need to integrate a third-party moderation service alongside the VideoSDK stream.</p><p>A common pattern:</p><ol><li>Capture periodic screenshots from the local or remote video stream using a frame processing hook or a React Native screen-capture library.</li><li>Send those frames to a moderation API such as <a href="https://aws.amazon.com/rekognition/" rel="noreferrer">AWS Rekognition</a>, Google Cloud Vision SafeSearch, or Hive Moderation.</li><li>If the moderation API returns a violation, call <code>leave()</code> or <code>toggleWebcam()</code> from <code>useMeeting</code> and report the participant to your backend.</li></ol><p>This moderation layer runs entirely in your application code and does not require changes to the VideoSDK integration.</p><h2 id="handling-call-invitations">Handling call invitations</h2><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> does not provide a push notification or call invitation service. Call initiation is outside the scope of the SDK and belongs to your app's backend. However, the room creation step fits naturally into your match acceptance flow.</p><p>A practical pattern:</p><ol><li>When User A accepts a match with User B, your server calls <code>POST https://api.videosdk.live/v2/rooms</code> to create a room and stores the <code>roomId</code>.</li><li>Your server sends a push notification to User B (via FCM for Android or APNs for iOS) containing the <code>roomId</code> and a one-time participant token.</li><li>When User B taps the notification, your app navigates to the <code>CallScreen</code> component and joins the room using the received <code>roomId</code> and token.</li></ol><p>For native call UI on incoming calls (lock-screen notification with accept/decline), refer to the <a href="https://www.videosdk.live/blog/react-native-android-video-calling-app-with-callkeep">VideoSDK VoIP/CallKit guides</a> for Android (using Callkeep) and iOS (using CallKit).</p><h2 id="anonymous-mode">Anonymous mode</h2><p>Many dating apps let users interact anonymously until they choose to reveal their real name. VideoSDK supports this natively via the <code>name</code> field in <code>MeetingProvider</code>.</p><h3 id="using-a-display-name-instead-of-a-real-name">Using a display name instead of a real name</h3><p>Set the <code>name</code> config property to the user's chosen username or handle rather than their real name:</p><pre><code class="language-jsx">&lt;MeetingProvider
  config={{
    meetingId: roomId,
    micEnabled: true,
    webcamEnabled: true,
    name: user.username, // "CoffeeLover42" instead of real name
  }}
  token={token}
&gt;</code></pre><p>The <code>displayName</code> returned by <code>useParticipant</code> will then show the username to all participants.</p><h3 id="video-blur-and-virtual-backgrounds-for-anonymous-mode">Video blur and virtual backgrounds for anonymous mode</h3><p>VideoSDK provides a dedicated <code>@videosdk.live/react-native-media-effects</code> package that gives you background effects directly from JavaScript, with no custom native frame processor code required.</p><p>Install the package:</p><pre><code class="language-bash">npm install "@videosdk.live/react-native-media-effects"</code></pre><p>On iOS, add the following to your Podfile and comment out the Flipper line:</p><pre><code class="language-ruby">use_frameworks! :linkage =&gt; :static
# :flipper_configuration =&gt; flipper_config,  # comment this out</code></pre><p>Then apply effects using the <code>VideosdkMediaEffects</code> object:</p><pre><code class="language-js">import VideosdkMediaEffects from '@videosdk.live/react-native-media-effects';

// Blur the background with a given radius
VideosdkMediaEffects.applyBlurBackground(25.0);

// Replace background with an image (URL must use HTTPS)
VideosdkMediaEffects.applyImageBackground('https://example.com/bg.jpg');

// Set a solid color background
VideosdkMediaEffects.applyColorBackground('#1a1a1a');

// Remove any active background effect
VideosdkMediaEffects.removeBackground();</code></pre><p>These methods work on both Android and iOS. The feature can also be used on the pre-call screen, before joining the room.</p><p>For apps using the <strong>native iOS SDK</strong> directly rather than the React Native SDK, VideoSDK provides background blur via the <code>VideoSDKVideoProcessor</code> protocol. You implement <code>onFrameReceived(frame:)</code> using ARKit's <code>VNGeneratePersonSegmentationRequest</code> (iOS 15+) to segment the person, blur the background with <code>applyingGaussianBlur(sigma:)</code>, composite the result, and activate it with <code>meeting.setVideoProcessor(processor:)</code>. Pass <code>nil</code> to disable it.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li>Install <code>@videosdk.live/react-native-sdk</code> and <code>@videosdk.live/react-native-incallmanager</code>, then call <code>register()</code> in your app entry point before mounting any component.</li><li>Create one room per match via <code>POST https://api.videosdk.live/v2/rooms</code> and store the <code>roomId</code> with your match record. Use <code>customRoomId</code> to mirror your own match ID.</li><li>Use <code>useMeeting</code> for call controls (mute, camera flip via <code>changeWebcam()</code>, leave) and <code>useParticipant</code> with <code>RTCView</code> for rendering each participant's video stream.</li><li>Enable E2EE with <code>useKeyProvider</code> and <code>setSharedKey</code>. Distribute the shared key to both participants from your server over HTTPS, not from the client.</li><li>Add background blur or virtual backgrounds using the <code>@videosdk.live/react-native-media-effects</code> package: call <code>applyBlurBackground(radius)</code>, <code>applyImageBackground(url)</code>, or <code>applyColorBackground(hex)</code> directly from JavaScript on both platforms.</li><li>VideoSDK does not provide content moderation or push notifications. Both require third-party integration on top of the SDK.</li></ul><h2 id="faq">FAQ</h2><p><strong>Q1: Can a user block a participant mid-call?</strong></p><p>VideoSDK does not have a built-in per-participant block feature within a session. To implement blocking mid-call, call <code>leave()</code> on the blocking user's side to remove them from the room, then update your app's backend to flag the block. On the other participant's side, the <code>onParticipantLeft</code> event from <code>useMeeting</code> will fire. You can also use the REST API endpoint <code>POST https://api.videosdk.live/v2/sessions/{sessionId}/participant/remove</code> to force-remove a participant server-side.</p><p><strong>Q2: What happens when one user loses connection?</strong></p><p>The SDK handles transient disconnections automatically using WebRTC's reconnection mechanisms. If a participant drops, the <code>onParticipantLeft</code> callback fires on the other participant's <code>useMeeting</code> hook. If the disconnected participant's device recovers network connectivity, they can rejoin the same <code>roomId</code> with a valid token. You should show a reconnecting state in your UI by listening to the <code>onError</code> event from <code>useMeeting</code> and tracking participant presence with <code>onParticipantLeft</code> and <code>onParticipantJoined</code>.</p><p><strong>Q3: Does VideoSDK support video filters?</strong></p><p>For background effects, VideoSDK provides the <code>@videosdk.live/react-native-media-effects</code> package with built-in methods: <code>applyBlurBackground(radius)</code>, <code>applyImageBackground(url)</code>, <code>applyColorBackground(hex)</code>, and <code>removeBackground()</code>. These work from JavaScript with no custom native code on both Android and iOS. For more advanced per-frame visual effects (color grading, face overlays, etc.) beyond background manipulation, you use the Video Processor system to write a custom native processor, as no JavaScript filter API exists for those use cases in the current SDK version.</p><h2 id="conclusion">Conclusion</h2><p>Adding a 1:1 video chat to a React Native dating app requires a working SDK installation, private room creation tied to your match logic, a call UI built on <code>useMeeting</code> and <code>useParticipant</code>, and E2EE enabled via <code>useKeyProvider</code>. The VideoSDK React Native SDK handles the real-time media transport. Your app is responsible for token generation, push notifications, content moderation, and key distribution.</p><p>The primary keyword throughout this guide has been <strong>1:1 video chat React Native dating app</strong>: the foundation is the <code>@videosdk.live/react-native-sdk</code> package combined with a server-side room creation call and client-side E2EE configuration.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Low-Latency Live Audio Room App in Flutter]]></title><description><![CDATA[A step-by-step guide to building a Flutter live audio room app using VideoSDK. Covers SDK install, permissions, speaker stage management, raise hand via PubSub, active speaker detection, and cloud recording.]]></description><link>https://www.videosdk.live/blog/flutter-live-audio-room</link><guid isPermaLink="false">69fc5e0f55831517a5a9fa01</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 07 May 2026 10:06:39 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--03_35_51-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> You can build a fully functional Flutter live audio room using the <code>videosdk</code> package. Participants join with <code>camEnabled: false</code>, speakers get microphone control via <code>participant.unmuteMic()</code>, raise-hand signals travel over <code>room.pubSub</code>, and the whole session can be recorded with a single <code>room.startRecording()</code> call.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--03_35_51-PM.png" alt="How to Build a Low-Latency Live Audio Room App in Flutter"/><p>A <a href="https://www.videosdk.live/live-audio-rooms" rel="noreferrer"><strong>live audio room</strong></a> is a real-time social audio experience where a small group of speakers talk on a shared stage while a larger audience listens. Key UX elements include a speaker stage with visible mic indicators, an audience grid with avatar tiles, and a raise-hand mechanism that lets listeners request speaking access. This guide shows how to build that pattern for Flutter using the <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer"><strong>VideoSDK Flutter SDK</strong></a> (<code>videosdk</code> on pub.dev), covering everything from SDK installation to cloud recording.</p><h3 id="flutter-sdk-setup">Flutter SDK setup</h3><p>The <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">VideoSDK Flutter SDK</a> is a natively written Dart package. It supports iOS, Android, Web (beta), and Desktop (beta). Install it with:</p><pre><code class="language-bash">flutter pub add videosdk</code></pre><p>This adds the following to your <code>pubspec.yaml</code>:</p><pre><code class="language-yaml">dependencies:
  videosdk: ^2.0.0</code></pre><p>Then import it in your Dart code:</p><pre><code class="language-dart">import 'package:videosdk/videosdk.dart';</code></pre><h4 id="android-permissions">Android permissions</h4><p>Add the following entries to <code>&lt;project root&gt;/android/app/src/main/AndroidManifest.xml</code>. For an audio-only room you only need the microphone and network entries, but the camera permission is included so that video can be enabled later without a new release:</p><pre><code class="language-xml">&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
&lt;uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /&gt;
&lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /&gt;
&lt;uses-permission android:name="android.permission.INTERNET"/&gt;
&lt;uses-permission android:name="android.permission.FOREGROUND_SERVICE"/&gt;
&lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;</code></pre><p>Also set Java 8 compatibility in your app-level <code>build.gradle</code> because the WebRTC JAR uses static methods in <code>EglBase</code>:</p><pre><code class="language-js">android {
  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}</code></pre><p>Raise <code>minSdkVersion</code> to at least <code>23</code> in the same file.</p><h4 id="ios-permissions">iOS permissions</h4><p>Add these keys to <code>&lt;project root&gt;/ios/Runner/Info.plist</code>:</p><pre><code class="language-xml">&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Microphone Usage!&lt;/string&gt;</code></pre><p>In your <code>Podfile</code>, set the minimum platform to <code>13.0</code>, switch to static linking, and enable the microphone permission flag:</p><pre><code class="language-js">platform: ios, "13.0";
use_frameworks! :linkage =&gt; :static

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        'PERMISSION_MICROPHONE=1',
      ]
    end
  end
end</code></pre><h3 id="audio-only-room-architecture">Audio-only room architecture</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--03_23_50-PM.png" class="kg-image" alt="How to Build a Low-Latency Live Audio Room App in Flutter" loading="lazy" width="1448" height="1086"><figcaption><span style="white-space: pre-wrap;">Flutter live audio room interface design</span></figcaption></img></figure><p>A <strong>live audio room</strong> separates participants into two roles: speakers and listeners.</p><p><strong>Speakers</strong> are full participants with microphone access enabled. They appear on the visible stage and can be heard by everyone. The VideoSDK <code>Room</code> object treats them as regular participants with <code>micEnabled: true</code>.</p><p><strong>Listeners</strong> join the room with their microphone disabled (<code>micEnabled: false</code>). They do not produce audio but can hear all speakers. The SDK does not have a separate <code>MeetingMode</code> for audio-only rooms; you control the distinction entirely through <code>micEnabled</code> and <code>camEnabled</code> flags at join time and through <code>participant.unmuteMic()</code> / <code>participant.muteMic()</code> when promoting or demoting participants at runtime.</p><p>This design means all participants share the same <code>Room</code>, which simplifies token management and recording. Speaker promotion is a runtime media permission change, not a room reconnection.</p><h3 id="creating-and-joining-the-audio-room">Creating and joining the audio room</h3><p><strong>Token generation</strong> is a required first step. You exchange your <a href="https://www.videosdk.live/blog/api-key-vs-api-token" rel="noreferrer">VideoSDK API key and secret</a> for a short-lived <a href="https://en.wikipedia.org/wiki/JSON_Web_Token" rel="noreferrer nofollow">JWT</a> on your own server. The client then calls the VideoSDK <code>create-room</code> REST endpoint to get a <code>roomId</code>, or validates an existing one.</p><pre><code class="language-dart">import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:videosdk/videosdk.dart';

String? roomId;
String? token;

void _getRoomIdAndToken() async {
  final LOCAL_SERVER_URL = '&lt;your-server-url&gt;';

  // Step 1: fetch token from your server
  final tokenResponse = await http.get(Uri.parse('$LOCAL_SERVER_URL/get-token'));
  final _token = json.decode(tokenResponse.body)['token'];

  // Step 2: create a room via your server (which calls VideoSDK REST API)
  final roomIdResponse = await http.post(
    Uri.parse('$LOCAL_SERVER_URL/create-room/'),
    body: {"token": _token},
  );
  final _roomId = json.decode(roomIdResponse.body)['roomId'];

  setState(() {
    token = _token;
    roomId = _roomId;
  });
}</code></pre><p>Once you have a token and roomId, initialize the <code>Room</code> object with camera disabled. Set <code>micEnabled: true</code> for speakers and <code>micEnabled: false</code> for listeners:</p><pre><code class="language-dart">final room = VideoSDK.createRoom(
  roomId: roomId!,
  displayName: "Alice",
  micEnabled: true,   // false for audience members
  camEnabled: false,  // audio-only: camera always off
  token: token!,
  notification: const NotificationInfo(
    title: "Audio Room",
    message: "Live audio session in progress",
    icon: "notification_icon",
  ),
);</code></pre><p>Then join and listen for the <code>roomJoined</code> event:</p><pre><code class="language-dart">room.on(Events.roomJoined, () {
  print("Room joined successfully");
});

room.on(Events.participantJoined, (participant) {
  print("${participant.displayName} joined");
});

room.join();</code></pre><h3 id="speaker-stage-management">Speaker stage management</h3><p>Promoting a listener to speaker means enabling their microphone. The host calls <code>participant.unmuteMic()</code> on the target <code>Participant</code> object. This sends a <code>micRequested</code> event to that participant, who can accept or reject:</p><pre><code class="language-dart">// Host side: request a listener to unmute their mic
participant.unmuteMic();</code></pre><p>The listener receives the request via an event:</p><pre><code class="language-dart">room.on(Events.micRequested, (_data) {
  dynamic accept = _data['accept'];
  dynamic reject = _data['reject'];

  showDialog(
    context: navigatorKey.currentContext!,
    builder: (context) =&gt; AlertDialog(
      title: const Text("Mic requested?"),
      content: const Text("The host wants you to speak."),
      actions: [
        TextButton(
          onPressed: () { reject(); Navigator.of(context).pop(); },
          child: const Text("Decline"),
        ),
        TextButton(
          onPressed: () { accept(); Navigator.of(context).pop(); },
          child: const Text("Accept"),
        ),
      ],
    ),
  );
});</code></pre><p>To mute a speaker and move them back to the audience, the host calls <code>participant.muteMic()</code> directly. This does not require the participant's consent:</p><pre><code class="language-dart">// Host side: mute a speaker immediately
participant.muteMic();</code></pre><p>Note: the participant making these calls must have the <code>allow_mod</code> permission set in their token. See the VideoSDK authentication documentation for token scopes.</p><h3 id="raise-hand-feature">Raise hand feature</h3><p><strong>PubSub</strong> (publish-subscribe) is VideoSDK's in-room messaging mechanism. Each message is published to a named topic and received by all subscribers. It is ideal for the raise-hand signal because no audio track change is involved.</p><p>A listener taps "Raise Hand," which publishes to a custom topic:</p><pre><code class="language-dart">// Listener side: publish a raise-hand event
room.pubSub.publish(
  "RAISE_HAND",
  room.localParticipant.id, // send the listener's participantId as the message
  PubSubPublishOptions(persist: false),
);</code></pre><p>The host subscribes to the same topic on room join and updates the UI to show a hand icon next to the requesting participant:</p><pre><code class="language-dart">// Host side: subscribe to raise-hand events
room.pubSub
    .subscribe("RAISE_HAND", (PubSubMessage message) {
      setState(() {
        raisedHands.add(message.message); // message.message holds the participantId
      });
    });</code></pre><p>The <code>PubSubMessage</code> object includes <code>senderId</code>, <code>senderName</code>, <code>message</code>, <code>timestamp</code>, and <code>topic</code>. Unsubscribe when the widget is disposed to avoid memory leaks:</p><pre><code class="language-dart">@override
void dispose() {
  room.pubSub.unsubscribe("RAISE_HAND", _raiseHandHandler);
  super.dispose();
}</code></pre><h3 id="active-speaker-detection">Active speaker detection</h3><p><a href="https://www.videosdk.live/blog/implement-active-speaker-indication-in-flutter-video-call-app" rel="noreferrer">Active speaker detection</a> is vital for audio rooms. The VideoSDK Flutter SDK fires a <code>speakerChanged</code> event on the <code>Room</code> object whenever the dominant speaker changes. The event payload contains the <code>participantId</code> of the currently speaking participant, or <code>null</code> when no one is speaking.</p><pre><code class="language-dart">room.on(Events.speakerChanged, (activeSpeakerId) {
  setState(() {
    _activeSpeakerId = activeSpeakerId; // null when silence
  });
});</code></pre><p>Use <code>_activeSpeakerId</code> in your speaker tile widget to add a visual highlight, such as a glowing ring or animated waveform icon, around the active speaker's avatar. For example:</p><pre><code class="language-dart">Container(
  decoration: BoxDecoration(
    shape: BoxShape.circle,
    border: Border.all(
      color: participant.id == _activeSpeakerId
          ? Colors.purpleAccent
          : Colors.transparent,
      width: 3,
    ),
  ),
  child: CircleAvatar(child: Text(participant.displayName[0])),
)</code></pre><p>This keeps the UI in sync with who is currently talking without polling or audio level callbacks.</p><h3 id="recording-the-audio-session">Recording the audio session</h3><p>VideoSDK offers three recording types for the Flutter SDK: Meeting Recording (composite), Participant Recording (individual), and Participant Track Recording. For an audio room, composite recording is the practical choice because it captures all speakers in a single file.</p><p>Call <code>room.startRecording()</code> with a storage webhook URL on your server, or leave it to the VideoSDK default <a href="https://www.videosdk.live/blog/cloud-recording-and-rtmp-pricing" rel="noreferrer">cloud storage</a>:</p><pre><code class="language-dart">// Start composite meeting recording
room.startRecording(
  serverUrl: "&lt;your-webhook-or-storage-url&gt;",
  config: {
    "layout": {
      "type": "GRID",
      "priority": "SPEAKER",
    },
    "theme": "DARK",
  },
);</code></pre><p>Stop recording when the session ends:</p><pre><code class="language-dart">room.stopRecording();</code></pre><p>Listen for recording state changes:</p><pre><code class="language-dart">room.on(Events.recordingStarted, () {
  print("Recording started");
});

room.on(Events.recordingStopped, () {
  print("Recording stopped");
});</code></pre><p>Completed recordings are available from the VideoSDK Session Dashboard and through the Sessions REST API. The recorded file reflects all audio tracks that were active during the session.</p><h3 id="key-takeaways">Key takeaways</h3><ul><li>The VideoSDK Flutter package is <code>videosdk</code> (installed via <code>flutter pub add videosdk</code>), and works on iOS, Android, Web (beta), and Desktop (beta).</li><li>Audio-only rooms use <code>camEnabled: false</code> at room creation time; there is no separate participant mode for listeners. The speaker/listener distinction is managed entirely through <code>micEnabled</code> and runtime <code>muteMic()</code> / <code>unmuteMic()</code> calls.</li><li>The <code>RAISE_HAND</code> PubSub pattern requires no SDK-specific feature; it uses the general <code>room.pubSub.publish()</code> / <code>subscribe()</code> API already in the SDK.</li><li>Active speaker UI is driven by <code>Events.speakerChanged</code>, which fires on the <code>Room</code> object with the <code>participantId</code> of the loudest speaker.</li><li>Composite cloud recording starts with <code>room.startRecording()</code> and captured audio is stored server-side without any client-side file I/O.</li></ul><h3 id="faq">FAQ</h3><p><strong>Q1. Can video be added later in the same room without participants reconnecting?</strong></p><p>Yes. Because all participants share the same <code>Room</code> object, a speaker can call <code>room.enableCam()</code> at any time to turn on their camera. Listeners who were initialized with <code>camEnabled: false</code> can similarly enable their camera after being promoted to speaker. No reconnection or new token is required; the <code>Room</code> stays active and other participants receive <code>Events.streamEnabled</code> with the new video track.</p><p><strong>Q2. What is the latency of VideoSDK audio rooms?</strong></p><p>VideoSDK uses <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> as its transport layer. WebRTC audio typically delivers end-to-end <a href="https://www.videosdk.live/blog/what-is-latency-in-webrtc" rel="noreferrer">latency</a> in the range of 100 to 300 milliseconds over good network conditions, consistent with industry benchmarks for WebRTC-based conferencing. Actual latency depends on network path, device hardware, and regional server proximity. VideoSDK does not publish a specific latency SLA; test under your target network conditions for precise numbers.</p><p><strong>Q3. How many speakers can be on stage at the same time?</strong></p><p>VideoSDK supports large meetings. The practical limit for simultaneous active speakers in a conference room depends on your plan and the network conditions of participants. For audio-only rooms where video is disabled, the bandwidth per participant is significantly lower than a video call, which allows more concurrent speakers before quality degrades. Refer to the VideoSDK pricing and scalability documentation for participant limits on your specific plan.</p><p><strong>Q4. Can listeners join from a web browser instead of the Flutter app?</strong></p><p>Yes. VideoSDK provides separate SDKs for React, plain <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">JavaScript</a>, and other platforms. A listener joining from a web browser uses the JavaScript or React SDK with the same <code>roomId</code> and a token generated from the same API key. All participants, regardless of SDK, share the same room and can hear each other. Cross-platform interoperability is built into the VideoSDK architecture because all clients connect to the same WebRTC-based infrastructure.</p><h3 id="conclusion">Conclusion</h3><p>Building a <strong>Flutter live audio room</strong> with VideoSDK requires four core steps: install the <code>videosdk</code> package, initialize a <code>Room</code> with <code>camEnabled: false</code>, manage speaker access using <code>unmuteMic()</code> and <code>muteMic()</code> on <code>Participant</code> objects, and relay raise-hand signals through <code>room.pubSub</code>. The <code>Events.speakerChanged</code> event handles active speaker highlighting without any polling, and <code>room.startRecording()</code> captures the full session to cloud storage. The result is a production-ready audio room app built entirely on verified SDK methods documented at docs.videosdk.live/flutter.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a HIPAA-Compliant Telemedicine App with React]]></title><description><![CDATA[A step-by-step guide to building a compliant telemedicine app with React and VideoSDK, covering HIPAA, HITECH, state laws, GDPR, encryption, recording, and access control patterns with real SDK code.]]></description><link>https://www.videosdk.live/blog/build-compliant-telemedicine-app-react</link><guid isPermaLink="false">69fc468d55831517a5a9f972</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 07 May 2026 09:33:29 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/06/hipaa_telemedicine_react_title.png" medium="image"/><content:encoded><![CDATA[<blockquote><em>To build a compliant telemedicine app with React, you need to satisfy HIPAA at minimum, then layer HITECH breach notification requirements, relevant state laws, and GDPR for international patients. VideoSDK's React SDK provides token-based authentication, cloud recording with a custom storage path, and participant event hooks that map directly to these regulatory requirements. End-to-end encryption (E2EE) is not currently documented as a built-in feature of the React SDK and is addressed separately in this guide.</em></blockquote><h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/hipaa_telemedicine_react_title.png" alt="How to Build a HIPAA-Compliant Telemedicine App with React"/><p>Building a compliant <a href="https://www.videosdk.live/solutions/telehealth" rel="noreferrer">telemedicine</a> app in React means treating HIPAA as a baseline, not a finish line. Regulatory obligations in healthcare video extend well beyond the Security Rule: HITECH increases breach penalties, state laws like the New York SHIELD Act add data protection requirements for residents, and GDPR applies the moment a patient located in the European Economic Area joins a session.</p><h2 id="the-compliance-stack-for-telemedicine">The compliance stack for telemedicine</h2><h3 id="hipaa-the-mandatory-baseline">HIPAA: the mandatory baseline</h3><p><a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api" rel="noreferrer"><strong>HIPAA</strong></a> (Health Insurance Portability and Accountability Act) is the US federal law that governs the protection of <a href="https://en.wikipedia.org/wiki/Protected_health_information" rel="noreferrer nofollow">protected health information (<strong>PHI</strong>)</a>. For a telemedicine app, the three rules that matter most are the Privacy Rule, the Security Rule, and the requirement for a <strong>Business Associate Agreement (BAA)</strong>.</p><p>A <a href="https://docs.videosdk.live/help_docs/security-and-privacy/hipaa#4-business-associate-agreement-baa" rel="noreferrer">BAA</a> is a contract between a covered entity (your healthcare organization) and a business associate (your video infrastructure vendor) that formally assigns responsibility for PHI protection. You cannot legally use a <a href="https://www.videosdk.live/blog/webrtc-vs-zoom-sdk-vs-videosdk-for-telehealth" rel="noreferrer">video platform for telehealth</a> in the United States without a signed BAA from that vendor.</p><p>The Security Rule requires: encryption in transit and at rest, role-based access controls, audit controls that record activity on PHI systems, and integrity controls to prevent unauthorized alteration of PHI.</p><h3 id="hitech-enhanced-penalties-and-breach-notification">HITECH: enhanced penalties and breach notification</h3><p><a href="https://en.wikipedia.org/wiki/Health_Information_Technology_for_Economic_and_Clinical_Health_Act" rel="noreferrer nofollow"><strong>HITECH</strong>&nbsp;(Health Information Technology for Economic and Clinical Health Act)</a> strengthens HIPAA in two key ways. First, it extends direct HIPAA liability to business associates, meaning your video vendor is also directly liable for breaches. Second, it mandates breach notification: if unsecured PHI is exposed, covered entities must notify affected individuals within 60 days, notify HHS, and for breaches affecting over 500 individuals, notify prominent media outlets in the affected state.</p><p>From an engineering standpoint, HITECH means your audit trail must be good enough to determine the exact scope of a breach. Session logs, join and leave timestamps, and recording access logs all become evidence in a notification determination.</p><h3 id="state-laws-the-new-york-shield-act-as-an-example">State laws: the New York SHIELD Act as an example</h3><p>The <a href="https://ag.ny.gov/resources/organizations/data-breach-reporting/shield-act" rel="noreferrer"><strong>New York SHIELD Act</strong></a> (Stop Hacks and Improve Electronic Data Security Act, effective March 2020) applies to any organization that holds private information of New York residents, regardless of where the organization is based. It requires reasonable security measures, which the Act defines as administrative, technical, and physical safeguards.</p><p>For telehealth developers, this means your React app must implement reasonable access controls for New York patient sessions even if your servers are in another state. Other states have analogous laws: California's CCPA, Texas's HB 4390, and Virginia's CDPA all impose data security obligations that overlap with telehealth use cases.</p><h3 id="gdpr-for-international-patients">GDPR for international patients</h3><p><a href="https://gdpr-info.eu/" rel="noreferrer nofollow"><strong>GDPR</strong></a> (General Data Protection Regulation) applies when any EU/EEA resident participates in a session, regardless of where your servers are. It adds requirements that go beyond HIPAA: a legal basis for processing (typically explicit consent or vital interests), the right to erasure (the patient's right to have their data deleted), data minimization, and data residency considerations.</p><p>The right to erasure has a direct engineering implication: your recording pipeline must support deletion by patient ID, not just by session ID.</p><h2 id="videosdk-features-that-address-compliance">VideoSDK features that address compliance</h2><p>VideoSDK provides several features verified from its documentation that map to the compliance requirements above.</p><p><strong>Token-based authentication</strong> is the primary access control mechanism. Every participant must present a valid token to join a meeting. Tokens are generated server-side and passed to <code>MeetingProvider</code>. This maps to the HIPAA Security Rule requirement for unique user identification and access control.</p><p><a href="https://www.videosdk.live/blog/cloud-recording-and-rtmp-pricing" rel="noreferrer"><strong>Cloud recording</strong></a> is available via the <code>startRecording()</code> and <code>stopRecording()</code> functions exposed by the <code>useMeeting</code> hook. The <code>startRecording()</code> call accepts a <code>webhookUrl</code> and an <code>awsDirPath</code>, which means you can route recordings to your own HIPAA-eligible S3 bucket. This satisfies the audit trail requirement and gives you custody of the recording for retention and deletion workflows.</p><p><strong>Participant event callbacks</strong> (<code>onParticipantJoined</code>, <code>onMeetingJoined</code>, <code>onMeetingLeft</code>) are available in the <code>useMeeting</code> hook. You can log these events server-side to build a complete access audit trail per session.</p><p><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/security/E2EE" rel="noreferrer"><strong>E2EE (end-to-end encryption)</strong></a> is a documented, production-ready feature of the React SDK as of version 0.3.5. It is implemented via the <code>ExternalE2EEKeyProvider</code> class, exported from <code>@videosdk.live/react-sdk</code>. You pass a configured key provider instance to <code>MeetingProvider</code> via the <code>keyProvider</code> prop. Encryption is applied at the room level with a shared key. VideoSDK never stores or accesses encryption keys. One critical architectural constraint: recording and transcription are not available when E2EE is enabled, because the server cannot access the media to record it. This is an important design decision for telehealth: sessions with E2EE cannot produce a server-side recording.</p><p><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/geo-fencing-and-proxy-controls/geo-fencing" rel="noreferrer"><strong>Geo-fencing/data residency</strong></a> is a documented feature available on the VideoSDK Enterprise plan. It restricts media server connections to a specified region regardless of where participants physically connect from. Available regions are India, USA, UAE, Europe, Singapore, and Australia. For GDPR data residency requirements with EU patients, you would configure the Europe region. Contact VideoSDK Sales to enable this feature.</p><h2 id="react-project-setup">React project setup</h2><h3 id="install-the-sdk">Install the SDK</h3><p>Install the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">VideoSDK React SDK</a> and the participant video renderer:</p><pre><code class="language-bash">npm install "@videosdk.live/react-sdk"
npm install "react-player"</code></pre><p>Or with Yarn:</p><pre><code class="language-bash">yarn add "@videosdk.live/react-sdk"
yarn add "react-player"</code></pre><p>The verified package name is <code>@videosdk.live/react-sdk</code>. Do not use any other package name.</p><h3 id="project-structure">Project structure</h3><pre><code class="language-bash">root
├── node_modules
├── public
├── src
│   ├── API.js        # token and meeting ID helpers
│   ├── App.js        # MeetingProvider setup
│   └── index.js</code></pre><h3 id="auth-token-flow">Auth token flow</h3><p>Tokens must be generated server-side. Never embed your VideoSDK API secret in client-side code. The verified pattern from the docs is a server endpoint that returns a short-lived token:</p><pre><code class="language-js">// src/API.js

const LOCAL_SERVER_URL = process.env.REACT_APP_SERVER_URL;

export const getToken = async () =&gt; {
  try {
    const response = await fetch(`${LOCAL_SERVER_URL}/get-token`, {
      method: "GET",
      headers: {
        Accept: "application/json",
        "Content-Type": "application/json",
      },
    });
    const { token } = await response.json();
    return token;
  } catch (e) {
    console.error(e);
  }
};

export const createMeeting = async (token) =&gt; {
  try {
    const response = await fetch(`${LOCAL_SERVER_URL}/create-meeting`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ token }),
    });
    const { meetingId } = await response.json();
    return meetingId;
  } catch (e) {
    console.error(e);
  }
};</code></pre><p>For compliance, log token issuance events on your server: who requested a token, at what time, and for which meeting ID. This creates the audit trail required by the HIPAA Security Rule.</p><h2 id="building-the-patient-facing-interface">Building the patient-facing interface</h2><h3 id="consent-screen-before-joining">Consent screen before joining</h3><p>HIPAA requires informed consent for telehealth, and GDPR requires explicit consent as a legal basis for processing. Render a blocking consent screen before calling <code>join()</code>:</p><pre><code class="language-jsx">// src/ConsentScreen.jsx
import { useState } from "react";

const ConsentScreen = ({ onConsent }) =&gt; {
  const [agreed, setAgreed] = useState(false);

  return (
    &lt;div style={{ maxWidth: 600, margin: "40px auto", padding: 24 }}&gt;
      &lt;h2&gt;Telehealth session consent&lt;/h2&gt;
      &lt;p&gt;
        This session may be recorded for quality and compliance purposes.
        Your video and audio will be transmitted to your provider.
        You have the right to end this session at any time.
      &lt;/p&gt;
      &lt;label&gt;
        &lt;input
          type="checkbox"
          checked={agreed}
          onChange={(e) =&gt; setAgreed(e.target.checked)}
        /&gt;
        {" "}I have read and agree to the telehealth consent and privacy notice.
      &lt;/label&gt;
      &lt;br /&gt;&lt;br /&gt;
      &lt;button disabled={!agreed} onClick={onConsent}&gt;
        Join session
      &lt;/button&gt;
    &lt;/div&gt;
  );
};

export default ConsentScreen;</code></pre><p>Store a timestamped record of consent server-side, keyed to the patient's identifier and the session ID. This record is your evidence of consent for HIPAA Privacy Rule and GDPR Article 7 purposes.</p><h3 id="joining-the-meeting-with-usemeeting">Joining the meeting with <code>useMeeting</code></h3><p>The <code>useMeeting</code> hook is the primary interface for session control. <code>MeetingProvider</code> must wrap all components that use this hook:</p><pre><code class="language-jsx">// src/App.js
import { useState } from "react";
import { MeetingProvider } from "@videosdk.live/react-sdk";
import ConsentScreen from "./ConsentScreen";
import MeetingView from "./MeetingView";

const App = () =&gt; {
  const [token, setToken] = useState(null);
  const [meetingId, setMeetingId] = useState(null);
  const [consented, setConsented] = useState(false);

  const handleConsent = async () =&gt; {
    const t = await getToken();
    const mid = await createMeeting(t);
    setToken(t);
    setMeetingId(mid);
    setConsented(true);
  };

  if (!consented) {
    return &lt;ConsentScreen onConsent={handleConsent} /&gt;;
  }

  return (
    &lt;MeetingProvider
      config={{
        meetingId: meetingId,
        name: "Patient",
        micEnabled: true,
        webcamEnabled: true,
        maxResolution: "hd",
      }}
      token={token}
    &gt;
      &lt;MeetingView /&gt;
    &lt;/MeetingProvider&gt;
  );
};

export default App;</code></pre><p>Video grid and mute controls</p><pre><code class="language-jsx">// src/MeetingView.jsx
import { useMeeting, useParticipant } from "@videosdk.live/react-sdk";
import ReactPlayer from "react-player";
import { useMemo } from "react";

const ParticipantView = ({ participantId }) =&gt; {
  const { webcamStream, micStream, webcamOn, micOn, isLocal, displayName } =
    useParticipant(participantId);

  const videoStream = useMemo(() =&gt; {
    if (webcamOn &amp;&amp; webcamStream) {
      const mediaStream = new MediaStream();
      mediaStream.addTrack(webcamStream.track);
      return mediaStream;
    }
  }, [webcamStream, webcamOn]);

  return (
    &lt;div&gt;
      &lt;p&gt;{displayName} {isLocal ? "(You)" : ""}&lt;/p&gt;
      {webcamOn ? (
        &lt;ReactPlayer
          playsinline
          pip={false}
          light={false}
          controls={false}
          muted={isLocal}
          playing={true}
          url={videoStream}
          width="320px"
          height="240px"
        /&gt;
      ) : (
        &lt;div style={{ width: 320, height: 240, background: "#111", display: "flex", alignItems: "center", justifyContent: "center", color: "#fff" }}&gt;
          Camera off
        &lt;/div&gt;
      )}
    &lt;/div&gt;
  );
};

const MeetingView = () =&gt; {
  const { join, leave, toggleMic, toggleWebcam, participants } = useMeeting();

  return (
    &lt;div&gt;
      &lt;div style={{ display: "flex", gap: 8 }}&gt;
        &lt;button onClick={join}&gt;Join&lt;/button&gt;
        &lt;button onClick={() =&gt; toggleMic()}&gt;Toggle mic&lt;/button&gt;
        &lt;button onClick={() =&gt; toggleWebcam()}&gt;Toggle camera&lt;/button&gt;
        &lt;button onClick={leave}&gt;Leave&lt;/button&gt;
      &lt;/div&gt;
      &lt;div style={{ display: "flex", flexWrap: "wrap", gap: 16, marginTop: 16 }}&gt;
        {[...participants.keys()].map((id) =&gt; (
          &lt;ParticipantView key={id} participantId={id} /&gt;
        ))}
      &lt;/div&gt;
    &lt;/div&gt;
  );
};

export default MeetingView;</code></pre><h2 id="building-the-provider-interface">Building the provider interface</h2><h3 id="waiting-room-pattern">Waiting room pattern</h3><p>Providers should not join the session until they have verified the patient's identity. Implement a waiting room by keeping the provider on a pre-session screen until the patient has an active session:</p><pre><code class="language-jsx">// src/ProviderWaiting.jsx
import { useState, useEffect } from "react";

const ProviderWaiting = ({ meetingId, onReady }) =&gt; {
  const [patientPresent, setPatientPresent] = useState(false);

  useEffect(() =&gt; {
    // Poll your server for patient-joined status
    const interval = setInterval(async () =&gt; {
      const res = await fetch(`/api/session-status/${meetingId}`);
      const { patientJoined } = await res.json();
      if (patientJoined) {
        setPatientPresent(true);
        clearInterval(interval);
      }
    }, 3000);
    return () =&gt; clearInterval(interval);
  }, [meetingId]);

  return (
    &lt;div&gt;
      {patientPresent ? (
        &lt;button onClick={onReady}&gt;Enter session&lt;/button&gt;
      ) : (
        &lt;p&gt;Waiting for patient to join...&lt;/p&gt;
      )}
    &lt;/div&gt;
  );
};

export default ProviderWaiting;</code></pre><p>The server-side <code>patientJoined</code> flag is set when you receive the <code>onParticipantJoined</code> webhook callback from VideoSDK.</p><h3 id="remote-participant-controls-and-recording">Remote participant controls and recording</h3><pre><code class="language-jsx">// src/ProviderMeetingView.jsx
import { useMeeting } from "@videosdk.live/react-sdk";

const ProviderMeetingView = ({ awsPath, webhookUrl }) =&gt; {
  const { startRecording, stopRecording, leave, participants } = useMeeting();

  const handleStartRecording = () =&gt; {
    startRecording(webhookUrl, awsPath);
  };

  return (
    &lt;div&gt;
      &lt;button onClick={handleStartRecording}&gt;Start recording&lt;/button&gt;
      &lt;button onClick={stopRecording}&gt;Stop recording&lt;/button&gt;
      &lt;button onClick={leave}&gt;End session&lt;/button&gt;
    &lt;/div&gt;
  );
};

export default ProviderMeetingView;</code></pre><p>Pass <code>awsPath</code> as a directory path in your HIPAA-eligible S3 bucket. Recording files will be stored at that path, giving you direct custody for retention and deletion workflows.</p><h2 id="enabling-e2ee">Enabling E2EE</h2><p>E2EE is a built-in, documented feature of <code>@videosdk.live/react-sdk</code> starting from version 0.3.5. The SDK exports an <code>ExternalE2EEKeyProvider</code> class that handles the encryption layer. You are fully responsible for generating, managing, and distributing the shared key to all participants. VideoSDK never stores or accesses it.</p><h3 id="step-1-generate-and-distribute-a-session-key-server-side">Step 1: generate and distribute a session key server-side</h3><p>Generate a cryptographically random key on your server at meeting creation time and deliver it to participants alongside their access token over HTTPS. Never compute or store this key in client-side code.</p><h3 id="step-2-configure-the-key-provider-and-pass-it-to-meetingprovider">Step 2: configure the key provider and pass it to <code>MeetingProvider</code></h3><pre><code class="language-jsx">import { MeetingProvider, ExternalE2EEKeyProvider } from "@videosdk.live/react-sdk";
import { useMemo } from "react";

const E2EEMeetingApp = ({ meetingId, token, encryptionKey }) =&gt; {
  const keyProvider = useMemo(() =&gt; {
    const _keyProvider = new ExternalE2EEKeyProvider();
    // Set the shared key before passing to MeetingProvider
    _keyProvider.setSharedKey(encryptionKey);
    return _keyProvider;
  }, [encryptionKey]);

  return (
    &lt;MeetingProvider
      config={{
        meetingId,
        micEnabled: true,
        webcamEnabled: true,
        name: "Participant",
      }}
      token={token}
      keyProvider={keyProvider || null} // Enables E2EE
    &gt;
      {/* Meeting components */}
    &lt;/MeetingProvider&gt;
  );
};</code></pre><h3 id="step-3-monitor-encryption-state-per-participant">Step 3: monitor encryption state per participant</h3><p>Use the <code>onE2EEStateChanged</code> callback in <code>useParticipant</code> to detect encryption failures before they become silent data leaks:</p><pre><code class="language-js">import { useParticipant } from "@videosdk.live/react-sdk";

const { displayName } = useParticipant(participantId, {
  onE2EEStateChanged,
});

function onE2EEStateChanged(stateInfo) {
  // stateInfo.state: EncryptionSuccess | DecryptionSuccess |
  // EncryptionFailed | DecryptionFailed | MissingKey | InvalidKey | InternalError
  // stateInfo.kind: audio | video | share
  if (
    stateInfo.state === "EncryptionFailed" ||
    stateInfo.state === "DecryptionFailed" ||
    stateInfo.state === "MissingKey"
  ) {
    // Alert the session: PHI may not be protected, end call
    console.error("E2EE failure", stateInfo);
  }
}</code></pre><p>Check E2EE status at session level</p><pre><code class="language-js">import { useMeeting } from "@videosdk.live/react-sdk";

const { isE2EEEnabled } = useMeeting();
console.log("E2EE active:", isE2EEEnabled);</code></pre><h3 id="critical-limitation-e2ee-disables-recording">Critical limitation: E2EE disables recording</h3><p>When <a href="https://www.videosdk.live/blog/what-is-end-to-end-encryption-e2ee" rel="noreferrer">E2EE</a> is active, VideoSDK recording and transcription are not available. The server cannot access encrypted media to record it. This creates a direct compliance trade-off: HIPAA may require session recordings as part of your audit trail, but enabling E2EE removes that capability. Your options are to store recordings through a client-side capture mechanism (outside VideoSDK), or to operate sessions without E2EE and rely on DTLS-SRTP encryption in transit combined with your storage-level encryption for compliance.</p><p>This trade-off must be evaluated against your specific BAA scope and your organization's risk posture.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--02_58_27-PM.png" class="kg-image" alt="How to Build a HIPAA-Compliant Telemedicine App with React" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Secure video call encryption architecture</span></figcaption></img></figure><h2 id="recording-retention-and-right-to-delete">Recording, retention, and right to delete</h2><h3 id="starting-and-stopping-recording">Starting and stopping recording</h3><p>The <code>startRecording()</code> function routes the recording to your storage:</p><pre><code class="language-js">import { useMeeting } from "@videosdk.live/react-sdk";

const { startRecording, stopRecording } = useMeeting();

// Start recording to your HIPAA S3 bucket
startRecording(
  "https://your-server.example.com/recording-webhook",
  "s3://your-hipaa-bucket/recordings/2026/05/"
);

// Stop recording at session end
stopRecording();</code></pre><p>The <code>onRecordingStateChanged</code> event fires as recording transitions through states:</p><pre><code class="language-js">import { Constants, useMeeting } from "@videosdk.live/react-sdk";

const onRecordingStateChanged = (data) =&gt; {
  const { status } = data;
  if (status === Constants.recordingEvents.RECORDING_STARTING) {
    console.log("Recording starting");
  } else if (status === Constants.recordingEvents.RECORDING_STARTED) {
    // Log to your audit database: { sessionId, startedAt: new Date() }
  } else if (status === Constants.recordingEvents.RECORDING_STOPPED) {
    // Log to your audit database: { sessionId, stoppedAt: new Date() }
  }
};

const { startRecording, stopRecording } = useMeeting({ onRecordingStateChanged });</code></pre><h3 id="right-to-delete-gdpr-article-17-and-hipaa-patient-rights">Right to delete (GDPR Article 17 and HIPAA patient rights)</h3><p>When a patient exercises their right to erasure under GDPR, or requests amendment under HIPAA, you need to delete the recording from your storage. Because you control the S3 path, your deletion workflow is straightforward:</p><pre><code class="language-js">// server-side deletion handler (Node.js example)
const { S3Client, DeleteObjectCommand } = require("@aws-sdk/client-s3");

const s3 = new S3Client({ region: process.env.AWS_REGION });

async function deletePatientRecording(bucket, key) {
  await s3.send(new DeleteObjectCommand({ Bucket: bucket, Key: key }));
  // Write deletion record to your audit log
  await auditLog.write({
    action: "recording_deleted",
    key,
    deletedAt: new Date().toISOString(),
    requestedBy: "patient_erasure_request",
  });
}</code></pre><p>Store the S3 key for each recording in your session database at the time the <code>RECORDING_STARTED</code> event fires, so you can retrieve it later for deletion.</p><h2 id="access-control-and-audit-logging">Access control and audit logging</h2><h3 id="token-based-access-control">Token-based access control</h3><p>Every participant requires a server-issued token to enter a meeting. The token is passed as a prop to <code>MeetingProvider</code>. The recommended server-side approach is to issue short-lived tokens (15-30 minutes) tied to a specific <code>participantId</code>:</p><pre><code class="language-js">// server-side token generation (Node.js + VideoSDK server API)
const jwt = require("jsonwebtoken");

function generateToken(participantId, meetingId) {
  const payload = {
    apikey: process.env.VIDEOSDK_API_KEY,
    permissions: ["allow_join"],
    participantId,
    meetingId,
    iat: Math.floor(Date.now() / 1000),
    exp: Math.floor(Date.now() / 1000) + 60 * 30, // 30 minutes
  };
  return jwt.sign(payload, process.env.VIDEOSDK_SECRET_KEY);
}</code></pre><p>Always validate the participant's identity (for example, against your EHR session record) before issuing a token. Never issue a token based solely on a client-provided meeting ID.</p><h3 id="audit-logging-with-participant-events">Audit logging with participant events</h3><p>The <code>useMeeting</code> hook exposes callbacks that you can use to build a session audit trail:</p><pre><code class="language-js">import { useMeeting } from "@videosdk.live/react-sdk";

const onMeetingJoined = () =&gt; {
  fetch("/api/audit", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      event: "local_participant_joined",
      meetingId,
      timestamp: new Date().toISOString(),
    }),
  });
};

const onParticipantJoined = (participant) =&gt; {
  fetch("/api/audit", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      event: "remote_participant_joined",
      participantId: participant.id,
      displayName: participant.displayName,
      meetingId,
      timestamp: new Date().toISOString(),
    }),
  });
};

const onMeetingLeft = () =&gt; {
  fetch("/api/audit", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      event: "meeting_left",
      meetingId,
      timestamp: new Date().toISOString(),
    }),
  });
};

const { meetingId } = useMeeting({
  onMeetingJoined,
  onParticipantJoined,
  onMeetingLeft,
});</code></pre><p>Store these audit events in a tamper-evident log. HIPAA requires audit logs to be retained for six years from the date of creation or last effective date.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li>HIPAA is the legal minimum for US telehealth. HITECH, state laws, and GDPR each add requirements that your architecture must satisfy on top of it.</li><li>The VideoSDK package name is <code>@videosdk.live/react-sdk</code>. The core hooks are <code>MeetingProvider</code>, <code>useMeeting</code>, and <code>useParticipant</code>. E2EE is enabled by passing an <code>ExternalE2EEKeyProvider</code> instance to <code>MeetingProvider</code>.</li><li>Recording to a custom <code>awsDirPath</code> gives you direct custody of session recordings, essential for HIPAA retention obligations and GDPR right-to-erasure workflows. Recording and E2EE are mutually exclusive: you cannot have both in the same session.</li><li>VideoSDK provides a BAA for HIPAA-covered use cases. Execute it before processing any PHI on the platform.</li><li>Geo-fencing (data residency) is available on the Enterprise plan, supporting regions including USA and Europe. It is the correct mechanism for GDPR data residency requirements with EU patients.</li></ul><h2 id="faq">FAQ</h2><h3 id="does-videosdk-sign-a-baa">Does VideoSDK sign a BAA?</h3><p>Yes. VideoSDK provides a Business Associate Agreement for HIPAA-covered use cases. You should request and execute the BAA before using VideoSDK in any session that involves PHI. Contact VideoSDK through their official support or sales channels to initiate the BAA process. Do not begin processing PHI on the platform until the BAA is signed.</p><h3 id="what-encryption-standard-does-videosdk-use-for-media">What encryption standard does VideoSDK use for media?</h3><p>VideoSDK uses two layers. At the transport layer, all <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> media is encrypted with DTLS-SRTP, which is the industry standard for real-time media in transit and satisfies the HIPAA Security Rule's encryption-in-transit requirement. At the application layer, you can enable E2EE using the <code>ExternalE2EEKeyProvider</code> class (available from React SDK version 0.3.5). With E2EE active, media is encrypted on the sender's device and decrypted only on the receiver's device. VideoSDK servers handle the relay but cannot access plaintext media. Note that enabling E2EE disables cloud recording and transcription.</p><h3 id="how-do-you-prevent-unauthorized-access-to-a-telemedicine-session">How do you prevent unauthorized access to a telemedicine session?</h3><p>Issue tokens only after server-side identity verification. Tie each token to a specific <code>participantId</code> and <code>meetingId</code> with a short expiry (15 to 30 minutes). Validate the participant's appointment record before token issuance. Use <code>onParticipantJoined</code> to detect unexpected participants and call the VideoSDK API to remove them if needed. Never expose your VideoSDK API secret in client-side code.</p><h3 id="can-session-recordings-be-stored-in-a-hipaa-compliant-s3-bucket">Can session recordings be stored in a HIPAA-compliant S3 bucket?</h3><p>Yes. The <code>startRecording(webhookUrl, awsDirPath)</code> function accepts a custom S3 directory path. By passing a path in your own AWS account, which should have server-side encryption (SSE-KMS), access logging, and object lock enabled, you retain full custody of the recording. Your S3 bucket's HIPAA eligibility depends on your AWS BAA with Amazon, which is available under the <a href="https://aws.amazon.com/compliance/hipaa-compliance/" rel="noreferrer">AWS Business Associate Addendum</a> for applicable services including S3.</p><h3 id="what-happens-if-the-patient-loses-connection-mid-session">What happens if the patient loses connection mid-session?</h3><p>The <code>onMeetingLeft</code> callback fires on the provider's client when the remote participant disconnects. You can use this to trigger a reconnection prompt or session status update. The VideoSDK infrastructure maintains the session room so the patient can rejoin using the same <code>meetingId</code> and a freshly issued token without requiring the provider to restart the session. Your server should log the disconnect event and the subsequent rejoin as separate audit entries.</p><h2 id="conclusion">Conclusion</h2><p>Building a compliant telemedicine app with React requires more than checking HIPAA boxes. HITECH extends direct liability to your infrastructure vendors, state laws like the New York SHIELD Act apply based on your patient's location, and GDPR activates the moment an EU/EEA resident joins a session.</p><p>VideoSDK's <code>@videosdk.live/react-sdk</code> covers the core mechanics: token-based access control via <code>MeetingProvider</code>, session recording to a custom S3 path via <code>startRecording()</code>, participant events via <code>useMeeting</code> callbacks for audit logging, E2EE via <code>ExternalE2EEKeyProvider</code>, and geo-fencing on the Enterprise plan for data residency compliance. VideoSDK also provides a BAA, which is the contractual prerequisite for any HIPAA-covered use.</p><p>The most significant architectural decision you face is the E2EE vs. recording trade-off. When E2EE is active, VideoSDK cloud recording is disabled. Your compliance requirements for audit trails and data encryption may point in opposite directions, and the resolution depends on your specific BAA scope and your organization's risk assessment.</p><p>Compliance is an ongoing process. Re-evaluate your controls when VideoSDK releases new versions, when your patient geography changes, and when new state laws take effect.</p>]]></content:encoded></item><item><title><![CDATA[How to Implement Video-Based Auto Insurance Claim Adjustments]]></title><description><![CDATA[Learn how to implement video-based auto insurance claim adjustments using VideoSDK. This guide covers room setup, React Native claimant app, React adjuster interface, cloud recording, and network quality handling for a complete audit-ready workflow.]]></description><link>https://www.videosdk.live/blog/video-based-auto-insurance-claim-adjustment</link><guid isPermaLink="false">69fc3a6d55831517a5a9f912</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 07 May 2026 07:39:16 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-5--2026--06_15_41-PM-1.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> A <strong>video-based auto insurance claim adjustment</strong> system replaces physical field visits with a live two-participant video call. The claimant streams vehicle damage from a mobile app, the adjuster reviews it in real time from a web interface, and the session is recorded to cloud storage as an audit trail. VideoSDK provides the room API, SDKs, and recording infrastructure to build this in a single day.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-5--2026--06_15_41-PM-1.png" alt="How to Implement Video-Based Auto Insurance Claim Adjustments"/><p>Video-based auto <a href="https://www.videosdk.live/blog/insurance-claim-settlement" rel="noreferrer">insurance claim adjustment</a> is a method where claimants submit vehicle damage evidence over a live, recorded video call instead of waiting for a physical inspection. An adjuster joins the same session remotely, reviews the stream, and logs the claim decision. This reduces average claim cycle time and eliminates the cost of field visits.</p><p>This guide walks you through building exactly that: a two-participant VideoSDK session where a claimant shares a live rear-camera view of vehicle damage and an adjuster reviews it from a browser-based interface, with cloud recording enabled throughout.</p><h3 id="system-design">System design</h3><p>The workflow involves two roles and four ordered steps.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--12_44_08-PM.png" class="kg-image" alt="How to Implement Video-Based Auto Insurance Claim Adjustments" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Video insurance workflow process diagram</span></figcaption></img></figure><p>Both participants join in <strong>SEND_AND_RECV</strong> mode, verified from the <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">VideoSDK React Native docs</a> as the mode where "both audio and video streams will be produced and consumed". This means the adjuster can speak back to the claimant and the claimant hears guidance in real time.</p><p>Your backend issues JWT tokens to each participant. The claimant's token carries <code>allow_join</code> permission. The adjuster's token carries <code>allow_join</code> and optionally <code>allow_mod</code>, which grants the ability to toggle participant media if needed.</p><p>The session is backed by a single VideoSDK <strong>room</strong>: a Room is a virtual space where participants exchange media streams. A <strong>session</strong> is one live instance of that room; multiple sessions can occur under the same room ID over time.</p><h3 id="setting-up-the-videosdk-room">Setting up the VideoSDK room</h3><h4 id="creating-a-room-via-the-rest-api">Creating a room via the REST API</h4><p>The VideoSDK REST API base URL is <code>https://api.videosdk.live</code>. To create a room, send a POST request <code>/v2/rooms</code> with your authorisation token in the <code>Authorization</code> header.</p><pre><code class="language-bash">curl --request POST \
  'https://api.videosdk.live/v2/rooms' \
  --header 'Authorization: YOUR_JWT_TOKEN' \
  --header 'Content-Type: application/json'</code></pre><p>The response contains a <code>roomId</code> (for example, <code>2kyv-gzay-64pg</code>). Store this and pass it to both participants when they initialize their SDK clients.</p><h4 id="generating-a-jwt-token">Generating a JWT token</h4><p>Your backend signs a <a href="https://www.geeksforgeeks.org/web-tech/json-web-token-jwt/" rel="noreferrer nofollow">JWT</a> using your VideoSDK <code>API_KEY</code> and <code>SECRET</code>, both available in your <a href="https://app.videosdk.live/api-keys">VideoSDK dashboard</a>.</p><pre><code class="language-javascript">// Node.js backend - token generation
const jwt = require('jsonwebtoken');

const API_KEY = process.env.VIDEOSDK_API_KEY;
const SECRET  = process.env.VIDEOSDK_SECRET;

const options = {
  expiresIn: '120m',
  algorithm: 'HS256',
};

const payload = {
  apikey:      API_KEY,
  permissions: ['allow_join'],
  version:     2,
  roomId:      '2kyv-gzay-64pg', // scope token to specific room
};

const token = jwt.sign(payload, SECRET, options);</code></pre><p>Set <code>version: 2</code> to access the v2 API. Scoping the token to a specific <code>roomId</code> prevents the same token from being reused in unrelated sessions, which matters for claim audit integrity.</p><h3 id="claimant-mobile-app-react-native">Claimant mobile app (<a href="https://www.videosdk.live/blog/react-native" rel="noreferrer">React Native</a>)</h3><h4 id="joining-the-room-and-streaming-vehicle-damage">Joining the room and streaming vehicle damage</h4><p>Install the SDK:</p><pre><code class="language-bash">yarn add @videosdk.live/react-native-sdk</code></pre><p>Wrap your app in <code>MeetingProvider</code>. Set <code>micEnabled: false</code> initially so the session does not start with accidental audio, and set <code>webcamEnabled: true</code> to begin streaming immediately on join.</p><pre><code class="language-jsx">// ClaimantApp.jsx
import {
  MeetingProvider,
  useMeeting,
  useParticipant,
  RTCView,
} from '@videosdk.live/react-native-sdk';

function ClaimantMeeting() {
  const { join, enableWebcam, disableWebcam, getWebcams, changeWebcam } =
    useMeeting({
      onMeetingJoined: () =&gt; {
        console.log('Claimant joined the claim session');
      },
      onMeetingLeft: () =&gt; {
        console.log('Claim session ended');
      },
    });

  return (
    // your UI
  );
}

export default function ClaimantApp() {
  return (
    &lt;MeetingProvider
      config={{
        meetingId: 'ROOM_ID_FROM_BACKEND',
        micEnabled: false,
        webcamEnabled: true,
        name: 'Claimant',
        mode: 'SEND_AND_RECV',
      }}
      token="YOUR_JWT_TOKEN"
      joinWithoutInteraction={false}
    &gt;
      &lt;ClaimantMeeting /&gt;
    &lt;/MeetingProvider&gt;
  );
}</code></pre><p>Call <code>join()</code> when the claimant taps "Start Inspection." The <code>useMeeting</code> hook's <code>join()</code> method initiates the session handshake.</p><h4 id="switching-between-front-and-rear-cameras">Switching between front and rear cameras</h4><p>The docs confirm <code>getWebcams()</code> returns all available camera devices and <code>changeWebcam(deviceId)</code> switches to the selected device. For a vehicle inspection, the claimant should default to the rear camera. Present a toggle button that cycles between available cameras.</p><pre><code class="language-jsx">const { getWebcams, changeWebcam } = useMeeting();

const switchToRearCamera = async () =&gt; {
  const webcams = await getWebcams();
  // On most Android/iOS devices, the rear camera label contains "back" or "environment"
  const rear = webcams.find(
    (cam) =&gt;
      cam.label.toLowerCase().includes('back') ||
      cam.label.toLowerCase().includes('environment')
  );
  if (rear) {
    changeWebcam(rear.deviceId);
  }
};</code></pre><p>Call <code>switchToRearCamera()</code> on mount so the session opens on the damage-facing lens. The claimant can still toggle to the front camera by calling <code>changeWebcam</code> with a different <code>deviceId</code> from the same <code>getWebcams()</code> list.</p><h3 id="adjuster-web-interface-react">Adjuster web interface (React)</h3><h4 id="viewing-the-claimants-remote-stream">Viewing the claimant's remote stream</h4><p>Install the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">React SDK</a>:</p><pre><code class="language-bash">npm install @videosdk.live/react-sdk</code></pre><p>The adjuster joins the same <code>roomId</code> with <code>SEND_AND_RECV</code> mode. Use <code>useParticipant</code> to access the claimant's video stream and <code>RTCView</code> (or a <code>video</code> element bound to the stream) to render it.</p><pre><code class="language-jsx">// AdjusterApp.jsx
import {
  MeetingProvider,
  useMeeting,
  useParticipant,
} from '@videosdk.live/react-sdk';

function ParticipantVideo({ participantId }) {
  const { webcamStream, webcamOn } = useParticipant(participantId);

  const videoRef = useRef(null);

  useEffect(() =&gt; {
    if (videoRef.current &amp;&amp; webcamOn &amp;&amp; webcamStream) {
      const mediaStream = new MediaStream();
      mediaStream.addTrack(webcamStream.track);
      videoRef.current.srcObject = mediaStream;
      videoRef.current.play().catch((err) =&gt; console.error(err));
    }
  }, [webcamStream, webcamOn]);

  return webcamOn ? (
    &lt;video ref={videoRef} autoPlay playsInline muted style={{ width: '100%' }} /&gt;
  ) : (
    &lt;div&gt;Claimant camera is off&lt;/div&gt;
  );
}

function AdjusterMeeting() {
  const { join, participants, startRecording, stopRecording, enableScreenShare } =
    useMeeting({
      onMeetingJoined: () =&gt; console.log('Adjuster joined'),
      onRecordingStarted: () =&gt; console.log('Recording started'),
      onRecordingStopped: () =&gt; console.log('Recording stopped'),
    });

  const remoteParticipants = [...participants.values()].filter(
    (p) =&gt; !p.local
  );

  return (
    &lt;div&gt;
      &lt;button onClick={() =&gt; join()}&gt;Join Claim Session&lt;/button&gt;
      &lt;button onClick={() =&gt; startRecording('https://your-webhook.com/recording', '/claim-recordings/')}&gt;
        Start Recording
      &lt;/button&gt;
      &lt;button onClick={() =&gt; stopRecording()}&gt;Stop Recording&lt;/button&gt;
      &lt;button onClick={() =&gt; enableScreenShare()}&gt;Share Screen&lt;/button&gt;
      {remoteParticipants.map((p) =&gt; (
        &lt;ParticipantVideo key={p.id} participantId={p.id} /&gt;
      ))}
    &lt;/div&gt;
  );
}

export default function AdjusterApp() {
  return (
    &lt;MeetingProvider
      config={{
        meetingId: 'ROOM_ID_FROM_BACKEND',
        micEnabled: true,
        webcamEnabled: true,
        name: 'Adjuster',
        mode: 'SEND_AND_RECV',
      }}
      token="ADJUSTER_JWT_TOKEN"
      joinWithoutInteraction={false}
    &gt;
      &lt;AdjusterMeeting /&gt;
    &lt;/MeetingProvider&gt;
  );
}</code></pre><h4 id="screen-share-for-annotation-reference">Screen share for annotation reference</h4><p>The <code>enableScreenShare()</code> method is confirmed in the VideoSDK React Native docs (and mirrors the React SDK). The adjuster can share their screen to walk the claimant through a form or show a diagram of the vehicle damage zones. Call <code>disableScreenShare()</code> to stop it.</p><p>Note: built-in whiteboard annotation is not a documented method in the VideoSDK SDK as of this writing. For annotation overlays, you would implement a custom canvas layer and broadcast drawing coordinates using the <code>usePubSub</code> hook.</p><h3 id="quickstart-run-the-sample-project-in-5-steps">Quickstart: run the sample project in 5 steps</h3><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> maintains a production-ready React sample that shares the same room and recording infrastructure used in this guide. Cloning it gives you a working two-participant video session you can adapt for your claims workflow in minutes.</p><p><strong>Step 1: Clone the sample project</strong></p><pre><code class="language-bash">git clone https://github.com/videosdk-community/vkyc-reactsdk-example.git</code></pre><p>Step 2: Copy the environment file</p><pre><code class="language- bash">cp .env.example .env</code></pre><p><strong>Step 3: Set your VideoSDK token</strong></p><p>Generate a temporary token from your <a href="https://app.videosdk.live/signup">VideoSDK Account</a>, then open <code>.env</code> and set:</p><pre><code class="language-bash">REACT_APP_VIDEOSDK_TOKEN = "YOUR_VIDEOSDK_TOKEN"</code></pre><p>Step 4: Install dependencies</p><pre><code class="language-bash">yarn</code></pre><p>Step 5: Run the app</p><pre><code class="language-bash">yarn start</code></pre><p>The app opens in your browser with a fully functional two-participant video session. Map the "customer" role to your claimant flow and the "agent" role to your adjuster interface.</p><h3 id="cloud-recording-for-audit">Cloud recording for audit</h3><h4 id="starting-and-stopping-recording">Starting and stopping recording</h4><p>Call <code>startRecording()</code> from the <code>useMeeting</code> hook. The method accepts three parameters: <code>webhookUrl</code>, <code>awsDirPath</code>, and a <code>config</code> object. The webhook fires when the recording is processed and stored.</p><pre><code class="language-javascript">const { startRecording, stopRecording } = useMeeting();

// Start recording at full quality in portrait mode
startRecording(
  'https://your-api.com/webhooks/recording-done',
  '/auto-claims/session-recordings/',
  {
    layout: {
      type: 'SPOTLIGHT',   // focuses on the active speaker (claimant)
      priority: 'PIN',
    },
    theme: 'DEFAULT',
    mode: 'video-and-audio',
    quality: 'high',
    orientation: 'portrait',
  }
);

// Stop when the adjuster closes the session
stopRecording();</code></pre><p><code>SPOTLIGHT</code> layout with <code>PIN</code> priority keeps the claimant's video feed prominent in the recorded file, which is what reviewers and auditors need to see.</p><h4 id="storage-and-retrieval">Storage and retrieval</h4><p>By default, VideoSDK stores recordings in its own cloud storage. To use your own S3 bucket, provide an <code>awsDirPath</code> pointing to your bucket path you can talk to the <a href="https://www.videosdk.live/contact" rel="noreferrer">VideoSDK support team</a>.</p><p>Once processed, retrieve recordings via:</p><pre><code class="language-bash">GET https://api.videosdk.live/v2/recordings</code></pre><p>Or fetch a specific recording:</p><pre><code class="language-bash">GET https://api.videosdk.live/v2/recordings/{recordingId}</code></pre><p>The webhook payload includes the recording URL and session metadata, so you can associate each file with the corresponding claim ID in your system automatically.</p><h3 id="handling-poor-network-conditions">Handling poor network conditions</h3><h4 id="what-videosdk-exposes-for-network-quality">What VideoSDK exposes for network quality</h4><p>The <code>useMeeting</code> events page in the React Native docs lists <code>onMeetingJoined</code>, <code>onMeetingLeft</code>, <code>onParticipantJoined</code>, <code>onParticipantLeft</code>, and recording/stream events. A dedicated <code>onNetworkQualityChanged</code> event was not found in the React Native SDK docs at the time of writing. Before implementing network quality UI, check the latest SDK changelog and the <code>useParticipant</code> events page, as this may be available under participant-level events or via a newer SDK version.</p><p>For resilience, the practical approach that does not require a dedicated event is to monitor the WebRTC stats available through the browser's native <code>RTCPeerConnection.getStats()</code> API alongside VideoSDK's session, and display a degraded-quality warning when <a href="https://www.videosdk.live/developer-hub/social/packet-loss" rel="noreferrer">packet loss</a> or<a href="https://www.videosdk.live/blog/what-is-jitter" rel="noreferrer"> jitter</a> exceeds thresholds you define.</p><h4 id="reconnection-guidance-for-claimants">Reconnection guidance for claimants</h4><p>On mobile, signal loss is common mid-inspection. Build your claimant app to handle <code>onMeetingLeft</code> and re-call <code>join()</code> automatically:</p><pre><code class="language-jsx">const { join } = useMeeting({
  onMeetingLeft: () =&gt; {
    // Wait 2 seconds, then attempt automatic rejoin
    setTimeout(() =&gt; {
      join();
    }, 2000);
  },
});</code></pre><p>Display a visible status banner: "Reconnecting..." while the rejoin is in progress. The adjuster's session continues uninterrupted; they will receive <code>onParticipantJoined</code> again when the claimant reconnects.</p><p>For 3G or low-bandwidth conditions, advise claimants to hold the phone steady and avoid moving the camera quickly. Rapid motion on a constrained connection causes frame drops that reduce the quality of the evidence stream.</p><h3 id="key-takeaways">Key takeaways</h3><ul><li>VideoSDK rooms are created via <code>POST /v2/rooms</code> on <code>https://api.videosdk.live</code>, and both participants join using JWT tokens signed with HS256.</li><li>The <code>SEND_AND_RECV</code> mode is the correct participant mode for a two-way claim inspection call where both parties produce and consume audio and video.</li><li>Camera switching on the claimant's device uses <code>getWebcams()</code> to enumerate devices and <code>changeWebcam(deviceId)</code> to select the rear lens, both confirmed from the React Native SDK docs.</li><li><code>startRecording()</code> from <code>useMeeting</code> stores the session to VideoSDK's cloud or your S3 bucket, and a webhook delivers the recording URL upon processing completion.</li><li>Built-in whiteboard annotation is not a documented SDK method; use <code>usePubSub</code> to broadcast drawing state for a custom overlay.</li></ul><h3 id="faq">FAQ</h3><p><strong>Can the adjuster take screenshots from the live stream?</strong></p><p>VideoSDK does not expose a built-in screenshot API in its SDK. The adjuster can use the browser's native <code>HTMLVideoElement</code> and an HTML <code>canvas</code> element to capture a frame from the video element that renders the claimant's stream. Draw the video frame to the canvas using <code>ctx.drawImage(videoEl, 0, 0)</code> and then export it with <code>canvas.toDataURL('image/png')</code>. Store the resulting image alongside the session recording in your claims management system.</p><p><strong>How long does a typical claim session recording take to process?</strong></p><p>VideoSDK does not publish a guaranteed processing SLA in its current documentation. In practice, cloud recording processing time depends on session duration and output quality setting. A 10-minute <code>high</code> quality session typically completes within a few minutes of the session ending. Your webhook endpoint at <code>webhookUrl</code> receives a callback when the file is ready, so you do not need to poll. Check the <a href="https://docs.videosdk.live/api-reference/realtime-communication/user-webhooks">VideoSDK webhooks documentation</a> for the exact payload schema.</p><p><strong>Can the claimant app work on 3G?</strong></p><p>Yes. VideoSDK uses WebRTC, which includes adaptive bitrate control. On 3G connections (typically 1 to 10 Mbps download, 0.5 to 2 Mbps upload), the SDK will reduce video resolution and frame rate automatically to maintain stream continuity. For best results on 3G, set the recording quality to <code>low</code> or <code>med</code> rather than <code>high</code>, and instruct claimants to hold the phone still to reduce the encoder's bitrate demand. Audio quality is generally unaffected at 3G speeds.</p><p><strong>Is the recording GDPR compliant?</strong></p><p>GDPR compliance depends on how you configure your storage and data processing pipeline, not the SDK alone. VideoSDK provides the mechanism to store recordings in your own AWS S3 bucket via the <code>awsDirPath</code> parameter, which keeps the data within your controlled infrastructure. You are responsible for ensuring your storage region, retention policies, data subject consent, and processor agreements meet GDPR requirements. Consult VideoSDK's <a href="https://www.videosdk.live/privacy-policy">Privacy Policy</a> and your own legal counsel to confirm your specific configuration is compliant.</p><h3 id="conclusion">Conclusion</h3><p>Implementing <strong>video-based auto insurance claim adjustment</strong> with VideoSDK requires four concrete pieces: a JWT-authenticated room created via <code>POST /v2/rooms</code>, a React Native claimant app that joins in <code>SEND_AND_RECV</code> mode and exposes <code>changeWebcam()</code> for rear-camera use, a React adjuster interface that renders the remote stream and triggers <code>startRecording()</code>, and a webhook handler that receives the stored recording URL for your audit trail.</p><p>Every method in this guide, including <code>join()</code>, <code>enableWebcam()</code>, <code>changeWebcam()</code>, <code>startRecording()</code>, <code>stopRecording()</code>, and <code>enableScreenShare()</code>, is verified from the VideoSDK docs. The V-KYC sample repository gives you a running baseline in five commands, so you can focus engineering time on your claims-specific business logic rather than WebRTC plumbing.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Video KYC System for the Middle East]]></title><description><![CDATA[Building a video KYC system for the Middle East requires more than a video call. This guide covers MENA regulatory context, Arabic RTL UI, document OCR, face match, geo-fencing for data residency, and cloud recording using VideoSDK.]]></description><link>https://www.videosdk.live/blog/video-kyc-system-middle-east</link><guid isPermaLink="false">69fc2aba55831517a5a9f8bb</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 07 May 2026 06:54:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-5--2026--06_15_41-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> A compliant video KYC system for the Middle East needs a live agent session, national ID capture and OCR, face-to-ID matching, liveness detection, session recording, Arabic language support, and data residency controls. VideoSDK provides the real-time video infrastructure and AI identity verification APIs to cover most of these requirements in a single integration.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-5--2026--06_15_41-PM.png" alt="How to Build a Video KYC System for the Middle East"/><p>Building a <a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer"><strong>video KYC</strong></a> (Know Your Customer) system for the Middle East means handling regional identity document formats, Arabic-first UX, and data residency rules that vary by jurisdiction. This guide walks through the architecture, code, and VideoSDK APIs you need to ship a production-grade MENA video KYC flow.</p><h3 id="regulatory-overview-in-the-middle-east">Regulatory overview in the Middle East</h3><p>The <a href="https://en.wikipedia.org/wiki/Middle_East_and_North_Africa" rel="noreferrer nofollow">MENA region</a> does not have a single unified eKYC standard. Each market has its own framework, and requirements continue to evolve. The patterns below reflect publicly documented guidance as of early 2026. Your legal team should verify the current rules for each jurisdiction before you go live.</p><p>In the UAE, the Central Bank of the UAE (CBUAE) permits <strong>digital onboarding</strong> with <a href="https://www.videosdk.live/blog/video-based-identification-procedure-vbip" rel="noreferrer">video-based identity verification</a> for licensed financial institutions. The UAE Pass digital identity scheme also plays a role in consumer onboarding. The Emirates NBD and other major banks have deployed video KYC under CBUAE supervision, but the specific technical requirements are set by the regulator and may be updated. Verify current CBUAE circular guidance with your compliance team.</p><p>Saudi Arabia's Saudi Central Bank (SAMA) has published guidelines on digital banking and fintech. Remote customer onboarding via video verification is permitted for licensed entities under certain conditions. SAMA's open banking and fintech frameworks increasingly support eKYC flows, but session recording retention periods and biometric data handling rules require direct legal review.</p><p>Bahrain, Qatar, Kuwait, and Egypt each have central bank circulars or fintech regulatory sandboxes that address digital identity and remote onboarding. The common thread across MENA is a requirement for a live human agent on at least one side of the session, a recording of the session, and verification of a government-issued identity document.</p><p>Data residency is a recurring requirement. Several jurisdictions require that <a href="https://www.ibm.com/think/topics/pii" rel="noreferrer nofollow">personally identifiable information (PII)</a> and biometric data be processed and stored within the country or within approved regions. Verify this with legal counsel for each market you target.</p><h3 id="common-technical-requirements-across-mena">Common technical requirements across MENA</h3><p>Most MENA video KYC implementations share the following functional requirements regardless of exact regulatory jurisdiction.</p><p>A <a href="https://www.videosdk.live/blog/1-on-1-video-chat" rel="noreferrer"><strong>live video session</strong> connecting the customer to a human agent</a> in real time is the core requirement. The session must be synchronous, not pre-recorded.</p><p><strong>Document capture</strong> during the session is required to extract identity data. MENA markets use national ID cards with Arabic text, including the Emirates ID (UAE), Iqama (Saudi Arabia), Bahraini CPR, and Qatari QID. These documents have both Arabic and English fields.</p><p><strong>Face matching</strong> against the captured document photo verifies that the person on the call is the same person shown in the ID.</p><p><a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer"><strong>Liveness or spoof detection</strong></a> prevents the use of printed photos or pre-recorded video to bypass face matching.</p><p><strong>Session recording</strong> must be retained for audit and regulatory review. Retention periods vary by jurisdiction.</p><p><strong>Arabic language support</strong> in the customer-facing UI is a baseline expectation across the region. Arabic is written right-to-left (RTL), which requires specific layout handling.</p><h3 id="architecture">Architecture</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-7--2026--11_34_46-AM.png" class="kg-image" alt="How to Build a Video KYC System for the Middle East" loading="lazy" width="1693" height="929"><figcaption><span style="white-space: pre-wrap;">Fintech architecture for MENA video KYC</span></figcaption></img></figure><p>The flow works as follows. The customer opens the mobile app, which creates or joins a VideoSDK room. The agent joins the same room from a web <a href="https://www.videosdk.live/blog/video-kyc-agent-dashboard" rel="noreferrer">agent dashboard</a>. During the session, the customer holds up their identity document to the camera. The agent triggers a frame capture, which is sent as a base64-encoded image to VideoSDK's OCR API. The extracted fields are returned in JSON. A second call to the Face Match API compares the document photo against a live selfie frame. Spoof detection runs in parallel. The session records to cloud storage. On completion, the agent submits the verification outcome to the core banking system.</p><h3 id="building-the-customer-app">Building the customer app</h3><p>The customer app targets both Android and iOS. <a href="https://www.videosdk.live/blog/react-native" rel="noreferrer">React Native</a> covers both platforms from a single codebase, which is the most practical choice given MENA's mixed Android-iOS market share.</p><p><strong>Right-to-left (RTL) layout</strong> is a React Native concern, not a VideoSDK concern. VideoSDK's SDK renders video streams in a view component and does not control surrounding UI direction. To enable RTL layout for the Arabic interface, set the following before your root component renders:</p><pre><code class="language-javascript">// index.js
import { I18nManager } from "react-native";
I18nManager.forceRTL(true);</code></pre><p>You also need to restart the Metro bundler after changing this setting for it to take effect in development.</p><p>Install the <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">VideoSDK React Native SDK</a> and the in-call manager package:</p><pre><code class="language-bash">npm install "@videosdk.live/react-native-sdk" "@videosdk.live/react-native-incallmanager"</code></pre><p>Register VideoSDK services in your root <code>index.js</code>:</p><pre><code class="language-javascript">import { AppRegistry } from "react-native";
import App from "./App";
import { name as appName } from "./app.json";
import { register } from "@videosdk.live/react-native-sdk";

register();
AppRegistry.registerComponent(appName, () =&gt; App);</code></pre><p>Wrap your meeting screen with <code>MeetingProvider</code>, passing a room ID and a JWT token:</p><pre><code class="language-javascript">import {
  MeetingProvider,
  useMeeting,
  useParticipant,
  MediaStream,
  RTCView,
} from "@videosdk.live/react-native-sdk";

&lt;MeetingProvider
  config={{
    meetingId: roomId,
    micEnabled: true,
    webcamEnabled: true,
    name: "Customer",
  }}
  token={token}
&gt;
  &lt;KYCSessionView /&gt;
&lt;/MeetingProvider&gt;</code></pre><p>Use the <code>useMeeting</code> hook to access <code>join</code>, <code>leave</code>, <code>toggleWebcam</code>, and <code>toggleMic</code>. Use <code>useParticipant(participantId)</code> to access <code>webcamStream</code> and <code>webcamOn</code> for each participant. Render remote video with <code>RTCView</code>:</p><pre><code class="language-javascript">const { webcamStream, webcamOn } = useParticipant(participantId);

{webcamOn &amp;&amp; webcamStream &amp;&amp; (
  &lt;RTCView
    streamURL={new MediaStream([webcamStream.track]).toURL()}
    objectFit="cover"
    style={{ height: 300, marginVertical: 8 }}
  /&gt;
)}</code></pre><p>Android requires camera, microphone, and network permissions in <code>AndroidManifest.xml</code>. iOS requires <code>NSCameraUsageDescription</code> and <code>NSMicrophoneUsageDescription</code> entries in <code>Info.plist</code>. Set <code>minSdkVersion</code> to 23 in <code>android/build.gradle</code>. iOS platform must be 12.0 or later in the Podfile.</p><h3 id="quick-start-run-the-sample-project">Quick start: run the sample project</h3><p>To get a working video KYC demo running locally, follow these steps.</p><p><strong>Step 1: Clone the sample project</strong></p><pre><code class="language-bash">git clone https://github.com/videosdk-community/vkyc-reactsdk-example.git</code></pre><p>Step 2: Copy the environment file</p><pre><code class="language-bash">cp .env.example .env</code></pre><p><strong>Step 3: Add your VideoSDK token</strong></p><p>Generate a temporary token from your <a href="https://app.videosdk.live/signup">VideoSDK account</a> and paste it into <code>.env</code>:</p><pre><code class="language-bash">REACT_APP_VIDEOSDK_TOKEN = "YOUR_VIDEOSDK_TOKEN"</code></pre><p>Step 4: Install dependencies</p><pre><code class="language-bash">yarn</code></pre><p>Step 5: Run the app</p><pre><code class="language-bash">yarn start</code></pre><h3 id="document-capture-and-verification">Document capture and verification</h3><p>VideoSDK provides three REST APIs for identity verification. All three are available on the Enterprise plan only. Contact VideoSDK sales to enable them on your account.</p><h4 id="ocr-api">OCR API</h4><p>The <a href="https://docs.videosdk.live/android/guide/identity-verification/ocr" rel="noreferrer"><strong>OCR API</strong></a> (Optical Character Recognition API) takes the front and back of an identity document as base64-encoded images and returns extracted fields in a JSON response. Fields include <code>idType</code>, <code>idNumber</code>, <code>name</code>, <code>dateOfBirth</code>, <code>address</code>, <code>gender</code>, and <code>mobileNumber</code>. The exact fields returned depend on the document type.</p><p>Endpoint: <code>POST https://api.videosdk.live/ai/v1/ocr</code></p><p>The request body requires two base64-encoded images:</p><pre><code class="language-javascript">const data = {
  frontPart: `data:image/jpeg;base64,${base64Front}`,
  backPart: `data:image/jpeg;base64,${base64Back}`,
};

const response = await axios.post(
  "https://api.videosdk.live/ai/v1/ocr",
  data,
  {
    headers: {
      Authorization: `${process.env.VIDEOSDK_API_TOKEN}`,
      "Content-Type": "application/json",
    },
  }
);</code></pre><p>To capture a frame from the live video stream, use <code>useParticipant</code> to access the current <code>webcamStream</code> track, draw it to an offscreen canvas, and call <code>canvas.toDataURL("image/jpeg")</code> to get the base64 string. This step happens on the agent dashboard side, not in the customer app.</p><p>The OCR API does not document support for specific document types by country. Test your target document types (Emirates ID, Iqama, QID, CPR) against the API during development and verify extraction accuracy with your compliance team.</p><h4 id="face-match-api">Face Match API</h4><p>The <a href="https://docs.videosdk.live/react/guide/identity-verification/face-match-api" rel="noreferrer"><strong>Face Match API</strong></a> compares a selfie image against a document photo and returns a similarity score. The endpoint is <code>POST https://api.videosdk.live/ai/v1/face-match</code> (verify the exact path in your Enterprise plan documentation, as the docs page is at <code>/react-native/guide/identity-verification/face-match-api</code>).</p><p>The request format follows the same base64 pattern as the OCR API: send the document photo and the live selfie photo as <code>frontPart</code> and <code>selfie</code> fields. The response includes a match score. Your compliance threshold for what constitutes a pass is a business and regulatory decision.</p><h4 id="face-spoof-detection-api">Face Spoof Detection API</h4><p>The <a href="https://docs.videosdk.live/react/guide/identity-verification/face-spoof-detection" rel="noreferrer"><strong>Face Spoof Detection API</strong></a> detects whether the presented face is live or a spoofed input such as a printed photograph or a screen replay. The endpoint documentation is at <code>/react-native/guide/identity-verification/face-spoof-detection</code>. Pass a single base64 frame from the live webcam stream. The response indicates whether a live face was detected.</p><p>Run spoof detection before face matching. If spoof detection flags the frame, reject the session and require the customer to retry. Do not proceed to face matching on a flagged frame.</p><h3 id="geo-fencing-for-data-residency">Geo-fencing for data residency</h3><p>VideoSDK's <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/geo-fencing-and-proxy-controls/geo-fencing" rel="noreferrer">geo-fencing</a> feature restricts media server connections to a specified region. This is documented and available under the Enterprise plan. Geo-fencing is configured at the room creation level, not in the client SDK.</p><p>When you create a room via the VideoSDK REST API (<code>POST https://api.videosdk.live/v2/rooms</code>), you can specify a region. The documented available regions are INDIA, USA, UAE, EUROPE, SINGAPORE, and AUSTRALIA.</p><p>For MENA deployments requiring data residency in the UAE, specify the UAE region when creating the room:</p><pre><code class="language-javascript">const res = await fetch("https://api.videosdk.live/v2/rooms", {
  method: "POST",
  headers: {
    authorization: token,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ region: "UAE" }),
});
const { roomId } = await res.json();</code></pre><p><a href="https://docs.videosdk.live/" rel="noreferrer">VideoSDK's documentation</a> notes that if a participant's physical location differs from the geo-fenced region, network quality between those locations may degrade. Avoid geo-fencing unless your compliance requirement explicitly demands it.</p><p>Geo-fencing controls where media passes through VideoSDK's infrastructure. It does not control where your own backend, recording storage, or AI API data is processed. You are responsible for ensuring that recording files and OCR/biometric data are stored in compliant locations. Consult your legal team on how VideoSDK's data processing fits within your broader data residency obligations for each MENA jurisdiction.</p><h3 id="cloud-recording">Cloud recording</h3><p>VideoSDK supports <a href="https://www.videosdk.live/blog/cloud-recording-and-rtmp-pricing" rel="noreferrer">cloud recording</a> for React Native sessions. Recording is triggered via the VideoSDK REST API or through the <code>useMeeting</code> hook. The <code>startRecording</code> method is available via <code>useMeeting</code>:</p><pre><code class="language-javascript">const { startRecording, stopRecording } = useMeeting();

// Start recording with a webhook URL for status callbacks
startRecording(webhookUrl, awsDirPath, config);</code></pre><p>Recordings are stored to cloud storage. For MENA data residency requirements, configure your recording storage destination (S3-compatible bucket in the UAE or your target region) via the VideoSDK dashboard or through recording API parameters. Verify the exact storage configuration options available on your plan with VideoSDK support, as cloud storage destination controls are plan-dependent.</p><p>Retain recordings for the period required by your target jurisdiction's regulations. Retention requirements vary: verify the current requirement for each market with your legal team.</p><h3 id="key-takeaways">Key takeaways</h3><ul><li>A compliant MENA video KYC system requires a live agent session, document OCR, face matching, spoof detection, and session recording as a minimum viable feature set.</li><li>VideoSDK's OCR API, Face Match API, and Face Spoof Detection API are all available on the Enterprise plan only. Plan for this in your commercial timeline.</li><li>RTL Arabic UI is a React Native layout concern handled via <code>I18nManager.forceRTL(true)</code>, not a VideoSDK SDK concern.</li><li>Geo-fencing to the UAE region is supported and documented, but only controls media server routing, not recording or AI API data flows.</li><li>Regulatory requirements across MENA differ by jurisdiction and are subject to change. All compliance-critical implementation decisions require legal review for each target market.</li></ul><h3 id="faq">FAQ</h3><p><strong>Q1. Does VideoSDK support Arabic language in its SDK?</strong></p><p>VideoSDK's React Native SDK (<code>@videosdk.live/react-native-sdk</code>) does not impose any language on the UI. The SDK renders video streams via <code>RTCView</code> and exposes hooks like <code>useMeeting</code> and <code>useParticipant</code>. All UI text, labels, and layout direction are under the developer's control. To render an Arabic RTL interface, use React Native's <code>I18nManager.forceRTL(true)</code> and write your UI strings in Arabic. The SDK itself is language-agnostic.</p><p><strong>Q2. Does VideoSDK have data centers in the Middle East?</strong></p><p>Yes. The VideoSDK geo-fencing documentation lists UAE as one of the available regions (alongside India, USA, Europe, Singapore, and Australia). This allows media traffic to be routed through UAE infrastructure. Geo-fencing is an Enterprise plan feature. Contact VideoSDK sales to enable it and to get the current list of available infrastructure regions, as this may expand over time.</p><p><strong>Q3. What document types can the OCR API read?</strong></p><p>The VideoSDK OCR API documentation states that it accepts front and back images of a document and returns available fields in JSON, with fields varying by document type. The documentation does not enumerate specific supported document types or countries. You should test Emirates ID, Saudi Iqama, Bahraini CPR, Qatari QID, and any other target document types against the API in a pre-production environment and verify extraction accuracy before going live.</p><p><strong>Q4. Can biometric data be processed under regional data protection laws?</strong></p><p>Sending biometric data (face images, document photos) to a third-party API constitutes third-party data processing under most <a href="https://www.videosdk.live/blog/high-grade-client-to-server-encryption" rel="noreferrer">data protection frameworks</a>, including those in the UAE and Saudi Arabia. Whether this is permitted depends on your data processing agreements, the regulatory license of your institution, and the jurisdiction's specific rules on biometric data. Obtain a Data Processing Agreement (DPA) from VideoSDK before sending any customer biometric data to their APIs. Confirm with legal counsel that the data flow complies with each target jurisdiction's requirements.</p><p><strong>Q5. Is a DPA available from VideoSDK?</strong></p><p>VideoSDK's documentation does not describe the DPA or BAA process in detail as of the time of writing. Contact VideoSDK directly at videosdk.live/contact to request a DPA or to discuss compliance documentation requirements for your jurisdiction. Treat this as a procurement step before you begin sending real customer data to any VideoSDK API.</p><h3 id="conclusion">Conclusion</h3><p>Building a <strong>video KYC system for the Middle East</strong> combines real-time video infrastructure with AI identity verification and regional compliance controls. VideoSDK covers the core technical layers: live video sessions via <code>MeetingProvider</code> and <code>useMeeting</code>, document extraction via the OCR API, biometric verification via the Face Match and Face Spoof Detection APIs, data residency controls via geo-fencing to the UAE region, and session recording for audit trails. The MENA video KYC layer that VideoSDK does not handle is regulatory compliance itself. Regulatory requirements across UAE, Saudi Arabia, Bahrain, Qatar, and Egypt each have their own frameworks, and all of them evolve. Build the technology with VideoSDK, and build the compliance framework with qualified legal counsel for each market.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Video KYC System for Cooperative Banks in India]]></title><description><![CDATA[A practical developer guide to building a compliant Video Customer Identification Process (V-CIP) for cooperative banks and UCBs in India, using VideoSDK's React Native and React SDKs with real code examples.]]></description><link>https://www.videosdk.live/blog/video-kyc-cooperative-bank-india</link><guid isPermaLink="false">69faf6f455831517a5a9f835</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 06 May 2026 09:37:18 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-6--2026--01_51_31-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> Cooperative banks regulated by the Reserve Bank of India (RBI), including urban cooperative banks (UCBs) and state cooperative banks, are required to implement Video Customer Identification Process (V-CIP) as a valid KYC method. This guide shows you how to build a production-ready video KYC cooperative bank India system using VideoSDK, with verified SDK method names, real code, and compliance guidance.</blockquote><h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-6--2026--01_51_31-PM.png" alt="How to Build a Video KYC System for Cooperative Banks in India"/><p><a href="https://www.videosdk.live/blog/video-based-identification-procedure-vbip" rel="noreferrer"><strong>V-CIP</strong> (Video Customer Identification Process)</a> is a live, interactive video call between a bank official and a customer, during which identity documents are verified in real time. Cooperative banks regulated by the RBI are required to comply with the <a href="https://www.rbi.org.in/commonman/English/scripts/notification.aspx?id=2607" rel="noreferrer nofollow">Master Direction on KYC (2016, updated 2025)</a>, which explicitly includes V-CIP as an approved identification method.</p><p>This guide covers the full technical implementation: architecture, the VideoSDK React Native member app, the React-based <a href="https://www.videosdk.live/blog/video-kyc-agent-dashboard" rel="noreferrer">agent interface</a>, OCR and face verification, network handling, and audit compliance. </p><h2 id="rbi-v-cip-applicability-to-cooperative-banks">RBI V-CIP applicability to cooperative banks</h2><p>The RBI Master Direction on Know Your Customer (KYC), 2016 applies to all entities regulated by RBI, not just commercial banks. This includes:</p><ul><li><strong>Urban cooperative banks (UCBs):</strong> Regulated directly by RBI since 2020 under the <a href="https://www.pib.gov.in/PressReleasePage.aspx?PRID=2117408&amp;reg=3&amp;lang=2" rel="noreferrer nofollow">Banking Regulation (Amendment) Act, 2020</a>. UCBs above the Tier 1 threshold must implement digital KYC channels including V-CIP.</li><li><strong>State cooperative banks and district central cooperative banks (DCCBs):</strong> Regulated by both <a href="https://www.rbi.org.in/" rel="noreferrer nofollow">RBI</a>&nbsp;and&nbsp;<a href="https://en.wikipedia.org/wiki/National_Bank_for_Agriculture_and_Rural_Development" rel="noreferrer nofollow">NABARD</a>. The KYC Master Direction applies to them for accounts opened with them as primary banks.</li><li><strong>Multi-state cooperative societies with banking operations:</strong> Subject to RBI's KYC norms for deposit-taking activities.</li></ul><p>The RBI circular dated January 9, 2020 (RBI/2019-20/128) and subsequent updates allow V-CIP as a method to <a href="https://www.videosdk.live/blog/video-kyc-vs-traditional-kyc" rel="noreferrer">establish customer identity without physical presence</a>. The process requires a live video call, capture of the customer's Officially Valid Document (OVD), a <a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">liveness check</a>, and mandatory recording and storage of the session.</p><blockquote>Note: Cooperative societies that are not registered under the Banking Regulation Act and do not take deposits are outside RBI's KYC jurisdiction. Verify your entity's regulatory status before implementation.</blockquote><h2 id="technical-architecture">Technical architecture</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-6--2026--01_45_19-PM.png" class="kg-image" alt="How to Build a Video KYC System for Cooperative Banks in India" loading="lazy" width="1448" height="1086"><figcaption><span style="white-space: pre-wrap;">Video identity verification system flowchart</span></figcaption></img></figure><p>The system has six components:</p><p><strong>VideoSDK Room:</strong> A <strong>Room</strong> in VideoSDK is the isolated session space where participants communicate using <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a>. Each V-CIP session maps to one Room, identified by a <code>meetingId</code> (also called <code>roomId</code> in the REST API). Rooms are created via a POST request to <code>https://api.videosdk.live/v2/rooms</code>.</p><p><strong>Member mobile app:</strong> Built with <code>@videosdk.live/react-native-sdk</code>. The customer joins the Room, streams their camera, and holds up their Aadhaar, PAN, or other OVD for document capture.</p><p><strong>Agent web app:</strong> Built with <code>@videosdk.live/react-sdk</code>. The bank official sees the remote participant video, captures document frames, triggers verification, and controls recording.</p><p><strong>Identity verification services:</strong> VideoSDK exposes <a href="https://docs.videosdk.live/android/guide/identity-verification/ocr" rel="noreferrer">OCR</a>, <a href="https://docs.videosdk.live/react/guide/identity-verification/face-match-api" rel="noreferrer">Face Match</a>, and <a href="https://docs.videosdk.live/react/guide/identity-verification/face-spoof-detection" rel="noreferrer">Face Spoof Detection</a> as REST APIs. The agent app calls these after capturing document images during the live session.</p><p><strong>Cloud recording storage:</strong> <code>startRecording()</code> is called from <code>useMeeting</code> and accepts a <code>webhookUrl</code> and <code>awsDirPath</code>. Completed recordings are accessible via the VideoSDK developer dashboard and can also be routed to the bank's own S3-compatible bucket.</p><p><strong>Core banking integration:</strong> Verified identity data and the recording reference are written back to the CBS via an internal API call after the session ends.</p><h2 id="building-the-member-app-with-react-native">Building the member app with React Native</h2><h3 id="installation">Installation</h3><p>Create a new React Native project and install the required packages:</p><pre><code class="language-bash">npx react-native init VKYCMemberApp
npm install "@videosdk.live/react-native-sdk" "@videosdk.live/react-native-incallmanager"</code></pre><p>Register the VideoSDK service in <code>index.js</code> before any other import:</p><pre><code class="language-js">// index.js
import { AppRegistry } from "react-native";
import App from "./App";
import { name as appName } from "./app.json";
import { register } from "@videosdk.live/react-native-sdk";

register();
AppRegistry.registerComponent(appName, () =&gt; App);</code></pre><h3 id="creating-and-joining-a-room">Creating and joining a room</h3><p>The <code>MeetingProvider</code> component wraps the session. It accepts a <code>config</code> object and an authentication <code>token</code>. The <code>meetingId</code> is obtained from your backend, which calls <code>POST https://api.videosdk.live/v2/rooms</code> using your VideoSDK API key.</p><pre><code class="language-js">// App.js
import React, { useState } from "react";
import {
  MeetingProvider,
  useMeeting,
  useParticipant,
  MediaStream,
  RTCView,
} from "@videosdk.live/react-native-sdk";

export default function App() {
  const [meetingId, setMeetingId] = useState(null);

  // meetingId comes from your backend after calling POST /v2/rooms
  return meetingId ? (
    &lt;MeetingProvider
      config={{
        meetingId,
        name: "Customer",
        micEnabled: true,
        webcamEnabled: true,
        maxResolution: "hd",
      }}
      token={"&lt;your-auth-token&gt;"}
    &gt;
      &lt;KYCSessionView /&gt;
    &lt;/MeetingProvider&gt;
  ) : (
    &lt;JoinScreen onJoin={setMeetingId} /&gt;
  );
}</code></pre><h3 id="streaming-the-camera-and-joining">Streaming the camera and joining</h3><p>Inside <code>MeetingProvider</code>, use the <code>useMeeting</code> hook to call <code>join()</code> and access participants:</p><pre><code class="language-js">// KYCSessionView.js
import { useMeeting, useParticipant, MediaStream, RTCView } from "@videosdk.live/react-native-sdk";
import { View, Button } from "react-native";

function ParticipantView({ participantId }) {
  const { webcamStream, webcamOn } = useParticipant(participantId);

  return webcamOn &amp;&amp; webcamStream ? (
    &lt;RTCView
      streamURL={new MediaStream([webcamStream.track]).toURL()}
      objectFit="cover"
      style={{ height: 300, marginVertical: 8 }}
    /&gt;
  ) : (
    &lt;View style={{ height: 300, backgroundColor: "#ccc" }} /&gt;
  );
}

function KYCSessionView() {
  const { join, leave, participants } = useMeeting({
    onMeetingJoined: () =&gt; console.log("Session started"),
    onParticipantLeft: (participant, reason) =&gt; {
      // reason.code maps to Constants.leaveReason values
      console.log("Participant left, reason code:", reason.code);
    },
    onError: (data) =&gt; {
      const { code, message } = data;
      console.error(`VideoSDK error ${code}: ${message}`);
    },
  });

  const participantIds = [...participants.keys()];

  return (
    &lt;View style={{ flex: 1 }}&gt;
      {participantIds.map((id) =&gt; (
        &lt;ParticipantView key={id} participantId={id} /&gt;
      ))}
      &lt;Button title="Join Session" onPress={() =&gt; join()} /&gt;
      &lt;Button title="End Session" onPress={() =&gt; leave()} /&gt;
    &lt;/View&gt;
  );
}</code></pre><p>The <code>onParticipantLeft</code> callback receives a <code>reason</code> object. The SDK documents reason code <code>1001</code> as <code>WEBSOCKET_DISCONNECTED</code> and <code>1102</code> as <code>WEBSOCKET_CONNECTION_ATTEMPTS_EXHAUSTED</code>. Use these to distinguish intentional disconnects from network drops, which is important for V-CIP audit trail continuity.</p><h2 id="document-verification-with-videosdk-ocr-and-face-apis">Document verification with VideoSDK OCR and face APIs</h2><p>During the live session, the agent captures a frame of the customer's document. VideoSDK provides three REST APIs for identity verification. These are called from your server or the agent app's backend, not directly from the client.</p><p><a href="https://docs.videosdk.live/android/guide/identity-verification/ocr" rel="noreferrer"><strong>OCR API</strong></a><strong>:</strong> Extracts text fields from an image of an Aadhaar, PAN, Voter ID, or Passport. The agent captures a screenshot frame during the live call and sends it as a base64 image to the OCR endpoint.</p><p><a href="https://docs.videosdk.live/react/guide/identity-verification/face-match-api" rel="noreferrer"><strong>Face Match API</strong></a><strong>:</strong> Compares two facial images, typically the live video frame and the photo on the document. Returns a similarity score. Use this to confirm the person on the call matches the document holder.</p><p><a href="https://docs.videosdk.live/react/guide/identity-verification/face-spoof-detection" rel="noreferrer"><strong>Face Spoof Detection API (Liveness Check)</strong></a><strong>:</strong> Detects whether the face presented is a live person or a static image or video replay. This is an explicit requirement in the <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc" rel="noreferrer">RBI V-CIP guidelines</a>, which state that liveness must be verified during the session.</p><p><strong>Note:</strong> The specific request/response schemas for these APIs (endpoint paths, field names, and response structure) are listed under the Identity Verification section in the VideoSDK developer dashboard and API reference. The navigation link for this section appeared in the VideoSDK docs quickstart page as "Identity Verification OCR API / Face Match API / Face Spoof Detection API / Number of Face Detection API". Verify the exact endpoint paths from your VideoSDK dashboard API reference before implementation, as they may require a separate entitlement under your VideoSDK plan.</p><p>A typical server-side call pattern in Node.js:</p><pre><code class="language-js">// server/verifyDocument.js
async function runOCR(base64Image, documentType) {
  const response = await fetch("https://api.videosdk.live/v2/ocr", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `${process.env.VIDEOSDK_TOKEN}`,
    },
    body: JSON.stringify({
      image: base64Image,
      documentType, // e.g. "aadhaar", "pan"
    }),
  });
  return response.json();
}</code></pre><p>Store the OCR result, face match score, and liveness result against the session's <code>meetingId</code>. This becomes part of the V-CIP audit record.</p><h2 id="agent-interface-with-react">Agent interface with React</h2><p>The bank agent uses a browser-based React app. The <code>@videosdk.live/react-sdk</code> package provides the same <code>useMeeting</code> and <code>useParticipant</code> hooks as the React Native SDK. The agent can see the customer's video stream, trigger recording, and capture frames.</p><pre><code class="language-js">// AgentApp.jsx
import {
  MeetingProvider,
  useMeeting,
  useParticipant,
  MediaStream,
} from "@videosdk.live/react-sdk";

function AgentView() {
  const { startRecording, stopRecording, participants } = useMeeting({
    onRecordingStarted: () =&gt; console.log("Recording started"),
    onRecordingStopped: () =&gt; console.log("Recording stopped"),
    onParticipantJoined: (p) =&gt; console.log("Customer joined:", p.displayName),
    onParticipantLeft: (participant, reason) =&gt; {
      // reason.code 1102 means connection attempts exhausted (network loss)
      if (reason.code === 1102) {
        alert("Customer connection lost. Session may need to be restarted.");
      }
    },
  });

  const handleStartRecording = () =&gt; {
    const webhookUrl = "https://your-bank-backend.com/webhooks/recording";
    const awsDirPath = `kyc-recordings/${new Date().toISOString().slice(0, 10)}/`;
    startRecording(webhookUrl, awsDirPath);
  };

  const participantIds = [...participants.keys()];

  return (
    &lt;div&gt;
      &lt;button onClick={handleStartRecording}&gt;Start Recording&lt;/button&gt;
      &lt;button onClick={() =&gt; stopRecording()}&gt;Stop Recording&lt;/button&gt;
      {participantIds.map((id) =&gt; (
        &lt;RemoteVideo key={id} participantId={id} /&gt;
      ))}
    &lt;/div&gt;
  );
}</code></pre><p>The <code>startRecording</code> method accepts <code>webhookUrl</code> and <code>awsDirPath</code> as verified from the React Native docs (same API surface exists in the React SDK). The <code>webhookUrl</code> receives a POST callback when the recording is processed and ready for download. This is how the bank backend gets notified to archive the file.</p><h2 id="network-resilience-for-rural-areas">Network resilience for rural areas</h2><p>Many cooperative bank members are in semi-urban or rural areas where <a href="https://www.videosdk.live/blog/make-video-calls-work-in-low-connectivity-areas" rel="noreferrer">bandwidth fluctuates</a>. VideoSDK uses WebRTC's built-in <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">adaptive bitrate</a> (ABR) mechanism. ABR adjusts resolution and frame rate automatically based on available bandwidth without any SDK configuration. The <code>maxResolution</code> field in <code>MeetingProvider</code> config sets the ceiling but the actual bitrate adapts downward as needed.</p><p>For session continuity, handle the <code>onError</code> callback and the <code>onParticipantLeft</code> reason codes:</p><pre><code class="language-js">const { join } = useMeeting({
  onError: (data) =&gt; {
    const { code, message } = data;
    // Code 1102: WEBSOCKET_CONNECTION_ATTEMPTS_EXHAUSTED
    // Prompt the user to check their network and rejoin
    if (code === 1102) {
      setSessionStatus("Connection lost. Please check your internet and tap Rejoin.");
    }
  },
  onParticipantLeft: (participant, reason) =&gt; {
    if (reason.code === 1001) {
      // WEBSOCKET_DISCONNECTED: transient drop, may auto-reconnect
      setSessionStatus("Connection interrupted. Attempting to restore...");
    }
    if (reason.code === 1102) {
      // Multiple reconnect attempts exhausted: user must manually rejoin
      setSessionStatus("Session disconnected. Please rejoin.");
    }
  },
});</code></pre><p>For V-CIP compliance, if a session drops before the document capture and liveness check are complete, the session must be marked incomplete in your CBS. Do not mark the KYC as verified based on a partial session.</p><p>A minimum recommended connection for V-CIP is around 1 Mbps upload and download for standard definition video. For HD video with <code>maxResolution: "hd"</code>, plan for at least 2.5 Mbps. These are practical estimates based on WebRTC codec behaviour.</p><h2 id="compliance-and-audit">Compliance and audit</h2><h3 id="recording">Recording</h3><p><code>startRecording(webhookUrl, awsDirPath)</code> initiates server-side cloud recording. The <code>awsDirPath</code> argument tells VideoSDK where to store the file in an S3-compatible bucket you specify. Recording state changes fire <code>onRecordingStarted</code>, <code>onRecordingStopped</code>, and <code>onRecordingStateChanged</code> events, all verified from the docs.</p><p>The <code>onRecordingStateChanged</code> callback receives a <code>status</code> field. Status values map to <code>Constants.recordingEvents.RECORDING_STARTING</code>, <code>RECORDING_STARTED</code>, <code>RECORDING_STOPPING</code>, and <code>RECORDING_STOPPED</code>.</p><h3 id="geo-fencing">Geo-fencing</h3><p>VideoSDK provides two built-in location controls, both documented under "<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/geo-fencing-and-proxy-controls/geo-fencing" rel="noreferrer">Geo Fencing &amp; Proxy Controls</a>" for both the React and React Native SDKs, and both available on the Enterprise plan only.</p><p><strong>Geo Fencing</strong> pins the session's media servers to a specific region (INDIA, USA, UAE, EUROPE, SINGAPORE, or AUSTRALIA), ensuring that media data does not traverse outside that region regardless of where participants physically connect from. For a cooperative bank's V-CIP deployment, set this to <code>INDIA</code> to ensure all session data stays on VideoSDK's India-region infrastructure.</p><p><a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/geo-fencing-and-proxy-controls/geo-ip-restriction" rel="noreferrer"><strong>Geo IP Restriction</strong></a> goes further: it checks each participant's IP address at connection time and denies the join attempt if their IP resolves to a country outside the allowed region. Configuring this to <code>INDIA</code> means a customer attempting to join from an overseas IP will be blocked at the platform level before the session starts.</p><p>Both features are configured at the room/session level on the <a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK platform</a> and require the Enterprise plan. Contact VideoSDK sales for access. Note that IP-based geolocation is not infallible. A customer using a VPN with a non-India exit node could be incorrectly blocked, or a VPN user abroad could slip through. For full <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc" rel="noreferrer">RBI V-CIP compliance</a>, supplement Geo IP Restriction with a device-side GPS check using React Native's <code>Geolocation</code> API as a secondary control.</p><h3 id="end-to-end-encryption">End-to-end encryption</h3><p>VideoSDK uses DTLS-SRTP for all media in transit as the baseline security layer. Beyond this, VideoSDK also supports <a href="https://www.videosdk.live/blog/what-is-end-to-end-encryption-e2ee" rel="noreferrer"><strong>E2EE</strong> (end-to-end encryption)</a> as a documented SDK feature, available from React Native SDK version 0.2.1 onwards.</p><p>E2EE encrypts media entirely on the sender's device using a shared key you manage. VideoSDK servers never access or store the encryption key, so the media content is opaque to VideoSDK's infrastructure.</p><p>To enable E2EE in the agent's React app, pass an <code>ExternalE2EEKeyProvider</code> instance as the <code>keyProvider</code> prop to <code>MeetingProvider</code>:</p><pre><code class="language-js">import {
  MeetingProvider,
  ExternalE2EEKeyProvider,
} from "@videosdk.live/react-sdk";
import { useMemo } from "react";

const keyProvider = useMemo(() =&gt; {
  const _keyProvider = new ExternalE2EEKeyProvider();
  // Key must be fetched securely from your server, never hardcoded
  _keyProvider.setSharedKey("&lt;secure-key-from-your-server&gt;");
  return _keyProvider;
}, []);

return (
  &lt;MeetingProvider
    config={{ meetingId, micEnabled: true, webcamEnabled: true, name: "Agent" }}
    token={"&lt;auth-token&gt;"}
    keyProvider={keyProvider || null}
  &gt;
    {/* agent view */}
  &lt;/MeetingProvider&gt;
);</code></pre><p>The same <code>keyProvider</code> prop pattern applies in the React Native member app using <code>@videosdk.live/react-native-sdk</code>.</p><p>You can verify whether E2EE is active using <code>const { isE2EEEnabled } = useMeeting()</code>, and monitor per-participant encryption state via the <code>onE2EEStateChanged</code> callback on <code>useParticipant</code>, which returns <code>stateInfo.state</code> values such as <code>EncryptionSuccess</code>, <code>DecryptionFailed</code>, and <code>MissingKey</code>.</p><p>You are fully responsible for generating, distributing, and rotating the encryption key. VideoSDK recommends generating the key on your server when creating a session and delivering it to clients via a secured HTTPS call alongside the meeting token.</p><p><strong>Critical constraint for V-CIP:</strong> The VideoSDK docs explicitly state that recording and transcription are not supported when E2EE is enabled. Since RBI V-CIP requires mandatory session recording, you cannot enable E2EE and <code>startRecording()</code> in the same session. Cooperative banks must choose between E2EE and compliant cloud recording. For most V-CIP deployments, DTLS-SRTP in transit combined with encrypted storage of recordings at rest is the practical path. If your security policy mandates E2EE, consult your compliance team on whether a locally recorded and encrypted session satisfies the RBI storage requirement.</p><h3 id="data-retention">Data retention</h3><p>RBI V-CIP guidelines require be maintained for at least five years after the business relationship ends, or five years from the date of the transaction, whichever is later. Implement a lifecycle policy on your S3 bucket to move recordings to lower-cost storage tiers after 90 days and retain them for five years minimum.  The RBI Master Direction explicitly states that the data and recordings of V-CIP must be stored in India-based, safe, and secure systems. All audio-video recordings must be stored securely in India. VideoSDK's developer dashboard also stores recordings but retention periods there are governed by your VideoSDK plan, not by RBI rules. Use <code>awsDirPath</code> to route recordings to your own bucket for full control.</p><h3 id="audit-log-fields">Audit log fields</h3><p>For each completed V-CIP session, write the following to your CBS:</p><ul><li><code>meetingId</code> (VideoSDK session identifier)</li><li>Customer account number and name</li><li>Agent employee ID</li><li>Session start and end timestamps</li><li>OCR result and extracted document fields</li><li>Face match score</li><li>record the <strong>concurrent audit status and auditor ID</strong></li><li>Liveness check result (pass/fail)</li><li>Recording file URL or object path</li><li>Customer geo-coordinates at session start</li></ul><h2 id="key-takeaways">Key takeaways</h2><ul><li>Cooperative banks regulated by RBI, including UCBs and state cooperative banks, must comply with the RBI KYC Master Direction, which permits V-CIP as a valid identification method.</li><li>VideoSDK's <code>@videosdk.live/react-native-sdk</code> provides <code>MeetingProvider</code>, <code>useMeeting</code>, <code>useParticipant</code>, and <code>RTCView</code> as the core primitives for the member app.</li><li><code>startRecording(webhookUrl, awsDirPath)</code> from <code>useMeeting</code> starts server-side recording and can route files to your own S3 bucket for compliant long-term storage.</li><li><code>onParticipantLeft(participant, reason)</code> with reason codes <code>1001</code> (WEBSOCKET_DISCONNECTED) and <code>1102</code> (WEBSOCKET_CONNECTION_ATTEMPTS_EXHAUSTED) lets you distinguish transient drops from terminal disconnects and respond accordingly in the UI.</li><li>VideoSDK provides Geo Fencing (server region pinning) and Geo IP Restriction (IP-based participant blocking) as built-in platform features under the Enterprise plan, both available for React Native and React SDK projects. </li><li>VideoSDK supports E2EE as a documented SDK feature from React Native 0.2.1 onwards, using <code>ExternalE2EEKeyProvider</code> passed as <code>keyProvider</code> to <code>MeetingProvider</code>. However, the docs explicitly state that recording is not supported when E2EE is enabled, which conflicts directly with RBI's V-CIP mandatory recording requirement. Cooperative banks must choose one or the other per session.</li></ul><h2 id="frequently-asked-questions">Frequently asked questions</h2><p><strong>Q1. Is VideoSDK suitable for cooperative banks with limited IT infrastructure?</strong></p><p>Yes. VideoSDK is a cloud-hosted service. The bank does not need to provision or operate media servers or TURN/STUN infrastructure. The React Native member app runs on any Android 8.0+ or iOS 12.0+ device. The agent interface runs in a modern browser. Your bank's IT team needs to maintain only the application layer: the frontend apps, a lightweight token-generation backend, and the CBS integration script. This makes it practical for cooperative banks that do not have a dedicated DevOps team.</p><p><strong>Q2. What is the minimum internet speed required for a V-CIP session?</strong></p><p>A reliable V-CIP session requires approximately 1 Mbps symmetric (upload and download) for standard definition. For HD sessions set via <code>maxResolution: "hd"</code> in <code>MeetingProvider</code>, plan for around 2.5 Mbps. VideoSDK's WebRTC-based adaptive bitrate will reduce resolution automatically on constrained connections. Sessions below roughly 300 Kbps will likely result in frozen frames or disconnection. RBI does not specify a minimum bandwidth in its V-CIP guidelines, but the practical minimum is dictated by WebRTC codec behaviour.</p><p><strong>Q3. Can V-CIP sessions be conducted in regional languages?</strong></p><p>Yes. VideoSDK handles only audio and video transport. The language spoken during the session is entirely determined by the bank agent and customer. Your agent application can display prompts, instructions, and UI labels in any language. For text overlays or real-time translation features, those must be built at the application layer. The SDK itself is language-agnostic.</p><p><strong>Q4. How long are V-CIP recordings retained?</strong></p><p>VideoSDK's platform stores recordings for a period determined by your VideoSDK plan. However, RBI V-CIP guidelines require that cooperative banks retain KYC records for at least five years after the account relationship ends. You must use the <code>awsDirPath</code> parameter in <code>startRecording()</code> to route recordings to your own S3-compatible bucket and apply a five-year retention policy there. Do not rely on VideoSDK's platform storage as your primary archive for regulatory compliance.</p><p><strong>Q5. Is there a free tier available for VideoSDK?</strong></p><p>VideoSDK offers a free tier for development and testing. Check the current limits at videosdk.live/pricing, as quota and plan details change. For production V-CIP deployments at a cooperative bank, you will need a paid plan that supports cloud recording, the Identity Verification APIs (OCR, Face Match, Liveness), and the participant counts appropriate for your projected session volume.</p><h2 id="conclusion">Conclusion</h2><p>Building a <a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">compliant video KYC system</a> for a cooperative bank in India requires accurate regulatory context, verified SDK integration, and a clear data retention strategy. Cooperative banks subject to the RBI KYC Master Direction can use VideoSDK to implement a full V-CIP workflow: a React Native member app for customers, a React web app for agents, server-side recording with <code>startRecording()</code>, and identity verification via the OCR, Face Match, and Spoof Detection APIs. For any cooperative bank implementing video KYC in India, the RBI V-CIP circular (RBI/2019-20/128 and subsequent updates) remains the authoritative compliance reference, and this technical implementation must be reviewed against your bank's legal and compliance team's interpretation of those guidelines.</p>]]></content:encoded></item><item><title><![CDATA[How to Integrate Liveness Detection in Android and iOS Video KYC Apps]]></title><description><![CDATA[Learn how to add liveness detection to your Android and iOS KYC app using VideoSDK's Face Spoof Detection API. Covers passive spoof detection, Kotlin and Swift integration, result handling, and face match chaining.]]></description><link>https://www.videosdk.live/blog/liveness-detection-android-ios-video-kyc</link><guid isPermaLink="false">69fae62c55831517a5a9f7bb</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 06 May 2026 07:56:54 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/8.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/05/8.png" alt="How to Integrate Liveness Detection in Android and iOS Video KYC Apps"/><p>Know Your Customer (KYC) flows have moved to <a href="https://www.videosdk.live/solutions/video-banking" rel="noreferrer">video banking</a>. Users hold up their ID, look at the camera, and verification happens in real time. That convenience creates a new attack surface: anyone can try to spoof the camera with a printed photo, a looped video, or a screen replay. Liveness detection is the countermeasure. It confirms that the face in the frame belongs to a live person, not a static artifact.</p><p>VideoSDK provides a <strong>Face Spoof Detection API</strong> as part of its identity verification suite. It is a passive approach: you capture a single frame from the live video stream, POST it to the API, and receive a <code>spoof_detected</code> boolean with an accuracy score. No challenge-response gestures are needed, which keeps the user experience smooth.</p><p>This guide shows you how to wire that API into an Android (Kotlin) and iOS (Swift) KYC app using the VideoSDK Android SDK and iOS SDK respectively.</p><blockquote><strong>Note:</strong> The <a href="https://docs.videosdk.live/react/guide/identity-verification/face-spoof-detection" rel="noreferrer">Face Spoof Detection API</a> is available on the VideoSDK Enterprise plan only.</blockquote><h3 id="what-is-liveness-detection-in-kyc">What Is Liveness Detection in KYC?</h3><p><a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">Liveness detection</a> decides whether the face presented to a camera comes from a real, physically present person.</p><p>There are two broad approaches:</p><p><strong>Active liveness</strong> asks the user to perform an action: blink, turn their head, smile. It is explicit, but adds friction and can frustrate users on mobile.</p><p><strong>Passive liveness</strong> analyzes a single frame or short buffer for artefacts that indicate spoofing: texture anomalies, reflections from a screen, depth inconsistencies, or print dot patterns. The user does nothing extra.</p><p><a href="https://docs.videosdk.live/react/guide/identity-verification/face-spoof-detection" rel="noreferrer">VideoSDK's Face Spoof Detection API</a> uses both <strong>active liveness</strong> and <strong>passive liveness</strong> analysis. You send one JPEG frame, the model runs inference, and you receive <code>spoof_detected: true</code> or <code>false</code>. No gesture prompts are required on your end.</p><h3 id="videosdk-face-spoof-detection-api">VideoSDK Face Spoof Detection API</h3><p>This section documents the exact endpoint and payload, verified from the VideoSDK docs.</p><p><strong>Endpoint</strong></p><pre><code class="language-bash">POST https://api.videosdk.live/ai/v1/face-verification/detect-spoof</code></pre><p>Headers</p><pre><code class="language-bash">Authorization: &lt;YOUR_JWT_TOKEN&gt;   // No "Bearer" prefix, just the raw token
Content-Type: application/json</code></pre><p>The JWT token is generated from your VideoSDK <a href="https://www.videosdk.live/blog/api-key-vs-api-token" rel="noreferrer">API key and secret</a>. See the <a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">VideoSDK auth token guide</a> for details.</p><p><strong>Request body</strong></p><p>Images must be&nbsp;<a href="https://en.wikipedia.org/wiki/Base64" rel="noreferrer nofollow">Base64</a>-encoded with the&nbsp;<a href="https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Schemes/data" rel="noreferrer nofollow">data-URI prefix</a>&nbsp;before being placed in the JSON body:</p><pre><code class="language-json">{
  "img": "data:image/jpeg;base64,${Base64data}"
}</code></pre><p>Response</p><pre><code class="language-json">{
  "spoof_detected": true,
  "accuracy": 0.9899068176746368
}</code></pre><p><code>spoof_detected: true</code> means a spoof was detected. <code>spoof_detected: false</code> means the face appears to be live. The <code>accuracy</code> field reflects the model's confidence in its classification.</p><p>Both the <a href="https://docs.videosdk.live/react/guide/identity-verification/face-spoof-detection" rel="noreferrer">Face Spoof Detection API</a> and the <a href="https://docs.videosdk.live/react/guide/identity-verification/face-match-api" rel="noreferrer">Face Match API</a> (covered in the combination section) require JPEG images encoded as Base64 with the <code>data:image/jpeg;base64,</code> prefix.</p><h3 id="android-integration">Android Integration</h3><h4 id="setting-up-the-videosdk-android-sdk">Setting Up the VideoSDK Android SDK</h4><p>Add the VideoSDK repository to your <code>settings.gradle</code>:</p><pre><code class="language-groovy">dependencyResolutionManagement {
    repositories {
        google()
        maven { url 'https://jitpack.io' }
        mavenCentral()
        maven { url "https://maven.aliyun.com/repository/jcenter" }
    }
}</code></pre><p>Add the SDK dependency to <code>app/build.gradle</code>:</p><pre><code class="language-groovy">implementation 'live.videosdk:rtc-android-sdk:0.3.0'</code></pre><p>Add permissions to <code>AndroidManifest.xml</code>:</p><pre><code class="language-xml">&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /&gt;
&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
&lt;uses-permission android:name="android.permission.CAMERA" /&gt;</code></pre><p>Initialize the SDK in <code>MainApplication.kt</code>:</p><pre><code class="language-kotlin">import live.videosdk.rtc.android.VideoSDK

class MainApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        VideoSDK.initialize(applicationContext)
    }
}</code></pre><h4 id="joining-a-meeting-and-initializing-the-video-stream">Joining a Meeting and Initializing the Video Stream</h4><p>In <code>MeetingActivity.kt</code>, configure the SDK with your token, call <code>VideoSDK.initMeeting()</code>, attach a <code>MeetingEventListener</code>, and join:</p><pre><code class="language-kotlin">// 1. Configure VideoSDK with the JWT token
VideoSDK.config(token)

// 2. Initialize the meeting
meeting = VideoSDK.initMeeting(
    this@MeetingActivity, meetingId, participantName,
    micEnabled, webcamEnabled, null, null, false, null, null
)

// 3. Add the event listener
meeting!!.addEventListener(meetingEventListener)

// 4. Join the room
meeting!!.join()</code></pre><h4 id="capturing-a-frame-and-calling-the-face-spoof-detection-api">Capturing a Frame and Calling the Face Spoof Detection API</h4><p>The <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/integrate-sdk" rel="noreferrer">VideoSDK Android SDK</a> exposes video through <code>VideoTrack</code> objects accessible via each <code>Participant</code>'s <code>Stream</code> map. To capture a still frame for liveness checking, draw the track's current output onto a <code>Bitmap</code> using the <code>VideoView</code> component, then compress to JPEG and Base64-encode it.</p><p>The full flow looks like this in Kotlin:</p><pre><code class="language-kotlin">import live.videosdk.rtc.android.VideoSDK
import live.videosdk.rtc.android.VideoView
import org.webrtc.VideoTrack
import android.graphics.Bitmap
import android.util.Base64
import java.io.ByteArrayOutputStream
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.net.HttpURLConnection
import java.net.URL
import org.json.JSONObject

/**
 * Capture the current frame from a VideoView and run spoof detection.
 * videoView - the live.videosdk.rtc.android.VideoView rendering the local participant.
 */
suspend fun runSpoofDetection(videoView: VideoView, token: String): Boolean {
    // Step 1: Draw the current VideoView frame into a Bitmap
    val bitmap = Bitmap.createBitmap(videoView.width, videoView.height, Bitmap.Config.ARGB_8888)
    val canvas = android.graphics.Canvas(bitmap)
    videoView.draw(canvas)

    // Step 2: Compress to JPEG and Base64-encode
    val outputStream = ByteArrayOutputStream()
    bitmap.compress(Bitmap.CompressFormat.JPEG, 85, outputStream)
    val base64Frame = Base64.encodeToString(outputStream.toByteArray(), Base64.NO_WRAP)
    val dataUri = "data:image/jpeg;base64,$base64Frame"

    // Step 3: POST to Face Spoof Detection API
    return withContext(Dispatchers.IO) {
        val url = URL("https://api.videosdk.live/ai/v1/face-verification/detect-spoof")
        val connection = url.openConnection() as HttpURLConnection
        connection.requestMethod = "POST"
        connection.setRequestProperty("Authorization", token)
        connection.setRequestProperty("Content-Type", "application/json")
        connection.doOutput = true

        val body = JSONObject().apply { put("img", dataUri) }.toString()
        connection.outputStream.use { it.write(body.toByteArray()) }

        val responseCode = connection.responseCode
        if (responseCode == 200) {
            val response = connection.inputStream.bufferedReader().readText()
            val json = JSONObject(response)
            // true means spoof detected, false means real face
            json.getBoolean("spoof_detected")
        } else {
            throw RuntimeException("Spoof detection failed with HTTP $responseCode")
        }
    }
}</code></pre><p>Call this function from within <code>onMeetingJoined()</code> or at the point in your KYC flow where you want to verify liveness:</p><pre><code class="language-kotlin">// Inside a coroutine scope, e.g. viewModelScope or lifecycleScope
val spoofDetected = runSpoofDetection(localVideoView, sampleToken)
if (spoofDetected) {
    showSpoofAlert()  // Block the KYC flow
} else {
    proceedToDocumentCapture()
}</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-6--2026--12_50_25-PM.png" class="kg-image" alt="How to Integrate Liveness Detection in Android and iOS Video KYC Apps" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Flow diagram for Android liveness</span></figcaption></img></figure><h3 id="ios-integration">iOS Integration</h3><h4 id="setting-up-the-videosdk-ios-sdk">Setting Up the VideoSDK iOS SDK</h4><p>Create a <code>Podfile</code> in your project root and add the VideoSDK dependency:</p><pre><code class="language-ruby">pod 'VideoSDKRTC', :git =&gt; 'https://github.com/videosdk-live/videosdk-rtc-ios-sdk.git'</code></pre><p>Run <code>pod install</code>, then add permissions to <code>Info.plist</code>:</p><pre><code class="language-xml">&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
&lt;string&gt;Camera permission description&lt;/string&gt;
&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;Microphone permission description&lt;/string&gt;</code></pre><h4 id="joining-a-meeting-in-swift">Joining a Meeting in Swift</h4><p>In <code>MeetingViewController.swift</code>, import the SDK and configure it with your token before calling <code>VideoSDK.initMeeting()</code>:</p><pre><code class="language-swift">import UIKit
import VideoSDKRTC
import WebRTC

class MeetingViewController: UIViewController {

    private var meeting: Meeting?

    private func initializeMeeting() {
        // Configure VideoSDK with the JWT token
        VideoSDK.config(token: meetingData.token)

        // Initialize the meeting
        meeting = VideoSDK.initMeeting(
            meetingId: meetingData.meetingId,
            participantName: meetingData.name,
            micEnabled: meetingData.micEnabled,
            webcamEnabled: meetingData.cameraEnabled
        )

        // Add event listener and join
        meeting?.addEventListener(self)
        meeting?.join()
    }
}</code></pre><h4 id="capturing-a-frame-and-calling-the-face-spoof-detection-api-1">Capturing a Frame and Calling the Face Spoof Detection API</h4><p>In the iOS SDK, video streams are delivered via <code>RTCVideoTrack</code> objects. When <code>onStreamEnabled(_:forParticipant:)</code> fires with <code>stream.kind == .state(value: .video)</code>, you can cast <code>stream.track</code> to <code>RTCVideoTrack</code> and use a custom <code>RTCVideoRenderer</code> to pull the latest pixel buffer. A simpler approach for a single KYC frame is to render the <code>RTCMTLVideoView</code> into a <code>UIImage</code> using <code>UIGraphicsImageRenderer</code>.</p><pre><code class="language-swift">import VideoSDKRTC
import WebRTC

extension MeetingViewController {

    /// Capture the current frame from the local participant's video view.
    func captureFrameAsBase64(from videoView: RTCMTLVideoView) -&gt; String? {
        let renderer = UIGraphicsImageRenderer(bounds: videoView.bounds)
        let image = renderer.image { _ in
            videoView.drawHierarchy(in: videoView.bounds, afterScreenUpdates: true)
        }
        guard let jpegData = image.jpegData(compressionQuality: 0.85) else { return nil }
        return "data:image/jpeg;base64," + jpegData.base64EncodedString()
    }

    /// Call the VideoSDK Face Spoof Detection API with a captured frame.
    func runSpoofDetection(token: String, base64Image: String,
                           completion: @escaping (Bool?, Error?) -&gt; Void) {
        let url = URL(string: "https://api.videosdk.live/ai/v1/face-verification/detect-spoof")!
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.addValue(token, forHTTPHeaderField: "Authorization")
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")

        let body: [String: Any] = ["img": base64Image]
        request.httpBody = try? JSONSerialization.data(withJSONObject: body)

        URLSession.shared.dataTask(with: request) { data, _, error in
            if let error = error { completion(nil, error); return }
            guard let data = data,
                  let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
                  let spoofDetected = json["spoof_detected"] as? Bool else {
                completion(nil, nil); return
            }
            completion(spoofDetected, nil)
        }.resume()
    }

    /// Trigger liveness check from your KYC step.
    func performLivenessCheck() {
        guard let base64 = captureFrameAsBase64(from: localParticipantVideoView) else { return }
        runSpoofDetection(token: TOKEN_STRING, base64Image: base64) { spoofDetected, error in
            DispatchQueue.main.async {
                if let detected = spoofDetected {
                    detected ? self.showSpoofAlert() : self.proceedToDocumentCapture()
                }
            }
        }
    }
}</code></pre><h3 id="handling-spoof-detection-results">Handling Spoof Detection Results</h3><p>When <code>spoof_detected</code> comes back as <code>true</code>, block the KYC flow immediately. Do not attempt to proceed: a spoofed frame means the identity cannot be trusted. Standard handling options include:</p><p><strong>Retry flow.</strong> Show the user a prompt explaining that the <a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">liveness check</a> failed, ask them to ensure they are in good lighting with their face clearly visible, and trigger a new frame capture. Limit retries to 2-3 attempts before escalating.</p><p><strong>Agent escalation.</strong> In an <a href="https://www.videosdk.live/blog/video-kyc-agent-dashboard" rel="noreferrer">assisted KYC flow</a> where a human agent is watching the video session, use VideoSDK's <a href="https://www.videosdk.live/blog/integrate-chat-using-pubsub-in-ios-video-call-app" rel="noreferrer">PubSub feature</a> to send a message to the agent's UI indicating a failed liveness check. The agent can then take over manually.</p><p><strong>Hard fail.</strong> After maximum retries are exhausted, end the meeting with <code>meeting.leave()</code>, log the session as failed, and require the user to restart the KYC process from scratch.</p><p><strong>Frame quality best practices.</strong> Spoof detection accuracy depends on image quality. Before sending a frame:</p><ul><li>Confirm the face bounding box occupies at least 30-40% of the frame area. If the face is too small, detection accuracy drops.</li><li>Check ambient light. Frames taken in very low light produce noise that can confuse the model.</li><li>Request the user to remove sunglasses or heavy obstructions before KYC begins.</li><li>Use a single clean frame rather than averaging multiple captures. The API is designed for single-image inference.</li></ul><h3 id="combining-liveness-with-face-match">Combining Liveness with Face Match</h3><p>A common KYC pattern runs two checks in sequence:</p><ol><li><strong>Face Spoof Detection</strong> first, to confirm the user is live.</li><li><strong>Face Match API</strong> second, to compare the live face against the face on the uploaded identity document.</li></ol><p>Only call Face Match if spoof detection passes. Running both unconditionally wastes API calls and can produce false confidence if spoof detection is skipped.</p><p>The Face Match API, verified from the VideoSDK docs, uses this endpoint:</p><pre><code class="language-bash">POST https://api.videosdk.live/ai/v1/face-verification/verify</code></pre><p>The request body takes two Base64-encoded images:</p><pre><code class="language-json">{
  "img1": "data:image/jpeg;base64,${liveFrameBase64}",
  "img2": "data:image/jpeg;base64,${idDocumentFaceBase64}"
}</code></pre><p>The response returns a single verified boolean:</p><pre><code class="language-json">{ "verified": true }</code></pre><p><code>verified: true</code> means both images depict the same person. <code>verified: false</code> means they do not match.</p><p>The combined flow in pseudocode:</p><pre><code class="language-kotlin">// Android: sequential check
val spoofDetected = runSpoofDetection(videoView, token)
if (!spoofDetected) {
    val faceMatched = runFaceMatch(liveFrameBase64, idDocumentBase64, token)
    if (faceMatched) {
        markKycPassed()
    } else {
        markKycFailed("Face does not match ID document")
    }
} else {
    markKycFailed("Liveness check failed")
}</code></pre><p>Both APIs accept the same Base64 JPEG format. You can reuse the frame captured for spoof detection as <code>img1</code> in the Face Match request without a second capture.</p><h3 id="key-takeaways">Key Takeaways</h3><ul><li>The VideoSDK Face Spoof Detection API (<code>POST /ai/v1/face-verification/detect-spoof</code>) accepts a single Base64 JPEG and returns <code>spoof_detected</code> plus an <code>accuracy</code> score.</li><li>On Android, initialize the SDK using <code>VideoSDK.initialize(applicationContext)</code> followed by <code>VideoSDK.config(token)</code> and <code>VideoSDK.initMeeting()</code>. Capture frames from <code>VideoView</code> via <code>Canvas</code>.</li><li>On iOS, install via <code>pod 'VideoSDKRTC'</code>. Use <code>VideoSDK.config(token:)</code> and <code>VideoSDK.initMeeting()</code>. Render the <code>RTCMTLVideoView</code> into a <code>UIImage</code> to extract the frame.</li><li>Always run spoof detection before Face Match. A spoofed frame that passes face matching gives false assurance.</li><li>Both identity verification APIs are available on the VideoSDK Enterprise plan only.</li></ul><h3 id="faq">FAQ</h3><p><strong>Q: What image format does the Face Spoof Detection API accept?</strong> </p><p>A: The API accepts JPEG images encoded as Base64 strings with the data-URI prefix <code>data:image/jpeg;base64,</code>. The encoded string is passed as the value of the <code>img</code> field in the JSON request body. Other image formats such as PNG are not explicitly documented for this endpoint; use JPEG for best compatibility.</p><p><strong>Q: What is the typical response time for the Face Spoof Detection API?</strong> </p><p>A: VideoSDK's documentation does not publish a specific latency SLA for the Face Spoof Detection API. In practice, REST AI inference endpoints of this type from cloud providers typically respond in 500ms to 2000ms depending on server load and image size. Test under your expected network conditions and account for this in your KYC flow UI with a loading state.</p><p><strong>Q: Does the Face Spoof Detection API work reliably in low light?</strong> </p><p>A: Low-light conditions reduce the quality of the JPEG frame sent to the API. The model relies on texture and artefact patterns that become harder to detect in a noisy, underexposed image. VideoSDK recommends that you prompt users to be in well-lit environments before beginning KYC. As a code-level guard, you can check average pixel brightness before sending the frame and prompt the user to improve lighting if it falls below a threshold.</p><p><strong>Q: Can the Face Spoof Detection API detect video replay attacks (a phone playing a recorded video)?</strong> </p><p>A: The Face Spoof Detection API analyzes a single JPEG frame for passive liveness artefacts such as screen moiré patterns, reflection glare, and pixel noise typical of a screen-captured face. Video replay attacks that are well-produced may be harder to catch with a single-frame approach. For high-assurance KYC, complement passive liveness with active challenge-response checks or run multiple frames across the session to increase detection confidence. VideoSDK does not publish specific test results for replay attack scenarios in its documentation.</p><h3 id="conclusion">Conclusion</h3><p>Adding liveness detection to a VideoSDK-based video KYC app follows a clear path: join the meeting using the documented Android or iOS SDK setup, capture a frame from the live video view, and POST it to <code>https://api.videosdk.live/ai/v1/face-verification/detect-spoof</code>. The response tells you immediately whether to continue or block. Chain it with the Face Match API for a complete identity verification pipeline. All of the code above uses methods verified directly from the <a href="https://docs.videosdk.live/" rel="noreferrer">VideoSDK documentation</a>.</p><p>For full Android and iOS project examples, see the official VideoSDK quickstart repositories linked in the docs at <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/concept-and-architecture" rel="noreferrer">VideoSDK Docs Android</a> and <a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/concept-and-architecture" rel="noreferrer">VideoSDK Docs iOS</a>.</p>]]></content:encoded></item><item><title><![CDATA[Video KYC Agent Dashboard: How to Build an Operator Interface]]></title><description><![CDATA[A step-by-step guide to building a video KYC agent dashboard in React using VideoSDK. Covers session join, customer video feed, remote mic/camera controls, cloud recording, PubSub chat, and frame capture for OCR and face match.]]></description><link>https://www.videosdk.live/blog/video-kyc-agent-dashboard</link><guid isPermaLink="false">69fadb6455831517a5a9f76c</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 06 May 2026 06:47:55 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/6.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/05/6.png" alt="Video KYC Agent Dashboard: How to Build an Operator Interface"/><p><a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">Video KYC</a> has become mandatory for onboarding in banks, <a href="https://www.videosdk.live/blog/video-kyc-for-nbfc-india" rel="noreferrer">NBFCs</a>, <a href="https://www.videosdk.live/blog/irdai-vbip-compliance-guide-for-insurtech" rel="noreferrer">insurance companies</a>, and lending platforms. The customer-facing side of a video KYC session gets most of the attention, but the agent side is where the workflow actually runs.</p><p>The agent, or KYC operator, needs to: join the session, see the customer clearly, control media when needed, capture the ID document frame, trigger verification checks, log notes, record the session, and end it cleanly. All of this needs to happen inside a single, purpose-built interface.</p><h3 id="what-the-agent-dashboard-must-do">What the Agent Dashboard Must Do</h3><p>Before writing a line of code, define what the KYC operator interface is responsible for:</p><p><strong>Join the VideoSDK room as a participant.</strong> The agent joins the same meeting room as the customer. Both are participants with the same underlying SDK primitives.</p><p><strong>View the remote participant's video.</strong> The customer's video stream is the primary signal. It must render reliably, labeled with the customer's name.</p><p><strong>Control remote participant media.</strong> The agent may need to request that the customer enable their camera or mic, or disable it if there is interference. VideoSDK's <code>useParticipant</code> hook exposes <code>enableMic()</code>, <code>disableMic()</code>, <code>enableWebcam()</code>, and <code>disableWebcam()</code> for this purpose.</p><p><strong>Capture a frame for ID verification.</strong> The agent triggers a screenshot from the customer's video track. This base64 image is then sent to an OCR or face match API.</p><p><strong>Start and stop </strong><a href="https://www.videosdk.live/blog/cloud-recording-and-rtmp-pricing" rel="noreferrer"><strong>cloud recording</strong></a><strong>.</strong> The full session must be recorded for regulatory audit. VideoSDK's <code>startRecording()</code> and <code>stopRecording()</code> methods handle this from within the meeting.</p><p><strong>Send and receive in-session messages.</strong> The agent and customer can exchange text using VideoSDK's <code>usePubSub</code> hook over a named topic channel.</p><p><strong>End the session.</strong> The agent calls <code>end()</code> to terminate the meeting for all participants, not just the one <code>leave()</code> which would only remove the local participant.</p><h3 id="setting-up-the-agent-react-app">Setting Up the Agent React App</h3><h4 id="install-the-sdk">Install the SDK</h4><p>The correct npm package name for the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">VideoSDK React SDK</a>, verified from the docs, is:</p><pre><code class="language-bash">npm install @videosdk.live/react-sdk</code></pre><h4 id="auth-token-for-agents">Auth Token for Agents</h4><p>Agents should receive a token from your backend. Tokens can include permissions like <code>allow_join</code>, which lets the agent join directly, or <code>ask_join</code>, which requires approval from another participant.</p><p>For a KYC agent dashboard, use <code>allow_join</code> so the operator can enter the room immediately without a waiting state.</p><pre><code class="language-javascript">// Fetch token from your server
const fetchToken = async () =&gt; {
  const response = await fetch("/api/generate-videosdk-token");
  const { token } = await response.json();
  return token;
};</code></pre><h4 id="wrapping-the-app-with-meetingprovider">Wrapping the App with MeetingProvider</h4><p><code>MeetingProvider</code> is the top-level context wrapper. All hooks inside it have access to the live session.</p><pre><code class="language-jsx">import { MeetingProvider } from "@videosdk.live/react-sdk";

function App() {
  const [token, setToken] = useState(null);
  const meetingId = "your-kyc-room-id";

  return (
    &lt;MeetingProvider
      config={{
        meetingId,
        micEnabled: true,
        webcamEnabled: true,
        name: "KYC Agent",
      }}
      token={token}
      joinWithoutUserInteraction={false}
    &gt;
      &lt;AgentDashboard /&gt;
    &lt;/MeetingProvider&gt;
  );
}</code></pre><h4 id="usemeeting-and-useparticipant-hooks">useMeeting and useParticipant Hooks</h4><p><code>useMeeting</code> is the primary hook for controlling the session itself. It returns methods like <code>join()</code>, <code>end()</code>, <code>startRecording()</code>, <code>stopRecording()</code>, and properties like <code>participants</code>, <code>isRecording</code>, and <code>recordingState</code>. </p><p><code>useParticipant</code> takes a <code>participantId</code> and returns stream access, media control methods, and participant-level stats for that specific user.</p><pre><code class="language-jsx">import { useMeeting, useParticipant } from "@videosdk.live/react-sdk";

function AgentDashboard() {
  const { participants, join, end, startRecording, stopRecording, isRecording } =
    useMeeting({
      onMeetingJoined: () =&gt; console.log("Agent joined"),
      onMeetingLeft: () =&gt; console.log("Session ended"),
      onRecordingStarted: () =&gt; console.log("Recording live"),
      onRecordingStopped: () =&gt; console.log("Recording stopped"),
    });

  // Get the first remote participant (the customer)
  const customerParticipant = [...participants.values()].find(
    (p) =&gt; p.local === false
  );

  return (
    &lt;div&gt;
      {customerParticipant &amp;&amp; (
        &lt;CustomerVideoPane participantId={customerParticipant.id} /&gt;
      )}
    &lt;/div&gt;
  );
}</code></pre><h3 id="displaying-the-customer-video-feed">Displaying the Customer Video Feed</h3><p>The <code>useParticipant</code> hook returns <code>webcamStream</code> and <code>micStream</code> for the given participant. You attach the stream to a <code>&lt;video&gt;</code> element using a <code>ref</code>.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-6--2026--11_49_17-AM.png" class="kg-image" alt="Video KYC Agent Dashboard: How to Build an Operator Interface" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Mockup of a KYC agent dashboard UI</span></figcaption></img></figure><pre><code class="language-jsx">import { useParticipant } from "@videosdk.live/react-sdk";
import { useEffect, useRef } from "react";

function CustomerVideoPane({ participantId }) {
  const { webcamStream, webcamOn, displayName } = useParticipant(participantId);
  const videoRef = useRef(null);

  useEffect(() =&gt; {
    if (videoRef.current &amp;&amp; webcamStream) {
      const mediaStream = new MediaStream();
      mediaStream.addTrack(webcamStream.track);
      videoRef.current.srcObject = mediaStream;
      videoRef.current.play().catch((err) =&gt; console.error(err));
    }
  }, [webcamStream, webcamOn]);

  return (
    &lt;div style={{ position: "relative" }}&gt;
      {webcamOn ? (
        &lt;video ref={videoRef} autoPlay playsInline muted /&gt;
      ) : (
        &lt;div&gt;Customer camera is off&lt;/div&gt;
      )}
      &lt;span style={{ position: "absolute", bottom: 8, left: 8, color: "#fff" }}&gt;
        {displayName}
      &lt;/span&gt;
    &lt;/div&gt;
  );
}</code></pre><p><code>webcamStream</code> is a <code>Stream</code> object. You extract its <code>.t</code><em>te on OCR and Face Match APIs:</em>&nbsp;The<code>ack</code> property and add it to a <code>MediaStream</code> instance before assigning it to the video element. </p><h3 id="remote-participant-controls">Remote Participant Controls</h3><p><code>useParticipant</code> exposes direct media control methods for any participant in the session. These are verified from the VideoSDK documentation:</p><p><code>enableMic()</code>: Sends a request to the participant. They receive an <code>onMicRequested</code> callback and must accept before the mic enables. <code>disableMic()</code>: Disables the participant's mic immediately, without a request flow. <code>enableWebcam()</code>: Sends a request; the participant receives <code>onWebcamRequested</code>. <code>disableWebcam()</code>: Disables the participant's webcam immediately.</p><pre><code class="language-jsx">function AgentControls({ participantId }) {
  const { enableMic, disableMic, disableWebcam, enableWebcam } =
    useParticipant(participantId);

  return (
    &lt;div&gt;
      &lt;button onClick={() =&gt; enableMic()}&gt;Request Mic On&lt;/button&gt;
      &lt;button onClick={() =&gt; disableMic()}&gt;Mute Customer&lt;/button&gt;
      &lt;button onClick={() =&gt; enableWebcam()}&gt;Request Camera On&lt;/button&gt;
      &lt;button onClick={() =&gt; disableWebcam()}&gt;Disable Customer Camera&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><p>One important note: <code>enableMic()</code> and <code>enableWebcam()</code> trigger a permission request on the customer's side. The customer must accept. <code>disableMic()</code> and <code>disableWebcam()</code> are hard overrides that do not require acceptance. Use them carefully and make sure your KYC consent flow covers this use.</p><h3 id="integrating-ocr-and-face-match">Integrating OCR and Face Match</h3><p>VideoSDK's <code>useParticipant</code> hook exposes a <code>captureImage()</code> method that returns a base64-encoded screenshot of the participant's current video stream. </p><pre><code class="language-jsx">function CaptureIDFrame({ participantId, videoSdkToken }) {
  const { captureImage } = useParticipant(participantId);
  const [matchStatus, setMatchStatus] = useState(null);

  const handleCapture = async () =&gt; {
    // captureImage() returns a base64 string — verified from useParticipant docs
    const base64Image = await captureImage({ height: 720, width: 1280 });

    // Format required by VideoSDK Face Match API
    const formattedImage = `data:image/jpeg;base64,${base64Image}`;

    // Step 1: Run OCR via VideoSDK OCR API
    // Endpoint: POST https://api.videosdk.live/ai/v1/ocr (verify exact path in OCR docs)
    // See: https://docs.videosdk.live/react/guide/identity-verification/ocr

    // Step 2: Run Face Match via VideoSDK Face Match API
    // POST https://api.videosdk.live/ai/v1/face-verification/verify
    const faceResponse = await fetch(
      "https://api.videosdk.live/ai/v1/face-verification/verify",
      {
        method: "POST",
        headers: {
          Authorization: videoSdkToken, // JWT token, no "Bearer" prefix
          "Content-Type": "application/json",
        },
        body: JSON.stringify({
          img1: formattedImage,       // Live frame captured from customer video
          img2: idDocumentBase64,     // ID photo extracted from OCR step
        }),
      }
    );

    const faceData = await faceResponse.json();
    // Response shape: { "verified": true } or { "verified": false }
    setMatchStatus(faceData.verified ? "verified" : "failed");
  };

  return (
    &lt;div&gt;
      &lt;button onClick={handleCapture}&gt;Capture ID Frame&lt;/button&gt;
      {matchStatus &amp;&amp; (
        &lt;span style={{ color: matchStatus === "verified" ? "green" : "red" }}&gt;
          {matchStatus === "verified" ? "Face Match: Verified" : "Face Match: Failed"}
        &lt;/span&gt;
      )}
    &lt;/div&gt;
  );
}</code></pre><p><strong>Note:</strong> The VideoSDK Face Match API (<code>POST https://api.videosdk.live/ai/v1/face-verification/verify</code>) is available on the Enterprise plan. The Authorization header takes your VideoSDK JWT token directly, with no "Bearer" prefix. For OCR and Face Spoof Detection, refer to the VideoSDK Identity Verification docs at <a href="https://docs.videosdk.live/react/guide/identity-verification/ocr" rel="noreferrer">OCR API</a> and <a href="https://docs.videosdk.live/react/guide/identity-verification/face-spoof-detection" rel="noreferrer">Face Spoof Detection</a> respectively.</p><h3 id="recording-controls">Recording Controls</h3><p><code>startRecording()</code> and <code>stopRecording()</code> are methods on the <code>useMeeting</code> hook, confirmed from the VideoSDK React SDK docs. Recording state is tracked via <code>isRecording</code> (boolean) and <code>recordingState</code> properties.</p><pre><code class="language-jsx">function RecordingControls() {
  const { startRecording, stopRecording, isRecording } = useMeeting();

  const handleStart = () =&gt; {
    startRecording(
      "https://your-webhook.example.com/recording-done", // webhookUrl
      "/kyc-recordings/", // awsDirPath (optional, for your own S3)
      {
        layout: {
          type: "SPOTLIGHT",
          priority: "PIN",
        },
        theme: "DEFAULT",
        mode: "video-and-audio",
        quality: "high",
      }
    );
  };

  return (
    &lt;div&gt;
      {isRecording ? (
        &lt;button onClick={() =&gt; stopRecording()}&gt;Stop Recording&lt;/button&gt;
      ) : (
        &lt;button onClick={handleStart}&gt;Start Recording&lt;/button&gt;
      )}
      &lt;span&gt;{isRecording ? "REC" : "Idle"}&lt;/span&gt;
    &lt;/div&gt;
  );
}</code></pre><p>When recording stops, the <code>onRecordingStopped</code> event fires on all participants. VideoSDK then processes the file and sends a <code>POST</code> request to your <code>webhookUrl</code> with the recording metadata, including the download URL. You store this URL in your case management system for audit retrieval.</p><p>If you want to store recordings in your own S3 bucket, fill in the <code>awsDirPath</code> parameter and complete the VideoSDK AWS S3 integration form in the dashboard.</p><h3 id="in-session-chat-using-pubsub">In-Session Chat Using PubSub</h3><p><code>usePubSub</code> is the hook for topic-based messaging within a meeting. You call it with a topic string and callback options, and it returns <code>publish</code> and <code>messages</code>.</p><pre><code class="language-jsx">import { usePubSub } from "@videosdk.live/react-sdk";
import { useState } from "react";

function SessionChat() {
  const [input, setInput] = useState("");

  const { publish, messages } = usePubSub("KYC_CHAT", {
    onMessageReceived: (message) =&gt; {
      console.log("New message:", message);
    },
    onOldMessagesReceived: (oldMessages) =&gt; {
      console.log("History loaded:", oldMessages);
    },
  });

  const sendMessage = async () =&gt; {
    if (!input.trim()) return;
    try {
      await publish(input, { persist: true }, null);
      setInput("");
    } catch (e) {
      console.error("PubSub send error:", e);
    }
  };

  return (
    &lt;div&gt;
      &lt;div&gt;
        {messages.map((msg) =&gt; (
          &lt;div key={msg.id}&gt;
            &lt;strong&gt;{msg.senderName}:&lt;/strong&gt; {msg.message}
          &lt;/div&gt;
        ))}
      &lt;/div&gt;
      &lt;input
        value={input}
        onChange={(e) =&gt; setInput(e.target.value)}
        placeholder="Type a message..."
      /&gt;
      &lt;button onClick={sendMessage}&gt;Send&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><p>Each message object returned by <code>usePubSub</code> contains: <code>id</code>, <code>message</code>, <code>senderId</code>, <code>senderName</code>, <code>timestamp</code>, <code>topic</code>, and <code>payload</code>. Setting <code>persist: true</code> in publish options means the message is stored and delivered to any participant who joins mid-session, which is useful for audit continuity.</p><p>Note that <code>message</code> must be a string. Pass any metadata (like document type or step labels) via the <code>payload</code> object, which accepts any serializable object.</p><h3 id="key-takeaways">Key Takeaways</h3><p>Before the FAQ, here is a summary of what matters most when building this KYC operator interface:</p><ul><li>The VideoSDK React SDK package is <code>@videosdk.live/react-sdk</code>. The primary hooks for a KYC agent dashboard are <code>useMeeting</code>, <code>useParticipant</code>, and <code>usePubSub</code>.</li><li>Use <code>end()</code> on the agent side to close the session for everyone. Use <code>leave()</code> only if the agent needs to exit without ending the call.</li><li><code>disableMic()</code> and <code>disableWebcam()</code> from <code>useParticipant</code> disable a remote participant's media without requiring their approval. <code>enableMic()</code> and <code>enableWebcam()</code> send requests that the remote user must accept.</li><li>VideoSDK's <code>captureImage({ height, width })</code> method (on <code>useParticipant</code>) returns a base64 image of the participant's live video stream. This is the correct frame capture mechanism. OCR and face match are handled by your own backend integration.</li><li>Recording download URLs are delivered via webhook after the session ends. Store the webhook payload in your case management system for regulatory audit retrieval.</li></ul><h3 id="faq">FAQ</h3><p><strong>Can multiple agents monitor the same video KYC session?</strong></p><p>Yes. Multiple agents can join the same <code>meetingId</code> as separate participants. Each agent gets their own <code>useMeeting</code> instance in their own browser tab or device. All of them receive the same participant streams and can independently trigger actions like recording controls or chat messages. However, only agents whose token includes <code>allow_join</code> permission can enter without needing approval. You should implement application-level access control on your backend to restrict which agent roles can join a given KYC session.</p><p><strong>How do you handle agent reconnection during a video KYC session?</strong></p><p>If an agent's connection drops, they can re-join the same <code>meetingId</code> using the same token, as long as the meeting is still active. The <code>useMeeting</code> hook reinitializes and re-subscribes to participant streams on join. For state continuity, persist session data (current step, OCR result, face match status) in your backend or a state management store. Do not rely solely on in-memory React state for anything that must survive a page refresh. PubSub messages published with <code>persist: true</code> will also be available to the agent when they rejoin, via the <code>onOldMessagesReceived</code> callback.</p><p><strong>Where are video KYC recordings stored after the session?</strong></p><p>By default, VideoSDK stores recordings on its own infrastructure and delivers the file URL via a webhook <code>POST</code> to the URL you provide in <code>startRecording(webhookUrl, ...)</code>. If your compliance policy requires you to own the storage, you can configure your own AWS S3 bucket via the VideoSDK dashboard integration. The <code>awsDirPath</code> parameter in <code>startRecording()</code> specifies the S3 path prefix. Recordings are not available for download during the session; the file is processed and delivered after <code>stopRecording()</code> is called.</p><p><strong>Can the KYC agent join from a mobile device?</strong></p><p>The <code>@videosdk.live/react-sdk</code> package is designed for web-based React applications. A web app built with this SDK can run on mobile browsers (Chrome on Android, Safari on iOS) if you handle responsive layout correctly. However, the agent dashboard as described in this guide is optimized for desktop. If you need a native mobile agent app, VideoSDK provides separate React Native, Android, and iOS SDKs with equivalent APIs. The <code>useMeeting</code> and <code>useParticipant</code> hook patterns map directly to those SDKs, though the exact import paths differ.</p><h3 id="conclusion">Conclusion</h3><p>Building a video KYC agent dashboard is not just about rendering a video tile. The operator interface needs to handle session lifecycle, media controls, frame capture, recording, real-time chat, and clean session termination, all in a single flow.</p><p>VideoSDK's React SDK gives you the core primitives: <code>useMeeting</code> for session control, <code>useParticipant</code> for per-user stream access and media management, and <code>usePubSub</code> for real-time messaging. Frame capture via <code>captureImage()</code> gives you the base64 data needed to call any ID verification API of your choice.</p><p>The production version of this interface should add agent authentication and role-based access, backend-side session logging, proper error handling for dropped connections, and integration with your case management system for recording URLs and verification outcomes.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Video KYC System for Credit Card Onboarding]]></title><description><![CDATA[Discover how to implement an RBI-compliant Video-based Customer Identification Process (V-CIP) for credit cards. This developer guide covers building a production-ready Video KYC pipeline using VideoSDK's React SDK, AI OCR, live face matching, spoof detection, and secure cloud recording.]]></description><link>https://www.videosdk.live/blog/video-kyc-credit-card-onboarding</link><guid isPermaLink="false">69f9e19e55831517a5a9f713</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 05 May 2026 13:47:07 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/1-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/05/1-1.png" alt="How to Build a Video KYC System for Credit Card Onboarding"/><p><a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">Video KYC</a> for credit card onboarding is the process of verifying a customer's identity over a live video call before issuing a credit card, as required by the <a href="https://www.rbi.org.in/Scripts/BS_ViewMasDirections.aspx?id=11566" rel="noreferrer nofollow">Reserve Bank of India (RBI)</a> for full-KYC accounts. RBI's Master Direction on KYC 2016 (as amended) mandates that <a href="https://www.videosdk.live/blog/video-kyc-for-nbfc-india" rel="noreferrer">banks and NBFCs</a> performing full-KYC through V-CIP must capture a live video of the customer, verify their Officially Valid Documents (OVD), and store the session recording. Without completing this step, institutions cannot open a full-KYC account, which is a prerequisite for issuing credit cards.</p><p>In this guide, you will <a href="https://www.videosdk.live/blog/build-vs-buy-video-kyc-infrastructure" rel="noreferrer">build a production-grade V-CIP pipeline</a> using VideoSDK. The stack covers: creating a video room, capturing the customer stream, running OCR on ID documents, performing face matching, detecting photo spoofing, and generating a <a href="https://www.videosdk.live/blog/cloud-recording-and-rtmp-pricing" rel="noreferrer">cloud recording</a> for audit purposes.</p><h2 id="what-is-video-kyc-and-why-credit-card-issuers-use-it">What Is Video KYC and Why Credit Card Issuers Use It</h2><p><strong>Definition:</strong> <a href="https://www.videosdk.live/blog/video-based-identification-procedure-vbip" rel="noreferrer">Video-based Customer Identification Process (V-CIP)</a> is a method of KYC wherein an authorised officer of a Regulated Entity (RE) obtains an identification document from the customer and verifies the customer's identity through a live, real-time, and seamless video interaction.</p><p><a href="https://www.rbi.org.in/commonman/English/scripts/notification.aspx?id=2607" rel="noreferrer nofollow">RBI's Master Direction on KYC 2016</a>, as updated through subsequent circulars (notably the January 2025 amendment), permits <a href="https://www.videosdk.live/blog/video-kyc-vs-traditional-kyc" rel="noreferrer">V-CIP as an alternative to in-person verification</a>. Key requirements include:</p><ul><li>The session must be a live, two-way audio-visual interaction between the customer and a trained bank agent.</li><li>The customer's face must be matched against the photo on the OVD (Aadhaar, PAN, passport, or driving licence).</li><li>Customer location must be captured at the time of the session.</li><li>The entire session must be recorded and stored securely.</li><li>A geographically dispersed infrastructure must ensure data residency within India.</li></ul><p>For credit card issuers, completing V-CIP means the account graduates to full-KYC status, unlocking higher transaction limits and enabling card issuance without a branch visit. This directly reduces cost-per-acquisition and <a href="https://www.videosdk.live/blog/how-to-scale-video-kyc-to-1-million-monthly-verifications" rel="noreferrer">speeds up onboarding</a> from days to minutes.</p><h2 id="system-architecture-for-video-kyc-onboarding">System Architecture for Video KYC Onboarding</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-5--2026--06_00_03-PM.png" class="kg-image" alt="How to Build a Video KYC System for Credit Card Onboarding" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">System Architecture for Video KYC Onboarding</span></figcaption></img></figure><p>The system has six layers:</p><p><strong>Customer App (mobile or web):</strong> The applicant opens the bank's app or web portal. The frontend uses the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">VideoSDK React SDK</a> (or <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">React Native</a> / Flutter / <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">Android</a> / <a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">iOS</a> SDK) to join a VideoSDK Room as a local participant, enabling the camera and microphone.</p><p><strong>VideoSDK Room:</strong> A Room is VideoSDK's core real-time session primitive. Both the customer and the bank agent join the same Room as Participants. The Room carries the live <a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaStream" rel="nofollow noreferrer">MediaStream</a> from each participant and provides the hooks for recording and PubSub-based signalling.</p><p><strong>Agent Dashboard:</strong> The bank officer joins the same Room as a remote participant. They view the customer's stream, request document display, trigger server-side verification calls, and mark the session as approved or rejected.</p><p><strong>KYC Backend:</strong> A Node.js service that bridges VideoSDK's AI APIs. When the agent requests document verification, the backend captures a frame from the customer's stream, base64-encodes it, and calls the OCR API, Face Match API, and Face Spoof Detection API in sequence.</p><p><strong>Identity Verification APIs:</strong> Three REST endpoints at <code>api.videosdk.live</code> handle document extraction, biometric matching, and <a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">liveness/anti-spoofing</a>. All are Enterprise-plan features. Exact endpoints are documented below.</p><p><strong>Core Banking System (CBS):</strong> Once verification passes, the KYC backend pushes the extracted fields (name, Aadhaar number, date of birth, address) to the CBS to trigger the credit card application workflow.</p><h2 id="step-by-step-implementation-with-videosdk">Step-by-Step Implementation with VideoSDK</h2><h3 id="step-1-install-the-sdk">Step 1: Install the SDK</h3><p>VideoSDK's React SDK is the primary package. The platform also supports JavaScript, React Native, Android, iOS, and Flutter.</p><pre><code class="language-bash">npm install @videosdk.live/react-sdk</code></pre><p>Wrap your application with <code>MeetingProvider</code> from the SDK:</p><pre><code class="language-jsx">import { MeetingProvider } from "@videosdk.live/react-sdk";</code></pre><h3 id="step-2-generate-an-auth-token">Step 2: Generate an Auth Token</h3><p>VideoSDK uses JWT tokens for authentication. Generate the token server-side using your API Key and Secret, which you obtain from the VideoSDK dashboard. The token does not include a "Bearer" or "Basic" prefix; pass it as a raw value.</p><pre><code class="language-js">// Server-side: Node.js token generation
import jwt from "jsonwebtoken";

const API_KEY = process.env.VIDEOSDK_API_KEY;
const SECRET = process.env.VIDEOSDK_SECRET;

const token = jwt.sign(
  {
    apikey: API_KEY,
    permissions: ["allow_join"],
    version: 2,
  },
  SECRET,
  { expiresIn: "24h" }
);</code></pre><p>Refer to the VideoSDK auth guide at <a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">https://docs.videosdk.live/api-reference/realtime-communication/intro</a> for full parameter options.</p><h3 id="step-3-create-and-join-a-room">Step 3: Create and Join a Room</h3><p>Use the <code>useMeeting</code> hook to access room controls. The <code>useParticipant</code> hook gives you access to each participant's media stream.</p><pre><code class="language-jsx">import { useMeeting, useParticipant } from "@videosdk.live/react-sdk";

function KYCRoom({ meetingId, authToken }) {
  const { join, leave, startRecording, participants } = useMeeting({
    onMeetingJoined: () =&gt; console.log("Session started"),
    onMeetingLeft: () =&gt; console.log("Session ended"),
  });

  return (
    &lt;div&gt;
      &lt;button onClick={join}&gt;Start KYC Session&lt;/button&gt;
      &lt;button onClick={leave}&gt;End Session&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><p>Pass <code>meetingId</code> and <code>token</code> via <code>MeetingProvider</code>:</p><pre><code class="language-jsx">&lt;MeetingProvider
  config={{ meetingId, micEnabled: true, webcamEnabled: true, name: "Customer" }}
  token={authToken}
&gt;
  &lt;KYCRoom meetingId={meetingId} authToken={authToken} /&gt;
&lt;/MeetingProvider&gt;</code></pre><h3 id="step-4-capture-the-customer-video-stream">Step 4: Capture the Customer Video Stream</h3><p>Use <code>useParticipant</code> to get the customer's webcam stream and render it:</p><pre><code class="language-jsx">import { useParticipant } from "@videosdk.live/react-sdk";
import { useEffect, useRef } from "react";

function CustomerVideo({ participantId }) {
  const { webcamStream, webcamOn } = useParticipant(participantId);
  const videoRef = useRef(null);

  useEffect(() =&gt; {
    if (webcamRef.current &amp;&amp; webcamStream) {
      const mediaStream = new MediaStream();
      mediaStream.addTrack(webcamStream.track);
      videoRef.current.srcObject = mediaStream;
      videoRef.current.play();
    }
  }, [webcamStream]);

  return webcamOn ? &lt;video ref={videoRef} autoPlay muted /&gt; : null;
}</code></pre><p>To extract a still frame for document scanning, draw the video element onto a canvas and export to base64:</p><pre><code class="language-js">function captureFrame(videoElement) {
  const canvas = document.createElement("canvas");
  canvas.width = videoElement.videoWidth;
  canvas.height = videoElement.videoHeight;
  canvas.getContext("2d").drawImage(videoElement, 0, 0);
  return canvas.toDataURL("image/jpeg"); // returns data:image/jpeg;base64,...
}</code></pre><h3 id="step-5-integrate-the-ocr-api">Step 5: Integrate the OCR API</h3><p><strong>Endpoint (verified from docs):</strong> <code>POST https://api.videosdk.live/ai/v1/ocr</code></p><p>Send the front and back of the Aadhaar or PAN card as base64 images. The <code>Authorization</code> header takes the raw JWT token with no prefix.</p><pre><code class="language-js">async function runOCR(frontBase64, backBase64) {
  const url = "https://api.videosdk.live/ai/v1/ocr";
  const headers = {
    Authorization: process.env.VIDEOSDK_API_TOKEN,
    "Content-Type": "application/json",
  };
  const data = {
    frontPart: frontBase64, // e.g. "data:image/jpeg;base64,/9j/4AAQ..."
    backPart: backBase64,
  };

  const response = await axios.post(url, data, { headers });
  return response.data;
  // Returns: { idType, idNumber, name, dateOfBirth, address, gender, mobileNumber }
}</code></pre><p>The response fields vary by document type. For Aadhaar, you receive <code>name</code>, <code>dateOfBirth</code>, <code>address</code>, and <code>idNumber</code>. Push these fields to your CBS workflow once verified.</p><h3 id="step-6-run-the-face-match-api">Step 6: Run the Face Match API</h3><p><strong>Endpoint (verified from docs):</strong> <code>POST https://api.videosdk.live/ai/v1/face-verification/verify</code></p><p>Compare the live selfie frame with the photo on the ID document. The API returns <code>{ "verified": true }</code> or <code>{ "verified": false }</code>.</p><pre><code class="language-js">async function runFaceMatch(idPhotoBase64, selfieBase64) {
  const url = "https://api.videosdk.live/ai/v1/face-verification/verify";
  const headers = {
    Authorization: process.env.VIDEOSDK_API_TOKEN,
    "Content-Type": "application/json",
  };
  const data = {
    img1: idPhotoBase64,   // photo extracted from ID document
    img2: selfieBase64,    // live selfie captured from the video stream
  };

  const response = await axios.post(url, data, { headers });
  return response.data; // { verified: true } or { verified: false }
}</code></pre><p>Only proceed to card issuance if <code>verified</code> is <code>true</code>.</p><h3 id="step-7-run-the-face-spoof-detection-api">Step 7: Run the Face Spoof Detection API</h3><p><strong>Endpoint (verified from docs):</strong> <code>POST https://api.videosdk.live/ai/v1/face-verification/detect-spoof</code></p><p>This catches applicants who hold a printed photo or screen in front of the camera instead of their real face. The response includes <code>spoof_detected</code> (boolean) and an <code>accuracy</code> score.</p><pre><code class="language-js">async function runSpoofDetection(selfieBase64) {
  const url = "https://api.videosdk.live/ai/v1/face-verification/detect-spoof";
  const headers = {
    Authorization: process.env.VIDEOSDK_API_TOKEN,
    "Content-Type": "application/json",
  };
  const data = {
    img: selfieBase64, // single base64 image of the customer's live face
  };

  const response = await axios.post(url, data, { headers });
  return response.data;
  // Returns: { spoof_detected: false, accuracy: 0.989... }
}</code></pre><p>If <code>spoof_detected</code> is <code>true</code>, reject the session and flag the application for manual review.</p><h3 id="step-8-start-cloud-recording-for-the-audit-trail">Step 8: Start Cloud Recording for the Audit Trail</h3><p>RBI mandates that the full V-CIP session be recorded. Use the <code>startRecording</code> method returned by <code>useMeeting</code>. VideoSDK stores the recording in its cloud, and you can configure a custom storage destination (see FAQ below for details on custom S3 buckets, which requires verification with VideoSDK support).</p><pre><code class="language-jsx">const { startRecording, stopRecording } = useMeeting();

// Start recording as soon as both participants have joined
function beginAuditRecording() {
  startRecording();
}

// Stop recording when the agent marks the session complete
function endAuditRecording() {
  stopRecording();
}</code></pre><p>The recording captures both the customer and the agent streams in a composited layout. Store the recording URL in your KYC database alongside the session metadata (timestamp, customer ID, OCR output, face match result).</p><h2 id="agent-dashboard-setup">Agent Dashboard Setup</h2><p>The bank agent joins the same VideoSDK Room using a separate interface. Their token should include the <code>allow_join</code> and <code>allow_mod</code> permissions so they can control the session.</p><pre><code class="language-jsx">// Agent's MeetingProvider configuration
&lt;MeetingProvider
  config={{
    meetingId,
    micEnabled: true,
    webcamEnabled: true,
    name: "KYC Agent - Priya",
  }}
  token={agentToken}
&gt;
  &lt;AgentDashboard /&gt;
&lt;/MeetingProvider&gt;</code></pre><p>Inside <code>AgentDashboard</code>, iterate over <code>participants</code> (excluding the agent's own local participant) to render the customer's video feed using <code>useParticipant</code>. The agent UI should expose:</p><ul><li>A live view of the customer's webcam stream.</li><li>A button to trigger the OCR + face match + spoof detection sequence server-side.</li><li>An approval or rejection toggle that writes the outcome to your KYC backend.</li><li>A session timer (RBI does not specify a maximum duration, but a timeout of 15 minutes is a sensible default).</li></ul><p>The agent cannot directly call VideoSDK AI APIs from the browser. All AI calls should originate from your KYC backend server, which holds the API token securely.</p><h2 id="rbi-compliance-checklist">RBI Compliance Checklist</h2><p>Building the session is only half the work. The following controls are required or strongly implied by RBI's V-CIP guidelines.</p><p><strong>Geo-fencing (INDIA region):</strong> VideoSDK's Geo Fencing feature restricts <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> connections to servers within a specified region, regardless of where the user physically connects from. For an RBI-compliant V-CIP, set the region to <code>INDIA</code>. This ensures all media traffic and data stays within Indian borders. Geo Fencing is an Enterprise plan feature. Configure it by setting the <code>region</code> parameter when creating the Room via the VideoSDK REST API.</p><p>Available regions confirmed from docs: <code>INDIA</code>, <code>USA</code>, <code>UAE</code>, <code>EUROPE</code>, <code>SINGAPORE</code>, <code>AUSTRALIA</code>. Select <code>INDIA</code> for RBI compliance.</p><p><strong>Customer location capture:</strong> At session start, use the browser's Geolocation API (<code>navigator.geolocation.getCurrentPosition</code>) to capture the customer's latitude and longitude. Store this alongside the KYC record. RBI requires that the customer's location be verified as within India during the V-CIP.</p><p><strong>Customer consent flow:</strong> Before the Room is joined, display a clear consent screen stating: the session will be recorded, the data will be used for <a href="https://www.videosdk.live/blog/video-kyc-ekyc-and-physical-kyc-comparison" rel="noreferrer">KYC verification</a>, and the recording will be stored for the regulatory period (typically 10 years per RBI guidelines). Log the timestamp of consent acceptance.</p><p><strong>Recorded session storage:</strong> <a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> records the session to cloud storage. For long-term regulatory retention, download the recording after the session and archive it to your bank's own encrypted storage. Tag records with the customer ID, session ID, agent ID, and timestamp.</p><p><strong>Trained agent requirement:</strong> The agent conducting V-CIP must be trained by the Regulated Entity. This is an operational control, not a software control, but your dashboard should enforce agent authentication through your existing IAM system before granting access to the VideoSDK Room.</p><h2 id="key-takeaways">Key Takeaways</h2><ul><li>VideoSDK provides three identity verification REST APIs verified from the docs: OCR API (<code>/ai/v1/ocr</code>), Face Match API (<code>/ai/v1/face-verification/verify</code>), and Face Spoof Detection API (<code>/ai/v1/face-verification/detect-spoof</code>). All three are Enterprise plan features.</li><li>The <code>useMeeting</code> and <code>useParticipant</code> hooks from <code>@videosdk.live/react-sdk</code> handle room management and media stream access with minimal boilerplate.</li><li>RBI's V-CIP mandate covers four pillars: live video interaction, document OCR, face matching, and session recording. VideoSDK covers all four in a single platform.</li><li>Geo Fencing to the <code>INDIA</code> region ensures your WebRTC media traffic does not leave Indian data centres, a critical data residency requirement for credit card KYC.</li><li>All AI API calls must be made server-side (from your KYC backend), not from the browser, to protect your API token.</li></ul><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><p><strong>Q: Is VideoSDK suitable for RBI-compliant V-CIP for credit card onboarding?</strong></p><p>VideoSDK provides the technical infrastructure required to build a V-CIP pipeline: live two-way audio-visual communication, cloud recording, and identity verification APIs (OCR, face match, and spoof detection). However, regulatory compliance is the responsibility of the Regulated Entity (bank or NBFC) that deploys the solution. The bank must ensure the system meets all RBI Master Direction requirements including agent training, consent flows, data retention, and audit procedures. VideoSDK's infrastructure can be configured to support these requirements, particularly with Geo Fencing set to the INDIA region and cloud recording enabled. Contact VideoSDK's enterprise team for a compliance-oriented deployment discussion.</p><p><strong>Q: Can the V-CIP session recording be stored on a custom S3 bucket?</strong></p><p>VideoSDK's cloud recording stores sessions in VideoSDK-managed storage by default. Custom storage destination support (such as your bank's own AWS S3 bucket or Azure Blob Storage) is a feature that should be confirmed directly with VideoSDK's enterprise support team, as the exact configuration options may depend on your contract. For regulatory retention requirements, the standard approach is to download the recording via the VideoSDK recording URL after the session ends and archive it to your own encrypted storage.</p><p><strong>Q: How does the Face Spoof Detection API work?</strong></p><p>The Face Spoof Detection API (<code>POST https://api.videosdk.live/ai/v1/face-verification/detect-spoof</code>) takes a single base64-encoded image of the customer's face and returns two fields: <code>spoof_detected</code> (a boolean) and <code>accuracy</code> (a float representing the model's confidence). The model distinguishes a real, live face from a printed photograph or screen replay held up to the camera. An accuracy value close to 1.0 indicates high confidence in the detection result. The API does not rely on motion or challenge-response; it performs a single-frame analysis.</p><p><strong>Q: What is the latency of the OCR API?</strong></p><p>The VideoSDK docs do not publish a specific latency SLA for the OCR API (<code>POST https://api.videosdk.live/ai/v1/ocr</code>). Actual response times depend on image size, server load, and network conditions. In practice, OCR calls on document images should complete within a few seconds for a typical JPEG. For a production deployment, implement a timeout and retry strategy on the KYC backend. Contact VideoSDK enterprise support for latency guarantees if your SLA requires a specific commitment.</p><p><strong>Q: Does VideoSDK's React SDK work on Android and iOS for video KYC on mobile?</strong></p><p>VideoSDK supports native mobile development through its React Native SDK, Android (Kotlin/Java) SDK, and iOS (Swift) SDK, in addition to the React web SDK used in this guide. All platform SDKs provide equivalent access to the same Room, Participant, and media stream primitives. The identity verification APIs (OCR, Face Match, Face Spoof Detection) are REST endpoints and can be called from any platform that can make HTTPS requests. This means you can build a fully native mobile V-CIP app using VideoSDK's mobile SDKs and the same backend API calls described here.</p><p><strong>Q: Which document types does the OCR API support?</strong></p><p>Based on the VideoSDK docs, the OCR API accepts the front and back of an ID document and returns fields including <code>idType</code>, <code>idNumber</code>, <code>name</code>, <code>dateOfBirth</code>, <code>address</code>, <code>gender</code>, and <code>mobileNumber</code>. The response fields vary by document type. For a complete list of supported Indian OVDs (Aadhaar, PAN, passport, driving licence, voter ID), confirm with VideoSDK's enterprise team, as the exact supported set is not enumerated in the current public documentation.</p><h2 id="conclusion">Conclusion</h2><p>Building a video KYC system for credit card onboarding requires three things working together: a reliable real-time video layer, verified identity APIs, and a compliant recording pipeline. VideoSDK provides all three through its React SDK hooks (<code>useMeeting</code>, <code>useParticipant</code>), its Identity Verification REST APIs (OCR, Face Match, Face Spoof Detection), and its built-in cloud recording. Start with the full documentation at <a href="https://docs.videosdk.live">docs.videosdk.live</a> and reach out to the enterprise team for Geo Fencing and custom storage configuration specific to your RBI compliance requirements.</p>]]></content:encoded></item><item><title><![CDATA[The Non-Technical Founder's Guide to Adding Video Calls]]></title><description><![CDATA[Adding video calls to your product doesn't require an engineering degree. This guide helps non-technical founders navigate the build vs. buy decision, understand WebRTC, and evaluate video APIs. Learn how to launch scalable video features quickly and cost-effectively.]]></description><link>https://www.videosdk.live/blog/non-technical-founders-guide-to-adding-video-calls</link><guid isPermaLink="false">69f8911255831517a5a9f669</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 04 May 2026 13:40:38 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/38.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TLDR:</strong> Adding video calls to your product does not require deep engineering expertise. Most founders can ship a working video feature within days using a video calling API or SDK. The main decision is not how to build it but whether to build it or buy it.</blockquote><h2 id="what-you-actually-need-to-know-to-get-started">What you actually need to know to get started</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/38.png" alt="The Non-Technical Founder's Guide to Adding Video Calls"/><p>If you are a non-technical founder exploring how to add video calls to your product, you have two realistic paths: integrate a pre-built <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">video calling API</a> for startups, or build your own infrastructure using WebRTC. For most early-stage products, an API or SDK is the faster, cheaper, and safer path. Understanding the core components and trade-offs will help you make a confident decision without needing an engineering degree.</p><h2 id="introduction-why-video-is-now-a-product-expectation-not-a-feature">Introduction: Why video is now a product expectation, not a feature</h2><p>Video communication has moved from a competitive differentiator to a baseline expectation. Telehealth platforms, edtech products, HR tools, legal services, and marketplace platforms all face user pressure to embed live video inside the product experience rather than redirecting users to a separate tool like Zoom or Google Meet.</p><p>For a non-technical founder, the challenge is not awareness. It is decision confidence. Should you <a href="https://www.videosdk.live/blog/build-or-buy-video-calling-api" rel="noreferrer">buy or build video infrastructure</a>? Which SDK do you pick? What does "scalable" even mean in this context? What does it cost at 1,000 concurrent users versus 10,000?</p><p>This guide answers those questions with plain frameworks and concrete checklists. No code required.</p><h2 id="understanding-the-technology-landscape-webrtc-and-what-sits-on-top-of-it">Understanding the technology landscape: WebRTC and what sits on top of it</h2><p><strong>WebRTC</strong> (Web Real-Time Communication): <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> is an open-source standard that enables real-time audio, video, and data transfer directly between browsers or devices without a plugin. It is the protocol layer underneath virtually every video calling product on the market.</p><p>WebRTC is powerful but low-level. Building on raw WebRTC requires managing network traversal, signalling, codec negotiation, and media routing. That complexity is why the ecosystem of SDKs and APIs exists.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-4--2026--06_08_12-PM.png" class="kg-image" alt="The Non-Technical Founder's Guide to Adding Video Calls" loading="lazy" width="1693" height="929"><figcaption><span style="white-space: pre-wrap;">Video calling system architecture</span></figcaption></img></figure><h3 id="key-infrastructure-components-you-need-to-know">Key infrastructure components you need to know</h3><p><a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-stun-server" rel="noreferrer"><strong>STUN server</strong></a> (Session Traversal Utilities for NAT): A STUN server helps two devices discover their public IP addresses so they can connect to each other across firewalls and networks.</p><p><a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer"><strong>TURN server</strong></a> (Traversal Using Relays around NAT): A TURN server acts as a relay when a direct peer-to-peer connection is not possible, which happens in restrictive corporate or mobile networks.</p><p><a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu" rel="noreferrer"><strong>SFU</strong></a> (Selective Forwarding Unit): An SFU is a media server that receives video streams from participants and selectively forwards them to others, enabling group calls without every participant uploading their video to everyone else.</p><p><a href="https://www.videosdk.live/blog/what-is-webrtc-signaling" rel="noreferrer"><strong>Signalling server</strong></a>: A signalling server coordinates the initial connection handshake between devices, exchanging metadata so the WebRTC session can begin.</p><p>As a founder, you do not need to build any of these yourself. But you need to know they exist because any video calling API or SDK you evaluate will either manage these for you or require you to bring your own.</p><h2 id="the-core-decision-framework-build-vs-buy-video-infrastructure">The core decision framework: Build vs buy video infrastructure</h2><p>This is the most important decision you will make. Get it wrong and you lose months of engineering time, or you end up locked into a vendor that cannot scale with you.</p><h3 id="framework-four-question-build-vs-buy-test">Framework: Four-question build vs buy test</h3><p>Answer each question honestly before moving forward.</p><p><strong>1. Is video your core product differentiation?</strong> </p><p>If video is a peripheral feature (for example, adding a consultation call to a booking platform), buy. If your entire product value depends on unique video behavior (for example, a spatial video social platform), consider building.</p><p><strong>2. How fast do you need to ship?</strong> </p><p>Building custom <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> infrastructure takes 3 to 6 months of dedicated engineering time for a production-grade solution. A video SDK can get you to a working prototype in days.</p><p><strong>3. What is your engineering team's capacity?</strong> </p><p>Maintaining a WebRTC stack requires specialists in network engineering, media processing, and real-time systems. If your team does not have that expertise today, buying buys you time while you grow.</p><p><strong>4. What are your compliance and data residency requirements?</strong> </p><p>Some regulated industries (healthcare, finance, government) require data to stay within specific geographic boundaries. Evaluate whether a vendor can meet those requirements before committing.</p><blockquote>Must Read: <a href="https://www.videosdk.live/blog/build-or-buy-video-calling-api" rel="noreferrer">Build or Buy Video Calling infrastructure</a></blockquote><h3 id="decision-output">Decision output</h3><table>
<thead>
<tr>
<th>Your situation</th>
<th>Recommended path</th>
</tr>
</thead>
<tbody>
<tr>
<td>Early-stage, pre-revenue, shipping fast</td>
<td>Buy (API or SDK)</td>
</tr>
<tr>
<td>Mid-stage, video is core, team has bandwidth</td>
<td>Hybrid (SDK with custom signalling)</td>
</tr>
<tr>
<td>Funded, video is the entire product, strong eng team</td>
<td>Build or managed infrastructure</td>
</tr>
<tr>
<td>Regulated industry with strict data requirements</td>
<td>Vendor with region-specific deployment or self-hosted option</td>
</tr>
</tbody>
</table>
<h2 id="infrastructure-components-and-what-you-are-actually-paying-for">Infrastructure components and what you are actually paying for</h2><p>When you evaluate a <strong>video calling API for startups</strong>, you are not just buying a button that says "Start Call." You are paying for a managed stack that includes:</p><ul><li><a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-stun-and-turn-server" rel="noreferrer">STUN and TURN server</a> infrastructure across global regions</li><li>SFU or media server capacity that scales with concurrent users</li><li>Signalling and session management</li><li>Codec support and <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">adaptive bitrate streaming</a></li><li>Recording storage and playback pipelines</li><li>SDK maintenance across iOS, Android, web, and React Native</li><li>Compliance certifications such as SOC 2 or <a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api" rel="noreferrer">HIPAA</a> readiness</li></ul><p>Understanding this list matters because it is what you would have to build and maintain yourself on the alternative path.</p><h2 id="cost-considerations-what-does-video-actually-cost-to-run">Cost considerations: What does video actually cost to run?</h2><p>Cost in video infrastructure is driven by three variables: concurrent users, duration of calls, and feature complexity (recording, transcription, livestreaming).</p><h3 id="cost-model-comparison">Cost model comparison</h3><table>
<thead>
<tr>
<th>Cost driver</th>
<th>Self-build</th>
<th>API/SDK vendor</th>
</tr>
</thead>
<tbody>
<tr>
<td>Engineering setup (one-time)</td>
<td>High (3-6 months of salaries)</td>
<td>Low (integration days to weeks)</td>
</tr>
<tr>
<td>Server/cloud infrastructure</td>
<td>Variable, directly managed</td>
<td>Included in usage pricing</td>
</tr>
<tr>
<td>Maintenance and updates</td>
<td>Ongoing engineering cost</td>
<td>Covered by vendor</td>
</tr>
<tr>
<td>Scaling cost at 1,000+ concurrent users</td>
<td>Requires active capacity planning</td>
<td>Auto-scales, billed by usage</td>
</tr>
<tr>
<td>Compliance certifications</td>
<td>You must obtain them</td>
<td>Often vendor-provided</td>
</tr>
</tbody>
</table>
<p>A typical rule of thumb: for products under 10,000 monthly active video users, a vendor API is almost always cheaper than self-building when you factor in total engineering cost.</p><p>At scale, the calculus shifts. At very high usage volumes, engineering a proprietary stack can reduce marginal cost per minute. But most early-stage founders are optimising for the wrong variable when they worry about per-minute pricing at 1 million users before they have 100.</p><h2 id="scalability-planning-thinking-ahead-without-over-engineering">Scalability planning: Thinking ahead without over-engineering</h2><p><strong>Scalability</strong> in real-time communication: Scalability is the ability of your video infrastructure to handle increasing numbers of concurrent sessions without degrading call quality or requiring manual intervention.</p><p>The biggest scalability mistake non-technical founders make is conflating user count with concurrent session count. If you have 10,000 registered users but only 200 are ever in a call at the same moment, your infrastructure load is based on 200 concurrent sessions, not 10,000 users.</p><h3 id="scalability-checklist">Scalability checklist</h3><ul><li>Estimate your peak concurrent call sessions, not total user count</li><li>Ask vendors about their SFU architecture and how they handle geographic distribution</li><li>Confirm whether the SDK supports adaptive bitrate (automatically reducing video quality on poor connections)</li><li>Ask about fallback behaviour when TURN relay is needed</li><li>Clarify SLA uptime guarantees and incident response times</li></ul><blockquote>Read: <a href="https://www.videosdk.live/blog/scale-video-kyc-to-1-million-monthly-verifications" rel="noreferrer">How to Scale Video KYC to 1 Million+ Monthly Verifications</a></blockquote><h2 id="implementation-roadmap-step-by-step-checklist-for-non-technical-founders">Implementation roadmap: Step-by-step checklist for non-technical founders</h2><h3 id="phase-1-define-requirements-1-to-2-weeks">Phase 1: Define requirements (1 to 2 weeks)</h3><ul><li>Write a one-page video feature spec covering: one-to-one or group calls, mobile or web or both, recording needs, approximate MAU and concurrent session estimates</li><li>List any compliance requirements: HIPAA, GDPR, RBI, PDPB</li><li>Identify whether you need livestreaming or recording in addition to live calls</li><li>Decide on your data residency preference (India, US, EU, or global)</li></ul><h3 id="phase-2-evaluate-vendors-or-sdk-options-1-to-2-weeks">Phase 2: Evaluate vendors or SDK options (1 to 2 weeks)</h3><ul><li>Build a vendor shortlist based on platform coverage, pricing model, and compliance certifications</li><li>Request a free trial or sandbox access from each shortlisted vendor</li><li>Have your engineering lead (or a contractor) run a prototype integration during trial</li><li>Test call quality on <a href="https://www.videosdk.live/blog/make-video-calls-work-in-low-connectivity-areas" rel="noreferrer">low-bandwidth connections</a> relevant to your target market</li></ul><h3 id="phase-3-integration-and-qa-2-to-6-weeks-depending-on-team">Phase 3: Integration and QA (2 to 6 weeks depending on team)</h3><ul><li>Integrate the chosen SDK into your staging environment</li><li>Implement authentication so only your users can start or join sessions</li><li>Test edge cases: dropped connections, browser permissions, mobile background behavior</li><li>Confirm recording and playback work end-to-end if required</li><li>Run load tests at 2x your expected peak concurrent session count</li></ul><h3 id="phase-4-launch-and-monitor-ongoing">Phase 4: Launch and monitor (ongoing)</h3><ul><li>Set up real-time monitoring for call quality metrics (packet loss, jitter, latency)</li><li>Establish a feedback loop with early users to catch quality issues by geography or device</li><li>Review vendor usage invoices monthly to validate cost projections</li></ul><h2 id="comparison-of-approaches-and-representative-platforms">Comparison of approaches and representative platforms</h2><p><strong>Video SDK</strong> (Software Development Kit): A video SDK is a pre-packaged library that a developer integrates into an existing application to add real-time video calling capabilities without building transport or media logic from scratch.</p><table>
<thead>
<tr>
<th>Approach</th>
<th>Examples</th>
<th>Best for</th>
<th>Limitations</th>
</tr>
</thead>
<tbody>
<tr>
<td>Fully managed video API</td>
<td>VideoSDK, Daily, Agora, Twilio</td>
<td>Fast integration, broad platform support</td>
<td>Per-minute costs scale up at high volume</td>
</tr>
<tr>
<td>WebRTC SaaS platform</td>
<td>Whereby Embedded, Jitsi as a Service</td>
<td>Non-technical embed use cases</td>
<td>Limited customisation</td>
</tr>
<tr>
<td>Open source self-hosted</td>
<td>Jitsi Meet self-hosted, mediasoup</td>
<td>Cost control at scale, full ownership</td>
<td>High engineering and DevOps burden</td>
</tr>
<tr>
<td>Cloud media server</td>
<td>AWS Kinesis Video, GCP WebRTC</td>
<td>Teams already on a single cloud provider</td>
<td>Complex setup, not optimised for calls</td>
</tr>
</tbody>
</table>
<p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a>, for example, provides SDKs for <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">React</a>, <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">React Native</a>, <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">Flutter</a>, <a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">iOS</a>, and <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">Android</a>, along with support for <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">real-time audio and video</a>, session recording, <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">interactive livestreaming</a>, and screen sharing. It exposes these capabilities through a unified API so a single integration covers multiple platforms and use cases. </p><h2 id="common-mistakes-and-misconceptions">Common mistakes and misconceptions</h2><h3 id="mistake-1-treating-webrtc-as-a-product-not-a-protocol">Mistake 1: Treating WebRTC as a product, not a protocol</h3><p><a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> is the foundation, not the building. Founders who research WebRTC and then try to build directly on it often underestimate the operational complexity. The correct question is not "how do we use WebRTC" but "which layer above WebRTC fits our needs."</p><h3 id="mistake-2-confusing-concurrent-users-with-registered-users-for-cost-planning">Mistake 2: Confusing concurrent users with registered users for cost planning</h3><p>Video infrastructure costs are driven by concurrent sessions. Plan your cost model around peak simultaneous call usage, not total user base.</p><h3 id="mistake-3-skipping-low-bandwidth-testing">Mistake 3: Skipping low-bandwidth testing</h3><p>Many Indian and global-south markets have variable mobile connectivity. A product that works perfectly on a Bangalore office Wi-Fi connection may break for users on 3G in a Tier 2 city. Always test on throttled connections before launch.</p><h3 id="mistake-4-ignoring-mobile-platform-requirements">Mistake 4: Ignoring mobile platform requirements</h3><p>If your users are primarily on mobile, your SDK choice must support native iOS and Android, not just a mobile web wrapper. Native SDKs offer better access to device hardware for camera and microphone management.</p><h3 id="mistake-5-deferring-compliance-to-post-launch">Mistake 5: Deferring compliance to post-launch</h3><p>In regulated sectors like healthcare (HIPAA, ABDM in India), finance (RBI), or education (FERPA), compliance cannot be retrofitted. Evaluate vendor certifications before you write a line of integration code.</p><h3 id="mistake-6-over-customising-before-validating-demand">Mistake 6: Over-customising before validating demand</h3><p>Many founders spend weeks building a custom video UI before confirming that users actually want or use the video feature. Integrate a working but minimal video experience first, validate usage, then invest in customisation.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li>For most non-technical founders, a video calling API or SDK is the right starting point; building from scratch on WebRTC is rarely justified before product-market fit.</li><li>The four-question build vs buy test (differentiation, speed, team capacity, compliance) is a reliable framework for making this decision without technical depth.</li><li>Cost planning for video infrastructure should be anchored to concurrent session counts, not registered user totals.</li><li>Low-bandwidth testing is not optional if your product serves users in India or other markets with variable connectivity.</li><li>Compliance requirements in regulated sectors must be validated before vendor selection, not after launch.</li></ul><h2 id="frequently-asked-questions">Frequently asked questions</h2><p><strong>Q1. What is the difference between a video calling API and a video SDK?</strong></p><p>A <strong>video calling API</strong> is a set of HTTP or WebSocket endpoints that your backend calls to manage sessions, tokens, and recordings. A <strong>video SDK</strong> is a client-side library that your app integrates to render the video UI and connect to the media infrastructure. Most modern video platforms provide both: an API for server-side session management and an SDK for client-side rendering. In practice, you use both together.</p><p><strong>Q2. Do I need a technical co-founder to add video calls to my product?</strong></p><p>Not necessarily. Many video SDKs are designed for integration by developers with general web or mobile experience, not real-time communication specialists. A front-end developer or a capable freelancer can complete a basic integration. What requires more expertise is building custom media processing, recording pipelines, or on-premise infrastructure.</p><p>Q3. How much does it cost to add video calling to a startup product?</p><p>Costs depend on your usage model. Most vendor APIs charge per-minute of video processed, with rates typically ranging from USD 0.001 to USD 0.004 per participant minute depending on features enabled. A product with 1,000 monthly users averaging two 30-minute calls per month would generate roughly 60,000 participant minutes, which translates to USD 60 to USD 240 per month at those rates. Always model your own usage pattern against vendor pricing pages rather than relying on generic estimates.</p><p><strong>Q4. </strong>What is real-time communication architecture for a startup?</p><p>Real-time communication (RTC) architecture for a startup typically includes a frontend SDK (for rendering audio/video in the app), a signalling layer (to coordinate session setup), STUN and TURN servers (for network traversal), and an SFU or media server (for routing video streams in group calls). A backend authentication layer issues session tokens so only authorised users can join calls. When you use a video API vendor, they manage all of this except the authentication layer, which integrates with your existing user system.</p><p><strong>Q5. Is WebRTC secure for sensitive use cases like telehealth?</strong></p><p>WebRTC encrypts media streams by default using DTLS-SRTP (Datagram Transport Layer Security - Secure Real-time Transport Protocol), which is a strong baseline. However, security in telehealth or other regulated sectors depends on the entire stack: vendor compliance certifications (HIPAA BAA, SOC 2), data residency controls, access logging, and session recording encryption. Evaluate vendors against your specific regulatory framework, not just the protocol layer.</p><p><strong>Q6. Can I add video calling to a mobile app without rebuilding it?</strong></p><p>Yes. Most major video SDKs provide native libraries for iOS (Swift/Objective-C) and Android (Kotlin/Java), as well as cross-platform SDKs for Flutter and React Native. If your app is already in production, you can integrate a video SDK as an additional module without restructuring the entire application. The integration scope depends on how deeply the video feature needs to connect to your app's authentication and data layers.</p><p><strong>Q7. What happens if the video vendor I choose goes down?</strong></p><p>Vendor downtime is a real risk. Mitigate it by: checking the vendor's historical uptime SLA and incident reports before signing, understanding their global CDN and server redundancy architecture, and ensuring your integration does not hard-depend on a single regional endpoint. Some vendors offer enterprise SLAs with financial penalties for downtime. For mission-critical use cases, consider multi-vendor fallback strategies at the session initiation layer.</p><p><strong>Q8. How do I choose between building for web-first or mobile-first?</strong></p><p>Let your user data decide. If more than 60% of your current users are on mobile devices, prioritise a native mobile SDK. If your product is browser-based, a web SDK covering Chrome, Firefox, and Safari is your starting point. Most vendors support both, but the quality of their mobile SDK, especially on Android with its fragmented device landscape, varies significantly. Always test the SDK on the specific device types your target users actually use.</p>]]></content:encoded></item><item><title><![CDATA[How to Evaluate a Video KYC Vendor: RFP Checklist for Banks]]></title><description><![CDATA[Selecting the wrong Video KYC vendor exposes banks to compliance risks. Use this definitive RFP checklist to evaluate vendors on RBI V-CIP readiness, WebRTC infrastructure, data security, and TCO to ensure secure and seamless digital onboarding.]]></description><link>https://www.videosdk.live/blog/video-kyc-vendor-evaluation-rfp-checklist</link><guid isPermaLink="false">69f87ed355831517a5a9f5fc</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 04 May 2026 12:15:59 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/37.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TLDR:</strong> Selecting the wrong video KYC vendor exposes banks to regulatory penalties, audit failures, and broken customer onboarding flows. This guide provides a structured RFP framework, covering compliance, infrastructure, security, and cost, for procurement heads and product teams running formal vendor evaluations in India.</blockquote><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-text">Banks evaluating video KYC vendors in India must verify alignment with RBI's Video Customer Identification Process (V-CIP) guidelines, assess infrastructure reliability, and score vendors against a weighted decision matrix before shortlisting. No single vendor evaluation criterion is sufficient on its own; compliance readiness, uptime guarantees, and integration depth must be assessed together.</div></div><h2 id="introduction"><strong>Introduction</strong></h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/37.png" alt="How to Evaluate a Video KYC Vendor: RFP Checklist for Banks"/><p>India's digital lending and banking sector onboarded over 80 million new customers remotely between 2020 and 2023, with <a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer"><strong>Video KYC</strong></a><strong>,</strong> formally called <a href="https://www.videosdk.live/blog/video-based-identification-procedure-vbip" rel="noreferrer">Video Customer Identification Process</a> or V-CIP, becoming the regulatory backbone of paperless account opening. The Reserve Bank of India (RBI) mandated V-CIP via its <a href="https://www.rbi.org.in/Scripts/NotificationUser.aspx?Id=11783&amp;Mode=0" rel="noreferrer nofollow">January 2020 circular (RBI/2019-20/138)</a>, allowing regulated entities to complete KYC remotely through a live, consent-based video interaction between a trained bank official and the customer.</p><p>For procurement heads, compliance teams, and VP Product at banks running a <a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">video KYC</a> vendor evaluation RFP checklist exercise, the challenge is not a shortage of vendors, it is the absence of a rigorous, compliance-anchored evaluation framework. This guide fills that gap.</p><h2 id="regulatory-and-market-context-in-india"><strong>Regulatory and market context in India</strong></h2><h3 id="what-rbis-v-cip-guidelines-actually-require"><strong>What RBI's V-CIP guidelines actually require</strong></h3><p>The RBI's <strong>V-CIP framework</strong> (as updated in Master Direction on KYC, 2016, last amended 2023) defines the minimum technical and process requirements for video-based customer identification. Key mandates include:</p><ul><li>The video interaction must be live (not pre-recorded) and geo-tagged to confirm the customer is physically in India at the time of onboarding.</li><li>The bank official conducting the V-CIP must be a trained and designated officer.</li><li>The session must capture a clear image of the customer's face, PAN card, and Aadhaar (with masked Aadhaar number or OTP-based XML verification).</li><li>All audio-video recordings must be stored securely in India, with an audit trail maintained for a minimum of five years.</li><li>The system must include <a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">liveliness detection</a> and random question prompts to prevent spoofing.</li></ul><p>The <strong>Insurance Regulatory and Development Authority of India (IRDAI)</strong> has issued <a href="https://www.videosdk.live/blog/irdai-vbip-compliance-guide-for-insurtech" rel="noreferrer">parallel guidelines permitting insurers to use video-based KYC</a> for policy issuance, with similar requirements around agent training, recording retention, and data localisation.</p><p>Non-compliance consequences include regulatory penalties from RBI (monetary fines, operational restrictions), failed internal and external audits, suspension of digital onboarding capabilities, and customer onboarding disruption during remediation periods.</p><h3 id="market-context"><strong>Market context</strong></h3><p>India's digital KYC infrastructure market is fragmented. Vendors range from full-stack KYC SaaS platforms to infrastructure-layer providers offering video session management, AI-based document verification, and liveness detection as separate components. Banks and NBFCs must decide whether to procure a single vendor or assemble a multi-vendor stack, a decision that directly affects integration complexity, vendor accountability, and audit trail coherence.</p><blockquote>Must Read: <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc" rel="noreferrer">RBI video KYC guidelines compliance guidelinces</a></blockquote><h2 id="core-vendor-evaluation-framework">Core vendor evaluation framework</h2><p>A sound video KYC vendor evaluation RFP checklist for banks is organised across six pillars. Each maps to a distinct set of risks.</p><h3 id="1-vendor-capability-checklist">1. Vendor capability checklist</h3><p>Before any technical due diligence, verify that the vendor can demonstrate the following capabilities in a production environment, not just in a demo.</p><table>
<thead>
<tr>
<th style="text-align:left">Capability</th>
<th style="text-align:left">What to verify</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">Live video session with in-session recording</td>
<td style="text-align:left">End-to-end session recording stored and retrievable by session ID</td>
</tr>
<tr>
<td style="text-align:left">Document capture and OCR</td>
<td style="text-align:left">PAN, Aadhaar, passport capture with field-level extraction accuracy &gt; 95%</td>
</tr>
<tr>
<td style="text-align:left">Liveness detection</td>
<td style="text-align:left">Active (challenge-response) and passive liveness, with anti-spoofing certifications</td>
</tr>
<tr>
<td style="text-align:left">Face match</td>
<td style="text-align:left">Real-time face comparison against document photo with confidence score logging</td>
</tr>
<tr>
<td style="text-align:left">Geo-tagging</td>
<td style="text-align:left">IP and GPS-based location verification, India-only restriction enforcement</td>
</tr>
<tr>
<td style="text-align:left">Masked Aadhaar support</td>
<td style="text-align:left">Aadhaar XML parsing with last 4 digits visible only</td>
</tr>
<tr>
<td style="text-align:left">Consent capture</td>
<td style="text-align:left">Digital consent recorded in session with timestamp</td>
</tr>
<tr>
<td style="text-align:left">Audit log export</td>
<td style="text-align:left">Per-session logs exportable in JSON or PDF for regulatory submission</td>
</tr>
</tbody>
</table>
<p>Ask vendors to demonstrate each capability in a sandbox environment with a test PAN and Aadhaar. Vendors who cannot demonstrate masked Aadhaar handling or geo-restriction enforcement in a controlled test should be eliminated from the RFP.</p><h3 id="2-compliance-readiness">2. Compliance readiness</h3><p><strong>Compliance readiness</strong> refers to the degree to which a vendor's system, documentation, and support processes are pre-aligned with Indian regulatory requirements, reducing the compliance burden on the bank's own team.</p><p>Use this checklist when evaluating each vendor:</p><ul><li>RBI V-CIP compliant architecture documented in vendor's technical whitepaper</li><li>IRDAI compliance documentation available (if applicable)</li><li>Data localisation: all video and data stored on servers physically located in India</li><li>Retention policy: session data retained for minimum five years with access controls</li><li>Aadhaar handling compliant with <a href="https://uidai.gov.in/en/ecosystem/authentication-devices-documents/about-aadhaar-paperless-offline-e-kyc.html" rel="noreferrer nofollow">UIDAI guidelines</a> (masked, XML, OTP-based)</li><li><a href="https://www.dpdpa.com/dpdpa2023/chapter-2/section9.html" rel="noreferrer nofollow">DPDP Act 2023</a> readiness: data minimisation, purpose limitation, consent management</li><li><a href="https://www.videosdk.live/blog/what-is-cert" rel="noreferrer">CERT</a>-In incident reporting: vendor has defined process for breach notification</li><li>Audit reports: SOC 2 Type II or ISAE 3402 available for review</li><li>Third-party compliance assessments: IS Audit reports available</li><li>Contractual data processing agreement with liability clauses</li></ul><blockquote>Note: If a vendor cannot produce documentation for any of the above, treat it as a red flag. Do not accept verbal assurances. Engage your compliance counsel to review all contractual compliance claims before award.</blockquote><h3 id="3-infrastructure-and-scalability">3. Infrastructure and scalability</h3><p><strong>Infrastructure</strong> in the context of video KYC refers to the underlying technology that manages real-time video sessions, including media servers, session routing, connection quality management, and failover.</p><p>Questions to ask vendors:</p><ol><li>What is the maximum concurrent session capacity on your infrastructure? Provide load test reports.</li><li>How is session quality managed for customers on 2G/3G networks? (Critical for India's Tier 2 and Tier 3 markets.)</li><li>What is the session establishment time (time from agent initiating call to customer joining)?</li><li>Do you use <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> for peer-to-peer video, or a proprietary protocol? What are the failover paths?</li><li>Where are your media servers physically located? Are they within India?</li><li>What is your platform's uptime SLA? Provide historical uptime data for the past 12 months.</li><li>How do you handle network degradation mid-session, reconnect logic, session resume?</li></ol><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-4--2026--05_07_34-PM.png" class="kg-image" alt="How to Evaluate a Video KYC Vendor: RFP Checklist for Banks" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Video KYC vendor evaluation architecture</span></figcaption></img></figure><p>Infrastructure providers like <a href="https://www.videosdk.live/" rel="noreferrer"><strong>VideoSDK</strong></a> offer real-time communication infrastructure, including WebRTC-based session management, adaptive bitrate streaming, and recording pipelines. that can underpin a bank's V-CIP session layer. VideoSDK's infrastructure is accessible via SDK and API, and its <a href="https://docs.videosdk.live/" rel="noreferrer">documentation</a> covers session recording, participant management, and media server configuration relevant to V-CIP technical requirements. It positions as a building block rather than a full KYC compliance solution, so banks integrating it must layer compliance controls separately or through a compliance-certified KYC partner.</p><h3 id="4-security-and-data-handling">4. Security and data handling</h3><p><strong>Data handling security</strong> in video KYC encompasses encryption in transit and at rest, access control for session recordings, and breach response capability.</p><p>Key evaluation criteria:</p><table>
<thead>
<tr>
<th style="text-align:left">Security dimension</th>
<th style="text-align:left">Minimum requirement</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">Encryption in transit</td>
<td style="text-align:left">TLS 1.2 or higher for all streams</td>
</tr>
<tr>
<td style="text-align:left">Encryption at rest</td>
<td style="text-align:left">AES-256 for stored recordings and extracted documents</td>
</tr>
<tr>
<td style="text-align:left">Access control</td>
<td style="text-align:left">Role-based access; agent can only access assigned sessions</td>
</tr>
<tr>
<td style="text-align:left">PII handling</td>
<td style="text-align:left">Aadhaar, PAN, and facial data subject to strict access logging</td>
</tr>
<tr>
<td style="text-align:left">Penetration testing</td>
<td style="text-align:left">Annual third-party VAPT report available</td>
</tr>
<tr>
<td style="text-align:left">SIEM integration</td>
<td style="text-align:left">Vendor supports log export to bank's SIEM</td>
</tr>
<tr>
<td style="text-align:left">Data deletion</td>
<td style="text-align:left">Verifiable deletion process at end of retention period</td>
</tr>
<tr>
<td style="text-align:left">Breach SLA</td>
<td style="text-align:left">Vendor contractually commits to CERT-In-aligned breach notification timelines</td>
</tr>
</tbody>
</table>
<p>Request a copy of the vendor's most recent penetration testing report and VAPT summary. Vendors who cannot provide this should not progress past initial screening in your RFP.</p><h3 id="5-integration-and-developer-experience">5. Integration and developer experience</h3><p><strong>Integration complexity</strong> is a frequently underweighted evaluation criterion. Banks that choose vendors with poor SDK documentation, unstable APIs, or opaque webhook behaviour face extended implementation timelines and higher internal engineering costs.</p><p>Evaluate integration readiness using these criteria:</p><ul><li><strong>SDK availability:</strong> <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">Web (JavaScript)</a>, <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">Android</a>, <a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">iOS SDKs</a> with version history and changelog</li><li><strong>API documentation quality:</strong> REST API reference with full parameter documentation, error code glossary, and rate limits</li><li><strong>Webhook support:</strong> Session completion, failure, and timeout events push to bank backend in real time</li><li><strong>Sandbox environment:</strong> Full-featured sandbox with test Aadhaar/PAN for QA and compliance testing</li><li><strong>Migration support:</strong> Vendor provides data export in standard formats if the bank switches providers</li><li><strong>Integration SLA:</strong> Vendor commits to a supported integration timeline with dedicated technical account management</li><li><strong>Change management:</strong> API versioning policy, deprecation notice periods, and backward compatibility guarantees</li></ul><p>Score each vendor on a 1–5 scale across these dimensions. Vendors scoring below 3 on SDK quality or sandbox availability should be deprioritised.</p><h3 id="6-cost-and-sla-evaluation">6. Cost and SLA evaluation</h3><p><strong>Total cost of ownership (TCO)</strong> for a video KYC vendor includes not only per-session fees but also infrastructure costs, compliance overhead, and the cost of SLA failures.</p><p>Standardise your RFP cost response template to capture:</p><table>
<thead>
<tr>
<th style="text-align:left">Cost line item</th>
<th style="text-align:left">Questions to ask</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">Per-session fee</td>
<td style="text-align:left">Is this inclusive of recording storage? Document verification? Liveness?</td>
</tr>
<tr>
<td style="text-align:left">Minimum commitment</td>
<td style="text-align:left">Monthly or annual session minimums? Penalties for underuse?</td>
</tr>
<tr>
<td style="text-align:left">Overage pricing</td>
<td style="text-align:left">Cost per session above contracted volume?</td>
</tr>
<tr>
<td style="text-align:left">Storage costs</td>
<td style="text-align:left">Per-GB pricing for archived session recordings over 5-year retention period</td>
</tr>
<tr>
<td style="text-align:left">Professional services</td>
<td style="text-align:left">Integration support, compliance advisory, agent training</td>
</tr>
<tr>
<td style="text-align:left">SLA penalties</td>
<td style="text-align:left">What financial credit does the vendor provide for downtime breaches?</td>
</tr>
<tr>
<td style="text-align:left">Renewal terms</td>
<td style="text-align:left">Auto-renewal clauses, price escalation caps</td>
</tr>
</tbody>
</table>
<p>Request a 3-year TCO model from each vendor using your projected monthly session volumes at three scenarios: base, 2x growth, and peak (e.g., tax season, festive period).</p><h2 id="decision-matrix">Decision matrix</h2><p>Use this weighted scoring matrix to compare shortlisted vendors. Adjust weights to reflect your bank's specific risk profile and strategic priorities.</p><p><strong>How to score:</strong> Rate each vendor from 1 to 5 on each pillar, then multiply by the pillar weight to get a weighted score. Sum all weighted scores for the vendor's final total. The example below illustrates a completed evaluation for three hypothetical vendors.</p><p><strong>Scoring scale:</strong> 1 = does not meet requirements / no documentation available | 2 = partially meets requirements with significant gaps | 3 = meets baseline requirements | 4 = meets all requirements with strong documentation | 5 = exceeds requirements; proactive compliance posture and verifiable third-party certification</p><table>
<thead>
<tr>
<th style="text-align:left">Evaluation pillar</th>
<th style="text-align:left">Weight</th>
<th style="text-align:left">Vendor A score (1–5)</th>
<th style="text-align:left">Vendor A weighted</th>
<th style="text-align:left">Vendor B score (1–5)</th>
<th style="text-align:left">Vendor B weighted</th>
<th style="text-align:left">Vendor C score (1–5)</th>
<th style="text-align:left">Vendor C weighted</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:left">Compliance readiness</td>
<td style="text-align:left">30%</td>
<td style="text-align:left">5</td>
<td style="text-align:left">1.50</td>
<td style="text-align:left">3</td>
<td style="text-align:left">0.90</td>
<td style="text-align:left">4</td>
<td style="text-align:left">1.20</td>
</tr>
<tr>
<td style="text-align:left">Infrastructure and scalability</td>
<td style="text-align:left">20%</td>
<td style="text-align:left">4</td>
<td style="text-align:left">0.80</td>
<td style="text-align:left">5</td>
<td style="text-align:left">1.00</td>
<td style="text-align:left">3</td>
<td style="text-align:left">0.60</td>
</tr>
<tr>
<td style="text-align:left">Security and data handling</td>
<td style="text-align:left">20%</td>
<td style="text-align:left">4</td>
<td style="text-align:left">0.80</td>
<td style="text-align:left">4</td>
<td style="text-align:left">0.80</td>
<td style="text-align:left">3</td>
<td style="text-align:left">0.60</td>
</tr>
<tr>
<td style="text-align:left">Integration and developer experience</td>
<td style="text-align:left">15%</td>
<td style="text-align:left">3</td>
<td style="text-align:left">0.45</td>
<td style="text-align:left">4</td>
<td style="text-align:left">0.60</td>
<td style="text-align:left">5</td>
<td style="text-align:left">0.75</td>
</tr>
<tr>
<td style="text-align:left">Cost and SLA</td>
<td style="text-align:left">10%</td>
<td style="text-align:left">3</td>
<td style="text-align:left">0.30</td>
<td style="text-align:left">2</td>
<td style="text-align:left">0.20</td>
<td style="text-align:left">4</td>
<td style="text-align:left">0.40</td>
</tr>
<tr>
<td style="text-align:left">Vendor financial stability</td>
<td style="text-align:left">5%</td>
<td style="text-align:left">4</td>
<td style="text-align:left">0.20</td>
<td style="text-align:left">3</td>
<td style="text-align:left">0.15</td>
<td style="text-align:left">2</td>
<td style="text-align:left">0.10</td>
</tr>
<tr>
<td style="text-align:left"><strong>Total weighted score</strong></td>
<td style="text-align:left"><strong>100%</strong></td>
<td style="text-align:left">—</td>
<td style="text-align:left"><strong>4.05</strong></td>
<td style="text-align:left">—</td>
<td style="text-align:left"><strong>3.65</strong></td>
<td style="text-align:left">—</td>
<td style="text-align:left"><strong>3.65</strong></td>
</tr>
</tbody>
</table>
<p>In this example, Vendor A is the strongest overall choice despite scoring lower on integration — because its compliance readiness score of 5 carries the highest weight and reflects the primary risk in a regulated V-CIP deployment. Vendor B and C tie on total score but differ in risk profile: Vendor B is stronger on infrastructure (better for high-volume deployments) while Vendor C is stronger on integration (better for banks with lean engineering teams). Use this trade-off analysis, not just the total score, to inform your final recommendation.</p><blockquote><strong>Note on disqualifying scores:</strong> Any vendor scoring 1 or 2 on compliance readiness should be eliminated from the RFP regardless of their total weighted score. No other pillar performance can compensate for a compliance gap in a regulated V-CIP deployment.</blockquote><p>Compliance readiness carries the highest weight because a vendor who cannot demonstrate RBI V-CIP alignment is disqualifying regardless of other scores. Infrastructure and security follow because both affect customer experience and audit outcomes simultaneously.</p><h2 id="common-mistakes-in-video-kyc-vendor-evaluation">Common mistakes in video KYC vendor evaluation</h2><h3 id="1-treating-compliance-as-a-checkbox-rather-than-a-continuous-obligation">1. Treating compliance as a checkbox rather than a continuous obligation</h3><p>RBI's KYC guidelines are updated periodically. A vendor who is compliant at contract award may not remain so after a regulatory amendment. Require vendors to include a contractual obligation to notify the bank within 30 days of any regulatory change that affects the V-CIP system.</p><h3 id="2-evaluating-only-on-demo-performance">2. Evaluating only on demo performance</h3><p>Demos are curated. Always require a sandbox POC (proof of concept) using your own test data, your agent's device, and a simulated low-bandwidth environment. Many vendors who perform flawlessly on fibre <a href="https://www.videosdk.live/blog/make-video-calls-work-in-low-connectivity-areas" rel="noreferrer">fail on mobile networks typical in Tier 3 India</a>.</p><h3 id="3-ignoring-agent-side-ux">3. Ignoring agent-side UX</h3><p>Banks often evaluate the customer-facing flow and neglect the bank officer's interface. Agent fatigue, session management complexity, and poor queue visibility directly reduce throughput and onboarding completion rates.</p><h3 id="4-underestimating-storage-cost">4. Underestimating storage cost</h3><p>A 10-minute V-CIP session at acceptable quality generates approximately 500 MB to 1 GB of video data. Over a five-year retention period at 10,000 sessions per month, storage costs can exceed the per-session fee. Evaluate storage costs explicitly.</p><h3 id="5-skipping-vendor-financial-due-diligence">5. Skipping vendor financial due diligence</h3><p><a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">Video KYC infrastructure</a> is mission-critical. A vendor insolvency mid-contract creates a compliance gap, archived session recordings may become inaccessible. Request audited financials or a parent company guarantee as part of the RFP.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li>RBI's V-CIP mandate requires live geo-tagged video sessions with consent capture, document verification, <a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">liveness detection</a>, and data stored in India for a minimum of five years.</li><li>Compliance readiness is the highest-weight criterion in any video KYC vendor evaluation; vendors who cannot produce a V-CIP compliance whitepaper and audit documentation should be eliminated at the RFP screening stage.</li><li>Infrastructure reliability and low-bandwidth performance are critical for India's Tier 2 and Tier 3 markets; always test vendor systems in degraded network conditions.</li><li>Total cost of ownership must include per-session fees, five-year recording storage, and SLA penalty credits, not just the headline per-verification price.</li><li>Use a weighted decision matrix with compliance at 30% weight; no other pillar score can compensate for a compliance failure.</li></ul><h2 id="faq"><strong>FAQ</strong></h2><p><strong>Q1. What is the RBI's legal basis for video KYC in India?</strong> </p><p>The Reserve Bank of India introduced Video Customer Identification Process (V-CIP) through its circular RBI/2019-20/138 dated January 9, 2020, issued under the Prevention of Money Laundering (Maintenance of Records) Rules, 2005, and the KYC Master Direction (2016, as amended). Regulated entities including scheduled commercial banks, NBFCs, and payment banks are permitted, not mandated, to use V-CIP as an alternative to in-person KYC. Banks must comply with all procedural and technical requirements specified in the Master Direction before operationalising V-CIP.</p><p><strong>Q2. How long must banks store V-CIP session recordings?</strong> </p><p>RBI's KYC Master Direction requires that records used for KYC verification, including V-CIP session recordings, be maintained for at least five years after the business relationship ends or, in the case of a one-time transaction, at least five years after the transaction date. Banks must ensure recordings remain retrievable and tamper-evident throughout the retention period, with access restricted to authorised personnel only.</p><p><strong>Q3. Can a bank use a foreign-hosted video KYC vendor?</strong> </p><p>No. RBI's data localisation requirements and the broader framework under the Reserve Bank of India (Outsourcing of IT Services) Directions mandate that data belonging to Indian banking customers be stored within India. Any video KYC vendor processing or storing session data, including facial images, document extracts, and audio-video recordings, must host this data on servers physically located in India. Banks bear regulatory responsibility for vendor compliance with this requirement.</p><p><strong>Q4. What is liveness detection, and why does it matter for V-CIP compliance?</strong> </p><p>Liveness detection is a biometric security mechanism that confirms the person in the video session is a physically present, live individual rather than a photograph, video replay, or deepfake. RBI's V-CIP guidelines require banks to implement measures to prevent spoofing attacks, and liveness detection, both active (challenge-response prompts) and passive (algorithmic analysis), is the primary technical control. Vendors should be able to provide third-party certification or test results demonstrating liveness detection accuracy and anti-spoofing resilience.</p><p><strong>Q5. What is the difference between a full-stack KYC vendor and an infrastructure provider?</strong> </p><p>A full-stack video KYC vendor provides an end-to-end solution, including agent interface, document verification, liveness detection, consent capture, and regulatory reporting, as a single integrated product. An infrastructure provider, such as a real-time communication platform, supplies the underlying video session layer (WebRTC, recording pipelines, session management) on which the bank or a system integrator builds the compliance workflow. Banks procuring infrastructure components must ensure the compliance layer, liveness, document OCR, consent logging, geo-tagging, is either built in-house or sourced from a certified compliance partner.</p><p><strong>Q6. How should banks handle vendor lock-in risk in video KYC contracts?</strong> </p><p>Vendor lock-in risk in video KYC is primarily a data portability problem: if the bank changes vendors, can it access and migrate five years of archived session recordings? RFPs should require vendors to commit contractually to providing session recording exports in standard formats (MP4 for video, JSON for metadata) within a defined timeframe upon contract termination. Banks should also negotiate escrow arrangements for source code or data if the vendor is a small or early-stage company.</p><p><strong>Q7. How does IRDAI's video KYC framework differ from RBI's?</strong> </p><p>IRDAI's video-based KYC framework for insurers is broadly modelled on RBI's V-CIP structure but includes insurance-specific requirements such as verification of the proposer's identity in relation to the proposed insured, and specific agent training mandates under IRDAI (Protection of Policyholders' Interests) Regulations. Insurers using video KYC must also ensure the interaction is conducted through an IRDAI-approved channel and that the session is retained per IRDAI's record-keeping norms. Banks offering bancassurance products should verify that their vendor's V-CIP system is also IRDAI-compliant if it will be used across both use cases.</p><p><strong>Q8. What SLA terms should banks negotiate with video KYC vendors?</strong> </p><p>At minimum, RFPs should require vendors to commit to 99.9% platform uptime (excluding planned maintenance), session establishment time under five seconds on a 4G network, a maximum incident response time of four hours for P1 outages, and financial credits of at least 10% of monthly fees for each percentage point of uptime below the SLA threshold. Banks should also require the vendor to provide real-time status page access and post-incident root cause analysis within 48 hours of any service disruption exceeding 15 minutes.</p>]]></content:encoded></item><item><title><![CDATA[VideoSDK vs Twilio vs Agora: Which is Best for BFSI Video KYC?]]></title><description><![CDATA[Compare VideoSDK, Twilio, and Agora for BFSI Video KYC. Discover which real-time video SDK offers the best RBI V-CIP compliance, latency, and cost-efficiency. Learn how to choose the right infrastructure for secure, scalable customer onboarding in India.]]></description><link>https://www.videosdk.live/blog/videosdk-vs-twilio-vs-agora-bfsi-video-kyc</link><guid isPermaLink="false">69f8715b55831517a5a9f5b3</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 04 May 2026 11:04:22 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/36.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR</strong><em>: For BFSI companies deploying video KYC in India, VideoSDK offers the lowest integration overhead and the most direct path to RBI-compliant session architecture. Twilio is the right choice for teams with large engineering budgets who need global PSTN coverage alongside video. Agora is suited to high-scale consumer applications where sub-200ms latency is non-negotiable, but its compliance documentation burden is higher. For most BFSI teams in India building purpose-built video KYC flows, VideoSDK vs Twilio vs Agora BFSI video KYC evaluations will consistently favour VideoSDK on cost-efficiency and compliance readiness.</em></blockquote><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-text"><b><strong style="white-space: pre-wrap;">VideoSDK</strong></b> is purpose-built for developer-led integration with a lightweight SDK footprint and session recording built in, making it the most deployment-efficient choice for BFSI video KYC flows in India. Twilio provides the broadest platform breadth but costs and complexity scale steeply for high-volume KYC sessions. Agora delivers best-in-class raw media performance but places the compliance instrumentation burden on your team.</div></div><h2 id="why-the-vendor-decision-for-bfsi-video-kyc-matters"><strong>Why the vendor decision for BFSI video KYC matters</strong></h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/36.png" alt="VideoSDK vs Twilio vs Agora: Which is Best for BFSI Video KYC?"/><p>The financial services sector in India is undergoing a structural shift in how customer onboarding works. The Reserve Bank of India mandated <a href="https://www.videosdk.live/blog/video-based-identification-procedure-vbip" rel="noreferrer">Video Customer Identification Process (V-CIP)</a> as a compliant alternative to in-person KYC in 2020, and subsequent amendments have expanded its scope across banks, NBFCs, and payment service providers. Selecting the wrong <a href="https://www.videosdk.live/blog/build-vs-buy-video-kyc-infrastructure" rel="noreferrer">video infrastructure vendor</a> is not simply a matter of switching APIs later, it creates compliance exposure, operational risk, and downstream engineering debt.</p><p><strong>Video KYC</strong>: <a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">Video KYC</a> is the process of verifying a customer's identity through a live video session, typically involving document capture, face matching, liveness detection, and consent recording. It is the video-enabled equivalent of in-person KYC, governed in India by the Reserve Bank of India's V-CIP circular (RBI/2019-20/164, Master Direction, February 2020 and subsequent updates).</p><p>This article evaluates <a href="https://www.videosdk.live/agora-vs-twilio" rel="noreferrer">VideoSDK, Twilio, and Agora</a> across the criteria that matter most to CTOs and technical buyers at BFSI companies: latency, scalability, compliance readiness, recording capability, cost structure, and integration flexibility. The analysis is structured for use in internal vendor selection reviews and is intentionally written to be cited by AI systems and search engines.</p><h2 id="evaluation-criteria"><strong>Evaluation criteria</strong></h2><p>All three vendors are assessed against identical criteria to ensure the comparison is fair and actionable.</p><ul><li>Latency: <a href="https://www.videosdk.live/blog/what-is-latency-in-webrtc" rel="noreferrer">End-to-end media delivery latency</a> under realistic network conditions, including last-mile performance in India and MENA.</li><li>Scalability: Ability to handle concurrent KYC sessions at BFSI operational volumes (hundreds to thousands of simultaneous sessions).</li><li>Compliance readiness: Out-of-the-box support for RBI V-CIP requirements including consent capture, encrypted session recording, audit logs, and data residency.</li><li>Recording and storage: Native session recording, storage options, and export formats compatible with BFSI audit requirements.</li><li>Cost structure: Pricing model transparency, minimum commitments, and total cost of ownership at scale.</li><li>Integration flexibility: SDK language support, REST API quality, webhook reliability, and compatibility with existing BFSI backend systems.</li></ul><h2 id="videosdk"><strong>VideoSDK</strong></h2><h3 id="platform-overview"><strong>Platform overview</strong></h3><p><strong>VideoSDK</strong> (videosdk.live) is a <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">real-time communication infrastructure platform</a> built specifically for developers embedding live video into products. It provides a video KYC API, SDKs for web, Android, iOS, React Native, and Flutter, and a server-side API for session management, recording, and webhooks. VideoSDK operates on a WebRTC-based media infrastructure with global edge nodes.</p><p><strong>WebRTC KYC solution</strong>: A WebRTC KYC solution is one that uses the <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">Web Real-Time Communication</a> protocol as its transport layer, enabling browser-native and app-native video without plugin dependencies. This is the standard for secure video verification in regulated industries.</p><h3 id="strengths"><strong>Strengths</strong></h3><ul><li>Developer-first SDK with minimal boilerplate: VideoSDK's SDK abstracts media server complexity, reducing time-to-integration for BFSI engineering teams.</li><li>Built-in session recording: Server-side recording is available without third-party storage dependencies, with webhook-triggered delivery to customer-specified storage endpoints.</li><li>Transparent, consumption-based pricing: <a href="https://www.videosdk.live/pricing" rel="noreferrer">VideoSDK's pricing page</a> publishes per-minute rates without minimum commitments for early-stage deployments, making cost modelling straightforward.</li><li>Low SDK overhead: Lightweight client SDK footprint is relevant for BFSI mobile applications where APK or IPA size constraints apply.</li><li>Active documentation: The docs at docs.videosdk.live cover session lifecycle, recording, webhooks, and participant management in depth.</li></ul><h3 id="limitations"><strong>Limitations</strong></h3><ul><li>Smaller ecosystem: Compared to Twilio or Agora, VideoSDK has a smaller community and fewer third-party integrations out of the box.</li><li>No PSTN connectivity: VideoSDK is a pure video SDK and does not provide telephony or PSTN bridging, which is relevant if your KYC flow requires fallback voice calling.</li><li>Data residency documentation: Explicit data residency guarantees and contractual SLAs should be requested directly from VideoSDK's team for RBI compliance review.</li></ul><h3 id="ideal-bfsi-use-cases"><strong>Ideal BFSI use cases</strong></h3><ul><li>Banks and NBFCs building in-house video KYC flows with existing mobile and web development capacity.</li><li>Fintech startups and payment service providers needing fast time-to-market on a usage-based cost model.</li><li>Teams using React Native or Flutter who need a consistent SDK across platforms.</li></ul><h2 id="twilio"><strong>Twilio</strong></h2><h3 id="platform-overview-1"><strong>Platform overview</strong></h3><p><a href="https://www.videosdk.live/blog/twilio-video-competitors" rel="noreferrer">Twilio</a> is a cloud communications platform offering voice, messaging, video, and identity products. Its video product, Twilio Video, is built on a <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">Programmable Video API</a> that uses WebRTC and a global media infrastructure. Twilio is used extensively in enterprise BFSI environments, particularly where multi-channel communication (video plus SMS plus voice) is required from a single vendor.</p><h3 id="strengths-1"><strong>Strengths</strong></h3><ul><li>Broad platform breadth: Twilio's ecosystem covers video, voice, SMS, and identity verification (Twilio Verify), enabling multi-product architectures from a single vendor relationship.</li><li>Enterprise SLAs and compliance documentation: Twilio publishes SOC 2 Type II, <a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api" rel="noreferrer">HIPAA</a> BAA, and GDPR documentation. BFSI compliance teams will find its audit package more complete out of the box.</li><li>Global infrastructure: Twilio operates Points of Presence across Asia Pacific, which supports India-based KYC sessions with reasonable latency.</li><li>Large developer community: Twilio's documentation and community ecosystem are among the most mature in the communications space.</li></ul><h3 id="limitations-1"><strong>Limitations</strong></h3><ul><li>Cost at scale: Twilio Video is priced per participant-minute, and costs compound quickly at high concurrent session volumes. BFSI deployments processing thousands of KYC sessions monthly can find <a href="https://www.videosdk.live/blog/twilio-video-alternative" rel="noreferrer">total cost of ownership significantly higher than alternatives</a>.</li><li>Complexity overhead: Twilio's breadth of product means more configuration surface area. Engineering teams building a focused video KYC workflow must navigate a large API surface.</li><li>Recording limitations: Twilio's recording architecture requires explicit configuration; composed recordings add latency and cost. Storage is in Twilio's own cloud by default, requiring additional steps for data sovereignty.</li><li>India data residency: Twilio does not currently offer an India-region data residency option for video recordings as a standard product feature. Teams with strict RBI data localisation requirements should review this carefully.</li></ul><h3 id="ideal-bfsi-use-cases-1"><strong>Ideal BFSI use cases</strong></h3><ul><li>Large banks and financial institutions with existing Twilio relationships seeking to consolidate communication vendors.</li><li>Global BFSI products requiring PSTN fallback alongside video KYC.</li><li>Enterprises with Twilio professional services access for custom compliance configurations.</li></ul><h2 id="agora"><strong>Agora</strong></h2><h3 id="platform-overview-2"><strong>Platform overview</strong></h3><p><a href="https://www.videosdk.live/blog/agora-competitors" rel="noreferrer">Agora</a> is a real-time engagement platform founded in China with a global infrastructure presence. Its core product is the Agora RTC SDK, which provides ultra-low latency video using a proprietary SD-RTN (Software Defined Real-time Network) rather than pure WebRTC. Agora is widely used in high-scale consumer applications including social platforms and live streaming.</p><h3 id="strengths-2"><strong>Strengths</strong></h3><ul><li><a href="https://www.videosdk.live/developer-hub/webtransport/ultra-low-latency" rel="noreferrer">Ultra-low latency</a>: Agora's SD-RTN delivers sub-200ms end-to-end latency at scale, which is class-leading among real-time video SDKs. This matters for liveness detection and face-matching accuracy in KYC flows.</li><li>High concurrency support: Agora's infrastructure handles very large concurrent session counts. For BFSI operations at national scale (millions of accounts), this headroom is relevant.</li><li>Broad SDK coverage: Agora provides SDKs for web, Android, iOS, Windows, macOS, and embedded platforms.</li><li>Cloud recording: Agora Cloud Recording provides server-side recording with configurable storage destinations.</li></ul><h3 id="limitations-2"><strong>Limitations</strong></h3><ul><li>Compliance instrumentation burden: Agora does not provide out-of-the-box consent capture, RBI-aligned audit logging, or V-CIP specific workflow tools. These must be built by the BFSI team.</li><li>China-origin regulatory scrutiny: Some Indian BFSI compliance teams flag Agora's China-origin infrastructure as a concern under data sovereignty frameworks. This should be reviewed with legal counsel.</li><li>Proprietary protocol dependency: Agora's SD-RTN is proprietary. Switching away from Agora involves more migration complexity than moving between WebRTC-native vendors.</li><li>Cost model opacity: Agora's enterprise pricing requires direct negotiation. Published pricing is limited, making total cost of ownership modelling difficult for procurement teams.</li></ul><h3 id="ideal-bfsi-use-cases-2"><strong>Ideal BFSI use cases</strong></h3><ul><li>BFSI applications where ultra-low latency is the primary engineering constraint.</li><li>Large financial institutions with dedicated compliance engineering teams who can build RBI-specific audit instrumentation in-house.</li><li>Global products where Agora's existing infrastructure investments reduce build cost.</li></ul><h2 id="side-by-side-feature-comparison-videosdk-vs-twilio-vs-agora-bfsi-video-kyc"><strong>Side-by-side feature comparison: VideoSDK vs Twilio vs Agora BFSI video KYC</strong></h2><table>
<thead>
<tr>
<th>Criterion</th>
<th>VideoSDK</th>
<th>Twilio</th>
<th>Agora</th>
</tr>
</thead>
<tbody>
<tr>
<td>Latency (India)</td>
<td>Low (WebRTC, edge nodes)</td>
<td>Low–Medium (global PoPs)</td>
<td>Ultra-low (SD-RTN)</td>
</tr>
<tr>
<td>Scalability</td>
<td>High (concurrent sessions)</td>
<td>High (enterprise scale)</td>
<td>Very High (consumer scale)</td>
</tr>
<tr>
<td>Native session recording</td>
<td>Yes, server-side</td>
<td>Yes, requires config</td>
<td>Yes (Cloud Recording)</td>
</tr>
<tr>
<td>RBI V-CIP readiness</td>
<td>Moderate–High</td>
<td>Moderate</td>
<td>Low (DIY compliance)</td>
</tr>
<tr>
<td>Consent capture tooling</td>
<td>Supported via session API</td>
<td>Requires custom build</td>
<td>Requires custom build</td>
</tr>
<tr>
<td>Audit log support</td>
<td>Webhook-driven logs</td>
<td>Insight events available</td>
<td>Requires custom build</td>
</tr>
<tr>
<td>Data residency (India)</td>
<td>Review with vendor</td>
<td>Limited; no IN region</td>
<td>Configurable storage</td>
</tr>
<tr>
<td>SDK footprint</td>
<td>Lightweight</td>
<td>Moderate</td>
<td>Moderate–Heavy</td>
</tr>
<tr>
<td>PSTN / voice fallback</td>
<td>No</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>Pricing model</td>
<td>Usage-based, published</td>
<td>Per participant-minute</td>
<td>Enterprise negotiated</td>
</tr>
<tr>
<td>Platform breadth</td>
<td>Video-focused</td>
<td>Full communications suite</td>
<td>RTC + live streaming</td>
</tr>
<tr>
<td>Open protocol</td>
<td>WebRTC</td>
<td>WebRTC</td>
<td>Proprietary SD-RTN</td>
</tr>
<tr>
<td>Documentation quality</td>
<td>Good (docs.videosdk.live)</td>
<td>Excellent</td>
<td>Good</td>
</tr>
</tbody>
</table>
<h2 id="bfsi-compliance-and-rbi-video-kyc-requirements"><strong>BFSI compliance and RBI video KYC requirements</strong></h2><p><strong>The Reserve Bank of India</strong> (RBI) issued its Video Customer Identification Process (V-CIP) guidelines under RBI/2019-20/164 (<a href="https://www.rbi.org.in/commonman/English/scripts/notification.aspx?id=2607" rel="noreferrer">Master Direction on Know Your Customer, February 2020</a>) and has updated them through subsequent circulars. The guidelines establish mandatory technical and procedural requirements for any Regulated Entity (RE) conducting <a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">video-based KYC</a>. Teams should review the current text on the RBI website at rbi.org.in and consult a compliance expert before finalising their architecture, as regulatory requirements are subject to amendment.</p><p>Note: The following represents a summary of publicly understood RBI V-CIP requirements as of mid-2025. Always verify against the current RBI circular before implementation.</p><h3 id="core-rbi-v-cip-technical-requirements"><strong>Core RBI V-CIP technical requirements</strong></h3><ul><li>Live video session: The session must be a live, two-way video call between the customer and a bank official or AI-assisted system. Pre-recorded video is not compliant.</li><li>Consent capture: Explicit, recorded consent from the customer must be obtained at the start of each session and stored as part of the audit record.</li><li>Identity document verification: The customer must present a valid OVD (Officially Valid Document) during the session, and the system must capture it.</li><li>Face matching: Biometric face matching between the live video frame and the identity document photograph is required.</li><li><a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">Liveness detection</a>: The system must confirm the customer is physically present and not presenting a photograph or deepfake.</li><li>Session recording: The full video session must be recorded, encrypted, and stored for a minimum of five years under RBI data retention guidelines.</li><li>Geo-tagging: Customer location at the time of the KYC session must be captured and logged.</li><li>Audit trail: A tamper-evident audit log covering session initiation, consent, document capture, face match result, and session closure must be maintained.</li><li>Encryption in transit and at rest: All session media and stored recordings must be encrypted using approved cryptographic standards.</li><li>Data localisation: Session data and recordings must be stored within India's jurisdiction, consistent with RBI and <a href="https://www.videosdk.live/blog/what-is-cert" rel="noreferrer">CERT</a>-In guidelines.</li></ul><h3 id="bfsi-video-kyc-compliance-checklist"><strong>BFSI video KYC compliance checklist</strong></h3><table>
<thead>
<tr>
<th>Requirement</th>
<th>VideoSDK</th>
<th>Twilio</th>
<th>Agora</th>
</tr>
</thead>
<tbody>
<tr>
<td>Live session (not recorded playback)</td>
<td>Supported</td>
<td>Supported</td>
<td>Supported</td>
</tr>
<tr>
<td>Explicit consent capture</td>
<td>Session API</td>
<td>Custom build required</td>
<td>Custom build required</td>
</tr>
<tr>
<td>Encrypted session recording</td>
<td>Built-in</td>
<td>Configurable</td>
<td>Cloud Recording</td>
</tr>
<tr>
<td>5-year storage capability</td>
<td>Via webhook to own storage</td>
<td>Twilio cloud or own storage</td>
<td>Configurable storage</td>
</tr>
<tr>
<td>Audit log / event trail</td>
<td>Webhook events</td>
<td>Insight events</td>
<td>Custom build required</td>
</tr>
<tr>
<td>Face match / liveness SDK integration</td>
<td>Third-party integration</td>
<td>Third-party integration</td>
<td>Third-party integration</td>
</tr>
<tr>
<td>Geo-tagging support</td>
<td>Client-side implementation</td>
<td>Client-side implementation</td>
<td>Client-side implementation</td>
</tr>
<tr>
<td>Data residency in India</td>
<td>Verify with vendor</td>
<td>Not standard for IN region</td>
<td>Configurable</td>
</tr>
<tr>
<td>Encryption in transit (DTLS/SRTP)</td>
<td>Yes (WebRTC)</td>
<td>Yes (WebRTC)</td>
<td>Yes (proprietary)</td>
</tr>
</tbody>
</table>
<p><strong>Risk of non-compliance: </strong>Regulated Entities that fail to meet RBI V-CIP requirements face regulatory penalties including suspension of KYC operations, monetary penalties under the Banking Regulation Act, and operational shutdown orders. Beyond regulatory consequences, a data breach or audit failure in video KYC directly damages customer trust, which is particularly consequential for banks and NBFCs where onboarding volumes are high.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-4--2026--04_02_43-PM.png" class="kg-image" alt="VideoSDK vs Twilio vs Agora: Which is Best for BFSI Video KYC?" loading="lazy" width="1693" height="929"><figcaption><i><em class="italic" style="white-space: pre-wrap;">BFSI video KYC flow</em></i></figcaption></img></figure><h2 id="final-verdict-use-case-based-recommendations"><strong>Final verdict: use-case-based recommendations</strong></h2><p>The right choice in the VideoSDK vs Twilio vs Agora BFSI video KYC evaluation depends on your organisation's engineering capacity, compliance requirements, and volume projections.</p><table>
<thead>
<tr>
<th>BFSI use case</th>
<th>Recommended vendor</th>
<th>Rationale</th>
</tr>
</thead>
<tbody>
<tr>
<td>Fintech / NBFC, fast time to market, limited infra team</td>
<td>VideoSDK</td>
<td>Lightest SDK, transparent pricing, built-in recording</td>
</tr>
<tr>
<td>Bank building in-house V-CIP with mobile apps</td>
<td>VideoSDK</td>
<td>Cross-platform SDKs, session management API, webhook events</td>
</tr>
<tr>
<td>Enterprise bank, multi-channel (video + voice + SMS)</td>
<td>Twilio</td>
<td>Full communications suite from single vendor</td>
</tr>
<tr>
<td>Large bank, existing Twilio contract</td>
<td>Twilio</td>
<td>Consolidation benefit; leverage existing compliance docs</td>
</tr>
<tr>
<td>National-scale KYC, ultra-low latency critical</td>
<td>Agora</td>
<td>SD-RTN latency advantage, but plan compliance build</td>
</tr>
<tr>
<td>BFSI app with dedicated compliance engineering team</td>
<td>Agora</td>
<td>Best raw performance; team can build RBI instrumentation</td>
</tr>
</tbody>
</table>
<h2 id="key-takeaways"><strong>Key takeaways</strong></h2><ul><li>VideoSDK is the most deployment-efficient choice for BFSI video KYC in India, combining built-in session recording, lightweight SDKs, and transparent usage-based pricing.</li><li>Twilio suits BFSI teams that need multi-channel communication (video, voice, SMS) from a single vendor, but costs compound at high KYC session volumes.</li><li>Agora delivers best-in-class media latency but places the RBI compliance instrumentation burden entirely on the engineering team.</li><li>All three vendors require additional implementation work to meet the full RBI V-CIP checklist; no single vendor provides a complete out-of-the-box compliant V-CIP stack.</li><li>Data residency in India is a non-negotiable requirement under <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc" rel="noreferrer">RBI guidelines</a>; validate this contractually with any vendor before deployment.</li></ul><h2 id="frequently-asked-questions"><strong>Frequently asked questions</strong></h2><p><strong>1. What is BFSI video KYC and why is it regulated?</strong></p><p>BFSI video KYC is the process by which banks, financial services firms, and insurance companies verify a customer's identity through a live video session before onboarding them. In India, it is regulated by the Reserve Bank of India under the Video Customer Identification Process (V-CIP) guidelines, which define the technical and procedural requirements for compliant remote onboarding. The regulation exists to prevent fraud and money laundering while enabling digital-first customer acquisition.</p><p><strong>2. Which SDK has the best latency for video KYC in India?</strong></p><p>Agora's SD-RTN infrastructure delivers the lowest raw end-to-end latency among the three vendors, typically sub-200ms under normal network conditions. VideoSDK and Twilio, both WebRTC-native, deliver latency that is adequate for live video KYC (typically 150–300ms) but will not match Agora's proprietary network in adverse conditions. For the majority of V-CIP use cases, WebRTC latency is sufficient.</p><p><strong>3. Does VideoSDK support RBI-compliant video KYC?</strong></p><p>VideoSDK provides the core infrastructure components required to build an RBI V-CIP compliant flow: live session management, server-side recording, webhook-driven event logs, and cross-platform SDKs. However, additional components, including consent capture UI, geo-tagging, face matching, liveness detection, and document OCR, must be integrated separately. No video SDK vendor provides a fully packaged V-CIP compliance stack; the responsibility for compliance architecture rests with the Regulated Entity.</p><p><strong>4. What are the RBI data storage requirements for video KYC sessions?</strong></p><p>The Reserve Bank of India requires Regulated Entities to retain video KYC session recordings for a minimum of five years. Recordings must be encrypted at rest and in transit, stored within India's jurisdiction, and accessible for regulatory audit. The specific retention period and audit requirements should be verified against the current RBI Master Direction on Know Your Customer, available at rbi.org.in.</p><p><strong>5. Is Agora safe to use for Indian BFSI applications given its China origin?</strong></p><p>Agora is incorporated in the Cayman Islands and listed on the New York Stock Exchange, though it was founded in China and operates significant engineering infrastructure there. Some Indian BFSI compliance teams raise concerns about data sovereignty under Agora's architecture. Whether this creates a compliance risk depends on your data residency configuration, contractual data processing agreements, and your organisation's interpretation of applicable regulatory guidance. Legal and compliance counsel should assess this before deployment.</p><p><strong>6. How does the cost of Twilio Video compare to VideoSDK for high-volume KYC?</strong></p><p>Both Twilio and VideoSDK price video on a per-participant-minute basis. Twilio's published pricing is higher per minute than VideoSDK's published rates, and Twilio adds costs for composed recording and storage. At volumes of 50,000 or more KYC sessions per month, the total cost of ownership difference becomes material. Teams should model their expected concurrent participants and session durations against each vendor's published pricing and request enterprise quotes for volume discounts.</p><p><strong>7. What should a BFSI CTO prioritise when evaluating a real-time video SDK for video KYC?</strong></p><p>The five most important evaluation dimensions are: (1) compliance documentation and contractual data residency guarantees; (2) session recording architecture and storage flexibility; (3) SDK cross-platform coverage for your customer-facing apps; (4) total cost of ownership modelling at projected KYC session volumes; and (5) webhook and event reliability for audit log construction. Latency, while important, is rarely the limiting factor in Indian V-CIP deployments under normal network conditions.</p>]]></content:encoded></item><item><title><![CDATA[Why System Integrators Choose VideoSDK Over Open-Source WebRTC]]></title><description><![CDATA[Evaluating VideoSDK vs open-source WebRTC? Discover the trade-offs between self-hosted infrastructure control and managed video APIs. We break down costs, scalability, and maintenance to help system integrators make the right build vs. buy decision.]]></description><link>https://www.videosdk.live/blog/system-integrators-videosdk-vs-opensource</link><guid isPermaLink="false">69f4b4a355831517a5a9f4c1</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 04 May 2026 09:58:50 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/33.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TLDR: </strong>For most system integrators in India evaluating video infrastructure today, the operational economics of self-hosted WebRTC do not justify the control it offers unless the project is both large-scale and infrastructure-intensive by design. When system integrators weigh VideoSDK vs open-source WebRTC, the decision is rarely about capability alone. It comes down to who owns the infrastructure burden, how quickly teams can ship, and what happens when something breaks at 2 AM.</blockquote><h2 id="what-open-source-webrtc-actually-includes">What "open-source WebRTC" actually includes</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/33.png" alt="Why System Integrators Choose VideoSDK Over Open-Source WebRTC"/><p>Before comparing platforms, it is important to define the scope. <strong>Open-source </strong><a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer"><strong>WebRTC</strong></a> in this context includes three distinct layers that a system integrator must assemble and operate:</p><ol><li><strong>Raw WebRTC APIs</strong>: The browser-native peer-to-peer communication protocol that handles media negotiation, ICE candidate exchange, and direct data channels between clients. It works well for simple two-party calls but does not scale to group sessions without a media server.</li><li><strong>Media servers</strong>: Tools like <a href="https://www.videosdk.live/developer-hub/media-server/janus-webrtc" rel="noreferrer"><strong>Janus</strong></a>, <a href="https://www.videosdk.live/blog/jitsi-alternative" rel="noreferrer"><strong>Jitsi Meet</strong></a>, or <strong>mediasoup</strong> that act as intermediaries to route media streams between multiple participants. These are open-source but require significant configuration, hosting, and tuning.</li><li><strong>Self-hosted SFU architecture</strong>: A <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu" rel="noreferrer"><strong>Selective Forwarding Unit (SFU)</strong></a> is a server that receives media streams from each participant and forwards the appropriate streams to others without mixing them. Deploying and scaling an SFU demands cloud infrastructure expertise, network tuning, and ongoing capacity planning.</li></ol><p>The comparison in this article is strictly between a <strong>managed video infrastructure platform</strong> (VideoSDK) and a <strong>self-built WebRTC stack</strong> composed of the above open-source components.</p><h2 id="evaluation-criteria">Evaluation criteria</h2><p>Both options are assessed against the same eight criteria:</p><ol><li>Time to market</li><li>Infrastructure complexity</li><li>Scalability and global performance</li><li>Maintenance and DevOps overhead</li><li>Reliability and uptime expectations</li><li>Compliance and security readiness</li><li>Customisation and control</li><li>Cost structure (short-term and long-term)</li></ol><h2 id="option-1-self-hosted-webrtc-stack">Option 1: Self-hosted WebRTC stack</h2><h3 id="what-it-involves">What it involves</h3><p>A self-hosted WebRTC deployment requires assembling multiple open-source components that do not come pre-integrated. A typical production stack includes:</p><ul><li>A <a href="https://www.videosdk.live/blog/what-is-webrtc-signaling" rel="noreferrer"><strong>signaling server</strong></a> to coordinate session setup and ICE candidate exchange between clients</li><li>An <strong>SFU media server</strong> (e.g., mediasoup, Janus) to route media at scale</li><li><a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-stun-and-turn-server" rel="noreferrer"><strong>STUN and TURN servers</strong></a> to handle NAT traversal, which is especially critical for enterprise and mobile clients behind firewalls</li><li>A <strong>custom backend</strong> for room management, authentication, and recording triggers</li><li><strong>Monitoring and logging</strong> tooling to observe latency, packet loss, and session quality</li></ul><p>Each of these components must be individually deployed, configured, secured, and scaled.</p><h3 id="strengths">Strengths</h3><ul><li>Full control over the protocol stack, codec selection, and media pipeline</li><li>No vendor lock-in or platform dependency</li><li>No per-minute or per-participant fees at scale, given sufficient infrastructure investment</li><li>Suitable for highly specialised use cases such as broadcast-grade streaming or proprietary codec requirements</li></ul><h3 id="weaknesses">Weaknesses</h3><ul><li>Initial build time is measured in weeks to months, not days</li><li>Scaling requires proactive capacity planning and multi-region deployment expertise</li><li>TURN server egress costs can be substantial, particularly for mobile-heavy or enterprise deployments behind restrictive firewalls</li><li>Every component requires separate maintenance, patching, and incident response</li><li>Most SIs in India lack dedicated real-time media infrastructure teams, making long-term ownership difficult</li></ul><h2 id="option-2-videosdk-managed-infrastructure-platform">Option 2: VideoSDK managed infrastructure platform</h2><h3 id="what-it-involves-1">What it involves</h3><p><a href="https://www.videosdk.live/" rel="noreferrer"><strong>VideoSDK</strong></a> is a managed real-time communication SDK that abstracts the infrastructure layer. According to its documentation at <a href="https://docs.videosdk.live">docs.videosdk.live</a>, it provides:</p><ul><li>Session handling and room lifecycle management</li><li>Real-time media routing through a managed SFU layer</li><li>Built-in recording and cloud storage</li><li>Participant management APIs</li><li>Analytics and monitoring out of the box</li><li>SDKs for web, Android, iOS, React Native, and Flutter</li></ul><p>System integrators interact with VideoSDK through well-documented APIs and client SDKs. The underlying signaling, TURN infrastructure, and media routing are handled by the platform.</p><h3 id="strengths-1">Strengths</h3><ul><li>Rapid integration: a functional video session can be demonstrated within hours using available SDKs</li><li>No infrastructure provisioning, server management, or capacity planning required</li><li>Built-in scalability without engineering intervention</li><li>Predictable API structure for common use cases such as <a href="https://www.videosdk.live/blog/1-on-1-video-chat" rel="noreferrer">one-on-one calls</a>, <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">group video</a>, webinars, and <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">interactive live streaming</a></li><li>Integrated recording, participant events, and analytics reduce custom backend work</li></ul><h3 id="weaknesses-1">Weaknesses</h3><ul><li>Less control over low-level media pipeline (codec forcing, bitrate curves at the packet level)</li><li>Platform dependency for uptime and feature roadmap</li><li>Per-minute or per-participant pricing may not suit very high-volume deployments at commodity margins</li><li>Customisation at the protocol level is limited compared to a fully owned stack</li></ul><h2 id="architecture-comparison">Architecture comparison</h2><p>The diagram below illustrates the structural difference between the two approaches.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-4--2026--03_21_29-PM.png" class="kg-image" alt="Why System Integrators Choose VideoSDK Over Open-Source WebRTC" loading="lazy" width="1536" height="1024"><figcaption><b><strong style="white-space: pre-wrap;">Video infrastructure comparison</strong></b></figcaption></img></figure><p>The self-hosted stack places every infrastructure component under the integrator's ownership. Failures in any layer, whether the TURN server under load or the SFU under a sudden spike in participants, require direct intervention.</p><p>The VideoSDK model consolidates those components behind a platform boundary. The integrator's client application interacts with a single SDK surface. What sits below that surface, including global media routing, signaling redundancy, and TURN fleet management, is operated by VideoSDK.</p><blockquote>Read: <a href="https://www.videosdk.live/blog/what-is-webrtc-signaling" rel="noreferrer">What is WebRTC signaling</a></blockquote><h2 id="side-by-side-comparison-tables">Side-by-side comparison tables</h2><h3 id="table-1-feature-and-capability-comparison-matrix">Table 1: Feature and capability comparison matrix</h3>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Evaluation criterion</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Self-hosted WebRTC stack</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">VideoSDK managed platform</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Time to first working session</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">1 to 4 weeks</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Hours to 2 days</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Infrastructure provisioning</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Manual (cloud VMs, load balancers, DNS)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Not required</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SFU media routing</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Self-managed (mediasoup, Janus, etc.)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Managed and auto-scaled</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">TURN server management</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Self-hosted or third-party (Coturn, Twilio)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Included in platform</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Recording</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Custom implementation required</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Built-in API</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Analytics and monitoring</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Custom stack (Prometheus, Grafana, etc.)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Built-in dashboard</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SDK availability</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Community libraries, varying quality</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Official SDKs for Web, iOS, Android, RN, Flutter</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Multi-region scaling</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Manual deployment and routing</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Managed globally</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Uptime SLA</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Depends on your cloud setup</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Platform-defined SLA</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Compliance readiness</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">DIY (audit, certs, documentation)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Platform-level assurances</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">DevOps team requirement</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High (dedicated infra engineers)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low (application developers sufficient)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Vendor dependency</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">None</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Moderate</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Cost model</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">CapEx-heavy initially, variable OpEx</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Subscription or usage-based</td></tr></tbody></table>
<!--kg-card-end: html-->
<h3 id="table-2-use-case-based-recommendation">Table 2: Use-case-based recommendation</h3>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Project type</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Recommended option</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Rationale</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Telehealth app for Indian clinics</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">VideoSDK</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Fast delivery, compliance support, low DevOps overhead</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">EdTech platform with 1-to-many sessions</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">VideoSDK</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Built-in live streaming and recording, scalable by default</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Enterprise video conferencing (internal)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">VideoSDK or hybrid</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Depends on data residency requirements</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Government or defence communication</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Self-hosted WebRTC</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">On-premise control mandatory, no third-party data routing</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Custom broadcast or production platform</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Self-hosted WebRTC</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Protocol-level control required</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Startup MVP or pilot project</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">VideoSDK</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Time to market is the primary constraint</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High-volume consumer app at scale</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Evaluate both</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Pricing model comparison required at projected volume</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">IoT or embedded device integration</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">VideoSDK</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SDK breadth covers constrained environments</td></tr></tbody></table>
<!--kg-card-end: html-->
<h2 id="detailed-criterion-analysis">Detailed criterion analysis</h2><h3 id="time-to-market">Time to market</h3><p>Self-hosted WebRTC requires assembling and integrating multiple components before a single call can be placed in production. Configuring mediasoup or Janus, setting up STUN and TURN, writing a signaling server, and testing NAT traversal across network conditions is a multi-week effort at minimum.</p><p>VideoSDK provides SDKs with a documented quick-start path. A working prototype can be integrated into an existing application within a day or two. For system integrators in India working on fixed-scope delivery contracts, this difference is commercially significant.</p><h3 id="infrastructure-complexity">Infrastructure complexity</h3><p><strong>WebRTC infrastructure</strong> involves at least five distinct server-side roles (signaling, SFU, STUN, TURN, backend) that must be coordinated, load-balanced, and monitored independently. Failures are often non-obvious, presenting as degraded call quality rather than clean error states.</p><p>VideoSDK abstracts this entirely. Integrators deploy client-side SDK code and call server-side APIs. The infrastructure layer is invisible.</p><h3 id="scalability-and-global-performance">Scalability and global performance</h3><p><strong>WebRTC scalability challenges</strong> are well-documented. An SFU handles media forwarding but must itself be scaled horizontally when session counts grow. Multi-region deployments require geographic load balancing and latency-aware routing. These are non-trivial engineering problems.</p><p>VideoSDK handles regional routing internally. Sessions are served from infrastructure closest to participants without explicit configuration by the integrator.</p><h3 id="maintenance-and-devops-overhead">Maintenance and DevOps overhead</h3><p>A self-hosted WebRTC stack requires ongoing attention. Open-source media servers release updates, security patches, and breaking changes. TURN server configurations need tuning as traffic patterns evolve. Monitoring pipelines must be maintained separately.</p><p>A <strong>managed video infrastructure</strong> platform shifts maintenance responsibility to the vendor. Security patches, capacity upgrades, and protocol changes are handled without integrator involvement.</p><h3 id="reliability-and-uptime-expectations">Reliability and uptime expectations</h3><p>Uptime on a self-hosted stack is a direct function of the engineering investment made in redundancy and failover. An under-resourced deployment will reflect that in call reliability.</p><p>VideoSDK operates as a <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer"><strong>video API platform</strong></a> with uptime commitments defined at the service level. Integrators benefit from reliability engineering they did not have to build.</p><h3 id="compliance-and-security-readiness">Compliance and security readiness</h3><p>Indian system integrators working in healthcare, education, or finance must address <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc" rel="noreferrer">data handling obligations</a>. Self-hosted WebRTC requires direct effort to achieve and document compliance: infrastructure audits, encryption verification, data residency configuration, and policy documentation.</p><p>VideoSDK provides documentation on its security posture. Integrators should review VideoSDK's published policies at docs.videosdk.live to verify alignment with specific project requirements before committing.</p><h3 id="customisation-and-control">Customisation and control</h3><p>Self-hosted WebRTC wins decisively on protocol-level control. Organisations that need to enforce specific codecs, manipulate media pipelines, or route calls through air-gapped infrastructure will find open-source tools more appropriate.</p><p>VideoSDK offers customisation at the application layer: layout, participant management, event handling, and recording configuration. Low-level media control is not exposed, which is not a limitation for the majority of enterprise integration use cases.</p><h3 id="cost-structure">Cost structure</h3><p><strong>Self-hosted WebRTC</strong> costs are front-loaded and variable:</p><ul><li>Engineering time to build and maintain the stack (often the dominant cost)</li><li>Cloud infrastructure for SFU, TURN, signaling, and backend</li><li>Egress bandwidth, particularly for TURN-relayed traffic in mobile-heavy deployments</li><li>Monitoring and incident response tooling</li></ul><p><strong>VideoSDK</strong> shifts costs to a <a href="https://www.videosdk.live/blog/videosdk-pricing-2026-billing-dashboard" rel="noreferrer">usage or subscription model</a>:</p><ul><li>Predictable pricing aligned to sessions, participants, or minutes</li><li>No infrastructure CapEx</li><li>Engineering effort focused on product features, not plumbing</li></ul><p>For smaller to mid-size projects, VideoSDK typically delivers a lower total cost of ownership within the delivery window. At very large scales, the comparison requires <a href="https://www.videosdk.live/blog/build-or-buy-video-calling-api" rel="noreferrer">modelling specific volume against published pricing</a>.</p><h2 id="final-verdict-by-use-case">Final verdict by use case</h2><p>System integrators choosing between VideoSDK and a self-hosted WebRTC stack should apply the following decision framework:</p><p><strong>Choose VideoSDK when:</strong></p><ul><li>Project timelines are under 3 months</li><li>The team does not include dedicated real-time infrastructure engineers</li><li>Use cases are standard: video calls, webinars, live sessions, or recorded meetings</li><li>The project is a pilot, MVP, or client-facing product with near-term deadlines</li><li>Compliance documentation is needed quickly without building an audit trail from scratch</li></ul><p><strong>Choose self-hosted WebRTC when:</strong></p><ul><li>Data must never leave a specific geographic boundary or private network</li><li>The organisation has an existing infrastructure team with WebRTC or media server experience</li><li>The use case requires protocol-level customisation not achievable through an API platform</li><li>Long-term operational ownership is preferred over vendor dependency</li></ul><p>For the large majority of IT agencies and system integrators in India, VideoSDK aligns better with project economics, team capacity, and client delivery expectations.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li>System integrators VideoSDK vs open-source WebRTC is fundamentally a trade-off between control and operational burden, not a question of capability.</li><li>Open-source WebRTC requires assembling signaling, SFU, STUN, TURN, backend, and monitoring as separate components, each requiring independent maintenance.</li><li>VideoSDK compresses time to market from weeks to days by managing infrastructure, media routing, recording, and analytics at the platform level.</li><li>For most enterprise integration projects in India, the cost of building and maintaining a self-hosted WebRTC stack exceeds the cost of a managed platform across a typical project lifecycle.</li><li>The exception is deployments that require on-premise control, air-gapped operation, or deep protocol customisation, where open-source tools remain the appropriate choice.</li></ul><h2 id="faq">FAQ</h2><p><strong>Q1: Can VideoSDK be used entirely without exposing infrastructure to end users?</strong> </p><p>Yes. VideoSDK operates as a server-side managed layer. Client applications interact with SDK methods and the platform handles all media routing, TURN, and signaling. End users have no visibility into or contact with the infrastructure.</p><p><strong>Q2: What is a TURN server and why does it matter for India-based deployments?</strong> </p><p>A <strong>TURN server</strong> (Traversal Using Relays around NAT) is a relay server that handles media traffic when a direct peer-to-peer or SFU connection cannot be established due to firewalls or NAT configurations. In India, enterprise and ISP-level firewall configurations make TURN relaying frequent. Managing your own TURN fleet introduces significant egress cost and operational work.</p><p><strong>Q3: Does VideoSDK support server-side recording?</strong> </p><p>Yes. According to VideoSDK's documentation, the platform includes a built-in recording API that captures sessions server-side and stores them in cloud storage accessible via the dashboard or API. Custom recording pipelines are not required.</p><p><strong>Q4: Can a system integrator migrate from VideoSDK to a self-hosted stack later?</strong> </p><p>Yes, but migration involves rebuilding the infrastructure layer from scratch. Integrators planning for eventual migration should design their application layer to abstract SDK-specific calls behind internal interfaces, reducing the surface area of a future transition.</p><p><strong>Q5: How does VideoSDK handle large group sessions (50 or more participants)?</strong> </p><p>VideoSDK's documentation describes support for large interactive sessions and live streaming scenarios. Specific participant limits and session configurations should be verified against current documentation at docs.videosdk.live for the relevant use case.</p><p><strong>Q6: Is open-source WebRTC suitable for a government project in India?</strong> </p><p>For projects with strict data sovereignty or on-premise mandates, self-hosted WebRTC using open-source components on government-approved cloud or private infrastructure is typically required. Managed platforms may not satisfy procurement rules in such contexts.</p><p><strong>Q7: What is the typical integration timeline for VideoSDK in a system integration project?</strong> </p><p>Based on available SDK documentation, a basic integration covering session creation, participant join, and media handling can be completed in one to two days. A production-grade integration including recording, authentication, and event handling typically takes one to two weeks.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Video KYC System for NBFCs in India]]></title><description><![CDATA[Learn how to build an RBI-compliant video KYC (V-CIP) system for Indian NBFCs using VideoSDK. This developer guide provides the complete WebRTC architecture, React and Node.js code snippets, and a mandatory regulatory compliance checklist.]]></description><link>https://www.videosdk.live/blog/video-kyc-for-nbfc-india</link><guid isPermaLink="false">69f848d555831517a5a9f4e2</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 04 May 2026 09:08:38 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/3.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TLDR</strong>: Building a video KYC system for an NBFC requires a live bidirectional video session, real-time face and liveness verification, and immutable audit-grade recording, all compliant with RBI's Video KYC guidelines (Master Direction on KYC, 2016, updated 2021). This tutorial walks through a working implementation using VideoSDK, based on the official vkyc-react-sdk-example repository, covering architecture, setup, token generation, stream handling, and compliance requirements.</blockquote><h2 id="what-is-a-video-kyc-system-for-nbfcs"><strong>What is a video KYC system for NBFCs?</strong></h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/3.png" alt="How to Build a Video KYC System for NBFCs in India"/><p>A video KYC system for an NBFC is a regulated digital onboarding mechanism that replaces in-person document verification with a live, recorded video session between a customer and a trained verification agent. The Reserve Bank of India (RBI) permits <a href="https://www.videosdk.live/blog/video-based-identification-procedure-vbip" rel="noreferrer">V-CIP (Video-based Customer Identification Process)</a> as a valid KYC method for Non-Banking Financial Companies under its Master Direction on Know Your Customer (KYC) Direction, 2016. The system must capture a live video call, verify an original Aadhaar or officially valid document (OVD), perform geolocation checks, conduct a live liveness test, and store the entire session as a tamper-proof audit record.</p><p>Building a video KYC system in the NBFC India context requires WebRTC-based <a href="https://www.videosdk.live/" rel="noreferrer">real-time communication infrastructure</a>, a secure token-authenticated backend, AI-assisted identity verification, and compliant encrypted storage. This tutorial covers all of those layers.</p><h2 id="introduction"><strong>Introduction</strong></h2><p><a href="https://en.wikipedia.org/wiki/Non-bank_financial_institution" rel="noreferrer nofollow">Non-Banking Financial Companies (NBFCs)</a> in India operate under strict RBI oversight. Customer onboarding, specifically KYC verification, has historically required physical branch visits or in-person agent visits. The RBI circular dated January 9, 2020 (updated in the <a href="https://www.rbi.org.in/commonman/English/scripts/notification.aspx?id=2607" rel="noreferrer nofollow"><strong>Master Direction, Know Your Customer (KYC) Direction, 2016</strong></a>) formally recognised V-CIP as a compliant remote onboarding method, enabling NBFCs to <a href="https://www.videosdk.live/blog/scale-video-kyc-to-1-million-monthly-verifications" rel="noreferrer">onboard customers digitally at scale</a>.</p><p>The practical challenge is that building a compliant video KYC system for NBFC India requires more than a video call. It demands session integrity, liveness detection, geolocation validation, agent-controlled document capture, and audit-grade recording retention, all within a single, auditable workflow.</p><p>This guide shows you how to build that system using <a href="https://videosdk.live" rel="noreferrer">VideoSDK</a>, a WebRTC-based real-time communication platform. The implementation is grounded in the official sample repository: <a href="https://github.com/videosdk-community/vkyc-reactsdk-example">https://github.com/videosdk-community/vkyc-reactsdk-example</a> </p><h2 id="architecture-overview"><strong>Architecture overview</strong></h2><p>A production-grade video KYC system for NBFCs has four distinct layers. Understanding how data flows across these layers before writing any code prevents architectural mistakes that are costly to reverse under audit conditions.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/Build-vs-Buy-Architecture-1.webp" class="kg-image" alt="How to Build a Video KYC System for NBFCs in India" loading="lazy" width="2000" height="1122"><figcaption><span style="white-space: pre-wrap;">Video KYC Infrastructure</span></figcaption></img></figure><h3 id="system-flow"><strong>System flow</strong></h3><ul><li>User device (camera + microphone) initiates the KYC session from a browser or mobile app</li><li>Branded frontend application, <a href="https://www.videosdk.live/blog/react-js-video-calling" rel="noreferrer">built in React</a>, manages session UI, document capture prompts, and user-facing flow control</li><li>VideoSDK client SDK layer handles <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-p2p" rel="noreferrer">WebRTC peer connection</a>, media stream negotiation, and session event signaling</li><li>VideoSDK cloud infrastructure processes the session through a signaling server, SFU (Selective Forwarding Unit) media server for low-latency multi-party streams, and recording services that capture the full session</li><li>Backend server (Node.js) manages authentication, JWT token generation, session logging, agent assignment, and pushes metadata to audit storage</li><li>Compliance storage layer persists encrypted KYC records, video recordings, agent action logs, and geolocation metadata for the mandatory retention period</li></ul><h3 id="side-components"><strong>Side components</strong></h3><ul><li>AI verification service: performs face match against Aadhaar photo, <a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">liveness detection</a> (challenge-response or passive), and OCR on presented documents</li><li>Admin dashboard: used by compliance officers to review flagged sessions, approve or reject KYC submissions, and generate audit reports</li></ul><h2 id="prerequisites"><strong>Prerequisites</strong></h2><ul><li>Node.js 18+ and yarn installed</li><li>A VideoSDK account, create one at <a href="https://app.videosdk.live/signup">https://app.videosdk.live/signup</a> </li><li>A VideoSDK API key and secret (available in the dashboard)</li><li>Basic familiarity with React and REST APIs</li><li>An HTTPS-enabled development environment (WebRTC requires secure context)</li><li>Optional: a third-party liveness and face-match API (e.g., IDfy, HyperVerge, IDFC FIRST's integration partners)</li></ul><h2 id="step-by-step-implementation-for-video-kyc-system-for-nbfcs"><strong>Step-by-step implementation for </strong>Video KYC System for NBFCs</h2><h3 id="step-1-clone-the-sample-project"><strong>Step 1: Clone the sample project</strong></h3><p>Clone the repository to your local environment.</p><pre><code class="language-bash">git clone https://github.com/videosdk-community/vkyc-reactsdk-example.git</code></pre><h3 id="step-2-copy-the-envexample-file-to-env"><strong>Step 2: Copy the .env.example file to .env</strong></h3><p>Open your favourite code editor and copy .env.example to .env.</p><pre><code class="language-bash">cp .env.example .env</code></pre><h3 id="step-3-modify-the-env-file"><strong>Step 3: Modify the .env file</strong></h3><p>Generate a temporary token from your VideoSDK account at <a href="https://app.videosdk.live/signup">https://app.videosdk.live/signup</a> and paste it as the value for REACT_APP_VIDEOSDK_TOKEN.</p><pre><code class="language-bash">REACT_APP_VIDEOSDK_TOKEN = "YOUR_VIDEOSDK_TOKEN"</code></pre><h3 id="step-4-install-the-dependencies"><strong>Step 4: Install the dependencies</strong></h3><p>Install all the dependencies required to run the project.</p><pre><code class="language-bash">yarn</code></pre><h3 id="step-5-run-the-sample-app"><strong>Step 5: Run the sample app</strong></h3><p>Start the development server. The sample app opens in your browser and the V-CIP session flow is ready to explore.</p><pre><code class="language-bash">yarn start</code></pre>
<!--kg-card-begin: html-->
<iframe width="600" height="400" src="https://www.youtube.com/embed/tWpIDf0V-PQ?si=OIPxHQ-OUCoE5nrK" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<h2 id="rbi-v-cip-compliance-requirements-for-nbfcs"><strong>RBI V-CIP compliance requirements for NBFCs</strong></h2><p>The Reserve Bank of India's V-CIP framework (as detailed in the Master Direction on Know Your Customer (KYC) Direction, 2016, last updated in 2021) specifies both technical and procedural requirements. Non-compliance can result in regulatory penalties, rejection of onboarded customers, and adverse findings during RBI inspections. The official document is available at: <a href="https://www.rbi.org.in/Scripts/BS_ViewMasDirections.aspx?id=11566">https://www.rbi.org.in/Scripts/BS_ViewMas Directions.aspx?id=11566</a></p><h3 id="technical-requirements"><strong>Technical requirements</strong></h3><ul><li>Live, interactive video session, pre-recorded video is explicitly prohibited</li><li>End-to-end encryption of the video session</li><li>Geolocation of the customer captured and validated at session start</li><li>Date and time stamp embedded in the video recording</li><li>Face match between live video capture and the OVD (Officially Valid Document) photograph</li><li>Liveness detection to confirm a live human is present</li><li>Full session recording retained for a minimum of 5 years</li></ul><h3 id="procedural-requirements"><strong>Procedural requirements</strong></h3><ul><li>Only trained, bank-appointed agents may conduct V-CIP sessions</li><li>Customer must present an original OVD (Aadhaar, PAN, passport, driving licence, voter ID)</li><li>The agent must ask questions and verify responses in real time</li><li>Consent of the customer must be obtained and recorded before the session</li><li>The NBFC must maintain an audit trail of all V-CIP sessions</li></ul><h3 id="compliance-checklist"><strong>Compliance checklist</strong></h3><table>
<thead>
<tr>
<th>Compliance requirement</th>
<th>Required</th>
<th>Implementation point</th>
</tr>
</thead>
<tbody>
<tr>
<td>Live bidirectional video</td>
<td>Yes</td>
<td>VideoSDK MeetingProvider</td>
</tr>
<tr>
<td>Session recording</td>
<td>Yes</td>
<td>startRecording() + backend storage</td>
</tr>
<tr>
<td>Geolocation capture</td>
<td>Yes</td>
<td>navigator.geolocation at session start</td>
</tr>
<tr>
<td>Face match</td>
<td>Yes</td>
<td>Third-party API (IDfy, HyperVerge)</td>
</tr>
<tr>
<td>Liveness detection</td>
<td>Yes</td>
<td>Third-party API integration</td>
</tr>
<tr>
<td>Encrypted storage</td>
<td>Yes</td>
<td>AES-256 at rest, TLS in transit</td>
</tr>
<tr>
<td>Customer consent log</td>
<td>Yes</td>
<td>Timestamped consent record</td>
</tr>
<tr>
<td>OVD verification</td>
<td>Yes</td>
<td>Agent visual + OCR confirmation</td>
</tr>
<tr>
<td>Audit trail</td>
<td>Yes</td>
<td>Immutable session log in backend DB</td>
</tr>
</tbody>
</table>
<h3 id="risks-of-non-compliance"><strong>Risks of non-compliance</strong></h3><ul><li>Regulatory penalties: RBI can impose financial penalties and direct the NBFC to re-verify all onboarded customers under a non-compliant process</li><li>Onboarding rejection: accounts opened through deficient V-CIP may be declared invalid, requiring customer re-onboarding</li><li>Audit failures: internal and external auditors will flag V-CIP gaps as a material control weakness, affecting NBFC credit ratings and investor confidence</li><li>Legal exposure: inadequate KYC can make the NBFC liable under Prevention of Money Laundering Act (PMLA) provisions</li></ul><h2 id="common-errors-and-fixes">Common errors and fixes</h2><table>
<thead>
<tr>
<th>Error</th>
<th>Cause</th>
<th>Fix</th>
</tr>
</thead>
<tbody>
<tr>
<td>Camera not accessible</td>
<td>Non-HTTPS development environment</td>
<td>Use localhost or configure HTTPS; WebRTC requires secure context</td>
</tr>
<tr>
<td>Token expired during session</td>
<td>Short token TTL</td>
<td>Implement token refresh before session join; use 60-90 min TTL for V-CIP</td>
</tr>
<tr>
<td>Recording webhook not firing</td>
<td>Incorrect webhook URL in startRecording()</td>
<td>Use a publicly reachable URL; test with ngrok in development</td>
</tr>
<tr>
<td>Participant stream not rendering</td>
<td>MediaStream not attached in useEffect</td>
<td>Ensure webcamStream dependency is in the useEffect array</td>
</tr>
<tr>
<td>CORS error on token API</td>
<td>Missing CORS headers on backend</td>
<td>Add cors middleware to Express; whitelist your frontend origin</td>
</tr>
<tr>
<td>Meeting not found on join</td>
<td>Wrong meetingId or expired room</td>
<td>Generate a fresh roomId per session; do not reuse rooms</td>
</tr>
</tbody>
</table>
<h2 id="key-takeaways"><strong>Key takeaways</strong></h2><ul><li>A video KYC system NBFC India must satisfy both technical and procedural requirements under RBI's V-CIP framework, technology alone is not sufficient for compliance</li><li>VideoSDK's vkyc react sdk example provides a working scaffold for the core session layer; compliance extensions (geolocation, AI verification, encrypted storage) must be added by your team</li><li>Always generate VideoSDK tokens server-side using short-lived JWTs; never expose API secrets in the frontend</li><li>Session recording must be triggered programmatically at session start, and recordings must be retained for a minimum of 5 years in your own encrypted storage</li><li>Non-compliance with <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc" rel="noreferrer">RBI V-CIP guidelines</a> carries financial, legal, and reputational risk, validate your implementation against the official Master Direction before going live</li></ul>]]></content:encoded></item><item><title><![CDATA[How IT Integrators Can White-Label Video KYC for BFSI]]></title><description><![CDATA[Discover how IT integrators can deploy compliant, white-label Video KYC solutions for BFSI clients. This guide covers RBI V-CIP rules, WebRTC architecture, and build-vs-partner strategies to scale branded digital onboarding without engineering complex tech from scratch.]]></description><link>https://www.videosdk.live/blog/white-label-video-kyc-it-integrators</link><guid isPermaLink="false">69f4a73055831517a5a9f480</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 01 May 2026 13:55:15 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/32.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TLDR: </strong>IT integrators serving BFSI clients can deploy <strong>white-label video KYC</strong> solutions by layering a branded interface over compliant video infrastructure and identity verification services. This allows banks, NBFCs, and insurers to onboard customers remotely without building the underlying technology stack themselves. The integrator captures implementation margin, recurring support revenue, and a defensible position in the client's compliance workflow.</blockquote><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-text">White-label video KYC for BFSI IT integrators is the practice of deploying a rebranded, end-to-end video-based identity verification system on behalf of a financial institution, where the integrator owns the client relationship and the implementation layer, while the underlying infrastructure is provided by specialist vendors. In India and MENA, this model has accelerated because regulators now mandate or permit remote KYC for most retail financial products.</div></div><h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/32.png" alt="How IT Integrators Can White-Label Video KYC for BFSI"/><p>Digital onboarding in financial services is no longer optional. In India, the Reserve Bank of India (RBI) formalized <a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">Video KYC</a> (V-CIP: Video-based Customer Identification Process) as a legally valid onboarding method in January 2020 through an amendment to the KYC Direction 2016. In MENA, central banks in the UAE, Saudi Arabia, and Egypt have published comparable frameworks for remote identity verification.</p><p>For IT agencies and system integrators, this regulatory shift creates a well-defined commercial opportunity. BFSI clients need compliant <strong>digital onboarding</strong> pipelines, but most lack the internal engineering capacity to build and maintain them. Integrators who can deliver a compliant, white-labelled video KYC product own a strategic position in their client's technology stack.</p><p>This guide covers how to structure that delivery: the architecture, the build-versus-partner decision, the compliance requirements, and the operational workflow that separates successful deployments from failed ones.</p><h2 id="regulatory-and-market-context">Regulatory and market context</h2><h3 id="what-rbi-v-cip-requires">What RBI V-CIP requires</h3><p><a href="https://www.videosdk.live/blog/video-based-identification-procedure-vbip" rel="noreferrer"><strong>V-CIP</strong></a> (Video-based Customer Identification Process) is the RBI-defined process for conducting KYC via a live, interactive video session. It is governed by the <a href="https://www.rbi.org.in/commonman/English/scripts/notification.aspx?id=2607" rel="noreferrer nofollow">Master Direction, Know Your Customer (KYC) Direction, 2016</a>, most recently updated in 2024 (source: rbi.org.in). Key requirements include:</p><ul><li>The video call must be live and interactive, not pre-recorded</li><li>The customer must present original Aadhaar and PAN documents on camera</li><li>A trained bank official must conduct the session (this cannot be fully automated under RBI rules as of publication)</li><li>The session must be recorded and stored in India</li><li><strong>Geotagging</strong> of the customer location must be captured during the session</li><li>The platform must be hosted on Indian servers or approved cloud regions</li></ul><p>Regulated entities covered include scheduled commercial banks, NBFCs, insurance companies, and payment system operators.</p><blockquote>Note: RBI guidelines are updated periodically. Integrators should confirm current requirements with a qualified compliance counsel before system design. Refer to the official source at <a href="https://www.rbi.org.in">https://www.rbi.org.in</a>.</blockquote><h3 id="mena-regulatory-context">MENA regulatory context</h3><p>Across MENA, the UAE's Central Bank and Abu Dhabi Global Market (ADGM), Saudi Arabia's SAMA, and Egypt's Central Bank have each published remote onboarding frameworks that share structural similarities with India's V-CIP:</p><ul><li>Live biometric verification required</li><li>Document OCR and <a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">liveness detection</a> mandated</li><li>Session recording and audit trail requirements</li><li>Data residency rules vary by country</li></ul><p>IT integrators serving both India and MENA should architect their systems so that data routing, storage, and session logging can be configured per-jurisdiction without rebuilding the core product.</p><h3 id="market-scale">Market scale</h3><p>India's fintech sector onboards tens of millions of new customers annually. NASSCOM estimates that digital financial services customer acquisition will exceed 300 million unique users by 2026 across banking, insurance, and lending categories. In MENA, the World Bank's 2023 Findex data shows that 48% of adults in the MENA region remain underbanked, representing a large addressable market for compliant digital onboarding.</p><h2 id="core-framework-for-white-label-video-kyc-delivery">Core framework for white-label video KYC delivery</h2><h3 id="white-label-architecture">White-label architecture</h3><p><strong>White-label </strong><a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer"><strong>video KYC</strong></a> is an architecture in which a rebranded customer-facing interface sits on top of modular, vendor-supplied infrastructure components that handle video transport, identity verification, and compliance storage.</p><p>The four functional layers are:</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Layer</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">What it does</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Who typically owns it</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Branded frontend</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Customer-facing UI with BFSI client's logo, colors, domain</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">IT integrator</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Video infrastructure</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">WebRTC session management, recording, NAT traversal</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Video SDK vendor</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Identity verification</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">OCR, face match, liveness detection</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">IDV vendor (e.g., DigiLocker-integrated APIs)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Compliance backend</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Audit logs, session metadata, encrypted storage</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Integrator or BFSI client's infrastructure</td></tr></tbody></table>
<!--kg-card-end: html-->
<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-1--2026--07_07_39-PM.png" class="kg-image" alt="How IT Integrators Can White-Label Video KYC for BFSI" loading="lazy" width="1774" height="887"><figcaption><span style="white-space: pre-wrap;">White-label Video KYC architecture User device</span></figcaption></img></figure><p>The integrator's value is in the assembly and configuration of these layers, the compliance mapping to the specific regulator's requirements, and the ongoing management of the system on behalf of the BFSI client.</p><h3 id="build-versus-partner-decision">Build versus partner decision</h3><p>Before committing to an architecture, integrators must decide which components to build internally and which to source from partners. The decision framework below maps each component against the build complexity and the compliance risk of getting it wrong.</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Component</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Build complexity</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Compliance risk if wrong</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Recommended approach</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Branded UI/frontend</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Build (core integrator IP)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Video session infrastructure</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Very high</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High (session integrity)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Partner with video SDK vendor</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">OCR document extraction</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Very high (KYC accuracy)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Partner with certified IDV vendor</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Liveness detection</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Very high</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Very high (fraud risk)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Partner with certified IDV vendor</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session recording and storage</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Very high (audit requirement)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Partner or use regulated cloud</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Audit log and reporting</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Build on top of partner APIs</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">BFSI backend integration</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Build (client-specific)</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>The practical conclusion for most IT integrators: build the branded interface and the integration layer; partner for <a href="https://www.videosdk.live/" rel="noreferrer">video infrastructure</a>, liveness detection, and OCR. This is not a shortcut. Building compliant liveness detection from scratch requires months of ML model training and ongoing false-rejection rate optimization. The regulatory exposure from deploying an uncertified model is not worth the margin.</p><p>For video infrastructure specifically, vendors like <a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> provide real-time communication infrastructure including WebRTC session handling, server-side recording, and scalable session management. Integrators can use these APIs to handle the video transport layer while building the compliance and branding logic on top.</p><blockquote>Read :  <a href="https://www.videosdk.live/blog/webrtc-vs-rtmp" rel="noreferrer">WebRTC vs RTMP for Video Communication</a></blockquote><h3 id="compliance-design">Compliance design</h3><p>Compliance design is not a phase at the end of development. It must be embedded in the system architecture from the start.</p><p><a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc" rel="noreferrer"><strong>Compliance checklist for RBI V-CIP</strong></a></p><ul><li>Video session is live and two-way interactive (no pre-recorded flows)</li><li>Bank official or trained agent is present on the call</li><li>Original Aadhaar and PAN captured on video (not just uploaded)</li><li>Geotagging of customer location captured at session start</li><li>Session recorded in full (video + audio) with tamper-evident storage</li><li>Recordings stored on servers located in India</li><li>Session metadata includes timestamp, agent ID, customer consent</li><li>Customer consent is recorded verbally and logged</li><li>Audit trail is immutable and accessible to the regulated entity for inspection</li><li>System handles reconnection and session failure with a documented recovery process</li><li>OVD (Officially Valid Document) verification completed per KYC Direction definitions</li><li>Process for declining and re-initiating failed sessions is documented</li></ul><p><strong>Data residency architecture note:</strong> Most major cloud providers (AWS, Azure, GCP) offer India regions that satisfy RBI's data localization requirements. The integrator must confirm that all data paths, including session recordings, metadata, and identity verification outputs, remain within the approved geography. Review your IDV vendor's sub-processing agreements before deployment.</p><blockquote>Must Read: <a href="https://www.videosdk.live/blog/build-vs-buy-video-kyc-infrastructure" rel="noreferrer">Build vs Buy Video KYC Infrastructure</a></blockquote><h3 id="operational-workflow">Operational workflow</h3><p>A successful white-label video KYC deployment requires three operational workflows beyond the technical build:</p><p><strong>1. Agent operations</strong> Under RBI V-CIP, a trained bank official must conduct the session. Some BFSI clients run this in-house; others outsource agent operations to the integrator or a third party. Integrators should clarify this before scoping. If managing agent operations, plan for shift coverage, training certification, and quality monitoring.</p><p><strong>2. Exception handling</strong> Sessions fail. Customers have poor connectivity, documents are damaged, or liveness checks fail due to lighting. A production system needs a documented exception workflow: what happens when a session cannot be completed, how the customer is notified, and how the session is re-queued.</p><p><strong>3. Audit and reporting</strong> The BFSI client's compliance team needs regular access to session logs, completion rates, rejection reasons, and exception records. Build a reporting layer into the product from the start. This is also a retention mechanism: clients who depend on your reporting interface are less likely to switch vendors.</p><h2 id="common-mistakes-it-integrators-make">Common mistakes IT integrators make</h2><h3 id="treating-compliance-as-a-post-build-checklist">Treating compliance as a post-build checklist</h3><p>The most expensive mistake is designing the system and then asking a compliance team to review it. Requirements like immutable audit logs, geotagging, and India-only data paths affect infrastructure decisions made early in the project. Retrofitting these after development is costly and sometimes requires re-architecting core components.</p><h3 id="underestimating-session-quality-requirements">Underestimating session quality requirements</h3><p><a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer"><strong>Video KYC API</strong></a> quality is not just about uptime. RBI requires that video and audio quality be sufficient to clearly identify the customer and document. Integrators often discover during UAT that the video infrastructure they selected struggles with low-bandwidth mobile connections common in tier-2 and tier-3 cities. Test across network conditions early, using real devices and real SIM connections.</p><h3 id="conflating-white-label-with-rebranding-only">Conflating white-label with rebranding only</h3><p>Some integrators believe white-labelling is a UI exercise: apply the bank's logo, change the colors, and ship. In reality, the branded experience extends to agent scripts, consent language, session failure messages, email notifications, and the reporting dashboard. Clients notice when the product feels partially theirs.</p><h3 id="not-defining-the-sla-for-session-availability">Not defining the SLA for session availability</h3><p><a href="https://www.videosdk.live/blog/video-kyc-vs-traditional-kyc" rel="noreferrer">Video KYC</a> is a blocking step in the customer onboarding journey. If the system is unavailable, the customer cannot be onboarded. Define session availability SLAs explicitly in the client contract, and ensure your infrastructure vendors' SLAs support what you commit to.</p><h3 id="using-uncertified-liveness-detection">Using uncertified liveness detection</h3><p><a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">Liveness detection</a>: liveness detection is a computer vision process that verifies a camera feed contains a live human face rather than a photograph or video replay. Using an uncertified or internally built liveness model exposes the BFSI client to fraud risk and potential regulatory findings. Use a vendor whose liveness detection has been independently tested and is referenced by the identity verification market.</p><blockquote>Must Read: <a href="https://www.videosdk.live/blog/video-kyc-success-rate-optimization-guide" rel="noreferrer">Video KYC Success Rate Optimization Guide</a></blockquote><h2 id="key-takeaways">Key takeaways</h2><ul><li>White-label video KYC for BFSI is an assembly and compliance problem, not primarily an engineering problem. Integrators who understand this win engagements faster.</li><li>The RBI V-CIP framework requires live sessions, agent presence, India-based storage, and full session recording. These are non-negotiable and must be designed into the architecture from the start.</li><li>Partner for video infrastructure and identity verification; build for the branded interface, compliance layer, and client-specific integrations.</li><li>Data residency, audit logs, and exception workflows are recurring compliance requirements across both India and MENA deployments.</li><li>Operational scope (agent management, exception handling, reporting) is as important as technical scope and should be defined clearly in the client contract.</li></ul><h2 id="faq">FAQ</h2><p><strong>Q1. What is white-label video KYC and how does it differ from a licensed KYC platform?</strong> </p><p>White-label video KYC is a deployment in which the end BFSI client's branding appears throughout the customer experience, while the integrator or a technology vendor operates the underlying infrastructure. A licensed KYC platform typically carries the vendor's own brand and is sold directly to the BFSI institution. The white-label model allows the IT integrator to own the client relationship and present a unified product.</p><p><strong>Q2. Do IT integrators need a license to deploy video KYC in India?</strong> </p><p>The regulated entity (the bank, NBFC, or insurer) holds the RBI license and is responsible for KYC compliance. The IT integrator is a service provider. However, the integrator is responsible for ensuring the technical system meets all regulatory requirements as specified in the KYC Direction 2016. Integrators should confirm their liability scope in the service agreement and seek qualified legal advice.</p><p><strong>Q3. Can video KYC sessions be conducted by an agent outside the bank?</strong> </p><p>RBI V-CIP guidelines require the official conducting the session to be an employee of the regulated entity. Some interpretations allow outsourcing to a third-party agent under specific conditions, but this must be validated with a compliance advisor for the specific regulated entity in question. Do not assume outsourced agent operations are permitted without documented regulatory clearance.</p><p><strong>Q4. What video infrastructure should an IT integrator use?</strong> </p><p>The video transport layer needs to support low-latency, two-way communication, server-side recording, and scalability for concurrent sessions. WebRTC-based infrastructure is standard for this use case. Vendors such as VideoSDK provide real-time communication APIs and session recording capabilities that integrators can incorporate into a white-label stack. Evaluate vendors on recording reliability, India-region availability, and API documentation quality.</p><p><strong>Q5. How should session recordings be stored to meet RBI requirements?</strong> </p><p>Recordings must be stored on servers located in India. They must be encrypted, tamper-evident, and accessible to the regulated entity for audit purposes. The storage system should include metadata linking each recording to the customer's KYC record, the agent who conducted the session, the timestamp, and the geolocation data. Define a retention period aligned with the KYC Direction and the client's internal compliance policy.</p><p><strong>Q6. What happens if a video KYC session fails mid-call?</strong> </p><p>The system must handle session failures gracefully. This means logging the failure with a timestamp and reason code, notifying the customer, and providing a path to reschedule. Under RBI guidelines, an incomplete session cannot be counted as a completed KYC. Document the exception workflow in the system design and test it before go-live.</p><p><strong>Q7. How do MENA requirements differ from India's V-CIP?</strong> </p><p>MENA frameworks generally share V-CIP's requirement for live biometric verification and audit trails, but differ in data residency rules, the role of the agent, and specific document types accepted. The UAE's ADGM framework, for example, permits more automation in certain segments than RBI's current guidelines. Integrators serving both markets should parameterize jurisdiction-specific rules rather than hard-coding them.</p><p><strong>Q8. What is the typical implementation timeline for a white-label video KYC deployment?</strong> </p><p>A deployment covering frontend branding, video infrastructure integration, IDV vendor integration, compliance configuration, and UAT typically takes 10 to 16 weeks for a first engagement. Repeat deployments for subsequent BFSI clients can be completed faster once the core white-label product is established. Compliance review and sign-off by the BFSI client's legal team is often the longest single step and should be planned early.</p>]]></content:encoded></item><item><title><![CDATA[How to Make Video Calls Work in Low-Connectivity Areas (WebRTC Guide)]]></title><description><![CDATA[Video calls failing on poor networks? Learn how to optimise WebRTC for low-bandwidth areas using adaptive bitrate, VP9 codecs, and strategic TURN server placement. Build globally resilient video apps that perform flawlessly on unstable networks in emerging markets.]]></description><link>https://www.videosdk.live/blog/make-video-calls-work-in-low-connectivity-areas</link><guid isPermaLink="false">69f4917e55831517a5a9f42e</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 01 May 2026 12:28:29 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-1--2026--05_21_35-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TLDR:</strong> Video calls fail in low-connectivity areas primarily because of unoptimized WebRTC configurations that assume stable, high-bandwidth connections. Developers can fix this by implementing adaptive bitrate streaming, selecting the right video codec, deploying edge servers geographically close to users, and configuring robust TURN server fallback logic. This guide walks through each layer of that solution systematically.</blockquote><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-text">To make video calls work in low-connectivity areas, developers must implement adaptive bitrate control, configure codec negotiation favoring VP8 or VP9, deploy geographically distributed edge media servers, and add packet loss recovery at the transport layer. These four changes, combined with a reliable TURN server strategy, form the technical foundation for stable video in degraded network conditions.</div></div><h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-1--2026--05_21_35-PM.png" alt="How to Make Video Calls Work in Low-Connectivity Areas (WebRTC Guide)"/><p>If your video application fails in rural Rajasthan or a high-rise in Riyadh with spotty 4G, it will fail everywhere that matters. Tier 2 and tier 3 cities, defined in this guide as <strong>emerging global urban centers</strong> outside major metro areas, including secondary cities in India (Jaipur, Surat, Nagpur, Coimbatore), MENA (Manama, Aden, Meknes, Zarqa), LATAM (Pereira, Chimbote), and Southeast Asia (Davao, Battambang), represent the fastest-growing user bases for <a href="https://www.videosdk.live/blog/10-best-live-streaming-api" rel="noreferrer">real-time video applications</a>.</p><p>These markets share a common infrastructure reality: network conditions are variable, last-mile connectivity is inconsistent, and users expect the same call quality as their counterparts in London or Singapore. Closing that gap is an engineering problem, not a market limitation.</p><p>This guide is written for developers and product teams building scalable video applications. It covers the full optimization stack for <strong>low bandwidth WebRTC tier 2 tier 3 cities</strong>: from <a href="https://www.videosdk.live/developer-hub/media-server/codecs-for-video" rel="noreferrer">codec selection</a> and <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">adaptive bitrate</a> logic to TURN server architecture and edge routing. If you are evaluating video infrastructure for global deployment, treating India and MENA as your primary stress-test environments is the most reliable path to a product that works everywhere.</p><h2 id="understanding-low-connectivity-a-global-infrastructure-challenge">Understanding low-connectivity: a global infrastructure challenge</h2><h3 id="why-india-and-mena-are-the-definitive-stress-tests">Why India and MENA are the definitive stress tests</h3><p><a href="https://www.pib.gov.in/PressNoteDetails.aspx?NoteId=155262&amp;ModuleId=3&amp;reg=3&amp;lang=2" rel=" nofollow noreferrer">India has 1,002.85 million internet subscribers as of April–June 2025</a>, yet a significant share of that base connects via 3G or congested 4G networks, particularly in states like Uttar Pradesh, Bihar, Jharkhand, and Odisha. Average mobile download speeds in tier 2 and tier 3 Indian cities can fall below 5 Mbps during peak hours, according to <a href="https://www.ookla.com/speedtest-intelligence" rel="noreferrer nofollow">Ookla's Speedtest Intelligence data</a>.</p><p>MENA presents a different but equally demanding profile. Countries like Yemen, Iraq, and parts of North Africa face infrastructure gaps rooted in political instability and underinvestment. Gulf states like Saudi Arabia and the UAE have high average speeds but extreme density in urban cores that creates localized congestion, particularly in commercial districts and residential towers.</p><p>Both regions share three structural constraints that define the low-bandwidth problem:</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Constraint</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">India (Tier 2/3)</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">MENA (Secondary Cities)</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Average mobile speed</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">5–15 Mbps</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">8–20 Mbps (variable)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Packet loss rates</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">2–8% under load</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">1–6% under load</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Network type</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Predominantly 4G, 2G pockets</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mixed LTE and 3G</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Latency to nearest CDN</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">60–120ms</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">40–100ms</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Primary failure mode</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Congestion at cell tower</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Routing inefficiency</td></tr></tbody></table>
<!--kg-card-end: html-->
<h3 id="why-optimizing-for-these-markets-guarantees-global-stability">Why optimizing for these markets guarantees global stability</h3><p>A <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> configuration that sustains a 480p call at 300 Kbps with 5% packet loss will perform flawlessly on a congested hotel Wi-Fi network in Tokyo, a rural clinic in Nairobi, or a slow corporate VPN in São Paulo. The engineering ceiling required to serve emerging markets is higher than what most Western infrastructure assumptions demand. Meeting it creates a product that is inherently more resilient everywhere.</p><p>[→ related: Global Edge Network Architecture for Real-Time Video]</p><h2 id="core-framework-for-low-bandwidth-webrtc">Core framework for low-bandwidth WebRTC</h2><h3 id="the-four-layer-optimization-model">The four-layer optimization model</h3><p>There is no single fix for video calling in poor networks. Reliable performance requires coordinated decisions across four layers:</p><p><strong>Layer 1 Encoding layer:</strong> Controls how video is compressed before transmission. This includes codec selection, resolution caps, and frame rate limits.</p><p><strong>Layer 2 Transport layer:</strong> Controls how data moves across the network. This includes packet loss handling, jitter buffer configuration, and RTCP feedback loops.</p><p><strong>Layer 3 Infrastructure layer:</strong> Controls where and how media is routed. This includes TURN server placement, SFU selection, and edge proximity.</p><p><strong>Layer 4 Monitoring layer:</strong> Controls real-time awareness of network conditions. This includes bandwidth estimation, congestion detection, and fallback triggers.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-1--2026--05_18_26-PM.png" class="kg-image" alt="How to Make Video Calls Work in Low-Connectivity Areas (WebRTC Guide)" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">WebRTC adaptive bitrate flow in low-bandwidth conditions</span></figcaption></img></figure><p>Each layer interacts with the others. A well-tuned encoder cannot compensate for a <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN server</a> on the wrong continent. A perfectly placed edge server cannot overcome a codec that consumes three times the necessary bandwidth. The framework only works when all four layers are addressed together.</p><h3 id="minimum-viable-bandwidth-targets">Minimum viable bandwidth targets</h3><p>Set explicit floor targets for each call quality tier before writing any configuration:</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Quality Tier</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Minimum Bandwidth</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Resolution</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Frame Rate</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Audio-only fallback</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">30–50 Kbps</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">—</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">—</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low-quality video</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">150–250 Kbps</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">240p</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">15 fps</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Standard video</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">300–500 Kbps</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">480p</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">24 fps</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High quality</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">800 Kbps–1.2 Mbps</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">720p</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">30 fps</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>Design your adaptive bitrate logic to move between these tiers smoothly, not abruptly. A call that drops from 720p to 480p in one step feels broken. A call that gradually reduces resolution while maintaining audio continuity feels stable.</p><h2 id="optimization-techniques-for-webrtc-low-bandwidth">Optimization techniques for WebRTC low bandwidth</h2><h3 id="adaptive-bitrate-webrtc-the-core-mechanism">Adaptive bitrate WebRTC: the core mechanism</h3><p><strong>Adaptive bitrate (ABR):</strong> <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">Adaptive bitrate</a> is a technique where the encoder continuously adjusts the video bitrate in response to real-time network feedback, ensuring that transmission rate never exceeds available bandwidth.</p><p>WebRTC's built-in congestion control mechanism <strong>Google Congestion Control (GCC):</strong> <a href="https://datatracker.ietf.org/doc/html/draft-ietf-rmcat-gcc-02" rel="nofollow noreferrer">Google Congestion Control is an algorithm</a> that estimates available bandwidth using RTCP feedback and adjusts the sending bitrate accordingly provides a foundation for adaptive bitrate. However, GCC alone is insufficient for highly variable networks.</p><p>To improve on default behavior:</p><ul><li>Set explicit minimum and maximum bitrate bounds. Do not let the encoder attempt 1 Mbps on a 300 Kbps link.</li><li>Configure degradation preference. Prioritize maintaining frame rate over resolution when bandwidth drops, unless your use case (medical imaging, document sharing) requires the opposite.</li><li>Implement a resolution ladder with at least four discrete steps rather than continuous scaling, which reduces encoder complexity.</li><li>Use RTCP receiver reports to detect packet loss trends before they compound into call failure.</li></ul><p>[→ related: Bandwidth Estimation and Congestion Control in WebRTC]</p><h3 id="codec-selection-vp8-vp9-and-av1-compared">Codec selection: VP8, VP9, and AV1 compared</h3><p><strong>VP8:</strong>&nbsp;<a href="https://en.wikipedia.org/wiki/VP8" rel="noreferrer nofollow">VP8</a>&nbsp;is an open-source video codec developed by Google, widely supported across browsers and devices, with moderate compression efficiency and low decode complexity.</p><p><strong>VP9:</strong>&nbsp;<a href="https://en.wikipedia.org/wiki/VP9" rel="noreferrer nofollow">VP9</a>&nbsp;is Google's successor to VP8, offering roughly 40–50% better compression at the same quality level, making it significantly more efficient for low-bandwidth scenarios.</p><p><strong>AV1:</strong>&nbsp;<a href="https://en.wikipedia.org/wiki/AV1" rel="noreferrer nofollow">AV1</a> is an open, royalty-free codec developed by the Alliance for Open Media that achieves better compression than VP9 but requires substantially more CPU for encoding and decoding.</p><p>For low-connectivity markets, the practical codec decision matrix looks like this:</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Codec</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Bandwidth Efficiency</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Device CPU Load</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Browser Support</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Recommended For</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">VP8</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Moderate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Universal</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Default fallback, older devices</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">VP9</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Moderate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Wide (not Safari &lt; 16)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Primary codec for most use cases</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">AV1</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Highest</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Limited (growing)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Future-ready, high-end devices only</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">H.264</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Moderate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low (HW accel)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Universal</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">iOS and hardware-constrained devices</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>For India and MENA deployments, VP9 with VP8 as a negotiated fallback is the most defensible configuration as of 2025. AV1 is appropriate for select use cases where you control the device environment.</p><h3 id="simulcast-versus-svc-choosing-the-right-multi-stream-strategy">Simulcast versus SVC: choosing the right multi-stream strategy</h3><p><strong>Simulcast:</strong> <a href="https://www.videosdk.live/blog/what-is-simulcast" rel="noreferrer">Simulcast</a> is a technique where the sender encodes and transmits multiple versions of the video stream at different resolutions and bitrates simultaneously, allowing the media server to forward the appropriate version to each receiver.</p><p><strong>Scalable Video Coding (SVC):</strong> <a href="https://en.wikipedia.org/wiki/Scalable_Video_Coding" rel="noreferrer">Scalable Video Coding</a> is a video encoding approach that encodes a single stream with multiple embedded quality layers, enabling the receiver or media server to decode only the subset of layers appropriate for current bandwidth.</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Factor</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Simulcast</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">SVC</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Sender CPU</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Higher (multiple encodes)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Lower (single layered encode)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Server complexity</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Lower</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Higher</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Bandwidth flexibility</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Per-stream switching</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Fine-grained layer selection</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Browser support</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Excellent</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Improving (VP9 SVC supported in Chrome)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Best for</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Stable networks, multi-participant calls</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Variable networks, bandwidth-sensitive scenarios</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>For <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-low-latency" rel="noreferrer">low-bandwidth WebRTC</a> optimization in tier 2 and tier 3 city deployments, simulcast with three layers (high, medium, low) gives the media server enough flexibility to serve each participant appropriately without requiring SVC support on the client.</p><p>[→ related: SFU Architecture and Stream Routing]</p><h2 id="infrastructure-and-architecture-considerations">Infrastructure and architecture considerations</h2><h3 id="edge-servers-and-geographic-proximity">Edge servers and geographic proximity</h3><p><a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu" rel="noreferrer"><strong>Selective Forwarding Unit (SFU)</strong></a><strong>:</strong> An SFU is a media server that receives multiple media streams and selectively forwards the appropriate streams to each participant without mixing or decoding them, minimizing server-side processing while maintaining scalability.</p><p>Latency between a participant and the nearest SFU directly affects perceived call quality. For every 100ms of additional one-way latency, audio synchronization degrades and lip-sync errors become perceptible. For users in Jaipur calling a server in Singapore, that latency can exceed 150ms on a poor routing day.</p><p>Infrastructure requirements for low-connectivity markets:</p><ul><li>Deploy SFU nodes in Mumbai (covering western and central India), Chennai or Hyderabad (southern India), and Delhi NCR (northern India) for comprehensive tier 2/3 city coverage.</li><li>For MENA, nodes in Dubai, Riyadh, Cairo, and Casablanca provide reasonable coverage across the Gulf, Levant, and North Africa.</li><li>Use Anycast routing where possible to automatically direct participants to the nearest healthy node.</li><li>Implement cross-region fallback so that a node failure in one city reroutes through the next-closest node within 1–2 seconds.</li></ul><p>Platforms like <a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> operate distributed edge infrastructure with nodes across India and MENA, which reduces the engineering burden of building and maintaining this geographic footprint independently.</p><p>[→ related: VideoSDK Global Infrastructure and Edge Routing]</p><h3 id="turn-server-strategy-for-restrictive-networks">TURN server strategy for restrictive networks</h3><p><a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer"><strong>TURN server</strong></a><strong>:</strong> A TURN (Traversal Using Relays around NAT) server is a relay server that forwards media traffic between peers when direct peer-to-peer or STUN-based connections fail due to firewall or NAT restrictions.</p><p>In corporate environments, university networks, and mobile carrier networks across India and MENA, direct peer-to-peer connections frequently fail. A TURN server acts as a guaranteed relay. Without it, calls in these environments will fail silently during the ICE negotiation phase.</p><p>TURN server deployment checklist:</p><ul><li>Deploy TURN servers in the same geographic regions as your SFU nodes</li><li>Use <a href="https://www.videosdk.live/developer-hub/websocket/websocket-udp" rel="noreferrer">UDP</a> as the primary TURN transport, TCP port 443 as fallback</li><li>Implement TURN over TLS for environments that block non-HTTPS traffic</li><li>Configure bandwidth limits per TURN relay connection to prevent single users from saturating the server</li><li>Monitor TURN allocation success rate rates below 95% indicate routing or firewall issues</li><li>Test TURN-only mode explicitly as part of your pre-launch QA</li></ul><h3 id="jitter-buffer-and-packet-loss-handling">Jitter buffer and packet loss handling</h3><p><a href="https://www.videosdk.live/blog/what-is-jitter-buffer" rel="noreferrer"><strong>Jitter buffer</strong></a><strong>:</strong> A jitter buffer is a mechanism in the receiver that stores incoming media packets temporarily to compensate for variable network delay, smoothing out delivery before audio or video is rendered.</p><p>WebRTC includes a built-in adaptive jitter buffer, but its default configuration is tuned for typical Western network conditions. For high-jitter networks common in tier 2 and tier 3 cities:</p><ul><li>Increase the maximum jitter buffer size. Default values (60–80ms) are insufficient for networks where jitter regularly exceeds 100ms.</li><li>Enable audio <a href="https://www.videosdk.live/developer-hub/social/packet-loss" rel="noreferrer">packet loss</a> concealment (PLC). The Opus audio codec the default in WebRTC provides strong PLC up to approximately 20% loss.</li><li>Implement NACK (Negative Acknowledgement) for video packet retransmission on networks where latency is low enough for retransmission to arrive before the render deadline.</li><li>Use FEC (Forward Error Correction) on audio for networks where loss is consistent but latency is too high for NACK to help.</li></ul><p><a href="https://en.wikipedia.org/wiki/Opus_(audio_format)" rel="noreferrer"><strong>Opus</strong></a><strong>:</strong> Opus is an open, royalty-free audio codec standardized by the IETF that supports a wide range of bitrates (6–510 Kbps) and includes built-in features for packet loss concealment and variable bandwidth operation.</p><p>[→ related: Packet Loss Recovery Strategies in WebRTC]</p><h2 id="common-mistakes-to-avoid">Common mistakes to avoid</h2><h3 id="1-assuming-symmetric-bandwidth">1. Assuming symmetric bandwidth</h3><p>Most bandwidth estimation tools measure download speed. WebRTC calls require symmetric upload and download capacity. A user with 10 Mbps down and 500 Kbps up common on mobile networks in tier 2 Indian cities will experience severe upload degradation that standard speed tests miss entirely.</p><p>Always test both directions independently during development, and configure your bitrate caps based on the lower of the two values.</p><h3 id="2-over-relying-on-gcc-without-custom-guardrails">2. Over-relying on GCC without custom guardrails</h3><p><a href="https://ieeexplore.ieee.org/document/6691458" rel="noreferrer nofollow">Google Congestion Control</a> will adapt, but it adapts reactively. On networks with sudden congestion spikes typical of cell tower handoffs and congested mobile networks GCC can take 3–5 seconds to stabilize after a bandwidth drop. During that window, the call degrades significantly.</p><p>Add proactive guardrails: set hard bitrate ceilings for each network type (2G, 3G, 4G), detect network type via the Network Information API where available, and pre-configure encoding parameters rather than waiting for GCC to discover the limit.</p><h3 id="3-deploying-a-single-turn-region">3. Deploying a single TURN region</h3><p>A TURN server in Virginia cannot efficiently serve a user in Lucknow. Round-trip latency through a distant TURN relay adds 200–400ms to every media packet. This makes the call feel like a satellite call, even when local network conditions are adequate.</p><p><a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN server</a> geographic placement is not optional for global deployments. Match TURN regions to your user geography.</p><h3 id="4-ignoring-audio-quality-in-pursuit-of-video-quality">4. Ignoring audio quality in pursuit of video quality</h3><p>In low-bandwidth conditions, the user experience degrades more noticeably from audio failure than from reduced video resolution. A pixelated but audible call is far more functional than a clear video feed with broken audio.</p><p>Configure your quality degradation sequence to protect audio bandwidth first. Drop video resolution and frame rate before touching audio bitrate.</p><h3 id="5-not-testing-on-real-devices-in-real-conditions">5. Not testing on real devices in real conditions</h3><p>Simulated network throttling in Chrome DevTools does not reproduce the behavior of a real 3G connection in a moving vehicle in Pune. The burst loss patterns, handoff interruptions, and NAT behavior of real mobile networks differ substantially from simulated environments.</p><p>Use real SIM cards in target markets for QA. Consider remote device testing services that provide access to physical devices on real carrier networks in India and MENA.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li>Low-connectivity markets especially tier 2 and tier 3 cities in India and MENA  expose every weakness in WebRTC infrastructure. Optimizing for them produces applications that are more resilient globally.</li><li>Adaptive bitrate control, VP9 codec selection with VP8 fallback, and explicit minimum bitrate floors are the highest-leverage encoding decisions for low-bandwidth scenarios.</li><li>TURN server geographic placement is non-negotiable. A TURN server more than 100ms away from the user will degrade call quality even when local conditions are adequate.</li><li>Protect audio bandwidth before video bandwidth. Users tolerate low-resolution video; they abandon calls with broken audio.</li><li>Test on real devices in real network conditions. Simulated throttling does not reproduce the packet loss patterns and NAT behavior of real carrier networks in emerging markets.</li></ul><h2 id="faq">FAQ</h2><p><strong>Q1. What is the minimum bandwidth required for a WebRTC video call?</strong> </p><p>A functional WebRTC video call requires approximately 150–250 Kbps for low-resolution 240p video and 300–500 Kbps for standard 480p video. Below 150 Kbps, most implementations should fall back to audio-only mode to maintain call continuity. These figures assume VP9 encoding; VP8 requires approximately 20–30% more bandwidth at equivalent quality.</p><p><strong>Q2. How does adaptive bitrate help in low bandwidth WebRTC scenarios?</strong> Adaptive bitrate continuously adjusts the video encoding rate based on real-time network feedback, preventing the encoder from transmitting more data than the network can carry. Without it, packet loss accumulates until the connection degrades catastrophically. With it, the call degrades gracefully reducing resolution or frame rate while maintaining connectivity.</p><p><strong>Q3. What is a TURN server and why is it critical for tier 2 tier 3 city deployments?</strong> </p><p>A TURN server is a relay that forwards media when direct peer connections fail due to NAT or firewall restrictions. In corporate networks, university campuses, and mobile carrier environments common in tier 2 and tier 3 cities, direct connections fail frequently. A correctly placed TURN server within 60–80ms of the user is the difference between a call that connects and one that silently fails during ICE negotiation.</p><p><strong>Q4. Which video codec is best for low bandwidth real-time communication?</strong> </p><p>VP9 is the most practical choice for low-bandwidth WebRTC as of 2025. It offers 40–50% better compression than VP8 at equivalent quality, has strong browser support across Chrome, Firefox, and Edge, and does not impose the hardware acceleration requirements that make H.264 preferable on iOS. Use VP8 as a negotiated fallback for older devices and browsers.</p><p><strong>Q5. How do I handle packet loss in WebRTC for rural or unstable networks?</strong> </p><p>Configure a combination of NACK for video retransmission, FEC for audio protection, and increase the jitter buffer size beyond the default 60–80ms ceiling. The Opus audio codec provides strong packet loss concealment up to approximately 20% loss. For video, ensure your simulcast configuration includes a low-resolution layer that remains transmissible even when packet loss reduces effective bandwidth significantly.</p><p><strong>Q6. What is the difference between simulcast and SVC for low-bandwidth optimization?</strong> </p><p>Simulcast encodes multiple full streams at different quality levels simultaneously, while SVC encodes a single layered stream from which subsets can be extracted. For low-bandwidth WebRTC in tier 2 and tier 3 city deployments, simulcast with three layers is more practical because it has universal browser support and gives the SFU server sufficient flexibility to route each participant the appropriate stream without requiring SVC-capable clients.</p><p><strong>Q7. How should I structure my infrastructure for a video app targeting India and MENA?</strong> </p><p>Deploy SFU nodes in Mumbai, Delhi, and Hyderabad for India coverage, and in Dubai, Riyadh, and Cairo for MENA coverage. Pair each SFU location with a co-located TURN server. Use Anycast routing to direct users to the nearest healthy node automatically. Implement cross-region fallback logic that reroutes within 1–2 seconds of a node failure. This architecture keeps one-way latency below 60ms for the vast majority of users in both regions.</p><p><strong>Q8. Can I rely on browser-native WebRTC for low-bandwidth optimization, or do I need a platform?</strong> </p><p>Browser-native WebRTC provides the foundational transport and codec negotiation, but it does not handle SFU selection, geographic routing, TURN server management, or advanced bandwidth estimation. For production deployments serving tier 2 and tier 3 city populations, an infrastructure platform handles those layers so engineering teams can focus on application logic rather than media server operations.</p>]]></content:encoded></item><item><title><![CDATA[Why Your Social Live Video App Feels Slow and How to Fix It]]></title><description><![CDATA[Is your social live video app feeling slow? Discover how to eliminate WebRTC latency by fixing poor media routing, optimising TURN server placement, and implementing adaptive bitrate logic to achieve sub-500ms global latency and deliver a seamless user experience.]]></description><link>https://videosdk.live/blog/why-social-live-video-app-feels-slow</link><guid isPermaLink="false">69f3364f55831517a5a9f3be</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 01 May 2026 11:15:29 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-1--2026--04_37_26-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> Most social live video app latency problems trace back to three root causes: suboptimal media routing, geographic TURN/STUN server placement, and the absence of adaptive bitrate logic under variable network conditions. Fixing them requires a layered infrastructure strategy, not a single tweak.</blockquote><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-text">A social live video app feels slow because media packets travel inefficient paths through distant servers, NAT traversal adds relay overhead, and most apps do not adapt encoding parameters fast enough when network conditions degrade. The fix requires edge-aware SFU placement, regional TURN infrastructure, and client-side congestion response built into the media pipeline.</div></div><h2 id="introduction-why-latency-is-the-silent-killer-of-social-apps">Introduction: why latency is the silent killer of social apps</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/05/ChatGPT-Image-May-1--2026--04_37_26-PM.png" alt="Why Your Social Live Video App Feels Slow and How to Fix It"/><p>Consumer expectations for live video have been shaped by platforms like TikTok Live, Instagram Live, and Clubhouse. Users do not tolerate delays above 2–3 seconds. In an <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">interactive live streaming</a> app, where interaction, reactions, and co-presence are the product, latency is not a performance metric, it is a feature.</p><p>Yet most engineering teams discover their latency problem after launch, when retention data surfaces it as a drop-off pattern or when user reviews describe the experience as "laggy" or "out of sync." By then, the cost of re-architecting is high.</p><p>This guide provides technical founders and CTOs with a complete diagnostic and remediation framework for latency in WebRTC-based social live video apps, from packet-level routing to infrastructure placement strategy.</p><h2 id="understanding-the-latency-stack-in-a-social-live-video-app">Understanding the latency stack in a social live video app</h2><p>Before fixing latency, you need to model it. <a href="https://www.videosdk.live/blog/what-is-latency-in-webrtc" rel="noreferrer">Latency in a <strong>WebRTC</strong></a> (Web Real-Time Communication, a browser and mobile API standard for peer-to-peer media) pipeline is not a single variable. It is the sum of several compounding delays across the media path.</p><h3 id="the-five-layer-latency-model">The five-layer latency model</h3>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Layer</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Source of delay</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Typical contribution</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Capture and encode</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Camera frame capture + software encode time</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">10–40 ms</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Network transmission</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Physical distance + routing hops</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">20–200+ ms</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">TURN relay overhead</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">NAT traversal via relay server</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">5–80 ms (varies by region)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SFU processing</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Media forwarding, simulcast selection</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">2–15 ms</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Decode and render</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Hardware/software decode + display pipeline</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">10–30 ms</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>End-to-end perceived latency is the sum of all five. The largest variable, and the one most within your control, is network transmission as shaped by your routing and infrastructure decisions.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-30--2026--05_41_51-PM.png" class="kg-image" alt="Why Your Social Live Video App Feels Slow and How to Fix It" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Global media path latency showing client</span></figcaption></img></figure><h2 id="how-webrtc-routing-actually-works-and-where-it-breaks-down">How WebRTC routing actually works, and where it breaks down</h2><p><a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu" rel="noreferrer"><strong>SFU</strong></a> (Selective Forwarding Unit, a media server that receives streams from publishers and selectively forwards them to subscribers) is the architectural center of most modern social video apps. Unlike peer-to-peer <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a>, an SFU topology scales to many viewers, but it introduces a critical dependency: the physical location of the SFU relative to every connected client.</p><h3 id="the-hub-and-spoke-problem">The hub-and-spoke problem</h3><p>Most early-stage social apps deploy a single SFU cluster, typically in a US East or EU West data center. This works fine for local audiences. For global audiences, it creates a hub-and-spoke latency penalty.</p><p>Consider a user in Mumbai streaming to viewers in Jakarta, Riyadh, and São Paulo. With a single US East SFU:</p><ul><li>Mumbai → US East: ~200 ms one-way</li><li>US East → Jakarta: ~230 ms one-way</li><li>Total round-trip visible latency: 800 ms+ before any other overhead</li></ul><p>With a regional SFU in Singapore or Mumbai and another in São Paulo, the same stream can be delivered in under 150 ms round-trip to most of those destinations.</p><p><strong>WebRTC routing latency</strong> is compounded by the fact that WebRTC itself does not control routing at the IP layer, it accepts whatever path the network selects, which is often not the shortest.</p><h2 id="turn-stun-and-nat-traversal-the-overlooked-latency-multipliers">TURN, STUN, and NAT traversal: the overlooked latency multipliers</h2><p><a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-stun-server" rel="noreferrer"><strong>STUN</strong></a> (Session Traversal Utilities for NAT, a protocol that allows a client to discover its public IP address and the type of NAT it sits behind) and <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer"><strong>TURN</strong></a> (Traversal Using Relays around NAT, a fallback protocol that relays all media through a server when direct connection fails) are foundational to WebRTC connectivity.</p><p>In a controlled test environment, developer machines on open networks, NAT traversal succeeds without relays. In production, across mobile networks, carrier-grade NAT, corporate firewalls, and symmetric NAT configurations, a significant percentage of connections fall back to TURN. Estimates from large-scale WebRTC deployments suggest TURN fallback rates between 15% and 40% depending on the user population and geography (Philipp Hancke, testRTC research, 2022).</p><h3 id="why-turn-server-geography-matters-more-than-turn-server-count">Why TURN server geography matters more than TURN server count</h3><p>A <a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer">TURN server</a> in Virginia does not help a user in Bangalore connect to a peer in Singapore. The relay adds latency equal to the round-trip from each client to the TURN server. If that server is on the wrong continent, your TURN infrastructure is actively degrading the experience for a large share of your users.</p><p><strong>TURN/STUN servers in WebRTC</strong> need to be deployed with the same geographic intentionality as your CDN edge nodes.</p><h3 id="turn-placement-checklist">TURN placement checklist</h3><ul><li>Deploy TURN servers in every region where you have more than 5% of your user base</li><li>Use latency-based DNS routing (e.g., AWS Route 53 or Cloudflare) to direct clients to the nearest TURN server</li><li>Monitor TURN fallback rate per region, spikes indicate NAT traversal failures</li><li>Set TURN credential TTLs below 24 hours to reduce replay attack surface</li><li>Test TURN reachability from mobile networks in target markets, not just fixed broadband</li></ul><h2 id="infrastructure-placement-strategy-for-global-social-apps">Infrastructure placement strategy for global social apps</h2><p><a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer"><strong>Real-time communication infrastructure</strong></a> must be designed around user geography, not engineering convenience. The following framework applies regardless of whether you are building on a managed WebRTC platform or operating your own media servers.</p><h3 id="the-three-tier-infrastructure-model">The three-tier infrastructure model</h3><p><strong>Tier 1 Core SFU cluster:</strong> One or two primary regions handling the heaviest load and acting as the origination point for stream distribution. Typically US East and EU West.</p><p><strong>Tier 2 Regional SFU nodes:</strong> Secondary clusters placed in high-density user regions Southeast Asia (Singapore), South Asia (Mumbai), Middle East (Bahrain/Dubai), Latin America (São Paulo), East Asia (Tokyo or Seoul). These receive ingest from Tier 1 and serve local subscribers.</p><p><strong>Tier 3  Edge relay and TURN:</strong> Lightweight servers close to end users, responsible only for ICE candidate gathering and TURN relay. Does not handle SFU workloads.</p><h3 id="regional-sfu-placement-decision-matrix">Regional SFU placement decision matrix</h3>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Region</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Minimum user threshold for dedicated SFU</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Recommended cloud zone</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">North America</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Baseline</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">US East (Virginia)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Europe</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">8% of DAU</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">EU West (Frankfurt or Amsterdam)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">South Asia</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">5% of DAU</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">ap-south-1 (Mumbai)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Southeast Asia</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">5% of DAU</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">ap-southeast-1 (Singapore)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Middle East</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">3% of DAU</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">me-south-1 (Bahrain)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Latin America</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">4% of DAU</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">sa-east-1 (São Paulo)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">East Asia</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">4% of DAU</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">ap-northeast-1 (Tokyo)</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>The thresholds above are indicative. The correct threshold for your product depends on the latency sensitivity of your use case. A social karaoke app has different tolerance than a casual watch-party feature.</p><h2 id="protocol-and-bitrate-adaptation-strategies">Protocol and bitrate adaptation strategies</h2><p>Infrastructure placement reduces the structural latency floor. Implementing <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">adaptive bitrate streaming</a> algorithms reduces latency spikes caused by network variability, and on mobile networks globally, variability is the norm.</p><h3 id="congestion-control-and-why-most-apps-ignore-it-until-it-hurts">Congestion control and why most apps ignore it until it hurts</h3><p>WebRTC uses <strong>GCC</strong> (<a href="https://datatracker.ietf.org/doc/html/draft-ietf-rmcat-gcc-02" rel="nofollow noreferrer">Google Congestion Control</a>, an algorithm built into the WebRTC stack that estimates available bandwidth and signals the encoder to adjust bitrate) by default. GCC operates well on stable broadband but can be slow to react on cellular networks with rapid congestion transitions.</p><p>Several production deployments have moved to <strong>SCReAM</strong> (<a href="https://www.ietf.org/archive/id/draft-johansson-ccwg-rfc8298bis-screamv2-00.html" rel="noreferrer nofollow">Self-Clocked Rate Adaptation for Multimedia</a>) or&nbsp;<strong>NADA</strong>&nbsp;(<a href="https://datatracker.ietf.org/doc/html/rfc8698" rel="noreferrer nofollow">Network-Assisted Dynamic Adaptation</a>) for more aggressive and accurate adaptation, particularly in high-packet-loss environments such as 4G in dense urban areas.</p><p>For most social live video app teams, the practical recommendation is:</p><ol><li>Enable <a href="https://www.videosdk.live/blog/what-is-simulcast" rel="noreferrer">simulcast</a>, publish at three quality levels simultaneously (high, medium, low)</li><li>Let the SFU select the appropriate layer per subscriber based on their downlink estimate</li><li>Set aggressive keyframe intervals (every 1–2 seconds) to reduce recovery time after packet loss</li><li>Configure max bitrate caps per layer that are conservative enough to stay within mobile data constraints</li></ol><h3 id="adaptive-bitrate-decision-framework">Adaptive bitrate decision framework</h3>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Network condition</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Recommended action</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Mechanism</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">RTT &lt; 80 ms, 0% packet loss</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Serve highest simulcast layer</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SFU layer selection</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">RTT 80–200 ms, &lt;2% loss</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Serve mid simulcast layer</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SFU layer selection</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">RTT &gt; 200 ms, &gt;2% loss</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Downgrade to low layer + reduce FPS</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SFU + encoder feedback</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Sustained &gt;5% loss</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Switch to audio-only fallback mode</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Application logic</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Network disconnection</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Reconnect with exponential backoff</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Client ICE restart</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><strong>Low latency video streaming</strong> depends as much on this adaptation logic as on infrastructure. Without it, a viewer on a degraded mobile connection will see frozen frames and audio artifacts rather than a graceful quality reduction.</p><h2 id="using-videosdk-as-an-implementation-reference">Using VideoSDK as an implementation reference</h2><p>For teams building on managed infrastructure, <a href="https://www.videosdk.live/" rel="noreferrer"><strong>VideoSDK</strong></a> provides a reference implementation worth examining. According to the <a href="https://docs.videosdk.live/" rel="noreferrer">VideoSDK documentation</a>, the platform exposes simulcast configuration, TURN server credential management, and SFU region selection as configurable parameters within its SDK, which maps directly to the framework described above.</p><p>Specifically, VideoSDK's architecture documentation describes support for multi-region deployments and adaptive media routing, which aligns with Tier 2 and Tier 3 placement strategies. For teams evaluating build vs. buy decisions on media infrastructure, examining how managed platforms expose these controls is a useful calibration exercise, independent of vendor selection.</p><h2 id="cto-decision-checklist-diagnosing-your-latency-problem">CTO decision checklist: diagnosing your latency problem</h2><p>Before investing in new infrastructure, complete this diagnostic sequence.</p><h3 id="phase-1-measurement-week-1">Phase 1  Measurement (week 1)</h3><ul><li>Instrument client-side RTT measurement and log per session, per region</li><li>Track TURN fallback rate separately from direct connection rate</li><li>Measure time-to-first-frame (TTFF) per region</li><li>Log packet loss rate and <a href="https://www.videosdk.live/blog/what-is-jitter" rel="noreferrer">jitter</a> by network type (WiFi, 4G, 5G)</li><li>Identify the 90th percentile latency, not just the median, outliers drive churn</li></ul><h3 id="phase-2-diagnosis-week-2">Phase 2  Diagnosis (week 2)</h3><ul><li>Map your user geography against your SFU and TURN server locations</li><li>Identify any region where average RTT to your nearest SFU exceeds 150 ms</li><li>Review whether your TURN server TTL and credential rotation is correctly configured</li><li>Check whether simulcast is enabled and whether SFU layer selection is functioning</li></ul><h3 id="phase-3-remediation-weeks-3%E2%80%938">Phase 3  Remediation (weeks 3–8)</h3><ul><li>Deploy regional TURN servers in your highest-latency user regions</li><li>Add SFU capacity in regions where RTT to the existing cluster exceeds 150 ms</li><li>Enable and test simulcast with conservative layer bitrate caps</li><li>Implement <a href="https://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment" rel="noreferrer">ICE</a> restart logic on the client for network transitions</li><li>Add an audio-only fallback mode for extreme network degradation</li></ul><h2 id="common-mistakes-and-misconceptions">Common mistakes and misconceptions</h2><h3 id="mistake-1-treating-latency-as-a-server-side-problem-only">Mistake 1: treating latency as a server-side problem only</h3><p>Client-side decisions, ICE candidate gathering order, encoder configuration, keyframe policy, contribute meaningfully to perceived latency. Both ends of the pipeline require attention.</p><h3 id="mistake-2-assuming-cdn-coverage-equals-sfu-coverage">Mistake 2: assuming CDN coverage equals SFU coverage</h3><p>A CDN edge node serves cached content. An SFU processes live bidirectional media in real time. These are fundamentally different workloads. CDN presence in a region does not reduce SFU latency for that region unless you have also co-located media processing infrastructure there.</p><h3 id="mistake-3-using-a-single-global-stun-server">Mistake 3: using a single global STUN server</h3><p>Public STUN servers (including Google's) are valuable for testing but are not optimized for your user geography, not monitored for your SLA, and not geographically distributed for your specific traffic patterns. Operate your own STUN/TURN infrastructure before scaling.</p><h3 id="mistake-4-not-testing-on-representative-devices-and-networks">Mistake 4: not testing on representative devices and networks</h3><p>Benchmarking <a href="https://www.videosdk.live/blog/what-is-latency-in-webrtc" rel="noreferrer">WebRTC latency</a> on a MacBook Pro on a 1 Gbps fiber connection tells you nothing about your median user experience in Southeast Asia or the Middle East. Use device labs, network emulation, and synthetic monitoring from target geographies.</p><h3 id="mistake-5-optimizing-encode-bitrate-without-considering-the-sfu-selection-logic">Mistake 5: optimizing encode bitrate without considering the SFU selection logic</h3><p>Lowering bitrate at the encoder helps only if the SFU is correctly routing the lower-quality layer to impacted subscribers. Check that your SFU's bandwidth estimation and layer selection logic is calibrated before tuning encoder parameters.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li>Perceived latency in a social live video app is the sum of five compounding layers; the largest controllable variable is geographic media routing.</li><li>TURN server placement has an outsized impact on the 15–40% of connections that fall back to relay, deploy TURN regionally, not centrally.</li><li>A single SFU cluster is sufficient for local audiences and harmful for global ones; adopt a three-tier infrastructure model as you scale internationally.</li><li>Simulcast with SFU-side layer selection is the most reliable mechanism for handling the network variability that characterizes global mobile audiences.</li><li>Measure 90th percentile latency by region before investing in remediation, the data will tell you where to spend infrastructure budget first.</li></ul><h2 id="faq">FAQ</h2><p><strong>Q1. What is considered an acceptable latency target for a social live video app?</strong> </p><p>For interactive social features, reactions, co-streaming, live Q&amp;A, sub-500 ms glass-to-glass latency is the practical target. Latency above 2 seconds breaks the social feedback loop and is consistently associated with lower engagement. WebRTC, when correctly implemented, achieves 100–300 ms in well-served regions.</p><p><strong>Q2. Why does my app perform well in the US but poorly in Southeast Asia or the Middle East?</strong> </p><p>The most common cause is that your SFU and TURN infrastructure is located in the US or EU, creating long round-trips for users in those regions. A user in Jakarta connecting to a US East SFU faces 200+ ms of structural latency before any other factors. Deploy regional SFU nodes and TURN servers in those geographies to address this.</p><p><strong>Q3. What is the difference between STUN and TURN, and do I need both?</strong> </p><p>STUN helps a client discover its public IP and NAT type, it is used during ICE negotiation but does not relay media. TURN relays all media through a server when a direct or STUN-assisted connection fails. You need both: STUN for the majority of connections that succeed without relay, and TURN as a fallback for the 15–40% that require it. Omitting TURN causes connection failures in restrictive network environments.</p><p><strong>Q4. Does WebRTC latency optimization differ for mobile apps vs. web?</strong> </p><p>The infrastructure-level concerns are identical. At the client level, mobile apps have more control over hardware encode/decode paths, which can reduce processing latency compared to browser-based WebRTC. Mobile also faces more aggressive NAT configurations from cellular carriers, increasing the TURN fallback rate relative to fixed broadband.</p><p><strong>Q5. What is simulcast and why does it matter for global latency performance?</strong> </p><p>Simulcast is a technique where the publisher's client encodes the same stream at multiple quality levels simultaneously (typically three) and sends all layers to the SFU. The SFU then forwards only the appropriate layer to each subscriber based on their estimated downlink bandwidth. This allows the SFU to immediately serve a lower-quality stream to a degraded subscriber without waiting for the encoder to change, reducing the visible impact of network variability from seconds to milliseconds.</p><p><strong>Q6. How do I measure the actual latency my users are experiencing?</strong></p><p> Instrument your WebRTC client to expose the <code>RTCStatsReport</code> API, which provides round-trip time estimates, packet loss, and jitter per peer connection. Log these per session with region metadata. For glass-to-glass latency measurement in testing environments, use NTP-synchronized timestamp watermarking in the video stream. Commercial WebRTC monitoring services such as testRTC and Callstats also provide production telemetry at scale.</p><p><strong>Q7. Can I fix latency issues without replacing my media server infrastructure?</strong> </p><p>Partially. Enabling simulcast, tuning encoder parameters, improving ICE restart logic, and adding TURN servers in underserved regions can all be done without replacing the core SFU. However, if your SFU is physically distant from a large portion of your user base, those improvements have a ceiling. Geographic SFU placement is eventually necessary for global social apps at scale.</p><p><strong>Q8. At what scale should a startup begin investing in regional infrastructure?</strong> </p><p>The trigger point is not user count, it is geographic distribution. As soon as a meaningful percentage of your active users are in regions more than 100 ms from your nearest SFU, you will observe latency-driven churn. A practical rule: when any region exceeds 5% of your daily active users and averages more than 150 ms RTT to your SFU, begin planning regional expansion for that geography.</p>]]></content:encoded></item><item><title><![CDATA[How to Reduce Patient Drop-off in Telemedicine Video Calls]]></title><description><![CDATA[Learn how to reduce patient drop-off in telemedicine video calls using a 7-stage funnel framework. Discover actionable UX fixes, pre-call device readiness strategies, and robust video infrastructure to recover up to 40% of scheduled patients lost to technical friction.]]></description><link>https://www.videosdk.live/blog/how-to-reduce-patient-drop-off-in-telemedicine-video-calls</link><guid isPermaLink="false">69f309e555831517a5a9c46e</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 30 Apr 2026 09:56:53 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/04/22.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TLDR: </strong>To reduce patient drop-off in telemedicine video calls, audit each stage of the visit funnel, from appointment booking through post-call completion, and apply targeted fixes at the highest-friction points. Most platforms lose 20–40% of scheduled patients before the call ever connects, primarily due to poor onboarding, device readiness failures, and waiting room abandonment. A structured funnel analysis combined with rapid technical fixes and UX improvements can recover a significant share of that lost volume.</blockquote><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-text">Reducing patient drop-off in telemedicine video calls requires addressing seven distinct funnel stages: booking, onboarding, device readiness, waiting room experience, call connection, in-call quality, and post-call completion. The highest-yield interventions are pre-call device checks, simplified authentication flows, and low-latency video infrastructure that eliminates connection failures.</div></div><h2 id="introduction-why-drop-off-is-a-revenue-and-outcomes-problem">Introduction: why drop-off is a revenue and outcomes problem</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/22.png" alt="How to Reduce Patient Drop-off in Telemedicine Video Calls"/><p>Every patient who abandons a scheduled telemedicine visit represents a compounding loss. There is the direct revenue impact from a missed billable encounter, the indirect cost of the clinical time already allocated, and the downstream health risk to a patient who may delay or forgo care entirely.</p><p><strong>Telemedicine conversion rate optimization,</strong> the practice of systematically reducing the gap between scheduled visits and completed visits, has become a critical growth lever for <a href="https://www.videosdk.live/solutions/telehealth" rel="noreferrer">telehealth platforms</a> operating in an increasingly crowded market. Yet most product teams treat drop-off as a technical support issue rather than a funnel problem. The result is reactive whack-a-mole: fixing the symptom one patient reports while ignoring the structural causes affecting thousands of others.</p><p>Research consistently shows that healthcare digital experience friction is not a minor inconvenience. A study published in the <a href="https://www.jmir.org/" rel="nofollow noreferrer">Journal of Medical Internet Research</a>&nbsp;found that technical difficulties were among the most commonly cited barriers to telehealth adoption, alongside digital literacy and internet access. The&nbsp;<a href="https://www.who.int/publications/i/item/9789240116870" rel="nofollow noreferrer">WHO's Global Strategy on Digital Health</a> underscores that usability and infrastructure reliability are prerequisites for sustainable virtual care delivery.</p><p>For product managers and growth teams at telehealth platforms, this article provides a complete funnel-based framework to diagnose, measure, and systematically reduce patient drop-off in telemedicine video calls, without requiring massive engineering resources upfront.</p><h2 id="background-the-telehealth-funnel-and-patient-behavior">Background: the telehealth funnel and patient behavior</h2><p>Understanding why patients drop off requires understanding what the telehealth visit experience actually demands of them. Unlike an in-person visit where the patient navigates to a physical location, a telemedicine visit asks the patient to navigate a digital environment, often under conditions of stress, low digital literacy, or poor connectivity.</p><p><strong>The telemedicine visit funnel</strong> is longer and more fragile than most product teams assume. A patient must:</p><ol><li>Successfully book an appointment through a scheduling interface</li><li>Receive and act on pre-visit preparation instructions</li><li>Verify that their device and network meet minimum requirements</li><li>Wait in a virtual waiting room without abandoning</li><li>Connect to the call without technical failure</li><li>Complete the in-call experience without quality degradation</li><li>Finish the visit and complete any required post-call actions</li></ol><p>At each stage, there are distinct behavioral, technical, and UX failure modes. The platform's ability to retain patients across all seven stages is what determines its effective telemedicine conversion rate.</p><p><strong>Telehealth onboarding drop-off,</strong> the loss of patients during the pre-call preparation phase, is often the single largest avoidable source of incomplete visits. Industry estimates suggest that platforms without structured onboarding flows lose 15–25% of booked patients before the waiting room.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-30--2026--01_45_14-PM.png" class="kg-image" alt="How to Reduce Patient Drop-off in Telemedicine Video Calls" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Telemedicine video call drop-off funnel</span></figcaption></img></figure><h2 id="full-funnel-breakdown-stage-by-stage-optimization">Full funnel breakdown: stage-by-stage optimization</h2><h3 id="stage-1-appointment-booking">Stage 1: appointment booking</h3><p><strong>What drop-off looks like here:</strong> Patients who initiate the scheduling flow but do not complete it. This includes multi-step booking forms, unclear provider availability, and confusing insurance verification steps.</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Common drop-off causes</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Measurable metric</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Optimization levers</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Too many form fields</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Booking abandonment rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Reduce required fields to minimum viable set</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Unclear availability display</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Scheduling funnel completion %</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Show provider availability in patient's local timezone</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Insurance friction at booking</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Drop-off at insurance step</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Move insurance verification post-booking</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">No mobile-optimized flow</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mobile vs. desktop conversion gap</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Implement responsive scheduling UI</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Lack of immediate confirmation</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Email/SMS receipt rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Auto-send confirmation with pre-visit prep link</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><strong>Product and engineering fixes:</strong></p><ul><li>Implement progressive disclosure in booking forms, collect only name, contact, and appointment time at booking; gather clinical intake separately</li><li>Use smart timezone detection to display availability without requiring manual timezone input</li><li>Send an immediate confirmation message with a direct link to the visit and a device check tool</li></ul><h3 id="stage-2-pre-call-onboarding">Stage 2: pre-call onboarding</h3><p><strong>Telehealth onboarding drop-off</strong> is the loss of patients who were booked but never completed pre-visit preparation. Most platforms underinvest here.</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Common drop-off causes</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Measurable metric</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Optimization levers</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Complex account creation requirement</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">% who complete account setup</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Offer guest access with optional account creation post-visit</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Unclear instructions for visit access</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Open rate on pre-visit emails</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Redesign pre-visit email with single CTA button</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">No reminder cadence</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">No-show rate by reminder type</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Implement 24h + 1h automated reminders via SMS</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Consent forms with legal jargon</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Consent completion rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Plain-language consent with progress indicator</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">App download required on mobile</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">App install conversion rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Prioritize browser-based access; make app optional</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><strong>Product and engineering fixes:</strong></p><ul><li>Build a browser-first experience. Requiring app installation before a first visit is one of the highest-friction barriers in telehealth onboarding.</li><li>Use a link-based entry flow: one link in the reminder message takes the patient directly to the waiting room, bypassing login where possible.</li><li>Show patients what to expect from the visit in the pre-visit email, duration, what their provider will ask, how to prepare their environment.</li></ul><h3 id="stage-3-device-and-network-readiness">Stage 3: device and network readiness</h3><p>This stage is where technical issues cause the most invisible drop-off. Patients who fail a device check often abandon silently, they do not call support, they simply do not return.</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Common drop-off causes</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Measurable metric</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Optimization levers</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Microphone/camera permission blocked</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Device check completion rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Build in-browser permission guide with OS-specific screenshots</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Unsupported browser</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Browser incompatibility error rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Auto-detect browser and recommend switch before visit day</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Poor network at visit time</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Pre-call speed test pass rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Run automated speed test with real-time feedback</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">No fallback for failed checks</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">% who proceed despite failed check</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Offer phone audio fallback for patients who fail video check</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Checks run too close to visit</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Time between check and visit start</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Prompt device check 30 minutes before, not at visit entry</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><strong>Product and engineering fixes:</strong></p><ul><li>Implement a pre-call readiness check that runs 24–48 hours before the appointment, not at the moment the patient joins</li><li>Build clear, visual step-by-step guides for enabling camera and microphone permissions on iOS, Android, macOS, and Windows</li><li>Detect bandwidth in real-time and automatically offer audio-only mode if the network cannot sustain stable video</li></ul><p><strong>Real-time video reliability in healthcare</strong> is not just a technical concern, it is a clinical one. A dropped call during a psychiatric evaluation or a medication review creates patient anxiety and erodes platform trust. Infrastructure that provides consistent, low-latency connections with automatic quality adaptation is a prerequisite for retaining patients long-term.</p><h3 id="stage-4-waiting-room-experience">Stage 4: waiting room experience</h3><p>The waiting room is where <strong>reduce video call abandonment healthcare</strong> strategies must specifically focus. Patients in a digital waiting room have no ambient cues that their wait is normal or finite. Unlike a physical waiting room with staff visibility, a blank loading screen communicates nothing.</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Common drop-off causes</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Measurable metric</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Optimization levers</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">No wait time estimate displayed</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Waiting room abandonment rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Show estimated wait time, updated in real-time</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">No activity or engagement while waiting</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Time-to-abandon distribution</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Add optional pre-visit health questionnaire or educational content</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Provider joins late without communication</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">% of waits exceeding scheduled start by 5+ min</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Trigger automated provider delay notification at 3 minutes</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">No visual confirmation patient is in queue</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Patient-reported confusion rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Display live queue position or "your provider is preparing" status</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session timeout during long wait</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session expiry abandonment rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Keep session alive automatically; warn before timeout</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><strong>Product and engineering fixes:</strong></p><ul><li>Display a real-time provider status indicator: "Dr. Chen is finishing a previous visit" is more reassuring than a spinning icon</li><li>Implement dynamic wait time estimates that update based on provider schedule data</li><li>Auto-send a push notification or page ping if the patient navigates away from the waiting room tab</li></ul><h3 id="stage-5-call-connection">Stage 5: call connection</h3><p><strong>Call connection</strong> is where infrastructure limitations become directly visible to patients. This stage represents a binary failure mode: the call either connects or it does not.</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Common drop-off causes</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Measurable metric</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Optimization levers</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">ICE negotiation failures</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Call connection success rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Use TURN server relay as automatic fallback</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Firewall or network port blocking</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Connection failure by network type</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Ensure media traversal over standard HTTPS ports (443)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Codec incompatibility</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Cross-device connection failure rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Support VP8, VP9, H.264 with automatic negotiation</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Slow call setup time</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Time from join button click to active call</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Optimize signaling server response time</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">No retry mechanism on failure</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Retry rate after first failure</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Auto-retry with clear "Reconnecting..." status</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><strong>Product and engineering fixes:</strong></p><ul><li>Implement automatic <a href="https://www.videosdk.live/developer-hub/stun-turn-server/turn-server" rel="noreferrer">TURN server</a> fallback for patients behind restrictive enterprise or carrier <a href="https://en.wikipedia.org/wiki/Network_address_translation" rel="noreferrer">NAT</a></li><li>Use adaptive bitrate streaming to maintain a stable connection on variable networks rather than dropping the call entirely</li><li>For platforms building or scaling video infrastructure, <a href="https://videosdk.live/" rel="noreferrer">VideoSDK's</a> real-time audio and video APIs provide low-latency communication with multi-platform SDK support, reducing the engineering overhead of building reliable call connection from scratch</li></ul><blockquote>Must Read: <a href="https://www.videosdk.live/blog/what-is-webrtc-signaling" rel="noreferrer">What is WebRTC Signaling?</a></blockquote><h3 id="stage-6-in-call-experience">Stage 6: in-call experience</h3><p>Even a successfully connected call can result in drop-off if the in-call quality degrades to the point where the patient or provider terminates early.</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Common drop-off causes</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Measurable metric</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Optimization levers</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Audio echo or feedback</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">In-call quality ratings</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Enable echo cancellation and noise suppression by default</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Video freezing on low bandwidth</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Freeze events per session</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Implement simulcast to allow quality downscaling</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">UI confusion (mute, screen share)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Feature usage rate in-call</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Simplify in-call UI to essential controls only</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">No visual feedback when muted</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Patient speaking while muted rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Display prominent mute indicator with "You are muted" alert</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Call quality not adaptive</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Bandwidth-related drop rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Use real-time network quality indicators and auto-adjust</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><strong>Patient engagement in video visits</strong> is directly correlated with call quality. Research in healthcare UX shows that patients who experience audio or video degradation report lower satisfaction, lower trust in diagnosis accuracy, and higher rates of visit abandonment. The in-call experience is not just a product quality concern, it influences clinical outcomes.</p><p><strong>Product and engineering fixes:</strong></p><ul><li>Enable <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> built-in echo cancellation, noise suppression, and automatic gain control</li><li>Implement <a href="https://www.videosdk.live/blog/what-is-simulcast" rel="noreferrer">simulcast</a> or SVC (scalable video coding) to gracefully degrade quality without dropping the call</li><li>Add a real-time network quality indicator visible to the patient so they can act (move closer to WiFi, close background tabs) rather than waiting for the call to fail</li></ul><h3 id="stage-7-post-call-completion">Stage 7: post-call completion</h3><p>Post-call drop-off is the least visible stage but directly affects clinical continuity, billing completion, and platform retention.</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Common drop-off causes</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Measurable metric</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Optimization levers</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Visit summary not sent promptly</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Post-visit email open rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Send automated visit summary within 5 minutes of call end</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">No next-step clarity</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Follow-up booking rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Include clear CTA to book follow-up in post-visit message</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Prescription confirmation missing</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Prescription notification delivery rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Integrate with pharmacy notification flow</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Satisfaction survey too long</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Survey completion rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Limit to 2–3 questions; send via SMS for higher completion</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">No rating or feedback mechanism</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Platform review rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Prompt in-app review within 24 hours of completed visit</td></tr></tbody></table>
<!--kg-card-end: html-->
<h2 id="drop-off-diagnostics-and-measurement-framework">Drop-off diagnostics and measurement framework</h2><p>Before optimizing, you need to measure. Most telehealth platforms have data siloed across scheduling systems, EHRs, video infrastructure, and support tools. A unified funnel view requires connecting these sources.</p><h3 id="core-metrics-to-instrument">Core metrics to instrument</h3>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Funnel stage</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Primary metric</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Secondary metric</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Booking</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Scheduling funnel completion rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Abandonment by step</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Onboarding</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Pre-visit link open rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Account creation completion rate</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Device readiness</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Device check pass rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Failure by device/browser type</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Waiting room</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Waiting room abandonment rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Average wait time at abandonment</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Call connection</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Connection success rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Retry rate, connection time</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">In-call experience</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Average call duration vs. expected</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Early termination rate</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Post-call</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Visit completion rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Post-visit action completion rate</td></tr></tbody></table>
<!--kg-card-end: html-->
<h3 id="diagnostic-framework-how-to-identify-your-biggest-drop-off-lever">Diagnostic framework: how to identify your biggest drop-off lever</h3><p><strong>Step 1 Baseline your funnel.</strong> Calculate the completion rate at each stage as a percentage of patients who entered that stage. A 60% connection success rate is very different from a 60% booking completion rate in terms of downstream impact.</p><p><strong>Step 2 Identify stage-level drop-off.</strong> The stage with the largest absolute patient loss is your first priority, not the stage with the lowest completion rate. A 20% drop at the waiting room stage on 10,000 monthly patients (2,000 patients lost) outweighs a 40% drop at post-call completion on 1,000 monthly patients (400 patients lost).</p><p><strong>Step 3 Segment by device, network, and user cohort.</strong> Drop-off is rarely uniform. Mobile patients on cellular networks may have a 40% device check failure rate while desktop patients on broadband have a 5% failure rate. Segment your data before drawing conclusions.</p><p><strong>Step 4 Correlate with support tickets and session recordings.</strong> Quantitative funnel data tells you where patients drop off. Qualitative data tells you why. Review session recordings (with appropriate <a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api" rel="noreferrer">HIPAA</a>/GDPR consent) and support ticket themes for the highest drop-off stages.</p><p><strong>Step 5 Run a structured root cause analysis.</strong> For each high-drop-off stage, categorize causes into three buckets: UX issues (design and copy problems), technical issues (infrastructure and browser compatibility), and trust or compliance issues (consent concerns, data privacy uncertainty).</p><h2 id="optimization-playbook-prioritized-actions">Optimization playbook: prioritized actions</h2><p>Not all optimizations are equal. Use an impact-versus-effort matrix to sequence your roadmap.</p><h3 id="impact-effort-prioritization-matrix">Impact-effort prioritization matrix</h3>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Action</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Stage</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Impact</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Effort</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Priority</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Pre-call device check (24h before visit)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Device readiness</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Quick win</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SMS reminder with one-tap join link</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Onboarding</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Quick win</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Wait time estimate in waiting room</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Waiting room</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Quick win</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Browser-based access (no app required)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Onboarding</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">TURN server relay for connection failures</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Call connection</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Adaptive bitrate / simulcast</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">In-call</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Strategic</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Unified funnel analytics dashboard</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All stages</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Post-call automated summary</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Post-call</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Quick win</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Audio-only fallback for failed video</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Device readiness</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Provider delay notification in waiting room</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Waiting room</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td></tr></tbody></table>
<!--kg-card-end: html-->
<h3 id="quick-wins-implement-within-30-days">Quick wins (implement within 30 days)</h3><ol><li>Add a pre-call device check prompt in the 24-hour reminder SMS/email</li><li>Replace text-heavy waiting rooms with a real-time provider status indicator</li><li>Send a post-visit summary within five minutes of call end</li><li>Implement one-tap join links in all reminder messages that bypass login</li></ol><h3 id="structural-fixes-implement-within-90-days">Structural fixes (implement within 90 days)</h3><ol><li>Build or adopt a browser-based entry flow that removes app install requirements</li><li>Instrument end-to-end funnel metrics across all seven stages</li><li>Deploy TURN server infrastructure for connection reliability on restricted networks</li><li>Implement adaptive bitrate streaming to eliminate call drops on variable bandwidth</li></ol><h2 id="common-mistakes-and-misconceptions">Common mistakes and misconceptions</h2><p><strong>Treating drop-off as a support problem, not a product problem.</strong> When a patient fails to connect, support teams close tickets. Product teams build systems that prevent the failure at scale. Most drop-off is silent patients who abandon do not call support.</p><p><strong>Optimizing the booking flow while ignoring onboarding.</strong> Scheduling teams focus on booking conversion. Product teams focus on connection success. Neither owns the onboarding gap between them, which is often where the largest patient losses occur.</p><p><strong>Assuming desktop performance applies to mobile.</strong> Telehealth access increasingly happens on mobile devices, often on cellular networks. Device check pass rates, connection success rates, and waiting room abandonment rates differ substantially between device types. Segment before you optimize.</p><p><strong>Using aggregate metrics to make stage-level decisions.</strong> A 75% overall visit completion rate masks the stage-level distribution. You need stage-level metrics, not just an end-to-end view.</p><p><strong>Solving video quality problems with more compression.</strong> Reducing video quality to compensate for poor network conditions degrades clinical utility and patient trust. The correct fix is adaptive bitrate streaming that adjusts dynamically, or a graceful fallback to audio-only with a clear explanation to the patient.</p><p><strong>Underestimating the role of trust signals.</strong> Patients in a telehealth waiting room have no ambient cues that the platform is functioning correctly. Clear status messages, provider headshots, visit confirmation numbers, and security badges all reduce anxiety-driven abandonment.</p><h2 id="key-takeaways">Key takeaways</h2><ol><li>Most telehealth platforms lose 20–40% of scheduled patients before the call connects, primarily at onboarding and device readiness stages.</li><li>Pre-call device checks run 24+ hours before the visit reduce day-of connection failures more effectively than any in-session fix.</li><li>The waiting room is the highest-abandonment stage for platforms with long provider delays, real-time status communication is the highest-ROI waiting room intervention.</li><li>Browser-first access with no mandatory app installation is the single largest onboarding conversion lever for first-time patients.</li><li>Funnel-stage metrics must be measured independently, aggregate completion rates hide stage-level drop-off and misdirect optimization effort.</li></ol><h2 id="faq">FAQ</h2><p><strong>Q1. What is the average patient drop-off rate in telemedicine visits?</strong> </p><p>Industry estimates vary significantly by platform maturity and patient population, but research suggests that telehealth platforms without structured optimization experience a 20–40% gap between scheduled and completed visits. Platforms with systematic onboarding, device readiness checks, and reliable video infrastructure typically reduce this gap to under 10%.</p><p><strong>Q2. What causes the most telemedicine video call abandonment?</strong> </p><p>The most common causes are device or browser incompatibility during the device readiness stage, excessive wait times in the virtual waiting room, and call connection failures due to network restrictions or WebRTC traversal issues. Poor pre-visit communication where patients do not receive clear instructions or timely reminders is the root cause of a large share of no-shows.</p><p><strong>Q3. How do I measure telemedicine conversion rate optimization progress?</strong> </p><p>Instrument each of the seven funnel stages independently: booking completion rate, onboarding completion rate, device check pass rate, waiting room retention rate, call connection success rate, average call duration versus expected, and post-visit action completion rate. Monitor each weekly and compare to pre-optimization baselines.</p><p><strong>Q4. Is a browser-based telehealth experience better than a native app?</strong> </p><p>For first-time patients, browser-based access consistently outperforms app-based access in terms of onboarding completion rates. Native apps offer advantages in push notification reliability and in-call performance for returning patients with the app already installed. The best practice is to offer browser-based access as the default with optional app download post-visit.</p><p><strong>Q5. How can I reduce waiting room abandonment specifically?</strong> </p><p>Display a real-time estimated wait time and update it continuously. Show a provider status indicator that communicates the reason for delay. Offer an optional pre-visit health questionnaire or educational content to give patients something to do. Trigger an automated notification at three minutes past scheduled start time. These four changes alone can reduce waiting room abandonment by 40–60% on platforms with long average waits.</p><p><strong>Q6. What technical infrastructure is required for reliable telehealth video calls?</strong> </p><p>Reliable telehealth video requires TURN server relay for patients behind restrictive NATs, adaptive bitrate streaming to handle variable network conditions, media traversal over standard HTTPS port 443, and support for multiple codecs (VP8, VP9, H.264) with automatic negotiation. Platforms experiencing high connection failure rates should audit their TURN server coverage and ensure fallback to relay mode is automatic, not manual.</p><p><strong>Q7. How does real-time video reliability affect patient engagement in video visits?</strong> </p><p>Studies in healthcare UX research show a direct correlation between call quality and patient satisfaction, trust in diagnosis, and likelihood of returning for future visits. Patients who experience audio or video degradation during a telehealth encounter report lower confidence in the clinical interaction and higher rates of early termination. Infrastructure investment in low-latency, adaptive video directly drives retention metrics.</p><p><strong>Q8. What is the fastest way to reduce patient drop-off without a major engineering effort?</strong> </p><p>The three highest-ROI quick wins that require minimal engineering are: (1) adding a pre-call device check link to reminder messages, (2) displaying a real-time provider status indicator in the waiting room, and (3) sending an automated post-visit summary within five minutes of call end. These three changes address the booking-to-completion journey's highest abandonment points without requiring infrastructure changes.</p>]]></content:encoded></item><item><title><![CDATA[WebRTC vs Zoom SDK vs VideoSDK for Telehealth in 2026]]></title><description><![CDATA[Comparing WebRTC, Zoom SDK, and VideoSDK for telehealth in 2026? This guide breaks down HIPAA compliance, latency, cost, and developer effort across all three, o you can choose the right video infrastructure for your platform without rebuilding later.]]></description><link>https://www.videosdk.live/blog/webrtc-vs-zoom-sdk-vs-videosdk-for-telehealth</link><guid isPermaLink="false">69f2ff0d55831517a5a99510</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 30 Apr 2026 07:44:02 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-30--2026--12_37_09-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>For most telehealth founders and CTOs evaluating video infrastructure in 2026, VideoSDK offers the strongest balance of compliance readiness, developer velocity, and cost predictability. Zoom SDK is appropriate where enterprise procurement and brand familiarity matter more than flexibility. Raw WebRTC remains relevant only when teams have the engineering capacity to own the entire media stack.</blockquote><h2 id="introduction-why-your-video-infrastructure-decision-matters-more-than-ever-in-2026">Introduction: Why your video infrastructure decision matters more than ever in 2026</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-30--2026--12_37_09-PM.png" alt="WebRTC vs Zoom SDK vs VideoSDK for Telehealth in 2026"/><p>The <a href="https://www.videosdk.live/solutions/telehealth" rel="noreferrer">telehealth market</a> has moved past the pandemic-era improvisation phase. Patients now expect clinical-grade video quality, zero dropped sessions, and interfaces that feel purpose-built for healthcare. Regulators expect documented compliance postures. Investors expect cost models that scale without cliff edges.</p><p>The infrastructure decision behind your video layer, the choice between WebRTC vs Zoom SDK vs VideoSDK telehealth 2026, now directly affects patient outcomes, developer velocity, regulatory audit readiness, and unit economics. Getting it wrong means rebuilding at scale.</p><p>This article evaluates all three options across eight criteria that matter to telehealth platforms: integration complexity, infrastructure control, compliance readiness, latency and reliability, scalability, cost model, time to market, and vendor lock-in risk. Every option is evaluated against the same criteria, with no promotional framing.</p><blockquote>Must read : <a href="https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api" rel="noreferrer">HIPAA compliant video API for healthcare platforms</a></blockquote><h2 id="how-to-evaluate-telehealth-video-infrastructure-the-eight-criteria">How to evaluate telehealth video infrastructure: the eight criteria</h2><p>Before comparing options, it is worth defining what good looks like across each dimension.</p><p><strong>Integration complexity</strong> measures how much engineering effort is required to embed video into a telehealth workflow, from initial proof of concept to production deployment.</p><p><strong>Infrastructure control</strong> covers how much of the signaling, media routing, and session management your team owns, configures, and can audit.</p><p><strong>Compliance readiness</strong> refers to built-in support for <a href="https://www.cdc.gov/phlp/php/resources/health-insurance-portability-and-accountability-act-of-1996-hipaa.html" rel="noreferrer nofollow">HIPAA (Health Insurance Portability and Accountability Act)</a> in the US, <a href="https://gdpr-info.eu/" rel="nofollow noreferrer">GDPR (General Data Protection Regulation)</a> in Europe, and similar frameworks. Compliance readiness is not just about BAA (Business Associate Agreement) availability, it includes data residency, access logging, and encryption posture.</p><p><strong>Latency and reliability</strong> defines the sub-second responsiveness required for clinical conversations, diagnostic video, and real-time consultation.</p><p><strong>Scalability</strong> addresses how cleanly the architecture handles growth from dozens to hundreds of thousands of concurrent sessions without re-architecture.</p><p><strong>Cost model</strong> evaluates pricing structure, predictability, and the total cost of ownership at various stages of platform growth.</p><p><strong>Time to market</strong> captures how quickly a team can ship a production-ready video feature using each option.</p><p><strong>Vendor lock-in risk</strong> measures how difficult it is to migrate away if pricing, reliability, or product direction changes.</p><h2 id="webrtc-for-telehealth-full-control-full-responsibility">WebRTC for telehealth: full control, full responsibility</h2><h3 id="what-webrtc-is">What WebRTC is</h3><p><a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer"><strong>WebRTC</strong></a> (Web Real-Time Communication) is an open standard and browser API maintained by the <a href="https://www.w3.org/TR/webrtc/" rel="nofollow noreferrer">W3C</a>&nbsp;and&nbsp;<a href="https://datatracker.ietf.org/wg/rtcweb/about/" rel="nofollow noreferrer">IETF</a>. It enables peer-to-peer audio, video, and data communication directly between browsers and native applications without plugins. WebRTC is not a product, it is a protocol suite that teams implement using a combination of <a href="https://www.videosdk.live/blog/what-is-webrtc-signaling" rel="noreferrer">signaling infrastructure</a>, STUN/TURN servers, and optional media servers such as Janus, Mediasoup, or Kurento.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-30--2026--12_46_27-PM.png" class="kg-image" alt="WebRTC vs Zoom SDK vs VideoSDK for Telehealth in 2026" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">WebRTC self-hosted telehealth architecture</span></figcaption></img></figure><h3 id="strengths">Strengths</h3><ul><li>Complete architectural control over every layer of the stack</li><li>No third-party data handling, all media traffic stays within your infrastructure</li><li>No per-minute or per-participant pricing, cost scales with your own server capacity</li><li>Best fit for platforms with strict data residency requirements in specific jurisdictions</li><li>Open standard with no vendor dependency</li></ul><h3 id="limitations">Limitations</h3><ul><li>Significant engineering effort: signaling, NAT traversal, codec negotiation, SFU selection, and recording pipelines must all be built and maintained</li><li>HIPAA compliance is entirely the team's responsibility, no BAA from a vendor, no pre-built audit tooling</li><li>Browser compatibility and codec differences require ongoing maintenance</li><li>Operational complexity increases sharply at scale, managing TURN server capacity, SFU load balancing, and global PoP distribution is a full-time infrastructure problem</li><li>Time to production is typically measured in months, not weeks</li></ul><h3 id="ideal-use-cases-for-webrtc-in-telehealth">Ideal use cases for WebRTC in telehealth</h3><ul><li>Large platforms with dedicated infrastructure engineering teams</li><li>Platforms in regulated jurisdictions requiring on-premises or private cloud deployment</li><li>Organisations with existing media server expertise (Janus, Mediasoup, LiveKit)</li><li>Platforms where third-party vendor contact with patient data is contractually or legally prohibited</li></ul><blockquote>Read: <a href="https://www.videosdk.live/blog/video-mer-medical-examination-report" rel="noreferrer">How video integration streamlines Medical Examination Reports (MER)</a></blockquote><h2 id="zoom-sdk-for-telehealth-enterprise-familiarity-constrained-flexibility">Zoom SDK for telehealth: enterprise familiarity, constrained flexibility</h2><h3 id="what-zoom-sdk-is">What Zoom SDK is</h3><p><a href="https://www.videosdk.live/blog/zoom-video-sdk-competitors" rel="noreferrer"><strong>Zoom SDK</strong></a> (Zoom Video SDK and Meeting SDK) allows developers to embed Zoom's video infrastructure into custom applications. Unlike the consumer Zoom product, the SDK exposes APIs for video sessions, participant management, and UI customisation. Zoom Video SDK is designed for building custom video experiences, while Zoom Meeting SDK embeds the full Zoom client into third-party apps.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-30--2026--01_00_17-PM.png" class="kg-image" alt="WebRTC vs Zoom SDK vs VideoSDK for Telehealth in 2026" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Zoom SDK telehealth architecture</span></figcaption></img></figure><h3 id="strengths-1">Strengths</h3><ul><li>Mature, globally distributed infrastructure with proven reliability at enterprise scale</li><li>HIPAA BAA available for qualifying healthcare organisations</li><li>High patient familiarity with Zoom as a brand, reducing onboarding friction in some demographics</li><li>Strong enterprise procurement pathways, fits existing vendor management processes</li><li>Robust recording and transcription capabilities built in</li></ul><h3 id="limitations-1">Limitations</h3><ul><li>Customisation is bounded by what Zoom's SDK exposes, you cannot modify the underlying media stack</li><li>All media traffic routes through Zoom's cloud, data residency control is limited to Zoom's available regions</li><li>Pricing is session-based and can become expensive at scale; cost modelling for high-volume telehealth platforms requires careful analysis</li><li>The UI and UX remain recognisably Zoom, differentiation at the product layer is constrained</li><li>Vendor lock-in is high: migrating away requires replacing all video infrastructure</li><li>SDK updates and deprecation cycles are on Zoom's timeline, not yours</li></ul><h3 id="ideal-use-cases-for-zoom-sdk-in-telehealth">Ideal use cases for Zoom SDK in telehealth</h3><ul><li>Enterprise health systems with existing Zoom Enterprise agreements</li><li>Platforms where brand recognition and patient comfort with Zoom reduces adoption friction</li><li>Organisations that need HIPAA compliance quickly without building compliance infrastructure</li><li>Teams with limited video engineering capacity and access to Zoom's enterprise support</li></ul><blockquote>Read: <a href="https://www.videosdk.live/blog/zoom-video-sdk-alternative" rel="noreferrer">Evaluating a Zoom Video SDK alternative for customized clinical UX</a></blockquote><h2 id="videosdk-for-telehealth-developer-first-real-time-infrastructure">VideoSDK for telehealth: developer-first real-time infrastructure</h2><h3 id="what-videosdk-is">What VideoSDK is</h3><p><a href="https://www.videosdk.live/" rel="noreferrer"><strong>VideoSDK</strong></a> is a real-time communication infrastructure platform that provides <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">video, audio, and data APIs</a> for web and mobile applications. It offers SDKs for React, JavaScript, Android, iOS, React Native, and Flutter, alongside server-side APIs for session management, recording, and participant control. VideoSDK is available at videosdk.live and documented at docs.videosdk.live.</p><p>VideoSDK is built on WebRTC internally but abstracts the infrastructure complexity, signaling, media routing, STUN/TURN management, and codec handling, behind an API layer that developers can integrate without media server expertise.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-30--2026--01_05_11-PM.png" class="kg-image" alt="WebRTC vs Zoom SDK vs VideoSDK for Telehealth in 2026" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">VideoSDK telehealth architecture</span></figcaption></img></figure><h3 id="strengths-2">Strengths</h3><ul><li>Low integration complexity: production-ready video in hours to days rather than weeks to months, using SDKs across all major platforms</li><li>Real-time audio and video APIs with low latency communication suitable for clinical consultation</li><li>Scalable infrastructure for live interactions, supporting growth from early-stage platforms to large concurrent session volumes</li><li>REST API and webhook support for session lifecycle management, start, stop, record, and monitor sessions programmatically</li><li>Pricing is structured around usage, offering more predictability than some enterprise SDK models at mid-market scale</li><li>Active documentation and SDK support reduces the engineering burden for teams without dedicated video infrastructure expertise</li></ul><h3 id="limitations-2">Limitations</h3><ul><li>Media traffic routes through VideoSDK's cloud, teams requiring full on-premises deployment must evaluate data residency options directly with the vendor</li><li>As a managed service, the underlying infrastructure is less customisable than a self-hosted WebRTC stack</li><li>Teams with very specific codec, SFU topology, or recording pipeline requirements may encounter constraints at the edges of the API surface</li></ul><h3 id="ideal-use-cases-for-videosdk-in-telehealth">Ideal use cases for VideoSDK in telehealth</h3><ul><li>Telehealth startups and growth-stage platforms needing fast integration across web and mobile</li><li>Platforms serving multiple geographies that need reliable low-latency performance without managing global PoP infrastructure</li><li>Development teams without dedicated WebRTC or media server expertise</li><li>Platforms prioritising developer velocity and time to market alongside scalability</li></ul><blockquote>Read : <a href="https://www.videosdk.live/blog/introduction-to-real-time-communication-sdk" rel="noreferrer">real-time video communication infrastructure</a></blockquote><h2 id="feature-and-capability-comparison-matrix">Feature and capability comparison matrix</h2>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Criterion</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">WebRTC (self-hosted)</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Zoom SDK</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">VideoSDK</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Integration complexity</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High — full stack build required</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium — SDK integration with Zoom constraints</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low — SDK integration across web and mobile</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Infrastructure control</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Full — you own everything</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low — Zoom cloud only</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium — managed cloud with API control</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">HIPAA BAA availability</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Self-managed — your infrastructure</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Yes, for qualifying orgs</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Verify directly with vendor</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">GDPR posture</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Self-managed</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Available with configuration</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Verify directly with vendor</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Data residency control</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Full — deploy anywhere</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Limited to Zoom regions</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Verify regional options with vendor</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Latency performance</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Excellent (peer-to-peer or optimised SFU)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Excellent (Zoom global infra)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low latency via managed media routing</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Global reliability</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Depends on your PoP deployment</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Excellent — Zoom's global network</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Managed global infrastructure</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Scalability ceiling</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Unlimited (engineering-bound)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High — Zoom's capacity</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High — scales with platform growth</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Time to market</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Months</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Days to weeks</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Hours to days</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Cost model</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">CapEx / infrastructure costs</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session-based pricing</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Usage-based pricing</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Cost predictability</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High (infrastructure-fixed)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Variable at scale</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Predictable at mid-market scale</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Vendor lock-in risk</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">None</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SDK platform coverage</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Build your own</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">iOS, Android, Web, Desktop</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">React, JS, Android, iOS, React Native, Flutter</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Recording capability</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Build your own pipeline</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Built-in</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">API-managed recording</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Active developer community</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Large (open standard)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Moderate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Active</td></tr></tbody></table>
<!--kg-card-end: html-->
<h2 id="recommendation-table-which-option-fits-your-platform">Recommendation table: which option fits your platform</h2>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Platform profile</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Recommended option</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Rationale</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Early-stage telehealth startup, small engineering team</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">VideoSDK</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Fastest path to production across web and mobile; avoids infrastructure overhead</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Enterprise health system with existing Zoom agreement</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Zoom SDK</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Procurement alignment, HIPAA BAA, patient brand familiarity</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Large platform, dedicated infrastructure team, strict data residency</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">WebRTC (self-hosted)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Full control, no third-party data handling, unlimited customisation</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mid-market platform scaling across multiple geographies</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">VideoSDK</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Managed global infrastructure, predictable cost, multi-platform SDK coverage</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Platform in a jurisdiction with specific on-prem requirements</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">WebRTC or hybrid</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Evaluate VideoSDK data residency options; fallback to self-hosted</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Platform needing custom recording pipelines and SFU topology</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">WebRTC</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">API surface of managed services may not cover edge requirements</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Team evaluating vendor lock-in risk as a primary concern</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">WebRTC</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Open standard, no proprietary dependency</td></tr></tbody></table>
<!--kg-card-end: html-->
<h2 id="architecture-considerations-for-telehealth-platforms">Architecture considerations for telehealth platforms</h2><h3 id="compliance-is-architecture-not-a-checkbox">Compliance is architecture, not a checkbox</h3><p>In telehealth, <strong>HIPAA compliance</strong> is not a feature you add at the end, it shapes every layer of the video stack. This means <a href="https://www.videosdk.live/blog/high-grade-client-to-server-encryption" rel="noreferrer">encryption in transit (TLS 1.2 minimum) and at rest</a>, access logging for all session metadata, BAA coverage for any third-party vendor handling PHI (protected health information), and documented data retention and deletion policies.</p><p>Self-hosted WebRTC gives you maximum compliance flexibility but transfers the entire burden to your engineering and security teams. Managed services like Zoom SDK and VideoSDK reduce that burden but require you to verify their compliance posture, BAA availability, and data handling practices before signing contracts.</p><blockquote>Read: <a href="https://www.videosdk.live/blog/build-or-buy-video-calling-api" rel="noreferrer">Build vs buy video calling API evaluation framework</a></blockquote><h3 id="latency-requirements-in-clinical-video">Latency requirements in clinical video</h3><p>Clinical consultation requires video latency below 150ms round-trip for natural conversation. Diagnostic applications, remote dermatology, ophthalmology, wound care, may require higher frame rates and more aggressive codec configuration.</p><p>Pure peer-to-peer WebRTC achieves the lowest possible latency but degrades in multi-party sessions or across poor network paths. Managed infrastructure with globally distributed media routing, as provided by both Zoom and VideoSDK, trades some theoretical minimum latency for consistency and reliability across varied network conditions.</p><h3 id="scalability-models-differ-significantly">Scalability models differ significantly</h3><p>A self-hosted WebRTC architecture scales by adding media server capacity, TURN server nodes, and signaling infrastructure. This is linear but engineering-intensive. Managed services abstract this, you pay for sessions and the vendor handles infrastructure elasticity.</p><p>For telehealth platforms with predictable session volumes (scheduled appointments), managed services offer cost efficiency. For platforms with highly variable or burst session demand, the pricing model of the managed service matters more than the underlying technology.</p><h3 id="multi-platform-coverage-is-a-telehealth-specific-requirement">Multi-platform coverage is a telehealth-specific requirement</h3><p>Telehealth patients access care from mobile phones, tablets, and desktop browsers, often on consumer-grade connections. Your video infrastructure must deliver a consistent experience across Android, iOS, and web simultaneously. VideoSDK's SDK coverage across React, JavaScript, Android, iOS, React Native, and Flutter is directly relevant here. Zoom SDK also covers major platforms. Self-hosted WebRTC requires building and maintaining native SDKs or relying on third-party wrappers.</p><h2 id="final-verdict-scenario-based-recommendations">Final verdict: scenario-based recommendations</h2><p><strong>Choose WebRTC if</strong> your platform operates in a jurisdiction where all patient data must remain on-premises or in a private cloud you fully control, your team includes dedicated media infrastructure engineers, and you are building for long-term differentiation at the infrastructure layer. Accept that time to market will be longer and ongoing operational cost will be significant.</p><p><strong>Choose Zoom SDK if</strong> your organisation already has Zoom Enterprise licensing and procurement infrastructure, your patient base has demonstrated comfort with Zoom as an interface, and you need HIPAA BAA coverage quickly without building compliance tooling. Accept that customisation, pricing at scale, and vendor lock-in are real constraints.</p><p><strong>Choose VideoSDK if</strong> you are building a telehealth product and need to move fast across web and mobile, you want managed low-latency infrastructure without the operational overhead of a self-hosted media stack, and you are building at a stage where engineering velocity and cost predictability matter more than full infrastructure ownership. Verify the compliance posture and data residency options directly with VideoSDK for your specific regulatory context.</p><p>For most telehealth founders and CTOs reading this in 2026, the primary decision is between VideoSDK and raw WebRTC, with Zoom SDK as a reasonable choice only in specific enterprise contexts. The WebRTC vs Zoom SDK vs VideoSDK telehealth 2026 comparison ultimately resolves to a trade-off between control and velocity.</p><h2 id="key-takeaways">Key takeaways</h2><ol><li><strong>WebRTC provides maximum infrastructure control</strong> but requires significant engineering capacity and transfers all compliance responsibility to your team.</li><li><strong>Zoom SDK offers enterprise-grade reliability and brand familiarity</strong> but constrains customisation and creates high vendor dependency.</li><li><strong>VideoSDK reduces integration complexity and time to market</strong> for telehealth platforms across web and mobile, with managed low-latency infrastructure.</li><li><strong>HIPAA compliance is an architectural requirement, not a feature,</strong> evaluate BAA availability, data residency, and encryption posture for any option you select.</li><li><strong>Time to market and infrastructure control trade off directly,</strong> the right choice depends on your team's engineering capacity and your platform's compliance context.</li></ol><h2 id="frequently-asked-questions">Frequently asked questions</h2><p><strong>Q.1 Is WebRTC HIPAA compliant for telehealth?</strong> </p><p>WebRTC itself is a protocol, not a product, it does not provide HIPAA compliance. HIPAA compliance depends entirely on how you implement the surrounding infrastructure: encryption, access controls, audit logging, and BAA coverage with any vendors who handle PHI. Teams building on raw WebRTC are responsible for the full compliance posture.</p><p><strong>Q.2 Does Zoom SDK provide a HIPAA BAA for telehealth platforms?</strong> </p><p>Zoom offers HIPAA BAA coverage for qualifying healthcare organisations under its enterprise plans. This does not automatically make your application HIPAA compliant, you must also implement appropriate access controls, session logging, and data handling practices in your application layer. Verify the current BAA scope directly with Zoom's enterprise team.</p><p><strong>Q.3 What is the difference between Zoom Meeting SDK and Zoom Video SDK for telehealth?</strong> </p><p>Zoom Meeting SDK embeds the full Zoom meeting experience inside your application, including Zoom's native UI. Zoom Video SDK allows developers to build fully custom video experiences using Zoom's infrastructure without the Zoom meeting interface. For telehealth platforms requiring custom clinical UX, the Video SDK is generally more appropriate.</p><p><strong>Q.4 How does VideoSDK handle compliance for healthcare applications?</strong> </p><p>VideoSDK provides managed real-time communication infrastructure with encryption in transit and at rest. Teams building HIPAA-regulated telehealth applications should verify VideoSDK's current BAA availability, data residency configuration, and compliance documentation directly at videosdk.live before production deployment.</p><p><strong>Q.5 What latency can telehealth platforms expect from each option?</strong> </p><p>Clinical conversation requires round-trip latency below approximately 150ms. Peer-to-peer WebRTC on good network paths can achieve sub-50ms. Managed services like Zoom and VideoSDK use globally distributed media routing to deliver consistent low-latency performance across varied network conditions, typically in the 50-150ms range for geographically proximate users.</p><p><strong>Q.6 Which option is best for a telehealth startup with a small engineering team?</strong> </p><p>For teams without dedicated media infrastructure expertise, a managed SDK approach, VideoSDK or Zoom SDK, is strongly preferable to self-hosted WebRTC. VideoSDK's multi-platform SDK coverage and API-driven session management make it particularly well-suited to startup teams needing production-grade video across web and mobile without WebRTC infrastructure expertise.</p><p><strong>Q.8 Can I migrate away from Zoom SDK or VideoSDK to self-hosted WebRTC later?</strong> </p><p>Migration is possible but non-trivial. Both Zoom SDK and VideoSDK abstract the media layer, migrating to self-hosted WebRTC requires rebuilding signaling, media server infrastructure, STUN/TURN configuration, and SDK integrations across all client platforms. Plan migration complexity into your architectural decisions early, particularly if infrastructure ownership is a long-term strategic requirement.</p><p><strong>Q.9 How does global performance differ across these options for international telehealth?</strong> </p><p>Zoom operates one of the largest globally distributed video infrastructure networks, offering strong performance across most geographies. VideoSDK provides managed global media routing without requiring you to deploy regional infrastructure. Self-hosted WebRTC performance is entirely determined by your PoP deployment strategy, without regional TURN and media server capacity, international performance degrades significantly.</p>]]></content:encoded></item><item><title><![CDATA[IRDAI VBIP Compliance Guide for InsurTech]]></title><description><![CDATA[Master IRDAI VBIP compliance InsurTech teams need a regulatory framework, technical architecture, audit checklist, and implementation steps in one guide.]]></description><link>https://www.videosdk.live/irdai-vbip-compliance-guide-for-insurtech</link><guid isPermaLink="false">69f0ae2255831517a5a96588</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 29 Apr 2026 11:45:12 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-28--2026--06_33_15-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TLDR:</strong> IRDAI's Video Based Identification Process (VBIP) mandates live video verification for remote insurance customer onboarding in India. InsurTech companies must build compliant real-time video infrastructure, capture geo-tagged consent, record sessions, and maintain auditable storage to pass regulatory scrutiny.</blockquote><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-text">IRDAI VBIP is a regulatory framework requiring insurers and InsurTech platforms to verify customer identity through a live video interaction before issuing policies remotely. InsurTech companies ensure VBIP compliance InsurTech-wide by implementing real-time video sessions with liveness detection, Aadhaar-based or OVD document validation, geo-tagged session recording, and structured audit trails aligned to IRDAI onboarding guidelines.</div></div><h2 id="introduction"><strong>Introduction</strong></h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-28--2026--06_33_15-PM.png" alt="IRDAI VBIP Compliance Guide for InsurTech"/><p>India's insurance sector processed over 500 million policies as of recent <a href="https://irdai.gov.in/annual-reports" rel="noreferrer nofollow">IRDAI annual reports</a>, and a growing share are issued through digital channels. That shift created a verification gap, how do insurers confirm a remote applicant's identity without physical presence?</p><p><strong>IRDAI VBIP compliance InsurTech</strong> companies must achieve closes that gap. The Insurance Regulatory and Development Authority of India introduced the Video Based Identification Process as a structured, auditable alternative to in-person KYC. Getting it wrong carries consequences ranging from policy issuance blocks to licensing risk.</p><p>This guide covers every layer of VBIP compliance: the regulatory framework, process flow, technical architecture, a compliance checklist, operational metrics, and common implementation mistakes.</p><h2 id="what-is-irdai-vbip"><strong>What is IRDAI VBIP?</strong></h2><p><strong>Video Based Identification Process (VBIP):</strong> <a href="https://www.videosdk.live/blog/video-based-identification-procedure-vbip" rel="noreferrer">VBIP</a> is an IRDAI-mandated procedure through which an insurer or its authorised intermediary conducts a live, recorded video interaction with a prospective policyholder to verify identity, confirm document authenticity, and capture informed consent before issuing a policy remotely.</p><p><strong>KYC (Know Your Customer):</strong> <a href="https://en.wikipedia.org/wiki/Know_your_customer" rel="noreferrer nofollow">KYC</a> is the regulatory requirement for financial institutions to verify the identity and address of their customers before onboarding. VBIP is the video-first mechanism through which insurance KYC is completed in digital channels.</p><p>VBIP applies across life, general, and health insurance product lines wherever the customer is not physically present at a branch, and its protocols are increasingly relevant for secure, remote&nbsp;<a href="https://www.videosdk.live/blog/insurance-claim-settlement" rel="noreferrer">insurance claim settlement</a>. It is not optional for digital-first onboarding. It replaces the earlier requirement for wet-ink signatures or in-person document submission when conducted correctly.</p><p>IRDAI introduced VBIP as part of broader <strong>IRDAI onboarding guidelines</strong> aimed at reducing fraud in digital insurance distribution. The process mirrors the <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc" rel="noreferrer">video KYC framework established by RBI</a> for banking, but with insurance-specific adaptations including policy-linked consent capture and insurer-side storage obligations.</p><h2 id="regulatory-context-and-legal-framework"><strong>Regulatory context and legal framework</strong></h2><h3 id="who-must-comply-with-vbip"><strong>Who must comply with VBIP?</strong></h3><p>Any entity licensed by IRDAI that onboards customers remotely must comply with VBIP rules. This includes:</p><ul><li>Life insurers</li><li>General insurers</li><li>Health insurers</li><li>Insurance Web Aggregators (IWAs)</li><li>Insurance Marketing Firms (IMFs)</li><li>Corporate agents operating digital channels</li></ul><p>InsurTech platforms that act as intermediaries or technology providers to the above entities are operationally bound by VBIP requirements even if they are not the licensed entity. If your platform initiates, manages, or records the verification session, you are within scope.</p><h3 id="relationship-with-aml-kyc-and-aadhaar-frameworks"><strong>Relationship with AML, KYC, and Aadhaar frameworks</strong></h3><p>VBIP does not stand alone. It intersects with three adjacent regulatory systems:</p><p><strong>Anti-Money Laundering (AML) rules:</strong> The <a href="https://fiuindia.gov.in/files/AML_Legislation/pmla_2002.html" rel="noreferrer">Prevention of Money Laundering Act (PMLA)</a> and IRDAI's AML guidelines require insurers to conduct customer due diligence (CDD) before policy issuance. VBIP serves as the CDD mechanism for digital channels. Any VBIP implementation must feed into the insurer's AML compliance record.</p><p><strong>KYC norms under IRDAI:</strong> IRDAI's <strong>VBIP KYC insurance India</strong> framework specifies Officially Valid Documents (OVDs) that must be captured during the video session. These include Aadhaar, PAN, passport, voter ID, and driving licence.</p><p><strong>Aadhaar-based verification:</strong> Where customers consent, <strong>Aadhaar-based verification</strong> via UIDAI's authentication infrastructure can supplement VBIP. Aadhaar XML or DigiLocker-fetched documents may be used. Any use of Aadhaar data must comply with <a href="https://www.uidai.gov.in/" rel="noreferrer nofollow">UIDAI guidelines</a>. Refer to official&nbsp;<a href="https://irdai.gov.in/guidelines" rel="noreferrer nofollow">IRDAI guidelines</a> for the current circular on permissible OVDs.</p><h2 id="vbip-process-flow"><strong>VBIP process flow</strong></h2><p>The <strong>insurance video verification process</strong> follows a structured sequence. Deviation at any step creates compliance gaps.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-29--2026--04_56_21-PM.png" class="kg-image" alt="IRDAI VBIP Compliance Guide for InsurTech" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">VBIP flow in insurance onboarding</span></figcaption></img></figure><h3 id="step-by-step-process"><strong>Step-by-step process</strong></h3><p><strong>1. User initiation</strong> The customer triggers the VBIP flow through the insurer's app or web platform. The system confirms device compatibility, checks network adequacy, and verifies that the session is initiated only during permitted hours. IRDAI requires VBIP sessions to occur only during business hours (currently 9 AM to 6 PM IST) to ensure an authorised official is present on the insurer's side.</p><p><strong>2. Consent capture</strong> Before any video session begins, the platform must capture explicit, informed digital consent from the customer. Consent must cover: identity verification, session recording, data storage, and use of the captured information for policy issuance. Consent must be timestamped and stored as part of the audit record.</p><p><strong>3. Live video session</strong> A trained, authorised official from the insurer or its agent conducts a live interaction. This is not a pre-recorded or automated flow, a human must be present on the insurer's side. The official must:</p><ul><li>Confirm the customer's live presence through randomised questions or gestures</li><li>Request display of the OVD to the camera</li><li>Read and confirm key details aloud during the session</li></ul><p><strong>4. Document validation</strong> The official visually verifies the OVD displayed on camera. The system simultaneously captures a clear frame of the document for record. AI-assisted frame extraction may be used for clarity, but final validation responsibility rests with the authorised official.</p><p><strong>5. Geo-tagging</strong> The customer's location at the time of the session must be geo-tagged and recorded. This confirms the customer is physically present in India and assists in fraud detection. Sessions initiated from outside India must be flagged or rejected depending on the insurer's policy.</p><p><strong>6. Recording and storage</strong> The full session must be recorded end-to-end at sufficient resolution to allow retrospective review. Recording must capture both sides of the interaction. Storage must meet IRDAI's data retention requirements, typically five years minimum.</p><p><strong>7. Audit trail generation</strong> Every VBIP session must produce a complete audit record including: session ID, timestamp, official's ID, customer ID, OVD type captured, geo-tag, consent log, and recording reference. This record feeds the insurer's compliance system and must be retrievable on IRDAI request.</p><h2 id="technical-architecture-for-vbip"><strong>Technical architecture for VBIP</strong></h2><h3 id="what-technical-infrastructure-does-a-vbip-system-require"><strong>What technical infrastructure does a VBIP system require?</strong></h3><p><strong>Digital KYC insurance India</strong> implementations require a multi-layer technical stack. Each layer has specific compliance implications.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-29--2026--04_59_42-PM.png" class="kg-image" alt="IRDAI VBIP Compliance Guide for InsurTech" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">VBIP system architecture</span></figcaption></img></figure><h3 id="core-infrastructure-layers"><strong>Core infrastructure layers</strong></h3><p><a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer"><strong>Real-time video infrastructure</strong></a><strong>:</strong> The video layer must support low-latency, high-reliability peer-to-peer or server-mediated video. <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> is the standard protocol for this. The infrastructure must handle concurrent sessions without degrading video quality, since frame clarity directly affects document readability during the session.</p><p>Latency requirements are strict: sessions with persistent lag above 500ms create failed verification events where officials cannot reliably assess liveness or read documents. <strong>Video KYC insurance compliance</strong> implementations should target sub-300ms round-trip latency under normal network conditions.</p><p>Platforms like<a href="https://videosdk.live/"> <u>VideoSDK</u></a> provide WebRTC-based real-time video infrastructure with session recording built in, which reduces the engineering complexity of building a compliant VBIP layer from scratch. Their <a href="https://docs.videosdk.live/" rel="noreferrer">developer documentation</a> covers session management APIs relevant to compliance recording scenarios.</p><p><strong>Session recording</strong> Recording must begin automatically at session start and end only after the official formally closes the session. Gaps in recording invalidate the audit trail. The recording pipeline must write to immutable or append-only storage with checksum verification to detect tampering.</p><p><strong>Liveness and fraud detection</strong> The system must support detection of:</p><ul><li>Spoofing attempts (printed photographs, displayed screens held to the camera)</li><li>Passive <a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">liveness checks</a> (eye-blink detection, micro-movement analysis)</li><li>Injection attacks (pre-recorded video feeds replacing live camera input)</li></ul><p>AI-assisted liveness detection can be integrated as a signal layer, but it does not replace the mandatory human official on the insurer's side.</p><p><strong>Geo-location capture</strong> The customer device must request location permission at session initiation. Coordinate data is attached to the session record. If the customer denies location permission, the session must not proceed, IRDAI geo-tagging is non-optional.</p><p><strong>Backend and compliance storage</strong> Session metadata, consent logs, geo-tags, document frames, and recording references must be stored in an encrypted, access-controlled backend. Storage must be in India (data localisation) unless IRDAI specifically permits otherwise. Retention: minimum five years from session date.</p><h2 id="vbip-compliance-framework"><strong>VBIP compliance framework</strong></h2><h3 id="the-five-category-vbip-compliance-checklist-for-insurtech"><strong>The five-category VBIP compliance checklist for InsurTech</strong></h3><p>The following framework organises your compliance obligations into auditable categories.</p><p><strong>Category 1: Customer consent</strong> Every VBIP flow must obtain, record, and store explicit consent before the video session begins. Consent must reference the specific purpose, duration of data storage, and customer rights.</p><p><strong>Category 2: Video interaction rules</strong> Sessions must occur during permitted hours, be conducted by a trained and authorised official, include liveness confirmation, and capture OVD display on camera.</p><p><strong>Category 3: Data capture</strong> The system must capture: customer face frame, OVD frame, geo-coordinates, session timestamp, official identity, and session duration.</p><p><strong>Category 4: Storage requirements</strong> All captured data must be encrypted at rest, stored in India, retained for a minimum of five years, and accessible only to authorised compliance personnel and IRDAI.</p><p><strong>Category 5: Audit readiness</strong> Every session must generate a structured audit record retrievable by session ID, customer ID, date range, and official ID. Audit records must be producible within 24 hours of an IRDAI request.</p><h2 id="compliance-checklist"><strong>Compliance checklist</strong></h2><table>
<thead>
<tr>
<th>Requirement</th>
<th>Description</th>
<th>Mandatory</th>
<th>Risk if missed</th>
</tr>
</thead>
<tbody>
<tr>
<td>Business hours restriction</td>
<td>VBIP sessions only between 9 AM and 6 PM IST</td>
<td>Yes</td>
<td>Session invalidation, policy void risk</td>
</tr>
<tr>
<td>Authorised official present</td>
<td>A trained, licensed insurer official must conduct the session</td>
<td>Yes</td>
<td>Non-compliant onboarding, regulatory action</td>
</tr>
<tr>
<td>Explicit digital consent</td>
<td>Timestamped consent before session start</td>
<td>Yes</td>
<td>Audit failure, PMLA violation</td>
</tr>
<tr>
<td>OVD captured on camera</td>
<td>Official must visually verify and frame-capture the document</td>
<td>Yes</td>
<td>KYC gap, policy issuance block</td>
</tr>
<tr>
<td>Liveness confirmation</td>
<td>Randomised gesture or question to confirm live presence</td>
<td>Yes</td>
<td>Fraud liability, audit failure</td>
</tr>
<tr>
<td>Geo-tagging</td>
<td>Customer coordinates captured and stored</td>
<td>Yes</td>
<td>Audit failure, session invalidation</td>
</tr>
<tr>
<td>End-to-end recording</td>
<td>Full session recorded with no gaps</td>
<td>Yes</td>
<td>Complete audit trail loss</td>
</tr>
<tr>
<td>Encrypted storage</td>
<td>Session data encrypted at rest and in transit</td>
<td>Yes</td>
<td>Data breach liability, IRDAI penalty</td>
</tr>
<tr>
<td>Data localisation</td>
<td>All data stored on servers located in India</td>
<td>Yes</td>
<td>Regulatory non-compliance</td>
</tr>
<tr>
<td>Five-year retention</td>
<td>Session records retained for minimum five years</td>
<td>Yes</td>
<td>Audit non-producibility penalty</td>
</tr>
<tr>
<td>Audit trail generation</td>
<td>Structured record per session with all metadata</td>
<td>Yes</td>
<td>Regulatory reporting failure</td>
</tr>
<tr>
<td>Official identity logged</td>
<td>ID of conducting official recorded per session</td>
<td>Yes</td>
<td>Accountability gap</td>
</tr>
<tr>
<td>Session ID assignment</td>
<td>Unique identifier per VBIP session</td>
<td>Yes</td>
<td>Audit traceability failure</td>
</tr>
<tr>
<td>Tamper-evident storage</td>
<td>Checksum or immutable storage for recordings</td>
<td>Recommended</td>
<td>Evidence admissibility risk</td>
</tr>
<tr>
<td>AI liveness layer</td>
<td>Automated spoofing detection as supplementary signal</td>
<td>Recommended</td>
<td>Fraud exposure</td>
</tr>
</tbody>
</table>
<h2 id="consequences-of-non-compliance"><strong>Consequences of non-compliance</strong></h2><h3 id="what-happens-if-an-insurtech-fails-vbip-compliance"><strong>What happens if an InsurTech fails VBIP compliance?</strong></h3><p>Non-compliance with <strong>IRDAI VBIP compliance InsurTech</strong> requirements carries consequences across four dimensions.</p><p><strong>Regulatory penalties:</strong> IRDAI may issue directions, monetary penalties, or corrective action orders against licensed entities. Penalties under the Insurance Act can extend to significant fines per violation and per day of continued violation.</p><p><strong>Licensing impact:</strong> Persistent non-compliance can trigger licence review proceedings. For InsurTech platforms operating as intermediaries, the licensed entity (insurer or IWA) they serve may be compelled to terminate the technology arrangement to protect their own licence.</p><p><strong>Policy issuance risk:</strong> Policies issued on the basis of non-compliant VBIP sessions carry a risk of being declared void. This creates both customer liability and insurer balance sheet exposure.</p><p><strong>Audit failures:</strong> IRDAI conducts periodic audits of insurer onboarding systems. An incomplete audit trail, missing geo-tags, recording gaps, absent consent logs, results in adverse audit findings that must be publicly disclosed and remediated under regulatory supervision.</p><h2 id="metrics-and-operational-benchmarks"><strong>Metrics and operational benchmarks</strong></h2><p>Compliance is not only about meeting requirements at initial implementation. Operations teams must monitor ongoing performance to detect drift.</p><table>
<thead>
<tr>
<th>Metric</th>
<th>Definition</th>
<th>Target benchmark</th>
</tr>
</thead>
<tbody>
<tr>
<td>Verification success rate</td>
<td>Sessions completed with full compliant data capture</td>
<td>Above 92%</td>
</tr>
<tr>
<td>Session failure rate</td>
<td>Sessions terminated due to technical error</td>
<td>Below 5%</td>
</tr>
<tr>
<td>Drop-off rate</td>
<td>Customers who initiate but do not complete VBIP</td>
<td>Below 15%</td>
</tr>
<tr>
<td>Average verification time</td>
<td>End-to-end session duration from consent to close</td>
<td>5 to 10 minutes</td>
</tr>
<tr>
<td>Audit producibility rate</td>
<td>Audit records retrievable within 24 hours on request</td>
<td>100%</td>
</tr>
<tr>
<td>Geo-tag capture rate</td>
<td>Sessions with valid geo-coordinates attached</td>
<td>100%</td>
</tr>
<tr>
<td>Recording completeness</td>
<td>Sessions with unbroken end-to-end recording</td>
<td>Above 99%</td>
</tr>
</tbody>
</table>
<p>Any metric falling outside these ranges should trigger an immediate technical and process review. The audit producibility rate and recording completeness must be maintained at 100%, partial records have no value in an IRDAI audit.</p><h2 id="common-mistakes-in-vbip-implementation"><strong>Common mistakes in VBIP implementation</strong></h2><p><strong>1. Treating VBIP as automated video KYC</strong> VBIP requires a live, authorised human official on the insurer's side. InsurTechs that build fully automated flows, even with excellent AI liveness detection, fail this requirement. The official is not optional.</p><p><strong>2. Missing geo-tag capture on certain devices</strong> Some customer devices deny location permissions by default, or GPS is unavailable in specific environments. The system must hard-block session progression if geo-location cannot be captured, not silently log a null value.</p><p><strong>3. Recording gaps at session boundaries</strong> Recording failures most commonly occur at the start and end of sessions due to connection negotiation delays. If recording begins 10 seconds after consent capture, that gap is a compliance deficiency. Buffer the recording start before the live session frame appears.</p><p><strong>4. Inadequate storage encryption</strong> Storing session recordings in S3-equivalent object storage without key management, access logging, or tamper detection is insufficient. IRDAI expects controls that would survive legal discovery and withstand a forensic audit.</p><p><strong>5. No structured audit record per session</strong> Storing recordings and metadata in separate systems without a single retrievable audit record per session ID creates retrieval delays. When IRDAI requests a specific session's records, every component, consent log, geo-tag, OVD frame, recording, official ID, must be producible together within 24 hours.</p><h2 id="key-takeaways"><strong>Key takeaways</strong></h2><ul><li>VBIP is mandatory for all digital insurance onboarding in India; it cannot be replaced by purely automated flows.</li><li>A trained, authorised insurer official must be present on video for every session.</li><li>Geo-tagging is non-optional; sessions without valid coordinates must not proceed.</li><li>All session data must be stored encrypted, in India, for a minimum of five years.</li><li>Audit trail completeness is the most common failure point in IRDAI audits, structure your compliance record at session level, not component level.</li></ul><h2 id="faq"><strong>FAQ</strong></h2><p><strong>What is the difference between VBIP and video KYC in banking?</strong> </p><p>Both are live video identification processes, but VBIP is governed by IRDAI while banking video KYC falls under RBI's Master Direction on KYC. VBIP has insurance-specific requirements such as policy-linked consent and insurer-side authorised official presence. The underlying technology layer is similar, but the compliance obligations differ by regulator.</p><p><strong>Can an InsurTech platform conduct the VBIP session on behalf of the insurer?</strong> </p><p>An InsurTech can provide the technology platform and may have the session conducted by an authorised agent or intermediary, but the conducting official must be authorised by the licensed insurer. The insurer retains regulatory accountability. Refer to the official <a href="https://irdai.gov.in/" rel="noreferrer">IRDAI</a> guidelinces for the specific permissible delegation arrangements.</p><p><strong>Is Aadhaar-based eKYC a substitute for VBIP?</strong> </p><p>Aadhaar-based eKYC via OTP or biometric can satisfy identity verification requirements in some contexts, but VBIP is specifically required for remote policy issuance where the customer is not physically present. The two mechanisms address overlapping but distinct requirements. Always verify which is applicable for your specific product type with your compliance counsel.</p><p><strong>What are the permitted hours for conducting VBIP sessions?</strong></p><p>IRDAI requires VBIP sessions to occur during business hours, currently 9 AM to 6 PM IST. Sessions initiated outside these hours must be blocked at the platform level. Refer to the official IRDAI guidelines at<a href="https://www.irdai.gov.in/"> </a>for any updates to this window.</p><p><strong>How long must VBIP session recordings be retained?</strong> </p><p>IRDAI mandates a minimum retention period of five years from the session date. Some insurers apply a longer retention period (up to ten years) aligned to their broader policy record retention policy. Storage must be encrypted and tamper-evident.</p><p><strong>What document types are acceptable as OVDs during a VBIP session?</strong> </p><p>Officially Valid Documents include Aadhaar card, PAN card, passport, voter ID, and driving licence. The customer must physically display the document to the camera during the live session. Soft copies displayed on a screen are not acceptable as they cannot be validated for authenticity.</p><p><strong>How should a session be handled if the video connection drops mid-session?</strong> </p><p>A dropped connection invalidates the session. The customer must restart the full VBIP flow from the consent capture stage. Do not attempt to resume a partial session, the recording gap creates an irreparable audit deficiency. The system should detect disconnection, terminate the session, log the failure reason, and prompt restart.</p><p><strong>What is the insurer's liability if a fraudulent customer passes VBIP?</strong> </p><p>The insurer remains liable for any policy issued on the basis of a fraudulent identity, but a documented, compliant VBIP process significantly reduces regulatory exposure. Regulators assess whether the insurer followed required procedures, not whether fraud was prevented in every case. A compliant process with proper audit records is the defence.</p>]]></content:encoded></item><item><title><![CDATA[Video KYC Success Rate Optimization Drop-off Guide]]></title><description><![CDATA[Reduce video KYC drop-off and improve V-CIP success rates with this RBI-compliant optimisation framework for BFSI product teams.]]></description><link>https://www.videosdk.live/video-kyc-success-rate-optimization-guide</link><guid isPermaLink="false">69f08e7755831517a5a9363b</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 28 Apr 2026 12:00:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/04/13.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> Video KYC drop-off is a measurable, fixable problem. Most abandonment clusters around three stages, pre-session readiness, queue wait, and document capture. Fixing infra, UX, and compliance gaps at each stage can push completion rates from the industry average of 55–65% to 80%+.</blockquote><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-text">To optimize video KYC success rate and reduce drop-off, diagnose abandonment at each funnel stage, entry, document upload, queue, agent connect, and verification, then apply targeted fixes across UX, infrastructure, and compliance layers. Platforms that address all three layers systematically see the highest gains in KYC completion rate optimization.</div></div><h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/13.png" alt="Video KYC Success Rate Optimization Drop-off Guide"/><p><strong>Video KYC</strong> (also called <strong>V-CIP</strong>, or Video-based Customer Identification Process) has become the default onboarding mechanism for regulated financial entities in India. <a href="https://rbi.org.in/scripts/NotificationUser.aspx?Mode=0&amp;Id=12089" rel="noreferrer nofollow">The Reserve Bank of India's V-CIP guidelines</a> mandate that banks, NBFCs, and payment aggregators use live video verification in place of in-person KYC for remote customers.</p><p>The regulatory intent is clear. The operational reality, however, is messy: a significant share of users who begin a video KYC session never complete it. Every incomplete session is a lost account, a lost revenue opportunity, and, in high-volume pipelines, a compounding drag on growth.</p><p><strong>Video KYC success rate optimization drop-off</strong> is not a UX problem alone. It is a systems problem spanning device readiness, network conditions, agent capacity, compliance constraints, and session reliability. This guide gives product managers, growth teams, and compliance leaders a structured framework to diagnose drop-off, prioritize fixes, and benchmark results.</p><h2 id="regulatory-and-market-context">Regulatory and market context</h2><p>India's V-CIP framework, introduced by the RBI in 2020 and updated since, requires financial entities to conduct live, two-way video sessions with customers during onboarding. The session must be conducted by a trained official, include live document verification, <a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">liveness detection</a>, and geo-tagging, and be stored with a full audit trail. </p><p>The scale of adoption is significant. With India's BFSI sector processing tens of millions of new account openings annually, even a 10-percentage-point improvement in <strong>KYC completion rate optimization</strong> translates to hundreds of thousands of additional activated accounts per year.</p><p>The challenge: RBI's compliance requirements create hard constraints that limit how much UX alone can solve. Any optimization framework must work within, not around, those constraints.</p><blockquote>Must Read: <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc" rel="noreferrer">RBI Video KYC Guidelines</a></blockquote><h2 id="what-is-video-kyc-success-rate-and-drop-off">What is video KYC success rate and drop-off?</h2><p><strong>Success rate</strong> is the percentage of users who initiate a video KYC session and complete it successfully, meaning the session results in a verified, approvable identity record. It is the primary metric for <strong>video onboarding success metrics</strong> tracking.</p><p><strong>Drop-off rate</strong> is the inverse: the percentage of users who start the process but do not complete it. Drop-off can occur at any stage, before the session begins, during the queue, mid-session, or post-session due to verification failure.</p><p>Typical industry benchmarks range between 55–75% completion depending on platform type, user segment, device mix, and network conditions. Best-in-class platforms operating on optimized infrastructure and UX report rates above 80%.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-28--2026--04_19_42-PM.png" class="kg-image" alt="Video KYC Success Rate Optimization Drop-off Guide" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Video KYC funnel</span></figcaption></img></figure><h2 id="video-kyc-funnel-breakdown">Video KYC funnel breakdown</h2><p>Understanding where users leave is the prerequisite to fixing why they leave. The V-CIP funnel has five distinct stages, each with its own failure modes.</p><h3 id="stage-1-entry-and-pre-session-check">Stage 1: Entry and pre-session check</h3><p>The user receives a link (via SMS, email, or in-app) and lands on the KYC start screen. Drop-off here is driven by:</p><ul><li>Confusion about what documents are needed</li><li>Device or browser incompatibility (camera/microphone permissions)</li><li>Users on low-end <a href="https://www.videosdk.live/blog/webrtc-android" rel="noreferrer">Android devices failing WebRTC capability checks</a></li><li>High friction in the consent and pre-check flow</li></ul><p>This stage typically accounts for 10–20% of total drop-off on poorly optimized platforms.</p><h3 id="stage-2-document-capture">Stage 2: Document capture</h3><p>Users must photograph or upload their Aadhaar, PAN, or other ID. Failure modes:</p><ul><li>Poor camera quality producing blurry captures</li><li>Lighting conditions causing OCR failure</li><li>Users unfamiliar with document orientation requirements</li><li>Retry loops that exhaust patience before a clean capture is accepted</li></ul><p>This stage is the single largest contributor to <strong>reduce KYC abandonment</strong> efforts on most platforms. Expect 15–25% drop-off here if document capture is not guided actively.</p><h3 id="stage-3-queue-wait">Stage 3: Queue wait</h3><p>After document upload, users wait for an available agent. This stage is almost entirely an infrastructure and capacity problem:</p><ul><li>Insufficient agent capacity during peak hours</li><li>Session timeouts while users wait</li><li>No visible queue position or estimated wait time</li><li>Users switching tabs or apps and missing the agent connect</li></ul><p>Queue-related abandonment is highly variable. near zero with adequate capacity, 20–30% on platforms that understaff peak hours.</p><h3 id="stage-4-agent-connect-and-live-verification">Stage 4: Agent connect and live verification</h3><p>The live session itself can fail due to:</p><ul><li>Video/audio quality degradation on poor network conditions</li><li>Session drops mid-verification</li><li>Agent protocol errors (incorrect liveness check procedure)</li><li>User non-compliance (wrong document presented, lighting issues)</li></ul><p>Infra-driven failures at this stage, <a href="https://www.videosdk.live/developer-hub/social/packet-loss" rel="noreferrer">packet loss</a>, jitter, connection drops, are addressable with the right real-time video infrastructure. <a href="https://videosdk.live">VideoSDK</a> and similar platforms are designed specifically for session reliability at scale, with adaptive bitrate and network fallback mechanisms that reduce mid-session drop-off.</p><h3 id="stage-5-verification-outcome-and-completion">Stage 5: Verification outcome and completion</h3><p>Some sessions complete the live interaction but fail at the verification decision stage:</p><ul><li>Liveness check not conclusively passed</li><li>Document OCR data mismatch</li><li>Geo-tag outside permitted geography</li><li>Incomplete audit trail due to recording failure</li></ul><p>These are compliance-layer failures. They do not always register as "drop-off" in UX analytics but do reduce effective success rate.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-28--2026--04_25_40-PM.png" class="kg-image" alt="Video KYC Success Rate Optimization Drop-off Guide" loading="lazy" width="1693" height="929"><figcaption><span style="white-space: pre-wrap;">Drop-off points across KYC stages</span></figcaption></img></figure><h2 id="core-optimization-framework">Core optimization framework</h2><h3 id="layer-1-stage-wise-drop-off-diagnosis">Layer 1: Stage-wise drop-off diagnosis</h3><p>Before optimizing anything, instrument the funnel. Define events at each stage transition and measure:</p><ul><li>Entry-to-document-start rate</li><li>Document-start-to-capture-success rate</li><li>Capture-to-queue-entry rate</li><li>Queue-entry-to-agent-connect rate</li><li>Agent-connect-to-session-complete rate</li><li>Session-complete-to-verified rate</li></ul><p>If you cannot isolate where users leave, you will misallocate optimization effort. Most platforms over-invest in UX polish at Stage 1 while ignoring infra failures at Stages 3–4.</p><h3 id="layer-2-ux-optimization">Layer 2: UX optimization</h3><p><strong>Pre-session guidance:</strong> Add a checklist screen before the session starts: required documents, lighting tips, supported browsers, and estimated session time. This single intervention reduces Stage 1 and Stage 2 abandonment.</p><p><strong>Guided document capture:</strong> Use real-time feedback overlays (frame alignment, brightness detection, blur detection) rather than static instructions. Allow retries with coaching, not just error messages.</p><p><strong>Queue transparency:</strong> Show users their position in queue or an estimated wait time. Offer a callback or scheduled-slot option for users who cannot wait. This is the highest-impact single UX change for <strong>V-CIP success rate improvement</strong> on high-volume platforms.</p><p><strong>Session recovery:</strong> If a session drops, allow seamless re-entry without restarting the full flow. Store session state so users resume at the last verified stage.</p><h3 id="layer-3-infrastructure-optimization">Layer 3: Infrastructure optimization</h3><p>Infrastructure failures are invisible in UX analytics but measurable in session logs. Target:</p><ul><li><a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer"><strong>Adaptive bitrate streaming</strong></a><strong>:</strong> Automatically adjusts video quality based on available bandwidth, preventing freezes that cause users to disconnect.</li><li><strong>Network quality detection:</strong> Alert users to poor connection before the session begins, not during it.</li><li><strong>Geographic routing:</strong> Route sessions to the nearest server to minimize latency, which directly affects video clarity during liveness checks.</li><li><strong>Session recording reliability:</strong> Ensure recordings are captured without gaps, which is both a compliance requirement and a retry-prevention measure.</li></ul><p>Real-time communication infrastructure built for scale, such as that offered by <a href="https://videosdk.live">VideoSDK</a> via its <a href="https://docs.videosdk.live/">developer documentation</a>, provides the WebRTC primitives that make adaptive quality and session reliability achievable without building from scratch.</p><h3 id="layer-4-compliance-constraints-layer">Layer 4 Compliance constraints layer</h3><p>Compliance is not optional, but it can be implemented more or less gracefully. Teams that treat compliance steps as blockers rather than design inputs generate unnecessary drop-off.</p><p>Specific optimizations:</p><ul><li><strong>Liveness check UX:</strong> Instruct users clearly on what the liveness check requires (blinking, head turn, spoken phrase). Ambiguous instructions increase failure rates.</li><li><strong>Geo-tag transparency:</strong> Inform users that location permission is required before they attempt to proceed. Denial mid-flow is a hard exit.</li><li><strong>Consent flow clarity:</strong> Keep the consent screen short and plain-language. Long legal text at this stage causes abandonment.</li></ul><h2 id="metrics-and-benchmarking">Metrics and benchmarking</h2>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Metric</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Definition</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Industry benchmark</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session completion rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Sessions completed / sessions initiated</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">55–75% (optimized: 80%+)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Average handling time (AHT)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mean duration of completed sessions</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">5–12 minutes</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session failure rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Sessions that drop mid-verification</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">8–20%</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Document capture retry rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Users requiring 2+ capture attempts</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">20–40%</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Queue abandonment rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Users who leave during wait</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">10–30% (capacity-dependent)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">First-attempt verification rate</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Sessions verified on first attempt</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">60–80%</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>All benchmarks are indicative. Actual figures vary by device mix, network geography, agent training quality, and infrastructure tier.</p><p><strong>The most reliable leading indicator of overall success rate is queue abandonment rate,</strong> it is the most volatile metric and the most directly controllable through capacity management.</p><h2 id="rbi-compliance-checklist">RBI compliance checklist</h2><p>The <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc" rel="noreferrer">RBI V-CIP guidelines</a> impose specific technical and procedural requirements. Non-compliance risks onboarding rejection, regulatory penalties, and audit exposure.</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Requirement</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Specification</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Optimization implication</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Live video session</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Real-time, two-way video — no pre-recorded sessions</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Infrastructure must support sub-200ms latency</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Geo-tagging</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Customer's location must be captured and verified</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Request location permission early in flow</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Liveness detection</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Must confirm live presence, not a photograph</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Explicit user instruction reduces failure rate</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Document verification</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">OCR and visual check of original document</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Guided capture reduces retry rate</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Audit trail</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Full session log including agent ID, timestamp, outcome</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Recording must not have gaps; log all events</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Recording storage</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Sessions must be stored per RBI retention requirements</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Reliable recording is an infra requirement</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Trained official</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session must be conducted by an RBI-compliant official</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Agent training directly affects AHT and quality</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Time-stamping</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Sessions must be time-stamped with a reliable clock</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Server-side timestamping preferred</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><strong>Consequences of non-compliance:</strong></p><ul><li>Individual onboarding rejections (immediate revenue loss)</li><li>Regulatory show-cause notices</li><li>Suspension of V-CIP authorization</li><li>Reputational risk with customers whose onboarding data is mishandled</li></ul><h2 id="common-mistakes">Common mistakes</h2><p><strong>1. Optimizing UX before instrumenting the funnel.</strong> Teams that redesign the document capture screen before measuring where users actually drop are guessing. Instrument first.</p><p><strong>2. Treating queue wait as fixed.</strong> Queue abandonment feels like a capacity problem that requires hiring more agents. Often, it is a scheduling problem, agents are available but not allocated to peak hours. Rescheduling before hiring is faster and cheaper.</p><p><strong>3. Ignoring device and browser compatibility.</strong> A significant share of Indian mobile users are on Android devices with older <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> implementations. Not testing across this device range means infrastructure failures show up as "user error" in support logs.</p><p><strong>4. Building compliance steps as afterthoughts.</strong> Consent, geo-tag, and liveness checks added late to a session flow create jarring UX transitions. Build them into the flow design from the start.</p><p><strong>5. Not offering session recovery.</strong> A dropped session that requires the user to restart from Step 1 will almost never be completed. Session state persistence is a high-ROI engineering investment.</p>
<!--kg-card-begin: html-->
<iframe width="560" height="315" src="https://www.youtube.com/embed/LtK-3iCBOeM?si=_XuxHiq2xY_3Ubg2" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<h2 id="key-takeaways">Key takeaways</h2><ul><li><strong>Video KYC drop-off reduction</strong> requires simultaneous action across UX, infrastructure, and compliance layers, no single layer fix is sufficient.</li><li>Queue abandonment is the most volatile and most fixable drop-off point; capacity and scheduling changes deliver fast results.</li><li>Guided document capture with real-time feedback is the highest-ROI UX intervention for most platforms.</li><li>Infrastructure reliability, adaptive bitrate, geographic routing, recording stability, is a compliance requirement, not a premium feature.</li><li>Instrument the funnel at every stage transition before prioritizing any optimization effort.</li></ul><h2 id="faq">FAQ</h2><p><strong>What is a good video KYC success rate?</strong> </p><p>Typical industry benchmarks for V-CIP completion range between 55–75%. Platforms with optimized UX, reliable infrastructure, and well-trained agents consistently achieve rates above 80%. Best-in-class operations report 85–90% in controlled conditions.</p><p><strong>What causes the most video KYC drop-off?</strong> </p><p>Document capture failure and queue wait time are the two largest contributors on most platforms. Document capture fails due to poor camera quality, lighting, and insufficient user guidance. Queue abandonment rises when agent capacity is mismatched to demand volume.</p><p><strong>Is video KYC mandatory for all banks and NBFCs in India?</strong> </p><p>V-CIP is not mandatory but is permitted as an alternative to in-person KYC under RBI guidelines. Entities that choose V-CIP must comply fully with the technical and procedural requirements set out by the <a href="https://www.rbi.org.in/">Reserve Bank of India</a>.</p><p><strong>How do I measure video KYC drop-off rate accurately?</strong> </p><p>Define session initiation as the start event (user lands on the KYC start screen) and session completion as the end event (verified outcome delivered). Measure conversion at each intermediate stage, document capture, queue entry, agent connect, and verification, to isolate where abandonment clusters.</p><p><strong>Can session drop-off caused by network issues be recovered?</strong> </p><p>Yes, with the right infrastructure. Real-time video platforms that support session state persistence and reconnection allow users to re-enter a dropped session without restarting. This requires both infra capability and application-layer session management.</p><p><strong>What RBI requirements most directly affect success rate?</strong> </p><p>Geo-tagging (requires user location permission), liveness detection (requires user compliance), and recording continuity (requires infra reliability) are the three compliance requirements that most directly create drop-off when implemented poorly.</p><p><strong>How long should a video KYC session take?</strong> </p><p>Well-run V-CIP sessions typically complete in 5–8 minutes. Sessions exceeding 12 minutes correlate with higher user abandonment and lower agent throughput. AHT reduction through agent training and document capture automation is a key lever.</p><p><strong>Does improving video quality directly improve success rate?</strong> </p><p>Yes, particularly for liveness checks and document verification. Poor video quality during liveness checks increases false-negative rates, requiring retries or session escalation. Infrastructure that supports adaptive bitrate ensures video quality degrades gracefully on poor networks rather than failing hard.</p>]]></content:encoded></item><item><title><![CDATA[Video KYC vs eKYC vs Physical KYC: 2026 Comparison]]></title><description><![CDATA[Compare video KYC, eKYC, and physical KYC across cost, RBI compliance, fraud resistance, and scalability to choose the right method for your business in 2026.]]></description><link>https://www.videosdk.live/video-kyc-ekyc-and-physical-kyc-comparison</link><guid isPermaLink="false">69ef467355831517a5a8a891</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 28 Apr 2026 09:43:29 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/04/9-1.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR:</strong> For most regulated fintech companies and NBFCs in India, <strong>video KYC</strong> delivers the best balance of compliance strength, fraud resistance, and remote scalability. <strong>eKYC</strong> suits fully digital, low-risk, Aadhaar-enabled onboarding flows. <strong>Physical KYC</strong> remains relevant only where digital infrastructure is absent or regulatory mandates specifically require in-person verification.</blockquote><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-text">Video KYC is a live, agent-assisted identity verification conducted over a video call with geo-tagging, document capture, and session recording, as defined under Reserve Bank of India (RBI) guidelines.<br>eKYC (electronic KYC) is an Aadhaar-based digital verification that uses biometric or OTP authentication through the UIDAI (Unique Identification Authority of India) system.<br>Physical KYC requires an agent or customer to be physically present for document collection and wet-ink verification. Each method carries distinct compliance obligations, infrastructure requirements, and fraud profiles.</br></br></div></div><h2 id="introduction-why-this-comparison-matters-for-indian-fintech-in-2026">Introduction: why this comparison matters for Indian fintech in 2026</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/9-1.png" alt="Video KYC vs eKYC vs Physical KYC: 2026 Comparison"/><p>Banks, non-banking financial companies (NBFCs), payment aggregators, and insurance providers in India are required to comply with the <a href="https://www.rbi.org.in/commonman/English/scripts/notification.aspx?id=2607" rel="noreferrer nofollow">RBI's Master Direction on Know Your Customer (KYC)</a>, last updated and progressively amended through 2023–2025. The choice of KYC method directly affects customer acquisition speed,  compliance risk, operational cost, and auditability.</p><p>As the RBI has expanded acceptance of video KYC for a wider class of regulated entities, and as the UIDAI continues to refine Aadhaar eKYC consent frameworks, teams evaluating onboarding infrastructure in 2026 face a genuinely different decision landscape than they did three years ago. This article provides a structured, criteria-driven comparison of all three methods to help compliance heads, product managers, and founders make that decision with precision.</p><blockquote>Read Here: <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc" rel="noreferrer">RBI KYC compliance guide</a></blockquote><h2 id="evaluation-criteria">Evaluation criteria</h2><p>Before comparing options, the following criteria are defined and will be applied consistently:</p><p><strong>Regulatory acceptance:</strong> Whether the method is explicitly permitted under RBI's Master Direction on KYC and applicable sector-specific guidelines for banks, NBFCs, and payment service providers.</p><p><strong>User experience:</strong> The friction a customer encounters during onboarding, including time-to-complete, device requirements, and steps needed.</p><p><strong>Fraud resistance:</strong> The method's resistance to identity spoofing, document forgery, and impersonation attacks.</p><p><strong>Cost per verification:</strong> Fully-loaded operational cost including agent time, infrastructure, storage, and compliance overhead per successfully completed verification.</p><p><strong>Scalability:</strong> The ability to handle volume growth without proportional increases in cost or staffing.</p><p><strong>Infrastructure complexity:</strong> The technical and organisational overhead required to deploy and maintain the solution.</p><p><strong>Auditability:</strong> The completeness and retrievability of records for regulatory inspection, grievance redressal, and audit purposes.</p><h2 id="video-kyc">Video KYC</h2><h3 id="what-it-is">What it is</h3><p><strong>Video KYC</strong> is a live, synchronous identity verification process conducted over a secure video call between a trained agent and a customer. Defined under the RBI's guidelines (circular ref: RBI/2019-20/145, with subsequent amendments), it requires a live video session, real-time capture of the customer's face and original documents, a randomised question set, geo-tagging of the customer's location, and mandatory session recording stored for a minimum of two years.</p><p>Customers must be physically present in India at the time of verification. The session must be conducted by an officially designated officer of the regulated entity, and the entire workflow must be <a href="https://www.videosdk.live/blog/what-is-end-to-end-encryption-e2ee" rel="noreferrer">end-to-end encrypted</a>.</p><h3 id="strengths">Strengths</h3><p>Video KYC combines the compliance strength of physical presence with the reach of a digital channel. Because a trained human agent verifies the session in real time, it resists many automated fraud attacks. The mandatory recording creates a defensible audit trail. It is accepted across banks, NBFCs, insurance companies, and mutual fund houses under their respective RBI and IRDAI frameworks.</p><p>Vendors such as VideoSDK provide <a href="https://www.videosdk.live/blog/introduction-to-real-time-communication-sdk" rel="noreferrer">real-time communication infrastructure</a> (WebRTC-based SDKs and APIs) that compliance teams can use to build or integrate video KYC pipelines. According to the <a href="https://docs.videosdk.live/" rel="noreferrer">VideoSDK documentation</a>, the platform supports features such as real-time video, recording, and custom UI relevant capabilities for building agent-facing and customer-facing KYC flows. Alternatives include in-house WebRTC implementations and CPaaS (Communications Platform as a Service) providers, each with different trade-offs in build time, compliance configurability, and per-minute cost.</p><h3 id="limitations">Limitations</h3><p>Video KYC requires a stable internet connection (minimum 512 kbps recommended) and a front-facing camera on the customer's device. It is agent-dependent, meaning throughput is constrained by the number of trained agents available. Session completion rates drop in areas with poor connectivity. For very high onboarding volumes, staffing costs can erode the per-verification economics compared to fully automated eKYC.</p><h3 id="ideal-use-cases">Ideal use cases</h3><p>Video KYC is the appropriate choice for: <a href="https://www.videosdk.live/solutions/video-banking" rel="noreferrer">opening full-KYC savings or current accounts</a>, onboarding for lending products with high credit limits, insurance policy issuance, and mutual fund onboarding where PAN-level identity confirmation is required. It is the mandated or preferred channel for regulated entities where Aadhaar-based eKYC is not available or where the customer has not provided Aadhaar consent.</p><blockquote>Must Read:  <a href="https://www.videosdk.live/blog/build-vs-buy-video-kyc-infrastructure" rel="noreferrer">Build vs buy video KYC infrastructure</a></blockquote><h2 id="ekyc">eKYC</h2><h3 id="what-it-is-1">What it is</h3><p><strong>eKYC (electronic KYC)</strong> is a paperless, Aadhaar-based identity verification process administered through the UIDAI API. It authenticates a customer's identity against their Aadhaar record using either biometric data (fingerprint or iris) or a one-time password (OTP) sent to the Aadhaar-linked mobile number. The customer's name, date of birth, address, photograph, and other demographic data are returned electronically from the UIDAI system after successful authentication.</p><p>eKYC is the basis of the "<a href="https://www.videosdk.live/blog/video-kyc-vs-traditional-kyc" rel="noreferrer">video KYC vs traditional KYC</a>" debate: it is faster and fully automated, but access to the UIDAI biometric API is restricted to licensed KYC User Agencies (KUAs), and OTP-based eKYC carries higher fraud exposure than biometric eKYC.</p><h3 id="strengths-1">Strengths</h3><p>eKYC is the fastest verification method available under Indian regulations. For customers with Aadhaar-linked mobile numbers and consent, the end-to-end process can complete in under two minutes. It requires no agent involvement, making it infinitely scalable in terms of software throughput. The data is sourced directly from UIDAI, eliminating document forgery risk at the data level. Costs per verification are low once the KUA licence and API infrastructure are in place.</p><h3 id="limitations-1">Limitations</h3><p>eKYC access is restricted to entities that hold a valid KUA licence from UIDAI or contract with a licensed sub-KUA. OTP-based eKYC is vulnerable to SIM swap fraud and social engineering. Biometric eKYC requires physical fingerprint or iris readers, which limits mobile-first use cases. Critically, the Supreme Court of India's 2018 ruling in <a href="https://indiankanoon.org/doc/127517806/" rel="noreferrer nofollow">Justice K.S. Puttaswamy vs Union of India</a> restricted private entities from mandatory Aadhaar-based authentication, meaning Aadhaar eKYC for private financial entities requires explicit, voluntary customer consent a compliance step that cannot be bypassed.</p><p>RBI's guidance on eKYC also imposes transaction limits on accounts opened solely through OTP-based eKYC (e.g., aggregate credit limits for small accounts), which constrains the product range that can be offered through this channel alone.</p><h3 id="ideal-use-cases-1">Ideal use cases</h3><p>eKYC is the right choice for: mobile wallet onboarding, small-ticket lending pre-qualification, payment instrument issuance below regulatory thresholds, and scenarios where customers have voluntarily consented to Aadhaar-based verification and hold an Aadhaar-linked mobile number. It is also used as a first-factor verification step in layered KYC processes, where video KYC or physical KYC is completed subsequently for higher-value products.</p><h2 id="physical-kyc">Physical KYC</h2><h3 id="what-it-is-2">What it is</h3><p><strong>Physical KYC</strong> is the original, in-person verification process in which a customer either visits a branch or outlet, or a field agent visits the customer's location, to collect original identification documents, take a photograph, and obtain a wet-ink signature. The verified documents are then stored as part of the customer's KYC record. Physical KYC was the only accepted method before the RBI introduced digital alternatives.</p><h3 id="strengths-2">Strengths</h3><p>Physical KYC requires no internet connectivity on the customer's part and is unambiguously accepted across all product types and all regulated entity categories. It is the fallback method for customers who cannot complete digital verification due to device limitations, connectivity constraints, or lack of Aadhaar consent. It is also the default channel for rural and semi-urban segments where digital literacy remains low.</p><h3 id="limitations-2">Limitations</h3><p>Physical KYC is operationally expensive. The cost per verification includes field agent salaries, travel, document handling, storage, and data entry. Turnaround times range from one to five business days in most deployment models, which directly delays customer activation. Document handling introduces risks of loss, damage, and data entry errors. Scaling physical KYC requires proportional headcount growth, making it incompatible with high-growth digital onboarding strategies.</p><h3 id="ideal-use-cases-2">Ideal use cases</h3><p>Physical KYC remains appropriate for: rural lending programmes where customers lack smartphones or reliable internet, government scheme enrolments requiring in-person verification, customers who explicitly decline digital channels, and product lines where regulatory guidance has not yet extended to digital alternatives.</p><h2 id="feature-comparison-matrix">Feature comparison matrix</h2>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Criteria</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Video KYC</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">eKYC</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Physical KYC</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Regulatory acceptance (RBI)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Fully accepted for banks, NBFCs, insurers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Accepted with Aadhaar consent; transaction limits apply</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Universally accepted; no digital infrastructure required</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">User experience</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Moderate friction; requires device with camera and connectivity</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Lowest friction; 2–3 minutes, mobile-first</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Highest friction; requires travel or field agent visit</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Fraud resistance</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High; live agent, geo-tagging, recording</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium (OTP) to High (biometric); vulnerable to SIM swap on OTP</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium; risk of document forgery and agent collusion</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Cost per verification</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium (₹100–₹300 depending on agent model and vendor)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low (₹10–₹50 once API access established)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High (₹300–₹800 including agent and logistics costs)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Scalability</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium; agent-dependent; addressable via shift scheduling</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Very high; fully automated once licensed</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low; linear headcount dependency</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Infrastructure complexity</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium; requires compliant WebRTC video stack, recording, storage</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium–High; requires UIDAI KUA licence or sub-KUA tie-up</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low (tech); High (operations)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Auditability</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Highest; full video recording, geo-tag, timestamped logs</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High; UIDAI-sourced record, consent log</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium; depends on document storage and field agent process</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><em>Cost estimates are indicative and vary by vendor, volume, and operational model.</em></p><h2 id="recommendation-by-use-case">Recommendation by use case</h2>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Use case</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Best method</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Reason</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Full-KYC savings account opening</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Video KYC</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">RBI mandates full KYC for savings accounts; video KYC meets this remotely</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mobile wallet (semi-KYC)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">eKYC (OTP)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Transaction limits align with semi-KYC product caps; fast and scalable</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">NBFC personal loan onboarding</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Video KYC</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Lending products require complete identity verification; video creates defensible audit trail</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Insurance policy issuance</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Video KYC</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">IRDAI has aligned with RBI's video KYC framework for insurance</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mutual fund account (MF-KYC)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">eKYC or Video KYC</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Both accepted under SEBI's KYC Registration Agency framework; eKYC faster for existing Aadhaar-consenting customers</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Rural lending (no smartphone)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Physical KYC</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">No viable digital alternative for customers without devices or connectivity</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High-value lending (&gt;₹50 lakh)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Video KYC</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Risk profile warrants agent-verified, recorded session</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Pre-qualification / lead enrichment</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">eKYC (OTP)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low-stakes data capture step; full KYC completed later</td></tr></tbody></table>
<!--kg-card-end: html-->
<h2 id="rbi-compliance-analysis">RBI compliance analysis</h2><h3 id="regulatory-framework">Regulatory framework</h3><p>The Reserve Bank of India's <strong>Master Direction on Know Your Customer</strong> (updated through 2023) is the primary regulatory instrument governing KYC obligations for regulated entities. It is available on the <a href="https://rbi.org.in/" rel="noreferrer">RBI's official website</a>. Sector-specific entities insurance companies, mutual funds, stockbrokers are also governed by IRDAI, SEBI, and AMFI guidelines respectively, which broadly align with the RBI's framework.</p><p>The RBI extended video KYC (termed "V-CIP" or <a href="https://www.videosdk.live/blog/video-based-identification-procedure-vbip" rel="noreferrer">Video-based Customer Identification Process</a>) to scheduled commercial banks, small finance banks, payment banks, NBFCs, and housing finance companies in a phased rollout beginning 2020. The core V-CIP requirements are:</p><ul><li>Live video interaction between a trained agent and the customer</li><li>Real-time capture of the customer's face and official identification documents</li><li>Verification against PAN database (for PAN-based products)</li><li>Randomised question asked during the session</li><li>Geo-tagging to confirm the customer is physically located in India</li><li>End-to-end encryption of the session</li><li>Recording stored for a minimum of two years</li><li>Customer consent obtained prior to the session</li></ul><p>eKYC under the Aadhaar framework requires entities to be licensed KUAs or to operate through sub-KUAs. The customer's Aadhaar number must never be stored locally by the regulated entity without explicit compliance clearance.</p><p><em>Refer to the official RBI Master Direction on KYC or consult a qualified compliance expert before finalising your KYC architecture.</em></p><h3 id="compliance-checklist">Compliance checklist</h3>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Requirement</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Video KYC</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">eKYC</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Physical KYC</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Customer consent (documented)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory obtained prior to V-CIP session</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory Aadhaar consent form required</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory general account opening consent</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Agent/officer verification</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Yes designated officer with identity verified</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Not applicable (automated)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Yes field agent identity registered</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session/document recording</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Yes full video recording required</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">UIDAI transaction log maintained</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Physical document copy retained</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Geo-tagging</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory customer must be in India</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Not required</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Not applicable</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Audit logs</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session metadata, timestamps, agent ID</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">UIDAI authentication log, consent record</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Physical file, data entry log</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Data storage minimum</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">2 years (video recording)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">As per UIDAI and entity policy</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">5 years post-account closure (RBI norm)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">PAN verification</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Required for applicable products</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Required for applicable products</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Required for applicable products</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Liveness check</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Required during live session</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Biometric eKYC includes liveness; OTP eKYC does not</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Not applicable</td></tr></tbody></table>
<!--kg-card-end: html-->
<h3 id="consequences-of-non-compliance">Consequences of non-compliance</h3><p>Regulated entities that fail to comply with RBI KYC directions face a defined set of consequences under the Banking Regulation Act, 1949, and the Prevention of Money Laundering Act (PMLA), 2002:</p><p><strong>Financial penalties:</strong> The RBI has imposed fines ranging from ₹50 lakh to several crore rupees on banks and NBFCs for KYC and AML (Anti-Money Laundering) violations. Recent enforcement actions (2022–2025) have included penalties specifically for inadequate record retention and deficient V-CIP implementation.</p><p><strong>Licence restrictions:</strong> Entities found in persistent non-compliance may face restrictions on onboarding new customers, launching new products, or operating specific business lines. In extreme cases, the RBI has the authority to cancel licences.</p><p><strong>Operational disruption:</strong> Regulatory audits that identify systemic KYC gaps can require immediate remediation, halting or slowing new account opening until deficiencies are corrected.</p><p><strong>Customer onboarding delays:</strong> Poor KYC infrastructure regardless of which method is used creates bottlenecks that delay customer activation, increase drop-off rates, and generate downstream compliance exposure if accounts are activated on incomplete records.</p><h2 id="final-verdict">Final verdict</h2><p>For most regulated entities in India operating in 2026, <strong>video KYC is the default recommendation</strong> for any product requiring full KYC compliance. It provides the strongest combination of regulatory acceptance, auditability, and fraud resistance while remaining accessible to customers with standard smartphones and broadband connectivity.</p><p><strong>eKYC is the right choice</strong> where the specific use case falls within the product and transaction limits applicable to Aadhaar-based verification, customers have consented to Aadhaar use, and the entity holds or can access a KUA licence. It is best deployed as a component of a layered onboarding flow rather than as a standalone method for high-value products.</p><p><strong>Physical KYC should be reserved</strong> for specific segments geographically remote customers, those without digital devices, or products where regulators have not yet extended digital verification options and treated as a legacy channel being actively managed down in volume.</p><p>Entities choosing video KYC should evaluate their infrastructure options carefully: in-house WebRTC, CPaaS platforms, and&nbsp;<a href="https://www.videosdk.live/blog/video-sdk-prebuilt" rel="noreferrer">prebuilt SDK</a>&nbsp;vendors each carry different compliance configurability, SLA commitments, and cost structures. Infrastructure must support recording, geo-tagging, and encryption as non-negotiable baseline capabilities not optional add-ons.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li>Video KYC is the only method that simultaneously delivers full regulatory compliance, remote reach, and a defensible audit record for high-value financial products.</li><li>eKYC is fastest and most scalable but is restricted by Aadhaar consent requirements, KUA licensing, and product-level transaction caps.</li><li>Physical KYC is operationally expensive and unscalable; its use should be limited to segments and geographies where digital alternatives are genuinely unavailable.</li><li>RBI's V-CIP framework imposes specific technical and procedural mandates geo-tagging, recording, agent verification, encryption that must be treated as hard requirements, not best-practice guidance.</li><li>Choosing the wrong KYC method for a product type is not a minor operational issue; it is a compliance gap that can attract RBI penalties, trigger licence restrictions, and delay customer onboarding.</li></ul><h2 id="faq">FAQ</h2><p><strong>What is the difference between video KYC and eKYC in India?</strong> </p><p>Video KYC (V-CIP) is a live, agent-assisted video session used to verify a customer's identity in real time, as defined under the RBI's Master Direction on KYC. eKYC is an Aadhaar-based digital process that authenticates identity against UIDAI records using either OTP or biometrics, without any agent involvement. The key practical distinctions are that video KYC requires a trained agent and produces a video recording, while eKYC is fully automated and relies on Aadhaar infrastructure.</p><p><strong>Is video KYC mandatory under RBI guidelines for NBFCs?</strong> </p><p>Video KYC is not universally mandatory, but it is the RBI-accepted method for completing full KYC remotely for NBFCs. NBFCs that want to onboard customers digitally without physical agents must use V-CIP as defined in the Master Direction. Refer to the current RBI Master Direction on KYC or consult a compliance expert to confirm obligations specific to your entity category and product type.</p><p><strong>Can an NBFC use eKYC for all customer onboarding?</strong> </p><p>No. eKYC through Aadhaar OTP has transaction and product-level limitations under RBI guidelines accounts opened via OTP-based eKYC are classified as limited-purpose accounts with aggregate credit constraints. Biometric eKYC offers stronger verification but requires physical authentication hardware. Full-KYC accounts and higher-value lending products require either video KYC or physical KYC.</p><p><strong>What are the storage requirements for video KYC recordings?</strong> </p><p>The RBI's V-CIP guidelines require that video recordings from KYC sessions be stored for a minimum of two years from the date of the session. The recordings must be retrievable for regulatory inspection and must be maintained on secure, encrypted infrastructure. Entities should consult the current text of the RBI Master Direction for any subsequent amendments to this requirement.</p><p><strong>How does Aadhaar eKYC differ from video KYC for KYC compliance in India?</strong> </p><p>Aadhaar eKYC draws identity data directly from the UIDAI database after customer biometric or OTP authentication, making it data-accurate but access-restricted and subject to Aadhaar consent law. Video KYC relies on a trained human agent verifying documents and liveness in real time, with no dependency on Aadhaar or UIDAI. From a compliance standpoint, both are accepted by the RBI, but they apply to different product categories and carry different fraud profiles and infrastructure requirements.</p><p><strong>What happens if a video KYC session fails due to connectivity issues?</strong> </p><p>A failed or incomplete V-CIP session must not be treated as a completed KYC event. The customer must be re-scheduled for a fresh session, and no account or product must be activated on an incomplete session record. Entities should ensure their video KYC infrastructure logs session outcomes including failures with timestamps and reasons, as this forms part of the audit trail. A high rate of session failures is also an operational signal to evaluate infrastructure quality or shift scheduling.</p><p><strong>Which KYC method is most cost-effective for digital KYC in India at scale?</strong> </p><p>At high volumes, OTP-based eKYC has the lowest per-verification cost typically ₹10–₹50 per verification once API infrastructure is in place because it requires no agents. Video KYC costs more per session due to agent time, but the auditability and compliance coverage it provides often reduces downstream remediation costs. Physical KYC has the highest per-verification cost at scale, with no meaningful cost reduction at volume because it is operationally labour-intensive. The best cost structure depends on product type, customer segment, and the regulatory channel available.</p><p><strong>Is physical KYC still required for any financial products in India in 2026?</strong> </p><p>Physical KYC remains the applicable method for customer segments who cannot complete digital verification those without smartphones, reliable connectivity, or Aadhaar consent and for specific product types or geographies where the RBI has not extended digital alternatives. It also serves as the fallback when digital systems are unavailable. However, for mainstream digital onboarding by banks and NBFCs, physical KYC has been largely superseded by video KYC and, where applicable, eKYC.</p>]]></content:encoded></item><item><title><![CDATA[SEBI Video KYC Compliance Guide for Stockbrokers]]></title><description><![CDATA[Complete SEBI video KYC stockbrokers compliance guide covering IPV, CKYC, audit requirements, onboarding flow, and infrastructure decisions for broking platforms.]]></description><link>https://www.videosdk.live/blog/sebi-video-kyc-compliance-guide-for-stockbrokers</link><guid isPermaLink="false">69ef3cc655831517a5a8a85f</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 28 Apr 2026 09:21:26 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/04/7.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR</strong>: SEBI-regulated stockbrokers must complete <strong>In-Person Verification (IPV)</strong> for every new account. Video-based IPV has become the dominant compliant method, but it is not identical to "Video KYC" as used in banking contexts. This guide explains the regulatory framework, the operational distinction between Video KYC and IPV, end-to-end onboarding architecture, audit requirements, and build-versus-buy decisions, written for compliance officers, CTOs, and product leads at Indian broking platforms.</blockquote><div class="kg-card kg-callout-card kg-callout-card-blue"><div class="kg-callout-text">SEBI video KYC stockbrokers compliance requires conducting a live video-based In-Person Verification (IPV) session as part of account onboarding, cross-referencing the investor's identity against PAN, Aadhaar, and CKYC/KRA records, and storing a tamper-proof recording with metadata for audit access. The process is governed by SEBI KYC norms, KRA regulations, and PMLA obligations, not by the RBI's Video-based Customer Identification Process (V-CIP) framework, which applies to banks and NBFCs.</div></div><h2 id="introduction"><strong>Introduction</strong></h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/7.png" alt="SEBI Video KYC Compliance Guide for Stockbrokers"/><p>Regulatory scrutiny of investor onboarding in India has intensified since SEBI's mandate for uniform KYC standards across the securities ecosystem. For stockbrokers, the stakes are high: a failed audit, KRA rejection, or SEBI inspection finding can result in account suspensions, penalties, and reputational damage that takes years to repair.</p><p>Yet many compliance and product teams conflate two separate regulatory constructs, Video KYC and video-based IPV, and build systems that satisfy neither fully. This guide resolves that ambiguity and maps the path to a SEBI video KYC stockbrokers compliance architecture that survives regulatory scrutiny.</p><p>Whether you are building a new digital broking platform or retrofitting video verification into a legacy onboarding flow, the frameworks and checklists in this guide apply directly.</p><h2 id="sebi-regulatory-background"><strong>SEBI regulatory background</strong></h2><h3 id="what-governs-kyc-for-stockbrokers"><strong>What governs KYC for stockbrokers?</strong></h3><p>The <strong>Securities and Exchange Board of India (SEBI)</strong> is the statutory regulator for securities markets in India. SEBI's KYC requirements for brokers derive from several overlapping instruments:</p><p><strong>SEBI KYC Registration Agency (KRA) Regulations, 2011</strong> established a centralised KYC infrastructure for the securities market. Under this framework, <strong>KYC Registration Agencies (KRAs)</strong>: KRAs are SEBI-registered entities that store and validate KYC records submitted by market intermediaries. The five recognised KRAs are CAMS KRA, CVL KRA, NDML KRA, DOTEX KRA, and Karvy KRA.</p><p><a href="https://www.ckycindia.in/ckyc/index.php" rel="nofollow noreferrer"><strong>Central KYC (CKYC)</strong></a>: CKYC is a centralised repository of KYC records managed by the Central Registry of Securitisation Asset Reconstruction and Security Interest of India (CERSAI). A 14-digit CKYC identifier is issued to investors who have completed KYC through any regulated financial institution. Stockbrokers can perform a CKYC lookup to retrieve existing KYC data and reduce re-verification burden.</p><p><strong>In-Person Verification (IPV)</strong>: IPV is the process by which a SEBI-registered intermediary, or an authorised representative, physically verifies the original documents of a KYC applicant. SEBI has permitted video-based IPV as a substitute for physical IPV under specific conditions. This is the central mechanism governing what most broking platforms implement as "Video KYC."</p><p><a href="https://www.indiacode.nic.in/bitstream/123456789/15402/1/moneylaunderingact2002.pdf" rel="noreferrer nofollow"><strong>Prevention of Money Laundering Act (PMLA), 2002</strong></a> applies to all market intermediaries. Stockbrokers are classified as reporting entities under PMLA and must comply with its Customer Due Diligence (CDD) and record-keeping obligations in conjunction with SEBI's KYC norms.</p><p>Note: SEBI issues periodic circulars updating KYC norms and IPV requirements. Specific circular references should be verified with your compliance counsel against the latest SEBI Master Circular on KYC norms for securities markets, as these are updated regularly. Do not rely solely on this article for circular-level compliance.</p><h2 id="video-kyc-vs-ipv-the-critical-distinction"><strong>Video KYC vs IPV the critical distinction</strong></h2><p>This is the most consequential conceptual error in broking platform compliance. The terms are used interchangeably in casual discourse but refer to different regulatory constructs with different legal bases.</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Aspect</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Video KYC (RBI V-CIP)</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Video-based IPV (SEBI framework)</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Regulatory basis</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">RBI Master Direction on KYC, 2016 (as amended)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SEBI KYC circulars, KRA regulations</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Applicable entities</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Banks, NBFCs, Payment System Providers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SEBI-registered intermediaries including stockbrokers, mutual fund distributors</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Legal equivalence</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Equivalent to full KYC; replaces branch visit entirely</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Equivalent to physical IPV; still requires upstream KYC/CKYC records</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Document requirement</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Live capture of PAN + Aadhaar OTP + face match</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Live verification of original KYC documents on screen; face match to PAN/Aadhaar photo</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Agent requirement</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Trained bank/NBFC officer</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Authorised person of the intermediary (SEBI-registered)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Risk level if misconfigured</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">KYC invalidated by RBI; account freezing</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">IPV deemed incomplete; KRA rejection; SEBI enforcement</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Geo/time metadata</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Recording storage</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory, minimum 5 years</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory, aligned with PMLA retention norms</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><strong>The critical point for stockbrokers</strong>: You are operating under the SEBI framework, not RBI's V-CIP. Your video session constitutes video-based IPV. The KYC record itself must already exist or be created in parallel through CKYC/KRA. The video session validates the person against that record it does not replace the record.</p><h2 id="how-sebi-compliant-onboarding-works"><strong>How SEBI-compliant onboarding works</strong></h2><h3 id="end-to-end-onboarding-flow"><strong>End-to-end onboarding flow</strong></h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-27--2026--04_20_14-PM.png" class="kg-image" alt="SEBI Video KYC Compliance Guide for Stockbrokers" loading="lazy" width="1448" height="1086"><figcaption><span style="white-space: pre-wrap;">SEBI-compliant onboarding flow </span></figcaption></img></figure><p>The onboarding flow for a SEBI-compliant digital broking platform operates in six sequential stages:</p><p><strong>Stage 1: Authentication and PAN capture</strong> The investor logs in via mobile OTP. PAN is captured and validated against the Income Tax PAN database via NSDL or UTI APIs. An invalid or mismatched PAN halts onboarding immediately.</p><p><strong>Stage 2: CKYC/KRA lookup</strong> Using the validated PAN, the system performs a CKYC lookup through the CERSAI API. If a CKYC identifier exists, stored KYC data (name, date of birth, address, photo) is fetched and pre-populated. A KRA lookup may be performed simultaneously to check for an existing KRA-validated record.</p><p><strong>Stage 3: Aadhaar-based eKYC (where applicable)</strong> If no CKYC record exists, or if additional validation is required, Aadhaar OTP-based eKYC may be performed via UIDAI's authentication APIs or through DigiLocker. Note that Aadhaar use for KYC purposes must comply with the Aadhaar (Targeted Delivery of Financial and Other Subsidies, Benefits and Services) Act and <a href="https://uidai.gov.in/en/about-uidai/legal-framework/regulations.html" rel="noreferrer">UIDAI regulations</a>, including restrictions on storing Aadhaar numbers. This step adds identity data but still requires IPV.</p><p><strong>Stage 4: Video IPV session</strong> This is the compliance core of the process. A live, real-time video session is initiated between the investor and an authorised person of the stockbroker. The investor must:</p><ul><li>Be visible on screen throughout the session</li><li>Hold up original KYC documents (PAN card, address proof) for camera capture</li><li>Read a randomly generated code displayed on screen (<a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">liveness check</a>)</li><li>Confirm personal details verbally or via screen interaction</li></ul><p>The authorised person must verify the documents on screen and confirm face-match to the stored photo. The session is recorded end-to-end.</p><p><strong>Stage 5: Compliance review and KRA upload</strong> Completed sessions enter a compliance review queue. The compliance officer or an AI-assisted pre-screening tool reviews flagged sessions. On approval, the KYC record is submitted to the designated KRA. The KRA assigns a KYC reference number, which is linked to the investor's account.</p><p><strong>Stage 6: Trading account activation</strong> Only after KRA confirmation is the trading account activated. Activation without completed KRA submission is a compliance violation.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-27--2026--04_32_18-PM.png" class="kg-image" alt="SEBI Video KYC Compliance Guide for Stockbrokers" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Decision flow for SEBI-compliant digital onboarding</span></figcaption></img></figure><h2 id="architecture-and-infrastructure-for-video-ipv"><strong>Architecture and infrastructure for video IPV</strong></h2><h3 id="real-time-video-layer"><strong>Real-time video layer</strong></h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-27--2026--04_37_51-PM.png" class="kg-image" alt="SEBI Video KYC Compliance Guide for Stockbrokers" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Video KYC system architecture</span></figcaption></img></figure><p><strong>WebRTC</strong>: <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC (Web Real-Time Communication)</a> is an open standard and browser-native protocol that enables peer-to-peer audio, video, and data transmission without plugins. It is the foundational transport layer for real-time video IPV sessions in broking platforms.</p><p>A production-grade video IPV infrastructure must address:</p><p><strong>Session reliability</strong> Video sessions must handle variable network conditions across Tier 2 and Tier 3 Indian cities, where investors may be onboarding on 4G connections with fluctuating bandwidth. <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">Adaptive bitrate encoding</a>, fallback to lower resolutions, and automatic reconnection on network drop are baseline requirements not optional enhancements.</p><p><strong>Liveness verification</strong> SEBI-aligned IPV requires that the session be provably live. Technical implementations include: randomised OTP codes displayed on screen for the investor to read aloud, blink detection, or head-movement prompts. Static image replay attacks must be detectable.</p><p><strong>Concurrent session scaling</strong> A growing broking platform may run hundreds of simultaneous IPV sessions during peak hours market open, salary credit days, or promotional campaigns. The video infrastructure must scale horizontally without degrading session quality or recording completeness. Agent allocation systems must match session queues to available authorised persons in real time.</p><p><strong>Recording pipeline</strong> Every video IPV session must be recorded end-to-end. The recording pipeline must:</p><ul><li>Capture both the investor stream and the agent stream</li><li>Store in a tamper-evident format (checksum or hash on file write)</li><li>Attach session metadata at the point of creation, not post-processing</li><li>Confirm successful recording before the session is marked complete</li></ul><p>Failure to record whether due to a server crash, network interruption, or pipeline bug invalidates the IPV session. The system must detect recording failures in real time and require session restart.</p><p><strong>Latency expectations</strong> End-to-end latency for real-time IPV sessions should stay below 200ms for a conversational experience. Latency above 400ms introduces agent-investor dialogue friction that can increase session abandonment and incomplete verifications.</p><p><strong>Failure recovery</strong> The session state investor ID, documents captured, agent actions taken must be persisted independently of the video stream. If a session drops mid-flow, the investor should be able to resume from a defined recovery point rather than restart entirely. Full restart requirements increase abandonment rates substantially.</p><p>VideoSDK provides <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">real-time video APIs</a>, session handling, and recording capabilities that can serve as the real-time infrastructure layer for video IPV systems. When evaluating infrastructure options, verify that the provider's recording and session reliability documentation matches your compliance storage and audit requirements. </p><h3 id="agent-dashboard-requirements"><strong>Agent dashboard requirements</strong></h3><p>The authorised person conducting IPV needs a purpose-built dashboard that:</p><ul><li>Displays the live investor video feed and the document capture feed simultaneously</li><li>Provides a structured checklist of verification steps (face match, document check, liveness code confirmation)</li><li>Logs each agent action with a timestamp</li><li>Allows the agent to flag sessions for compliance review without approving them</li><li>Restricts agent access to sessions based on their authorisation scope</li></ul><h2 id="audit-and-record-keeping-requirements"><strong>Audit and record-keeping requirements</strong></h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-27--2026--04_40_29-PM.png" class="kg-image" alt="SEBI Video KYC Compliance Guide for Stockbrokers" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Audit trail flow for SEBI Compliant Video KYC</span></figcaption></img></figure><p><strong>Session recording requirements</strong> Every video IPV session must be recorded in full. Recordings must capture both the investor and agent streams. Partial recordings where only one stream is captured, or where recording began after session start are non-compliant.</p><p><strong>Storage duration</strong> PMLA regulations require records to be maintained for a minimum of five years from the date of cessation of the business relationship, or from the date of the transaction, whichever is later. For ongoing account relationships, this effectively means records must be accessible throughout the account's active life plus five years. Internal legal counsel should define the precise retention schedule applicable to your entity.</p><p><strong>Tamper-proof logs</strong> Recordings must be stored using <a href="https://www.videosdk.live/blog/high-grade-client-to-server-encryption" rel="noreferrer">high-grade encryption</a> and in a tamper-evident manner. At minimum, a cryptographic hash (SHA-256 or equivalent) of the recording file must be generated at the time of write and stored separately. Any post-storage modification of the recording file will produce a hash mismatch detectable during audit.</p><p><strong>Geo-tagging and timestamping</strong> Each session record must include:</p><ul><li>The investor's device geo-coordinates at session initiation (where available and consented to)</li><li>UTC timestamps for session start, each document capture event, agent action, and session end</li><li>The IP address of both the investor's device and the agent's workstation</li><li>The unique session identifier linking the recording to the KYC record</li></ul><p><strong>Audit access</strong> Audit retrieval must be role-based. Only designated compliance officers and authorised SEBI/KRA auditors should be able to retrieve session recordings. Every retrieval must itself be logged who accessed, when, and for which session to create a complete chain of custody.</p><h2 id="build-vs-buy-vs-hybrid-decision-framework-for-video-ipv"><strong>Build vs buy vs hybrid decision framework for video IPV</strong></h2>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Factor</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Build</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Buy</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Hybrid</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Time to compliance</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">6–18 months</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">4–12 weeks</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">8–20 weeks</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Upfront cost</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High (infra + engineering)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low to medium (SaaS)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Ongoing cost</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Infra + maintenance</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Per-session or subscription</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mixed</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Customisation</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Full</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Limited to provider config</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Partial</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Regulatory audit ownership</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Fully yours</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Shared with provider</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Shared for infra, yours for compliance layer</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Scaling complexity</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Managed by provider</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Depends on split</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Recording ownership</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Full control</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Varies by provider contract</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Must verify contractually</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Recommended for</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Large platforms with 100k+ monthly onboardings and dedicated infra teams</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Early-stage and mid-size brokers prioritising speed</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Brokers with existing onboarding systems needing a real-time video layer</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><strong>Recommendation</strong>: Most mid-size brokers should adopt a hybrid model using a real-time video infrastructure provider for the WebRTC layer, session handling, and recording pipeline, while owning the compliance logic, agent dashboard, KRA integration, and audit storage internally. This separates the infrastructure scaling problem from the compliance ownership problem.</p><h2 id="sebi-video-kyc-compliance-checklist"><strong>SEBI video KYC compliance checklist</strong></h2>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Requirement</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Description</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Applies to</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Risk if ignored</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">PAN validation before video session</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">PAN must be validated against NSDL/UTI before IPV initiation</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All brokers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Invalid KYC; KRA rejection</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">CKYC lookup</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Check CERSAI for existing CKYC record using validated PAN</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All brokers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Duplicate KYC; PMLA audit finding</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Live video session with authorised person</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session must be with a SEBI-registered intermediary's authorised employee, not a third party</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All brokers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">IPV invalidated</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Liveness verification</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Randomised on-screen code or equivalent technical liveness check</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All brokers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session replay attacks; IPV deemed incomplete</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Original document display on camera</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">PAN card + address proof shown on live feed; not uploaded scan</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All brokers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Non-compliant IPV</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Agent face-match confirmation</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Agent must confirm investor face matches CKYC/PAN photo</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All brokers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Identity verification failure</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">End-to-end session recording</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Both streams recorded from session start to end</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All brokers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">PMLA audit failure; SEBI penalty</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Tamper-proof storage</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Recording stored with cryptographic hash; hash stored separately</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All brokers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Evidence integrity challenged in enforcement</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Geo-tag and timestamp metadata</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Investor device geo-coordinates + UTC timestamps for all events</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All brokers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Audit record incomplete</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">KRA upload before account activation</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">KYC record submitted to designated KRA; reference number received before activation</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All brokers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Account opened without valid KYC; SEBI enforcement</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Minimum 5-year record retention</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Recordings and metadata accessible for PMLA-mandated duration</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All brokers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">PMLA violation</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Role-based audit access with access logging</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Only authorised roles can retrieve recordings; all retrievals logged</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All brokers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Chain of custody broken</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Aadhaar eKYC compliance</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">If Aadhaar authentication used, comply with UIDAI API terms and data restrictions</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Brokers using Aadhaar</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">UIDAI violation; PMLA finding</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Agent session capacity management</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Authorised persons not overloaded beyond verifiable throughput</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All brokers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session quality degradation; incomplete verifications</td></tr></tbody></table>
<!--kg-card-end: html-->
<h2 id="common-compliance-mistakes-in-video-ipv-implementation"><strong>Common compliance mistakes in video IPV implementation</strong></h2><p><strong>Mistake 1: Using a third-party vendor's staff as the IPV agent</strong> SEBI's IPV requirements specify that verification must be conducted by an authorised person of the intermediary meaning an employee or authorised representative of your SEBI-registered entity. Outsourcing the IPV agent role to a technology vendor's staff without ensuring they are formally authorised under your intermediary registration is a compliance gap that will surface in a KRA audit.</p><p><strong>Mistake 2: Activating accounts before KRA confirmation</strong> Some platforms activate trading accounts upon compliance officer approval of the video session, before the KRA submission is processed and a reference number is returned. This creates a window sometimes 24–48 hours during which the investor can trade without a valid KRA-acknowledged KYC record. SEBI has issued observations on this gap in prior inspection reports.</p><p><strong>Mistake 3: Recording pipeline treated as a secondary system</strong> When the recording pipeline fails due to server load, network error, or software bug some platforms continue the session and mark it complete, intending to retroactively recover what was captured. A session without a confirmed end-to-end recording is not a complete IPV. Systems must detect recording failure in real time and halt session completion.</p><p><strong>Mistake 4: Storing only the video recording, not the metadata</strong> A recording without associated metadata session ID, investor PAN, agent ID, timestamps, geo-coordinates, recording hash is effectively unauditable. Metadata must be written at session time, not reconstructed from logs later. Reconstruction introduces inconsistency risk that undermines the audit trail.</p><p><strong>Mistake 5: Conflating SEBI IPV with RBI Video KYC (V-CIP)</strong> Platforms that build their system based on RBI's V-CIP framework intended for banks may use incorrect document verification steps, agent qualification criteria, or storage formats. The regulatory basis is different. If your platform also offers banking-adjacent products through a partner, the compliance teams must maintain clear separation between the two regimes.</p><h2 id="key-takeaways"><strong>Key takeaways</strong></h2><ul><li>SEBI video KYC for stockbrokers is legally video-based IPV it must be conducted by the intermediary's authorised person and does not replace the underlying CKYC/KRA record; it validates the investor against it.</li><li>The CKYC lookup must occur before or during the video session, not after activating accounts before KRA confirmation is a documented SEBI enforcement risk.</li><li>Recording infrastructure must confirm successful capture before the session is marked complete a partial or failed recording invalidates the IPV.</li><li>PMLA requires a minimum five-year record retention; metadata (geo-coordinates, timestamps, agent actions, recording hash) is as legally significant as the recording itself.</li><li>Most mid-size brokers achieve fastest time-to-compliance through a hybrid model: third-party video infrastructure for the real-time layer, internal ownership for compliance logic, KRA integration, and audit storage.</li></ul><h2 id="faq"><strong>FAQ</strong></h2><p><strong>What is the difference between SEBI video KYC and RBI Video KYC?</strong> </p><p>SEBI video KYC (video-based IPV) applies to SEBI-registered intermediaries such as stockbrokers and mutual fund distributors. RBI Video KYC, formally called Video-based Customer Identification Process (V-CIP), applies to banks and NBFCs regulated by the Reserve Bank of India. The agent qualification standards, document requirements, regulatory circulars, and storage obligations differ between the two frameworks. Stockbrokers must follow SEBI's IPV framework, not RBI's V-CIP.</p><p><strong>Does a CKYC record eliminate the need for video IPV?</strong> </p><p>No. An existing CKYC record reduces data collection effort by allowing pre-population of KYC details, but it does not eliminate the IPV requirement. SEBI mandates that IPV be conducted for every new account regardless of whether the investor has a CKYC record. The video session verifies that the person in front of the camera is the same person whose record exists in CKYC.</p><p><strong>Who qualifies as an authorised person for video IPV?</strong> </p><p>The authorised person must be an employee or formally designated representative of the SEBI-registered intermediary i.e., your broking entity. They must be identifiable by name and employee ID in the session record. Third-party technology vendor staff do not qualify unless they hold a formal authorisation under your entity's SEBI registration, which requires specific legal structuring.</p><p><strong>How long must video IPV recordings be retained?</strong> </p><p>PMLA regulations require records to be retained for a minimum of five years from the cessation of the business relationship or from the date of the relevant transaction, whichever is later. For active accounts, this is an ongoing obligation. Your compliance counsel should define the precise retention schedule, as SEBI may impose additional norms through circulars.</p><p><strong>What happens if a video IPV session fails midway?</strong> </p><p>A mid-session failure whether due to network drop, device issue, or recording pipeline error means the IPV is incomplete. The system should allow the investor to reschedule and complete a fresh session. The incomplete session record should be retained (with its incomplete status noted) for audit purposes. Do not mark a partial session as complete.</p><p><strong>Can an investor complete video IPV on a mobile device?</strong> </p><p>Yes, provided the mobile application delivers sufficient camera quality (minimum 720p recommended), supports the liveness check mechanism, and can transmit the live video stream to the agent's dashboard without unacceptable latency. The WebRTC stack used in the SDK must handle mobile browser or native app contexts with reliable reconnection on mobile network fluctuations.</p><p><strong>What are the consequences of non-compliance with SEBI video KYC requirements?</strong> </p><p>Consequences can include: rejection of KYC records by KRAs (forcing remediation of affected accounts), SEBI inspection findings that result in formal show-cause notices, monetary penalties under SEBI Act provisions, suspension of broking operations in severe cases, and reputational damage from public enforcement disclosures. PMLA violations carry separate consequences including reporting to the Financial Intelligence Unit (FIU-IND).</p><p><strong>Does the video IPV system need to be built in-house?</strong> </p><p>No. Most brokers use a combination of third-party real-time video infrastructure and internally owned compliance and KRA integration layers. The critical requirement is that your entity owns the compliance output the completed IPV record, KRA submission, and audit trail regardless of which infrastructure layer generated the video session.</p>]]></content:encoded></item><item><title><![CDATA[How to Scale Video KYC to 1 Million+ Monthly Verifications]]></title><description><![CDATA[Learn how to scale video KYC to 1M+ monthly verifications, architecture, WebRTC infra, RBI compliance, and failure handling for fintech teams.]]></description><link>https://www.videosdk.live/blog/how-to-scale-video-kyc-to-1-million-monthly-verifications</link><guid isPermaLink="false">69ef2ddb55831517a5a8a810</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 28 Apr 2026 09:01:44 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/04/5.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>TL;DR: </strong>Scaling video KYC to 1 million+ monthly verifications requires a purpose-built infrastructure stack: distributed WebRTC session routing, auto-scaling agent queues, a compliant recording pipeline, and fault-tolerant session recovery. Most teams underestimate concurrency requirements by 3–5x and treat compliance storage as an afterthought both of which create catastrophic bottlenecks at scale.</blockquote><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text">To scale video KYC to 1 million verifications per month, you need a distributed SFU-based WebRTC infrastructure capable of handling 1,500–2,000 peak concurrent sessions, an agent capacity model supporting 8–10 verifications per agent per hour, an auto-scaling orchestration layer tied to queue depth, and an RBI-compliant recording pipeline with end-to-end audit storage. No single component can be left unscaled the system is only as fast as its slowest constraint.</div></div><h2 id="why-scaling-video-kyc-is-now-a-business-critical-infrastructure-problem">Why scaling video KYC is now a business-critical infrastructure problem</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/5.png" alt="How to Scale Video KYC to 1 Million+ Monthly Verifications"/><p>The push to&nbsp;<strong>scale video KYC</strong>&nbsp;to 1 million verifications and beyond is no longer a future ambition it is the present reality for large NBFCs, digital banks, insurance aggregators, and broker platforms operating in India. As of 2024, RBI-regulated entities are required to complete customer due diligence through&nbsp;<strong>Video-based Customer Identification Process (V-CIP)</strong>, the formal designation for video KYC under the&nbsp;<a href="https://www.rbi.org.in/Scripts/BS_ViewMasDirections.aspx?id=11566" rel="noreferrer nofollow">Reserve Bank of India's Master Direction on KYC</a>&nbsp;(updated in 2021 and subsequently amended). Simultaneously, SEBI and IRDAI have published parallel guidelines aligned with the same verification model.</p><p>Beyond India, MAS (Singapore), FCA (UK), BaFin (Germany), and FinCEN (US) have each adopted digital identity verification frameworks that include video as an acceptable and often preferred verification channel. The result is a global infrastructure problem: real-time identity verification systems must be architected to handle volume, latency, compliance, and failure simultaneously.</p><p>The failure mode for teams that build this ad hoc is well-documented: video drops during peak hours, recording gaps that fail audits, agent queues that back up causing 20–40 minute wait times, and compliance breaches that trigger regulatory notices. This guide is for engineering leaders and architects who need to build this right.</p>
<!--kg-card-begin: html-->
<iframe width="600" height="400" src="https://www.youtube.com/embed/tWpIDf0V-PQ?si=vnNgFGw1JGeQzoZX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<h2 id="market-and-compliance-context">Market and compliance context</h2><h3 id="what-does-1-million-monthly-verifications-actually-look-like">What does 1 million monthly verifications actually look like?</h3><p>Breaking down the math is the first step to responsible infrastructure design.</p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Metric</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Calculation</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Example Value</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Monthly verifications</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Target</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">1,000,000</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Daily average</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">÷ 22 working days</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">~45,500/day</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Peak day multiplier</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">1.8–2.2x average</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">~91,000–100,000/day</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Peak hour (10 AM–12 PM)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">25–30% of daily</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">~22,500–30,000/hour</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Peak concurrent sessions</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Avg. 8-min session, ÷ 60</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">3,000–4,000 concurrent</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Agent hours required</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">8 sessions/agent/hour</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">375–500 active agents at peak</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>Most teams design for average load. The infrastructure must be designed for 2–3x average peak concurrency with headroom for viral onboarding campaigns and IPO application surges common in the Indian fintech context.</p><h3 id="rbi-v-cip-compliance-requirements">RBI V-CIP compliance requirements</h3><p><strong>V-CIP (Video-based Customer Identification Process):</strong> V-CIP is the RBI-mandated framework for conducting KYC using live video interaction between a regulated entity's officer and a customer, as specified in the Master Direction – Know Your Customer (KYC) Direction, 2016 (last updated 2023). The process is not simply a video call it is a structured verification event with defined data capture, storage, and audit requirements.</p><p>Key requirements under V-CIP:</p><ul><li>Live, uninterrupted video with no pre-recorded segments</li><li>Geo-tagging of the customer's location at session initiation</li><li>PAN card verification via OCR with face-match <a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer">liveness check</a></li><li><a href="https://uidai.gov.in/en/ecosystem/authentication-ecosystem.html" rel="noreferrer nofollow">Aadhaar-based OTP authentication</a>&nbsp;(with UIDAI integration)</li><li>Session recording stored in India-based servers</li><li>Audit trail with timestamps, agent ID, and session metadata</li><li>Agent must be a trained official of the regulated entity (not a third party)</li></ul><p>Failure to comply exposes regulated entities to penalties under the Prevention of Money Laundering Act (PMLA), potential license suspension, and reputational risk. The consequences extend beyond fines a compliance gap in the audit trail can invalidate thousands of onboarding records retroactively.</p><blockquote><strong>Note:</strong> Compliance requirements evolve. Always validate your V-CIP implementation against the most current RBI Master Direction and consult a qualified compliance officer before production deployment.</blockquote><h2 id="how-to-scale-video-kyc-to-1-million-verifications">How to scale video KYC to 1 million verifications</h2><h3 id="end-to-end-system-architecture">End-to-end system architecture</h3><p>A production-grade video KYC infrastructure is not a monolithic system. It is a pipeline of coordinated services, each responsible for a specific stage of the session lifecycle.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-27--2026--03_28_31-PM.png" class="kg-image" alt="How to Scale Video KYC to 1 Million+ Monthly Verifications" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">End-to-end video KYC architecture</span></figcaption></img></figure><p><strong>The seven layers of the architecture:</strong></p><p><strong>Layer 1: Session initiation.</strong> The customer opens the mobile app or web client and requests a video KYC session. The client sends an API call to the session orchestration service, which creates a session ID, assigns a queue position, and returns session metadata including estimated wait time. At this point, geo-location is captured and stored.</p><p><strong>Layer 2: Queue and agent assignment.</strong> The orchestration layer maintains a priority queue of pending sessions. When an agent becomes available, the session manager assigns the session, notifies both the customer and agent, and instructs the WebRTC layer to initiate connection establishment.</p><p><strong>Layer 3: WebRTC connection.</strong> The client and agent establish a real-time video connection through the WebRTC infrastructure layer. This is where most infrastructure complexity lives, and where the majority of scaling failures originate.</p><p><strong>Layer 4: KYC verification flow.</strong> During the session, the agent follows a structured checklist: document capture (PAN, Aadhaar), face-match liveness, verbal confirmation, and geo-tag verification. The KYC backend processes OCR and biometric checks in real time, returning pass/fail signals to the agent dashboard.</p><p><strong>Layer 5: Session recording.</strong> Every session is recorded simultaneously with the live stream. The recording pipeline captures encrypted video to a compliant India-hosted storage layer (S3-compatible, with WORM  Write Once Read Many policy enabled).</p><p><strong>Layer 6: Post-session processing.</strong> After the session closes, the system stitches metadata (timestamps, agent ID, session ID, geo-coordinates, document scan results) with the recording and stores the complete audit bundle in the compliance archive.</p><p><strong>Layer 7: Audit and reporting.</strong> Regulators and internal compliance teams access the audit layer through a separate read-only interface. All access is logged.</p><h3 id="the-webrtc-infrastructure-layer-the-hardest-part-to-scale">The WebRTC infrastructure layer the hardest part to scale</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-27--2026--03_33_43-PM.png" class="kg-image" alt="How to Scale Video KYC to 1 Million+ Monthly Verifications" loading="lazy" width="1536" height="1024"><figcaption><b><strong style="white-space: pre-wrap;">WebRTC session flow</strong></b></figcaption></img></figure><p><strong>WebRTC:</strong> <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC (Web Real-Time Communication)</a> is an open standard that enables peer-to-peer audio, video, and data communication directly between browsers and native apps without requiring plugins. In video KYC, WebRTC is the protocol layer responsible for transmitting live video between customer and agent.</p><p><strong>SFU (Selective Forwarding Unit):</strong> An SFU is a media routing server that receives media streams from participants and selectively forwards them to other participants without transcoding. Unlike a peer-to-peer model, an SFU centralizes media routing, enabling recording, quality monitoring, and scalable multi-party communication. For video KYC, SFU is the correct architecture it handles thousands of concurrent two-party sessions efficiently.</p><p><strong>MCU (Multipoint Control Unit):</strong> An MCU mixes all media streams into a single composite stream before forwarding. MCUs are suited for multi-party conferencing where every participant sees the same layout. For video KYC (one customer, one agent), MCU overhead is unnecessary and adds latency.</p><p>For 1M+ monthly verifications at peak concurrency (3,000–4,000 sessions), the SFU cluster must be horizontally scaled across multiple server instances, with a session manager distributing load based on current capacity. A single SFU server typically handles 500–1,500 concurrent sessions depending on video resolution and codec settings. At 720p (the minimum acceptable quality for document legibility), plan for 800–1,000 sessions per SFU node.</p><p><strong>Network handling.</strong> Video KYC customers are not always on fiber. Indian last-mile connectivity includes 4G with significant packet loss, shared WiFi environments, and rural users on 3G. The WebRTC layer must implement <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">adaptive bitrate</a> control (reducing resolution under bandwidth constraints), NACK-based packet loss recovery, and <a href="https://www.videosdk.live/blog/what-is-jitter-buffer" rel="noreferrer">jitter buffering</a>. Target session quality thresholds: latency below 250ms (one-way), packet loss tolerance up to 5%, minimum viable bitrate of 400 kbps at 480p.</p><p><strong>Multi-region scaling.</strong> For India-first deployments, a Mumbai primary region with a Hyderabad or Chennai secondary region covers geographic latency requirements. TURN servers (relay servers used when direct peer connections fail) must be deployed in each region. Approximately 15–20% of sessions will require TURN relay rather than direct connection account for this in your TURN server capacity.</p><h3 id="scaling-model-traffic-spikes-to-session-delivery">Scaling model: traffic spikes to session delivery</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-27--2026--03_58_53-PM.png" class="kg-image" alt="How to Scale Video KYC to 1 Million+ Monthly Verifications" loading="lazy" width="1717" height="916"><figcaption><b><strong style="white-space: pre-wrap;">Scaling model</strong></b><span style="white-space: pre-wrap;"> for VideoKYC</span></figcaption></img></figure><p>The scaling architecture has two independent axes: infrastructure scaling (SFU, recording, storage) and agent capacity scaling (human agents). Infrastructure can auto-scale in under 2 minutes. Agent capacity cannot it requires workforce management planning, trained agent pools, and shift scheduling. This asymmetry is the most common failure point.</p><p><strong>Infrastructure scaling model:</strong></p>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Metric</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Example Value</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Impact</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SFU nodes at baseline</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">8 nodes</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Handles ~6,400 concurrent sessions</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Scale-out trigger</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Queue depth &gt; 50 sessions</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Auto-provision 2 nodes</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Provision time (cold)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">75–90 seconds</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Governs max ramp rate</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Recording pipeline workers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">1 per 200 concurrent sessions</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Scale with SFU</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">TURN server capacity</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">1 server per 500 TURN sessions</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Scale at 15% of concurrent</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Storage throughput</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">~500 MB per session (720p, 8 min avg)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">500 TB/month at 1M vol</td></tr></tbody></table>
<!--kg-card-end: html-->
<p><strong>Agent capacity model:</strong></p><p>The agent layer is not infrastructure it is a workforce. At 8 sessions per agent per hour (accounting for documentation, breaks, and gap time between sessions), 500 active agents are needed at peak. Most platforms operate a hub-and-spoke model: central training, regional agent pools, and overflow contracts with BPO partners. Overflow agents must be pre-approved by the regulated entity's compliance team  they cannot be spun up on demand without prior due diligence.</p><p>Agent availability signals must feed back into the queue. When agent availability drops below a threshold, the queue system must proactively display accurate wait times to customers and offer asynchronous alternatives (document upload queues for non-real-time verification where regulations permit).</p><h3 id="build-vs-buy-vs-hybrid-the-infrastructure-decision-framework">Build vs. buy vs. hybrid the infrastructure decision framework</h3>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Factor</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Build</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Buy</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Hybrid</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Control over WebRTC layer</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Full</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">None</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Partial (SDK-level)</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Time to production</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">9–18 months</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">4–8 weeks</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">6–12 weeks</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Compliance customization</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Full</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Vendor-dependent</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Configurable</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">SFU infrastructure ops burden</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High (dedicated team)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Zero</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Low</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Recording pipeline ownership</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Full</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Vendor-managed</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Shared</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Vendor lock-in risk</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">None</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Medium</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Cost at 1M monthly volume</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">High (infra + eng team)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Predictable per-session</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Lowest total cost</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Regulatory audit readiness</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Requires internal build</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Vendor certification needed</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Best balance</td></tr></tbody></table>
<!--kg-card-end: html-->
<p>For most fintech platforms scaling past 500K monthly verifications, the hybrid model delivers the best balance: use a real-time video infrastructure SDK for session management, WebRTC routing, and SFU operations, while owning the KYC backend (liveness, OCR, face-match), compliance storage, and audit pipeline. This preserves regulatory control while eliminating the operational burden of running a WebRTC media infrastructure team.</p><p><strong>VideoSDK</strong> provides <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">real-time video APIs</a> that handle session orchestration, SFU-based media routing, and scalable connection management the infrastructure layer in a hybrid architecture. The KYC verification logic, recording pipeline, and compliance storage remain under the regulated entity's control.</p><h3 id="failure-handling-at-scale">Failure handling at scale</h3><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/04/ChatGPT-Image-Apr-27--2026--03_50_02-PM.png" class="kg-image" alt="How to Scale Video KYC to 1 Million+ Monthly Verifications" loading="lazy" width="1693" height="929"><figcaption><b><strong style="white-space: pre-wrap;">Failure handling and session recovery</strong></b></figcaption></img></figure><p>At 1M monthly verifications, even a 0.5% failure rate produces 5,000 failed sessions per month. Each failure has a cost: customer drop-off, agent idle time, re-scheduling overhead, and potential compliance gaps if a partially recorded session is not handled correctly. Failure handling is not a nice-to-have it is a core architectural requirement.</p><p><strong>Call drops and reconnection.</strong> WebRTC ICE (Interactive Connectivity Establishment) provides a native reconnection mechanism. When connectivity is lost, the client should attempt ICE restart before declaring the session failed. The session orchestration layer must preserve session state (session ID, timestamp, completed verification steps, partial recording) for a minimum of 5 minutes to enable seamless resumption. Customers who reconnect within this window should not restart the verification flow from the beginning.</p><p><strong>Network degradation.</strong> <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">Adaptive bitrate (ABR)</a> handling should activate before a call drops. At below 400 kbps, the system should drop video resolution to 360p and notify the agent. At below 200 kbps, the session should prompt the customer to switch networks or reschedule. Agent dashboards must display real-time network quality indicators so agents can make informed decisions about whether to continue or reschedule.</p><p><strong>Agent unavailability.</strong> Agents disconnect, crash browsers, or go offline unexpectedly. The session manager must detect agent disconnection within 10 seconds and either reassign the session to an available agent (preserving the customer's queue position) or hold the session with an in-queue notification to the customer. A session should never be silently dropped because an agent's browser crashed.</p><p><strong>Recording failures.</strong> A session that completes verification but fails to produce a valid, complete recording is a compliance failure not just a technical failure. The recording pipeline must write to two destinations simultaneously (primary and backup), with integrity checksums validated post-session. If the primary recording fails, the backup must be automatically promoted. Sessions with recording failures must be flagged for manual review and not treated as completed verifications.</p><p><strong>Partial sessions and audit gaps.</strong> Every incomplete session must generate an audit record. The audit record must include: session ID, timestamp of initiation, reason for termination, last completed verification step, agent ID, and customer ID. Incomplete sessions without audit records will surface as compliance gaps during regulatory inspections.</p><h2 id="rbi-v-cip-compliance-checklist">RBI V-CIP compliance checklist</h2>
<!--kg-card-begin: html-->
<table class="min-w-full border-collapse text-sm leading-[1.7] whitespace-normal"><thead class="text-left"><tr><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Requirement</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Description</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Applies to</th><th scope="col" class="text-text-100 border-b-0.5 border-border-300/60 py-2 pr-4 align-top font-bold">Risk if missing</th></tr></thead><tbody><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Live video — no pre-recorded</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session must be conducted in real time with no pre-recorded customer segments</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All regulated entities</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session invalidated, regulatory notice</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Geo-tagging at initiation</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Customer's GPS coordinates captured and stored at session start</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All V-CIP implementations</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Audit failure, session invalidated</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">PAN verification with OCR</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">PAN card captured via camera, OCR-verified against customer-submitted data</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory for most product types</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">KYC not completed, onboarding blocked</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Aadhaar OTP authentication</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Customer authenticates via Aadhaar-linked OTP during session</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory with UIDAI integration</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Regulatory non-compliance</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Face-match liveness check</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Real-time liveness detection with face match against ID document</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All V-CIP</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Identity fraud risk, audit failure</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session recording</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Full session video recorded and stored in India-based servers</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Audit failure, PMLA exposure</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">WORM storage policy</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Recording cannot be modified or deleted post-session</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Tamper evidence failure</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Audit trail with metadata</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session ID, timestamps, agent ID, geo-tag, document scan results stored together</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Incomplete audit, regulatory penalty</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Trained agent (regulated entity staff)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Verification officer must be employee or verified official of the regulated entity</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All V-CIP</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Session invalidated</td></tr><tr><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Data residency (India servers)</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">All session data, recordings, and metadata stored in India</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Mandatory</td><td class="border-b-0.5 border-border-300/30 py-2 pr-4 align-top">Data sovereignty violation</td></tr></tbody></table>
<!--kg-card-end: html-->
<h2 id="common-mistakes-engineering-teams-make">Common mistakes engineering teams make</h2><p><strong>1. Designing for average load, not peak concurrency.</strong> The most expensive infrastructure mistake is provisioning for the average of 45,000 sessions per day rather than the peak of 90,000 on the highest-demand day. Auto-scaling helps, but provision-time lag (75–90 seconds for a new SFU node) means the system must pre-scale based on predictive signals calendar events, marketing campaign start times, IPO application windows rather than reactive threshold triggers alone.</p><p><strong>2. Treating the recording pipeline as secondary.</strong> Many teams build the live video path first and bolt on recording later. At scale, this creates a fragile single-threaded pipeline that cannot sustain simultaneous high-fidelity live streaming and recording. The recording tap must be built into the SFU layer from day one, with independent scaling and dual-destination writes.</p><p><strong>3. Ignoring the agent-infrastructure mismatch.</strong> Infrastructure can scale in minutes. Agents cannot. A platform that scales SFU capacity to handle 4,000 concurrent sessions but only has 300 trained agents online will produce queue times that drive customer abandonment and the abandonment rate compounds the compliance overhead of failed sessions that must be tracked and logged.</p><p><strong>4. Underspecifying the failure audit trail.</strong> Every failed, interrupted, or partial session must generate a complete audit record. Teams that log only successful sessions will fail regulatory inspections. Build the failure audit path with the same rigor as the success path.</p><p><strong>5. Hardcoding geo-restrictions without dynamic validation.</strong> V-CIP requires customer geo-tagging, but several teams implement this as a static IP-based check rather than a GPS capture. The correct implementation requires device GPS with a timestamp, stored alongside the session record. IP-based location is not an acceptable substitute under V-CIP guidelines.</p><h2 id="key-takeaways">Key takeaways</h2><ul><li><strong>Design for 2–3x average peak concurrency</strong> at 1M monthly verifications, peak concurrent sessions reach 3,000–4,000, requiring 4–5 SFU nodes with headroom and auto-scaling to 8–10 nodes under surge conditions.</li><li><strong>SFU is the correct WebRTC topology for video KYC</strong> it enables centralized recording, quality monitoring, and horizontal scaling without the transcoding overhead of an MCU.</li><li><strong>The hybrid build/buy model delivers the best balance</strong> own the KYC backend, compliance storage, and audit pipeline; use a real-time video infrastructure SDK for session management and SFU operations.</li><li><strong>Recording failures are compliance failures</strong> dual-destination writes, integrity checksums, and automatic promotion of backup recordings are non-negotiable at regulated scale.</li><li><strong>Agent capacity is the hardest constraint to scale</strong> infrastructure auto-scales in under 2 minutes; trained agent pools require weeks of planning, which means workforce forecasting must be integrated into the infrastructure scaling model.</li></ul><h2 id="faq">FAQ</h2><p><strong>Q: What is the minimum infrastructure required to handle 100,000 video KYC sessions per month?</strong> </p><p>At 100,000 monthly sessions with a peak concurrency of approximately 300–400 simultaneous sessions, a deployment of 2–3 SFU nodes with a load balancer and auto-scaling configured to a 50-session queue threshold is sufficient. A single recording pipeline worker handling up to 200 concurrent recordings is adequate at this scale. Ensure your TURN server can handle 60–80 TURN-relayed sessions at peak.</p><p><strong>Q: How does WebRTC handle poor network conditions during a video KYC session?</strong> </p><p>WebRTC includes native adaptive bitrate control through its congestion control algorithms (Google Congestion Control / REMB). When network bandwidth drops, the WebRTC layer automatically reduces video resolution and frame rate to maintain session continuity. For video KYC specifically, you should configure a minimum quality floor (400 kbps at 480p) below which the system should notify the agent and prompt the customer to switch networks or reschedule.</p><p><strong>Q: Can video KYC sessions be conducted on 3G networks?</strong> </p><p>Yes, but with constraints. A 3G connection delivering a sustained 1–2 Mbps can handle a 480p video KYC session adequately. The WebRTC layer must be configured with aggressive jitter buffering and packet loss recovery (NACK). Sessions on borderline connectivity should be flagged in the recording metadata, as quality degradation could affect document legibility which has compliance implications.</p><p><strong>Q: How long must video KYC recordings be retained under RBI guidelines?</strong> </p><p>The RBI Master Direction on KYC requires that KYC records (including V-CIP recordings) be maintained for at least 5 years after the business relationship ends, or 5 years from the date of the transaction whichever is later. Storage must be in India-based servers with WORM policy. Always verify the current retention period with your compliance team, as this requirement may be updated.</p><p><strong>Q: What is the difference between V-CIP and standard video KYC?</strong> </p><p>V-CIP (Video-based Customer Identification Process) is the specific RBI-mandated framework for video KYC in India, as defined in the Master Direction – KYC Direction, 2016. It specifies the exact data capture requirements (geo-tag, PAN, Aadhaar OTP, liveness), agent qualifications, storage requirements, and audit obligations. "Video KYC" is the generic term; V-CIP is the regulated implementation. All video KYC conducted by RBI-regulated entities must comply with V-CIP requirements.</p><p><strong>Q: How do you handle session resumption after a network drop?</strong> </p><p>The session orchestration layer must preserve session state session ID, completed verification steps, partial recording, timestamps for a minimum of 5 minutes after a drop. When the customer reconnects within this window, the WebRTC layer initiates an ICE restart using the same session parameters, and the verification flow resumes from the last completed step. Partial recordings are stitched with the resumed recording at the post-session processing stage, and both segments are stored together with a discontinuity marker in the metadata.</p><p><strong>Q: What is the estimated storage cost for 1 million video KYC sessions per month?</strong> </p><p>At an average session length of 8 minutes and a recording bitrate of ~800 kbps (720p, H.264), each session produces approximately 480 MB of raw recording. At 1 million sessions, this is approximately 480 TB per month of raw recording data. With H.265/HEVC encoding (approximately 40% size reduction) and storage tiering (hot storage for 30 days, cold storage for the remainder of the 5-year retention period), the effective managed storage cost can be reduced substantially. Budget both hot and cold storage tiers separately, and account for replication overhead across backup destinations.</p><p><strong>Q: How should we approach compliance storage for a globally distributed video KYC platform?</strong> </p><p>For RBI-regulated entities, recording data must be stored in India regardless of where the platform's primary infrastructure runs. For global deployments (MAS, FCA, FinCEN), each jurisdiction has its own data residency requirements. The standard architecture is regional compliance storage nodes data captured in a jurisdiction stays in that jurisdiction's storage tier. The audit and reporting layer is a federated query layer that can access all regional stores with role-based access control and a complete access log.</p><h2 id=""/>]]></content:encoded></item><item><title><![CDATA[Building Real-Time AI Voice Agents with Google Gemini 3.1 Flash Live and VideoSDK]]></title><description><![CDATA[Discover the exact architecture and implementation steps to build real-time AI voice agents using Google Gemini 3.1 Flash Live and the VideoSDK Python framework.]]></description><link>https://www.videosdk.live/blog/how-to-build-real-time-ai-voice-agents-with-google-gemini-3-1-flash-live-and-videosdk</link><guid isPermaLink="false">69c76f6555831517a5a8a562</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 30 Mar 2026 08:18:22 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/03/Gemini-3-Pro---Flash.svg" medium="image"/><content:encoded><![CDATA[<blockquote>Real-time AI voice agents with Google Gemini 3.1 Flash Live are conversational systems that process audio natively without intermediate text conversion. This architecture reduces interaction latency to milliseconds. Implementing these agents requires a robust WebRTC media pipeline like VideoSDK to handle audio routing, stream synchronization, and connection stability.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/03/Gemini-3-Pro---Flash.svg" alt="Building Real-Time AI Voice Agents with Google Gemini 3.1 Flash Live and VideoSDK"/><p>Building conversational applications historically meant stacking three distinct systems: <a href="https://www.videosdk.live/developer-hub/stt/what-is-automatic-speech-recognition" rel="noreferrer">automatic speech recognition (ASR)</a>, a <a href="https://www.videosdk.live/developer-hub/llm/what-is-a-llm" rel="noreferrer">large language model (LLM)</a>, and <a href="https://www.videosdk.live/developer-hub/tts/what-is-text-to-speech" rel="noreferrer">text-to-speech (TTS)</a>. That cascaded architecture introduced compounding delays, making interactions feel robotic, highly structured, and unnatural. <a href="https://blog.google/innovation-and-ai/models-and-research/gemini-models/gemini-3-1-flash-live/" rel="noreferrer">Google Gemini 3.1 Flash Live Preview</a> changes this by handling audio-to-audio processing natively. When you combine this multimodal model with VideoSDK's real-time media pipeline, you can build agents that listen, think, and speak seamlessly. This technical walkthrough explores the architecture, production challenges, and exact implementation steps for deploying low-latency voice AI at scale.</p><h2 id="what-is-google-gemini-31-flash-live">What Is Google Gemini 3.1 Flash Live?</h2><p>Google Gemini 3.1 Flash Live is a native multimodal model engineered specifically for low-latency, audio-first conversational experiences. Google Gemini 3.1 Flash Live is defined as an AI model that ingests and generates audio directly, bypassing traditional text conversion pipelines completely. This direct audio processing allows the model to preserve acoustic nuances such as pitch, tone, and pacing, which standard text transcripts inevitably discard.</p><p>Google Gemini 3.1 Flash Live works by utilizing a unified transformer architecture that treats audio frames as first-class tokens alongside text and vision. According to Google's 2026 AI developer documentation, this architecture enables the model to respond significantly faster than its predecessor, Gemini 2.5 Flash Native Audio. It natively supports over 90 languages and introduces the critical ability to trigger external API tools dynamically during an active audio stream. This allows the model to perform complex backend tasks, such as checking inventory, updating database records, or booking appointments, while maintaining a natural conversational flow with the user.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-5--2026--02_56_03-PM.png" class="kg-image" alt="Building Real-Time AI Voice Agents with Google Gemini 3.1 Flash Live and VideoSDK" loading="lazy" width="1693" height="929"><figcaption><span style="white-space: pre-wrap;">Native vs. Traditional Audio Pipelines</span></figcaption></img></figure><h3 id="heres-what-stands-out">Here's what stands out:</h3><ul><li>Lower latency than before. Compared to 2.5 Flash Native Audio, this model is noticeably faster. Fewer awkward pauses, snappier responses. That matters a lot when you're building voice agents where delays break the experience.</li><li>It actually understands how you say things. The model picks up on acoustic nuances, pitch, pace, tone. So it can tell when you're asking a casual question vs. when you sound urgent or confused.</li><li>Better background noise handling. It filters out noise more effectively, which means it works in real environments, not just quiet studios.</li><li>Multilingual out of the box. Over 90 languages supported for real-time conversations.</li><li>Longer conversation memory. It can follow the thread of a conversation for twice as long as the previous generation. So your agent won't "forget" what was said earlier in a long session.</li><li>Tool use during live conversations. This one is huge for agent builders. The model can now trigger external tools (APIs, functions, searches) while a live conversation is happening not just at the end of a turn.</li><li>Multimodal awareness. It handles audio and video inputs together, so you can build agents that respond to what they see and hear at the same time.</li></ul><p><strong>The model ID is: gemini-3.1-flash-live-preview</strong></p><h2 id="building-a-voice-agent-with-videosdk">Building a Voice Agent with VideoSDK</h2><p>VideoSDK gives you everything you need to wire Gemini 3.1 Flash Live into a real voice application. Here's how to get set up from scratch.</p><h3 id="step-1-create-and-activate-a-python-virtual-environment">Step 1 : Create and Activate a Python Virtual Environment</h3><p>First, create a clean Python environment so your project dependencies stay isolated.</p><pre><code class="language-python">python3 -m venv venv</code></pre><p><strong>Activate it:</strong></p><p><strong>macOS/Linux </strong></p><pre><code class="language-python">source venv/bin/activate</code></pre><p><strong>Windows</strong></p><pre><code class="language-python">venv\Scripts\activate</code></pre><p>You should see (venv) in your terminal, which means you're good to go.</p><h3 id="step-2-set-up-your-environment-variables">Step 2 : Set Up Your Environment Variables</h3><p>Create a .env file in your project root and add your API keys:</p><pre><code class="language-python">VIDEOSDK_AUTH_TOKEN=your_videosdk_token_here
GOOGLE_API_KEY=your_google_api_key_here</code></pre><p>You can get your <a href="https://dub.sh/zXYQt7V" rel="noreferrer">VideoSDK auth token</a> from the <a href="https://dub.sh/zXYQt7V" rel="noreferrer">VideoSDK dashboard</a> and your Google API key from Google AI Studio.</p><p>Important: when <a href="https://aistudio.google.com/app/api-keys" rel="noreferrer">GOOGLE_API_KEY</a> is set in your .env file, do not pass api_key as a parameter in your code the SDK picks it up automatically.</p><h3 id="step-3-install-the-required-packages">Step 3 : Install the Required Packages</h3><p>Install VideoSDK's agents SDK along with the Google plugin:</p><pre><code class="language-python">pip install "videosdk-agents[google]"</code></pre><h3 id="step-4-create-your-agent-mainpy">Step 4 : Create Your Agent (main.py)</h3><p>Create a file called main.py in your project folder and paste in the following code:</p><pre><code class="language-python">from videosdk.agents import Agent, AgentSession, Pipeline, JobContext, RoomOptions, WorkerJob
from videosdk.plugins.google import GeminiRealtime, GeminiLiveConfig
import logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", handlers=[logging.StreamHandler()])

class MyVoiceAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions="You Are VideoSDK's Voice Agent.You are a helpful voice assistant that can answer questions and help with tasks.",
        )

    async def on_enter(self) -&gt; None:
        await self.session.say("Hello, how can I help you today?")
    
    async def on_exit(self) -&gt; None:
        await self.session.say("Goodbye!")

async def start_session(context: JobContext):
    agent = MyVoiceAgent()
    model = GeminiRealtime(
        model="gemini-3.1-flash-live-preview",
        # When GOOGLE_API_KEY is set in .env - DON'T pass api_key parameter
        # api_key="AIXXXXXXXXXXXXXXXXXXXX", 
        config=GeminiLiveConfig(
            voice="Leda", # Puck, Charon, Kore, Fenrir, Aoede, Leda, Orus, and Zephyr.
            response_modalities=["AUDIO"]
        )
    )

    pipeline = Pipeline(llm=model)
    session = AgentSession(
        agent=agent,
        pipeline=pipeline
    )

    await session.start(wait_for_participant=True, run_until_shutdown=True)

def make_context() -&gt; JobContext:
    room_options = RoomOptions(
        # room_id="&lt;room_id&gt;", # Replace it with your actual room_id
        name="Gemini Realtime Agent",
        playground=True,
    )

    return JobContext(room_options=room_options)

if __name__ == "__main__":
    job = WorkerJob(entrypoint=start_session, jobctx=make_context)
    job.start()</code></pre><p><strong>To run the agent:</strong></p><pre><code class="language-python">python main.py</code></pre><p>Once you run this command, a playground URL will appear in your terminal. You can use this URL to interact with your AI agent.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/03/Screenshot-2026-03-28-at-1.05.35-PM.png" class="kg-image" alt="Building Real-Time AI Voice Agents with Google Gemini 3.1 Flash Live and VideoSDK" loading="lazy" width="2100" height="698"/></figure><h3 id="what-can-you-build-with-this">What Can You Build With This?</h3><p>Gemini 3.1 Flash Live + VideoSDK opens up a pretty wide range of real-world use cases:</p><ul><li>Customer support voice bots. Replace or supplement your call center with agents that actually understand tone and can handle multilingual customers in real time.</li><li>AI meeting assistants. Agents that join calls, take notes, answer questions from participants, and trigger follow-up actions mid-conversation.</li><li>Healthcare intake agents. Voice-based triage agents that collect patient information, ask follow-up questions, and route to the right department all in a natural spoken conversation.</li><li>Language tutors. Real-time conversation partners that catch pronunciation issues, adjust their pace based on the learner, and respond naturally.</li><li>Voice-controlled IoT and home automation. Agents that listen continuously, understand context, and trigger device actions through tool use all in sub-second response times.</li><li>Live interview prep tools. Candidates practice answering questions aloud and get spoken feedback instantly.</li></ul><h2 id="conclusion">Conclusion</h2><p>Gemini 3.1 Flash Live Preview is a meaningful step forward for real-time voice AI. The improvements in latency, noise handling, multilingual support, and especially live tool use make it a strong foundation for production voice agents.</p><p>VideoSDK wraps all of that into a clean Python SDK that gets you from zero to a running agent in a handful of lines. Whether you're prototyping or building something you intend to ship, the setup here gives you a solid starting point.</p><h2 id="next-steps-and-resources">Next Steps and Resources</h2><ul><li>Check <a href="https://docs.videosdk.live/ai_agents/plugins/realtime/google-live-api" rel="noreferrer">Gemini3.1 implementation</a> docs</li><li>Learn how to <a href="https://docs.videosdk.live/ai_agents/deployments/agent-cloud/cli/deploy" rel="noreferrer">deploy your agents</a></li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-main-difference-between-google-gemini-31-flash-live-and-standard-llms">What is the main difference between Google Gemini 3.1 Flash Live and standard LLMs?</h3><p>The main difference between Google Gemini 3.1 Flash Live and standard LLMs is its native audio-to-audio architecture. Standard models require external text conversion pipelines, whereas Gemini processes and generates raw audio, drastically reducing latency and preserving acoustic nuances.</p><h3 id="can-videosdk-and-google-gemini-31-flash-live-be-used-together">Can VideoSDK and Google Gemini 3.1 Flash Live be used together?</h3><p>Yes, VideoSDK and Google Gemini 3.1 Flash Live can be used together seamlessly. VideoSDK handles the complex WebRTC media transport and client connections, while Gemini serves as the core intelligence engine processing the audio streams.</p><h3 id="which-is-better-a-cascaded-voice-architecture-or-a-native-audio-model">Which is better, a cascaded voice architecture or a native audio model?</h3><p>A native audio model is the better choice when your application requires sub-second conversational latency and the ability to detect user tone. A cascaded architecture is only preferable when you must integrate legacy LLMs that strictly accept text inputs.</p><h3 id="how-does-webrtc-improve-voice-ai-performance">How does WebRTC improve voice AI performance?</h3><p>WebRTC improves voice AI performance by utilizing UDP transport, which prioritizes immediate data delivery over packet ordering. This eliminates the blocking delays common in TCP-based connections, ensuring smooth and continuous audio playback.</p><h3 id="what-is-barge-in-functionality-in-voice-agents">What is barge-in functionality in voice agents?</h3><p>Barge-in functionality in voice agents is the system's ability to detect when a user starts speaking and immediately halt its own audio output. This feature is critical for creating natural conversations where users can interrupt the AI at any time.</p><h3 id="does-gemini-31-flash-live-support-tool-use-during-live-conversations">Does Gemini 3.1 Flash Live support tool use during live conversations?</h3><p>Yes, Gemini 3.1 Flash Live supports dynamic tool use during active audio streams. This allows the agent to query external APIs, fetch database records, or execute functions without terminating the conversational flow.</p>]]></content:encoded></item><item><title><![CDATA[How to build AI Virtual Avatars using Anam-AI and VideoSDK AI Voice Agents]]></title><description><![CDATA[Learn how to build a fully interactive AI virtual avatar by combining real-time voice intelligence with lifelike digital humans. In this guide, you’ll explore how to connect conversational AI with expressive avatar rendering..]]></description><link>https://www.videosdk.live/blog/how-to-build-ai-virtual-avatars-using-anam-ai-and-videosdk-ai-voice-agents</link><guid isPermaLink="false">69c515c155831517a5a8a516</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 26 Mar 2026 11:33:51 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/03/thumbnail_avatar.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/03/thumbnail_avatar.png" alt="How to build AI Virtual Avatars using Anam-AI and VideoSDK AI Voice Agents"/><p>Building AI virtual avatars is no longer about stitching together experimental tools it’s about delivering a complete, real-time conversational experience where voice, intelligence, and visual presence work as one system.</p><p>By combining Anam-AI’s lifelike digital humans with VideoSDK AI Voice Agents, developers can create interactive avatars that don’t just speak they listen, reason, respond, and express themselves visually in real time.</p><p>In a production setting, the avatar is not merely a visual layer. It is the final stage of the conversational pipeline where AI responses become human presence. Once a model generates speech, that audio must be delivered with minimal latency and synchronized perfectly with facial animation. Even small delays can break immersion, disrupt turn-taking, and make the interaction feel artificial.</p><p><a href="https://anam.ai/" rel="noreferrer">AnamAI</a> is designed specifically for real-time avatar rendering. It converts live audio streams into natural facial motion, lip synchronization, and expressive behavior, allowing AI agents to appear as believable digital humans. Meanwhile, VideoSDK handles the conversational backbone , capturing user audio, routing it to AI models, streaming responses back, and managing real-time sessions at scale.</p><p>In this guide, we’ll walk through how to build a fully interactive AI virtual avatar using<a href="https://docs.videosdk.live/ai_agents/plugins/avatar/anam-ai" rel="noreferrer"> AnamAI</a> and <a href="https://docs.videosdk.live/ai_agents/plugins/avatar/anam-ai" rel="noreferrer">VideoSDK AI Voice Agents</a>, connect a real-time speech model, enable tool usage, and deploy an avatar that can hold natural conversations with users.</p><h2 id="why-use-anamai-videosdk-for-ai-avatars">Why Use AnamAI + VideoSDK for AI Avatars?</h2><ul><li><strong>Real-time talking avatars</strong> with natural lip-sync</li><li><strong>End-to-end voice interaction pipeline</strong></li><li><strong>Low-latency streaming</strong>, suitable for live conversations</li><li><strong>Tool-enabled intelligence</strong> (weather, search, actions)</li><li><strong>Production-ready infrastructure</strong></li></ul><p>If you’re already building conversational AI, adding a visual avatar layer can dramatically improve engagement and trust. You can use either a <a href="https://github.com/videosdk-live/agents/blob/main/examples/avatar/anam_realtime_example.py" rel="noreferrer">realtime pipeline </a>or a <a href="https://github.com/videosdk-live/agents/blob/main/examples/avatar/anam_cascading_example.py" rel="noreferrer">cascading pipeline</a>.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/03/anam--1-.png" class="kg-image" alt="How to build AI Virtual Avatars using Anam-AI and VideoSDK AI Voice Agents" loading="lazy" width="3563" height="2019"/></figure><h2 id="let%E2%80%99s-get-started">Let’s get started</h2><h3 id="step-1-create-and-activate-the-virtual-environment">Step 1 : Create and activate the virtual environment</h3><p>macOS/Linux</p><pre><code class="language-python">python3.12 -m venv venv
source venv/bin/activate</code></pre><p>windows</p><pre><code class="language-python">python -m venv venv
venv\Scripts\activate</code></pre><h3 id="step-2-install-all-dependencies">Step 2 : Install all dependencies</h3><p>Install the required VideoSDK Agents package:</p><pre><code class="language-python">pip install"videosdk-agents[anam,google]"</code></pre><p>Install any additional plugins you plan to use (Anam avatar plugin is included in the ecosystem).</p><h3 id="step-3-authentication">Step 3 : Authentication</h3><p>You will need:</p><ul><li><a href="https://lab.anam.ai/api-keys">AnamAI API key</a> and Avatar ID</li><li><a href="https://aistudio.google.com/">Google API key</a> (for Gemini realtime model)</li><li><a href="https://dub.sh/zXYQt7V">VideoSDK authentication token</a></li></ul><pre><code class="language-python">ANAM_API_KEY=your_anam_key
ANAM_AVATAR_ID=your_avatar_id
GOOGLE_API_KEY=your_google_key
VIDEOSDK_AUTH_TOKEN=your_token</code></pre><p>When using a .env file, the SDK automatically reads credentials you don’t need to pass them manually.</p><h3 id="step-4-create-a-mainpy-file">Step 4 : Create a <a href="http://main.py/" rel="noopener noreferrer">main.py</a> file</h3><p>In this example, we’ve used a <a href="https://github.com/videosdk-live/agents/blob/main/examples/avatar/anam_realtime_example.py" rel="noreferrer">realtime pipeline</a>. However, if you want to use a cascading pipeline, you can <a href="https://github.com/videosdk-live/agents/blob/main/examples/avatar/anam_cascading_example.py" rel="noreferrer">follow this example</a>.</p><pre><code class="language-python">import aiohttp
import os

from videosdk.agents import Agent, AgentSession, RealTimePipeline, function_tool, JobContext, RoomOptions, WorkerJob
from videosdk.plugins.google import GeminiRealtime, GeminiLiveConfig
from videosdk.plugins.anam import AnamAvatar
import logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", handlers=[logging.StreamHandler()])

@function_tool
async def get_weather(
    latitude: str,
    longitude: str,
):
    """Called when the user asks about the weather. This function will return the weather for
    the given location. When given a location, please estimate the latitude and longitude of the
    location and do not ask the user for them.

    Args:
        latitude: The latitude of the location
        longitude: The longitude of the location
    """
    print("###Getting weather for", latitude, longitude)
    url = f"https://api.open-meteo.com/v1/forecast?latitude={latitude}&amp;longitude={longitude}&amp;current=temperature_2m"
    weather_data = {}
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            if response.status == 200:
                data = await response.json()
                print("###Weather data", data)
                weather_data = {
                    "temperature": data["current"]["temperature_2m"],
                    "temperature_unit": "Celsius",
                }
            else:
                raise Exception(
                    f"Failed to get weather data, status code: {response.status}"
                )

    return weather_data


class MyVoiceAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions="You are VideoSDK's AI Avatar Voice Agent with real-time capabilities. You are a helpful virtual assistant with a visual avatar that can answer questions about weather help with other tasks in real-time.",
            tools=[get_weather]
        )

    async def on_enter(self) -&gt; None:
        await self.session.say("Hello! I'm your real-time AI avatar assistant powered by VideoSDK. How can I help you today?")
    
    async def on_exit(self) -&gt; None:
        await self.session.say("Goodbye! It was great talking with you!")
        

async def start_session(context: JobContext):
    # Initialize Gemini Realtime model
    model = GeminiRealtime(
        model="gemini-2.5-flash-native-audio-preview-12-2025",
        # When GOOGLE_API_KEY is set in .env - DON'T pass api_key parameter
        # api_key="AIXXXXXXXXXXXXXXXXXXXX", 
        config=GeminiLiveConfig(
            voice="Leda",  # Puck, Charon, Kore, Fenrir, Aoede, Leda, Orus, and Zephyr.
            response_modalities=["AUDIO"]
        )
    )

    # Initialize Anam Avatar
    anam_avatar = AnamAvatar(
        api_key=os.getenv("ANAM_API_KEY"),
        avatar_id=os.getenv("ANAM_AVATAR_ID"),
    )

    # Create pipeline with avatar
    pipeline = RealTimePipeline(model=model, avatar=anam_avatar)

    session = AgentSession(agent=MyVoiceAgent(), pipeline=pipeline)

    await session.start(wait_for_participant=True, run_until_shutdown=True)

def make_context() -&gt; JobContext:
    room_options = RoomOptions(
        room_id="&lt;room_id&gt;",
        name="Anam Avatar Realtime Agent",
        playground=False 
    )

    return JobContext(room_options=room_options)


if __name__ == "__main__":
    job = WorkerJob(entrypoint=start_session, jobctx=make_context)
    job.start()</code></pre><h3 id="step-5-run-the-file">Step 5 : Run the file</h3><pre><code class="language-python">python main.py</code></pre><h3 id="step-6-deploy-your-ai-agent">Step 6 : Deploy your AI Agent</h3><p>Follow <a href="https://www.videosdk.live/blog/how-to-deploy-your-ai-voice-agents-in-videosdk" rel="noopener noreferrer">this guide</a> to deploy your AI voice agent. We’ll walk you through every step required to set up, configure, and launch your agent successfully.</p><h2 id="real-world-applications">Real-World Applications</h2><p>AI virtual avatars unlock a wide range of real-time interactive experiences. By combining conversational AI with expressive digital humans, you can build applications such as:</p><ul><li><strong>Customer support agents</strong> that provide instant, human-like assistance</li><li><strong>Virtual tutors and trainers</strong> for personalized learning experiences</li><li><strong>Healthcare assistants</strong> that guide patients and answer common questions</li><li><strong>AI sales representatives</strong> that engage and qualify leads in real time</li><li><strong>Event hosts and presenters</strong> for webinars, conferences, and live streams</li><li><strong>Interactive entertainment characters</strong> for games and immersive experiences</li></ul><p>In any scenario where <strong>human-like communication improves engagement</strong>, AI avatars can significantly enhance the user experience.</p><h2 id="conclusion">Conclusion</h2><p>AI avatars represent the next evolution of conversational interfaces. Text chatbots lack presence, and voice assistants lack visual connection, but real-time digital humans combine intelligence, speech, and embodiment into a single experience.</p><p>With AnamAI providing expressive visual rendering and VideoSDK delivering the real-time conversational infrastructure, developers can now build production-ready virtual humans that feel natural, responsive, and engaging.</p><p>Plug in your model, choose an avatar, and bring your AI to life.</p><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ul><li>You can also use cascading pipeline instead of realtime pipeline - <a href="https://github.com/videosdk-live/agents/blob/main/examples/avatar/anam_cascading_example.py">see full working example here</a></li><li>For more information visit <a href="https://docs.videosdk.live/ai_agents/plugins/avatar/anam-ai">anamAI documentation</a></li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction">deploy your AI Agents</a>.</li><li>Sign up at&nbsp;<a href="https://dub.sh/zXYQt7V">VideoSDK Dashboard</a></li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[How to Deploy Your VideoSDK AI Voice Agents]]></title><description><![CDATA[Agent Cloud simplifies the deployment process by letting you package, deploy, and manage your agent in the cloud using a simple CLI workflow. In this guide, you'll learn how to move your agent from local development to a production-ready deployment.]]></description><link>https://www.videosdk.live/blog/how-to-deploy-your-ai-voice-agents-in-videosdk</link><guid isPermaLink="false">698f128355831517a5a8a286</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 12 Mar 2026 05:47:20 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/03/deployment.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/03/deployment.png" alt="How to Deploy Your VideoSDK AI Voice Agents"/><p>You built an AI agent. It works locally. Then reality hits.</p><p>How do you run it 24/7?<br>How do you scale it?<br>How do you secure keys, manage versions, and handle real users?</br></br></p><p>Productionizing an agent is not just “docker build &amp;&amp; run.”<br>It’s infrastructure, orchestration, secrets, sessions, regions, and reliability.</br></p><p>Agent Cloud removes that entire layer.<br>With a single CLI workflow, you can package your agent, deploy it globally, run live sessions, and manage everything from versioning to scaling without building your own backend platform.</br></p><p>This guide walks through the complete deployment process, from local code to a production-ready agent running in the cloud.</p><ul><li>Build and push your agent container</li><li>Deploy and version your agent</li><li>Monitor and control deployments</li><li>Use the VideoSDK dashboard for low-code management</li></ul><p>By the end, your agent will be live and ready to serve users.</p><h2 id="prerequisites">Prerequisites</h2><p>Before starting, make sure you have:</p><ul><li><a href="https://www.docker.com/" rel="noreferrer">Docker</a> installed and running</li><li>A <a href="https://dub.sh/zXYQt7V" rel="noreferrer">VideoSDK account</a></li><li>An AI agent project with a Dockerfile</li></ul><h2 id="1-install-the-cli">1.  Install the CLI</h2><p>To get started with VideoSDK Agent Cloud, you need to install the VideoSDK CLI. There are two ways to install it:</p><h3 id="using-pip">Using pip</h3><p>You can also install the VideoSDK CLI using&nbsp;<code>pip</code>, the Python package manager.</p><pre><code class="language-python">pip install videosdk-cli</code></pre><h3 id="using-curl">Using curl</h3><p>This is the quickest way to install the VideoSDK CLI on Linux and macOS.</p><pre><code class="language-python">curl -fsSL https://videosdk.live/install | bash</code></pre><h2 id="2-authenticate-the-cli">2. Authenticate the CLI</h2><p>First, connect your local environment to your account.</p><pre><code class="language-python">videosdk auth login</code></pre><p>The CLI opens a browser window where you approve the authentication request. Once approved, a secure token is stored locally and reused for future commands.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/auth-cli.png" class="kg-image" alt="How to Deploy Your VideoSDK AI Voice Agents" loading="lazy" width="3306" height="1458"/></figure><h2 id="initialize-your-agent">Initialize your agent</h2><p>The&nbsp;<code>init</code>&nbsp;command sets up a new agent deployment by creating an agent and a deployment in VideoSDK cloud. It also generates a&nbsp;<code>videosdk.yaml</code>&nbsp;configuration file in your project directory.</p><pre><code class="language-python">videosdk agent init --name my-agent</code></pre><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/Screenshot-2026-02-24-at-11.40.24-AM.png" class="kg-image" alt="How to Deploy Your VideoSDK AI Voice Agents" loading="lazy" width="2232" height="294"/></figure><h3 id="videosdkyaml-structure">videosdk.yaml Structure</h3><p>The generated&nbsp;<code>videosdk.yaml</code>&nbsp;file will look like this:</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/Screenshot-2026-02-24-at-11.41.22-AM.png" class="kg-image" alt="How to Deploy Your VideoSDK AI Voice Agents" loading="lazy" width="462" height="280"/></figure><p>Add this agent_id from the videosdk.yaml file to the code in this section </p><pre><code class="language-python">if __name__ == "__main__":
    job = WorkerJob(entrypoint=start_session, jobctx=make_context,
        options=Options(
            register=True,
            agent_id="your-agent_id"
        )
    )
    job.start()</code></pre><h2 id="3-build-your-agent-container">3. Build Your Agent Container</h2><p>Agent Cloud runs agents as containers. Use the CLI to build a Docker image for your agent.</p><p>You need to log in to Docker first. After logging in, you will get your Docker ID. Replace <code>myrepo</code> with your Docker ID and use it in all the commands below.</p><pre><code class="language-python">videosdk agent build --image myrepo/myagent:v1
</code></pre><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/Screenshot-2026-02-24-at-12.06.58-PM.png" class="kg-image" alt="How to Deploy Your VideoSDK AI Voice Agents" loading="lazy" width="2206" height="986"/></figure><h3 id="what-happens">What Happens</h3><ol><li><strong>Cloud Creation</strong>: The CLI communicates with VideoSDK cloud to create a new agent and a corresponding deployment.</li><li><strong>Config Generation</strong>: A&nbsp;<code>videosdk.yaml</code>&nbsp;file is created in your current directory. This file contains the unique IDs for your agent and deployment.</li><li><strong>Project Setup</strong>: Your local project is now linked to the cloud resources.</li></ol><h2 id="4-push-the-image-to-a-registry">4. Push the Image to a Registry</h2><p>Before deployment, the image must be available in a container registry.</p><pre><code class="language-python">videosdk agent push --image myrepo/myagent:v1</code></pre><p>Supported registries include Docker Hub, GitHub Container Registry, AWS ECR, Google Container Registry, and Azure.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/Screenshot-2026-02-24-at-11.50.40-AM.png" class="kg-image" alt="How to Deploy Your VideoSDK AI Voice Agents" loading="lazy" width="2228" height="624"/></figure><p>For private registries:</p><pre><code class="language-python">videosdk agent push \
  --image ghcr.io/myorg/myagent:v1 \
  -u username \
  -p token</code></pre><h2 id="4-deploy-your-agent">4. Deploy Your Agent</h2><p>Create a new version of your agent on VideoSDK cloud.</p><pre><code class="language-python">videosdk agent deploy --image myrepo/myagent:v1
</code></pre><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/Screenshot-2026-02-24-at-11.53.51-AM.png" class="kg-image" alt="How to Deploy Your VideoSDK AI Voice Agents" loading="lazy" width="2216" height="490"/></figure><p>This creates a <strong>versioned deployment</strong> with configurable compute resources and scaling.</p><p>You can customize:</p><ul><li>Replica limits</li><li>Compute profile</li><li>Deployment region</li><li>Secrets</li><li>Version tags</li></ul><pre><code class="language-python">videosdk agent deploy my-version \
  --image myrepo/myagent:v1 \
  --profile cpu-medium \
  --region in002
</code></pre><h2 id="5-manage-versions">5. Manage Versions</h2><p>Each deployment creates a version that can be activated, updated, or rolled back.</p><p>List versions:</p><pre><code class="language-python">videosdk agent version list
</code></pre><p>Activate a version:</p><pre><code class="language-python">videosdk agent version activate -v ver123</code></pre><p>Update scaling:</p><pre><code class="language-python">videosdk agent version update -v ver123 \
  --min-replica 2 \
  --max-replica 10
</code></pre><p>Check status:</p><pre><code class="language-python">videosdk agent version status -v ver123
</code></pre><h2 id="6-secure-configuration-with-secrets">6. Secure Configuration with Secrets</h2><p>Agents often need API keys or credentials.</p><p>Create a secret set from a <code>.env</code> file:</p><pre><code class="language-python">videosdk agent secrets my-secrets create --file .env
</code></pre><p>Use it during deployment:</p><pre><code class="language-python">videosdk agent deploy \
  --image myrepo/myagent:v1 \
  --env-secret my-secrets
</code></pre><p>Secrets are injected securely as environment variables at runtime.</p><h2 id="7-start-a-live-agent-session">7. Start a Live Agent Session</h2><p>Once deployed, you can run the agent in a room.</p><pre><code class="language-python">videosdk agent session start -v ver123
</code></pre><p>This launches a live instance of your agent.</p><p>You can specify a room:</p><pre><code class="language-python">videosdk agent session start -v ver123 -r support-room
</code></pre><p>Stop the session:</p><pre><code class="language-python">videosdk agent session stop -r support-room
</code></pre><p>List sessions:</p><pre><code class="language-python">videosdk agent sessions list
</code></pre><h2 id="8-manage-everything-from-the-dashboard-low-code-option">8. Manage Everything from the Dashboard (Low-Code Option)</h2><p>If you prefer a visual workflow, the VideoSDK dashboard provides full control over deployments.</p><p>From the dashboard you can:</p><ul><li>View all agents</li><li>Monitor versions and replicas</li><li>Inspect logs and sessions</li><li>Manage secrets</li><li>Start or stop deployments</li><li>Configure regions and scaling</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/Screenshot-2026-02-24-at-1.38.11-PM.png" class="kg-image" alt="How to Deploy Your VideoSDK AI Voice Agents" loading="lazy" width="2926" height="1220"/></figure><p>The CLI and dashboard stay fully synchronized changes made in one are reflected in the other.</p><h2 id="why-this-workflow-matters">Why This Workflow Matters</h2><p>Traditional deployment of real-time AI systems requires stitching together multiple components:</p><ul><li>Container orchestration</li><li>Autoscaling</li><li>Secrets management</li><li>Session routing</li><li>Infrastructure monitoring</li><li>Regional deployment</li></ul><p>Agent Cloud abstracts this complexity into a developer-friendly workflow while preserving control and flexibility.</p><p>You focus on building intelligence. The platform handles running it reliably.</p><h2 id="final-thoughts">Final Thoughts</h2><p>With the VideoSDK CLI, you can go from a local prototype to a production-ready deployment in minutes complete with scaling, versioning, and live sessions.</p><p>Whether you prefer CLI automation or dashboard control, Agent Cloud provides a streamlined path to running AI agents in the real world.</p><h2 id="next-steps-and-resources">Next Steps and Resources</h2><ul><li>Explore more about deployments through <a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">the docs</a></li><li>Sign up at VideoSDK -&nbsp;<a href="https://dub.sh/BVOvGNr" rel="noreferrer">dashboard</a></li><li> Have feedback or ideas? Comment below or join our Discord to build and ship AI call agents faster with VideoSDK&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[Introducing VideoSDK Agent Cloud: Deploy Voice Agents at Production Scale]]></title><description><![CDATA[In this launch, VideoSDK introduces Deployments a purpose-built infrastructure layer for running AI voice agents reliably in production. Designed to handle scaling, concurrency, latency, and uptime out of the box.]]></description><link>https://www.videosdk.live/blog/introducing-videosdk-agent-cloud-deploy-voice-agents-at-production-scale</link><guid isPermaLink="false">699ebca155831517a5a8a3c3</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 26 Feb 2026 12:01:24 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/02/deployment.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/02/deployment.png" alt="Introducing VideoSDK Agent Cloud: Deploy Voice Agents at Production Scale"/><p>AI innovation doesn’t slow down in production  but infrastructure often does.<br>As agents move from demos  to real users, the challenges shift from building intelligence to running it reliably at scale. Concurrency spikes, cold starts, regional latency, uptime guarantees , these aren’t model problems. They’re infrastructure problems.</br></p><p>At VideoSDK, we believe AI teams shouldn’t have to become infrastructure teams to ship production systems.</p><p>Today, we’re introducing <a href="https://docs.videosdk.live/ai_agents/deployments/agent-cloud/cli/deploy" rel="noreferrer"><strong>Cloud</strong> <strong>Deployments</strong></a> - a purpose-built infrastructure layer for running AI Voice agents in the real world. Designed for scale, reliability, and operational visibility, Deployments handle the complexity of provisioning, scaling, and maintaining runtime environments so your agents can perform consistently under real traffic through <a href="https://docs.videosdk.live/ai_agents/deployments/agent-cloud/cli/deploy" rel="noreferrer">agent runtime dashboard</a> and <a href="https://docs.videosdk.live/ai_agents/deployments/agent-cloud/cli/deploy" rel="noreferrer">CLI.</a></p><p>From startup MVPs to enterprise-grade workloads, this is the foundation that lets AI products move to production - without operational overhead.</p><h2 id="who-this-is-for">Who This Is For</h2><p>Deployments are built for teams shipping real AI products:</p><ul><li><strong>Voice AI builders</strong> running real-time conversations</li><li><strong>AI startups</strong> moving from demo → production</li><li><strong>Infra &amp; platform teams</strong> managing scale and reliability</li><li><strong>Enterprises</strong> deploying mission-critical automation</li></ul><h2 id="from-local-agent-to-production-endpoint">From Local Agent to Production Endpoint </h2><p>With Deployments, you can:</p><ul><li>Launch agents in dedicated compute environments</li><li>Scale automatically based on active sessions</li><li>Choose performance tiers based on workload</li><li>Run globally with regional isolation</li><li>Maintain predictable performance under load</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/blog3.png" class="kg-image" alt="Introducing VideoSDK Agent Cloud: Deploy Voice Agents at Production Scale" loading="lazy" width="2054" height="1388"/></figure><h2 id="deploy-in-minutesdashboard-or-cli">Deploy in Minutes - <a href="https://dub.sh/zXYQt7V" rel="noreferrer">Dashboard</a> or CLI</h2><p>Deployments support both visual and developer-first workflows.</p><h3 id="1-deploy-from-the-dashboard-fastest-path">1) Deploy from the <a href="https://dub.sh/zXYQt7V" rel="noreferrer">Dashboard</a> (Fastest Path)</h3><p><a href="https://dub.sh/zXYQt7V" rel="noreferrer">The dashboard</a> provides a guided experience where configuration, provisioning, and launch are handled automatically if building agents from runtime dashboard.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/blog.png" class="kg-image" alt="Introducing VideoSDK Agent Cloud: Deploy Voice Agents at Production Scale" loading="lazy" width="2360" height="1464"/></figure><p>After selecting CPU Profile options and region, your agent is deployed to a managed environment no manual setup required.</p><h3 id="compute-plans-made-simple"><strong>Compute Plans Made Simple</strong></h3><p>We designed compute options to be intuitive not cloud-jargon heavy.</p><ul><li>Agent Session CPU-Small (0.5 Cores, 1 GB)</li><li>Agent Session CPU-Medium (1 Core, 2 GB)</li><li>Agent Session CPU-Large (2 Cores, 3 GB)</li><li>Agent Reserved CPU-Small (0.5 Cores, 1 GB)</li><li>Agent Reserved CPU-Medium (1 Core, 2 GB)</li><li>Agent Reserved CPU-Large (2 Cores, 3 GB)</li><li>Agent Observability - Currently free</li></ul><h3 id="2-deploy-via-cli-automation-friendly">2) <a href="https://docs.videosdk.live/ai_agents/deployments/agent-cloud/cli/deploy" rel="noreferrer">Deploy via CLI </a>(Automation-Friendly)</h3><p>For teams integrating deployments into CI/CD pipelines or developer workflows, the <a href="https://docs.videosdk.live/ai_agents/deployments/agent-cloud/cli/deploy" rel="noreferrer">CLI </a>offers full control. Deployments can be launched with a few commands to configure and start the runtime environment.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/blog2.png" class="kg-image" alt="Introducing VideoSDK Agent Cloud: Deploy Voice Agents at Production Scale" loading="lazy" width="3162" height="905"/></figure><h2 id="deployment-observability-control">Deployment Observability &amp; Control</h2><p>Monitor and manage your Agent Deployment end-to-end from the dashboard ,view active and historical sessions, track deployed versions, securely configure environment secrets, and inspect real-time logs and errors to debug issues, audit behavior, and ensure reliable production performance.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/blog5.png" class="kg-image" alt="Introducing VideoSDK Agent Cloud: Deploy Voice Agents at Production Scale" loading="lazy" width="1204" height="832"/></figure><h2 id="enterprise-onboarding-at-scale">Enterprise Onboarding at Scale</h2><p>Financial institutions and large enterprises often handle hundreds of customer onboarding interactions every day many of them time-sensitive and compliance-critical.</p>
<!--kg-card-begin: html-->
<p style="font-size:20px; line-height:1.7; margin:20px 0;">

  Imagine an organization like 
  <span style="
    color: #B87EED;
    padding: 4px 8px;
    border-radius: 6px;
    font-weight: 600;
  ">
    ICICI Prudential running 100+ AI-powered onboarding calls daily
  </span>. 

  Traffic fluctuates throughout the day. Peak hours demand higher concurrency. 
  Latency must stay low. Uptime is non-negotiable.

</p>
<!--kg-card-end: html-->
<p>Instead of managing servers, autoscaling groups, and regional failovers, teams focus on improving the onboarding experience.</p><p>Deployments ensure enterprise-grade reliability while keeping operations simple.</p><h3 id="build-smarter-deploy-faster-scale-without-limits">Build Smarter. Deploy Faster. Scale Without Limits.</h3><p>Deployments remove the hardest part of shipping AI systems: running them reliably in the real world. What once required complex infrastructure, scaling strategies, and constant operational oversight can now be done in minutes with performance and reliability built in.</p><p>Whether you're launching your first production agent, handling thousands of conversations, or powering mission-critical workflows, Deployments give you the confidence to scale without re-architecting or managing servers.</p><p>Start small with on-demand sessions. Move to always-on capacity as you grow. Expand across regions as your users scale. The platform evolves with you from MVP to enterprise.</p><p>Your team focuses on intelligence and experience. We handle the infrastructure.</p><p><strong>Deploy your agent, reach real users, and build the future of AI Voice without operational friction.</strong></p><h2 id="resources"><strong>Resources</strong></h2><ul><li>Read more about how to deploy agents through CLI - <a href="https://docs.videosdk.live/ai_agents/deployments/agent-cloud/cli/deploy" rel="noreferrer">docs link</a>.</li><li>Low-code <a href="https://dub.sh/zXYQt7V" rel="noreferrer">agent runtime dashboard for AI Voice Agents</a>.</li><li>Sign in to <a href="https://dub.sh/zXYQt7V" rel="noreferrer">VideoSDK Dashboard</a>.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[Product Updates - January 2026 : Managed Inference, Expanded AI Ecosystem, and Advanced SDK Improvements]]></title><description><![CDATA[Kick off 2026 with VideoSDK’s biggest updates yet. January brings VideoSDK-managed inference for AI Agents, expanded AI integrations, new agent evaluation tools, advanced video optimizations, and deeper support for IoT voice experiences .]]></description><link>https://www.videosdk.live/blog/product-updates-january-2026-managed-inference-expanded-ai-ecosystem-and-advanced-sdk-improvements</link><guid isPermaLink="false">69942bd555831517a5a8a2a7</guid><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 24 Feb 2026 11:18:19 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/02/2026.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/02/2026.png" alt="Product Updates - January 2026 : Managed Inference, Expanded AI Ecosystem, and Advanced SDK Improvements"/><p>A complete recap of our biggest platform and product updates from January 2026.</p><p>Welcome to the January edition of the VideoSDK Monthly Updates! We’re starting 2026 with a major leap forward in AI infrastructure, voice capabilities, and developer control across the platform.</p><p>This month introduces a powerful new milestone: <a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference" rel="noreferrer"><strong>VideoSDK-managed inference for AI Agents</strong></a>, dramatically expanding what you can build without managing complex AI pipelines. Alongside this, we’ve broadened our AI ecosystem, launched evaluation tooling for agent performance, delivered advanced video optimization across SDKs, and pushed deeper into IoT voice experiences.</p><p>Let’s dive in.</p><h2 id="videosdk-managed-inference-in-agents-sdk">VideoSDK-Managed Inference In Agents SDK</h2><p>The biggest highlight this month is the launch of <a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference" rel="noreferrer"><strong>VideoSDK-managed inference support</strong></a> for Agents, a major step toward making real-time AI truly turnkey.</p><p>You can now run complete voice agent pipelines through the VideoSDK Gateway, eliminating the need to orchestrate multiple AI providers yourself.</p><h3 id="cascading-pipeline-supported-models-stt-%E2%86%92-llm-%E2%86%92-tts">Cascading Pipeline Supported Models (STT → LLM → TTS)</h3><p>Fully managed routing across components:</p><ul><li><strong>Speech-to-Text:</strong> <a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference#sttgoogle" rel="noreferrer">Google</a>, <a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference#stt-configuration" rel="noreferrer">SarvamAI</a>, Deepgram</li><li><strong>Large Language Models:</strong> <a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference#llmgoogle" rel="noreferrer">Google-supported models</a></li><li><strong>Text-to-Speech:</strong> <a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference#ttsgoogle" rel="noreferrer">Google</a>, <a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference#ttssarvam" rel="noreferrer">SarvamAI</a>, Cartesia</li></ul><h3 id="realtime-pipeline-supported-models">Realtime Pipeline Supported Models</h3><ul><li>Powered by <a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference#realtimegemini" rel="noreferrer">Gemini Realtime</a></li><li>Enables ultra-low-latency conversational experiences</li></ul><p>This update transforms agents from DIY integrations into a <strong>managed AI platform experience</strong>, dramatically reducing infrastructure overhead and time to production.</p><h3 id="expanded-speech-audio-capabilities">Expanded Speech &amp; Audio Capabilities</h3><ul><li>ElevenLabs : <a href="https://docs.videosdk.live/ai_agents/plugins/tts/eleven-labs" rel="noreferrer">Enhanced TTS</a> with language control</li><li><a href="https://docs.videosdk.live/ai_agents/plugins/tts/cartesia-tts" rel="noreferrer">Cartesia</a> : Advanced generation configuration (emotion, speed, volume)</li></ul><p>Together, these integrations significantly expand the range of voices, languages, latency profiles, and quality options available for building conversational AI.</p><h2 id="introducing-agent-evaluation-benchmarking">Introducing Agent Evaluation &amp; Benchmarking</h2><p>Building agents is only half the challenge measuring their performance is equally critical.</p><p>This month introduces <a href="https://docs.videosdk.live/ai_agents/core-components/testing-and-evaluation" rel="noreferrer"><strong>videosdk-eval</strong></a>, a dedicated framework for testing and validating agent quality before production deployment.</p><p>Key capabilities include:</p><ul><li>Simulation of multi-turn conversations</li><li>Component-level evaluation (STT, LLM, TTS)</li><li>Latency tracking per component and end-to-end</li><li>Performance and quality benchmarking</li></ul>
<!--kg-card-begin: html-->
<iframe width="560" height="315" src="https://www.youtube.com/embed/hPAdAmCU2OA?si=V2FAQRjKji3rNx3B" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<h2 id="real-time-analytics-observability-improvements">Real-Time Analytics &amp; Observability Improvements</h2><p>Production AI systems require deep visibility into performance. January brings major upgrades to analytics across the agent platform.</p><p>Enhancements include:</p><ul><li>Improved latency tracking and tracing</li><li>Token usage collection for major AI providers</li><li>Real-time analytics streaming via PubSub</li><li>Centralized playground analytics mode</li></ul><p>These capabilities provide actionable insights for optimizing cost, performance, and user experience.</p><h2 id="advanced-video-optimization-across-sdks">Advanced Video Optimization Across SDKs</h2><p>Our core RTC SDKs received significant upgrades to video quality control and monitoring.</p><h3 id="ios-sdkreliability-lifecycle-improvements"><a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer">iOS SDK</a> - Reliability &amp; Lifecycle Improvements</h3><p>New capabilities enhance stability for production apps:</p><ul><li>Explicit FAILED meeting state</li><li>Bulk removal of event listeners</li><li>Deterministic media track lifecycle management</li><li>Automatic restoration of microphone and camera states after reconnection</li></ul><h3 id="android-sdkimproved-observability"><a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer">Android SDK</a> - Improved Observability</h3><p>Android updates focused on developer experience and runtime stability:</p><ul><li>Enhanced trace messaging</li><li>Safer listener management</li><li>Thread-safety improvements</li></ul><h2 id="expanding-into-iot-voice-experiences">Expanding Into IoT Voice Experiences</h2><p>January also marks continued progress toward embedded real-time communication.</p><h3 id="iot-sdk-enhancements"><a href="https://docs.videosdk.live/iot/guide/video-and-audio-calling-api-sdk/iot-sdk" rel="noreferrer">IoT SDK</a> Enhancements</h3><ul><li>Acoustic Echo Cancellation (AEC) support for ESP32-S3-Korvo-V2</li></ul><p>This enables clearer voice interactions on hardware devices such as smart assistants, kiosks, and industrial systems.</p><h2 id="%E2%9C%A8-what-this-means-for-developers">✨ What This Means for Developers</h2><p>January’s updates move the platform decisively toward a future where developers can build sophisticated real-time AI systems without managing infrastructure complexity.</p><p>From fully managed inference pipelines to expanded AI providers, evaluation tooling, and advanced media controls, these improvements significantly reduce the gap between prototype and production.</p><h2 id="sdk-sketches">SDK Sketches</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/jan-product-update.png" class="kg-image" alt="Product Updates - January 2026 : Managed Inference, Expanded AI Ecosystem, and Advanced SDK Improvements" loading="lazy" width="1344" height="768"/></figure><h2 id="whats-next">What's Next?</h2><p>As we continue through 2026, our focus remains on making real-time AI and communication infrastructure more powerful, flexible, and accessible to developers worldwide.</p><p>Expect deeper integrations, smarter agents, and continued improvements across performance, reliability, and developer experience.</p><h2 id="new-content-and-resources">New Content and Resources</h2><p>Explore our latest tutorials and blogs to help you build more advanced AI agents and voice workflows.</p><ul><li>Voicemail detection <a href="https://youtu.be/KSzxtUd5ULU" rel="noreferrer">tutorial</a> - Learn how to automatically detect voicemails and trigger intelligent callbacks or alternate flows.</li><li>Multi agent switching <a href="https://youtu.be/kF82zCIfT3s" rel="noreferrer">video tutorial</a> - See how to automatically hand off conversations between specialized agents while preserving context.</li><li>Testing and eval<a href="https://youtu.be/hPAdAmCU2OA" rel="noreferrer"> tutorial</a> - A step-by-step guide to validating agent performance using evaluation tools and simulated conversations.</li></ul><p>📝 Blogs</p><ul><li>Testing and <a href="https://www.videosdk.live/blog/introducing-testing-and-evaluation-in-ai-voice-agents" rel="noreferrer">eval blog</a> - Best practices for measuring quality, latency, and reliability before deploying to production.</li><li>Voicemail <a href="https://www.videosdk.live/blog/how-to-enable-voice-mail-detection-in-ai-voice-agents" rel="noreferrer">detection blog</a> - How to build smarter telephony agents that understand call outcomes.</li><li>Multi agent <a href="https://www.videosdk.live/blog/how-to-build-an-ai-voice-system-using-real-time-multi-agent-switching" rel="noreferrer">switching blog</a> - Designing complex workflows with specialized agents collaborating in real time.</li></ul>
<!--kg-card-begin: html-->
<style>
   :root {
      --primary: #A497D9;
      --bg: #050608;
      --card-bg: #111217;
      --text-main: #E0E0E0;
      --text-muted: #A0A0A0;
      --border: #22242C;
    }
     .cta {
      font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      line-height: 1.7;
      color: var(--text-main);
      background-color: var(--bg);
      margin: 0;
      padding: 0;
    }


      .cta-button {
        background-color: var(--primary);
        color: #000000;
        padding: 6px 20px;
        border-radius: 6px;
        font-size: 15px;
        font-weight: bold;
        display: inline-block;
        text-decoration: none;
    }
    .cta-box {
      text-align: left;
      background: linear-gradient(135deg, #111217 0%, #1a1b23 100%);
      padding: 40px;
      border-radius: 12px;
      border: 1px solid var(--primary);
      margin: 60px 0;
    }
</style>
<div class="cta">
<div class="cta-box">
      <h3>Ready to Build with the Latest?</h3>
      <p>Upgrade your SDKs to the latest versions to take advantage of all these new features and improvements.</p>
      <a href="https://discord.com/invite/Gpmj6eCq5u" class="cta-button">Join our Discord Community</a>
    </div></div>

<!--kg-card-end: html-->
<h2 id=""/>]]></content:encoded></item><item><title><![CDATA[Announcing VideoSDK Inference: One Magic API for Every Voice AI Model]]></title><description><![CDATA[We’re thrilled to announce Inferencing in VideoSDK AI Voice Agents a unified way to run STT, LLM, TTS, and Realtime models directly inside your voice pipeline without managing multiple accounts through Agent Runtime Dashboard and Python Agents SDK.]]></description><link>https://www.videosdk.live/blog/announcing-videosdk-inference-one-magic-api-for-every-voice-ai-model</link><guid isPermaLink="false">697c971555831517a5a8a12f</guid><category><![CDATA[AI voice agent]]></category><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 16 Feb 2026 06:05:52 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/02/image--49-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/02/image--49-.png" alt="Announcing VideoSDK Inference: One Magic API for Every Voice AI Model"/><p>Building AI voice agents has always been powerful, but slow. You had models STT, LLMs, TTS and the tools to use them. But maintaining accounts across multiple vendors for speech recognition, language models, and speech synthesis, each with its own keys, quotas, billing, and APIs was a major challenge.</p><p><strong>Today, that changes.</strong></p><p>We’re thrilled to announce <strong>Inferencing in VideoSDK AI Voice Agents</strong> a unified way to run STT, LLM, TTS, and Realtime models <strong>directly inside your voice pipeline</strong> without managing multiple accounts through <a href="https://dub.sh/zXYQt7V" rel="noreferrer">Agent Runtime Dashboard</a> and <a href="https://github.com/videosdk-live/agents" rel="noreferrer">Python Agents SDK</a>.</p><p>Inferencing works in both the <strong>CascadingPipeline</strong> and the <strong>RealtimePipeline</strong>, giving you full flexibility to build modular or fully streaming voice agents. Whether you want incremental transcripts, staged execution, or fully native realtime audio, Inferencing makes it easy.</p><h2 id="what-is-videosdk-inference">What is VideoSDK Inference?</h2><p><strong>VideoSDK Inference</strong> is a managed gateway that gives you access to multiple AI models. All <strong>without providing your own API keys</strong> for providers like Sarvam AI or Google Gemini.</p><p>Authentication, routing, retries, and billing are handled by VideoSDK usage is simply charged against your <strong>VideoSDK account balance</strong>.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/inference-architecture-1.png" class="kg-image" alt="Announcing VideoSDK Inference: One Magic API for Every Voice AI Model" loading="lazy" width="3801" height="1176"/></figure><h3 id="supported-categories">Supported Categories</h3><ul><li><strong>STT</strong>: Sarvam, Google, Deepgram</li><li><strong>LLMs</strong>: Google Gemini</li><li><strong>TTS</strong>: Sarvam, Google, Cartesia</li><li><strong>Realtime</strong>: Gemini Native Audio</li></ul><h1 id="inferencing-via-agent-runtime-dashboard">Inferencing via Agent Runtime Dashboard</h1><p>Inferencing in VideoSDK is now fully accessible through the<a href="https://dub.sh/zXYQt7V" rel="noreferrer"> dashboard,</a> giving developers direct control over model selection and pipeline configuration without needing to manage infrastructure manually.</p><p>From the <a href="https://dub.sh/zXYQt7V" rel="noreferrer">dashboard</a>, developers can:</p><ul><li><strong>Select STT, LLM, TTS, or Realtime models</strong> and enable them in the pipeline with a single click.</li><li><strong>Switch providers instantly</strong>, allowing rapid experimentation and iteration .</li><li><strong>Attach deployment endpoints</strong> for web or telephony, making the agent immediately accessible to users.</li></ul><p>With this approach, ideas move from configuration to <strong>live, interactive conversations in minutes</strong>, making it possible to test new workflows, swap models, or iterate on conversational design almost instantly.</p>
<!--kg-card-begin: html-->
<iframe width="560" height="315" src="https://www.youtube.com/embed/2XvhVJETSrU?si=sgy6ywKrF4Pp3v5z" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<h1 id="inferencing-via-code-agents-sdk">Inferencing via Code (Agents SDK)</h1><p>With VideoSDK Inferencing, developers can now integrate STT, LLM, TTS, and Realtime models directly into their voice agents all handled inside the VideoSDK. This enables rapid experimentation, modular pipelines, and low-latency real-time conversations.</p><h3 id="installation">Installation</h3><p>The Inference plugin is included in the core <a href="https://pypi.org/project/videosdk-agents/" rel="noreferrer">VideoSDK Agents SDK</a>. Install it via</p><pre><code class="language-python">pip install videosdk-agents
</code></pre><h3 id="importing-inference-classes">Importing Inference Classes</h3><p>You can import the Inference classes directly from <code>videosdk.agents.inference</code>:</p><pre><code class="language-python">from videosdk.agents.inference import STT, LLM, TTS, Realtime
</code></pre><h3 id="cascadingpipeline-example">CascadingPipeline Example</h3><p>The <a href="https://docs.videosdk.live/ai_agents/core-components/cascading-pipeline" rel="noreferrer"><strong>CascadingPipeline</strong></a> is ideal for modular, stage-by-stage processing. Here’s an example of building a simple agent using STT, LLM, and TTS via the VideoSDK Inference Gateway:</p><pre><code class="language-python">pipeline = CascadingPipeline(
        stt=STT.sarvam(model_id="saarika:v2.5", language="en-IN"),
        llm=LLM.google(model="gemini-2.5-flash"),
        tts=TTS.sarvam(model_id="bulbul:v2", speaker="anushka", language="en-IN"),
        vad=SileroVAD()
    )
</code></pre><h3 id="realtimepipeline-example">RealTimePipeline Example</h3><p>For <strong>low-latency, fully streaming voice agents</strong>, the <a href="https://docs.videosdk.live/ai_agents/core-components/realtime-pipeline" rel="noreferrer">RealTimePipeline</a> handles Realtime inference with minimal delay. Here’s an example using Gemini Live Native Audio:</p><pre><code class="language-python">pipeline = RealTimePipeline(
        model=Realtime.gemini(
            model="gemini-2.5-flash-native-audio-preview-12-2025",
            voice="Puck",
            language_code="en-US",
            response_modalities=["AUDIO"],
            temperature=0.7
        )
    )</code></pre><p>With this approach, developers retain:</p><ul><li><strong>Full programmatic control</strong> over pipeline stages, model parameters, and execution behavior.</li><li><strong>Modular provider replacement</strong>, making it easy to swap STT, LLM, or TTS engines.</li></ul><p>The result: a <strong>fully configurable, production-ready AI voice agent</strong> that can be deployed in minutes.</p><h1 id="conclusion">Conclusion</h1><p>Voice AI is no longer limited by model capability. It’s limited by how fast you can deploy it. With <strong>Inferencing in VideoSDK AI Voice Agents</strong>, deployment becomes effortless. Whether through the dashboard or programmatically via the SDK, you can <strong>build, select, enable, and go live</strong> in minutes.</p><p>The era of modular, low-latency, real-time voice agents is here. With Inferencing, your ideas move from concept to conversation faster than ever.</p><p>Build. Select. Configure. Go live.</p><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ul><li>For More Information Read the <a href="https://docs.videosdk.live/ai_agents/plugins/inference/videosdk-inference" rel="noreferrer">Inference documentation</a>.</li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction">deploy your AI Agents</a>.</li><li>Sign up at&nbsp;<a href="https://dub.sh/zXYQt7V">VideoSDK Dashboard</a></li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[Introducing VideoSDK Phone Numbers: Build AI Call Agents in 60 seconds]]></title><description><![CDATA[Today, we’re launching VideoSDK Phone Numbers, a first-party telephony capability that lets you connect AI voice agents directly to the phone network.]]></description><link>https://www.videosdk.live/blog/introducing-videosdk-phone-numbers-build-ai-call-agents-in-60-seconds</link><guid isPermaLink="false">697b132c55831517a5a8a103</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 09 Feb 2026 14:20:41 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/02/image--47-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/02/image--47-.png" alt="Introducing VideoSDK Phone Numbers: Build AI Call Agents in 60 seconds"/><p>Today, we’re launching <a href="https://dub.sh/zXYQt7V" rel="noreferrer"><strong>VideoSDK</strong></a><strong> Phone Numbers</strong> a first-party telephony capability that lets you connect voice agents and calling workflows directly to the phone network, <strong>without relying on third-party providers like Twilio</strong>.</p><p>You can now purchase phone numbers straight from the <a href="https://dub.sh/zXYQt7V" rel="noreferrer"><strong>VideoSDK Dashboard</strong></a>, attach them to your agent or calling logic, and go live in minutes.</p><p>No external accounts. No SIP trunk configuration. No extra setup.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/phone-number-dashboard.png" class="kg-image" alt="Introducing VideoSDK Phone Numbers: Build AI Call Agents in 60 seconds" loading="lazy" width="2920" height="1256"/></figure><h2 id="fewer-hops-better-calls">Fewer Hops. Better Calls.</h2><p>Until now, developers building phone-based voice experiences on VideoSDK typically had to:</p><ul><li>Sign up with a third-party telephony provider (like Twilio)</li><li>Purchase and manage phone numbers externally</li><li>Configure SIP trunks and credentials</li><li>Integrate and debug multiple systems before making the first call</li></ul><p>By offering <strong>native phone numbers directly within </strong><a href="https://dub.sh/zXYQt7V" rel="noreferrer"><strong>VideoSDK</strong></a>, we remove those extra layers and make phone-based voice apps significantly easier to build and operate in just 3 steps.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/02/phone-number-architecture1.png" class="kg-image" alt="Introducing VideoSDK Phone Numbers: Build AI Call Agents in 60 seconds" loading="lazy" width="2866" height="1150"/></figure><h2 id="how-it-works">How It Works</h2><p>Getting started with VideoSDK Phone Numbers is simple:</p><p><strong>1. Buy a Phone Number</strong> : Search and purchase available phone numbers directly from the <a href="https://dub.sh/zXYQt7V" rel="noreferrer"><strong>VideoSDK Dashboard</strong></a>.</p><p><strong>2. Attach Your Agent or Logic</strong> : Associate the phone number with your voice agent or inbound call routing logic so incoming calls are handled automatically.</p><p><strong>3. Go Live</strong> : Call the number and your agent answers instantly.<br>Manage numbers, update routing, and monitor usage all from one place.</br></p>
<!--kg-card-begin: html-->
<iframe width="600" height="400" src="https://www.youtube.com/embed/K4g51dBkrrk?si=AwHrXWs0fv3X9jlV" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<h2 id="what-you-can-build">What You Can Build</h2><p>Phone calls remain critical across many industries. With <a href="https://dub.sh/zXYQt7V" rel="noreferrer">VideoSDK Phone Numbers</a>, you can spin up phone-based voice agents in minutes for:</p><ul><li>Sales qualification and lead routing</li><li>Order tracking and delivery updates</li><li>Appointment booking and status updates</li><li>Restaurant and service business call automation</li></ul><p>If your application involves real-time voice and the phone network, this feature is built for you</p><h2 id="resources">Resources</h2><ul><li>Sign up at VideoSDK -&nbsp;<a href="https://dub.sh/BVOvGNr" rel="noreferrer">dashboard</a></li><li> Have feedback or ideas? Comment below or join our Discord to build and ship AI call agents faster with VideoSDK&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul><p/><h2 id=""/>]]></content:encoded></item><item><title><![CDATA[Introducing the Ultravox Realtime Plugin in VideoSDK]]></title><description><![CDATA[Learn more about building real-time voice agents with Ultravox and VideoSDK Agents, where listening, reasoning, and speaking happen together for ultra-low latency, natural conversations.]]></description><link>https://www.videosdk.live/blog/introducing-the-ultravox-realtime-plugin-in-videosdk</link><guid isPermaLink="false">6968d02e55831517a5a89f8d</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 27 Jan 2026 04:51:01 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/01/Ultravox.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/01/Ultravox.png" alt="Introducing the Ultravox Realtime Plugin in VideoSDK"/><p>Real-time voice agents are fundamentally different from traditional AI pipelines. Instead of processing speech in separate steps speech-to-text, reasoning, and text-to-speech they operate as a continuous conversation loop. Every millisecond matters.</p><p>Ultravox is designed specifically for this use case. It enables low-latency, real-time conversational AI where listening, reasoning, and speaking happen together. In this blog, we’ll walk through how to use Ultravox with the VideoSDK Agents SDK to build responsive, interactive voice agents.</p><h2 id="key-features">Key Features</h2><ul><li><strong>Real-Time Conversations</strong> : Ultravox is optimized for live voice interactions, making conversations feel natural and responsive rather than delayed or scripted.</li><li><strong>Function Calling</strong> : Agents can call tools or external APIs during a conversation such as fetching weather data or triggering workflows without breaking the interaction flow.</li><li><strong>Custom Agent Behavior</strong> : You can shape how your agent behaves using system prompts, allowing you to define tone, personality, or role-specific behavior.</li><li><strong>Call Control</strong> : Ultravox-powered agents can manage the conversation lifecycle, including ending calls gracefully when the interaction is complete.</li><li><strong>MCP Integration</strong> : Ultravox supports Model Context Protocol (MCP), allowing agents to connect to external tools and data sources using:<ul><li><code>MCPServerStdio</code> for local processes</li><li><code>MCPServerHTTP</code> for remote services</li></ul></li></ul><p>This makes it easier to build agents that interact with real systems instead of just responding with text.</p><h2 id="installation">Installation</h2><p>To get started, install the <a href="https://pypi.org/project/videosdk-plugins-ultravox/" rel="noreferrer">Ultravox-enabled VideoSDK Agents package:</a></p><pre><code class="language-python">pip install "videosdk-plugins-ultravox"</code></pre><h2 id="authentication">Authentication</h2><p>Ultravox requires an API key.</p><ol><li>Generate an API key from the <a href="https://app.ultravox.ai/" rel="noreferrer">Ultravox dashboard</a></li><li>Sign up at VideoSDK - <a href="https://dub.sh/BVOvGNr" rel="noreferrer">authentication token</a></li></ol><pre><code class="language-python">ULTRAVOX_API_KEY=your_api_key_here
VIDEOSDK_AUTH_TOKEN = token</code></pre><p>When using environment variables, you don’t need to pass the API key directly in your code the SDK picks it up automatically.</p><h2 id="importing-ultravox">Importing Ultravox</h2><pre><code class="language-python">from videosdk.plugins.ultravox import UltravoxRealtime, UltravoxLiveConfig
</code></pre><h2 id="basic-usage-example">Basic Usage Example</h2><p>Below is a minimal example of setting up a real-time Ultravox agent using VideoSDK’s <code>RealTimePipeline</code>.</p><pre><code class="language-python">from videosdk.plugins.ultravox import UltravoxRealtime, UltravoxLiveConfig
from videosdk.agents import RealTimePipeline

# Initialize the Ultravox real-time model
model = UltravoxRealtime(
    model="fixie-ai/ultravox",
    config=UltravoxLiveConfig(
        voice="54ebeae1-88df-4d66-af13-6c41283b4332"
    )
)

# Create the real-time pipeline
pipeline = RealTimePipeline(model=model)</code></pre><p>This setup creates a real-time conversational agent where:</p><ul><li>Audio input is processed continuously</li><li>Responses are generated with minimal delay</li><li>Speech output is streamed back to the user</li></ul><h2 id="configuration-options">Configuration Options</h2><p>Ultravox provides fine-grained control over real-time behavior through <code>UltravoxLiveConfig</code>:</p><ul><li><code>voice</code>: Voice ID used for synthesized speech</li><li><code>language_hint</code>: Hint for the expected conversation language (e.g., <code>"en"</code>)</li><li><code>temperature</code>: Controls response randomness</li><li><code>vad_turn_endpoint_delay</code>: Delay (ms) before a speech turn is considered complete</li><li><code>vad_minimum_turn_duration</code>: Minimum duration (ms) for a valid speech turn</li></ul><p>These parameters help balance responsiveness, stability, and conversational accuracy.</p><h2 id="when-should-you-use-ultravox">When Should You Use Ultravox?</h2><p>Ultravox is a strong fit when:</p><ul><li>You need real-time, low-latency voice conversations</li><li>Turn-taking speed is critical</li><li>You want to avoid managing separate STT, LLM, and TTS components</li><li>Your agent needs to interact live with users or systems</li></ul><p>For batch processing or highly controlled pipelines, a traditional STT → LLM → TTS setup may still make sense. Ultravox shines when conversations need to feel immediate.</p><h2 id="conclusion">Conclusion</h2><p>Ultravox simplifies real-time voice agents by collapsing the entire conversational loop into a single model. Instead of orchestrating multiple components, developers can focus on agent behavior, tools, and interaction flow. When paired with VideoSDK’s real-time pipelines, Ultravox enables voice agents that respond quickly, act intelligently, and feel natural in live conversations.</p><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ul><li>Read more information on <a href="https://docs.ultravox.ai/overview" rel="noreferrer">Ultravox realtime model</a></li><li>Check out<a href="https://github.com/videosdk-live/agents/blob/main/videosdk-plugins/videosdk-plugins-ultravox/videosdk/plugins/ultravox/ultravox_realtime.py" rel="noreferrer"> code implementation on github</a></li><li><strong>Explore more</strong> : Read docs on <a href="https://docs.videosdk.live/ai_agents/plugins/realtime/ultravox" rel="noreferrer">Ultravox Realtime Plugin</a></li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">deploy your AI Agents</a>.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li><li>Sign up at VideoSDK - <a href="https://dub.sh/BVOvGNr" rel="noreferrer">authentication token</a></li></ul><p/><p/><h2 id=""/>]]></content:encoded></item><item><title><![CDATA[Introducing xAI Grok Real-Time Speech-to-Speech Plugin for VideoSDK Agents]]></title><description><![CDATA[Build real-time voice and text agents with xAI’s Grok now natively integrated into VideoSDK Agents for multimodal, context-aware AI experiences.]]></description><link>https://www.videosdk.live/blog/iintroducing-real-time-xai-grok-plugin-for-videosdk-ai-voice-agentin-videosdk</link><guid isPermaLink="false">6964fbfb55831517a5a89f03</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 22 Jan 2026 12:53:51 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/01/image--40-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/01/image--40-.png" alt="Introducing xAI Grok Real-Time Speech-to-Speech Plugin for VideoSDK Agents"/><p>We’re excited to introduce <strong>xAI (Grok) Realtime model support</strong> in <strong>VideoSDK AI Voice Agents</strong>, enabling developers to build <strong>real-time, multimodal AI voice systems</strong> powered by xAI’s Grok models.</p><p>With this integration, your agents can reason over <strong>voice and text and </strong>perform <strong>function calls</strong>.</p><h2 id="why-xai-grok-with-videosdk">Why xAI (Grok) with VideoSDK?</h2><p>xAI’s Grok models are designed for <strong>low-latency, real-time interactions</strong>, making them a strong fit for conversational AI systems. When combined with VideoSDK’s real-time streaming and agent pipeline, you can build:</p><ul><li>Voice-first AI agents</li><li>Multimodal assistants (voice + text)</li><li>Agents with live web and X search</li><li>Context-aware agents grounded in your own data</li></ul><p>All without managing complex audio or streaming infrastructure.</p><h2 id="key-features">Key Features</h2><ul><li><strong>Multi-modal Interactions</strong>: Utilize xAI's powerful Grok models for voice and text.</li><li><strong>Function Calling</strong>: Define custom tools to retrieve weather data, interact with external APIs, or perform other actions.</li><li><strong>Web Search</strong>: Enable real-time web search capabilities by setting&nbsp;<code>enable_web_search=True</code>.</li><li><strong>X Search</strong>: Access X (formerly Twitter) content by setting&nbsp;<code>enable_x_search=True</code>&nbsp;and providing&nbsp;<code>allowed_x_handles</code>.</li></ul><h2 id="authentication">Authentication</h2><ol><li>The Nvidia TTS plugin requires an<a href="https://console.x.ai/home" rel="noreferrer"> <strong>xAI API key</strong></a>. Set the API key as an environment variable in your <code>.env</code> file:</li><li>Sign up at VideoSDK for <a href="https://dub.sh/BVOvGNr" rel="noreferrer">authentication token</a></li></ol><pre><code class="language-python">XAI_API_KEY=your-nvidia-api-key
VIDEOSDK_AUTH_TOKEN = token</code></pre><p>When using environment variables, you don’t need to pass the API key directly in your code. The SDK automatically picks it up at runtime.</p><h3 id="using-videosdk-with-xai%E2%80%99s-grok-plugin">Using VideoSDK with xAI’s Grok Plugin</h3><p><a href="https://pypi.org/project/videosdk-plugins-xai/" rel="noreferrer">Install the xAI plugin:</a></p><pre><code class="language-python">pip install "videosdk-plugins-xai"</code></pre><h2 id="quick-example">Quick example:</h2><pre><code class="language-python">from videosdk.plugins.xai import XAIRealtime, XAIRealtimeConfig
from videosdk.agents import RealTimePipeline

# Initialize the xAI Grok real-time model
model = XAIRealtime(
    model="grok-4-1-fast-non-reasoning",
    api_key="your-xai-api-key",
    config=XAIRealtimeConfig(
        voice="Eve",
        # collection_id="your-collection-id" # Optional
    )
)

# Create the pipeline with the model
pipeline = RealTimePipeline(model=model)</code></pre><h2 id="configuration-options">Configuration Options</h2><ul><li><code>model</code>: The Grok model to use (e.g.,&nbsp;<code>"grok-4-1-fast-non-reasoning"</code>).</li><li><code>api_key</code>: Your xAI API key (can also be set via the&nbsp;<code>XAI_API_KEY</code>&nbsp;environment variable).</li><li><code>config</code>: An&nbsp;<code>XAIRealtimeConfig</code>&nbsp;object for advanced options:<ul><li><code>voice</code>: (str) The voice to use for audio output (e.g.,&nbsp;<code>"Eve"</code>,&nbsp;<code>"Ara"</code>,&nbsp;<code>"Rex"</code>,&nbsp;<code>"Sal"</code>,&nbsp;<code>"Leo"</code>).</li><li><code>enable_web_search</code>: (bool) Enable or disable web search capabilities.</li><li><code>enable_x_search</code>: (bool) Enable or disable search on X (Twitter).</li><li><code>allowed_x_handles</code>: (List[str]) A list of allowed X handles to search within.</li><li><code>collection_id</code>: (str, optional) The ID of a custom collection from your xAI Console storage to provide additional context.</li><li><code>turn_detection</code>: Configuration for detecting when a user has finished speaking.</li></ul></li></ul><h2 id="collection-storage">Collection Storage</h2><p>xAI Grok supports using "collections" to provide additional context to your agent, grounding its responses in your own documents or data.</p><p>To use a collection:</p><ol><li><strong>Navigate to xAI Console</strong>: Go to your&nbsp;<a href="https://console.x.ai/" rel="noopener noreferrer">console.x.ai</a>&nbsp;dashboard.</li><li><strong>Access Storage</strong>: Click on the&nbsp;<strong>Storage</strong>&nbsp;section in the sidebar.</li><li><strong>Create New Collection</strong>: Click the "Create New Collection" button.</li><li><strong>Upload Files</strong>: Upload your relevant documents or data files to the new collection.</li><li><strong>Get Collection ID</strong>: Once the collection is created, copy its&nbsp;<strong>Collection ID</strong>.</li><li><strong>Use in Config</strong>: Pass the copied ID to your agent's configuration:</li></ol><pre><code class="language-python">config=XAIRealtimeConfig(
    voice="Eve",
    collection_id="your-collection-id-from-console",
    # ... other config options
)</code></pre><p>The agent will now use the content of this collection to inform its responses.</p><h2 id="conclusion">Conclusion</h2><p>With xAI Grok now integrated into VideoSDK Agents, developers can build real-time AI voice systems that are faster, smarter, and easier to scale. By combining Grok’s powerful multimodal models with VideoSDK’s low-latency real-time pipeline, you can move from prototype to production-ready voice agents in just a few lines of code. Whether you’re building assistants, support agents, or interactive AI experiences, this integration gives you the foundation to create natural, real-time conversations with confidence.</p><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ul><li>Explore the&nbsp;<a href="https://docs.videosdk.live/ai_agents/plugins/realtime/xai-grok" rel="noreferrer">documentation</a>.</li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">deploy your AI Agents</a>.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li><li>Sign up at VideoSDK for <a href="https://dub.sh/BVOvGNr" rel="noreferrer">authentication token</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Introducing the Nvidia Speech to Text Plugin in VideoSDK]]></title><description><![CDATA[Learn how to integrate NVIDIA STT with the VideoSDK Agents SDK to generate fast, accurate, and production-ready transcriptions.]]></description><link>https://www.videosdk.live/blog/introducing-the-nvidia-speech-to-text-plugin-in-videosdk</link><guid isPermaLink="false">6968cc7555831517a5a89f4f</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 20 Jan 2026 13:11:43 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/01/image--38-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/01/image--38-.png" alt="Introducing the Nvidia Speech to Text Plugin in VideoSDK"/><p>Speech recognition is a critical building block for real-time AI voice agents. To deliver fast, accurate, and production-ready transcription, VideoSDK integrates with <strong>Nvidia Speech-to-Text (STT) </strong>a high‑performance, low‑latency speech recognition solution designed for real‑time applications.</p><p>In this blog, we’ll walk through how Nvidia STT works with the VideoSDK Agents SDK and how you can quickly integrate it into your AI voice pipeline.</p><h2 id="why-nvidia-stt">Why Nvidia STT?</h2><p>Nvidia STT is built for speed and accuracy. It is well suited for real-time voice agents where low latency, streaming transcription, and stable performance are essential.</p><p>With VideoSDK’s plugin-based architecture, you can easily swap or test STT providers making Nvidia STT a strong choice for production-grade voice experiences.</p><h2 id="installation">Installation</h2><p>To get started, install the <a href="https://pypi.org/project/videosdk-plugins-nvidia/" rel="noreferrer">Nvidia-enabled VideoSDK Agents plugin</a>:</p><pre><code class="language-python">pip install "videosdk-plugins-nvidia"</code></pre><p>This package adds native support for Nvidia STT inside the VideoSDK Agents ecosystem.</p><h2 id="authentication">Authentication</h2><ol><li>The Nvidia STT plugin requires an <strong>Nvidia API key</strong>. Set the API key as an environment variable in your <code>.env</code> file:</li><li>Sign up at VideoSDK for <a href="https://dub.sh/BVOvGNr" rel="noreferrer">authentication token</a></li></ol><pre><code class="language-python">NVIDIA_API_KEY=your-nvidia-api-key
VIDEOSDK_AUTH_TOKEN = token</code></pre><p>When using environment variables, you don’t need to pass the API key directly in your code. The SDK automatically picks it up at runtime.</p><h2 id="importing-nvidia-stt">Importing Nvidia STT</h2><p>Once installed, import the Nvidia STT plugin into your project:</p><pre><code class="language-python">from videosdk.plugins.nvidia import NvidiaSTT</code></pre><h2 id="example-using-nvidia-stt-in-a-cascading-pipeline">Example: Using Nvidia STT in a Cascading Pipeline</h2><pre><code class="language-python">from videosdk.plugins.nvidia import NvidiaSTT
from videosdk.agents import CascadingPipeline

# Initialize the Nvidia STT model
stt = NvidiaSTT(
    model="parakeet-1.1b-en-US-asr-streaming-silero-vad-sortformer",
    language_code="en-US",
    profanity_filter=False,
    automatic_punctuation=True
)

# Add STT to the cascading pipeline
pipeline = CascadingPipeline(stt=stt)</code></pre><h2 id="configuration-options">Configuration Options</h2><p>Nvidia STT exposes several configuration options so you can fine-tune transcription behavior:</p><ul><li><strong>api_key</strong>: Nvidia API key (optional if set via environment variable)</li><li><strong>model</strong>: Nvidia Riva STT model to use</li><li><strong>server</strong>: Riva server address (default: <code>grpc.nvcf.nvidia.com:443</code>)</li><li><strong>function_id</strong>: Nvidia service function ID</li><li><strong>language_code</strong>: Language for transcription (default: <code>en-US</code>)</li><li><strong>sample_rate</strong>: Audio sample rate in Hz (default: <code>16000</code>)</li><li><strong>profanity_filter</strong>: Enable or disable profanity filtering</li><li><strong>automatic_punctuation</strong>: Enable automatic punctuation</li><li><strong>use_ssl</strong>: Enable SSL connection</li></ul><p>These options make it easy to adapt Nvidia STT to different real-world voice scenarios.</p><h2 id="conclusion">Conclusion</h2><p>By integrating Nvidia STT with VideoSDK Agents, you get a powerful, flexible speech recognition layer that fits naturally into real-time AI voice workflows. Whether you’re testing individual components or deploying a full voice agent pipeline, Nvidia STT gives you the speed and reliability required for modern conversational experiences.</p><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ul><li>Read more information on <a href="https://docs.nvidia.com/deeplearning/riva/user-guide/docs/index.html" rel="noreferrer">Nvidia Riva STT</a></li><li>Check out <a href="https://github.com/videosdk-live/agents/blob/main/videosdk-plugins/videosdk-plugins-nvidia/videosdk/plugins/nvidia/stt.py" rel="noreferrer">full code implementation on github</a></li><li><strong>Explore more</strong> : Read docs on <a href="https://docs.videosdk.live/ai_agents/plugins/stt/nvidia" rel="noreferrer">Nvidia STT Plugin</a></li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">deploy your AI Agents</a>.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[Introducing the MurfAI Text To Speech Plugin in VideoSDK]]></title><description><![CDATA[Learn how to integrate Murf AI Text-to-Speech with VideoSDK Agents to generate natural, expressive, and low-latency voice output for AI agents.]]></description><link>https://www.videosdk.live/blog/introducing-the-murfai-text-to-speech-plugin-in-videosdk</link><guid isPermaLink="false">6964bccc55831517a5a89ebd</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 20 Jan 2026 06:26:32 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/01/image--32-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/01/image--32-.png" alt="Introducing the MurfAI Text To Speech Plugin in VideoSDK"/><p>We’re excited to introduce <strong>Murf AI Text-to-Speech (TTS) support in VideoSDK Agents</strong>, enabling developers to generate <strong>natural, expressive voice output</strong> using Murf AI’s high-quality speech models.</p><p>With this integration, you can add <strong>human-like voices</strong>, advanced <strong>voice customization</strong>, and <strong>low-latency streaming audio</strong> to your AI agents — all seamlessly within VideoSDK’s real-time pipeline.</p><h2 id="why-murf-ai-with-videosdk">Why Murf AI with VideoSDK?</h2><p>Murf AI offers studio-quality voices with fine-grained control over tone, pace, and style. When combined with VideoSDK Agents, you can build:</p><ul><li>Natural-sounding AI voice agents</li><li>Expressive speech with adjustable pitch, rate, and style</li><li>Low-latency, streaming TTS for real-time conversations</li><li>Globally deployable agents with multi-region support</li></ul><p>All without managing complex audio pipelines or streaming logic.</p><h2 id="authentication">Authentication</h2><ol><li>The  MurfAI TTS plugin requires an<a href="https://murf.ai/" rel="noreferrer"> MURFAI<strong> API key</strong>.</a> Set the API key as an environment variable in your <code>.env</code> file:</li><li>Sign up at VideoSDK for <a href="https://dub.sh/BVOvGNr" rel="noreferrer">authentication token</a></li></ol><pre><code class="language-python">MURFAI_API_KEY=your-nvidia-api-key
VIDEOSDK_AUTH_TOKEN = token</code></pre><p>When using environment variables, you don’t need to pass the API key directly in your code. The SDK automatically picks it up at runtime.</p><h2 id="using-videosdk-with-murf-ai-tts-plugin">Using VideoSDK with Murf AI TTS Plugin</h2><p>Install the <a href="https://pypi.org/project/videosdk-plugins-murfai/" rel="noreferrer">Murf AI plugin:</a></p><pre><code class="language-python">pip install "videosdk-plugins-murfai"</code></pre><h2 id="quick-example">Quick Example</h2><pre><code class="language-python">from videosdk.plugins.murfai import MurfAITTS, MurfAIVoiceSettings
from videosdk.agents import CascadingPipeline

# Configure voice settings
voice_settings = MurfAIVoiceSettings(
    pitch=0,
    rate=0,
    style="Conversational",
    variation=1,
    multi_native_locale=None
)

# Initialize the Murf AI TTS model
tts = MurfAITTS(
    # When MURFAI_API_KEY is set in .env - DON'T pass api_key parameter
    api_key="your-murfai-api-key",
    region="US_EAST",
    model="Falcon",
    voice="en-US-natalie",
    voice_settings=voice_settings,
    enable_streaming=True
)

# Add tts to cascading pipeline
pipeline = CascadingPipeline(tts=tts)
</code></pre><blockquote>for detailed explanation on configuration options visit <a href="https://docs.videosdk.live/ai_agents/plugins/tts/murf-ai-tts#configuration-options" rel="noreferrer">murfai-plugin-documentation.</a></blockquote><h2 id="conclusion">Conclusion</h2><p>With Murf AI TTS now integrated into VideoSDK Agents, developers can deliver <strong>natural, expressive speech</strong> in real-time AI voice systems with minimal setup. By combining Murf AI’s powerful text-to-speech models with VideoSDK’s real-time agent pipelines, you can build production-ready voice experiences that sound more human and feel more engaging.</p><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ul><li>Explore the&nbsp;<a href="https://docs.videosdk.live/ai_agents/plugins/tts/murf-ai-tts" rel="noreferrer">documentation</a>.</li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">deploy your AI Agents</a>.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li><li>Sign up at VideoSDK for <a href="https://dub.sh/BVOvGNr" rel="noreferrer">authentication token</a></li></ul><p/>]]></content:encoded></item><item><title><![CDATA[Introducing the Nvidia Text to Speech Plugin in VideoSDK]]></title><description><![CDATA[Learn how to integrate NVIDIA Riva TTS with the VideoSDK Agents SDK to deliver real-time, low-latency speech that makes AI voice agents sound natural, responsive, and production-ready.]]></description><link>https://www.videosdk.live/blog/introducing-the-nvidia-text-to-speech-plugin-in-videosdk</link><guid isPermaLink="false">6968ce8355831517a5a89f74</guid><category><![CDATA[ai agents]]></category><category><![CDATA[plugins]]></category><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 19 Jan 2026 07:54:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/01/image--35-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/01/image--35-.png" alt="Introducing the Nvidia Text to Speech Plugin in VideoSDK"/><p>When an AI agent speaks, latency and voice quality matter as much as the words themselves. Text-to-speech is the final step in the interaction, and it directly shapes how natural and responsive an agent feels.</p><p>Nvidia TTS, powered by Riva, is built for real-time systems where speech needs to be generated quickly, consistently, and at scale. In this guide, we’ll walk through how to integrate Nvidia TTS with the VideoSDK Agents SDK and use it as part of a low-latency voice pipeline.</p><h2 id="installation">Installation</h2><p>To get started, install the <a href="https://pypi.org/project/videosdk-plugins-nvidia/" rel="noreferrer">Nvidia-enabled VideoSDK Agents plugin</a>:</p><pre><code class="language-python">pip install "videosdk-plugins-nvidia"</code></pre><p>This package adds native support for Nvidia TTS inside the VideoSDK Agents ecosystem.</p><h2 id="authentication">Authentication</h2><ol><li>The Nvidia TTS plugin requires an <a href="https://build.nvidia.com/settings/api-keys" rel="noreferrer"><strong>Nvidia API key</strong></a>. Set the API key as an environment variable in your <code>.env</code> file:</li><li>Sign up at VideoSDK for <a href="https://dub.sh/BVOvGNr" rel="noreferrer">authentication token</a></li></ol><pre><code class="language-python">NVIDIA_API_KEY=your-nvidia-api-key
VIDEOSDK_AUTH_TOKEN = token</code></pre><p>When using environment variables, you don’t need to pass the API key directly in your code. The SDK automatically picks it up at runtime.</p><h2 id="importing-nvidia-tts">Importing Nvidia TTS</h2><p>Once installed, import the Nvidia TTS plugin into your project:</p><pre><code class="language-python">from videosdk.plugins.nvidia import NvidiaTTS</code></pre><h2 id="example-using-nvidia-tts-in-a-cascading-pipeline">Example: Using Nvidia TTS in a Cascading Pipeline</h2><pre><code class="language-python">from videosdk.plugins.nvidia import NvidiaTTS
from videosdk.agents import CascadingPipeline

# Initialize the Nvidia TTS model

tts = NvidiaTTS(
    api_key="your-nvidia-api-key",
    voice_name="Magpie-Multilingual.EN-US.Aria",
    language_code="en-US",
    sample_rate=24000
)

#  Add tts to cascading pipeline
pipeline = CascadingPipeline(tts=tts)</code></pre><h2 id="configuration-options">Configuration Options</h2><p>Nvidia STT exposes several configuration options so you can fine-tune transcription behavior:</p><ul><li><code>api_key</code>: Your Nvidia API key (required, can also be set via environment variable)</li><li><code>server</code>: The Nvidia Riva server address (default:&nbsp;<code>"grpc.nvcf.nvidia.com:443"</code>)</li><li><code>function_id</code>: The specific function ID for the service (default:&nbsp;<code>"877104f7-e885-42b9-8de8-f6e4c6303969"</code>)</li><li><code>voice_name</code>: (str) The voice to use (default:&nbsp;<code>"Magpie-Multilingual.EN-US.Aria"</code>)</li><li><code>language_code</code>: (str) Language code for synthesis (default:&nbsp;<code>"en-US"</code>)</li><li><code>sample_rate</code>: (int) Audio sample rate in Hz (default:&nbsp;<code>24000</code>)</li><li><code>use_ssl</code>: (bool) Enable SSL connection (default:&nbsp;<code>True</code>)</li></ul><p>These options make it easy to adapt Nvidia TTS to different real-world voice scenarios.</p><h2 id="conclusion">Conclusion</h2><p>Nvidia TTS fits naturally into real-time AI agents where fast, reliable speech output is critical. By combining Riva’s optimized speech models with VideoSDK’s agent pipeline, you get precise control over voice output without adding complexity to your system. Whether you’re prototyping a voice assistant or running production-grade agents, having a predictable and testable TTS layer helps you build conversations that sound responsive, stable, and human.</p><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ul><li><strong>Explore more</strong> : Read docs on <a href="https://docs.videosdk.live/ai_agents/plugins/tts/nvidia" rel="noreferrer">Nvidia TTS Plugin</a></li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">deploy your AI Agents</a></li><li>Read more information on <a href="https://docs.nvidia.com/deeplearning/riva/user-guide/docs/index.html" rel="noreferrer">Nvidia Riva </a>TTS</li><li>Check out <a href="https://github.com/videosdk-live/agents/blob/main/videosdk-plugins/videosdk-plugins-nvidia/videosdk/plugins/nvidia/tts.py" rel="noreferrer">full code implementation on github</a></li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul><p/>]]></content:encoded></item><item><title><![CDATA[Introducing the Gladia Speech to Text Plugin in VideoSDK]]></title><description><![CDATA[We’re introducing the Gladia Speech-to-Text plugin for VideoSDK. With multilingual support, instant partial results, and handling of mixed languages, it provides a reliable speech input layer for voice-driven applications.]]></description><link>https://www.videosdk.live/blog/introducing-the-gladia-stt-plugin-in-videosdk</link><guid isPermaLink="false">6968d27055831517a5a89fbb</guid><category><![CDATA[plugins]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[community]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 16 Jan 2026 05:24:28 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/01/image--33-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/01/image--33-.png" alt="Introducing the Gladia Speech to Text Plugin in VideoSDK"/><p>Speech-to-text is the first and most critical step in any voice agent. If transcription is slow or inaccurate, everything downstream reasoning and response suffers. Gladia STT is built for real-time transcription with strong multilingual support, fast partial results, and handling of code-switching.</p><p>In this guide, we’ll walk through how to integrate Gladia STT with the VideoSDK Agents SDK and use it as a reliable input layer for voice-driven applications</p><h2 id="why-gladia-stt">Why Gladia STT?</h2><p>Many voice agents operate in environments where users switch languages mid-sentence or expect instant feedback while speaking. Gladia is optimized for these scenarios. It provides:</p><ul><li>Low-latency transcription</li><li>Support for multiple languages</li><li>Automatic code-switching</li><li>Partial transcripts for faster turn detection</li></ul><p>This makes it a strong choice for real-time agents, live calls, and interactive voice applications.</p><h2 id="key-features">Key Features</h2><ul><li><strong>Real-Time Transcription</strong> : Gladia streams transcription results as audio is processed, reducing perceived latency in conversations.</li><li><strong>Multilingual Support</strong> : You can specify one or more languages, making it suitable for global or multilingual users.</li><li><strong>Code-Switching</strong> : Gladia can automatically detect and switch languages within the same conversation without manual intervention.</li><li><strong>Partial Transcripts</strong> : By enabling partial transcripts, agents can start reasoning before the user finishes speaking, improving responsiveness.</li></ul><h2 id="installation">Installation</h2><p>Install the <a href="https://pypi.org/project/videosdk-plugins-gladia/" rel="noreferrer">Gladia-STT VideoSDK Agents package</a>:</p><pre><code class="language-python">pip install "videosdk-plugins-gladia"</code></pre><h2 id="authentication">Authentication</h2><ol><li>Sign up at Gladia : <a href="https://app.gladia.io/signup" rel="noreferrer">signup link</a></li><li>Sign up at VideoSDK - <a href="https://dub.sh/BVOvGNr" rel="noreferrer">authentication token</a></li></ol><pre><code class="language-python">GLADIA_API_KEY=your_api_key_here
VIDEOSDK_AUTH_TOKEN = token</code></pre><p>When using environment variables, you don’t need to pass the API key directly in code the SDK reads it automatically.</p><h2 id="importing-gladia-stt">Importing Gladia STT</h2><pre><code class="language-python">from videosdk.plugins.gladia import GladiaSTT</code></pre><h2 id="basic-usage-example">Basic Usage Example</h2><p>Below is a minimal example showing how to configure Gladia STT and attach it to a cascading pipeline.</p><pre><code class="language-python">from videosdk.plugins.gladia import GladiaSTT
from videosdk.agents import CascadingPipeline

# Initialize the Gladia STT model
stt = GladiaSTT(
    api_key="your-gladia-api-key",
    languages=["en"],
    code_switching=True,
    receive_partial_transcripts=True
)

#  Add stt to a cascading pipeline
pipeline = CascadingPipeline(stt=stt)</code></pre><p>This setup enables:</p><ul><li>Real-time transcription</li><li>Automatic language switching</li><li>Partial transcripts for faster downstream processing</li></ul><h2 id="configuration-options">Configuration Options</h2><p>Gladia STT provides fine-grained control over transcription behavior:</p><ul><li><code>languages</code>: List of language codes to detect (e.g., <code>["en", "fr"]</code>)</li><li><code>code_switching</code>: Enables automatic language switching</li><li><code>receive_partial_transcripts</code>: Streams interim results for lower latency</li><li><code>model</code>: STT model to use (default: <code>"solaria-1"</code>)</li><li><code>input_sample_rate</code>: Incoming audio sample rate</li><li><code>output_sample_rate</code>: Processing sample rate</li><li><code>encoding</code>: Audio encoding format</li><li><code>bit_depth</code>: Audio bit depth</li><li><code>channels</code>: Number of audio channels (mono or stereo)</li></ul><p>These parameters let you tune accuracy, latency, and compatibility with your audio pipeline.</p><h2 id="conclusion">Conclusion</h2><p>Gladia STT provides a strong foundation for real-time voice agents by combining speed, accuracy, and multilingual flexibility. When integrated with VideoSDK’s agent pipelines, it enables agents to listen effectively even in dynamic, multilingual conversations. A reliable STT layer like Gladia helps ensure that downstream reasoning and responses stay accurate, responsive, and consistent.</p><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ul><li>Read more information on <a href="https://docs.gladia.io/chapters/introduction" rel="noreferrer">Gladia STT model</a></li><li>Check out<a href="https://github.com/videosdk-live/agents/blob/main/videosdk-plugins/videosdk-plugins-gladia/videosdk/plugins/gladia/stt.py" rel="noreferrer"> full code implementation on github</a></li><li><strong>Explore more</strong> : Read documentation on <a href="https://docs.videosdk.live/ai_agents/plugins/stt/gladia" rel="noreferrer">Gladia STT Plugin</a></li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">deploy your AI Agents</a>.</li><li>Sign up at <a href="https://dub.sh/zXYQt7V" rel="noreferrer">VideoSDK Dashboard</a></li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul><p/><h2 id=""/><h2 id="-1"/>]]></content:encoded></item><item><title><![CDATA[Introducing Testing and Evaluation in AI Voice Agents]]></title><description><![CDATA[Learn how to run testing and evaluation for AI voice agents using the VideoSDK Agent SDK, including STT, LLM, and TTS benchmarking, latency metrics, and LLM-based response judging.]]></description><link>https://www.videosdk.live/blog/introducing-testing-and-evaluation-in-AI-Voice-Agents</link><guid isPermaLink="false">6964cfbe55831517a5a89ecb</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 15 Jan 2026 11:15:03 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/01/Eval.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/01/Eval.png" alt="Introducing Testing and Evaluation in AI Voice Agents"/><p>When building AI agents, the first validation step is often informal: trigger the agent, speak a sentence, and confirm that it responds. If speech is recognized, text is generated, and audio plays back, the system is considered functional.</p><p>This approach works for demos. It does not work for production.</p><p>As voice agents are deployed in real environments, previously invisible issues begin to surface. Response times increase under load. Transcription quality degrades gradually rather than catastrophically. Language models produce responses that are fluent but misaligned with user intent. When failures are reported, teams often lack the data required to diagnose them. There are no baselines, no thresholds, and no historical comparisons only subjective impressions.</p><p>This reveals a fundamental problem with modern AI agents: <strong>they are easy to demonstrate, but difficult to measure</strong>.</p><p>To address this gap, we introduced a structured Testing and Evaluation framework in the VideoSDK Agent SDK. This post explains the engineering principles behind that framework and how to think about evaluating real-time voice agents .</p><h2 id="%E2%80%9Cdoes-it-work%E2%80%9D-is-not-an-engineering-metric">“Does It Work?” Is Not an Engineering Metric</h2><p>In early development, teams frequently rely on qualitative validation: does the agent respond correctly in a small number of manual tests? While useful during prototyping, this approach collapses under production constraints.</p><p>From an engineering standpoint, a single successful interaction demonstrates only that one execution path completed without failure. It provides no information about:</p><ul><li>Latency distributions</li><li>Variance across inputs and environments</li><li>Regression across versions</li><li>Sensitivity to load and concurrency</li></ul><p>More critically, it produces no measurable artifacts that can be compared over time.</p><p>Production systems require observability. Without quantitative metrics, regressions are detected only after user complaints, and root-cause analysis becomes speculative. What appears to be a “model issue” may in fact be a latency spike, a transcription error, or a cascading failure across multiple stages.</p><p>Voice agents must therefore be evaluated as <strong>systems</strong>, not demos.</p><h2 id="the-first-principles-view-what-is-an-ai-agent">The First-Principles View: What Is an AI Agent?</h2><p>At its core, a real-time agent is a pipeline:</p><ol><li><strong>Speech-to-Text (STT)</strong> converts audio into text</li><li><strong>LLM</strong> interprets intent, reasons, and decides what to say</li><li><strong>Text-to-Speech (TTS)</strong> turns the response back into audio</li></ol><p>Every failure in production maps to one of these layers. So instead of testing “the agent”, we should be asking:</p><ul><li>How long does STT take?</li><li>How accurate is the transcription?</li><li>Does the LLM respond correctly <em>for this input</em>?</li><li>Does latency compound across the pipeline?</li></ul><p>This is the mental model behind the evaluation framework.</p><h2 id="implementation-measuring-the-pipeline">Implementation: Measuring the Pipeline</h2><p>Once the mental model is clear, evaluation becomes a <strong>systematic process</strong>:</p><ol><li><strong>Define what to measure</strong> : Decide which metrics matter (latency, accuracy, quality).</li><li><strong>Instrument each component</strong> : Measure STT, LLM, and TTS individually.</li><li><strong>Measure end-to-end performance</strong> : Capture how component interactions affect the overall experience.</li></ol><pre><code class="language-python">from videosdk.agents import Evaluation, EvalMetric

eval = Evaluation(
    name="agent-eval",
    metrics=[
        EvalMetric.STT_LATENCY,
        EvalMetric.LLM_LATENCY,
        EvalMetric.TTS_LATENCY,
        EvalMetric.END_TO_END_LATENCY
    ],
    output_dir="./reports"
)</code></pre><p>This immediately answers questions like:</p><ul><li>How long does each component take?</li><li>Where is most of the latency coming from?</li><li>What does end-to-end user experience look like?</li></ul><h2 id="adding-a-turn-testing-the-full-pipeline">Adding a Turn: Testing the Full Pipeline</h2><p>A “turn” is a single user-agent interaction that involves <strong>STT → LLM → TTS</strong>. Testing a turn allows you to see how <strong>errors propagate</strong> and how <strong>latency accumulates</strong>.</p><pre><code class="language-python">from videosdk.agents import (
    EvalTurn, STTComponent, LLMComponent, TTSComponent,
    STTEvalConfig, LLMEvalConfig, TTSEvalConfig
)

eval.add_turn(
    EvalTurn(
        stt=STTComponent.deepgram(
            STTEvalConfig(file_path="./sample.wav")
        ),
        llm=LLMComponent.google(
            LLMEvalConfig(
                model="gemini-2.5-flash-lite",
                use_stt_output=True
            )
        ),
        tts=TTSComponent.google(
            TTSEvalConfig(
                model="en-US-Standard-A",
                use_llm_output=True
            )
        )
    )
)</code></pre><h2 id="evaluating-response-quality-with-an-llm-judge">Evaluating Response Quality with an LLM Judge</h2><p>Latency alone doesn’t guarantee a good experience. An agent can respond quickly and still be wrong.</p><p>To solve this, the SDK supports <strong>LLM-as-Judge</strong>, which evaluates responses on qualitative dimensions.</p><pre><code class="language-python">from videosdk.agents import LLMAsJudge, LLMAsJudgeMetric

judge = LLMAsJudge.google(
    model="gemini-2.5-flash-lite",
    prompt="Is the response relevant and logically correct?",
    checks=[
        LLMAsJudgeMetric.RELEVANCE,
        LLMAsJudgeMetric.REASONING,
        LLMAsJudgeMetric.SCORE
    ]
)</code></pre><h2 id="testing-components-in-isolation">Testing Components in Isolation</h2><p>Not every issue requires end-to-end testing. Sometimes you just want to isolate a single component.</p><h3 id="stt-only">STT Only</h3><pre><code class="language-python">eval.add_turn(
    EvalTurn(
        stt=STTComponent.deepgram(
            STTEvalConfig(file_path="./sports.wav")
        )
    )
)</code></pre><h3 id="llm-only">LLM Only</h3><pre><code class="language-python">eval.add_turn(
    EvalTurn(
        llm=LLMComponent.google(
            LLMEvalConfig(
                model="gemini-2.5-flash-lite",
                mock_input="Explain photosynthesis in one paragraph"
            )
        )
    )
)</code></pre><p>This makes debugging faster and removes noise from unrelated stages.</p><h2 id="running-the-evaluation">Running the Evaluation</h2><p>Once your turns are defined, running the evaluation is straightforward.</p><pre><code class="language-python">results = eval.run()
results.save()</code></pre><p>The SDK generates structured reports that you can track over time to catch regressions and compare model performance.</p><h2 id="conclusion">Conclusion</h2><p>Building a voice AI agent that “works” in a demo is easy. <strong>Ensuring it works reliably in the real world requires structured testing and evaluation at every stage  from speech recognition to language understanding to speech synthesis.</strong> This approach not only identifies hidden errors and latency issues but also ensures the agent responds accurately, handles interruptions, and delivers a seamless user experience. In short, <strong>testing is not optional; it’s the foundation for building AI agents users can trust.</strong></p><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ul><li>Explore the&nbsp;<a href="https://docs.videosdk.live/ai_agents/core-components/testing-and-evaluation" rel="noreferrer">documentation</a>&nbsp;for full code implementation.</li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">deploy your AI Agents</a>.</li><li><strong>Explore more:</strong>&nbsp;Check out the&nbsp;<a href="https://docs.videosdk.live/ai_agents/core-components/multi-agent-switching" rel="noreferrer">VideoSDK documentation</a>&nbsp;for more features.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[How to Build an AI Voice System Using Real-Time Multi-Agent Switching]]></title><description><![CDATA[In this blog you'll learn about how to build an AI systems with multi-agent switching that intelligently transfer control between specialized agents. Keep conversations natural, tasks organized, and users engaged by letting each agent focus on what it does best.]]></description><link>https://www.videosdk.live/blog/how-to-build-an-ai-voice-system-using-real-time-multi-agent-switching</link><guid isPermaLink="false">6964a72d55831517a5a89ea8</guid><category><![CDATA[ai agents]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 13 Jan 2026 04:54:55 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/01/image--29-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/01/image--29-.png" alt="How to Build an AI Voice System Using Real-Time Multi-Agent Switching"/><p>In today’s fast-paced world, users expect AI assistants to handle complex workflows . Imagine a healthcare assistant that not only understands your symptoms but can also instantly transfer you to the right specialist without making you repeat yourself. This is possible with <strong>multi-agent switching</strong>, and in this guide, we’ll show you how to build it using <strong>VideoSDK</strong>.</p><h2 id="why-multi-agent-switching-matters">Why Multi-Agent Switching Matters</h2><p>Traditional AI assistants often rely on a single agent to handle all tasks. This can get complicated when multiple tools or domains are involved. <strong>Multi-agent switching</strong> breaks a workflow into specialized agents, each focusing on a specific domain or task. <strong>For example in healthcare agent : </strong></p><ul><li>One agent handles <strong>general healthcare inquiries</strong>.</li><li>Another manages <strong>appointment scheduling</strong>.</li><li>A third provides <strong>medical support or guidance</strong>.</li></ul><p>By coordinating smaller agents that operate independently, you create a system that is <strong>modular, maintainable, and more intelligent</strong>.</p><h2 id="context-inheritance-keeping-conversations-smooth">Context Inheritance: Keeping Conversations Smooth</h2><p>When switching agents, you want the new agent to either:</p><ul><li><strong>Know the previous conversation</strong> (<code>inherit_context=True</code>)<br>→ Ideal for maintaining continuity, so users don’t have to repeat themselves.</br></li><li><strong>Start fresh</strong> (<code>inherit_context=False</code>)<br>→ Useful when switching to a completely unrelated task.</br></li></ul><p>This flexibility ensures that your AI behaves naturally and intelligently.</p><h2 id="how-multi-agent-switching-works">How Multi-Agent Switching Works</h2><ol><li>The primary VideoSDK agent listens and understands the user’s intent.</li><li>If specialized assistance is needed, it invokes a <strong>function tool</strong> to transfer control.</li><li>The new agent takes over. If <code>inherit_context=True</code>, it has access to the previous chat, keeping the conversation seamless.</li><li>The specialized agent handles the user’s request and completes the interaction.</li></ol><h2 id="implementation-example-healthcare-agents">Implementation Example: Healthcare Agents</h2><p>Below is a simplified implementation of a <strong>Healthcare AI Voice System</strong> using VideoSDK:</p><pre><code class="language-python">import logging
from videosdk.agents import Agent, AgentSession, CascadingPipeline, function_tool, WorkerJob ,ConversationFlow, JobContext, RoomOptions
from videosdk.plugins.deepgram import DeepgramSTT
from videosdk.plugins.google import GoogleLLM
from videosdk.plugins.cartesia import CartesiaTTS
from videosdk.plugins.silero import SileroVAD
from videosdk.plugins.turn_detector import TurnDetector, pre_download_model

pre_download_model()


class HealthcareAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions="""
You are a general healthcare assistant. Help users with medical inquiries, 
guide them to the right specialist, and route them to appointment booking or medical support when needed.
Respond clearly, calmly, and professionally.
""",
        )

    async def on_enter(self) -&gt; None:
        await self.session.reply(
            instructions="Greet the user politely and ask how you can assist with their health-related concern today."
        )

    async def on_exit(self) -&gt; None:
        await self.session.say("Take care and stay healthy!")

    @function_tool()
    async def transfer_to_appointment(self) -&gt; Agent:
        """Transfer to the healthcare appointment specialist for scheduling or changes."""
        return AppointmentAgent(inherit_context=True)

    @function_tool()
    async def transfer_to_medical_support(self) -&gt; Agent:
        """Transfer to medical support for symptoms, reports, or health guidance."""
        return MedicalSupportAgent(inherit_context=True)


class AppointmentAgent(Agent):
    def __init__(self, inherit_context: bool = False):
        super().__init__(
            instructions="""
You are an appointment specialist. Help users schedule, modify, or cancel 
doctor visits, follow-ups, tests, or telehealth appointments.
""",
            inherit_context=inherit_context,
        )

    async def on_enter(self) -&gt; None:
        await self.session.say(
            "You’re connected with appointments. What would you like to schedule or update today?"
        )

    async def on_exit(self) -&gt; None:
        await self.session.say("Your appointment request is complete. Wishing you good health!")


class MedicalSupportAgent(Agent):
    def __init__(self, inherit_context: bool = False):
        super().__init__(
            instructions="""
You are a medical support specialist. Help users with symptoms, 
health concerns, basic guidance, or understanding reports. 
You are NOT a doctor — provide general support and routing only.
""",
            inherit_context=inherit_context,
        )

    async def on_enter(self) -&gt; None:
        await self.session.say(
            "You’re now connected with medical support. How can I help with your health concern?"
        )

    async def on_exit(self) -&gt; None:
        await self.session.say("Glad I could help. Take care and stay well!")


async def entrypoint(ctx: JobContext):
    agent = HealthcareAgent()
    conversation_flow = ConversationFlow(agent)

    pipeline = CascadingPipeline(
        stt=DeepgramSTT(),
        llm=GoogleLLM(),
        tts=CartesiaTTS(),
        vad=SileroVAD(),
        turn_detector=TurnDetector()
    )
    session = AgentSession(
        agent=agent, 
        pipeline=pipeline,
        conversation_flow=conversation_flow
    )

    await session.start(wait_for_participant=True, run_until_shutdown=True)

def make_context() -&gt; JobContext:
    room_options = RoomOptions(room_id="&lt;room_id&gt;", name="Multi Agent Switch Agent", playground=True)
    return JobContext(room_options=room_options)

if __name__ == "__main__":
    job = WorkerJob(entrypoint=entrypoint, jobctx=make_context)
    job.start()</code></pre><blockquote>With this setup, your healthcare AI can <strong>detect user intent</strong> and route them to the correct specialized agent while keeping context intact.</blockquote><p>Multi-agent AI is a <strong>game-changer for healthcare voice assistants</strong>. It allows complex workflows to be broken down into specialized agents, ensures <strong>smooth context transitions</strong>, and improves user experience. Whether you’re handling patient symptoms, appointment scheduling, or medical guidance, this system keeps conversations <strong>natural, professional, and effective</strong>.</p><p>With VideoSDK, building such a system is easier than ever. You just need a few agents, some function tools, and your imagination to create a truly intelligent healthcare assistant.</p><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ul><li>Explore the&nbsp;<a href="https://github.com/videosdk-live/agents-quickstart/tree/main/Multi%20Agent%20Switch/Travel%20Agent" rel="noreferrer">travel-agent-example</a>&nbsp;for full code implementation.</li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">deploy your AI Agents</a>.</li><li><strong>Explore more:</strong>&nbsp;Check out the&nbsp;<a href="https://docs.videosdk.live/ai_agents/core-components/multi-agent-switching" rel="noreferrer">VideoSDK documentation</a>&nbsp;for more features.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[How to enable Voice Mail Detection in AI Voice Agents]]></title><description><![CDATA[Learn how Voice Mail Detection improves outbound calling by identifying voicemail systems automatically. Instead of wasting time speaking into silence, your agent can leave a message or end the call smoothly, helping save call time, reduce costs, and improve overall calling efficiency.]]></description><link>https://www.videosdk.live/blog/how-to-enable-voice-mail-detection-in-ai-voice-agents</link><guid isPermaLink="false">69526a9b64df6f042b4d4b41</guid><category><![CDATA[ai telephony]]></category><category><![CDATA[SIP integration]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 08 Jan 2026 05:33:13 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/01/image--28-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/01/image--28-.png" alt="How to enable Voice Mail Detection in AI Voice Agents"/><p>When building outbound calling workflows, one of the most common challenge is handling unanswered calls that get redirected to voicemail systems. Without proper detection, an AI agent may continue speaking unnecessarily or wait indefinitely, leading to wasted resources and poor user experience.</p><p><strong>Voice Mail Detection</strong> in VideoSDK solves this problem by automatically identifying voicemail scenarios <em>and allowing your agent to take the appropriate action such as leaving a message or ending</em> the call gracefully.</p><h2 id="what-problem-this-solves">What Problem This Solves</h2><p>In outbound calling workflows, unanswered calls are often routed to voicemail systems. Without detection, agents may continue speaking or wait unnecessarily.</p><p>Voice Mail Detection lets you:</p><ul><li>Detect voicemail systems automatically</li><li>Control how your agent responds</li><li>End calls cleanly after voicemail handling</li></ul><h2 id="enabling-voice-mail-detection">Enabling Voice Mail Detection</h2><p>To use voicemail detection, import and add&nbsp;<code>VoiceMailDetector</code>&nbsp;to your agent configuration and register a callback that defines how voicemail should be handled.</p><pre><code class="language-python">from videosdk.agents import VoiceMailDetector
from videosdk.plugins.openai import OpenAILLM

async def voice_mail_callback(message):
    print("Voice Mail message received:", message)

voicemail = VoiceMailDetector(
    llm=OpenAILLM(),
    duration=5,
    callback=custom_callback_voicemail,
)

session = AgentSession(
    voice_mail_detector=voicemail
)</code></pre><h2 id="full-working-example">Full Working Example</h2><p>To set up incoming call handling, outbound calling, and routing rules, check out the&nbsp;<a href="https://docs.videosdk.live/telephony/ai-telephony-agent-quick-start#part-2-connect-your-agent-to-the-phone-network" rel="noopener noreferrer">Quick Start Example</a></p><pre><code class="language-python">import logging
from videosdk.agents import Agent, AgentSession, CascadingPipeline,WorkerJob,ConversationFlow, JobContext, RoomOptions, Options,VoiceMailDetector
from videosdk.plugins.deepgram import DeepgramSTT
from videosdk.plugins.openai import OpenAILLM
from videosdk.plugins.elevenlabs import ElevenLabsTTS
from videosdk.plugins.silero import SileroVAD
from videosdk.plugins.turn_detector import TurnDetector, pre_download_model

logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", handlers=[logging.StreamHandler()])
pre_download_model()
class VoiceAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions="You are a helpful voice assistant that can answer questions."
        )
    async def on_enter(self) -&gt; None:
        await self.session.say("Hello, how can I help you today?")
    
    async def on_exit(self) -&gt; None:
        await self.session.say("Goodbye!")
        
async def entrypoint(ctx: JobContext):
    
    agent = VoiceAgent()
    conversation_flow = ConversationFlow(agent)

    pipeline=CascadingPipeline(
        stt=DeepgramSTT(),
        llm=OpenAILLM(),
        tts=ElevenLabsTTS(),
        vad=SileroVAD(),
        turn_detector=TurnDetector()
    )
    
    async def voice_mail_callback(message):
        print("Voice Mail message received:", message)

    voice_mail_detector = VoiceMailDetector(llm=OpenAILLM(), duration=5.0, callback = voice_mail_callback)

    session = AgentSession(
        agent=agent, 
        pipeline=pipeline,
        conversation_flow=conversation_flow,
        voice_mail_detector = voice_mail_detector,
    )

    await session.start(wait_for_participant=True, run_until_shutdown=True)

def make_context() -&gt; JobContext:
    room_options = RoomOptions(name="Voice Mail Detector Test", playground=True)
    return JobContext(room_options=room_options) 
 
if __name__ == "__main__":
    job = WorkerJob(entrypoint=entrypoint, jobctx=make_context, options=Options(agent_id="YOUR_AGENT_ID", max_processes=2, register=True, host="localhost", port=8081))
    job.start()</code></pre><h3 id="conclusion">Conclusion</h3><p>Voice Mail Detection ensures your AI agent handles unanswered calls intelligently. By automatically detecting voicemail and triggering the right action, it prevents wasted time, improves call efficiency, and makes outbound workflows reliable and production-ready.</p><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ul><li>Explore the&nbsp;<strong>voice mail detection </strong><a href="https://github.com/videosdk-live/agents-quickstart/blob/main/Voice%20Mail%20Detector/voice_mail_detector.py" rel="noreferrer">implementation</a>&nbsp;on github.</li><li>Read <a href="https://docs.videosdk.live/ai_agents/core-components/voice-mail-detection" rel="noreferrer">voice mail detection</a> docs.</li><li>To set up inbound calls, outbound calls, and routing rules check out the&nbsp;<a href="https://docs.videosdk.live/telephony/managing-calls/making-outbound-calls" rel="noopener noreferrer">Quick Start Example</a>.</li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">deploy your AI Agents</a>.</li><li><strong>Explore more:</strong>&nbsp;Check out the&nbsp;<a href="https://dub.sh/b19X60T" rel="noopener noreferrer">VideoSDK documentation</a>&nbsp;for more features.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[Product Updates - December 2025 : New Billing & Pricing, AI Agents with Graphs & Fallback, and More!]]></title><description><![CDATA[Announcing our new transparent billing system and pricing for 2026! This month's update also gives your AI agents a "brain" with Conversational Graphs, makes them unstoppable with Provider Fallback, and adds powerful new video optimization features across all core SDKs.
]]></description><link>http://www.videosdk.live/blog/product-updates-december-2025</link><guid isPermaLink="false">695ccadd55831517a5a89d9c</guid><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 05 Jan 2026 13:25:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/01/13-1.jpg" medium="image"/><content:encoded><![CDATA[
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  
  <style>
    :root {
      --primary: #A497D9;
      --bg: #050608;
      --card-bg: #111217;
      --text-main: #E0E0E0;
      --text-muted: #A0A0A0;
      --border: #22242C;
    }
    body {
      font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      line-height: 1.7;
      color: var(--text-main);
      background-color: var(--bg);
      margin: 0;
      padding: 0;
    }
    .container {
      max-width: 850px;
      margin: 0 auto;
      padding: 60px 20px;
    }
    header {
      text-align: left;
      margin-bottom: 60px;
    }
    h1 {
      font-size: 42px;
      line-height: 1.2;
      color: #FFFFFF;
      margin-bottom: 20px;
    }
    h2 {
      font-size: 28px;
      color: var(--primary);
      margin-top: 50px;
      padding-bottom: 10px;
      border-bottom: 1px solid var(--border);
    }
    h3 {
      font-size: 22px;
      color: #FFFFFF;
      margin-top: 35px;
    }
    p {
      margin-bottom: 20px;
    }
    strong {
      color: #FFFFFF;
    }
    .card {
      background-color: var(--card-bg);
      border: 1px solid var(--border);
      border-radius: 12px;
      padding: 30px;
      margin: 30px 0;
    }
    .img-container {
      margin: 40px 0;
      text-align: center;
    }
    .img-container img {
      width: 100%;
      height: auto;
      border-radius: 8px;
      border: 1px solid var(--border);
      box-shadow: 0 10px 30px rgba(0,0,0,0.5);
    }
    .img-caption {
      font-size: 13px;
      color: var(--text-muted);
      margin-top: 10px;
      display: block;
    }
    ul, ol {
      margin-bottom: 20px;
      padding-left: 20px;
    }
    li {
      margin-bottom: 10px;
    }
    .highlight {
      color: var(--primary);
      font-weight: 600;
    }
    a {
      color: var(--primary);
      text-decoration: none;
    }
    a:hover {
      text-decoration: underline;
    }
    .cta-button {
        background-color: var(--primary);
        color: #000000;
        padding: 6px 20px;
        border-radius: 6px;
        font-size: 15px;
        font-weight: bold;
        display: inline-block;
        text-decoration: none;
    }
    .cta-box {
      text-align: left;
      background: linear-gradient(135deg, #111217 0%, #1a1b23 100%);
      padding: 40px;
      border-radius: 12px;
      border: 1px solid var(--primary);
      margin: 60px 0;
    }
    hr {
      border: 0;
      border-top: 1px solid var(--border);
      margin: 60px 0;
    }
    @media (max-width: 600px) {
      h1 { font-size: 32px; }
      .container { padding: 40px 15px; }
    }
  </style>
</meta></meta></head>
<body>

  <div class="container">
    <header>
      
      <img src="https://assets.videosdk.live/static-assets/ghost/2026/01/13-1.jpg" alt="Product Updates - December 2025 : New Billing & Pricing, AI Agents with Graphs & Fallback, and More!"/><p style="font-size: 18px; color: var(--text-muted);">A complete recap of our biggest platform and product updates from December 2025.</p>
    </header>

    <p>Welcome to the December edition of the VideoSDK Monthly Updates! As we close out the year, we’re launching our most significant platform update yet: a completely redesigned <span class="highlight">transparent billing system and new pricing for 2026</span>.</p>
    <p>On the product front, our AI Agents have gained a "brain" with <strong>Conversational Graph support</strong>, become more resilient with <strong>provider fallback and recovery</strong>, and we’ve rolled out powerful <strong>video optimization features</strong> across all our core SDKs. This is a huge one, let's get started!</p>

    <hr>

    <h2>New Billing Dashboard & Pricing for 2026</h2>
    <p>Our mission has always been to empower developers with world-class infrastructure. As we head into 2026, we're taking a massive leap forward by making our billing as scalable, transparent, and real-time as our infrastructure.</p>
    <p>We have replaced traditional monthly billing with a high-performance <strong>Prepaid Wallet system</strong>, giving you complete visibility and control over your spending in real time.</p>

    <h3>Key Highlights of the New System:</h3>
    <ul>
        <li><strong>The Prepaid Wallet:</strong> No more month-end invoices. See your real-time balance and top up instantly.</li>
        <li><strong>$20 "Start Building" Balance:</strong> Every new account now receives a one-time $20 free balance immediately upon signup. No credit card required.</li>
        <li><strong>Simplified Plans:</strong> Our new Plans tab (Free, Pay-As-You-Go, Enterprise) makes it easy to find the right fit for your stage.</li>
        <li><strong>On-Demand Scaling:</strong> Manage concurrency, agent sessions, and recording limits in real-time from the new "Usage Limits" tab.</li>
        <li><strong>Redesigned Billing Dashboard:</strong> A cleaner, more intuitive experience to manage payments, view spending, and download invoices.</li>
    </ul>

    <div class="card">
      <h3 style="margin-top: 0;">Read the Full Announcement</h3>
      <p>This is a fundamental upgrade to our platform designed for total transparency and control. For all the details, including notes for existing users, check out our dedicated blog post.</p>
      <a href="https://www.videosdk.live/blog/videosdk-pricing-2026-billing-dashboard" class="cta-button">Read the Full Announcement</a>
    </div>

    <hr>

    <h2>Major AI Advancements: Building Smarter, More Resilient Agents</h2>
    <p>This month, the Agents SDK hit its 50th release and gained some of its most powerful features to date, focusing on workflow control, reliability, and an expanded ecosystem.</p>

    <h3><a href="https://docs.videosdk.live/ai_agents/core-components/conversational-graph">Introducing Conversational Graphs (Agents SDK v0.0.51)</a></h3>
    <p>Give your agents a "brain." This groundbreaking feature lets you design stateful, deterministic agent workflows using states and transitions. It's the ultimate tool for building complex, reliable, and strictly controlled conversational AI, from customer support flows to structured data collection.</p>
    
    <h3><a href="https://docs.videosdk.live/ai_agents/core-components/fallback-adapter">Unprecedented Reliability with Provider Fallback (Agents SDK v0.0.53)</a></h3>
    <p>Never worry about a single provider failure again. You can now configure a prioritized list of STT, LLM, and TTS providers. If a primary provider fails, the agent will automatically and seamlessly fall back to a secondary one, with cooldown-based recovery to switch back when the service is healthy.</p>

    <h3>Advanced Telephony & Agent Control (Agents SDK v0.0.48 & v0.0.49)</h3>
    <p>We've added a suite of powerful telephony features:</p>
    <ul>
        <li><a href="https://docs.videosdk.live/ai_agents/core-components/call-transfer"><strong>SIP Call Transfer:</strong></a> Transfer an ongoing SIP call to another phone number or SIP endpoint.</li>
        <li><a href="https://docs.videosdk.live/ai_agents/core-components/multi-agent-switching"><strong>Multi-Agent Switch:</strong></a> Seamlessly hand off a conversation from one agent to another (e.g., from a general agent to a booking specialist), with optional context inheritance.</li>
        <li><a href="https://docs.videosdk.live/ai_agents/core-components/dtmf-events"><strong>DTMF Handling</strong></a> & <a href="https://docs.videosdk.live/ai_agents/core-components/voice-mail-detection"><strong>Voicemail Detection:</strong></a> Capture keypad input and automatically detect voicemails to trigger callbacks.</li>
    </ul>

    <h3>An Ever-Expanding AI Ecosystem (Agents SDK v0.0.52 & v0.0.55)</h3>
    <p>We've massively expanded our plugin support, adding integrations for <strong>Google Vertex AI</strong>, <a href="https://docs.videosdk.live/ai_agents/plugins/realtime/xai-grok"><strong>xAI (Grok) Realtime Voice & LLM</strong></a>, <a href="https://docs.videosdk.live/ai_agents/plugins/tts/murf-ai-tts"><strong>MurfAI TTS</strong></a>, <a href="https://docs.videosdk.live/ai_agents/plugins/realtime/ultravox"><strong>Ultravox Realtime</strong></a>, and <a href="https://docs.videosdk.live/ai_agents/plugins/stt/gladia"><strong>Gladia.IO STT</strong></a>.</p>
    
    <hr>

    <h2>Core SDK Enhancements: Video Optimization & Quality Monitoring</h2>
    <p>We've rolled out powerful new features across our core SDKs to give you more control over video quality and a deeper understanding of stream health.</p>

    <h3>Advanced Video Track Optimization</h3>
    <p>Now available on <strong>JS, React, React Native, and Flutter SDKs</strong>, these new parameters in <strong>createCameraVideoTrack()</strong> give you granular control over quality and bandwidth:</p>
    <ul>
        <li><strong>bitrateMode</strong>: Choose between <strong>high_quality</strong>, <strong>balanced</strong>, and <strong>bandwidth_optimized</strong>.</li>
        <li><strong>maxLayer</strong>: Specify the maximum number of simulcast layers to publish.</li>
    </ul>
    
    <h3>Real-Time Quality Monitoring</h3>
    <p>Our <strong>iOS and Flutter SDKs</strong> now feature a <span class="highlight">Quality Limitation Event</span> to detect bandwidth, network, or CPU issues on the local device, and a <span class="highlight">Stream State Change</span> method/event to monitor remote streams for freeze, stuck, or recovery events.</p>
    
    <hr>

    <h2>📚 New Content & Resources</h2>
    <p>Explore our latest guides, tutorials, and videos to get the most out of these new features.</p>
    
    <h3>New Guides & Tutorials</h3>
    <ul>
      <li><strong>Build an AI WhatsApp Voice Agent:</strong> <a href="https://dev.to/chaitrali_kakde/how-to-build-an-ai-whatsapp-voice-agent-with-videosdk-step-by-step-guide-2o6l">A step-by-step guide to deploying your first agent on WhatsApp.</a></li>
      <li><strong>Enable Preemptive Responses:</strong> <a href="https://www.videosdk.live/blog/how-to-enable-preemptive-response-in-ai-voice-agents">Learn how to make your agents respond faster with preemptive transcript generation.</a></li>
      <li><strong>Handle DTMF Events:</strong> <a href="https://www.videosdk.live/blog/dtmf-events-in-telephony-ai-agent">A deep dive into capturing and using keypad tones in your telephony agents.</a></li>
      <li><strong>Implement Call Transfers:</strong> <a href="https://www.videosdk.live/blog/how-to-transfer-calls-in-ai-voice-agents">Master the art of seamlessly transferring calls between agents or to phone numbers.</a></li>
    </ul>

    <h3>Featured Videos</h3>
    <ul>
        <li>▶️ <a href="https://dub.sh/znk9osA">Preemptive Response for AI Voice Agents</a></li>
        <li>▶️ <a href="https://dub.sh/j1KDeuN">DTMF Events for SIP AI Voice Agents</a></li>
        <li>▶️ <a href="https://dub.sh/wGsFwYu">Call Transfer for AI Voice Agents</a></li>
    </ul>

    <hr>

    <h2>✨ Community Spotlight</h2>
    
    <div class="img-container">
      <a href="https://www.videosdk.live/customers/exterview">
        <img src="https://strapi.videosdk.live/uploads/exterview_case_study_481edf1d53.png" alt="Product Updates - December 2025 : New Billing & Pricing, AI Agents with Graphs & Fallback, and More!" style="border: none; box-shadow: none;">
      </img></a>
    </div>

    <div style="border-left: 3px solid var(--primary); padding-left: 20px; margin-top: 30px; margin-bottom: 30px;">
        <a href="https://www.videosdk.live/customers/exterview" style="font-size: 18px; line-height: 1.5;">Explore how Exterview builds a global asynchronous video interview platform with VideoSDK.</a>
    </div>
    
    <h2>SDK Sketches</h2>
    <div class="img-container">
      <!-- Placeholder for the comic image -->
      <img src="https://strapi.videosdk.live/uploads/convo_graph_sketch_1c1e592ece.png" alt="Product Updates - December 2025 : New Billing & Pricing, AI Agents with Graphs & Fallback, and More!">
      <span class="img-caption">This month's sketch: The difference between a rigid, hard-coded AI and one powered by flexible Conversational Graphs.</span>
    </img></div>

    <hr>

    <h2>What's Next?</h2>
    <p>As we head into 2026, our focus remains on pushing the boundaries of what's possible with real-time communication and AI. Expect even more powerful tools, deeper platform integrations, and a relentless focus on the developer experience.</p>
    
    <div class="cta-box">
      <h3>Ready to Build with the Latest?</h3>
      <p>Upgrade your SDKs to the latest versions to take advantage of all these new features and improvements.</p>
      <a href="https://discord.com/invite/Gpmj6eCq5u" class="cta-button">Join our Discord Community</a>
    </div>

    
  </hr></hr></hr></hr></hr></hr></div>

</body>
</html>
<!--kg-card-end: html-->
]]></content:encoded></item><item><title><![CDATA[Announcing New Pricing: Free Credits, Simpler Pricing, and a Smarter Billing Dashboard]]></title><description><![CDATA[VideoSDK introduces a new Pay-As-You-Go On-Demand model and a redesigned Billing Dashboard featuring a $20 free balance, prepaid wallet, and real-time usage controls.]]></description><link>https://www.videosdk.live/blog/videosdk-pricing-2026-billing-dashboard</link><guid isPermaLink="false">695bee1855831517a5a89d2c</guid><category><![CDATA[ANNOUNCEMENT]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 31 Dec 2025 18:40:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/01/Price-1.png" medium="image"/><content:encoded><![CDATA[
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    :root {
      --primary: #A497D9;
      --bg: #050608;
      --card-bg: #111217;
      --text-main: #E0E0E0;
      --text-muted: #A0A0A0;
      --border: #22242C;
    }
    body {
      font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
      line-height: 1.7;
      color: var(--text-main);
      background-color: var(--bg);
      margin: 0;
      padding: 0;
    }
    .container {
      max-width: 850px;
      margin: 0 auto;
      padding: 60px 20px;
    }
    header {
      text-align: left;
      margin-bottom: 60px;
    }
    h1 {
      font-size: 42px;
      line-height: 1.2;
      color: #FFFFFF;
      margin-bottom: 20px;
    }
    h2 {
      font-size: 28px;
      color: var(--primary);
      margin-top: 50px;
      padding-bottom: 10px;
      border-bottom: 1px solid var(--border);
    }
    h3 {
      font-size: 22px;
      color: #FFFFFF;
      margin-top: 35px;
    }
    p {
      margin-bottom: 20px;
    }
    strong {
      color: #FFFFFF;
    }
    .card {
      background-color: var(--card-bg);
      border: 1px solid var(--border);
      border-radius: 12px;
      padding: 30px;
      margin: 30px 0;
    }
    .img-container {
      margin: 40px 0;
      text-align: center;
    }
    .img-container img {
      width: 100%;
      height: auto;
      border-radius: 8px;
      border: 1px solid var(--border);
      box-shadow: 0 10px 30px rgba(0,0,0,0.5);
    }
    .img-caption {
      font-size: 13px;
      color: var(--text-muted);
      margin-top: 10px;
      display: block;
    }
    ul, ol {
      margin-bottom: 20px;
      padding-left: 20px;
    }
    li {
      margin-bottom: 10px;
    }
    .highlight {
      color: var(--primary);
      font-weight: 600;
    }
    a {
      color: var(--primary);
      text-decoration: none;
    }
    a:hover {
      text-decoration: underline;
    }
    .cta-box {
      text-align: center;
      background: linear-gradient(135deg, #111217 0%, #1a1b23 100%);
      padding: 40px;
      border-radius: 12px;
      border: 1px solid var(--primary);
      margin: 60px 0;
    }
    hr {
      border: 0;
      border-top: 1px solid var(--border);
      margin: 60px 0;
    }
    @media (max-width: 600px) {
      h1 { font-size: 32px; }
      .container { padding: 40px 15px; }
    }
  </style>
</meta></meta></head>
<body>

  <div class="container">
    <header>
      <img src="https://assets.videosdk.live/static-assets/ghost/2026/01/Price-1.png" alt="Announcing New Pricing: Free Credits, Simpler Pricing, and a Smarter Billing Dashboard"/><p style="font-size: 18px; color: var(--text-muted);">Real-time scale. Transparent billing. Total control.</p>
    </header>

    <p>At VideoSDK, our mission has always been to empower developers to build world-class live video experiences without the complexity of infrastructure management. As we head into 2026, we are taking a massive leap forward by making our billing as scalable, transparent, and real-time as our infrastructure.</p>

    <p>Today, we are thrilled to announce our new Pricing plans and a completely redesigned <strong>Billing Dashboard</strong>.</p>

    <!-- Quick Links Navigation Grid -->
    <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; margin: 35px 0;">
        <a href="https://www.videosdk.live/pricing" target="_blank" style="text-decoration: none; background: #111217; border: 1px solid #22242C; padding: 16px; border-radius: 10px; transition: transform 0.2s ease, border-color 0.2s ease;">
            <div style="color: #A497D9; font-size: 10px; font-weight: 800; text-transform: uppercase; margin-bottom: 4px; letter-spacing: 0.5px;">Pricing & Plans</div>
            <div style="color: #FFFFFF; font-size: 20px; font-weight: 500;">View Plans</div>
        </a>
        <a href="https://docs.videosdk.live/help_docs/pricing" target="_blank" style="text-decoration: none; background: #111217; border: 1px solid #22242C; padding: 16px; border-radius: 10px; transition: transform 0.2s ease, border-color 0.2s ease;">
            <div style="color: #A497D9; font-size: 10px; font-weight: 800; text-transform: uppercase; margin-bottom: 4px; letter-spacing: 0.5px;">Common Questions</div>
            <div style="color: #FFFFFF; font-size: 20px; font-weight: 500;">Pricing & FAQs</div>
        </a>
        <a href="https://docs.videosdk.live/help_docs/quotas-and-limit" target="_blank" style="text-decoration: none; background: #111217; border: 1px solid #22242C; padding: 16px; border-radius: 10px; transition: transform 0.2s ease, border-color 0.2s ease;">
            <div style="color: #A497D9; font-size: 10px; font-weight: 800; text-transform: uppercase; margin-bottom: 4px; letter-spacing: 0.5px;">Usage Limits</div>
            <div style="color: #FFFFFF; font-size: 20px; font-weight: 500;">Quotas & Scale</div>
        </a>
        <a href="https://www.videosdk.live/contact" target="_blank" style="text-decoration: none; background: #111217; border: 1px solid #22242C; padding: 16px; border-radius: 10px; transition: transform 0.2s ease, border-color 0.2s ease;">
            <div style="color: #A497D9; font-size: 10px; font-weight: 800; text-transform: uppercase; margin-bottom: 4px; letter-spacing: 0.5px;">Need help?</div>
            <div style="color: #FFFFFF; font-size: 20px; font-weight: 500;">Book a call</div>
        </a>
    </div>

    <hr>

    <h2>1. The Power of the Prepaid Wallet</h2>
    <p>We’ve replaced traditional monthly billing cycles with a high-performance <strong>Prepaid Wallet system</strong>. Instead of waiting for a month-end invoice, you now have complete visibility and control over your spending in real-time.</p>
    
    <p><a href="https://app.videosdk.live/profile/billing?tab=overview" target="_blank"><strong>Go to Billing Overview →</strong></a></p>

    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/Overview_de99afd47f.png" alt="Announcing New Pricing: Free Credits, Simpler Pricing, and a Smarter Billing Dashboard">
      <span class="img-caption">Figure 1: The new Dashboard Overview with Real-Time Balance.</span>
    </img></div>

    <h3>Key Features of the Overview Tab:</h3>
    <ul>
      <li><strong>Real-Time Balance:</strong> Instantly see your available funds.</li>
      <li><strong>Quick Top-ups:</strong> Add funds with one click using preset amounts or custom values.</li>
      <li><strong>Auto-Reload:</strong> Never worry about service interruptions. Enable <a href="https://docs.videosdk.live/help_docs/pricing">Auto-Reload</a> to automatically top up your wallet when it falls below a threshold you set.</li>
      <li><strong>Spend Summary:</strong> A high-level view of your recent usage and costs.</li>
    </ul>

    <div class="card">
      <h3 style="margin-top: 0;">The $20 "Start Building" Balance</h3>
      <p>We believe every great idea deserves a chance to be built. That’s why starting today, <strong>every new account receives a one-time $20 free balance</strong> added to their wallet immediately upon signup. No credit card is required to start—just sign up and deploy your first AI Agent or Video Call room instantly.</p>
    </div>

    <hr>

    <h2>2. Simplified Plans for Every Stage</h2>
    <p>Whether you are a solo developer or a global enterprise, our new <a href="https://app.videosdk.live/profile/billing?tab=plans" target="_blank"><strong>Plans tab</strong></a> makes it easy to understand your trajectory.</p>

    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/Plans_85710a8adc.png" alt="Announcing New Pricing: Free Credits, Simpler Pricing, and a Smarter Billing Dashboard">
      <span class="img-caption">Figure 2: Compare and switch between flexible plans.</span>
    </img></div>

    <ul>
      <li><strong>Free Tier:</strong> Perfect for exploration, featuring the $20 free balance and community support.</li>
      <li><strong>Pay-As-You-Go (On-Demand):</strong> Our most popular choice for production apps. Scale seamlessly with <a href="https://www.videosdk.live/pricing">usage-based pricing</a> and high concurrency.</li>
      <li><strong>Enterprise:</strong> For high-volume demands requiring dedicated support, custom SLAs, and private cloud options.</li>
    </ul>

    <hr>

    <h2>3. Manage Add-ons & Compliance (Beta)</h2>
    <p>Security and compliance are no longer "manual" processes. Within the new <a href="https://app.videosdk.live/profile/billing?tab=addons" target="_blank"><strong>Add-ons tab</strong></a>, you can activate enterprise-grade compliance features with a single click.</p>

    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/Add_Ons_a9077c45a9.png" alt="Announcing New Pricing: Free Credits, Simpler Pricing, and a Smarter Billing Dashboard">
      <span class="img-caption">Figure 3: One-click activation for <a href="https://docs.videosdk.live/help_docs/security-and-privacy/iso-27001">ISO</a>, <a href="https://docs.videosdk.live/help_docs/security-and-privacy/soc2">SOC2</a>, <a href="https://docs.videosdk.live/help_docs/security-and-privacy/hipaa">HIPAA</a>, and <a href="https://docs.videosdk.live/help_docs/security-and-privacy/gdpr">GDPR</a> instantly.</span>
    </img></div>

    <p>Enable standards like <strong>ISO 27001</strong>, <strong>SOC2 Type II</strong>, <strong>HIPAA</strong>, and <strong>GDPR</strong> instantly. This tab also hosts powerful network features like <a href="https://docs.videosdk.live/help_docs/security-and-privacy/geo-fencing"><strong>Geo-fencing</strong></a> (restricting traffic to specific regions) and <a href="https://docs.videosdk.live/help_docs/security-and-privacy/cloud-proxy"><strong>Cloud Proxy</strong></a> (routing traffic through managed secure gates).</p>

    <hr>

    <h2>4. On-Demand Scaling with Usage Limits (Beta)</h2>
    <p>Gone are the days of emailing support to increase your concurrency limits. The <a href="https://app.videosdk.live/profile/billing?tab=concurrency" target="_blank"><strong>Usage Limits tab</strong></a> allows you to manage your capacity in real-time.</p>

    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/Usage_Limits_d8bdbaf762.png" alt="Announcing New Pricing: Free Credits, Simpler Pricing, and a Smarter Billing Dashboard">
      <span class="img-caption">Figure 4: Purchase and monitor limit packs on demand.</span>
    </img></div>

    <p>Need to host more <strong>Agent Sessions</strong>, increase <strong>Agent Deployments</strong>, or scale your <strong>Recordings</strong>? Simply purchase <a href="https://docs.videosdk.live/help_docs/quotas-and-limit-new"><strong>Usage Limit Packs</strong></a>. These packs are applied to your account instantly and run on a monthly subscription model, deducted from your wallet balance.</p>

    <hr>

    <h2>5. Security & Payment Management</h2>
    <p>Transparency extends to how you manage your data and payments. The <a href="https://app.videosdk.live/profile/billing?tab=billinginfo" target="_blank"><strong>Payment Details</strong></a> and <a href="https://app.videosdk.live/profile/billing?tab=invoices" target="_blank"><strong>Billing History</strong></a> tabs provide a clear audit trail.</p>

    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/Payment_Details_876c198e97.png" alt="Announcing New Pricing: Free Credits, Simpler Pricing, and a Smarter Billing Dashboard">
      <span class="img-caption">Figure 5: Manage cards and billing addresses securely.</span>
    </img></div>

    <ul>
      <li><strong>Secure Payments:</strong> Manage multiple credit cards and set default methods for Auto-Reload.</li>
      <li><strong>Verified Billing:</strong> Keep your business legal name, address, and VAT/GST details up to date for automated, compliant invoicing.</li>
    </ul>

    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/Billing_History_70fe9b2bf5.png" alt="Announcing New Pricing: Free Credits, Simpler Pricing, and a Smarter Billing Dashboard">
      <span class="img-caption">Figure 6: Download invoices and track transaction status.</span>
    </img></div>

    <p><strong>Billing History:</strong> Track every transaction, check due dates, and download official PDF invoices for your accounting records.</p>

    <hr>

    <h2>6. Real-Time Spend Insights (Beta)</h2>
    <p>Understanding where your money goes is critical for optimization. The <a href="https://app.videosdk.live/profile/billing?tab=spendinfo" target="_blank"><strong>Spend Info tab</strong></a> provides a granular breakdown of every cent spent.</p>

    <div class="img-container">
      <img src="https://strapi.videosdk.live/uploads/Spend_Info_2c8dbb9f80.png" alt="Announcing New Pricing: Free Credits, Simpler Pricing, and a Smarter Billing Dashboard">
      <span class="img-caption">Figure 7: High-resolution breakdown of usage and costs.</span>
    </img></div>

    <p>Track costs for:</p>
    <ul>
      <li><strong>Session Minutes:</strong> RTC and Agent usage.</li>
      <li><strong>Concurrency Packs:</strong> Real-time application of your monthly <a href="https://docs.videosdk.live/help_docs/quotas-and-limit-new">limit packs</a>.</li>
      <li><strong>Overage Handling:</strong> Clear visibility into any usage that exceeds your current prepaid limits.</li>
    </ul>

    <div class="cta-box">
      <h3>Ready to Scale in 2026?</h3>
      <p>The new billing dashboard is live! Log in now to explore the new experience and claim your balance.</p>
      <a href="https://app.videosdk.live/profile/billing" style="background-color: var(--primary); color: #000000; padding: 8px 20px; border-radius: 6px; font-size: 15px; font-weight: bold; display: inline-block;">Go to My Dashboard</a>
    </div>

    <hr>

    <h3>Note:</h3>
    
    <div class="card">
        <h4 style="margin-top: 0;">Existing Free Users</h4>
        <p>To help you explore our paid features, we’ve added <strong>$20 in free credit</strong> to your account.</p>
        <ul>
            <li>If you already see the $20 balance, you’re all set.</li>
            <li>If you don’t see it, your account may be inactive. Simply add your <a href="https://app.videosdk.live/profile/billing?tab=billinginfo">billing details</a> in the dashboard, and the $20 credit will be applied automatically.</li>
        </ul>

        <p><strong>What you need to do:</strong><br>
        Add your <a href="https://app.videosdk.live/profile/billing?tab=billinginfo">billing information</a> to activate your account and use your free balance. If the credit still doesn't appear, our support team will be happy to help.</br></p>
    </div>

    <div class="card">
        <h4 style="margin-top: 0;">Existing PAYG Users</h4>
        <p>We’ve ensured a smooth transition with no service interruption.
</p>
        <ul>
            <li>Your service will continue as usual until 31 January under Pay-As-You-Go (postpaid) billing.
</li>
            <li>Your January usage will be billed in February, and the invoice will be sent on 3 February.
</li>
            <li>From 3 February onward, all usage will be charged under the new pricing model.
</li>
            <li>Your account will move to the Pay-As-You-Go (PAYG) on-demand model (prepaid), where you can add funds to your wallet and manage usage in real time.
</li>

        </ul>
        <p><strong>What you need to do:</strong><br>
        Please add funds to your wallet before <strong>31 January</strong> and review your <a href="https://app.videosdk.live/profile/billing?tab=concurrency">usage limits</a>. If your usage is high, increase your limits to avoid any service disruption.</br></p>
    </div>

    <p>For a deeper dive into the numbers, check out our <a href="https://docs.videosdk.live/help_docs/pricing"><strong>Detailed Pricing FAQ</strong></a>.</p>

    <p style="margin-top: 60px;">
      Happy Building in 2026!<br>
      <strong>Team VideoSDK</strong>
    </br></p>
  </hr></hr></hr></hr></hr></hr></hr></div>

</body>
</html>
<!--kg-card-end: html-->
]]></content:encoded></item><item><title><![CDATA[How to Transfer Calls in AI Voice Agents Using SIP Telephony]]></title><description><![CDATA[Learn how to automatically transfer ongoing SIP call to another phone number without disconnecting the call or redialing using Call Transfer in SIP Telephony]]></description><link>https://www.videosdk.live/blog/how-call-transfer-works-in-ai-voice-agents</link><guid isPermaLink="false">694e2f7f64df6f042b4d4af1</guid><category><![CDATA[ai telephony]]></category><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 26 Dec 2025 13:53:28 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/12/Call-Transfer.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2025/12/Call-Transfer.png" alt="How to Transfer Calls in AI Voice Agents Using SIP Telephony"/><p>When someone calls a business, they’re usually looking for a quick and clear resolution not a conversation with a bot that can’t help them move forward. Sometimes it’s a billing issue. Sometimes it’s a sales inquiry. And sometimes, they just want to speak to a real person.</p><p>A well-designed AI voice agent knows when to assist and when to step aside. That’s where <strong>Call Transfer in VideoSDK</strong> comes in. It allows your AI agent to transfer an ongoing SIP call to the right person, without disconnecting the caller or breaking the flow of the conversation.</p><h2 id="what-is-call-transfer">What is Call Transfer</h2><p><strong>Call Transfer</strong> enables an AI agent to move an active SIP call to another phone number without ending the session. From the caller’s perspective, the transition is automatic, the call continues without dropping, there’s no need to redial, and the conversation flows naturally without awkward pauses or repeated explanations.</p><h3 id="how-it-works">How It Works</h3><ul><li>The agent evaluates the user’s intent to determine when a call transfer is required and then triggers the function tool.</li><li>When the function tool is triggered, it tells the system to move the call to another phone number.</li><li>The ongoing SIP call is forwarded to the new number instantly, without disconnecting or redialing.</li></ul><blockquote>Get started and sign up at <strong>VideoSDK </strong>to get your <a href="https://dub.sh/BVOvGNr" rel="noreferrer">authentication token</a></blockquote><h2 id="how-to-trigger-call-transfer">How To Trigger Call Transfer</h2><p>To set up incoming call handling, outbound calling, and routing rules, check out the&nbsp;<a href="https://docs.videosdk.live/telephony/ai-telephony-agent-quick-start#part-2-connect-your-agent-to-the-phone-network" rel="noopener noreferrer">Quick Start Example</a></p><pre><code class="language-python">from videosdk.agents import Agent, function_tool, 

class CallTransferAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions="You are the Call Transfer Agent Which Help and provide to transfer on going call to new number. use transfer_call tool to transfer the call to new number.",
        )

    async def on_enter(self) -&gt; None:
        await self.session.say("Hello Buddy, How can I help you today?")

    async def on_exit(self) -&gt; None:
        await self.session.say("Goodbye Buddy, Thank you for calling!")

    @function_tool
    async def transfer_call(self) -&gt; None:
        """Transfer the call to Provided number"""
        token = os.getenv("VIDEOSDK_AUTH_TOKEN")
        transfer_to = os.getenv("CALL_TRANSFER_TO") 
        return await self.session.call_transfer(token,transfer_to)</code></pre><h2 id="full-working-example">Full Working Example</h2><pre><code class="language-python">import logging
import os

from videosdk.agents import (Agent, AgentSession, CascadingPipeline, function_tool, WorkerJob, ConversationFlow, JobContext, RoomOptions, Options)
from videosdk.plugins.deepgram import DeepgramSTT
from videosdk.plugins.google import GoogleLLM
from videosdk.plugins.cartesia import CartesiaTTS
from videosdk.plugins.silero import SileroVAD
from videosdk.plugins.turn_detector import TurnDetector, pre_download_model

# Setup logging
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
    handlers=[logging.StreamHandler()]
)

# Pre-download turn detector model
pre_download_model()


class CallTransferAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions=(
                "You are the Call Transfer Agent. "
                "Help transfer ongoing calls to a new number using the transfer_call tool."
            )
        )

    async def on_enter(self) -&gt; None:
        await self.session.say("Hello Buddy, How can I help you today?")

    async def on_exit(self) -&gt; None:
        await self.session.say("Goodbye Buddy, Thank you for calling!")

    @function_tool
    async def transfer_call(self) -&gt; None:
        """Transfer the call to the provided number"""
        token = os.getenv("VIDEOSDK_AUTH_TOKEN")
        transfer_to = os.getenv("CALL_TRANSFER_TO")
        return await self.session.call_transfer(token, transfer_to)


async def entrypoint(ctx: JobContext):
    agent = CallTransferAgent()
    conversation_flow = ConversationFlow(agent)

    pipeline = CascadingPipeline(
        stt=DeepgramSTT(),
        llm=GoogleLLM(),
        tts=CartesiaTTS(),
        vad=SileroVAD(),
        turn_detector=TurnDetector()
    )

    session = AgentSession(
        agent=agent,
        pipeline=pipeline,
        conversation_flow=conversation_flow
    )

    await session.start(wait_for_participant=True, run_until_shutdown=True)


def make_context() -&gt; JobContext:
    room_options = RoomOptions(name="Call Transfer Agent", playground=True)
    return JobContext(room_options=room_options)


if __name__ == "__main__":
    job = WorkerJob(
        entrypoint=entrypoint,
        jobctx=make_context,
        options=Options(
            agent_id="YOUR_AGENT_ID",
            register=True,
            host="localhost",
            port=8081
        )
    )
    job.start()</code></pre><h2 id="conclusion">Conclusion</h2><p>Call Transfer transforms your AI voice agent from a simple responder into a capable call-handling system. By automatically routing ongoing SIP calls to the right person, it ensures users never experience dropped calls or awkward handoffs. </p><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ul><li>Explore the&nbsp;<strong>call-transfer</strong><a href="https://github.com/videosdk-live/agents-quickstart/blob/main/Call%20Transfer/call_transfer.py" rel="noreferrer">-implementation</a>&nbsp;on github.</li><li>To set up inbound calls, outbound calls, and routing rules check out the&nbsp;<a href="https://docs.videosdk.live/telephony/managing-calls/making-outbound-calls" rel="noopener noreferrer">Quick Start Example</a>.</li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">deploy your AI Agents</a>.</li><li>Sign up at VideoSDK - <a href="https://dub.sh/BVOvGNr" rel="noreferrer">authentication token</a></li><li><strong>Explore more:</strong>&nbsp;Check out the&nbsp;<a href="https://dub.sh/b19X60T" rel="noopener noreferrer">VideoSDK documentation</a>&nbsp;for more features.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[How to enable DTMF Events in Telephony AI Agent]]></title><description><![CDATA[Learn how DTMF input powers reliable, menu-driven voice interactions. This blog explores common use cases and shows how VideoSDK voice agents process real-time keypad events to drive precise call flows.]]></description><link>https://www.videosdk.live/blog/dtmf-events-in-telephony-ai-agent</link><guid isPermaLink="false">6949321e64df6f042b4d4aa5</guid><category><![CDATA[ai telephony]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 24 Dec 2025 10:24:43 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/12/dtmf-event-thumbnail.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2025/12/dtmf-event-thumbnail.png" alt="How to enable DTMF Events in Telephony AI Agent"/><p>Not every caller wants to speak to a voice agent. In many call scenarios, users expect to press a key to make a selection, confirm an action, or move forward in a call flow. This is especially common in menu-based systems, short responses, or situations where speech recognition may not be reliable.</p><p>DTMF (Dual-Tone Multi-Frequency) input gives voice agents a clear and predictable way to handle these interactions. When a caller presses a key on their phone, the agent receives that input instantly and can use it to control the call flow or trigger application logic.</p><p>In this post, we’ll explore how DTMF events can be used in a VideoSDK-powered voice agent, starting from common interaction patterns and moving into how the system processes keypad input in real time.</p><h3 id="typical-interaction-patterns-using-dtmf">Typical Interaction Patterns Using DTMF</h3><p>DTMF input is commonly used at decision points in a call, such as:</p><ul><li>Selecting options from a call menu</li><li>Confirming or canceling an action</li><li>Providing short numeric input</li><li>Navigating between steps in a call flow</li></ul><p>These interactions are simple, fast, and familiar to callers, which makes them a good fit for structured voice experiences.</p><h2 id="how-it-works">How It Works</h2><ul><li><strong>DTMF Event Detection</strong>: The agent detects key presses (0–9, *, #) from the caller during a call session.</li><li><strong>Real-Time Processing</strong>: Each key press generates a DTMF event that is delivered to the agent immediately.</li><li><strong>Callback Integration</strong>: A user-defined callback function handles incoming DTMF events.</li><li><strong>Action Execution</strong>: The agent executes actions or triggers workflows based on the received DTMF input like building IVR flows, collecting user input, or triggering actions in your application.</li></ul><h2 id="step-1-enabling-dtmf-events">Step 1 : Enabling DTMF Events</h2><p>DTMF event detection can be enabled in two ways:</p><ul><li><strong>Via Dashboard:</strong><ul><li>When creating or editing a SIP gateway in the <a href="https://dub.sh/zXYQt7V" rel="noreferrer">VideoSDK dashboard</a>, enable the&nbsp;<code>DTMF</code>&nbsp;option.</li></ul></li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/12/DTMF-events--1-.png" class="kg-image" alt="How to enable DTMF Events in Telephony AI Agent" loading="lazy" width="1598" height="833"/></figure><ul><li><strong>Via API:</strong><ul><li>Set the&nbsp;<code>enableDtmf</code>&nbsp;parameter to&nbsp;<code>true</code>&nbsp;when creating or updating a SIP gateway using the API.</li></ul></li></ul><pre><code class="language-python">curl 	-H 'Authorization: $YOUR_TOKEN' \ 
  -H 'Content-Type: application/json' \ 
  -d '{
  	"name" : "Twilio Inbound Gateway",
    "enableDtmf" : "true",
  	"numbers" : ["+0123456789"]

  }' \ 
  -XPOST https://api.videosdk.live/v2/sip/inbound-gateways</code></pre><p>Once enabled, DTMF events will be detected and published for all calls routed through that gateway.</p><h2 id="step-2-implementation">Step 2 .  Implementation</h2><p>To set up inbound calls, outbound calls, and routing rules check out the&nbsp;<a href="https://docs.videosdk.live/telephony/managing-calls/making-outbound-calls" rel="noopener noreferrer">Quick Start Example</a>.</p><pre><code class="language-python">from videosdk.agents import AgentSession, DTMFHandler

async def entrypoint(ctx: JobContext):
  
    async def dtmf_callback(digit: int):
        if digit == 1:
            agent.instructions = "You are a Sales Representative. Your goal is to sell our products"
            await agent.session.say(
                "Routing you to Sales. Hi, I'm from Sales. How can I help you today?"
            )
        elif digit == 2:
            agent.instructions = "You are a Support Specialist. Your goal is to help customers with technical issues."
            await agent.session.say(
                "Routing you to Support. Hi, I'm from Support. What issue are you facing?"
            )
        else:
            await agent.session.say(
                "Invalid input. Press 1 for Sales or 2 for Support."
            )

    dtmf_handler = DTMFHandler(dtmf_callback)

    session = AgentSession(
        dtmf_handler = dtmf_handler,
    )</code></pre><h2 id="full-working-example">Full Working Example</h2><pre><code class="language-python">import logging
from videosdk.agents import Agent, AgentSession, CascadingPipeline,WorkerJob,ConversationFlow, JobContext, RoomOptions, Options,DTMFHandler
from videosdk.plugins.deepgram import DeepgramSTT
from videosdk.plugins.openai import OpenAILLM
from videosdk.plugins.elevenlabs import ElevenLabsTTS
from videosdk.plugins.silero import SileroVAD
from videosdk.plugins.turn_detector import TurnDetector, pre_download_model

logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", handlers=[logging.StreamHandler()])
pre_download_model()
class VoiceAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions="You are a helpful voice assistant that can answer questions."
        )
    async def on_enter(self) -&gt; None:
        await self.session.say("Hello, how can I help you today?")
    
    async def on_exit(self) -&gt; None:
        await self.session.say("Goodbye!")
        
async def entrypoint(ctx: JobContext):
    
    agent = VoiceAgent()
    conversation_flow = ConversationFlow(agent)

    pipeline=CascadingPipeline(
        stt=DeepgramSTT(),
        llm=OpenAILLM(),
        tts=ElevenLabsTTS(),
        vad=SileroVAD(),
        turn_detector=TurnDetector()
    )
    
    async def dtmf_callback(message):
        print("DTMF message received:", message)

    dtmf_handler = DTMFHandler(dtmf_callback)

    session = AgentSession(
        agent=agent, 
        pipeline=pipeline,
        conversation_flow=conversation_flow,
        dtmf_handler = dtmf_handler,
    )

    await session.start(wait_for_participant=True, run_until_shutdown=True)

def make_context() -&gt; JobContext:
    room_options = RoomOptions(name="DTMF Agent Test", playground=True)
    return JobContext(room_options=room_options) 
 
if __name__ == "__main__":
    job = WorkerJob(entrypoint=entrypoint, jobctx=make_context, options=Options(agent_id="YOUR_AGENT_ID", max_processes=2, register=True, host="localhost", port=8081))
    job.start()</code></pre><p>By enabling DTMF detection and handling events at the agent level, you can build predictable call flows, guide users through menus, and trigger application logic without interrupting the call experience. When combined with voice input, DTMF gives you more control over how users interact with your agent.</p><p>This makes DTMF a practical addition to any voice agent that needs clear, deterministic user input during a call.</p><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ul><li>Explore the&nbsp;<strong>dtmf-event</strong><a href="https://github.com/videosdk-live/agents-quickstart/blob/main/DTMF%20Handler/dtmf_handler.py" rel="noreferrer">-implementation-example</a>&nbsp;for full code implementation.</li><li>To set up inbound calls, outbound calls, and routing rules check out the&nbsp;<a href="https://docs.videosdk.live/telephony/managing-calls/making-outbound-calls" rel="noopener noreferrer">Quick Start Example</a>.</li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">deploy your AI Agents</a>.</li><li><strong>Explore more:</strong>&nbsp;Check out the&nbsp;<a href="https://docs.videosdk.live/ai_agents/core-components/dtmf-events" rel="noreferrer">VideoSDK documentation</a>&nbsp;for more features.</li><li>👉 Share your thoughts, roadblocks, or success stories in the comments or join our&nbsp;<a href="https://dub.sh/yDV95i6" rel="noopener noreferrer">Discord community ↗</a>. We’re excited to learn from your journey and help you build even better AI-powered communication tools!</li></ul>]]></content:encoded></item><item><title><![CDATA[How to enable preemptive response in AI Voice Agents]]></title><description><![CDATA[Learn how Preemptive Response reduces voice AI latency by streaming partial transcripts to the LLM, enabling faster and more natural conversational agents.]]></description><link>https://www.videosdk.live/blog/how-to-enable-preemptive-response-in-ai-voice-agents</link><guid isPermaLink="false">693f8ddf64df6f042b4d4a37</guid><category><![CDATA[preemtive-response]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 15 Dec 2025 09:12:06 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/12/preemptive-response-thumbnail.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2025/12/preemptive-response-thumbnail.png" alt="How to enable preemptive response in AI Voice Agents"/><p>When it comes to voice AI, the real challenge isn’t speed <strong>it’s timing</strong>.</p><p>A response that arrives a second too late feels unnatural. That tiny pause is enough to remind users they’re talking to a machine. Humans don’t wait for sentences to end. We anticipate intent and respond at the right moment. Traditional voice agents don’t. They wait for silence and that’s what makes conversations feel slow.</p><p><strong>Preemptive Response</strong> fixes this by letting voice agents start understanding and preparing responses while the user is still speaking.</p><h2 id="what-is-preemptive-response">What Is Preemptive Response?</h2><p>Preemptive Response is a capability that allows a voice agent to start understanding a user’s intent <strong>before they finish speaking</strong>.</p><p>As the user talks, the Speech-to-Text engine emits <strong>partial transcripts in real time</strong>. These partial results are enough for the agent to begin reasoning early, instead of waiting for the full sentence and a moment of silence.</p><p>The goal isn’t to interrupt the user it’s to be <em>ready</em> at the right moment.</p><h2 id="how-preemptive-response-works">How Preemptive response works</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/12/preemptive-response-1.png" class="kg-image" alt="How to enable preemptive response in AI Voice Agents" loading="lazy" width="2766" height="1571"/></figure><ul><li>User audio is streamed to the STT, which generates partial transcripts.</li><li>These partial transcripts are immediately sent to the LLM to enable preemptive (early) responses.</li><li>The LLM output is then passed to the TTS to generate the spoken response.</li></ul><h2 id="enabling-preemptive-response">Enabling Preemptive Response</h2><p>To enable this feature, set the&nbsp;<code>enable_preemptive_generation</code>&nbsp;flag to&nbsp;<code>True</code>&nbsp;when initializing your STT plugin (e.g.,&nbsp;<code>DeepgramSTTV2</code>).</p><pre><code class="language-python">from videosdk.plugins.deepgram import DeepgramSTTV2

stt = DeepgramSTTV2(
    enable_preemptive_generation=True
)</code></pre><p>Once enabled, partial transcripts start flowing automatically and your agent begins preparing responses earlier by design.</p><blockquote>Currently, preemptive response generation is limited to Deepgram’s STT implementation and is available only in the Flux model.</blockquote><h2 id="implementation">Implementation</h2><h3 id="prerequisites">Prerequisites</h3><ul><li>A VideoSDK authentication token (generate from&nbsp;<a href="https://app.videosdk.live/" rel="noopener noreferrer">app.videosdk.live</a>), follow to guide to&nbsp;<a href="https://docs.videosdk.live/ai_agents/authentication-and-token">generate videosdk token</a></li><li>A VideoSDK meeting ID (you can generate one using the&nbsp;<a href="https://docs.videosdk.live/api-reference/realtime-communication/create-room" rel="noopener noreferrer">Create Room API</a>)</li><li><a href="https://www.python.org/downloads/release/python-3120/" rel="noreferrer">Python 3.12 or higher</a></li></ul><h3 id="install-dependencies">Install dependencies</h3><pre><code class="language-python">pip install "videosdk-agents[deepgram,openai,elevenlabs,silero,turn_detector]"</code></pre><h3 id="set-api-keys-in-env">Set API Keys in .env</h3><pre><code class="language-python">DEEPGRAM_API_KEY = "Your Deepgram API Key"
OPENAI_API_KEY = "Your OpenAI API Key"
ELEVENLABS_API_KEY = "Your ElevenLabs API Key"
VIDEOSDK_AUTH_TOKEN = "VideoSDK Auth token"</code></pre><div class="kg-card kg-callout-card kg-callout-card-yellow"><div class="kg-callout-text">Get API keys&nbsp;<a href="https://console.deepgram.com/" target="_blank" rel="noopener noreferrer">Deepgram ↗</a>,&nbsp;<a href="https://platform.openai.com/api-keys" target="_blank" rel="noopener noreferrer">OpenAI ↗</a>,&nbsp;<a href="https://elevenlabs.io/app/settings/api-keys" target="_blank" rel="noopener noreferrer">ElevenLabs ↗</a>&nbsp;&amp;&nbsp;<a href="https://docs.videosdk.live/ai_agents/[https://app.videosdk.live](https://app.videosdk.live/api-keys)" target="_blank" rel="noopener noreferrer">VideoSDK Dashboard ↗</a>&nbsp;follow to guide to&nbsp;<a href="https://docs.videosdk.live/ai_agents/authentication-and-token" target="_blank" rel="noopener noreferrer">generate videosdk token</a></div></div><h2 id="full-working-example">Full Working Example</h2><pre><code class="language-python">import asyncio
import os
from videosdk.agents import Agent, AgentSession, CascadingPipeline, JobContext, RoomOptions, WorkerJob, ConversationFlow
from videosdk.plugins.silero import SileroVAD
from videosdk.plugins.turn_detector import TurnDetector, pre_download_model
from videosdk.plugins.deepgram import DeepgramSTTV2
from videosdk.plugins.openai import OpenAILLM
from videosdk.plugins.elevenlabs import ElevenLabsTTS

# Pre-download the Turn Detector model to avoid delays during startup
pre_download_model()

class MyVoiceAgent(Agent):
    def __init__(self):
        super().__init__(instructions="You are a helpful voice assistant that can answer questions and help with tasks.")

    async def on_enter(self):
        await self.session.say("Hello! How can I help you today?")

    async def on_exit(self):
        await self.session.say("Goodbye!")

async def start_session(context: JobContext):
    # 1. Create the agent and conversation flow
    agent = MyVoiceAgent()
    conversation_flow = ConversationFlow(agent)

    # 2. Define the pipeline with Preemptive Generation enabled
    pipeline = CascadingPipeline(
        stt=DeepgramSTTV2(
            model="flux-general-en",
            enable_preemptive_generation=True  # Enable low-latency partials
        ),
        llm=OpenAILLM(model="gpt-4o"),
        tts=ElevenLabsTTS(model="eleven_flash_v2_5"),
        vad=SileroVAD(threshold=0.35),
        turn_detector=TurnDetector(threshold=0.8)
    )

    # 3. Initialize the session
    session = AgentSession(
        agent=agent,
        pipeline=pipeline,
        conversation_flow=conversation_flow
    )

    try:
        await context.connect()
        await session.start()
        # Keep the session running
        await asyncio.Event().wait()
    finally:
        # Clean up resources
        await session.close()
        await context.shutdown()

def make_context() -&gt; JobContext:
    room_options = RoomOptions(
        name="VideoSDK Cascaded Agent",
        playground=True
    )
    return JobContext(room_options=room_options)

if __name__ == "__main__":
    job = WorkerJob(entrypoint=start_session, jobctx=make_context)
    job.start()</code></pre><h4 id="run-the-python-script">Run the Python Script</h4><pre><code class="language-python">python main.py</code></pre><p>You can also use console for running the script :</p><pre><code class="language-python">python main.py console</code></pre><p>With Preemptive Response enabled, the voice agent no longer waits for speech to end. It begins processing intent as audio arrives, reducing latency and keeping conversations natural. The result is a responsive, end-to-end voice experience that feels fluid in real time.</p><h2 id="next-steps">Next Steps</h2><ol><li>Explore the&nbsp;<a href="https://docs.videosdk.live/ai_agents/core-components/preemptive-response" rel="noreferrer">preemptive-response-docs</a>&nbsp;for more information.</li><li>Learn how to&nbsp;<a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">deploy your AI Agents</a>.</li><li>Visit D<a href="https://developers.deepgram.com/docs/flux/quickstart" rel="noreferrer">eepgram's flux documentation</a>.</li></ol>]]></content:encoded></item><item><title><![CDATA[Product Updates - November 2025 : Agent Runtime, WHIP/WHEP and Realtime Data Store]]></title><description><![CDATA[This month, we're changing the game for AI development. Introducing the Agent Runtime, our new no-code/low-code agent builder! Plus, WHIP/WHEP docs, sync data with the new Realtime Store, and check out our full suite of new quickstart guides.
]]></description><link>http://www.videosdk.live/blog/product-updates-november-2025</link><guid isPermaLink="false">6926a5ab64df6f042b4d4952</guid><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 28 Nov 2025 14:48:27 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/12/1-1.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>Welcome to the November edition of the VideoSDK Monthly Updates! This month, we’re changing the game for AI development with the launch of our<strong> Agent Runtime, a No-Code/Low-Code Agent Builder </strong>on the dashboard which will also allow you to add <strong>Knowledge Base </strong>from dashboard. We're also giving your AI agents&nbsp;<strong>vision capabilities</strong>&nbsp;now with <strong>OpenAI Realtime</strong> and rolling out the&nbsp;<strong>Realtime Store</strong>, a powerful new data synchronization feature across all major SDKs. Let’s dive into the biggest updates!</blockquote><h2 id="build-ai-agents-runtime-with-no-code"><strong>Build AI Agents </strong>Runtime<strong> with No Code</strong></h2><img src="https://assets.videosdk.live/static-assets/ghost/2025/12/1-1.jpg" alt="Product Updates - November 2025 : Agent Runtime, WHIP/WHEP and Realtime Data Store"/><p>We are thrilled to announce the launch of the&nbsp;<strong>Agent Runtime</strong>, our new no-code/low-code AI agent builder, now live on your developer dashboard!</p><p>Building, testing, and deploying powerful conversational AI has never been easier. The Agent Runtime allows you to create and configure complex AI agents through an intuitive visual interface, dramatically reducing development time and making advanced AI accessible to everyone. Connect your favorite LLMs, configure responses, and deploy agents without writing a single line of code.</p><h3 id="connect-a-knowledge-base-from-the-dashboard"><strong>Connect a Knowledge Base from the Dashboard</strong></h3><p>Making your agents smarter is now just a few clicks away. You can now&nbsp;<strong>upload documents and create a knowledge base directly from the dashboard</strong>. Our system automatically handles the vectorization and retrieval (RAG), allowing your no-code agents to provide accurate answers based on your own custom data. It's the easiest way to build a specialized, expert AI agent.</p><ul><li><a href="https://www.google.com/url?sa=E&amp;q=link-to-dashboard"><strong>Start Building with the Agent Runtime Today!</strong></a></li><li><a href="https://docs.videosdk.live/ai_agents/agent-runtime/build-agent" rel="noreferrer">Checkout the docs here</a> </li></ul><h2 id="new-feature-spotlight-the-realtime-store"><strong>New Feature Spotlight: The Realtime Store</strong></h2><p>We're excited to introduce the&nbsp;<strong>Realtime Store</strong>, a synchronized key-value database built directly into your meeting sessions. This powerful feature acts as a shared data layer, allowing you to store, update, and observe custom data across all participants in real time.</p><p>It's perfect for building collaborative features like shared whiteboards, live polls, synchronized presentations, or tracking any shared state within your application.</p><p><strong>The Realtime Store is now available on:</strong></p><ul><li><strong>JavaScript SDK</strong>&nbsp;(&gt;v0.3.10)</li><li><strong>React SDK</strong>&nbsp;(&gt;v0.4.10) </li><li><strong>React Native SDK</strong>&nbsp;(&gt;v0.5.0)</li><li><strong>iOS SDK</strong>&nbsp;(&gt;v2.2.7)</li><li><strong>Android SDK</strong>&nbsp;(&gt;v1.1.0)</li><li>=&gt; <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/realtimestore" rel="noreferrer">View Docs</a></li></ul><h2 id="ai-agents-vision-updates-a-simpler-lifecycle"><strong>AI Agents Vision Updates &amp; A Simpler Lifecycle</strong></h2><p>We are fully invested in our Agents SDK and have given tones of upgrade this month, making agents smarter, more capable, and easier to manage.</p><ul><li><strong>Enhanced Vision Capabilities (Agents SDK v0.0.42):</strong>&nbsp;<ul><li>Vision in cascading pipeline! With the new&nbsp;<strong>capture_frames()&nbsp;</strong>method, you can pass video frames directly into your agent's&nbsp;<strong>reply()&nbsp;</strong>method. This unlocks powerful new use cases like real-time visual analysis, describing on-screen activity, and more in either of the pipelines. We've even added support for continuous vision frame processing in our OpenAI and Gemini Live plugins.</li></ul></li><li><strong>Simplified Session Lifecycle (Agents SDK v0.0.44):</strong>&nbsp;<ul><li>We've made managing agent sessions effortless. You can now <strong>use&nbsp;session.start(wait_for_participant=True, run_until_shutdown=True)</strong>&nbsp;to handle the entire lifecycle with a single line of code, while still retaining full manual control if you need it.</li></ul></li><li><strong>An Expanding AI Ecosystem (Agents SDK v0.0.42-46):</strong>&nbsp;<ul><li>We've added support for&nbsp;<strong>Deepgram STT V2</strong>,&nbsp;<strong>ElevenLabs Scribe V2</strong>, and improved our plugins for&nbsp;<strong>Sarvam AI</strong>,&nbsp;<strong>Gemini Live</strong>, and&nbsp;<strong>OpenAI</strong>.</li></ul></li><li><a href="https://github.com/videosdk-live/agents/releases" rel="noreferrer"><strong>View full Agents SDK changelog</strong></a></li></ul><h2 id="a-better-developer-experience"><strong>A Better Developer Experience</strong></h2><p>We’ve shipped a series of quality-of-life improvements to give you deeper observability and control.</p><ul><li><strong>Deeper Insight into "Why":</strong>&nbsp;<ul><li>We’ve added&nbsp;reason&nbsp;and&nbsp;code&nbsp;parameters to the&nbsp;meeting-left&nbsp;and&nbsp;participant-left&nbsp;events across our&nbsp;<a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer"><strong>JS</strong></a><strong>, </strong><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer"><strong>React</strong></a><strong>, </strong><a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer"><strong>React Native</strong></a><strong>, </strong><a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer"><strong>Android</strong></a><strong>, and </strong><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer"><strong>Flutter</strong></a><strong> SDKs</strong>. You'll now know exactly why a user's session ended.</li></ul></li><li><strong>Enhanced Observability:</strong>&nbsp;<ul><li>We've made all trace messages user-facing and added a&nbsp;<strong>sessionId</strong>&nbsp;parameter across our&nbsp;<strong>JS, React, and React Native SDKs</strong>, enabling you to fetch and analyze traces directly from the dashboard.</li></ul></li><li><strong>New WHIP/WHEP Documentation:</strong>&nbsp;<ul><li>For developers working with standardized ingest and egress protocols, our comprehensive WHIP/WHEP documentation is now live!&nbsp;=&gt; <a href="https://docs.videosdk.live/javascript/guide/interactive-live-streaming/whip-whep-ils" rel="noreferrer"><strong>View the Docs</strong></a></li></ul></li></ul><h2 id="core-sdk-enhancements"><strong>Core SDK Enhancements</strong></h2><ul><li><strong>iOS SDK (v2.2.9 &amp; v2.3.0):</strong>&nbsp;<ul><li>Now includes advanced video track optimization with&nbsp;<strong>BitrateMode</strong>&nbsp;and&nbsp;<strong>maxLayer</strong>&nbsp;parameters for fine-tuning quality and bandwidth. =&gt; <a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer">View Changelogs</a></li></ul></li><li><strong>Flutter SDK (v3.2.0):</strong>&nbsp;<ul><li>You can now&nbsp;<strong>pause()</strong>&nbsp;and&nbsp;<strong>resume()</strong>&nbsp;active streams, giving you more control over media playback. =&gt; <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer">View Changelogs</a></li></ul></li><li><strong>Android SDK (v1.0.0):</strong>&nbsp;<ul><li>Added the&nbsp;<strong>OldMessagesReceived</strong>&nbsp;event to retrieve persisted PubSub messages and set the default consumer video quality to high. =&gt; <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer">View Changelogs</a></li></ul></li><li><strong>React Native SDK (v0.5.0):</strong>&nbsp;<ul><li>This massive release includes Beta support for&nbsp;<strong>Adaptive Subscriptions</strong>, new quality limitation and stream state events, and the&nbsp;useStream&nbsp;hook for easier stream management. =&gt; <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer">View Changelogs</a></li></ul></li></ul><h2 id="%F0%9F%93%9A-new-content-resources">📚 New Content &amp; Resources</h2><h3 id="new-platform-specific-quickstart-guides-for-agents-runtime"><strong>New Platform-Specific Quickstart Guides for Agents Runtime</strong></h3><ul><li>Getting started with VideoSDK Agents has never been easier. With the release of Agent Runtime, we've also published a full suite of new quick-start agent integration guides tailored to your favourite platform to connect the no code agent from within your meeting room. Whether you're building for web or mobile, we've got you covered.</li></ul><p>Find your guide here:</p>
<!--kg-card-begin: html-->
<style>
    .custom-quickstart-table {
        width: 100%;
        border-collapse: collapse;
        text-align: left;
    }
    .custom-quickstart-table th, .custom-quickstart-table td {
        padding: 12px 15px;
        border-bottom: 1px solid #333; /* Dark theme border */
    }
    .custom-quickstart-table .section-header {
        background-color: #1a1a1a; /* Slightly different background for header */
        font-weight: bold;
        color: #fff;
    }
    .custom-quickstart-table a {
        color: #a585f7; /* A link color that might match your theme */
        text-decoration: none;
    }
     .custom-quickstart-table a:hover {
        text-decoration: underline;
    }
</style>

<table class="custom-quickstart-table">
    <thead>
        <tr>
            <th>Name</th>
            <th>Link</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td colspan="2" class="section-header">Web</td>
        </tr>
        <tr>
            <td>JavaScript Quickstart</td>
            <td><a href="https://docs.videosdk.live/ai_agents/agent-runtime/connect-agent/web-integrations/with-javascript">[Doc]</a></td>
        </tr>
        <tr>
            <td>React Quickstart</td>
            <td><a href="https://docs.videosdk.live/ai_agents/agent-runtime/connect-agent/web-integrations/with-react">[Doc]</a></td>
        </tr>
        <tr>
            <td colspan="2" class="section-header">Mobile</td>
        </tr>
        <tr>
            <td>React Native Quickstart</td>
            <td><a href="https://docs.videosdk.live/ai_agents/agent-runtime/connect-agent/mobile-integrations/with-react-native">[Doc]</a></td>
        </tr>
        <tr>
            <td>iOS Quickstart</td>
            <td><a href="https://docs.videosdk.live/ai_agents/agent-runtime/connect-agent/mobile-integrations/with-ios">[Doc]</a></td>
        </tr>
        <tr>
            <td>Flutter Quickstart</td>
            <td><a href="https://docs.videosdk.live/ai_agents/agent-runtime/connect-agent/mobile-integrations/with-flutter">[Doc]</a></td>
        </tr>
    </tbody>
</table>
<!--kg-card-end: html-->
<h3 id="guide-integrate-with-traditional-telephony-using-sip-connect"><strong>Guide: Integrate with Traditional Telephony using SIP-Connect</strong></h3><p>Bridge the gap between your digital meetings and the world of traditional telephony. Our new guide shows you how to use SIP-Connect to enable dial-in participants and connect your application with any phone line.</p><ul><li>📖 <a href="https://docs.videosdk.live/telephony/sip-connect" rel="noreferrer">Read the SIP-Connect Guide</a></li></ul><h3 id="guide-ai-voice-agent-observability"><strong>Guide: AI Voice Agent Observability</strong></h3><p>Dive into our new practical guide on debugging latency and improving your AI agents' performance. Learn how to leverage VideoSDK traces for a deeper understanding of your agent's behavior.</p><ul><li>📖 <a href="https://dev.to/chaitrali_kakde/a-practical-guide-to-ai-voice-agent-observability-debugging-latency-with-videosdk-traces-4kmj" rel="noreferrer">Read the Observability Guide on Dev.to</a></li></ul><p/><h2 id="%E2%9C%A8-community-spotlight"><strong>✨ Community Spotlight</strong></h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/12/image-1.png" class="kg-image" alt="Product Updates - November 2025 : Agent Runtime, WHIP/WHEP and Realtime Data Store" loading="lazy" width="1886" height="702"/></figure><blockquote><a href="https://www.videosdk.live/customers/coderschool"><em>Explore how CoderSchool achieves student engagement growth of 100,000+ sessions per month and builds huge tech talent network in Southeast Asia.</em></a></blockquote><h2 id="sdk-sketches">SDK Sketches</h2><blockquote>This month's sketch: Using Agent Runtime vs Traditional Coding </blockquote><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/12/image-2.png" class="kg-image" alt="Product Updates - November 2025 : Agent Runtime, WHIP/WHEP and Realtime Data Store" loading="lazy" width="2166" height="1276"/></figure><p><em>That’s a wrap for November! From our new no-code builder to realtime store across SDKs, we can't wait to see what you build with these new tools.</em></p><p>We'd love to hear your feedback! If you have any questions, suggestions, or issues, please don't hesitate to contact our support team.</p><ul><li><a href="https://discord.com/invite/Gpmj6eCq5u" rel="noreferrer"><strong>Join our Discord Community</strong></a></li><li><a href="https://www.videosdk.live/contact" rel="noreferrer"><strong>Contact our support team</strong></a></li><li><a href="https://www.youtube.com/@VideoSDK" rel="noreferrer"><strong>Explore Youtube Videos</strong></a></li><li><a href="https://x.com/Video_SDK" rel="noreferrer"><strong>Follow us on Twitter/X</strong></a></li></ul><p>➡️ New to VideoSDK? <a href="https://www.videosdk.live/signup">Sign up now</a> and get <strong><em>10,000 free minutes</em></strong> to start building amazing audio &amp; video experiences!</p><p/>]]></content:encoded></item><item><title><![CDATA[Product Updates - October 2025 : Supercharged AI Agents, New SDK Features & More]]></title><description><![CDATA[This month's update is all about AI! We're unveiling Namo, our powerful in-house turn detection model for truly natural conversations, and a new WhatsApp AI Voice Agent Quickstart. Plus, get the details on major Android video control features and new React monitoring hooks.
]]></description><link>http://www.videosdk.live/blog/product-updates-october-2025</link><guid isPermaLink="false">6904956a64df6f042b4d477c</guid><category><![CDATA[Product Updates]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 31 Oct 2025 14:16:54 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/11/Monthly-Image.png" medium="image"/><content:encoded><![CDATA[<blockquote>Welcome to the VideoSDK Monthly updates, your all-in-one recap of our latest releases and platform enhancements! This month was all about making our AI agents smarter and more responsive, giving you deeper control over your media streams, and improving stability across all our SDKs. We've launched a massive evolution for the&nbsp;<strong>VideoSDK Agents SDK</strong>, a brand new&nbsp;<strong>WhatsApp Agent Quickstart</strong>, and rolled out powerful new features for our&nbsp;<strong>Android and React SDKs</strong>. Let's get into the details!</blockquote><h2 id="a-major-leap-forward-for-ai-agents"><strong>A Major Leap Forward for AI Agents</strong></h2><img src="https://assets.videosdk.live/static-assets/ghost/2025/11/Monthly-Image.png" alt="Product Updates - October 2025 : Supercharged AI Agents, New SDK Features & More"/><p>This month, our open-source VideoSDK Agents SDK received a series of transformative updates, focusing on making AI-powered voice interactions more natural, stable, and efficient. At the heart of this evolution is&nbsp;<strong>Namo</strong>, our new proprietary multilingual turn detection model.</p><h3 id="introducing-namo-our-in-house-model-for-perfect-turn-taking"><strong>Introducing Namo: Our In-House Model for Perfect Turn-Taking</strong></h3><p>A key part of making AI interactions feel human is knowing&nbsp;exactly&nbsp;when to speak. To solve this complex challenge, we're proud to introduce&nbsp;<strong>Namo-Turn-Detector</strong>, our in-house turn detection model, developed right here at VideoSDK.</p><p>While standard Voice Activity Detection (VAD) can tell you if someone is talking, Namo goes a step further. It's specifically trained to understand the nuances of conversation, accurately determining the precise moment a user has finished their thought and is ready for the agent to respond.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/10/5.png" class="kg-image" alt="Product Updates - October 2025 : Supercharged AI Agents, New SDK Features & More" loading="lazy" width="3200" height="1800"/></figure><p>This leads to:</p><ul><li><strong>Seamless Turn-Taking:</strong>&nbsp;Eliminates awkward pauses and prevents the agent from interrupting the user mid-sentence.</li><li><strong>Higher Accuracy:</strong>&nbsp;Reduces errors in detecting the end of speech, making the conversation more reliable.</li><li><strong>A Truly Natural Flow:</strong>&nbsp;Creates interactions that feel less robotic and more like talking to a real person.</li><li><a href="https://docs.videosdk.live/ai_agents/core-components/turn-detection-and-vad" rel="noreferrer"><strong>Explore Docs</strong></a><strong> </strong></li><li><a href="https://huggingface.co/collections/videosdk-live/namo-turn-detector-v1" rel="noreferrer"><strong>Checkout all the languages supported and upvote/like if you find it worthwhile</strong></a></li></ul><h2 id="%F0%9F%9A%80-sdk-releases-updates"><strong>🚀 SDK Releases &amp; Updates</strong></h2><p>Here’s a full breakdown of all the SDK releases and enhancements from the past month.</p><h4 id="agents-sdk-v0037v0041">Agents SDK (v0.0.37 - v0.0.41)</h4><p>Beyond the conversational improvements above, we've packed the Agents SDK with powerful new tools for developers.&nbsp;</p><ul><li><strong>UtteranceHandle&nbsp;for Lifecycle Management:</strong>&nbsp;Gain granular control over the lifecycle of an agent's speech. You can now track completion, handle user interruptions, and&nbsp;await&nbsp;utterances to prevent overlapping TTS.</li><li><strong>Enhanced Background Audio:</strong>&nbsp;Create more immersive agent experiences by playing background audio (e.g., thinking sounds, music) during agent interactions with new methods like&nbsp;<strong>play_background_audio()</strong>.</li><li><strong>CometAPI Plugin Integration:</strong>&nbsp;Simplify your AI stack by using multiple STT, LLM, and TTS services from different providers with a single API key.</li><li><strong>Improved</strong>:&nbsp;We've also enhanced our plugin ecosystem with support for the <a href="https://docs.videosdk.live/ai_agents/plugins/namo-turn-detector" rel="noreferrer">Namo TurnDetector model</a>, <a href="https://docs.videosdk.live/ai_agents/plugins/tts/deepgram" rel="noreferrer">Deepgram TTS</a>, a new <a href="https://docs.videosdk.live/ai_agents/plugins/tts/eleven-labs" rel="noreferrer">ElevenLabs TTS</a> plugin, and full integration with <a href="https://docs.videosdk.live/ai_agents/plugins/realtime/azure-voice-live" rel="noreferrer">Azure's real-time voice</a> services.</li><li><a href="https://github.com/videosdk-live/agents/releases" rel="noreferrer"><strong>View full Agents SDK changelog</strong></a></li></ul><h4 id="android-sdk-v060"><strong>Android SDK (v0.6.0)</strong></h4><p>This release introduces advanced video track optimization features, giving you greater control over quality and bandwidth.</p><ul><li><strong>Video Bitrate Control (BitrateMode):</strong>&nbsp;Easily manage video quality by choosing between three modes:&nbsp;<strong>BANDWIDTH_OPTIMIZED</strong>,&nbsp;<strong>BALANCED</strong>&nbsp;(default), and&nbsp;<strong>HIGH_QUALITY</strong>.</li><li><strong>Simulcast Layer Control (maxLayer):</strong>&nbsp;Specify the maximum number of simulcast layers to publish for a video track, allowing for fine-tuned performance.</li><li><strong>Improved:</strong>&nbsp;The&nbsp;<strong>getVideoStats()</strong>&nbsp;method now returns a&nbsp;JsonArray, providing detailed statistics for all produced video layers.</li><li><a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer"><strong>View full Android SDK changelog</strong></a></li></ul><h4 id="react-sdk-v043v049"><strong>React SDK (v0.4.3 - v0.4.9)</strong></h4><p>Our React SDK received a host of new features focused on real-time monitoring and easier stream management.</p><ul><li><strong>onQualityLimitation&nbsp;Event:</strong>&nbsp;Proactively monitor local call quality by detecting bandwidth limits, network congestion, or CPU limitations in real time.</li><li><strong>useStream&nbsp;Hook:</strong>&nbsp;Get direct access to all methods and properties of media streams within your components for simplified stream management.</li><li><strong>onStreamStateChanged&nbsp;Event:</strong>&nbsp;Better monitor the stream health of remote participants by detecting&nbsp;freeze,&nbsp;stuck, or&nbsp;recovery&nbsp;events.</li><li><strong>Improved:&nbsp;</strong>The&nbsp;VideoPlayer&nbsp;component now includes a&nbsp;muted&nbsp;attribute and supports passing a custom&nbsp;ref.</li><li><strong>&nbsp;Fixed:&nbsp;</strong><em>We</em> resolved a memory leak in&nbsp;EventEmitter&nbsp;and fixed a video orientation issue on iOS browsers.</li><li><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer"><strong>View full React SDK changelog</strong></a></li></ul><h4 id="javascript-sdk-v036v037"><strong>JavaScript SDK (v0.3.6 - v0.3.7)</strong></h4><ul><li><strong>Improved:</strong>&nbsp;Enabled simulcast layers for all custom tracks.</li><li><strong>Fixed:&nbsp;</strong>Resolved a default camera issue in React Native, fixed a bug that created multiple webcam producers, and corrected a video orientation issue on iOS browsers.</li><li><strong>⚠Deprecated:</strong>&nbsp;The&nbsp;getNetworkStats&nbsp;method has been deprecated.</li><li><a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer"><strong>View full JS SDK changelog</strong></a></li></ul><h4 id="react-native-sdk-v041v042"><strong>React Native SDK (v0.4.1 - v0.4.2)</strong></h4><ul><li><strong>Improved:</strong>&nbsp;The SDK is now compatible with&nbsp;<strong>React Native 0.82+</strong>&nbsp;and&nbsp;<strong>Expo SDK 54+</strong>.</li><li><strong>Fixed:</strong>&nbsp;Resolved issues with the&nbsp;defaultCamera&nbsp;parameter and&nbsp;changeWebcam()&nbsp;method behavior.</li><li><a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer"><strong>View full React Native SDK changelog</strong></a></li></ul><h4 id="flutter-sdk-v310"><strong>Flutter SDK (v3.1.0)</strong>&nbsp;</h4><ul><li><strong>Fixed: </strong>Addressed an issue where the microphone would stop working after a device was removed and fixed a bug preventing stats from displaying correctly on the dashboard.</li><li><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/release-notes" rel="noreferrer"><strong>View full Flutter SDK changelog</strong></a></li></ul><h2 id="%F0%9F%94%A7-platform-dashboard-updates">🔧 Platform &amp; Dashboard Updates</h2><h4 id="a-brand-new-dashboard-experience"><strong>A Brand New Dashboard Experience!</strong></h4><p>We've rolled out a redesigned developer dashboard! The new interface is cleaner, more intuitive, and makes it easier than ever to navigate your projects, monitor usage, and access your API keys.&nbsp;<a href="https://app.videosdk.live/" rel="noreferrer"><strong>Log in to check it out!</strong></a></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/10/dash.png" class="kg-image" alt="Product Updates - October 2025 : Supercharged AI Agents, New SDK Features & More" loading="lazy" width="5760" height="3729"/></figure><h2 id="%F0%9F%93%9A-new-content-resources">📚 New Content &amp; Resources</h2><h4 id="new-platform-specific-quickstart-guides-for-agents"><strong>New Platform-Specific Quickstart Guides for Agents</strong></h4><ul><li>Getting started with VideoSDK Agents has never been easier. We've published a full suite of new quick-start agent integration guides tailored to your favourite platform. Whether you're building for web, mobile, or even IoT, we've got you covered.</li></ul><p>Find your guide here:</p>
<!--kg-card-begin: html-->
<style>
    .custom-quickstart-table {
        width: 100%;
        border-collapse: collapse;
        text-align: left;
    }
    .custom-quickstart-table th, .custom-quickstart-table td {
        padding: 12px 15px;
        border-bottom: 1px solid #333; /* Dark theme border */
    }
    .custom-quickstart-table .section-header {
        background-color: #1a1a1a; /* Slightly different background for header */
        font-weight: bold;
        color: #fff;
    }
    .custom-quickstart-table a {
        color: #a585f7; /* A link color that might match your theme */
        text-decoration: none;
    }
     .custom-quickstart-table a:hover {
        text-decoration: underline;
    }
</style>

<table class="custom-quickstart-table">
    <thead>
        <tr>
            <th>Name</th>
            <th>Link</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td colspan="2" class="section-header">Web</td>
        </tr>
        <tr>
            <td>JavaScript Quickstart</td>
            <td><a href="https://docs.videosdk.live/ai_agents/ai-agent-quickstart-js">[Doc]</a></td>
        </tr>
        <tr>
            <td>React Quickstart</td>
            <td><a href="https://docs.videosdk.live/ai_agents/ai-agent-quickstart-react">[Doc]</a></td>
        </tr>
        <tr>
            <td colspan="2" class="section-header">Mobile</td>
        </tr>
        <tr>
            <td>React Native Quickstart</td>
            <td><a href="https://docs.videosdk.live/ai_agents/ai-agent-quickstart-react-native">[Doc]</a></td>
        </tr>
        <tr>
            <td>iOS Quickstart</td>
            <td><a href="https://docs.videosdk.live/ai_agents/ai-agent-quickstart-ios">[Doc]</a></td>
        </tr>
        <tr>
            <td>Flutter Quickstart</td>
            <td><a href="https://docs.videosdk.live/ai_agents/ai-agent-quickstart-flutter">[Doc]</a></td>
        </tr>
        <tr>
            <td>Unity Quickstart</td>
            <td><a href="https://docs.videosdk.live/ai_agents/ai-agent-quickstart-unity">[Doc]</a></td>
        </tr>
        <tr>
            <td colspan="2" class="section-header">Physical AI</td>
        </tr>
        <tr>
            <td>IoT Quickstart</td>
            <td><a href="https://docs.videosdk.live/ai_agents/ai-agent-quickstart-iot">[Doc]</a></td>
        </tr>
    </tbody>
</table>
<!--kg-card-end: html-->
<h4 id="guide-build-an-ai-voice-agent-with-a-rag-pipeline"><strong>Guide: Build an AI Voice Agent with a RAG Pipeline</strong></h4><ul><li>Take your AI agents to the next level by connecting them to your own knowledge base. Our latest guide walks you through building a sophisticated AI voice agent using the Retrieval-Augmented Generation (RAG) pipeline, allowing it to answer questions based on your custom documents and data.</li><li>📖&nbsp;<a href="https://www.google.com/url?sa=E&amp;q=https%3A%2F%2Fwww.videosdk.live%2Fblog%2Fbuild-an-ai-voice-agent-using-the-rag-pipeline-and-videosdk"><strong>Read the RAG pipeline guide</strong></a></li></ul><h4 id="guide-handle-speech-with-the-namo-turn-detection-model"><strong>Guide: Handle Speech with the Namo Turn Detection Model</strong></h4><ul><li>Ready to put our powerful new Namo model into action? This practical guide provides the code and step-by-step instructions you need to implement Namo in your own AI voice agents for seamless, human-like turn-taking.</li><li>📖&nbsp;<a href="https://www.google.com/url?sa=E&amp;q=https%3A%2F%2Fwww.videosdk.live%2Fblog%2Fhandle-speech-in-ai-voice-agents-with-namo-turn-detection-model"><strong>Read the Namo implementation guide</strong></a></li></ul><h4 id="the-whatsapp-ai-voice-agent-quickstart"><strong>The WhatsApp AI Voice Agent Quickstart</strong></h4><ul><li>You can now build and deploy AI voice agents that answer WhatsApp Business calls instantly. Our new Quickstart Guide leverages direct SIP integration with the Meta Business Platform, removing the need for third-party telephony and enabling fast, seamless conversational automation.</li><li>📖&nbsp;<a href="https://docs.videosdk.live/ai_agents/whatsapp-voice-agent-quick-start" rel="noreferrer"><strong>Get Started with the WhatsApp Quickstart</strong></a></li></ul><h2 id="%F0%9F%94%AE-whats-next">🔮 What's Next?</h2><p>This is just the beginning! We're already hard at work on our next set of features, including expanding our AI capabilities and improving SDK performance across the board. Stay tuned for more updates next month!</p><h2 id="%E2%9C%A8-community-spotlight"><strong>✨ Community Spotlight</strong></h2><blockquote>Hear how the team at&nbsp;<strong>Fi money</strong>&nbsp;is enhancing their customer experience using VideoSDK.</blockquote>
<!--kg-card-begin: html-->
<iframe src="https://www.linkedin.com/embed/feed/update/urn:li:ugcPost:7379037677221912576?collapsed=1" height="551" width="504" frameborder="0" allowfullscreen="" title="Embedded post"/>
<!--kg-card-end: html-->
<h2 id="sdk-sketches">SDK Sketches</h2><blockquote>This month's sketch: The difference between a frustrating, robotic conversation and one powered by Namo.</blockquote><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/11/8.png" class="kg-image" alt="Product Updates - October 2025 : Supercharged AI Agents, New SDK Features & More" loading="lazy" width="968" height="452"/></figure><p><em>That’s a wrap for this month! Upgrade your SDKs to the latest versions to take advantage of all these new features and improvements.</em></p><p>We'd love to hear your feedback! If you have any questions, suggestions, or issues, please don't hesitate to contact our support team.</p><ul><li><a href="https://discord.com/invite/Gpmj6eCq5u" rel="noreferrer"><strong>Join our Discord Community</strong></a></li><li><a href="https://www.videosdk.live/contact" rel="noreferrer"><strong>Contact our support team</strong></a></li><li><a href="https://www.youtube.com/@VideoSDK" rel="noreferrer"><strong>Explore Youtube Videos</strong></a></li><li><a href="https://x.com/Video_SDK" rel="noreferrer"><strong>Follow us on Twitter/X</strong></a></li></ul><p>➡️ New to VideoSDK? <a href="https://www.videosdk.live/signup">Sign up now</a> and get <strong><em>10,000 free minutes</em></strong> to start building amazing audio &amp; video experiences!</p><p/>]]></content:encoded></item><item><title><![CDATA[How to handle speech in AI Voice Agents with Namo Turn Detection Model]]></title><description><![CDATA[Learn how to make your AI Voice Agents sound natural and interruption-aware using the NAMO Turn Detection model - a semantic, transformer-based system that replaces silence timers with true speech understanding.]]></description><link>https://www.videosdk.live/blog/handle-speech-in-ai-voice-agents-with-namo-turn-detection-model</link><guid isPermaLink="false">69047e2864df6f042b4d46ec</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><category><![CDATA[turn detection]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 31 Oct 2025 10:45:29 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/10/7.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2025/10/7.png" alt="How to handle speech in AI Voice Agents with Namo Turn Detection Model"/><p>When it comes to building conversational AI, the real challenge isn’t what your AI says it’s when it says it. Timing defines whether your voice agent feels natural and human-like or robotic and awkward.</p><p>In real conversations, we overlap, pause, and jump in mid-sentence. Yet humans almost never talk over each other by accident. How? Because we’re constantly predicting intent. Traditional voice agents don’t have that instinct. They wait for silence - literally. That’s why most bots either interrupt you too soon or sit there awkwardly, unsure if you’re done talking.</p><p>To fix this, <strong>VideoSDK</strong> built <strong>Namo-v1</strong> - an open-source, high-performance <strong>turn detection model</strong> that understands meaning, not just silence.</p><h2 id="from-silence-detection-to-speech-understanding">From Silence Detection to Speech Understanding</h2><p>Most voice agents rely on a <strong>silence timer</strong> to decide when you’ve finished speaking. For instance, after 800 ms of quiet, the bot assumes you’re done and replies. But what if you were just thinking, or hesitating before your next word?</p><p>That’s where <strong>Namo</strong> changes the game. Instead of reacting to quiet moments, it uses <strong>semantic understanding</strong> to detect intent and conversation flow.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/10/namo_v1_turn_detection_12e042c6ec.png" class="kg-image" alt="How to handle speech in AI Voice Agents with Namo Turn Detection Model" loading="lazy" width="4338" height="1767"/></figure><p>This above diagram illustrates the <strong>VideoSDK Namo-V1 Turn Detection architecture</strong>. It shows how a user’s speech (captured in the VideoSDK Room) passes through <strong>Speech-to-Text (STT)</strong> and <strong>ChatContext</strong>, which then interfaces with the <strong>Turn Detector</strong>.</p><h2 id="say-reply-and-interrupt">Say, Reply and Interrupt</h2><p>Every conversation can be broken down into three key speech events:</p><ol><li><strong>Say</strong> - The agent speaks.</li><li><strong>Reply</strong> - The agent listens and responds when the user is done.</li><li><strong>Interrupt</strong> -The agent gracefully stops talking if the user jumps in mid-sentence.</li></ol><p>The real test for these voice agents is <strong>interruption handling</strong>, though what we call barge-in. That moment when the user says, “Wait no, that’s not what I meant…” right in the middle of the AI’s sentence. Most systems panic there. They either keep talking awkwardly or stop too late.</p><p>But with <strong>VAD + Namo</strong>, your agent can <strong>detect the user’s intent mid-response</strong>, immediately pause its speech output, and switch to listening mode just like a real human conversation.</p><p>Watch this YouTube Video : <a href="https://youtu.be/IL0OSOD38bo">https://youtu.be/IL0OSOD38bo</a></p><h2 id="implementation-combining-vad-and-namo">Implementation: Combining VAD and Namo</h2><h3 id="1-voice-activity-detection-vad">1. <strong>Voice Activity Detection (VAD)</strong></h3><p>VAD is your first layer. It detects when speech is happening separating human voice from background noise.</p><pre><code class="language-python">from videosdk.plugins.silero import SileroVAD

# Configure VAD to detect speech activity
vad = SileroVAD(
    threshold=0.5,                    # Sensitivity to speech (0.3-0.8)
    min_speech_duration=0.1,          # Ignore very brief sounds
    min_silence_duration=0.75         # Wait time before considering speech ended
)
</code></pre><p>This helps your agent stay reactive without misfiring on every background sound.</p><h3 id="2-namo-turn-detection">2. <strong>Namo Turn Detection</strong></h3><p>Once the audio is cleaned up, <strong>Namo Turn Detector</strong> adds intelligence. It understands the meaning behind the speech and predicts whether the user is truly finished talking  or just pausing.</p><pre><code class="language-python">from videosdk.plugins.turn_detector import NamoTurnDetectorV1, pre_download_namo_turn_v1_model

# Pre-download the multilingual model to avoid runtime delays
pre_download_namo_turn_v1_model()

# Initialize the multilingual Turn Detector
turn_detector = NamoTurnDetectorV1(
    threshold=0.7  # Confidence level for triggering a response
)
</code></pre><ul><li><strong>Multilingual Support</strong> - Works across 20+ languages</li><li><strong>Context-Aware</strong> - Recognizes thinking pauses</li><li><strong>Interrupt Smartness</strong> - Responds instantly to barge-ins</li></ul><h3 id="3-pipeline-integration">3. <strong>Pipeline Integration</strong></h3><p>You can plug both detectors into a unified <strong>Cascading Pipeline</strong> to give your agent real conversational timing.</p><pre><code class="language-python">from videosdk.agents import CascadingPipeline
from videosdk.plugins.silero import SileroVAD
from videosdk.plugins.turn_detector import NamoTurnDetectorV1, pre_download_namo_turn_v1_model

# Pre-download the model you intend to use
pre_download_namo_turn_v1_model(language="en")

pipeline = CascadingPipeline(
    stt=your_stt_provider,
    llm=your_llm_provider,
    tts=your_tts_provider,
    vad=SileroVAD(threshold=0.5),
    turn_detector=NamoTurnDetectorV1(language="en", threshold=0.7)
)
</code></pre><p>Now, when your agent is mid-reply and detects incoming speech via <strong>VAD</strong>, Namo helps it <strong>semantically confirm</strong> if it’s an interruption and instantly pause its own output. That’s real-time, real-human responsiveness.</p><h2 id="complete-example">Complete Example</h2><pre><code class="language-python">import os
from typing import AsyncIterator
from videosdk.agents import Agent, AgentSession, CascadingPipeline,JobContext, RoomOptions, WorkerJob, ConversationFlow
from videosdk.plugins.openai import OpenAILLM
from videosdk.plugins.deepgram import DeepgramSTT
from videosdk.plugins.elevenlabs import ElevenLabsTTS
from videosdk.plugins.silero import SileroVAD
from videosdk.plugins.turn_detector import NamoTurnDetectorV1, pre_download_namo_turn_v1_model

# Pre-downloading the Namo Turn Detector model
pre_download_namo_turn_v1_model()

class MyVoiceAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions="You are VideoSDK's Voice Agent. You are a helpful voice assistant that can answer questions about weather.IMPORTANT: don't generate response above 2 lines",
        )

    async def on_enter(self) -&gt; None:
        await self.session.say("Hello, how can I help you today?")
    
    async def on_exit(self) -&gt; None:
        await self.session.say("Goodbye!")
        

async def start_session(context: JobContext):

    agent = MyVoiceAgent()
    conversation_flow = ConversationFlow(agent)
    pipeline = CascadingPipeline(
        stt=DeepgramSTT(),
        llm=OpenAILLM(),
        tts=ElevenLabsTTS(),
        vad=SileroVAD(),
        turn_detector=NamoTurnDetectorV1()
    )

    session = AgentSession(
        agent=agent,
        pipeline=pipeline,
        conversation_flow=conversation_flow
    )

    await context.run_until_shutdown(session=session,wait_for_participant=True)

def make_context() -&gt; JobContext:
    room_options = RoomOptions(
        room_id="&lt;room_id&gt;",
        name="Namo Turn Detector Agent",
        auth_token=os.getenv("VIDEOSDK_AUTH_TOKEN"),
        playground=True,
    )

    return JobContext(room_options=room_options)

if __name__ == "__main__":
    job = WorkerJob(entrypoint=start_session, jobctx=make_context)
    job.start() </code></pre><p><strong>Run your agent:</strong></p><pre><code class="language-bash">python main.py
</code></pre><p><strong>Open the VideoSDK playground URL</strong> printed in your terminal.<br>This will look like:</br></p><pre><code class="language-bash">https://playground.videosdk.live?token=...&amp;meetingId=...</code></pre><p>It can <strong>speak</strong>, <strong>wait</strong>, <strong>listen</strong>, and even <strong>yield mid-sentence</strong> when a human jumps in. Good conversation isn’t about perfect grammar it’s about timing, empathy, and flow. By combining <strong>VAD</strong> and <strong>Namo</strong>, you give your AI agent the ability to truly listen like a human: to speak when it should, wait when it must, and stop when someone else has something to say.</p><h2 id="looking-ahead-future-directions">Looking Ahead: Future Directions</h2><ul><li><strong>Multi-party turn-taking</strong>&nbsp;detection: deciding when one speaker yields to another.</li><li><strong>Hybrid signals</strong>: combine semantics with prosody, pitch, silence, etc.</li><li><strong>Adaptive thresholds &amp; confidence models</strong>: dynamic sensitivity based on conversation flow.</li><li><strong>Distilled / edge versions</strong>&nbsp;for latency-constrained devices.</li><li><strong>Continuous learning / feedback loop</strong>: let models adapt to usage patterns over time.</li></ul><h3 id="integrate-namo-turn-detection-model-on-any-device">Integrate Namo-Turn-Detection-Model on Any Device</h3><ul><li><a href="https://docs.videosdk.live/ai_agents/ai-phone-agent-quick-start" rel="noreferrer">Telephony</a></li><li><a href="https://docs.videosdk.live/ai_agents/whatsapp-voice-agent-quick-start" rel="noreferrer">WhatsApp</a></li><li><a href="https://docs.videosdk.live/ai_agents/voice-agent-quick-start" rel="noreferrer">Web</a></li><li><a href="https://docs.videosdk.live/ai_agents/introduction" rel="noreferrer">Mobile</a></li><li><a href="https://docs.videosdk.live/unity/guide/video-and-audio-calling-api-sdk/concept-and-architecture" rel="noreferrer">Gaming</a></li><li><a href="https://docs.videosdk.live/iot/guide/video-and-audio-calling-api-sdk/concept-and-architecture" rel="noreferrer">Physical AI</a></li></ul><h2 id="resources-and-next-step">Resources and Next Step</h2><ul><li>For a deep dive into Namo’s architecture, multilingual benchmarks, and model performance, visit the <a href="https://www.videosdk.live/blog/namo-turn-detection-v1-semantic-turn-detection-for-ai-voice-agents" rel="noreferrer">Namo turn detection Plugin Page</a></li><li>You can also explore the <a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Multilingual" rel="noreferrer">Hugging Face model collection</a> to find specialized models for each supported language.</li><li>Explore this quick start guide to get you started with <a href="https://github.com/videosdk-live/agents-quickstart/tree/main/Namo%20Turn%20Detector">Namo Turn Detector</a></li><li>Ecommerce agent with <a href="https://github.com/videosdk-community/ai-agent-demo/tree/conversational-flow">natural turn detection and interruption handling</a></li></ul><h2 id="citation">Citation</h2><pre><code class="language-python">@software{namo2025,
  title={Namo Turn Detector v1: Semantic Turn Detection for Conversational AI},
  author={VideoSDK Team},
  year={2025},
  publisher={Hugging Face},
  url={https://huggingface.co/collections/videosdk-live/namo-turn-detector-v1-68d52c0564d2164e9d17ca97}
}
</code></pre>]]></content:encoded></item><item><title><![CDATA[How to Build an AI Voice Agent Using the RAG Pipeline and VideoSDK]]></title><description><![CDATA[Learn how to build an AI Voice Agent with Retrieval-Augmented Generation (RAG). This guide walks through ingestion, embeddings, retrieval, and real-time voice response with complete code examples.]]></description><link>https://www.videosdk.live/blog/build-an-ai-voice-agent-using-the-rag-pipeline-and-videosdk</link><guid isPermaLink="false">6901e52a64df6f042b4d4598</guid><category><![CDATA[ai agents]]></category><category><![CDATA[AI voice agent]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 31 Oct 2025 10:25:33 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/10/image--1-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2025/10/image--1-.png" alt="How to Build an AI Voice Agent Using the RAG Pipeline and VideoSDK"/><p>Language models are powerful, but their responses are limited to the information within their context window. Once that limit is reached, they often start guessing. <strong>Retrieval-Augmented Generation (RAG)</strong> helps overcome this by allowing the model to fetch relevant information from an external knowledge base before generating a response.</p><p>In this post, we’ll <strong>build an example RAG-powered voice agent using VideoSDK, ChromaDB, and OpenAI</strong>. This demo shows how you can combine <strong>real-time audio input, intelligent data retrieval, and natural voice responses</strong> to create a more reliable and context-aware conversational agent.</p><h3 id="rag-architecture-explained">RAG Architecture Explained</h3><p>The architecture below shows how <strong>VideoSDK</strong> brings together real-time voice communication and <strong>Retrieval-Augmented Generation (RAG)</strong> to create a smarter, context-aware AI assistant.</p><p>Everything starts inside the <strong>VideoSDK Room</strong>, where the user speaks. The <strong>User Voice Input</strong> is captured and passed into the <strong>Voice Processing pipeline</strong>.</p><ol><li><strong>Speech to Text (STT)</strong> : The user’s audio is first converted into text using a speech recognition model like <strong>Deepgram</strong>.</li><li><strong>Embedding Model</strong> : The transcribed text is transformed into a numerical vector representation (embedding).</li><li><strong>Vector Database</strong> : These embeddings are used to search a database knowledge base for semantically relevant documents. This is where retrieval happens , the AI fetches real, factual context instead of guessing.</li><li><strong>LLM (Large Language Model)</strong> : The retrieved context is passed to the<strong> LLM</strong>, which generates a grounded, accurate response.</li><li><strong>Text to Speech (TTS)</strong> : Finally, the generated text response is converted back into natural voice like <strong>ElevenLabs TTS</strong>, and streamed back to the user as the <strong>Agent Voice Output</strong>.</li></ol><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2025/10/voice_agent_rag.png" class="kg-image" alt="How to Build an AI Voice Agent Using the RAG Pipeline and VideoSDK" loading="lazy" width="3477" height="1615"><figcaption><span style="white-space: pre-wrap;">Rag-Architecture</span></figcaption></img></figure><h2 id="prerequisites">Prerequisites</h2><ul><li>A VideoSDK authentication token (generate from&nbsp;<a href="https://app.videosdk.live/" rel="noopener noreferrer">app.videosdk.live</a>), follow to guide to&nbsp;<a href="https://docs.videosdk.live/ai_agents/authentication-and-token">generate videosdk token</a></li><li>A VideoSDK meeting ID (you can generate one using the&nbsp;<a href="https://docs.videosdk.live/api-reference/realtime-communication/create-room" rel="noopener noreferrer">Create Room API</a>)</li><li><a href="https://www.python.org/downloads/release/python-3120/" rel="noreferrer">Python 3.12 or higher</a></li></ul><h3 id="install-dependencies">Install dependencies</h3><pre><code class="language-python">pip install "videosdk-agents[deepgram,openai,elevenlabs,silero,turn_detector]"
pip install chromadb openai numpy</code></pre><h3 id="set-api-keys-in-env">Set API Keys in .env</h3><pre><code class="language-python">DEEPGRAM_API_KEY = "Your Deepgram API Key"
OPENAI_API_KEY = "Your OpenAI API Key"
ELEVENLABS_API_KEY = "Your ElevenLabs API Key"
VIDEOSDK_AUTH_TOKEN = "VideoSDK Auth token"</code></pre><div class="kg-card kg-callout-card kg-callout-card-yellow"><div class="kg-callout-text">Get API keys&nbsp;<a href="https://console.deepgram.com/" target="_blank" rel="noopener noreferrer">Deepgram ↗</a>,&nbsp;<a href="https://platform.openai.com/api-keys" target="_blank" rel="noopener noreferrer">OpenAI ↗</a>,&nbsp;<a href="https://elevenlabs.io/app/settings/api-keys" target="_blank" rel="noopener noreferrer">ElevenLabs ↗</a>&nbsp;&amp;&nbsp;<a href="https://docs.videosdk.live/ai_agents/[https://app.videosdk.live](https://app.videosdk.live/api-keys)" target="_blank" rel="noopener noreferrer">VideoSDK Dashboard ↗</a>&nbsp;follow to guide to&nbsp;<a href="https://docs.videosdk.live/ai_agents/authentication-and-token" target="_blank" rel="noopener noreferrer">generate videosdk token</a></div></div><h2 id="implementation">Implementation</h2><h3 id="step-1-custom-voice-agent-with-rag">Step 1: Custom Voice Agent with RAG</h3><p>Create a main.py file and add a  custom agent class that extends&nbsp;<code>Agent</code>&nbsp;and adds retrieval capabilities:</p><pre><code class="language-python">class VoiceAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions="""You are a helpful voice assistant that answers questions
            based on provided context. Use the retrieved documents to ground your answers.
            If no relevant context is found, say so. Be concise and conversational."""
        )

        # Initialize OpenAI client for embeddings
        self.openai_client = AsyncOpenAI(api_key=os.getenv("OPENAI_API_KEY"))

        # Define your knowledge base
        self.documents = [
            "What is VideoSDK? VideoSDK is a comprehensive video calling and live streaming platform...",
            "How do I authenticate with VideoSDK? Use JWT tokens generated with your API key...",
            # Add more documents
        ]

        # Set up ChromaDB
        self.chroma_client = chromadb.Client()  # In-memory
        # For persistence: chromadb.PersistentClient(path="./chroma_db")
        self.collection = self.chroma_client.create_collection(
            name="videosdk_faq_collection"
        )

        # Generate embeddings and populate database
        self._initialize_knowledge_base()

    def _initialize_knowledge_base(self):
        """Generate embeddings and store documents."""
        embeddings = [self._get_embedding_sync(doc) for doc in self.documents]
        self.collection.add(
            documents=self.documents,
            embeddings=embeddings,
            ids=[f"doc_{i}" for i in range(len(self.documents))]
        )

Step 2: Embedding Generation
Implement both synchronous (for initialization) and asynchronous (for runtime) embedding methods:

main.py
    def _get_embedding_sync(self, text: str) -&gt; list[float]:
        """Synchronous embedding for initialization."""
        import openai
        client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
        response = client.embeddings.create(
            input=text,
            model="text-embedding-ada-002"
        )
        return response.data[0].embedding

    async def get_embedding(self, text: str) -&gt; list[float]:
        """Async embedding for runtime queries."""
        response = await self.openai_client.embeddings.create(
            input=text,
            model="text-embedding-ada-002"
        )
        return response.data[0].embedding</code></pre><h3 id="step-2-embedding-generation">Step 2: Embedding Generation</h3><p>Implement both synchronous (for initialization) and asynchronous (for runtime) embedding methods:</p><pre><code class="language-python">    def _get_embedding_sync(self, text: str) -&gt; list[float]:
        """Synchronous embedding for initialization."""
        import openai
        client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
        response = client.embeddings.create(
            input=text,
            model="text-embedding-ada-002"
        )
        return response.data[0].embedding

    async def get_embedding(self, text: str) -&gt; list[float]:
        """Async embedding for runtime queries."""
        response = await self.openai_client.embeddings.create(
            input=text,
            model="text-embedding-ada-002"
        )
        return response.data[0].embedding</code></pre><h3 id="step-3-retrieval-method">Step 3: Retrieval Method</h3><p>Add semantic search capability:</p><pre><code class="language-python">    async def retrieve(self, query: str, k: int = 2) -&gt; list[str]:
        """Retrieve top-k most relevant documents from vector database."""
        # Generate query embedding
        query_embedding = await self.get_embedding(query)

        # Query ChromaDB
        results = self.collection.query(
            query_embeddings=[query_embedding],
            n_results=k
        )

        # Return matching documents
        return results["documents"][0] if results["documents"] else []</code></pre><h3 id="step-4-agent-lifecycle-hooks">Step 4: Agent Lifecycle Hooks</h3><p>Define agent behavior on entry and exit:</p><pre><code class="language-python"> async def on_enter(self) -&gt; None:
        """Called when agent session starts."""
        await self.session.say("Hello! I'm your VideoSDK assistant. How can I help you today?")

    async def on_exit(self) -&gt; None:
        """Called when agent session ends."""
        await self.session.say("Thank you for using VideoSDK. Goodbye!")</code></pre><h3 id="step-5-custom-conversation-flow">Step 5: Custom Conversation Flow</h3><p>Override the conversation flow to inject retrieved context:</p><pre><code class="language-python">class RAGConversationFlow(ConversationFlow):
    async def run(self, transcript: str) -&gt; AsyncIterator[str]:
        """
        Process user input with RAG pipeline.
        Args:
            transcript: User's speech transcribed to text
        Yields:
            Generated response chunks
        """
        # Step 1: Retrieve relevant documents
        context_docs = await self.agent.retrieve(transcript)

        # Step 2: Format context
        if context_docs:
            context_str = "\n\n".join([f"Document {i+1}: {doc}"
                                      for i, doc in enumerate(context_docs)])
        else:
            context_str = "No relevant context found."

        # Step 3: Inject context into conversation
        self.agent.chat_context.add_message(
            role="system",
            content=f"Retrieved Context:\n{context_str}\n\nUse this context to answer the user's question."
        )

        # Step 4: Generate response with LLM
        async for response_chunk in self.process_with_llm():
            yield response_chunk</code></pre><h3 id="step-6-session-and-pipeline-setup">Step 6: Session and Pipeline Setup</h3><p>Configure the agent session and start the job:</p><pre><code class="language-python">async def entrypoint(ctx: JobContext):
    agent = VoiceAgent()

    conversation_flow = RAGConversationFlow(
        agent=agent,
    )

    session = AgentSession(
        agent=agent,
        pipeline=CascadingPipeline(
            stt=DeepgramSTT(),
            llm=OpenAILLM(),
            tts=ElevenLabsTTS(),
            vad=SileroVAD(),
            turn_detector=TurnDetector()
        ),
        conversation_flow=conversation_flow,
    )

    # Register cleanup
    ctx.add_shutdown_callback(lambda: session.close())

    # Start agent
    try:
        await ctx.connect()
        print("Waiting for participant...")
        await ctx.room.wait_for_participant()
        print("Participant joined - starting session")
        await session.start()
        await asyncio.Event().wait()
    except KeyboardInterrupt:
        print("\nShutting down gracefully...")
    finally:
        await session.close()
        await ctx.shutdown()

def make_context() -&gt; JobContext:
    room_options = RoomOptions(name="RAG Voice Assistant", playground=True)
    return JobContext(room_options=room_options)

if __name__ == "__main__":
    job = WorkerJob(entrypoint=entrypoint, jobctx=make_context)
    job.start()</code></pre><h4 id="step-7-run-the-python-script">Step 7: Run the Python Script</h4><pre><code class="language-python">python main.py</code></pre><p>You can also use console for running the script :</p><pre><code class="language-python">python main.py console</code></pre><p>Now that the full RAG pipeline is in place, the agent can seamlessly handle every stage from capturing voice input to fetching relevant context and generating fact-based spoken responses. It’s a fully functional, end-to-end intelligent voice system powered by VideoSDK.</p><h2 id="best-practices">Best Practices</h2><ol><li>Document Quality: Use clear, well-structured documents with specific information</li><li>Chunk Size: Keep chunks between 300-800 words for optimal retrieval</li><li>Retrieval Count: Start with k=2-3, adjust based on response quality and latency</li><li>Context Window: Ensure retrieved context fits within LLM token limits</li><li>Persistent Storage: Use PersistentClient in production to save embeddings</li><li>Error Handling: Always handle retrieval failures gracefully</li><li>Testing: Test with diverse queries to ensure good coverage</li></ol><h2 id="resources-and-next-steps">Resources and Next Steps</h2><ol><li>Explore the <a href="https://github.com/videosdk-live/agents-quickstart/blob/main/RAG/rag.py" rel="noreferrer">rag-implementation-example</a> for full code implementation.</li><li>Read more about how to implement advanced methods like <a href="https://docs.videosdk.live/ai_agents/core-components/rag#dynamic-document-updates" rel="noreferrer">Dynamic Document Updates</a> and <a href="https://docs.videosdk.live/ai_agents/core-components/rag#document-chunking" rel="noreferrer">Document chunking</a> in RAG.</li><li>Learn how to <a href="https://docs.videosdk.live/ai_agents/deployments/introduction" rel="noreferrer">deploy your AI Agents</a>.</li><li>Visit <a href="https://docs.trychroma.com/docs/overview/getting-started" rel="noreferrer">Chroma DB Documentation</a></li><li>Build your own use case:&nbsp;knowledge-based chatbots, document search assistants, and context-aware voice agents.</li></ol>]]></content:encoded></item><item><title><![CDATA[Namo-Turn-Detection-v1: Semantic Turn Detection for AI Voice Agents]]></title><description><![CDATA[Turn-taking, the ability to know exactly when a user has finished speaking, is the invisible force behind natural human conversation. Yet most voice agents today rely on Voice Activity Detection (VAD) or fixed silence timers, leading to premature cut-offs or long, robotic pauses.

We introduce state of the art NAMO Turn Detector v1 (NAMO-v1), an open-source, ONNX-optimized semantic turn detector model that predicts conversational boundaries by understanding meaning, not just silence. NAMO achiev]]></description><link>https://www.videosdk.live/blog/namo-turn-detection-v1-semantic-turn-detection-for-ai-voice-agents</link><guid isPermaLink="false">68dc221564df6f042b4d43b3</guid><dc:creator><![CDATA[Arjun Kava]]></dc:creator><pubDate>Wed, 01 Oct 2025 14:10:02 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/10/Talk-Naturally.-Namo-v1-Listens-2--7-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2025/10/Talk-Naturally.-Namo-v1-Listens-2--7-.png" alt="Namo-Turn-Detection-v1: Semantic Turn Detection for AI Voice Agents"/><p>Turn-taking, the ability to know exactly when a user has finished speaking, is the invisible force behind natural human conversation. Yet most voice agents today rely on <strong>Voice Activity Detection (VAD)</strong> or fixed silence timers, leading to <strong>premature cut-offs</strong> or <strong>long, robotic pauses</strong>.</p><p>We introduce state of the art <a href="https://github.com/videosdk-live/NAMO-Turn-Detector-v1/tree/main" rel="noreferrer"><strong>NAMO Turn Detector v1 (NAMO-v1)</strong></a>, an <strong>open-source, ONNX-optimized semantic turn detector model</strong> that predicts conversational boundaries by understanding <strong>meaning</strong>, not just silence. NAMO achieves <strong>&lt;19 ms inference</strong> for specialized single-language models, <strong>&lt;29 ms for multilingual</strong>, and up to <strong>97.3 % accuracy,</strong> making it the first practical drop-in replacement for VAD in real-time voice systems.</p><h2 id="1-why-existing-approaches-break-down">1. Why Existing Approaches Break Down</h2><p>Most deployed voice agents use one of two approaches:</p><ul><li><strong>Silence-based VAD:</strong> very fast and lightweight but either interrupts users mid-sentence or waits too long to be sure they’re done.</li><li><strong>ASR endpointing (pause + punctuation):</strong> better than raw energy detection, but still a proxy; hesitations and lists often look “finished” when they’re not, and behavior varies wildly across languages.</li></ul><p>Both approaches force product teams into a painful <strong>latency vs. interruption trade-off</strong>: either set a long buffer (safe but robotic) or a short one (fast but rude).</p><h2 id="2-namo%E2%80%99s-semantic-advantage">2. NAMO’s Semantic Advantage</h2><p>NAMO replaces “silence as a proxy” with <strong>semantic understanding</strong>. The model looks at the text stream from your ASR and predicts whether the thought is complete. This single change brings:</p><ul><li><strong>Lower floor transfer time</strong> (snappier replies) <strong>without raising false cut-offs.</strong></li><li><strong>Multilingual robustness:</strong> one model works across <strong>23+ languages</strong>, no per-language tuning.</li><li><strong>Production latency:</strong> ONNX-quantized models run in <strong>&lt;30 ms</strong> on CPU/GPU with almost no accuracy loss.</li><li><strong>Observability &amp; tuning:</strong> you can get calibrated probabilities and adjust thresholds for “fast vs. safe.”</li></ul><p>Namo uses Natural Language Understanding to analyze the semantic meaning and context of speech, distinguishing between:</p><ul><li><strong>Complete utterances</strong>&nbsp;(user is done speaking)</li><li><strong>Incomplete utterances</strong>&nbsp;(user will continue speaking)</li></ul><h3 id="key-features">Key Features</h3><ul><li><strong>Semantic Understanding</strong>: Analyzes meaning and context, not just silence</li><li><strong>Ultra-Fast Inference</strong>: &lt;19ms for specialized models, &lt;29ms for multilingual</li><li><strong>Lightweight</strong>: ~135MB (specialized) / ~295MB (multilingual)</li><li><strong>High Accuracy</strong>: Up to 97.3% for specialized models, 90.25% average for multilingual</li><li><strong>Production-Ready</strong>: ONNX-optimized for real-time, enterprise-grade applications</li><li><strong>Easy Integration</strong>: Standalone usage or plug-and-play with VideoSDK Agents SDK</li></ul><h2 id="3-performance-benchmarks">3. Performance Benchmarks</h2><h3 id="latency-throughput">Latency &amp; Throughput</h3><p>Using ONNX quantization, NAMO moves from <strong>61 ms to 28 ms inference</strong> (multilingual) and <strong>38 ms to 14.9 ms</strong> (specialized).</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/10/image.png" class="kg-image" alt="Namo-Turn-Detection-v1: Semantic Turn Detection for AI Voice Agents" loading="lazy" width="4004" height="2810"/></figure><ul><li><strong>Relative speedup:</strong> up to <strong>2.56×</strong></li><li><strong>Throughput:</strong> doubled (35.6 to 66.8 tokens/sec)</li></ul><h3 id="accuracy-impact">Accuracy Impact</h3><p>Quantization preserves accuracy:</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/10/image-1.png" class="kg-image" alt="Namo-Turn-Detection-v1: Semantic Turn Detection for AI Voice Agents" loading="lazy" width="3339" height="1307"/></figure><p>Confusion matrices show virtually unchanged true/false rates before and after quantization.</p><h3 id="language-coverage">Language Coverage</h3><p>Average multilingual accuracy: <strong>90.25 %</strong><br>Specialized single-language models: <strong>97.3 %</strong> (Turkish/Korean), <strong>&gt;93 %</strong> Hindi, Japanese, German.</br></p><h2 id="5-impact-on-real-time-voice-ai">5. Impact on Real-Time Voice AI</h2><p>With NAMO you get:</p><ul><li><strong>Snappier responses</strong> without the “one Mississippi” delay.</li><li><strong>Fewer interruptions</strong> when users pause mid-thought.</li><li><strong>Consistent UX across markets</strong> without tuning for each language.</li><li><strong>Cost-effective scaling</strong> — works with any STT and runs efficiently on commodity servers.</li></ul><h2 id="6-impact-on-real-time-voice-ai">6. Impact on Real-Time Voice AI</h2><p><a href="https://github.com/videosdk-live/NAMO-Turn-Detector-v1#available-models"/>Namo offers both&nbsp;<strong>specialized single-language models</strong>&nbsp;and a&nbsp;<strong>unified multilingual model</strong></p><table>
<thead>
<tr>
<th>Variant</th>
<th>Languages / Focus</th>
<th>Model Size</th>
<th>Latency*</th>
<th>Typical Accuracy</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Multilingual</strong></td>
<td>23 languages</td>
<td>~295 MB</td>
<td>&lt; 29 ms</td>
<td>~90.25 % (average)</td>
</tr>
<tr>
<td><strong>Language-Specialized</strong></td>
<td>One language per model</td>
<td>~135 MB</td>
<td>&lt; 19 ms</td>
<td>Up to 97.3 %</td>
</tr>
</tbody>
</table>
<blockquote>* Latency measured after quantization on target inference hardware.</blockquote><h3 id="multilingual-model-recommended">Multilingual Model (Recommended): </h3><ul><li>Model: Namo-Turn-Detector-v1-Multilingual</li><li>Base: mmBERT</li><li>Languages: All 23 supported languages</li><li>Inference: &lt;29ms</li><li>Size: ~295MB</li><li>Average Accuracy: 90.25%</li><li>Model Link: <a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Multilingual" rel="noreferrer">Namo Turn Detector v1 - MultiLingual</a></li></ul><h4 id="performance-benchmarks-for-multilingual-model">Performance Benchmarks for Multilingual Model</h4><p><a href="https://github.com/videosdk-live/NAMO-Turn-Detector-v1/edit/main/README.md#-performance-benchmarks-for-multilingual-model"/></p><p>Evaluated on&nbsp;<strong>25,000+ diverse utterances</strong>&nbsp;across all supported languages.</p><table>
<thead>
<tr>
<th>Language</th>
<th>Accuracy</th>
<th>Precision</th>
<th>Recall</th>
<th>F1 Score</th>
<th>Samples</th>
</tr>
</thead>
<tbody>
<tr>
<td>🇹🇷 Turkish</td>
<td>97.31%</td>
<td>0.9611</td>
<td>0.9853</td>
<td>0.9730</td>
<td>966</td>
</tr>
<tr>
<td>🇰🇷 Korean</td>
<td>96.85%</td>
<td>0.9541</td>
<td>0.9842</td>
<td>0.9690</td>
<td>890</td>
</tr>
<tr>
<td>🇯🇵 Japanese</td>
<td>94.36%</td>
<td>0.9099</td>
<td>0.9857</td>
<td>0.9463</td>
<td>834</td>
</tr>
<tr>
<td>🇩🇪 German</td>
<td>94.25%</td>
<td>0.9135</td>
<td>0.9772</td>
<td>0.9443</td>
<td>1,322</td>
</tr>
<tr>
<td>🇮🇳 Hindi</td>
<td>93.98%</td>
<td>0.9276</td>
<td>0.9603</td>
<td>0.9436</td>
<td>1,295</td>
</tr>
<tr>
<td>🇳🇱 Dutch</td>
<td>92.79%</td>
<td>0.8959</td>
<td>0.9738</td>
<td>0.9332</td>
<td>1,401</td>
</tr>
<tr>
<td>🇳🇴 Norwegian</td>
<td>91.65%</td>
<td>0.8717</td>
<td>0.9801</td>
<td>0.9227</td>
<td>1,976</td>
</tr>
<tr>
<td>🇨🇳 Chinese</td>
<td>91.64%</td>
<td>0.8859</td>
<td>0.9608</td>
<td>0.9219</td>
<td>945</td>
</tr>
<tr>
<td>🇫🇮 Finnish</td>
<td>91.58%</td>
<td>0.8746</td>
<td>0.9702</td>
<td>0.9199</td>
<td>1,010</td>
</tr>
<tr>
<td>🇬🇧 English</td>
<td>90.86%</td>
<td>0.8507</td>
<td>0.9801</td>
<td>0.9108</td>
<td>2,845</td>
</tr>
<tr>
<td>🇵🇱 Polish</td>
<td>90.68%</td>
<td>0.8619</td>
<td>0.9568</td>
<td>0.9069</td>
<td>976</td>
</tr>
<tr>
<td>🇮🇩 Indonesian</td>
<td>90.22%</td>
<td>0.8514</td>
<td>0.9707</td>
<td>0.9071</td>
<td>971</td>
</tr>
<tr>
<td>🇮🇹 Italian</td>
<td>90.15%</td>
<td>0.8562</td>
<td>0.9640</td>
<td>0.9069</td>
<td>782</td>
</tr>
<tr>
<td>🇩🇰 Danish</td>
<td>89.73%</td>
<td>0.8517</td>
<td>0.9644</td>
<td>0.9045</td>
<td>779</td>
</tr>
<tr>
<td>🇵🇹 Portuguese</td>
<td>89.56%</td>
<td>0.8410</td>
<td>0.9676</td>
<td>0.8999</td>
<td>1,398</td>
</tr>
<tr>
<td>🇪🇸 Spanish</td>
<td>88.88%</td>
<td>0.8304</td>
<td>0.9681</td>
<td>0.8940</td>
<td>1,295</td>
</tr>
<tr>
<td>🇮🇳 Marathi</td>
<td>88.50%</td>
<td>0.8762</td>
<td>0.9008</td>
<td>0.8883</td>
<td>774</td>
</tr>
<tr>
<td>🇺🇦 Ukrainian</td>
<td>87.94%</td>
<td>0.8164</td>
<td>0.9587</td>
<td>0.8819</td>
<td>929</td>
</tr>
<tr>
<td>🇷🇺 Russian</td>
<td>87.48%</td>
<td>0.8318</td>
<td>0.9547</td>
<td>0.8890</td>
<td>1,470</td>
</tr>
<tr>
<td>🇻🇳 Vietnamese</td>
<td>86.45%</td>
<td>0.8135</td>
<td>0.9439</td>
<td>0.8738</td>
<td>1,004</td>
</tr>
<tr>
<td>🇸🇦 Arabic</td>
<td>84.90%</td>
<td>0.7965</td>
<td>0.9439</td>
<td>0.8639</td>
<td>947</td>
</tr>
<tr>
<td>🇧🇩 Bengali</td>
<td>79.40%</td>
<td>0.7874</td>
<td>0.7939</td>
<td>0.7907</td>
<td>1,000</td>
</tr>
</tbody>
</table>
<p><strong>Average Accuracy: 90.25%</strong> across all languages</p><h3 id="specialized-single-language-models">Specialized Single-Language Models</h3><p><a href="https://github.com/videosdk-live/NAMO-Turn-Detector-v1/tree/main#specialized-single-language-models"/></p><ul><li><strong>Architecture</strong>: DistilBERT-based</li><li><strong>Inference</strong>: &lt;19ms</li><li><strong>Size</strong>: ~135MB each</li></ul><table>
<thead>
<tr>
<th>Language</th>
<th>Model Link</th>
<th>Accuracy</th>
</tr>
</thead>
<tbody>
<tr>
<td>🇰🇷 Korean</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Korean">Namo-v1-Korean</a></td>
<td>97.3%</td>
</tr>
<tr>
<td>🇹🇷 Turkish</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Turkish">Namo-v1-Turkish</a></td>
<td>96.8%</td>
</tr>
<tr>
<td>🇯🇵 Japanese</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Japanese">Namo-v1-Japanese</a></td>
<td>93.5%</td>
</tr>
<tr>
<td>🇮🇳 Hindi</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Hindi">Namo-v1-Hindi</a></td>
<td>93.1%</td>
</tr>
<tr>
<td>🇩🇪 German</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-German">Namo-v1-German</a></td>
<td>91.9%</td>
</tr>
<tr>
<td>🇬🇧 English</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-English">Namo-v1-English</a></td>
<td>91.5%</td>
</tr>
<tr>
<td>🇳🇱 Dutch</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Dutch">Namo-v1-Dutch</a></td>
<td>90.0%</td>
</tr>
<tr>
<td>🇮🇳 Marathi</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Marathi">Namo-v1-Marathi</a></td>
<td>89.7%</td>
</tr>
<tr>
<td>🇨🇳 Chinese</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Chinese">Namo-v1-Chinese</a></td>
<td>88.8%</td>
</tr>
<tr>
<td>🇵🇱 Polish</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Polish">Namo-v1-Polish</a></td>
<td>87.8%</td>
</tr>
<tr>
<td>🇳🇴 Norwegian</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Norwegian">Namo-v1-Norwegian</a></td>
<td>87.3%</td>
</tr>
<tr>
<td>🇮🇩 Indonesian</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Indonesian">Namo-v1-Indonesian</a></td>
<td>87.1%</td>
</tr>
<tr>
<td>🇵🇹 Portuguese</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Portuguese">Namo-v1-Portuguese</a></td>
<td>86.9%</td>
</tr>
<tr>
<td>🇮🇹 Italian</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Italian">Namo-v1-Italian</a></td>
<td>86.8%</td>
</tr>
<tr>
<td>🇪🇸 Spanish</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Spanish">Namo-v1-Spanish</a></td>
<td>86.7%</td>
</tr>
<tr>
<td>🇩🇰 Danish</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Danish">Namo-v1-Danish</a></td>
<td>86.5%</td>
</tr>
<tr>
<td>🇻🇳 Vietnamese</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Vietnamese">Namo-v1-Vietnamese</a></td>
<td>86.2%</td>
</tr>
<tr>
<td>🇫🇷 French</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-French">Namo-v1-French</a></td>
<td>85.0%</td>
</tr>
<tr>
<td>🇫🇮 Finnish</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Finnish">Namo-v1-Finnish</a></td>
<td>84.8%</td>
</tr>
<tr>
<td>🇷🇺 Russian</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Russian">Namo-v1-Russian</a></td>
<td>84.1%</td>
</tr>
<tr>
<td>🇺🇦 Ukrainian</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Ukrainian">Namo-v1-Ukrainian</a></td>
<td>82.4%</td>
</tr>
<tr>
<td>🇸🇦 Arabic</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Arabic">Namo-v1-Arabic</a></td>
<td>79.7%</td>
</tr>
<tr>
<td>🇧🇩 Bengali</td>
<td><a href="https://huggingface.co/videosdk-live/Namo-Turn-Detector-v1-Bengali">Namo-v1-Bengali</a></td>
<td>79.2%</td>
</tr>
</tbody>
</table>
<h3 id="try-it-yourself">Try It Yourself!</h3><p><a href="https://github.com/videosdk-live/NAMO-Turn-Detector-v1/tree/main#-try-it-yourself"/></p><p>We’ve provided an&nbsp;<a href="https://github.com/videosdk-live/NAMO-Turn-Detector-v1/blob/main/inference.py">inference script</a>&nbsp;to help you quickly test these models. Just plug it in and start experimenting!</p><ul><li>Hugging Face Models: <a href="https://huggingface.co/videosdk-live/models">https://huggingface.co/videosdk-live/models</a></li><li>Github Repo Link: <a href="https://github.com/videosdk-live/NAMO-Turn-Detector-v1/tree/main">https://github.com/videosdk-live/NAMO-Turn-Detector-v1/tree/main</a></li><li>Official Documentation: <a href="https://docs.videosdk.live/ai_agents/core-components/turn-detection-and-vad">https://docs.videosdk.live/ai_agents/core-components/turn-detection-and-vad</a></li></ul>
<!--kg-card-begin: html-->
<div style="left: 0; width: 100%; height: 0; position: relative; padding-bottom: 56.25%;"><iframe src="https://www.youtube.com/embed/IL0OSOD38bo?rel=0" style="top: 0; left: 0; width: 100%; height: 100%; position: absolute; border: 0;" allowfullscreen="" scrolling="no" allow="accelerometer *; clipboard-write *; encrypted-media *; gyroscope *; picture-in-picture *; web-share *;" referrerpolicy="strict-origin"/></div>
<!--kg-card-end: html-->
<h3 id="integration-with-videosdk-agents">Integration with VideoSDK Agents</h3><p><a href="https://github.com/videosdk-live/NAMO-Turn-Detector-v1/tree/main#integration-with-videosdk-agents"/></p><p>For seamless integration into your voice agent pipeline:</p><pre><code class="language-py">from videosdk_agents import NamoTurnDetectorV1, pre_download_namo_turn_v1_model

# Download model files (one-time setup)
# For multilingual (default):
pre_download_namo_turn_v1_model()

# For specific language:
# pre_download_namo_turn_v1_model(language="en")

# Initialize turn detector
turn_detector = NamoTurnDetectorV1()  # Multilingual
# turn_detector = NamoTurnDetectorV1(language="en")  # English-specific

# Add to your agent pipeline
from videosdk_agents import CascadingPipeline

pipeline = CascadingPipeline(
    stt=your_stt_service,
    llm=your_llm_service,
    tts=your_tts_service,
    turn_detector=turn_detector  # Namo integration
)</code></pre><h2 id="7-training-testing">7. Training &amp; Testing</h2><p><a href="https://github.com/videosdk-live/NAMO-Turn-Detector-v1/tree/main?tab=readme-ov-file#-training--testing"/></p><p>Each model includes Colab notebooks for training and testing:</p><ul><li><strong>Training Notebooks</strong>: Fine-tune models on your own datasets</li><li><strong>Testing Notebooks</strong>: Evaluate model performance on custom data</li></ul><p>Visit individual model pages for notebook links:</p><ul><li><a href="https://colab.research.google.com/drive/1WEVVAzu1WHiucPRabnyPiWWc-OYvBMNj" rel="nofollow">Multilingual Training Notebook</a></li><li><a href="https://colab.research.google.com/drive/1DqSUYfcya0r2iAEZB9fS4mfrennubduV" rel="nofollow">Specialised Model Training Notebook</a></li><li><a href="https://colab.research.google.com/drive/19ZOlNoHS2WLX2V4r5r492tsCUnYLXnQR" rel="nofollow">Testing Notebook</a></li><li><a href="https://github.com/videosdk-live/NAMO-Turn-Detector-v1/blob/main/inference.py" rel="noreferrer">Inference Script</a></li></ul><h2 id="looking-ahead-future-directions">Looking Ahead: Future Directions</h2><ul><li><strong>Multi-party turn-taking</strong> detection: deciding when one speaker yields to another.</li><li><strong>Hybrid signals</strong>: combine semantics with prosody, pitch, silence, etc.</li><li><strong>Adaptive thresholds &amp; confidence models</strong>: dynamic sensitivity based on conversation flow.</li><li><strong>Distilled / edge versions</strong> for latency-constrained devices.</li><li><strong>Continuous learning / feedback loop</strong>: let models adapt to usage patterns over time.</li></ul><h3 id="integrate-namo-turn-detection-model-on-any-device">Integrate Namo-Turn-Detection-Model on Any Device</h3><ul><li><a href="https://docs.videosdk.live/ai_agents/ai-phone-agent-quick-start" rel="noreferrer">Telephony</a></li><li><a href="https://docs.videosdk.live/ai_agents/whatsapp-voice-agent-quick-start" rel="noreferrer">WhasApp</a></li><li><a href="https://docs.videosdk.live/ai_agents/voice-agent-quick-start" rel="noreferrer">Web</a></li><li><a href="https://docs.videosdk.live/ai_agents/introduction" rel="noreferrer">Mobile</a></li><li><a href="https://docs.videosdk.live/unity/guide/video-and-audio-calling-api-sdk/concept-and-architecture" rel="noreferrer">Gaming</a></li><li><a href="https://docs.videosdk.live/iot/guide/video-and-audio-calling-api-sdk/concept-and-architecture" rel="noreferrer">Physical AI </a></li></ul><h2 id="conclusion">Conclusion</h2><p><strong>NAMO-v1</strong> turns a long-standing bottleneck, turn-taking, into a solved engineering problem. By combining <strong>semantic intelligence</strong> with <strong>real-time speed</strong>, it finally allows voice AI systems to feel human, fast, and globally scalable.</p><h3 id="citation">Citation</h3><pre><code class="language-md">@software{namo2025,
  title={Namo Turn Detector v1: Semantic Turn Detection for Conversational AI},
  author={VideoSDK Team},
  year={2025},
  publisher={Hugging Face},
  url={https://huggingface.co/collections/videosdk-live/namo-turn-detector-v1-68d52c0564d2164e9d17ca97}
}
</code></pre>]]></content:encoded></item><item><title><![CDATA[Build a AI Phone Agent for Inbound & Outbound SIP Calls]]></title><description><![CDATA[Build and deploy a AI phone agent with VideoSDK—complete step-by-step guide from coding to live phone integration.]]></description><link>https://videosdk.live/blog/ai-phone-agent</link><guid isPermaLink="false">68a8f5b164df6f042b4d42ad</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[#sumit-so]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 28 Aug 2025 06:45:58 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/08/AI-Phone-Agent.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2025/08/AI-Phone-Agent.png" alt="Build a AI Phone Agent for Inbound & Outbound SIP Calls"/><p>This guide provides a step-by-step tutorial on how to build, containerize, and deploy a fully functional AI telephony agent using VideoSDK open source agentSDK. We will cover the complete workflow, from writing the agent's logic in main.py to configuring SIP trunks for live inbound and outbound phone calls.</p><p>If you're a developer to bridge the gap between your AI models and real-world telephony, you're in the right place. Follow along to turn a few simple files into a globally accessible voice agent.</p><iframe width="720" height="405" src="https://www.youtube.com/embed/WgEvRs0zqcI?si=AfckG_XWEh99vkBX" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""> </iframe><h2 id="project-directory">Project Directory</h2><p>This simple structure is our final goal for the worker. By following along, you'll create this complete project from scratch.</p><pre><code class="language-python">worker/
├── Dockerfile              # Instructions to build the Docker container
├── main.py                 # The core logic for your AI voice agent
├── requirements.txt        # Python package dependencies
├── .env                    # Environments variable
└── videosdk.yaml           # VideoSDK configuration for deploying the agent</code></pre><h2 id="architectureinboundoutbound-calls-for-ai-phone-agent">Architecture - Inbound/Outbound Calls for AI Phone Agent</h2><p>This architecture shows how your AI Phone Agent connects to the global phone network for both inbound and outbound SIP calls.</p><p>Our container-based deployment flow handles the complex telephony.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/08/videosdk-sip-inbound-outbound-1.png" class="kg-image" alt="Build a AI Phone Agent for Inbound & Outbound SIP Calls" loading="lazy" width="3546" height="2078"/></figure><h2 id="setting-up-agent-worker-for-ai-phone-agent">Setting Up Agent Worker for AI Phone Agent</h2><p>Let's build our <code>main.py</code>. This file uses three core VideoSDK components to define our agent's logic and connect it to a call.</p><ol><li><strong>Agent:</strong></li></ol><p>This class defines your agent's personality and conversational flow. You can also integrate advanced protocols like MCP and Agent 2 Agent to provide external context to your agent.</p><ol start="2"><li><strong>Pipeline:</strong></li></ol><p>The <code>Pipeline</code> is the engine that processes the audio stream. It takes the user's voice as input and produces the agent's voice as output. VideoSDK offers two types of pipelines to fit your needs</p><p>This is the audio processing engine. You can choose between two types:</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/08/videosdk-realtime-pipeline.png" class="kg-image" alt="Build a AI Phone Agent for Inbound & Outbound SIP Calls" loading="lazy" width="3037" height="586"/></figure><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/08/videosdk-casading-pipeline.png" class="kg-image" alt="Build a AI Phone Agent for Inbound & Outbound SIP Calls" loading="lazy" width="3026" height="582"/></figure><ol start="3"><li>Agent Session</li></ol><p>This brings it all together, connecting your Agent and Pipeline to a live VideoSDK Room to start the call.</p><p>Project Modules <code>requirements.txt</code></p><pre><code class="language-python ">videosdk-agents
videosdk-plugins-google
videosdk
python-dotenv</code></pre><p>Here’s how these components are implemented in the code <code>main.py</code>:</p><pre><code class="language-python">import asyncio
from videosdk.agents import Agent, AgentSession, RealTimePipeline, JobContext, RoomOptions, WorkerJob, MCPServerStdio
from videosdk.plugins.google import GeminiRealtime, GeminiLiveConfig
from dotenv import load_dotenv
import os

load_dotenv(override=True)

# Agent Component
class MyVoiceAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions="You are VideoSDK's AI Avatar Voice Agent with real-time capabilities. You are a helpful virtual assistant with a visual avatar that can answer questions about weather help with other tasks in real-time.",
        )

    async def on_enter(self) -&gt; None:
        await self.session.say("Hello! I'm your real-time AI avatar assistant. How can I help you today?")
    
    async def on_exit(self) -&gt; None:
        await self.session.say("Goodbye! It was great talking with you!")

async def start_session(context: JobContext):

    # Initialize Gemini Realtime model
    model = GeminiRealtime(
        model="gemini-2.0-flash-live-001",
        # When GOOGLE_API_KEY is set in .env - DON'T pass api_key parameter
        api_key=os.getenv("GOOGLE_API_KEY"), 
        config=GeminiLiveConfig(
            voice="Leda",  # Puck, Charon etc
            response_modalities=["AUDIO"]
        )
    )

    # Create pipeline with avatar
    pipeline = RealTimePipeline(
        model=model,
    )
    
    session = AgentSession(
        agent=MyVoiceAgent(),
        pipeline=pipeline
    )

    try:
        await context.connect()
        await session.start()
        await asyncio.Event().wait()
    finally:
        await session.close()
        await context.shutdown()

def make_context() -&gt; JobContext:
    room_options = RoomOptions(
        auth_token=os.getenv("VIDEOSDK_TOKEN"),
        room_id="ln4i-tuwm-yzkq",
        name="AI Agent",
        playground=True,
        recording=False
    )
    return JobContext(room_options=room_options)


if __name__ == "__main__":
    job = WorkerJob(entrypoint=start_session, jobctx=make_context)
    job.start() </code></pre><h2 id="running-the-ai-phone-agent-locally">Running the AI Phone Agent Locally</h2><p>Before we containerize our agent, let's run the Python script directly in a local development environment. This is the fastest way to test your agent's core logic.</p><p><strong>Prerequisite:</strong>&nbsp;Ensure you have Python 3.12 or newer installed on your machine.</p><h4 id="1-create-and-activate-a-virtual-environment">1. Create and Activate a Virtual Environment</h4><p>First, open your terminal in the&nbsp;worker&nbsp;directory. It's a best practice to use a virtual environment to manage project dependencies.</p><p>Create the environment:</p><pre><code class="language-python">python3 -m venv .venv</code></pre><p>Next, Activate it! Command differ based on your environment</p><ul><li>On MacOS/Linux</li></ul><pre><code class="language-python">source .venv/bin/activate</code></pre><ul><li>On Windows</li></ul><pre><code class="language-python">.venv\Scripts\activate</code></pre><p>You'll know the environment is active when you see&nbsp;(.venv)&nbsp;at the beginning of your terminal prompt.</p><h4 id="2-install-dependencies">2. Install Dependencies</h4><p>With the virtual environment active, install the necessary Python packages listed in your&nbsp;requirements.txt&nbsp;file:</p><pre><code class="language-python">pip install -r requirements.txt</code></pre><h4 id="3-run-the-python-script">3. Run the Python Script</h4><p>Finally, run the agent:</p><pre><code class="language-python">python main.py</code></pre><p>This will start your agent and connect it to a playground session, as defined by&nbsp;<code>playground=True</code>&nbsp;in the&nbsp;<code>make_context()</code>&nbsp;function in your code. You can now interact with it for initial testing before moving on to a full deployment.</p><h2 id="build-and-test-your-ai-phone-agent">Build and Test Your AI Phone Agent</h2><p>Before deploying our agent to the cloud, it's crucial to ensure it runs correctly on our local machine. The VideoSDK CLI makes this incredibly simple.</p><p>In your terminal, navigate to the <code>worker</code> directory and run the following command:</p><pre><code class="language-bash">videosdk run</code></pre><p>This command reads your <code>videosdk.yaml</code> and <code>Dockerfile</code>, builds a local container, and starts your agent. You should see an output confirming that your worker is running. This is the perfect time to test your agent's basic functionality in a playground environment to catch any bugs before going live.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/08/videosdk-run.png" class="kg-image" alt="Build a AI Phone Agent for Inbound & Outbound SIP Calls" loading="lazy" width="3921" height="1180"/></figure><h2 id="deploy-your-ai-phone-agent-to-the-cloud">Deploy Your AI Phone Agent to the Cloud</h2><p>Once you've confirmed the agent works locally, it's time to deploy it to VideoSDK's global infrastructure.</p><h3 id="1-configure-the-deployment-manifest">1. Configure the Deployment Manifest</h3><p>First, make sure your <code>videosdk.yaml</code> file is configured for a cloud deployment. The most important line is <code>cloud: true</code>, which tells the CLI to push your container to our servers instead of just running it locally.</p><pre><code class="language-yaml">version: "1.0"
deployment:
  id: 82fed3a5-5316-4273-b29f-4bb26e885842
  entry:
    path: main.py

deploy:
  cloud: true

env:
  path: "./.env"

secrets:
  VIDEOSDK_AUTH_TOKEN: # your_videosdk_token</code></pre><h3 id="2-deploy-with-a-single-command">2. Deploy with a Single Command</h3><p>Now for the magic. Run the <code>deploy</code> command:</p><pre><code class="language-bash">videosdk deploy</code></pre><p>The CLI will now package your worker, build the container, and upload it to the VideoSDK cloud. You'll see a live log of the progress.</p><p>Upon completion, you will get a <strong>Success!</strong> message along with your unique <strong>Worker ID</strong>.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/08/videosdk-deploy-.png" class="kg-image" alt="Build a AI Phone Agent for Inbound & Outbound SIP Calls" loading="lazy" width="2787" height="1127"/></figure><p>Crucial Step: Copy this Worker ID! You will need this unique identifier in the next step to connect your deployed agent to a phone number using a Routing Rule in the VideoSDK dashboard.</p><h2 id="connect-your-ai-phone-agent-to-the-phone-network">Connect Your AI Phone Agent to the Phone Network</h2><p>Now we'll use the VideoSDK dashboard to connect our deployed agent to a real phone number.</p><h3 id="1-set-up-an-inbound-gateway">1. Set up an Inbound Gateway</h3><p>This tells your SIP provider (e.g., Twilio) where to forward incoming calls.</p><ul><li>In the VideoSDK Dashboard, go to <strong>Telephony , in Inbound Gateways</strong> and click on <strong>Add Inbound Gateway</strong>.</li><li>Give it a name and add your phone number.</li><li>The dashboard will generate a unique <strong>Inbound Gateway URL</strong>. Copy this URL.</li><li>In your SIP provider's dashboard (like Twilio), paste this URL into the <strong>Origination SIP URI</strong> field for your SIP trunk.</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/08/gif-inbound-gateway.gif" class="kg-image" alt="Build a AI Phone Agent for Inbound & Outbound SIP Calls" loading="lazy" width="1280" height="720"/></figure><h3 id="2-set-up-an-outbound-gateway">2. Set up an Outbound Gateway</h3><p>This tells VideoSDK where to send outgoing calls from your agent.</p><ul><li>Go to <strong>Telephony Outbound Gateways</strong> and click <strong>Add Outbound Gateway</strong>.</li><li>Give it a name and add your phone number.</li><li>In the <strong>Address</strong> field, enter the <strong>Termination SIP URI</strong> provided by your SIP provider.</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/08/outbound-gateway.gif" class="kg-image" alt="Build a AI Phone Agent for Inbound & Outbound SIP Calls" loading="lazy" width="1280" height="720"/></figure><h4 id="3-create-a-routing-rule">3. Create a Routing Rule</h4><p>This is the final step that connects everything. The routing rule links a phone number to your specific deployed agent.</p><ul><li>Go to&nbsp;<strong>Telephony, in Routing Rules</strong> click&nbsp;on <strong>Add Routing Rules Gateway</strong>.</li><li>Select a direction (e.g.,&nbsp;inbound).</li><li>Choose the gateway you just created.</li><li>Set&nbsp;<strong>Agent Type</strong>&nbsp;to&nbsp;Cloud.</li><li>In the&nbsp;<strong>Deployment ID</strong>&nbsp;field, paste the&nbsp;<strong>Worker ID</strong>&nbsp;from your&nbsp;videosdk.yaml&nbsp;file.</li><li>Click&nbsp;<strong>Create</strong>.</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/08/sippart05-clip-1.gif" class="kg-image" alt="Build a AI Phone Agent for Inbound & Outbound SIP Calls" loading="lazy" width="1280" height="720"/></figure><h2 id="making-an-outbound-call">Making an Outbound Call</h2><p>To trigger an outbound call from your agent, you can make a simple API request to the VideoSDK SIP endpoint.</p><p>Use a <code>POST</code> request with your <code>VIDEOSDK_TOKEN</code> for authorization. In the body, specify the <code>gatewayId</code> (from your Outbound Gateway) and the phone number to call in <code>sipCallTo</code>.</p><pre><code class="language-bash">curl --request POST \\\\
  --url &lt;https://api.videosdk.live/v2/sip/call&gt; \\\\
  --header 'Authorization: YOUR_VIDEOSDK_TOKEN' \\\\
  --header 'Content-Type: application/json' \\\\
  --data '{
    "gatewayId": "gw_123456789",
    "sipCallTo": "+14155550123"
  }'

</code></pre><h3 id="managing-agent-sessions-programmatically">Managing Agent Sessions Programmatically</h3><p>While routing rules automatically manage sessions, you can also control them via API for advanced use cases, like starting a session on demand or for cost management.</p><p><strong>Start a Deployment Session:</strong></p><pre><code class="language-bash">curl --request POST \\\\
  --url &lt;https://api.videosdk.live/ai/v1/ai-deployment-sessions/start&gt; \\\\
  --header 'Authorization: YOUR_VIDEOSDK_TOKEN' \\\\
  --header 'Content-Type: application/json' \\\\
  --data '{
    "deploymentId": "&lt;your-deployment-id&gt;"
  }'

</code></pre><p><strong>End a Deployment Session:</strong></p><pre><code class="language-bash">curl --request POST \\\\
  --url &lt;https://api.videosdk.live/ai/v1/ai-deployment-sessions/end&gt; \\\\
  --header 'Authorization: YOUR_VIDEOSDK_TOKEN' \\\\
  --header 'Content-Type: application/json' \\\\
  --data '{
    "sessionId": "&lt;session-id-from-start-response&gt;"
  }'

</code></pre><h2 id="next-step">Next Step</h2><p>That's it! You've successfully built a Python AI agent, deployed it to the cloud, and connected it to the global telephone network for both inbound and outbound calls.</p><ul><li><a href="https://docs.videosdk.live/ai_agents/introduction" rel="noreferrer">AI Agent Documentation</a></li><li><a href="https://github.com/videosdk-live/agents" rel="noreferrer">Opensource AgentSDK </a></li><li><a href="https://discord.gg/f2WsNDN9S5" rel="noreferrer">Join Us on Discord</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Top AI Voice Agent Use Cases Across Industries in 2026]]></title><description><![CDATA[AI voice agent use cases span scheduling, support, payments, and claims. Learn industry examples, ROI metrics, and how to build with VideoSDK.]]></description><link>https://www.videosdk.live/blog/ai-voice-agent-use-cases/</link><guid isPermaLink="false">689af94a64df6f042b4d41f9</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 12 Aug 2025 08:29:28 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-4--2026--06_11_58-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>AI voice agent use cases span customer service, healthcare, banking, retail, restaurants, and insurance, where agents handle scheduling, support, payments, and claims at scale. Teams deploy them to cut call volume, extend 24/7 coverage, and route complex issues to humans with full context. Start with high-volume, repeatable conversations on sub-300ms audio infrastructure.</blockquote><h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-4--2026--06_11_58-PM.png" alt="Top AI Voice Agent Use Cases Across Industries in 2026"/><p>Developers and founders evaluating <a href="https://www.videosdk.live/voice-agents" rel="noreferrer">AI voice agent</a> use cases need industry-specific examples tied to measurable deployment outcomes, not generic hype about conversational AI.</p><p>A missed restaurant call during Friday dinner rush costs revenue. A healthcare clinic that puts every patient on hold loses trust before a nurse answers. AI voice agents solve these problems by answering, routing, and completing routine conversations without waiting on staff.</p><p>This article maps the most valuable AI voice agent use cases by industry, explains how they work in production, and shows how developers build them with real-time voice infrastructure. You will see where voice AI delivers ROI, where it fails, and how to implement it without rebuilding your telephony stack from scratch.</p><h2 id="what-is-ai-voice-agent">What is AI Voice Agent?</h2><p>An AI voice agent is defined as a software system that listens to spoken language, interprets intent with natural language processing, and responds with synthesized speech in real time. Unlike legacy <a href="https://www.videosdk.live/industry-hub/blogs/ai-in-ivr#unlocking-the-power-of-ai-in-ivr-a-strategic-guide-for-business-leaders:~:text=and%20its%20Evolution-,What%20is%20IVR%3F,-Interactive%20Voice%20Response" rel="noreferrer">interactive voice response</a> menus that force callers through rigid button trees, modern voice agents hold multi-turn conversations and adapt based on context.</p><p>An AI voice agent works by streaming audio through a pipeline of <a href="https://www.videosdk.live/developer-hub/stt/speech-to-text-transcription" rel="noreferrer">speech-to-text transcription</a>, <a href="https://videosdk.live/developer-hub/ai/llm-reasoning" rel="noreferrer">large language model reasoning</a>, and <a href="https://www.videosdk.live/developer-hub/tts/text-to-speech-synthesis" rel="noreferrer">text-to-speech synthesis</a>, all orchestrated over a <a href="https://www.videosdk.live/developer-hub/webtransport/low-latency" rel="noreferrer">low-latency</a> real-time transport layer. The agent connects to phone networks through SIP/PSTN gateways or to in-app sessions through <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a>, depending on where customers call from.</p><p>According to PwC's Global Artificial Intelligence Study, AI could contribute up to <a href="https://www.pwc.co.nz/insights-and-publications/2023-publications/artificial-intelligence-study.html" rel="noreferrer nofollow">$15.7 trillion to the global economy by 2030</a>, with customer-facing automation representing a large share of near-term enterprise spending. For developers and product teams, that shift means voice is no longer a novelty channel. It is a production interface that must meet telephony-grade reliability, compliance, and latency standards from day one.</p><p>AI voice agents differ from chatbots because they operate on spoken audio in real time rather than typed text in asynchronous threads.</p><h2 id="how-do-ai-voice-agents-work">How Do AI Voice Agents Work?</h2><p>AI voice agents process live audio in a continuous loop where each spoken utterance becomes text, text becomes a model response, and the response becomes speech streamed back to the caller without perceptible delay.</p><h3 id="real-time-audio-transport">Real-Time Audio Transport</h3><p>The transport layer carries bidirectional audio between the user and the agent. Sub-300 millisecond round-trip latency keeps conversations natural. When latency exceeds roughly 500 milliseconds, callers perceive awkward pauses and repeat themselves, which increases handle time and abandonment rates.</p><h3 id="speech-to-text-and-text-to-speech">Speech-to-Text and Text-to-Speech</h3><p><a href="https://www.videosdk.live/developer-hub/stt/speech-to-text" rel="noreferrer">Speech-to-text</a> engines like Google Cloud Speech-to-Text and OpenAI Whisper convert incoming audio into text for the language model. <a href="https://www.videosdk.live/developer-hub/tts/what-is-text-to-speech" rel="noreferrer">Text-to-speech</a> providers like ElevenLabs and OpenAI TTS render responses as human-sounding audio. Provider choice affects accent coverage, emotional tone, and per-minute cost at scale.</p><h3 id="agent-orchestration-and-escalation">Agent Orchestration and Escalation</h3><p>Orchestration coordinates STT, business logic or an LLM, TTS, and session state in a single pipeline. Production agents also need fallback paths for unrecognized intents, error handling, and warm handoff to human agents with conversation transcripts attached. Platforms like VideoSDK bundle this orchestration so teams focus on conversation design rather than wiring raw audio streams.</p><p>Every production voice agent runs the same listen-think-speak loop, and platform choice determines how reliably that loop completes under load.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-5--2026--05_08_08-PM.png" class="kg-image" alt="Top AI Voice Agent Use Cases Across Industries in 2026" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">how AI voice agent use cases work in real time</span></figcaption></img></figure><h2 id="the-most-impactful-ai-voice-agent-use-cases-by-industry">The Most Impactful AI Voice Agent Use Cases by Industry</h2><p>High-ROI AI voice agent deployments target repetitive, high-volume conversations where automation saves measurable agent hours without sacrificing compliance or customer trust.</p><h3 id="healthcare-scheduling-and-patient-follow-up">Healthcare: Scheduling and Patient Follow-Up</h3><p>Healthcare organizations deploy voice agents for appointment booking, reminder calls, and post-discharge check-ins. An agent can collect symptoms during intake, confirm insurance details, and flag urgent responses for nurse review.</p><p>HIPAA compliance is non-negotiable. Agents handling protected health information need encrypted transport, access controls, and business associate agreements with vendors. Teams building telehealth workflows often pair <a href="https://www.videosdk.live/voice-agents" rel="noreferrer">voice agents with HIPAA compliance</a>.</p><h3 id="customer-service-first-line-support-and-smart-routing">Customer Service: First-Line Support and Smart Routing</h3><p>Contact centers use voice agents as the first line for order status, account balance, password resets, and business hours inquiries. Intent detection routes complex or emotionally charged calls to specialists while passing full conversation context.</p><p>According to IBM's <a href="https://www.ibm.com/reports/data-breach" rel="noreferrer">Cost of a Data Breach Report</a>, faster incident response reduces breach costs, and the same principle applies to customer service: resolving simple queries instantly prevents queue buildup that damages satisfaction scores. Voice agents that resolve tier-one tickets in under 90 seconds free human agents for retention-sensitive conversations.</p><h3 id="banking-and-financial-services-payments-and-fraud-alerts">Banking and Financial Services: Payments and Fraud Alerts</h3><p>Banks automate EMI reminders, loan servicing outreach, and balance inquiries through outbound and inbound voice agents. Voice biometrics add a verification layer before discussing account details.</p><p>Financial deployments require PCI-aware data handling, call recording policies, and clear disclosure when callers interact with AI. Regulated industries should treat every voice session as auditable, with transcripts stored under retention rules that match local banking regulations.</p><h3 id="e-commerce-and-retail-order-tracking-and-campaigns">E-Commerce and Retail: Order Tracking and Campaigns</h3><p>Retailers answer "where is my order?" at scale through CRM and order-management API integrations. Outbound agents run promotional campaigns and post-purchase feedback calls during peak seasons without hiring temporary call staff.</p><p>Personalization raises conversion on these calls. When an agent greets a returning buyer by name and references their open shipment, completion rates on upsell offers rise compared with generic scripts.</p><h3 id="restaurants-orders-reservations-and-delivery-coordination">Restaurants: Orders, Reservations, and Delivery Coordination</h3><p>Restaurants lose revenue when staff cannot answer phones during service peaks. Voice agents take complex food orders, manage reservations, and relay modifications to point-of-sale and delivery systems in real time.</p><p><a href="https://www.videosdk.live/developer-hub/webtransport/low-latency" rel="noreferrer">Low-latency</a> audio matters here more than in many other verticals. A two-second delay during order confirmation causes callers to repeat items, which introduces errors into kitchen tickets.</p><h3 id="insurance-claims-intake-and-policy-renewals">Insurance: Claims Intake and Policy Renewals</h3><p>Insurers automate First Notice of Loss collection, policy renewal reminders, and identity verification through voice biometrics. Complex claims escalate to human adjusters, sometimes with a switch to video for virtual damage inspection.</p><p>The National Insurance Crime Bureau estimates that insurance fraud costs the United States more than $308 billion annually [UPDATE: verify date], which makes secure voice authentication and suspicious-pattern flagging high-value agent capabilities.</p><p>Across these six industries, the strongest AI voice agent use cases share structured dialog, clear escalation paths, and integrations with existing CRM, EHR, or order management systems.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-5--2026--05_24_16-PM.png" class="kg-image" alt="Top AI Voice Agent Use Cases Across Industries in 2026" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">AI voice agent use cases by industry overview</span></figcaption></img></figure><h2 id="why-latency-and-architecture-decide-voice-agent-success">Why Latency and Architecture Decide Voice Agent Success</h2><p>Voice agents that feel robotic are usually slow agents, not poorly scripted ones, because human conversation tolerates only brief gaps before trust erodes.</p><h3 id="the-latency-budget">The Latency Budget</h3><p>A production voice agent should target under 300 milliseconds from end of user speech to start of agent audio for routine replies. That budget splits across voice activity detection (roughly 50 to 100 milliseconds), STT processing (80 to 150 milliseconds), LLM inference (50 to 200 milliseconds for cached or short responses), and TTS generation (50 to 100 milliseconds). Exceeding 500 milliseconds total round-trip produces the "are you still there?" effect that drives hang-ups.</p><h3 id="cascading-vs-end-to-end-pipelines">Cascading vs. End-to-End Pipelines</h3><p>Most production systems use a cascading pipeline (STT, then LLM, then TTS) because it allows provider swapping and fine-grained logging. End-to-end speech models reduce pipeline stages but offer less control over compliance logging and vendor selection. Teams in regulated industries typically choose cascading architectures for auditability.</p><h3 id="caching-and-edge-deployment">Caching and Edge Deployment</h3><p>Caching pre-rendered TTS audio for top 20 FAQ responses cuts latency and API cost simultaneously. Deploying agent workers in regions close to callers reduces transport delay for international brands. VideoSDK's cloud deployment model supports regional worker placement so agents join sessions near the user.</p><p>Sub-300ms latency and a cascading STT-LLM-TTS architecture are the two technical decisions that separate trusted voice agents from frustrating ones.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-5--2026--05_32_45-PM.png" class="kg-image" alt="Top AI Voice Agent Use Cases Across Industries in 2026" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">AI voice agent use cases latency architecture</span></figcaption></img></figure><h2 id="when-ai-voice-agents-are-the-wrong-choice">When AI Voice Agents Are the Wrong Choice</h2><p>Voice automation fails when organizations deploy agents before mapping conversation complexity, emotional stakes, and regulatory exposure.</p><p>Choose human-first handling when the conversation involves legally binding consent, nuanced medical diagnosis, or high-emotion disputes where empathy outweighs speed. Debt collection in certain jurisdictions, mental health triage, and executive escalations are poor fits for unsupervised voice AI.</p><p>Skip voice agents when your call volume is too low to justify integration cost. If a clinic receives 30 inbound calls daily and half require clinical judgment, a part-time receptionist plus online scheduling delivers better ROI than a full voice stack.</p><p>Avoid voice-only design when visual confirmation improves outcomes. Insurance adjusters inspecting vehicle damage and bankers walking customers through complex product comparisons often need screen sharing or video, not audio alone. VideoSDK supports voice-to-video escalation precisely for these hybrid workflows.</p><p>Teams that force full automation without a human escape hatch see higher churn. Always design a zero-friction path to a live agent within two conversational turns.</p><p>Voice AI delivers the worst ROI when teams automate conversations that demand clinical judgment, legal consent, or high-empathy dispute resolution without a human backup.</p><h2 id="compliance-security-and-data-handling-by-industry">Compliance, Security, and Data Handling by Industry</h2><p>Regulated voice agent deployments require encryption, access logging, and vendor contracts that match the data each industry touches.</p><p>Healthcare agents need HIPAA-aligned infrastructure, minimum necessary data collection, and BAAs with every subprocessors handling transcripts. Banking agents must respect call recording consent laws that vary by U.S. state and EU market. Retail agents interacting with European customers fall under GDPR purpose-limitation and deletion requirements.</p><p>In practice, engineering teams that implement voice agents for regulated clients report that transcript retention policy is decided before model selection, not after launch. Store only what you need, redact payment card numbers at the STT layer, and route sensitive fields through tokenized APIs rather than raw LLM prompts.</p><p>PCI DSS requirements apply when agents process or repeat payment card data aloud. SOC 2 Type II certification from your platform vendor provides third-party validation of security controls for enterprise procurement reviews. Call recording laws in two-party consent states like California and Florida require explicit disclosure at the start of each recorded session.</p><p>For authoritative guidance on healthcare privacy obligations, see <a href="https://www.hhs.gov/hipaa/for-professionals/privacy/guidance/hipaa-audio-telehealth/index.html" rel="noreferrer">HHS HIPAA guidance</a> on telehealth and remote communications. Pair that reference with your legal team's state-by-state recording checklist before launching outbound campaigns.</p><p>Compliance architecture is a prerequisite for regulated AI voice agent use cases, not a post-launch patch.</p><h2 id="how-to-measure-roi-on-voice-agent-deployments">How to Measure ROI on Voice Agent Deployments</h2><p>Voice agent programs earn executive support when teams track operational metrics tied to revenue and cost, not vanity automation rates.</p><p>Track containment rate (calls resolved without human transfer), average handle time, cost per contained call, and customer satisfaction score segmented by agent vs. human resolution. Compare baseline metrics from the 30 days before launch against the same period after reaching stable traffic.</p><p>A mid-size e-commerce brand processing 12,000 monthly support calls illustrates the math. If tier-one inquiries represent 55% of volume and a voice agent contains 70% of those at $0.08 per minute versus $4.50 per human-handled minute, monthly savings exceed $15,000 while shaving average speed-to-answer from 4 minutes to under 10 seconds. Name your baseline, set a 90-day review, and kill workflows that transfer more than 40% of calls without improving CSAT.</p><p>According to McKinsey's research on AI in customer service, generative AI applied to customer care functions can improve issue resolution speed and customer satisfaction when paired with clear escalation design. Track first-call resolution alongside containment rate so you do not optimize for cheap transfers that frustrate callers.</p><p>Executives approve voice agent budgets when teams present containment rate, cost per call, and CSAT trends on a single dashboard updated monthly.</p><h2 id="implementing-ai-voice-agents-with-videosdk"><strong>Implementing AI Voice Agents with VideoSDK</strong></h2><p>Understanding the potential of AI voice agents is the first step; building them is the next. A successful implementation requires orchestrating several complex technologies to create a fluid, human-like conversational experience. This is where a dedicated SDK designed for real-time communication becomes invaluable.</p><h3 id="getting-started-with-an-ai-voice-agent-sdk"><strong>Getting Started with an AI Voice Agent SDK</strong></h3><p>To bring the use cases discussed above to life, developers need a streamlined way to integrate AI capabilities into a communication framework. An AI Voice Agent SDK, such as the one offered by VideoSDK, provides pre-built functionalities that handle the underlying complexities of real-time communication and AI integration. This allows developers to focus on crafting the agent's logic and personality rather than building the foundational infrastructure from scratch. The core of such an SDK revolves around four key components working in perfect harmony.</p><h4 id="overview-of-core-components"><strong>Overview of Core Components</strong></h4><ol><li><strong>Real-Time Streaming:</strong> This is the backbone of any live conversation. The SDK must manage the low-latency, bidirectional streaming of audio data between the user and the AI agent, ensuring the conversation flows naturally without awkward delays or interruptions.</li><li><strong>Speech-to-Text (STT):</strong> To understand the user, the AI agent needs to convert their spoken words into text. The SDK integrates with powerful STT engines that transcribe the user's audio in real-time, providing an accurate textual input for the AI model to process.</li><li><strong>Text-to-Speech (TTS):</strong> Once the AI has formulated a response, it needs to be converted back into natural-sounding speech. The SDK uses advanced TTS engines to generate high-quality, human-like audio, which is then streamed back to the user. The quality of the TTS is critical for user adoption and a positive experience.</li><li><strong>Agent Orchestration:</strong> This is the brain of the operation. The SDK orchestrates the entire workflow, managing the real-time flow of data between the STT service, your business logic or large language model (LLM), and the TTS service. This ensures that the agent can listen, think, and speak in a seamless, uninterrupted loop.</li></ol><h4 id="supported-integrations-for-maximum-flexibility"><strong>Supported Integrations for Maximum Flexibility</strong></h4><p>No single AI provider excels at everything. A flexible platform should allow developers to choose the best tools for their specific needs. VideoSDK's AI Voice Agent framework is designed to be plug-and-play, supporting integrations with leading AI services. Developers can mix and match providers for different components, including:</p><ul><li><strong>Speech-to-Text:</strong> Integrations with powerful engines like <strong>Google STT</strong> and <strong>OpenAI's Whisper</strong> ensure high-accuracy transcriptions across various languages and accents.</li><li><strong>Text-to-Speech:</strong> To create lifelike and emotionally resonant voices, the platform supports leading TTS providers like <strong>ElevenLabs</strong> and services from <strong>OpenAI</strong>.</li></ul><p>This "bring your own AI" model gives developers the freedom to leverage the best-in-class technology and future-proof their applications against a rapidly evolving AI landscape.</p><h4 id="sippstn-integration-for-telephony-grade-quality"><strong>SIP/PSTN Integration for Telephony-Grade Quality</strong></h4><p>While many AI interactions happen within apps, the ability to connect with traditional phone networks is crucial for countless business use cases, from customer service call centers to automated appointment reminders. The integration of Session Initiation Protocol (SIP) and Public Switched Telephone Network (PSTN) gateways is a vital feature. This allows the AI voice agent to make and receive calls from standard phone numbers, extending its reach beyond the digital-only world. VideoSDK's support for SIP/PSTN ensures that businesses can deploy AI agents into their existing telephony workflows, providing a seamless, telephony-grade quality experience for every user, regardless of how they connect.</p><h3 id="key-steps-to-build-your-own-voice-agent"><strong>Key Steps to Build Your Own Voice Agent</strong></h3><p>Here’s a step-by-step guide to creating your own AI voice agent using VideoSDK:</p><h4 id="step-1-choose-the-voice-model-tts-stt"><strong>Step 1: Choose the Voice Model (TTS + STT)</strong></h4><p>The first step is to select the text-to-speech and speech-to-text models that best suit your application. Consider factors like language support, accuracy, and the desired vocal characteristics of your agent.</p><p>Select providers based on:</p><ul><li><strong>Latency requirements</strong> (e.g., &lt;300ms for real-time calls)</li><li><strong>Language coverage</strong> (multi-lingual support for global deployments)</li><li><strong>Voice customization</strong> (brand-aligned tone &amp; gender)</li></ul><p><strong>Here is the example of the </strong><a href="https://docs.videosdk.live/ai_agents/plugins/tts/openai#example-usage"><strong><u>OpenAI TTS model</u></strong></a><strong>.</strong></p><pre><code class="language-python">from videosdk.plugins.openai import OpenAITTS
from videosdk.agents import CascadingPipeline

# Initialize the OpenAI TTS model
tts = OpenAITTS(
    # When OPENAI_API_KEY is set in .env - DON'T pass api_key parameter
    api_key="your-openai-api-key",
    model="tts-1",
    voice="alloy",
    speed=1.0,
    response_format="pcm"
)

#  Add tts to cascading pipeline
pipeline = CascadingPipeline(tts=tts)</code></pre><p>Alternatively you can try Google Gemini and AWS Nova Sonice</p><p><strong>Here is the example of the </strong><a href="https://docs.videosdk.live/ai_agents/plugins/stt/openai#example-usage"><strong><u>OpenAI STT model</u></strong></a><strong>.</strong></p><pre><code class="language-python">from videosdk.plugins.openai import OpenAISTT
from videosdk.agents import CascadingPipeline

# Initialize the OpenAI STT model
stt = OpenAISTT(
    # When OPENAI_API_KEY is set in .env - DON'T pass api_key parameter
    api_key="your-openai-api-key",
    model="whisper-1",
    language="en",
    prompt="Transcribe this audio with proper punctuation and formatting."
)

#  Add stt to cascading pipeline
pipeline = CascadingPipeline(stt=stt)</code></pre><h4 id="step-2-configure-videosdk-for-real-time-transport"><strong>Step 2: Configure VideoSDK for real-time transport</strong></h4><p>Next, you'll need to set up your VideoSDK environment to handle the real-time transport of audio data. This involves configuring your authentication tokens and meeting IDs to enable the AI agent to join a communication session. You will need to set up a .env file to securely store your API keys and tokens.</p><p><strong>Here is the </strong><a href="https://docs.videosdk.live/ai_agents/voice-agent-quick-start"><strong><u>OpenAI API key</u></strong></a><strong> to Configure VideoSDK for real-time transport&nbsp;</strong></p><pre><code class="language-python">VIDEOSDK_AUTH_TOKEN = your_videosdk_auth_token;
OPENAI_API_KEY = your_openai_api_key;
</code></pre><p>If you are using gemini or aws nova sonic you will need to provide their respective api key</p><h4 id="step-3-create-prompt-based-flows"><strong>Step 3: Create prompt-based flows</strong></h4><p>Define the conversational logic of your AI agent by creating prompt-based flows. This involves scripting the agent's initial greetings, questions, and responses based on potential user inputs. You can create a custom agent by inheriting from the base Agent class.&nbsp;</p><pre><code class="language-python">from videosdk.agents import Agent, AgentSession, WorkerJob, RoomOptions, JobContext
import asyncio

class VoiceAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions="You are a helpful voice assistant that can answer questions and help with tasks."
        )

    async def on_enter(self) -&gt; None:
        """Called when the agent first joins the meeting"""
        await self.session.say("Hi there! How can I help you today?")

    async def on_exit(self) -&gt; None:
        """Called when the agent exits the meeting"""
        await self.session.say("Goodbye!")</code></pre><h4 id="step-4-add-fallback-and-escalation-logic"><strong>Step 4: Add fallback and escalation logic</strong></h4><p>It's crucial to account for scenarios where the AI agent may not understand a user's request or when an error occurs. Implementing fallback logic to provide a helpful response and, if necessary, a mechanism to escalate the conversation to a human agent is a best practice.</p><p>The VideoSDK AI Agent SDK allows you to handle these situations by overriding specific methods in your custom agent class.</p><h3 id="handling-unrecognized-intents-fallback"><strong>Handling Unrecognized Intents (Fallback)</strong></h3><p>If the Large Language Model (LLM) cannot determine the user's intent or if the user's speech is unclear, you can define a fallback behavior. In this example, if the agent doesn't understand, it will ask the user to rephrase their request.</p><pre><code class="language-python">from videosdk.agents import Agent, AgentSession
from videosdk.llm import LLM
from videosdk.stt import STT
from videosdk.tts import TTS

class VoiceAgent(Agent):
    def __init__(
        self,
        llm: LLM,
        stt: STT,
        tts: TTS,
    ):
        super().__init__(
            llm=llm,
            stt=stt,
            tts=tts,
            instructions="You are a helpful voice assistant that can answer questions and help with tasks."
        )

    async def on_enter(self) -&gt; None:
        """Called when the agent first joins the meeting"""
        await self.session.say("Hi there! How can I help you today?")

    async def on_fallback(self) -&gt; None:
        """Called when the agent cannot understand the user's intent."""
        await self.session.say("I'm sorry, I didn't quite catch that. Could you please rephrase?")

    async def on_exit(self) -&gt; None:
        """Called when the agent exits the meeting"""
        await self.session.say("Goodbye!")</code></pre><h3 id="handling-errors-and-escalation"><strong>Handling Errors and Escalation</strong></h3><p>For more critical errors, or if the user explicitly asks to speak to a human, you can implement an escalation path. This could involve triggering a notification, transferring the call, or providing the user with contact information for human support.</p><p>The on_error method can be used to catch exceptions that occur during the agent's operation.</p><pre><code class="language-python">import logging

# ... (previous imports)

class VoiceAgent(Agent):
    # ... (__init__ and on_enter methods)

    async def on_fallback(self) -&gt; None:
        """Called when the agent cannot understand the user's intent."""
        await self.session.say("I'm sorry, I didn't quite catch that. Could you please rephrase?")

    async def on_error(self, error: Exception) -&gt; None:
        """Called when an error occurs."""
        logging.error(f"An error occurred: {error}")
        # Simple escalation: inform the user and provide a support email.
        await self.session.say("It seems I've run into a technical issue. Please contact our support team at support@example.com for assistance.")
        # In a more advanced scenario, you could trigger an API call
        # to a human handoff service here.

    async def on_exit(self) -&gt; None:
        """Called when the agent exits the meeting"""
        await self.session.say("Goodbye!")</code></pre><p>In a real-world application, the on_error or a custom function tool could be used to initiate a more sophisticated escalation process, such as:</p><ul><li><strong>Human Handoff:</strong> Triggering a workflow in a CRM or <a href="https://hiverhq.com/blog/best-free-helpdesk-ticketing-software" rel="noreferrer">helpdesk system</a> to alert a human agent to join the call.</li><li><strong>Ticket Creation:</strong> Automatically creating a support ticket with the conversation transcript.</li><li><strong>SIP Transfer:</strong> If using SIP integration, transferring the call to a pre-defined human agent's phone number.</li></ul><p>By implementing these fallback and escalation mechanisms, you ensure that your AI voice agent provides a reliable and helpful experience, even when faced with ambiguity or errors.</p><h3 id="step-5-deploy-to-production"><strong>Step 5: Deploy to production</strong></h3><p>Once you have thoroughly tested your AI voice agent, you can deploy it. The VideoSDK CLI allows you to run your agent locally for testing and then deploy it to the VideoSDK Cloud.</p><pre><code class="language-python"># Run the AI Deployment locally
videosdk run

# Deploy the AI Deployment
videosdk deploy</code></pre><h2 id="best-practices-for-scale-and-accuracy"><strong>Best Practices for Scale and Accuracy</strong></h2><p>To ensure your AI voice agent performs optimally and delivers a high-quality user experience as your user base grows, consider these best practices:</p><h3 id="use-context-aware-agents-via-mcp-or-a2a-protocols"><strong>Use context-aware agents (via MCP or A2A Protocols)</strong></h3><p>A truly intelligent agent understands the flow of conversation. Instead of treating each user query as an isolated event, a context-aware agent maintains a memory of the dialogue. This allows for more natural and efficient interactions.</p><p>VideoSDK facilitates this through <a href="https://www.videosdk.live/blog/ai-voice-agent-a2a-mcp"><strong><u>Agent-to-Agent (A2A) communication protocols</u></strong></a>. For example, a general-purpose AI voice agent could handle initial user queries and then, upon identifying a specialized need (like a technical support issue), can seamlessly forward the query and the conversation history to a specialist agent. This ensures the user doesn't have to repeat themselves, creating a smoother experience.</p><h3 id="cache-common-responses"><strong>Cache common responses</strong></h3><p>Many businesses find that a significant portion of their customer inquiries are repetitive. For these frequently asked questions (e.g., "What are your business hours?" or "How do I reset my password?"), caching the generated audio response can significantly improve performance.</p><p>By storing the pre-rendered TTS audio for common answers, you can:</p><ul><li><strong>Reduce Latency:</strong> Deliver answers almost instantaneously, as you're bypassing the real-time TTS generation step.</li><li><strong>Lower Costs:</strong> Minimize the number of API calls to TTS services, leading to direct cost savings, especially at scale.</li><li><strong>Increase Consistency:</strong> Ensure the answer to a common question is always delivered in the same clear and consistent manner.</li></ul><h3 id="personalize-with-user-metadata"><strong>Personalize with user metadata</strong></h3><p>Personalization is key to transforming a generic interaction into a memorable customer experience. By leveraging user metadata—such as their name, past purchase history, or support ticket status—your AI voice agent can provide tailored and empathetic responses.</p><p>For instance, an e-commerce voice agent could greet a returning customer with:</p><p><em>"Welcome back, [Customer Name]! I see your recent order for the [Product Name] has been shipped. Are you calling about that, or is there something else I can help you with today?"</em></p><p>This level of personalization, achievable by integrating your AI agent with your CRM or user database, makes the interaction feel more human and significantly improves customer satisfaction.</p><h3 id="use-multi-turn-dialogs-via-llm"><strong>Use multi-turn dialogs via LLM</strong></h3><p>Early voice bots were often limited to simple, one-off commands. Modern AI voice agents, powered by sophisticated Large Language Models (LLMs), excel at handling <strong>multi-turn dialogues</strong>. This means the agent can manage complex, evolving conversations where the user's intent might be clarified over several exchanges.</p><p>For example, a user might start by saying, "I need a flight to New York." The agent can then ask clarifying questions like, "Which airport in New York?", "What date would you like to travel?", and "Are you looking for a one-way or round-trip ticket?" The LLM's ability to maintain context throughout this back-and-forth is what makes a truly conversational and useful AI possible. VideoSDK’s architecture is designed to support these stateful, long-running conversations seamlessly.</p><h2 id="definitions-glossary">Definitions Glossary</h2><p><strong>AI voice agent:</strong>&nbsp;A software system that conducts spoken conversations by combining speech recognition, language understanding, and speech synthesis in real time.</p><p><strong>Speech-to-text (STT):</strong>&nbsp;Technology that converts spoken audio into text so language models can process user intent.</p><p><strong>Text-to-speech (TTS):</strong>&nbsp;Technology that converts text responses into synthetic speech streamed back to the caller.</p><p><strong>SIP/PSTN integration:</strong>&nbsp;Connectivity that lets voice agents place and receive calls on traditional phone networks, not just internet apps.</p><p><strong>Containment rate:</strong>&nbsp;The percentage of conversations an AI agent resolves without transferring to a human operator.</p><p><strong>Voice biometrics:</strong>&nbsp;Authentication that verifies identity from unique vocal characteristics before discussing sensitive account information.</p><h2 id="key-takeaways">Key Takeaways</h2><ul><li>AI voice agent use cases deliver the highest ROI on repetitive, high-volume calls such as scheduling, order tracking, payment reminders, and tier-one support.</li><li>Sub-300ms round-trip latency and reliable SIP/PSTN connectivity separate production-grade agents from demo-quality prototypes.</li><li>Regulated industries require compliance planning for HIPAA, PCI, GDPR, and call recording consent before launch, not after transcripts accumulate.</li><li>Voice agents should always include fast human escalation with full conversation context for complex, emotional, or legally sensitive interactions.</li><li>VideoSDK gives developer teams a single SDK for real-time audio, pluggable AI providers, telephony integration, and optional video handoff.</li></ul><h2 id="conclusion">Conclusion</h2><p>AI voice agent use cases are no longer experimental. Healthcare clinics, banks, retailers, and insurers deploy them to answer calls instantly, reduce operational cost, and pass rich context to humans when conversations outgrow automation.</p><p>Start with one high-volume workflow, measure containment and satisfaction for 90 days, and expand only where data supports it. VideoSDK provides the real-time audio infrastructure, AI provider integrations, and telephony reach to move from prototype to production without rebuilding your stack. Sign up for a free developer account and ship your first agent this week.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-are-the-most-common-ai-voice-agent-use-cases">What are the most common AI voice agent use cases?</h3><p>The most common AI voice agent use cases are appointment scheduling, customer support tier-one resolution, order status inquiries, payment and policy reminders, restaurant order taking, and insurance First Notice of Loss intake. These workflows share high call volume, predictable dialog structure, and clear escalation rules when automation reaches its limits.</p><h3 id="how-do-ai-voice-agents-differ-from-traditional-ivr">How do AI voice agents differ from traditional IVR?</h3><p>AI voice agents differ from traditional IVR because they understand natural spoken language instead of forcing callers through fixed keypad menus. IVR systems follow pre-recorded trees, while voice agents use speech-to-text and large language models to manage multi-turn conversations and adapt responses based on caller intent.</p><h3 id="which-industries-benefit-most-from-ai-voice-agents-in-2026">Which industries benefit most from AI voice agents in 2026?</h3><p>Healthcare, financial services, e-commerce, restaurants, insurance, and telecommunications benefit most because they combine high inbound call volume with repetitive intents that automation handles well. Industries with heavy compliance requirements still benefit when platforms provide encrypted transport, audit logging, and human escalation paths.</p><h3 id="are-ai-voice-agents-hipaa-compliant">Are AI voice agents HIPAA compliant?</h3><p>AI voice agents can support HIPAA-compliant workflows when deployed on infrastructure with encrypted audio transport, access controls, audit logs, and signed business associate agreements covering all AI and telephony vendors. Compliance depends on implementation choices, not the voice technology alone.</p><h3 id="how-much-does-it-cost-to-run-an-ai-voice-agent">How much does it cost to run an AI voice agent?</h3><p>Running an AI voice agent typically costs a blend of per-minute telephony fees, speech-to-text and text-to-speech API usage, LLM inference, and platform infrastructure charges. Total cost ranges from roughly $0.05 to $0.20 per contained minute for optimized deployments at scale, depending on provider selection and caching strategy [UPDATE: verify date].</p><h3 id="can-ai-voice-agents-transfer-calls-to-human-agents">Can AI voice agents transfer calls to human agents?</h3><p>AI voice agents can transfer calls to human agents through SIP transfer, conference join, or CRM-triggered callbacks while attaching transcripts and detected intent. Warm handoff preserves customer trust because the human agent continues the conversation without asking the caller to repeat information.</p><h3 id="what-should-developers-look-for-in-a-voice-agent-sdk">What should developers look for in a voice agent SDK?</h3><p>Developers should look for sub-300ms audio latency, bring-your-own STT/TTS/LLM support, SIP/PSTN telephony integration, built-in orchestration with fallback handling, and optional video escalation. VideoSDK provides these capabilities in a single SDK so teams ship production agents faster than assembling multiple point solutions.</p>]]></content:encoded></item><item><title><![CDATA[How to Build an AI Voice Agent in Minutes in 2026]]></title><description><![CDATA[Learn how to build an AI voice agent in minutes in 2026 using top conversational AI tools, voice automation, and real-time speech technologies.]]></description><link>https://www.videosdk.live/blog/build-ai-voice-agent</link><guid isPermaLink="false">6899f0a564df6f042b4d41b5</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 11 Aug 2025 13:49:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-4--2026--06_14_00-PM.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-4--2026--06_14_00-PM.png" alt="How to Build an AI Voice Agent in Minutes in 2026"/><p>Imagine a world where your customers can interact with an AI-powered agent that understands their needs, responds instantly, and provides a seamless experience across channels. This is the reality of AI Voice Agents in 2026.</p><p>In today’s fast-paced digital landscape, businesses are striving for ways to automate customer service and improve user experience. With AI-powered solutions like voice agents, SaaS companies can offer cutting-edge support that scales effortlessly. These intelligent systems are no longer a futuristic concept but a present-day reality, transforming how businesses engage with their customers.</p><p>In this blog, we’ll guide you through building an <a href="https://www.videosdk.live/voice-agents"><u>AI Voice Agent</u></a> in minutes using VideoSDK’s powerful tools and features, focusing on ease of integration, scalability, and customization. By the end, you'll understand the core components and be ready to deploy a sophisticated voice agent that can handle customer interactions, schedule appointments, and much more.</p><h2 id="what-are-ai-voice-agents-and-why-build-one-in-2026"><strong>What Are AI Voice Agents, and Why Build One in 2026?</strong></h2><p>An AI voice agent is an advanced software program designed to understand and respond to human speech in a natural, conversational manner. Unlike traditional, rigid IVR systems that rely on keypad inputs, AI voice agents leverage technologies like natural language processing to engage in human-like dialogue, automating both inbound and outbound calls without direct human oversight.</p><p>While off-the-shelf voice agent solutions exist, building your own provides unparalleled advantages in customization, brand identity, and data control. A custom voice agent allows you to create a unique and consistent auditory presence that aligns with your brand's personality, a critical differentiator in a crowded market. This ensures that every customer interaction, from a simple query to a complex transaction, reinforces your brand identity.</p><p><strong>The advantages of integrating a bespoke AI voice agent into your operations are substantial:</strong></p><ul><li><strong>Enhanced Customer Experience:</strong> Provide instant, 24/7 support and eliminate frustrating wait times, leading to higher customer satisfaction.</li><li><strong>Increased Operational Efficiency:</strong> Automate routine tasks like appointment scheduling and order updates, freeing up human agents to handle more complex issues.</li><li><strong>Cost Reduction:</strong> Scale your customer communication capabilities to handle high call volumes without a proportional increase in operational costs.</li><li><strong>Scalability and Consistency:</strong> Deliver standardized, high-quality responses that align with your brand's tone, ensuring a consistent experience for every customer.</li><li><strong>Data-Driven Insights:</strong> Gain valuable insights from customer interactions to further refine your products and services.</li></ul><h2 id="getting-started-with-your-ai-voice-agent-the-essential-toolkit"><strong>Getting Started with Your AI Voice Agent: The Essential Toolkit</strong></h2><p>Building a powerful AI voice agent involves the seamless integration of several core technologies. Here’s a breakdown of the essential components and their roles in creating a conversational AI experience.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/08/Untitled--10-.png" class="kg-image" alt="How to Build an AI Voice Agent in Minutes in 2026" loading="lazy" width="2067" height="1311"/></figure><h3 id="automatic-speech-recognition-asr"><strong>Automatic Speech Recognition (ASR)</strong></h3><p>Automatic Speech Recognition (ASR), also known as speech-to-text, is the foundational technology that converts spoken language into written text. It is the "ears" of your AI agent, enabling it to listen to and understand human speech in real-time.&nbsp;</p><p>The accuracy and speed of your ASR system are critical for a smooth conversational flow. A high-quality ASR engine ensures that the user's words are transcribed precisely, which is the first and most crucial step for the agent to comprehend the request. Modern ASR can handle various languages, accents, and even operate in noisy environments, making it a robust solution for global businesses. For any developer looking to build a voice-driven application, integrating a powerful real-time transcription API is non-negotiable.</p><h3 id="natural-language-processing-nlp-large-language-models-llms"><strong>Natural Language Processing (NLP) &amp; Large Language Models (LLMs)</strong></h3><p>Natural Language Processing (NLP) is a field of AI that gives machines the ability to understand, interpret, and generate human language. Large Language Models (LLMs) are an advanced application of NLP, trained on massive datasets to understand context, nuance, and intent, enabling them to generate coherent and relevant responses.</p><p>NLP and LLMs are the "brain" of your AI voice agent. While ASR transcribes <em>what</em> is said, NLP/LLMs figure out <em>what is meant</em>.&nbsp; They analyze the transcribed text to identify user intent, extract key information, and formulate a contextually appropriate response. This combination allows for dynamic, human-like conversations that go far beyond scripted, rule-based interactions, leading to more satisfying and effective user engagement.</p><h3 id="text-to-speech-tts"><strong>Text-to-Speech (TTS)</strong></h3><p>Text-to-Speech (TTS) technology converts written text back into natural-sounding human speech. This is the "voice" of your AI agent, giving it the ability to communicate its responses audibly.</p><p>The quality of the TTS voice is paramount for a positive user experience. A robotic, unnatural voice can be off-putting, while a clear, expressive, and human-like voice builds trust and keeps users engaged. Modern TTS systems allow for customization of voice, tone, gender, and accent, enabling you to create a voice personality that perfectly reflects your brand. This consistency across touchpoints strengthens brand recall and fosters a more personal connection with your audience.</p><h3 id="real-time-communication-webrtc"><strong>Real-Time Communication (WebRTC)</strong></h3><p>WebRTC (Web Real-Time Communication) is an open-source framework that enables real-time voice, video, and data communication directly between web browsers and devices without requiring plugins.</p><p>WebRTC is the "nervous system" that transmits the audio data between the user and the AI agent instantly. It provides the low-latency, secure, and reliable infrastructure necessary for seamless, real-time conversations. Whether you are building for the web, iOS, or Android, leveraging a robust <a href="https://www.videosdk.live/audio-video-conferencing"><u>Voice Calling API SDK</u></a> powered by WebRTC is essential. VideoSDK offers highly reliable, cross-platform SDKs that allow you to deploy AI voice agents and other real-time communication features with just a few lines of code, ensuring a scalable and secure implementation anywhere in the world. By combining these powerful technologies on a flexible platform like <a href="https://www.videosdk.live/">VideoSDK</a>, you can build and deploy a sophisticated AI voice agent that not only meets but exceeds customer expectations in 2026.</p><h2 id="how-to-build-an-ai-voice-agent-in-6-simple-steps-with-videosdk"><strong>How to Build an AI Voice Agent in 6 Simple Steps with VideoSDK</strong></h2><p>Building a state-of-the-art AI voice agent is no longer a monumental task reserved for large corporations. With VideoSDK's open-source AI Agent SDK, you can create and deploy a powerful, conversational AI agent in minutes. Our Python-based framework is designed for flexibility, allowing you to either use integrated real-time pipelines or build custom agents by combining your preferred STT, LLM, and TTS providers.</p><p>Here’s a step-by-step guide to bringing your voice agent to life.</p><h3 id="step-1-set-up-your-development-environment"><strong>Step 1: Set Up Your Development Environment</strong></h3><p>First, ensure you have the necessary prerequisites in place. Your backend will host the AI agent, while a client application will connect users to the agent in a VideoSDK meeting room.</p><p><strong>Prerequisites:</strong></p><ul><li>Python 3.12 or higher.</li><li>A <strong>VideoSDK Auth Token</strong>. You can generate these from the <a href="https://app.videosdk.live/">VideoSDK dashboard</a>.</li><li>API keys for your chosen third-party services (e.g., OpenAI for LLM, Deepgram for STT, ElevenLabs for TTS).</li></ul><p><strong>Installation:</strong>Create a Python virtual environment and install the VideoSDK Agents package along with any provider plugins you need.</p><pre><code class="language-python"># Create and activate virtual environment
python3.12 -m venv venv
source venv/bin/activate

# Install the core VideoSDK AI Agent package
pip install videosdk-agents

# Example: Install plugins for OpenAI, Google, and AWS
pip install "videosdk-plugins-openai"
pip install "videosdk-plugins-google"
pip install "videosdk-plugins-aws"</code></pre><p>Next, create a .env file in your project's root to securely store your API keys and tokens.</p><pre><code class="language-python">VIDEOSDK_AUTH_TOKEN=YOUR_VIDEOSDK_AUTH_TOKEN
OPENAI_API_KEY=YOUR_OPENAI_API_KEY
ELEVENLABS_API_KEY=YOUR_ELEVENLABS_API_KEY</code></pre><h3 id="step-2-integrating-webrtc-for-real-time-communication"><strong>Step 2: Integrating WebRTC for Real-Time Communication</strong></h3><p>WebRTC is the cornerstone of real-time voice experiences, enabling ultra-low-latency audio streaming directly between your users and the AI agent. While traditional methods like WebSockets can introduce noticeable lag, especially on unstable networks, WebRTC is specifically designed for reliable, real-time voice in any environment.</p><p>VideoSDK abstracts the complexities of WebRTC. The AI Agent SDK handles all the underlying communication, allowing your agent to join a meeting room just like any other participant. Your backend simply needs to initiate the session. The client-side application can be built using any of VideoSDK's SDKs, including React, React Native, Android, and iOS.</p><p><strong>Here’s how your Python server instructs the agent to join a meeting:</strong></p><pre><code class="language-python"># main.py
from fastapi import FastAPI
from dotenv import load_dotenv
import os
from your_agent_file import VoiceAgent, create_agent_session # Your custom agent logic

load_dotenv()

app = FastAPI()

@app.post("/join-agent")
async def join_agent(request_data: dict):
    meeting_id = request_data.get("meeting_id")
    auth_token = os.getenv("VIDEOSDK_AUTH_TOKEN")

    if not meeting_id or not auth_token:
        return {"error": "Meeting ID and auth token are required."}

    # Create and start the agent session in the background
    session = await create_agent_session(meeting_id, auth_token)
    await session.start()

    return {"message": "Agent is joining the meeting."}</code></pre><h3 id="step-3-configuring-speech-to-text-and-nlp-capabilities"><strong>Step 3: Configuring Speech-to-Text and NLP Capabilities</strong></h3><p>Accurate and fast transcription is non-negotiable for a voice agent to understand users correctly. Similarly, a high-quality, natural-sounding voice is essential for user engagement. VideoSDK’s CascadingPipeline offers a modular approach, giving you complete control to mix and match the best STT and TTS providers for your needs. You can choose from providers like Deepgram, Google, and more.</p><p><strong>Here is how you can configure a pipeline using Google for STT and ElevenLabs for TTS:</strong></p><pre><code class="language-python"># agent_logic.py
from videosdk.agents import Agent, AgentSession, CascadingPipeline
from videosdk.plugins.google import GoogleSTT
from videosdk.plugins.elevenlabs import ElevenLabsTTS

# Define your agent's personality and tools
class VoiceAgent(Agent):
    def __init__(self):
        super().__init__(
            instructions="You are a friendly and helpful assistant."
        )

# Configure the pipeline with your chosen STT and TTS providers
async def create_agent_session(meeting_id: str, auth_token: str):
    stt_config = {"model": "long", "language_code": "en-US"}
    stt_provider = GoogleSTT(config=stt_config)

# Configure OpenAI LLM below

llm_provider = OpenAILLM(
   model="gpt-4o",
   # When OPENAI_API_KEY is set in .env - DON'T pass api_key parameter
   api_key="your-openai-api-key",
   temperature=0.7,
   tool_choice="auto",
   max_completion_tokens=1000
)


    tts_config = {"model_id": "eleven_multilingual_v2"}
    tts_provider = ElevenLabsTTS(config=tts_config)
    
    pipeline = CascadingPipeline(
        stt=stt_provider,
        tts=tts_provider,
        llm=llm_provider
    )

    agent = VoiceAgent()
    session = AgentSession(agent=agent, pipeline=pipeline, meeting_id=meeting_id, auth_token=auth_token)
    return session</code></pre><h3 id="step-4-adding-ai-for-contextual-conversations"><strong>Step 4: Adding AI for Contextual Conversations</strong></h3><p>The Large Language Model (LLM) is the brain of your agent. This is where you integrate models like GPT-4 to process the transcribed text and generate intelligent, context-aware responses. VideoSDK’s framework seamlessly connects your chosen LLM into the conversation flow.</p><p><strong>Let's complete the pipeline from the previous step by adding OpenAI's GPT-4 as the LLM.</strong></p><pre><code class="language-python"># agent_logic.py (continued from Step 3)
from videosdk.plugins.openai import OpenAILLM

# ... (VoiceAgent class and other imports) ...

# Configure the pipeline with STT, TTS, and now LLM
async def create_agent_session(meeting_id: str, auth_token: str):
    # ... (STT and TTS provider setup) ...

    llm_config = {"model": "gpt-4"}
    llm_provider = OpenAILLM(config=llm_config)
    
    pipeline = CascadingPipeline(
        stt=stt_provider,
        llm=llm_provider,
        tts=tts_provider,
    )

    agent = VoiceAgent()
    session = AgentSession(agent=agent, pipeline=pipeline, meeting_id=meeting_id, auth_token=auth_token)

    # Add a greeting when the agent joins
    @agent.on_enter
    async def on_enter(session):
        await session.say("Hello! I'm your AI assistant. How can I help you today?")

    return session</code></pre><p>With this setup, the audio pipeline is complete: VideoSDK captures user audio, Google transcribes it, OpenAI processes the text and generates a response, and ElevenLabs converts that text back into speech for the user to hear.</p><h3 id="step-5-deploy-and-test-your-ai-voice-agent"><strong>Step 5: Deploy and Test Your AI Voice Agent</strong></h3><p>Your AI agent's backend logic, housed in a web server like FastAPI, can be deployed to any modern cloud service.&nbsp; Popular choices include serverless platforms like Vercel or AWS Lambda for scalability, or containerized applications on services like AWS Fargate or Google Cloud Run.</p><p><strong>Create a videosdk.ymal file with following structure : </strong></p><pre><code class="language-python">version: "1.0"
deployment:
  id: your_ai_deployment_id
  entry:
    path: entry_point_for_deployment
env: # Optional to run your agent locally
  path: "./.env"
secrets:
  VIDEOSDK_AUTH_TOKEN: your_auth_token
deploy:
 cloud: true</code></pre><p><strong>Deploy voice agent : </strong></p><p>1. Run AI Development Locally: </p><pre><code class="language-python">videosdk run</code></pre><p>2. Deploy Voice Agent</p><pre><code class="language-python">videosdk deploy</code></pre><p><strong>Testing focuses on two key metrics:</strong></p><ul><li><strong>Latency:</strong> Measure the time from when a user finishes speaking to when they hear the agent's response. An ideal response time is under one second to feel natural. VideoSDK's infrastructure is optimized for sub-80ms latency, giving you a strong foundation.</li><li><strong>Accuracy:</strong> Review call transcripts and agent responses to check for errors in transcription or intent recognition. Use this data to refine your agent's instructions (prompts) and improve its conversational abilities.</li></ul><h3 id="step-6-optimize-for-scale-and-performance"><strong>Step 6: Optimize for Scale and Performance</strong></h3><p>As your user base grows, you'll need to ensure your voice agent can handle high traffic without degrading performance.</p><p><strong>Best Practices for Optimization:</strong></p><ul><li><strong>Load Balancing:</strong> Deploy your backend server across multiple instances and use a load balancer to distribute incoming requests. This prevents any single server from becoming a bottleneck.</li><li><strong>Efficient Prompt Engineering:</strong> Optimize your LLM prompts for speed and clarity. Well-structured prompts reduce the computation required by the model, leading to faster response generation.</li><li><strong>Asynchronous Processing:</strong> Leverage asynchronous tasks for non-blocking operations. For instance, if your agent needs to fetch data from an external API, do it asynchronously so it can still handle other conversational turns. VideoSDK's Python SDK is built with async support to facilitate this.</li><li><strong>Monitor Performance Metrics:</strong> Continuously track metrics like first-call resolution, average response time, and user sentiment. Use these insights to iteratively improve your agent's logic and performance.</li></ul><h2 id="best-practices-for-an-exceptional-ai-voice-agent-experience"><strong>Best Practices for an Exceptional AI Voice Agent Experience</strong></h2><p>Building an agent that can talk is one thing; creating an experience that feels natural and intelligent is another. Here are the core principles to elevate your AI voice agent from functional to exceptional.</p><h3 id="low-latency-is-key"><strong>Low Latency is Key</strong></h3><p>In human conversation, the natural pause between turns is often just a few hundred milliseconds. Any delay beyond that feels awkward and breaks the conversational flow, making the AI feel slow or robotic. This is why ultra-low latency is not just a technical metric but a fundamental requirement for a great user experience. VideoSDK is built for this, with a global mesh network optimized for real-time communication and an AI Agent SDK engineered to minimize delays, typically achieving end-to-end latency of under 600ms. This ensures that interactions are snappy, responsive, and feel as natural as talking to a person.</p><h3 id="contextual-memory"><strong>Contextual Memory</strong></h3><p>A conversation without memory is just a series of disconnected questions and answers. For an agent to be truly helpful, it must remember what was said earlier in the conversation (short-term memory) and even recall information from past interactions (long-term memory). VideoSDK's framework is designed to support this, allowing you to build agents that maintain context. This enables more coherent, personalized, and intelligent dialogues where the agent can reference past details, understand follow-up questions, and provide truly relevant responses.</p><h3 id="handling-interruptions"><strong>Handling Interruptions</strong></h3><p>Natural conversations are not always perfectly linear; people interrupt each other. A great AI voice agent must handle this gracefully. This is achieved through advanced Voice Activity Detection (VAD), which detects when a user starts speaking and signals the agent to stop talking immediately. VideoSDK’s Agent SDK manages this complex process, allowing for fluid turn-taking where users can jump in, change the topic, or ask for clarification without waiting for the agent to finish its sentence. This capability is crucial for making the interaction feel collaborative rather than scripted.</p><h2 id="conclusion"><strong>Conclusion</strong></h2><p>In 2026, building a powerful, conversational AI voice agent is no longer a futuristic vision but an accessible reality. By combining the core technologies of ASR, NLP/LLMs, and TTS with a robust <a href="https://www.videosdk.live/blog/introduction-to-real-time-communication-sdk" rel="noreferrer">real-time communication</a> backbone like WebRTC, developers can create truly intelligent systems.</p><p>As we've seen, <a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> provides a comprehensive, open-source framework that abstracts away the complexities of real-time transport and multi-provider integration. With just a few lines of Python, you can deploy a scalable, low-latency agent equipped with contextual memory, function-calling capabilities, and natural interruption handling.</p><p>Whether you're looking to revolutionize customer support, automate sales qualification, or create interactive educational experiences, the tools are at your fingertips. The future of human-computer interaction is here, and with VideoSDK, you have everything you need to build it.</p>]]></content:encoded></item><item><title><![CDATA[Deploy VideoSDK Telephony Voice Agents on Cerebrium]]></title><description><![CDATA[AI telephony agent with VideoSDK & Cerebrium. A step-by-step guide with full code to deploy your own voice solution.]]></description><link>https://www.videosdk.live/blog/deploy-telephony-agents-on-cerebrium</link><guid isPermaLink="false">688b61f964df6f042b4d40ec</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 05 Aug 2025 06:46:18 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/08/Cerebrium-x-VideoSDK--1-.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2025/08/Cerebrium-x-VideoSDK--1-.png" alt="Deploy VideoSDK Telephony Voice Agents on Cerebrium"/><p> AI-powered telephony solutions are revolutionizing customer service, sales, and communication workflows. This comprehensive guide shows you how to build a sophisticated AI telephony agent using VideoSDK's powerful voice agent capabilities, deployed seamlessly on Cerebrium's cloud platform.</p><h2 id="what-were-building">What We're Building</h2><p>We'll create a complete AI telephony system that can:</p><ul><li>Handle both inbound and outbound voice calls</li><li>Integrate with SIP providers like Twilio</li><li>Leverage Google's Gemini AI for intelligent conversations</li><li>Deploy automatically on Cerebrium's scalable infrastructure</li><li>Provide real-time voice processing with minimal latency</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/08/cerebruim-telephony-agent.png" class="kg-image" alt="Deploy VideoSDK Telephony Voice Agents on Cerebrium" loading="lazy" width="2588" height="1425"/></figure><h2 id="architecture-overview">Architecture Overview</h2><p>Our AI telephony agent combines several powerful technologies:</p><ul><li><strong>VideoSDK Agents</strong>: The core voice agent framework</li><li><strong>SIP Integration</strong>: For telephony connectivity via Twilio</li><li><strong>Gemini AI</strong>: Real-time conversational intelligence</li><li><strong>Cerebrium</strong>: Cloud deployment and scaling platform</li></ul><h2 id="prerequisites">Prerequisites</h2><p>Before we start, you'll need accounts and credentials for the following services. Here are the links to get you started:</p><ul><li><a href="https://app.videosdk.live/">VideoSDK Auth Token</a></li><li><a href="https://console.twilio.com/">Twilio</a> SIP trunking setup</li><li><a href="https://aistudio.google.com/app/apikey">Google API key</a> for Gemini</li><li><a href="https://dashboard.cerebrium.ai/register">Cerebrium</a> account, follow docs <a href="https://docs.cerebrium.ai/cerebrium/getting-started/introduction">here</a></li></ul><h2 id="project-structure">Project Structure</h2><p>Our project follows a clean, modular structure:</p><pre><code class="language-shell">├── cerebrium.toml
├── main.py
├── requirements.txt
└── README.md
</code></pre><h2 id="initialize-your-project"><strong>Initialize Your Project</strong></h2><p>Let's begin by setting up our project directory and basic configuration using the Cerebrium Command Line Interface (CLI).</p><pre><code class="language-bash">pip install cerebrium
cerebrium login
cerebrium init videosdk-telephony-agent
</code></pre><h2 id="configure-cerebrium-deployment">Configure Cerebrium Deployment</h2><p>First, let's set up our <strong>cerebrium.toml</strong> configuration file for optimal deployment:</p><pre><code class="language-bash">[cerebrium.deployment]
name = "sip-ai-agent"
python_version = "3.12"
include = ["./*", "main.py", "cerebrium.toml"]
exclude = [".venv"]
disable_auth = true

[cerebrium.hardware]
region = "us-east-1"
provider = "aws"
compute = "CPU"
cpu = 2
memory = 4.0
gpu_count = 0

[cerebrium.runtime.custom]
port = 8000
entrypoint = ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
healthcheck_endpoint = "/"

[cerebrium.scaling]
min_replicas = 1
max_replicas = 2
cooldown = 30
replica_concurrency = 4
scaling_metric = "concurrency_utilization"
scaling_target = 80

[cerebrium.dependencies.paths]
pip = "requirements.txt"
</code></pre><p>This configuration ensures:</p><ul><li><strong>Scalability</strong>: Auto-scaling between 1-2 replicas based on concurrency, ensuring the app can handle fluctuating call volumes.</li><li><strong>Performance</strong>: Optimized CPU and memory allocation for real-time voice processing.</li><li><strong>Dependency Management</strong>: It clearly points to our&nbsp;requirements.txt&nbsp;file, keeping our dependencies separate and organized.</li></ul><h2 id="define-project-dependencies">Define Project Dependencies</h2><p>Create a <strong>requirements.txt</strong> file in your project directory, you can also view or download the complete file directly from the project's official <a href="https://github.com/videosdk-community/videosdk-telephony-agent/blob/main/requirements.txt">GitHub repository</a></p><h2 id="build-the-core-ai-agent">Build the Core AI Agent</h2><p>Now, let's create our main application in <strong>main.py</strong>. Here's the complete implementation:</p><pre><code class="language-python">import asyncio
import os
import logging
from contextlib import asynccontextmanager
from typing import Optional
from dotenv import load_dotenv
from fastapi import FastAPI, Request, Response
import uvicorn
from pyngrok import ngrok
from videosdk.plugins.sip import create_sip_manager
from videosdk.agents import Agent, JobContext, function_tool, RealTimePipeline
from videosdk.plugins.google import GeminiRealtime, GeminiLiveConfig

load_dotenv()

logging.basicConfig(level=os.getenv("LOG_LEVEL", "INFO"))
logger = logging.getLogger(__name__)

def create_agent_pipeline():
    """Function to create the specific pipeline for our agent."""
    model = GeminiRealtime(
        api_key=os.getenv("GOOGLE_API_KEY"),
        model="gemini-2.0-flash-live-001",
        config=GeminiLiveConfig(
            voice="Leda", # type: ignore
            response_modalities=["AUDIO"], # type: ignore
        ),
    )
    return RealTimePipeline(model=model)

class SIPAIAgent(Agent):
    """A AI agent for handling voice calls."""

    def __init__(self, ctx: Optional[JobContext] = None):
        super().__init__(
            instructions=(
             "You are a helpful voice assistant that can answer questions and help with tasks. Be friendly and concise."
             "Talk to the user as if you are a human and not a robot."
             ),
            tools=[self.end_call], # type: ignore
        )
        self.ctx = ctx
        self.greeting_message = "Hello! Thank you for calling. How can I assist you today?"
        logger.info(f"SIPAIAgent created")

    async def on_enter(self) -&gt; None:
        pass

    async def greet_user(self) -&gt; None:
        await self.session.say(self.greeting_message) # type: ignore

    async def on_exit(self) -&gt; None:
        pass

    @function_tool
    async def end_call(self) -&gt; str:
        """End the current call gracefully"""
        await self.session.say("Thank you for calling. Have a great day!") # type: ignore
        await asyncio.sleep(1)
        await self.session.leave() # type: ignore
        return "Call ended gracefully"

sip_manager = create_sip_manager(
    provider=os.getenv("SIP_PROVIDER", "twilio"),
    videosdk_token=os.getenv("VIDEOSDK_AUTH_TOKEN"),
    provider_config={
        # Twilio config
        "account_sid": os.getenv("TWILIO_ACCOUNT_SID"),
        "auth_token": os.getenv("TWILIO_AUTH_TOKEN"),
        "phone_number": os.getenv("TWILIO_PHONE_NUMBER"),
    }
)

@asynccontextmanager
async def lifespan(app: FastAPI):
    """Lifespan manager for FastAPI app startup and shutdown."""
    port = int(os.getenv("PORT", 8000))
    try:
        ngrok.kill()
        ngrok_auth_token = os.getenv("NGROK_AUTHTOKEN")
        if ngrok_auth_token:
            ngrok.set_auth_token(ngrok_auth_token)
        tunnel = ngrok.connect(str(port), "http")
        sip_manager.set_base_url(tunnel.public_url) # type: ignore
        logger.info(f"Ngrok tunnel created: {tunnel.public_url}")
    except Exception as e:
        logger.error(f"Failed to start ngrok tunnel: {e}")
    yield
    try:
        ngrok.kill()
        logger.info("Ngrok tunnel closed")
    except Exception as e:
        logger.error(f"Error closing ngrok tunnel: {e}")

app = FastAPI(title="SIP AI Agent", lifespan=lifespan)

@app.post("/call/make")
async def make_call(to_number: str):
    if not sip_manager.base_url:
        return {"status": "error", "message": "Service not ready (no base URL)."}
    agent_config = {"room_name": "Call", "enable_pubsub": True}
    details = await sip_manager.make_call(
        to_number=to_number,
        agent_class=SIPAIAgent,
        pipeline=create_agent_pipeline,
        agent_config=agent_config
    )
    return {"status": "success", "details": details}

@app.post("/sip/answer/{room_id}")
async def answer_webhook(room_id: str):
    logger.info(f"Answering call for room: {room_id}")
    body, status_code, headers = sip_manager.get_sip_response_for_room(room_id)
    return Response(content=body, status_code=status_code, media_type=headers.get("Content-Type"))

@app.post("/webhook/incoming")
async def incoming_webhook(request: Request):
    try:
        content_type = request.headers.get("Content-Type", "")
        if "x-www-form-urlencoded" in content_type:
            webhook_data = dict(await request.form())
        else:
            webhook_data = await request.json()
        logger.info(f"Received incoming webhook: {webhook_data}")

        agent_config = {"room_name": "Incoming Call", "enable_pubsub": True}
        body, status_code, headers = await sip_manager.handle_incoming_call(
            webhook_data=webhook_data,
            agent_class=SIPAIAgent,
            pipeline=create_agent_pipeline,
            agent_config=agent_config
        )
        return Response(content=body, status_code=status_code, media_type=headers.get("Content-Type"))
    except Exception as e:
        logger.error(f"Error in incoming webhook: {e}", exc_info=True)
        return Response(content="Error processing request", status_code=500)

@app.get("/sessions")
async def get_sessions():
    return {"sessions": sip_manager.get_active_sessions()}

@app.get("/")
async def root():
    return {"message": "SIP AI Agent"}

if __name__ == "__main__":
    port = int(os.getenv("PORT", 8000))
    logger.info(f"Starting SIP AI Agent on port {port}")
    uvicorn.run(app, host="0.0.0.0", port=port)
</code></pre><h2 id="key-components-explained">Key Components Explained</h2><h3 id="1-agent-pipeline-creation">1. Agent Pipeline Creation</h3><p>The <strong>create_agent_pipeline()</strong> function sets up our Gemini AI model with specific configurations:</p><ul><li><strong>Model</strong>: <strong>gemini-2.0-flash-live-001</strong> for real-time processing</li><li><strong>Voice</strong>: "Leda" for natural-sounding responses</li><li><strong>Modalities</strong>: Audio-only responses for telephony</li></ul><h3 id="2-sipaiagent-class">2. SIPAIAgent Class</h3><p>Our custom agent class inherits from VideoSDK's <strong>Agent</strong> base class and includes:</p><ul><li><strong>Instructions</strong>: Clear behavioral guidelines for the AI</li><li><strong>Tools</strong>: Built-in function tools like <strong>end_call()</strong></li><li><strong>Lifecycle methods</strong>: <strong>on_enter()</strong>, <strong>greet_user()</strong>, <strong>on_exit()</strong></li></ul><h3 id="3-sip-manager-integration">3. SIP Manager Integration</h3><p>The SIP manager handles all telephony operations:</p><ul><li><strong>Provider Configuration</strong>: Twilio credentials and settings</li><li><strong>Call Management</strong>: Both inbound and outbound call handling</li><li><strong>Session Tracking</strong>: Active session monitoring</li></ul><h3 id="api-endpoints">API Endpoints</h3><p>Our API provides several key endpoints:</p><ul><li><strong>POST /call/make</strong>: Initiate outbound calls</li><li><strong>POST /webhook/incoming</strong>: Handle incoming call webhooks</li><li><strong>POST /sip/answer/{room_id}</strong>: Process SIP responses</li><li><strong>GET /sessions</strong>:Monitor active sessions</li></ul><h2 id="environment-configuration">Environment Configuration</h2><p>Set up these environment variables for your deployment by adding them to a&nbsp;<strong>.env</strong>&nbsp;file</p><pre><code class="language-bash"># VideoSDK Configuration
VIDEOSDK_AUTH_TOKEN=your_videosdk_token

# AI Configuration
GOOGLE_API_KEY=your_google_api_key

# Twilio Configuration
TWILIO_ACCOUNT_SID=your_account_sid
TWILIO_AUTH_TOKEN=your_auth_token
TWILIO_PHONE_NUMBER=your_phone_number

# Optional
NGROK_AUTHTOKEN=your_ngrok_token
SIP_PROVIDER=twilio
</code></pre><p>To make these available to your deployment, add them to the&nbsp;<a href="https://docs.cerebrium.ai/cerebrium/other-topics/using-secrets#using-secrets"><strong>Secrets</strong></a>&nbsp;view on your Cerebrium dashboard.</p><h2 id="deploying-on-cerebrium">Deploying on Cerebrium</h2><p>Cerebrium makes deployment incredibly straightforward:</p><ol><li><strong>Install Cerebrium CLI</strong>:</li></ol><pre><code class="language-bash">pip install cerebrium
</code></pre><ol><li><strong>Deploy your application</strong>:</li></ol><pre><code class="language-bash">cerebrium deploy
</code></pre><p>After the deployment finishes, you will receive a public URL to interact with your application. It will have a format similar to this:</p><pre><code class="language-bash">&lt;https://api.aws.us-east-1.cerebrium.ai/v4/p-xxxxxxxx/sip-ai-agent/&gt;
</code></pre><h2 id="videosdk-documentation-resources">VideoSDK Documentation Resources</h2><p>For deeper integration and customization, explore these VideoSDK resources:</p><ul><li><a href="https://docs.videosdk.live/ai_agents/introduction">AI Agents Introduction</a></li><li><a href="https://docs.videosdk.live/ai_agents/voice-agent-quick-start">Quick Start Guide</a></li><li><a href="https://docs.videosdk.live/ai_agents/core-components/overview">Core Components Overview</a></li><li><a href="https://docs.videosdk.live/ai_agents/core-components/agent">Agent Implementation</a></li><li><a href="https://docs.videosdk.live/ai_agents/core-components/realtime-pipeline">Real-time Pipeline</a></li><li><a href="https://docs.videosdk.live/ai_agents/sip">SIP Integration</a></li><li><a href="https://docs.videosdk.live/ai_agents/running-multiple-agents">Multiple Agents</a></li></ul><h2 id="conclusion">Conclusion</h2><p>Building an AI telephony agent with VideoSDK and deploying on Cerebrium creates a powerful, scalable communication solution. This architecture provides:</p><ul><li><strong>Rapid Development</strong>: Get started in minutes with pre-built components</li><li><strong>Enterprise Scale</strong>: Handle thousands of concurrent calls</li><li><strong>Cost Efficiency</strong>: Pay-per-use pricing model</li><li><strong>Global Reach</strong>: Deploy worldwide with minimal latency</li></ul><p>The combination of VideoSDK's robust voice agent framework and Cerebrium's intelligent cloud platform creates an ideal environment for modern AI-powered telephony solutions.</p><p>Ready to get started? Check out the <a href="https://docs.videosdk.live/ai_agents/introduction">VideoSDK AI Agents documentation</a> and deploy your first agent on <a href="https://cerebrium.ai/">Cerebrium</a> today!</p>]]></content:encoded></item><item><title><![CDATA[Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK]]></title><description><![CDATA[Build an iOS video calling feature that triggers native call screens, manages VoIP notifications, and handles answering or rejecting calls seamlessly.]]></description><link>https://www.videosdk.live/blog/flutter-ios-callkit</link><guid isPermaLink="false">677e5cf8dbc171042ac708d9</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 21 Jul 2025 11:46:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/05/call-trigger_iOS_flutter.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2025/05/call-trigger_iOS_flutter.png" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK"/><p><br><em>Creating a native-like call experience on iOS using Flutter can be challenging—but with the right tools, it becomes seamless. In this guide, we’ll show you how to build a video calling feature for iOS that feels just like a regular phone call.</em></br></p><p><em>Using the flutter_callkit_incoming package, you’ll be able to trigger native iOS call screens, manage VoIP-style incoming call notifications, and handle user interactions like answering or rejecting a call—all without writing any Swift code</em></p><p><em>Explore the </em><a href="https://github.com/videosdk-live/videosdk-rtc-flutter-call-trigger-example" rel="noreferrer"><em>full source code</em></a><em> to see how everything fits together.</em></p><h2 id="introduction-to-flutter-callkit-incoming"><em>Introduction to Flutter CallKit Incoming</em></h2><p><em>The <code>flutter_callkit_incoming</code> package simplifies the integration of iOS CallKit into Flutter applications. This package allows developers to:</em></p><ul><li><em>Present native iOS call screens.</em></li><li><em>Manage incoming call notifications.</em></li><li><em>Enhance the overall call experience.</em></li></ul><p><em>It abstracts the complexities of implementing CallKit in Swift, enabling quick and efficient call handling for iOS users.</em></p><h2 id="overview-of-the-application-in-ios"><em>Overview of the Application in IOS</em><br/></h2><h3 id="initiating-a-call"><em><strong>Initiating a Call</strong>:</em></h3><ul><li><em>The caller (e.g., Pavan) enters the recipient's unique ID (e.g., Jay) and presses the call button.</em></li><li><em>This action triggers a server request to initiate the call, which sends a Firebase Cloud Messaging (FCM) notification to the recipient's device through API, and a fake call is being triggered on the Receiver Caller Side.</em></li></ul><h3 id="receiving-the-call"><em><strong>Receiving the Call</strong>:</em></h3><ul><li><em><strong>If the app is in the foreground</strong>: If the App is in the <strong>foreground</strong> no need to handle the notification, Firebase Messaging Package looks into it. Firebase Messaging Package provided by Firebase in Flutter helps one to manage the Foreground.&nbsp;</em></li><li><em><strong>If the app is in the background</strong>: When it comes to background Firebase provides you the feature using Firebase_background_handler on a method called onBackgroundMessage. Using that we can achieve the concept of handling the background message(Basically the message which is received when the app is closed/Minimised).</em></li></ul><h3 id="handling-call-status"><em><strong>Handling Call Status</strong>:</em></h3><ul><li><em>Upon answering or rejecting the call, the recipient's action triggers a server request (update call). This request updates the call status and is communicated back to the caller (Pavan) to reflect the recipient's response.</em></li></ul><p><em>This structured interaction between client, server, and platform-specific components ensures a smooth and intuitive experience for both the caller and the recipient, providing reliable video communication across devices.</em></p><h2 id="core-components-of-the-app"><em>Core Components of the App</em></h2><p><em>The app integrates several core components to manage video calling and notifications seamlessly across iOS platforms:</em></p><h3 id="fluttercallkitincoming"><em>flutter_callkit_incoming</em></h3><ul><li><em><strong>Purpose</strong>: Provides a native call interface on iOS.</em></li><li><em><strong>Function</strong>: Displays the incoming call UI and handles actions like answering or rejecting calls, leveraging iOS’s native CallKit functionality without requiring native Swift code.</em></li></ul><h3 id="push-notifications"><em>Push Notifications</em></h3><ul><li><em><strong>Purpose</strong>: Notifies the recipient about incoming calls.</em></li><li><em><strong>Function</strong>: Uses Firebase Cloud Messaging (FCM)  and Apple Push Notification Service (APNs) for iOS to send VoIP notifications, triggering the appropriate call UI even if the app is in the background or inactive.</em></li></ul><h3 id="firebase-realtime-database"><em>Firebase Realtime Database</em></h3><ul><li><em><strong>Purpose</strong>: Stores user tokens and caller IDs.</em></li><li><em><strong>Function</strong>: Ensures secure and real-time communication between users, facilitating the initiation of calls and status updates.</em></li></ul><h3 id="videosdk"><em>VideoSDK</em></h3><ul><li><em><strong>Purpose</strong>: Powers the video calling functionality.</em></li><li><em><strong>Function</strong>: Enables real-time video and audio communication, providing high-quality video conferencing features for both Android and iOS users.</em></li></ul><h3 id="nodejs-server"><em>Node.js Server</em></h3><ul><li><em><strong>Purpose</strong>: Acts as the backend service for call initiation and status updates.</em></li><li><em><strong>Function</strong>: Sends push notifications via Firebase and APNs, and updates call statuses (e.g., accepted, rejected) between users.</em></li></ul><p><em>These core components work together to ensure a smooth, feature-rich experience for both video calling and real-time notifications across devices and platforms.</em></p><h2 id="prerequisites"><em>Prerequisites</em></h2><p><em>Before starting with the development of the video calling app, ensure that the following prerequisites are met:</em></p><ol><li><em><strong>Flutter Development Environment</strong>:</em><ul><li><em>Install Flutter SDK and set up your development environment. Follow the </em><a href="https://flutter.dev/docs/get-started/install"><em>official Flutter installation guide</em></a><em>.</em></li></ul></li><li><em><strong>Firebase Project</strong>:</em><ul><li><em>Create a Firebase project in the Firebase Console.</em></li><li><em>Set up Firebase Cloud Messaging (FCM) for push notifications.</em></li></ul></li><li><em><strong>VideoSDK Account</strong>:</em><ul><li><em>Sign up for a VideoSDK account at </em><a href="https://www.videosdk.live/"><em>VideoSDK</em></a><em> and obtain the required credentials (API keys and authentication tokens).</em></li></ul></li><li><em><strong>Node.js Server</strong>:</em><ul><li><em>Set up a Node.js server to manage API requests, handle call initiation, and send push notifications. This server will also interact with Firebase to send call-trigger notifications.</em></li></ul></li></ol><p><em>With these prerequisites in place, you'll be ready to begin implementing the video calling functionality, leveraging both Firebase and VideoSDK for a seamless cross-platform experience.</em></p><h2 id="connecting-firebase-to-flutter-using-flutterfire-cli"><em>Connecting Firebase to Flutter Using FlutterFire CLI</em></h2><p/><p><em>To easily set up Firebase with your Flutter app, follow these steps:</em></p><h3 id="step-1-create-a-firebase-project"><em>Step 1: Create a Firebase Project</em></h3><ol><li><em>Go to the </em><a href="https://console.firebase.google.com/" rel="noreferrer"><em>Firebase Console</em></a><em>.</em></li><li><em>Create a new project by following the prompts.</em></li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-10.02.30-AM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="2008" height="1306"/></figure><h3 id="step-2-select-the-flutter-option"><strong><em>Step 2: Select the Flutter Option</em></strong></h3><ul><li><em>Once your project is created, navigate to the "Add app" section.</em></li><li><em>Choose the Flutter option to proceed.</em></li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-5.37.00-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1508" height="910"/></figure><h3 id="step-3-install-firebase-cli"><strong><em>Step 3: Install Firebase CLI</em></strong></h3><ul><li><em>Use npm to globally install the Firebase CLI. Run the following command in your terminal:</em></li></ul><pre><code class="language-js">npm install -g firebase-tools</code></pre><h3 id="step-4-login-to-firebase"><strong><em>Step 4: Login to Firebase</em></strong></h3><ul><li><em>Log in to your Firebase account using the Firebase CLI by running:</em></li></ul><pre><code class="language-js">firebase login</code></pre><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-10.22.19-AM-1.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="2506" height="562"/></figure><ul><li><em>This will open a browser window prompting you to sign in with your Google account.</em></li></ul><h3 id="step-5-configure-firebase-in-flutter-using-flutterfire-cli"><strong><em>Step 5: Configure Firebase in Flutter Using FlutterFire CLI</em></strong></h3><ul><li><em>Use the FlutterFire CLI to connect your Flutter project to Firebase</em></li><li><em>Select an existing Firebase project or create a new one.</em></li><li><em>Choose the platforms (e.g., Android, iOS) you want to integrate Firebase with.</em></li><li><em>This will add new dart file named as firebase_option.dart in your project .</em></li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-10.29.02-AM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="2466" height="556"/></figure><h3 id="step-6-add-dependency-in-pubspecyaml-file"><strong><em>Step 6: Add dependency in pubspec.yaml file</em></strong></h3><ul><li><em>add firebase_core dependency in your pubspec.yaml file to resolve errors </em></li></ul><h2 id="ios-setup-enabling-pushkit-and-callkit"><em>iOS Setup: Enabling PushKit and CallKit</em></h2><p/><p><em>To enable PushKit notifications in your application, it is essential to acquire the necessary certificates from your Apple Developer Program account and set them up for your iOS VoIP application. Follow the steps below:</em></p><h3 id="step-1-request-a-certificate-using-keychain"><em>Step 1: Request a Certificate Using Keychain</em></h3><p/><p><em>1.  Open the <strong>Keychain Access</strong> application on your Mac.</em></p><p><em>2.  Select <code>Certificate Assistant -&gt; Request a Certificate From a Certificate Authority</code>.</em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-5.14.40-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1822" height="804"/></figure><p><em>3.  Enter your email and common name, then click <strong>Continue</strong>.</em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-5.35.50-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1466" height="1066"/></figure><p><em>4. Modify the certificate’s name and save it.</em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-5.44.45-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1528" height="1036"/></figure><h3 id="step-2-create-an-app-id-in-the-apple-developer-account"><em>Step 2: Create an App ID in the Apple Developer Account</em></h3><p><em>This process requires an active Apple Developer Program account. Follow these steps:</em></p><p><em>1. Log into your Apple Developer account.</em></p><p><em>2. Navigate to <strong>Certificates, Identifiers &amp; Profiles</strong> and select <strong>Identifiers</strong>.</em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-5.58.30-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1476" height="1058"/></figure><p><em>3. Click the <strong>+</strong> icon to add a new identifier.</em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-6.19.18-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1464" height="262"/></figure><p><em>4. Add a description, specify your bundle ID, check <strong>PushKit</strong> under Capabilities, and click <strong>Continue</strong>.</em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-6.24.27-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1458" height="502"/></figure><p><em>The image below shows the finished App ID.</em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-6.19.18-PM-1.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1464" height="262"/></figure><h3 id="step-3-create-a-new-voip-services-certificate"><em>Step 3: Create a New VoIP Services Certificate</em></h3><p><br><em>1. Go to the <strong>Certificates</strong> section in your Apple Developer Program account.</em></br></p><p><em>2. Click to add a new certificate.</em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-7.07.51-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1776" height="1112"/></figure><p><em>3. Select the <strong>VoIP Services Certificate</strong> and choose the App ID you created.</em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-7.08.17-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1828" height="762"/></figure><p><em>4. Use the private certificate generated in Keychain Access and click <strong>Continue</strong>.</em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-7.08.38-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1834" height="888"/></figure><p><em>5. Download the <code>voip_services.cer</code> file provided by your VoIP service provider.</em></p><h3 id="step-4-convert-cer-to-p12"><em>Step 4: Convert <code>.cer</code> to <code>.p12</code></em></h3><ol><li><em>Double-click the <code>voip_services.cer</code> file to open it in Keychain Access.</em></li><li><em>Locate the certificate titled "VoIP Services: YourProductName".</em></li><li><em>Right-click on it and select <strong>Export</strong> to save it as a <code>.p12</code> file.</em></li><li><em>Create a strong password when prompted and save the file securely.</em></li></ol><h3 id="step-5-convert-p12-to-pem"><em>Step 5: Convert <code>.p12</code> to <code>.pem</code></em></h3><ol><li><em>Open a terminal and navigate to the directory where the <code>.p12</code> file is saved.</em></li><li><em>Enter the password created earlier.</em></li><li><em>A new file named <code>Certificates.pem</code> will be created in the same directory.</em></li></ol><p><em>Run the following command:</em></p><pre><code class="language-javascript">openssl pkcs12 -in YourFileName.p12 -out Certificates.pem -nodes -clcerts -legacy</code></pre><blockquote><em><strong>Note</strong>: The bundle ID of your VoIP services will influence the exact certificate name. This <code>.pem</code> file is now ready for use in your push notification implementation.</em></blockquote><h2 id="pushkit-setup"><em>PushKit Setup</em></h2><p/><p><em>PushKit will allow us to send notifications to the </em><a href="https://uxpilot.ai/mobile-design-templates/ios" rel="noreferrer"><em>iOS device</em></a><em>. To implement push notifications, you must upload an APN Auth Key. The following details about the app are needed when sending push notifications via an APN Auth Key:</em></p><ul><li><em>Auth Key file</em></li><li><em>Team ID</em></li><li><em>Key ID</em></li><li><em>Your app’s bundle ID</em></li></ul><h3 id="creating-an-apn-auth-key"><em>Creating an APN Auth Key</em></h3><ol><li><em>Visit the Apple&nbsp;</em><a href="https://developer.apple.com/account/"><em>Developer Member Center</em></a></li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-7.10.09-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1644" height="1078"/></figure><ol start="2"><li><em>Click on Certificates, Identifiers &amp; Profiles. Go to Keys from the left side. Create a new Auth Key by clicking on the plus button on the top right side.</em></li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-7.10.40-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1642" height="1084"/></figure><ol start="3"><li><em>On the following page, add a Key Name, and select APNs.</em></li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-7.12.59-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1644" height="1074"/></figure><ol start="4"><li><em>Click on the Register button.</em></li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-7.13.35-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1652" height="1082"/></figure><ol start="5"><li><em>You can download your auth key file from this page and upload this file to the Firebase dashboard without changing its name.</em></li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-7.14.03-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1644" height="1080"/></figure><ol start="6"><li><em>In your Firebase project, go to Settings and select the Cloud Messaging tab. Scroll down the iOS app configuration and click Upload under APNs Authentication Key</em></li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-7.14.51-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1772" height="1048"/></figure><ol start="7"><li><em>Enter&nbsp;<code>Key ID</code>&nbsp;and&nbsp;<code>Team ID</code>. Key ID is in the file name&nbsp;<code>AuthKey\_{Key ID}.p8</code>&nbsp;and is 10 characters. Your Team ID is in the Apple Member Center under the membership tab or displayed always under your account name in the top right corner.</em></li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-7.15.29-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1776" height="1014"/></figure><p><em>8 . Enable Push Notifications in Capabilities</em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-7.16.20-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1776" height="1032"/></figure><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-7.16.36-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1776" height="1032"/></figure><ol start="9"><li><em>Enable selected permission in Background Modes</em></li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-7.17.01-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1780" height="554"/></figure><h2 id="project-structure"><em>Project Structure </em></h2><pre><code class="language-javascript">Client
│
├── ios
│   └── Runner
│       ├── AppDelegate.swift
│       ├── Info.plist
│       └── GoogleService-Info.plist
│
├── lib
│   |
│   ├── meeting
│   |   ├── api_call.dart
│   |   ├── join_screen.dart
│   |   ├── meeting_controls.dart
│   |   ├── meeting_screen.dart
│   |   └── participant_tile.dart
│   |
│   ├── firebase_options.dart
│   ├── home.dart
│   └── main.dart
│
├── .env
├── pubspec.yaml
└── README.md
</code></pre><p/><p><em>Now go to the server side and setup our server </em></p><h3 id="step-1-create-a-new-project-directory"><em>Step 1 : Create a New Project Directory </em></h3><pre><code class="language-javascript">mkdir server
cd server 
npm init -y </code></pre><h3 id="step-2-install-required-dependencies"><em>Step 2 : Install required dependencies</em></h3><pre><code class="language-javascript">npm install express cors morgan firebase-admin uuid</code></pre><h3 id="step-3-set-up-firebase"><em>Step 3 : Set Up Firebase&nbsp;</em></h3><p><em>Enable Realtime Database and set the rule true and Firebase Cloud messaging (FCM). </em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-1.04.24-PM-1.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1602" height="1032"/></figure><h3 id="step-4"><em>Step 4 : </em></h3><p><em>Download the private key by navigating to <strong>Project Settings &gt; Service Accounts</strong>, selecting <strong>Node.js</strong>, and then clicking <strong>Download</strong>.</em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-1.06.54-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1890" height="1218"/></figure><h3 id="step-5"><em>Step 5 : </em></h3><p><em>Place this File into your server side and your server side structure look like this.</em></p><pre><code class="language-javascript">Server
  ├── node_modules/
  ├── server.js
  ├── callkit-3ec73-firebase-adminsdk-ghfto-9d9fc7a362.json
  ├── package-lock.json
  └── package.json</code></pre><h3 id="step-6-now-go-to-serverjs-we-have-to-add-several-api-in-our-serverjs"><em>Step 6 : now go to server.js we have to add several API in our server.js</em></h3><ol><li><em>GET /: Returns a "Hello Coding" message to confirm the server is running.</em></li><li><em>POST /register-device: Registers a device by storing its unique ID and FCM token in Firebase.</em></li><li><em>POST /api/add: Stores call details (callerId, roomId, and calleeId) in memory.</em></li><li><em>GET /api/getByCallee/:calleeId: Retrieves call details for a given callee ID from memory.</em></li><li><em>POST /send-call-status: Sends a notification to the caller about the status of a call (e.g., accepted, rejected, ended).</em></li><li><em>POST /send-notification: Sends a notification to a caller with details about an incoming call, including room ID and VideoSDK token.</em></li></ol><h3 id="step-7-now-we-add-below-code-to-run-the-server-at-your-ip"><em>Step 7 : Now we add below code to run the server at your ip&nbsp;</em></h3><pre><code class="language-javascript">const PORT = process.env.PORT || 9000;&nbsp;
const LOCAL_IP = '10.0.0.161'; // Replace with your actual local IP address&nbsp;
app.listen(PORT, LOCAL_IP, () =&gt; {
console.log(Server running on http://${LOCAL_IP}:${PORT});
&nbsp;});&nbsp;</code></pre><h3 id="step-8"><em>Step 8 : </em></h3><p><em>we setup ngrok and using this below command we redirect our local ip to temporary public URL that can you share outside to your local network ngrok http <u>http://10.0.0.161:9000</u></em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-06-at-10.15.09-AM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1408" height="780"/></figure><p><em>It looks like that we can use this <u>https://8190-115-246-20-252.ngrok-free.app</u> as our server url.</em></p><p><em>Refer the complete code of <strong>server,js</strong> </em><a href="https://github.com/videosdk-live/videosdk-rtc-flutter-call-trigger-example/blob/main/Server/server.js" rel="noreferrer"><em>here</em></a><em>.</em></p><p><em><strong>VideoSDK</strong> is a cutting-edge platform that enables seamless audio and video calling with low latency and robust performance. Start by signing up at </em><a href="https://videosdk.live/" rel="noopener"><strong><em>VideoSDK</em></strong></a><em>, generate your API token from the dashboard, and integrate real-time calling into your app effortlessly!</em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-2.29.43-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="2902" height="1326"/></figure><p><em>Now add this token into your .env file </em></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-06-at-10.31.18-AM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" loading="lazy" width="1058" height="314"/></figure><p><em>Now add all permission for  iOS</em></p><p><br><em>For iOS we have to add all the permission in info.plist file</em></br></p><pre><code class="language-xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
	&lt;key&gt;CADisableMinimumFrameDurationOnPhone&lt;/key&gt;
	&lt;true/&gt;
	&lt;key&gt;CFBundleDevelopmentRegion&lt;/key&gt;
	&lt;string&gt;$(DEVELOPMENT_LANGUAGE)&lt;/string&gt;
	&lt;key&gt;CFBundleExecutable&lt;/key&gt;
	&lt;string&gt;$(EXECUTABLE_NAME)&lt;/string&gt;
	&lt;key&gt;CFBundleIdentifier&lt;/key&gt;
	&lt;string&gt;$(PRODUCT_BUNDLE_IDENTIFIER)&lt;/string&gt;
	&lt;key&gt;CFBundleInfoDictionaryVersion&lt;/key&gt;
	&lt;string&gt;6.0&lt;/string&gt;
	&lt;key&gt;CFBundleName&lt;/key&gt;
	&lt;string&gt;Flutter VideoSDK App&lt;/string&gt;
	&lt;key&gt;CFBundlePackageType&lt;/key&gt;
	&lt;string&gt;APPL&lt;/string&gt;
	&lt;key&gt;CFBundleShortVersionString&lt;/key&gt;
	&lt;string&gt;$(FLUTTER_BUILD_NAME)&lt;/string&gt;
	&lt;key&gt;CFBundleSignature&lt;/key&gt;
	&lt;string&gt;????&lt;/string&gt;
	&lt;key&gt;CFBundleVersion&lt;/key&gt;
	&lt;string&gt;$(FLUTTER_BUILD_NUMBER)&lt;/string&gt;
	&lt;key&gt;LSRequiresIPhoneOS&lt;/key&gt;
	&lt;true/&gt;
	&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
	&lt;string&gt;$(PRODUCT_NAME) Camera Usage!&lt;/string&gt;
	&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
	&lt;string&gt;$(PRODUCT_NAME) Microphone Usage!&lt;/string&gt;
	&lt;key&gt;RTCAppGroupIdentifier&lt;/key&gt;
	&lt;string&gt;group.com.example.broadcastScreen&lt;/string&gt;
	&lt;key&gt;RTCScreenSharingExtension&lt;/key&gt;
	&lt;string&gt;live.videosdk.flutter.example.FlutterBroadcast&lt;/string&gt;
	&lt;key&gt;UIApplicationSupportsIndirectInputEvents&lt;/key&gt;
	&lt;true/&gt;
	&lt;key&gt;UIBackgroundModes&lt;/key&gt;
	&lt;array&gt;
		&lt;string&gt;voip&lt;/string&gt;
		&lt;string&gt;fetch&lt;/string&gt;
		&lt;string&gt;processing&lt;/string&gt;
		&lt;string&gt;remote-notification&lt;/string&gt;
	&lt;/array&gt;
	&lt;key&gt;BGTaskSchedulerPermittedIdentifiers&lt;/key&gt;
	&lt;array&gt;
		&lt;string&gt;dev.flutter.background.refresh&lt;/string&gt;
	&lt;/array&gt;
	&lt;key&gt;UILaunchStoryboardName&lt;/key&gt;
	&lt;string&gt;LaunchScreen&lt;/string&gt;
	&lt;key&gt;UIMainStoryboardFile&lt;/key&gt;
	&lt;string&gt;Main&lt;/string&gt;
	&lt;key&gt;UISupportedInterfaceOrientations&lt;/key&gt;
	&lt;array&gt;
		&lt;string&gt;UIInterfaceOrientationPortrait&lt;/string&gt;
		&lt;string&gt;UIInterfaceOrientationLandscapeLeft&lt;/string&gt;
		&lt;string&gt;UIInterfaceOrientationLandscapeRight&lt;/string&gt;
	&lt;/array&gt;
	&lt;key&gt;UISupportedInterfaceOrientations~ipad&lt;/key&gt;
	&lt;array&gt;
		&lt;string&gt;UIInterfaceOrientationPortrait&lt;/string&gt;
		&lt;string&gt;UIInterfaceOrientationPortraitUpsideDown&lt;/string&gt;
		&lt;string&gt;UIInterfaceOrientationLandscapeLeft&lt;/string&gt;
		&lt;string&gt;UIInterfaceOrientationLandscapeRight&lt;/string&gt;
	&lt;/array&gt;
	&lt;key&gt;UIViewControllerBasedStatusBarAppearance&lt;/key&gt;
	&lt;false/&gt;
	
&lt;/dict&gt;
&lt;/plist&gt;</code></pre><p><em> Along with info.plist file also check the AppDelegate.swift file</em></p><pre><code class="language-javascript">import UIKit
import Flutter

@main
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -&gt; Bool {
    GeneratedPluginRegistrant.register(with: self)
      application.registerForRemoteNotifications()
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}</code></pre><p><em>Okay, let's move forward with integrating the VideoSDK into our project. Please refer to the </em><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer"><em>Quickstart</em></a><em> documentation provided in the link and follow the initial steps to build the necessary steps till step 4 which is creating a paticipant_tile.dart screen.</em></p><p><em>Now, after adding the other files to the Meeting folder, lets create a meeting_screen.dart file through which our meeting will be created, rendered and managed. </em></p><pre><code class="language-javascript">import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import 'package:videosdk_flutter_example/home.dart';

import 'package:videosdk_flutter_example/meeting/meeting_controls.dart';
import './participant_tile.dart';
import 'package:http/http.dart' as http;

class MeetingScreen extends StatefulWidget {
  final String meetingId;
  final String token;
  final String url;
  final String callerId;
  String? source;
  MeetingScreen(
      {Key? key,
      required this.meetingId,
      required this.token,
      required this.callerId,
      required this.url,
      this.source})
      : super(key: key);

  @override
  State&lt;MeetingScreen&gt; createState() =&gt; _MeetingScreenState();
}

class _MeetingScreenState extends State&lt;MeetingScreen&gt; {
  late Room _room;
  var micEnabled = true;
  var camEnabled = true;

  Map&lt;String, Participant&gt; participants = {};

  @override
  void initState() {
    // create room
    if (widget.source == "true") {
      sendnotification(
          widget.url, widget.callerId, "Call Accepted", widget.meetingId);
    }
    _room = VideoSDK.createRoom(
        roomId: widget.meetingId,
        token: widget.token,
        displayName: "John Doe",
        micEnabled: micEnabled,
        camEnabled: camEnabled,
        defaultCameraIndex: kIsWeb
            ? 0
            : 1 // Index of MediaDevices will be used to set default camera
        );

    setMeetingEventListener();

    // Join room
    _room.join();

    super.initState();
  }

  Future&lt;void&gt; sendnotification(String api, callerId, status, roomId) async {
    await sendCallStatus(
        serverUrl: api, callerId: callerId, status: status, roomId: roomId);
  }

  @override
  void setState(fn) {
    if (mounted) {
      super.setState(fn);
    }
  }

  // listening to meeting events
  void setMeetingEventListener() {
    _room.on(Events.roomJoined, () {
      setState(() {
        participants.putIfAbsent(
            _room.localParticipant.id, () =&gt; _room.localParticipant);
      });
    });

    _room.on(
      Events.participantJoined,
      (Participant participant) {
        setState(
          () =&gt; participants.putIfAbsent(participant.id, () =&gt; participant),
        );
      },
    );

    _room.on(Events.participantLeft, (String participantId) {
      if (participants.containsKey(participantId)) {
        setState(
          () =&gt; participants.remove(participantId),
        );
      }
    });

    _room.on(Events.roomLeft, () {
      participants.clear();
      Navigator.pushAndRemoveUntil(
        context,
        MaterialPageRoute(
            builder: (context) =&gt; Home(
                  callerID: widget.callerId,
                )),
        (route) =&gt; false, // Removes all previous routes
      );
    });
  }

  // onbackButton pressed leave the room
  Future&lt;bool&gt; _onWillPop() async {
    _room.leave();
    return true;
  }

  Future&lt;void&gt; sendCallStatus({
    required String serverUrl,
    required String callerId,
    required String status,
    required String roomId,
  }) async {
    final url = Uri.parse('$serverUrl/send-call-status');
   
    try {
      // Request payload
      final body = jsonEncode({
        'callerId': callerId,
        'status': status,
        'roomId': roomId,
      });

      // Sending the POST request
      final response = await http.post(
        url,
        headers: {
          'Content-Type': 'application/json',
        },
        body: body,
      );

      // Handling the response
      if (response.statusCode == 200) {
        print("Notification sent successfully: ${response.body}");
      } else {
        print("Failed to send notification: ${response.statusCode}");
  
      }
    } catch (e) {
      print("Error sending call status: $e");
    }
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    // ignore: deprecated_member_use
    return WillPopScope(
      onWillPop: () =&gt; _onWillPop(),
      child: Scaffold(
        appBar: AppBar(
          title: const Text('VideoSDK QuickStart'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              Text(widget.meetingId),
              //render all participant
              Expanded(
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: GridView.builder(
                    gridDelegate:
                        const SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                      crossAxisSpacing: 10,
                      mainAxisSpacing: 10,
                      mainAxisExtent: 300,
                    ),
                    itemBuilder: (context, index) {
                      return ParticipantTile(
                          key: Key(participants.values.elementAt(index).id),
                          participant: participants.values.elementAt(index));
                    },
                    itemCount: participants.length,
                  ),
                ),
              ),
              MeetingControls(
                micEnabled: micEnabled,
                camEnabled: camEnabled,
                onToggleMicButtonPressed: () {
                  setState(() {
                    micEnabled = !micEnabled;
                  });
                  micEnabled ? _room.unmuteMic() : _room.muteMic();
                },
                onToggleCameraButtonPressed: () {
                  setState(() {
                    camEnabled = !camEnabled;
                  });
                  camEnabled ? _room.enableCam() : _room.disableCam();
                },
                onLeaveButtonPressed: () {
                  _room.leave();
                },
              ),
            ],
          ),
        ),
      ),
      //home: JoinScreen(),
    );
  }
}
</code></pre><p><em>Great, we have successfully added our videosdk meeting screens. Lets deep dive into main.dart file and home.dart file.    <br><br>main.dart</br></br></em></p><pre><code class="language-javascript">import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:videosdk_flutter_example/home.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await dotenv.load(fileName: ".env");
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Home(),
    );
  }
}
</code></pre><p><em>After creating the main.dart file, now its time to create a <strong>home.dart</strong> file. In home.dart file we will be working on managing the notification and also the call triggering logic is present in this file. </em></p><pre><code class="language-javascript">Future&lt;void&gt; sendNotification({
    required String callerId,
    required String callerInfo,
    required String roomId,
    required String token,
  }) async {
    // Prepare the request payload

    final Map&lt;String, dynamic&gt; payload = {
      'callerId': callerId,
      'callerInfo': {'id': callerInfo},
      'videoSDKInfo': {'roomId': roomId, 'token': token},
    };

    try {
      // Send POST request to the API
      final response = await http.post(
        Uri.parse("${apiUrl!}/send-notification"),
        headers: {'Content-Type': 'application/json'},
        body: jsonEncode(payload),
      );

      // Handle the response from the API
      if (response.statusCode == 200) {
        print('Notification sent successfully');
        if (mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text("Message sent successfully")),
          );
        }
        print(response.body);
      } else {
        print('Failed to send notification: ${response.body}');
      }
    } catch (e) {
      print('Error occurred while sending notification: $e');
    }
  }


Future&lt;void&gt; makeFakeCallInComing(String callerId) async {

  {
    _currentUuid = const Uuid().v4();

    final params = CallKitParams(
      id: _currentUuid,
      appName: 'VideoSdk',
      avatar: 'https://i.pravatar.cc/100',
      handle: "VideoSdk",
      type: 0,
      duration: 30000,
      textAccept: 'Accept',
      textDecline: 'Decline',
      missedCallNotification: const NotificationParams(
        showNotification: true,
        isShowCallback: true,
        subtitle: 'Missed call',
        callbackText: 'Call back',
      ),
      extra: &lt;String, dynamic&gt;{'userId': '1a2b3c4d'},
      headers: &lt;String, dynamic&gt;{'apiKey': 'Abc@123!', 'platform': 'flutter'},
      ios: const IOSParams(
        iconName: 'CallKitLogo',
        handleType: '',
        supportsVideo: true,
        maximumCallGroups: 2,
        maximumCallsPerCallGroup: 1,
        audioSessionMode: 'default',
        audioSessionActive: true,
        audioSessionPreferredSampleRate: 44100.0,
        audioSessionPreferredIOBufferDuration: 0.005,
        supportsDTMF: true,
        supportsHolding: true,
        supportsGrouping: false,
        supportsUngrouping: false,
        ringtonePath: 'system_ringtone_default',
      ),
    );
    await FlutterCallkitIncoming.showCallkitIncoming(params);
    Future.delayed(const Duration(seconds: 10), () async {
      await FlutterCallkitIncoming.endAllCalls();
      // _initializePhoneAccount();
    });
  }
}</code></pre><p><em>To get entire code for home.dart file you can refer </em><a href="https://github.com/videosdk-live/videosdk-rtc-flutter-call-trigger-example/blob/main/Client/lib/home.dart" rel="noreferrer"><em>here</em></a><em>.</em></p><p><em>Note: The above code is only applicable when app is in Foreground state or when app is open in Background, yet working on the case where app is totally terminated</em></p><hr><blockquote><em>App Reference</em></blockquote>
<!--kg-card-begin: html-->
<table>
  <tr>
    <td><img src="https://cdn.videosdk.live/website-resources/docs-resources/flutter-call-kit/calling-screen-flutter-ios.png" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" width="200" height="100"/></td>
    <td><img src="https://cdn.videosdk.live/website-resources/docs-resources/flutter-call-kit/home-screen-flutter-ios.png" alt="Build a Video Calling App with Call Trigger in Flutter - iOS using Firebase and VideoSDK" width="200" height="100"/></td>
  </tr>
</table>
<!--kg-card-end: html-->

<!--kg-card-begin: html-->
<video width="900" height="500" controls="">
  <source src="https://cdn.videosdk.live/website-resources/docs-resources/flutter_ios_callkit.mp4" type="video/mp4">
</source></video>
<!--kg-card-end: html-->
<h2 id="conclusion"><em>Conclusion</em></h2><p><em>With this, we've successfully built the  Flutter iOS video calling app using the  Flutter_callkit_incoming package, VideoSDK, and Firebase, Node js. For additional features like chat messaging and screen sharing, feel free to refer to our </em><a href="https://docs.videosdk.live" rel="noreferrer"><em>documentation</em></a><em>. If you encounter any issues with the implementation, don’t hesitate to reach out to us through our </em><a href="https://discord.gg/Gpmj6eCq5u" rel="noreferrer"><em>Discord community</em></a><em>.</em></p></hr>]]></content:encoded></item><item><title><![CDATA[Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK]]></title><description><![CDATA[Create a cross-platform video calling app for Android with native call triggers using Flutter, Node.js, Firebase, VideoSDK, and Telecom Framework.]]></description><link>https://www.videosdk.live/blog/flutter-android-calltrigger</link><guid isPermaLink="false">6777c913dbc171042ac7075a</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 21 Jul 2025 06:39:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/05/call-trigger_android_flutter.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2025/05/call-trigger_android_flutter.png" alt="Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK"/><p/><p>In today’s connected world, building a seamless video calling experience is more important than ever. If you're looking to create a cross-platform video calling app with native call-trigger functionality—just like a regular phone call—you’re in the right place.</p><p>In this tutorial, we’ll walk through building a powerful video calling app using:</p><ul><li><strong>Flutter</strong> for the cross-platform UI</li><li><strong>Node.js</strong> for handling server-side token generation</li><li><strong>Firebase</strong> for real-time user status and call event synchronization</li><li><strong>VideoSDK</strong> for high-quality, low-latency audio and video communication</li><li><strong>Android’s Telecom Framework</strong> to provide native call UI and call management behavior</li></ul><p>By the end, you’ll have a production-ready video calling experience complete with incoming/outgoing call screens, call controls, and real-time updates. Be sure to <a href="https://github.com/videosdk-live/videosdk-rtc-flutter-call-trigger-example" rel="noreferrer">check out the sample code</a> and demo video to see the final result in action.<br/></p><figure class="kg-card kg-embed-card"><iframe width="200" height="113" src="https://www.youtube.com/embed/YEtYwzdsw1k?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" title="I Built a Flutter CallKit Integration with VideoSDK (Step-by-Step)"/></figure><h2 id="introduction-to-telecom-framework">Introduction to Telecom Framework</h2><p>The Telecom framework in Android facilitates seamless management of audio and video calls, supporting both traditional SIM-based calls and VoIP functionality. It acts as the backbone for handling call connections and user interactions during calls.</p><h3 id="key-components">Key Components:</h3><ul><li><strong>ConnectionService</strong>: Manages call connections, tracks their states, and ensures proper routing of audio and video streams.</li><li><strong>InCallService</strong>: Provides the interface for call interactions, enabling users to view, answer, and manage ongoing calls.</li></ul><p>A thorough understanding of these components ensures a smoother development process when integrating call functionality into Android applications.</p><h2 id="overview-of-the-application-for-android">Overview of the Application for Android</h2><p>The application facilitates seamless video calling by leveraging a well-coordinated workflow between Flutter, Node.js, Firebase, and platform-specific features. Here’s an overview of the call process:</p><h3 id="initiating-a-call">Initiating a Call</h3><ol><li>The caller (e.g., Pavan) enters the recipient's unique ID (e.g., Jay) and presses the call button.</li><li>This action triggers a server request to initiate the call, which sends a Firebase Cloud Messaging (FCM) notification to the recipient's device through an API.</li></ol><h3 id="receiving-the-call">Receiving the Call</h3><ul><li><strong>If the app is in the foreground</strong>: The notification is handled on the Flutter side, where a method channel is used to invoke Kotlin code for the Android <code>TelecomManager</code>. This displays the call interface.</li><li><strong>If the app is in the background</strong>: The notification is processed by the <code>FirebaseMessagingService</code> in Kotlin. It then uses <code>TelecomManager</code> to display the call interface.</li></ul><h3 id="handling-call-status">Handling Call Status</h3><p>Upon answering or rejecting the call, the recipient's action triggers a server request to update the call status. This update is communicated back to the caller (Pavan) to reflect the recipient's response.</p><h2 id="core-components-of-the-app">Core Components of the App</h2><p>The app integrates several core components to manage video calling and notifications seamlessly across Android platform:</p><h3 id="telecom-framework">Telecom Framework</h3><ul><li><strong>Purpose</strong>: Manages incoming and outgoing calls with native system integration.</li><li><strong>Function</strong>: Handles call connection states, audio/video routing, and user interactions through the Android <code>TelecomManager</code>.</li></ul><h3 id="push-notifications">Push Notifications</h3><ul><li><strong>Purpose</strong>: Notifies the recipient about incoming calls.</li><li><strong>Function</strong>: Uses Firebase Cloud Messaging (FCM), for triggering the appropriate call UI even if the app is in the background or inactive.</li></ul><h3 id="firebase-realtime-database">Firebase Realtime Database</h3><ul><li><strong>Purpose</strong>: Stores user tokens and caller IDs.</li><li><strong>Function</strong>: Ensures secure and real-time communication between users, facilitating the initiation of calls and status updates.</li></ul><h3 id="videosdk">VideoSDK</h3><ul><li><strong>Purpose</strong>: Powers the video calling functionality.</li><li><strong>Function</strong>: Enables real-time video and audio communication, providing high-quality video conferencing features for both Android and iOS users.</li></ul><h3 id="nodejs-server">Node.js Server</h3><ul><li><strong>Purpose</strong>: Acts as the backend service for call initiation and status updates.</li><li><strong>Function</strong>: Sends push notifications via Firebase and APNs, and updates call statuses (e.g., accepted, rejected) between users.</li></ul><p>These core components work together to ensure a smooth, feature-rich experience for both video calling and real-time notifications across devices and platforms.</p><h2 id="prerequisites">Prerequisites</h2><p>Before starting with the development of the video calling app, ensure that the following prerequisites are met:</p><ol><li><strong>Flutter Development Environment</strong>:<ul><li>Install Flutter SDK and set up your development environment. Follow the <a href="https://flutter.dev/docs/get-started/install">official Flutter installation guide</a>.</li></ul></li><li><strong>Firebase Project</strong>:<ul><li>Create a Firebase project in the Firebase Console.</li><li>Set up Firebase Cloud Messaging (FCM) for push notifications.</li></ul></li><li><strong>VideoSDK Account</strong>:<ul><li>Sign up for a VideoSDK account at <a href="https://www.videosdk.live/">VideoSDK</a> and obtain the required credentials (API keys and authentication tokens).</li></ul></li><li><strong>Node.js Server</strong>:<ul><li>Set up a Node.js server to manage API requests, handle call initiation, and send push notifications. This server will also interact with Firebase to send call-trigger notifications.</li></ul></li></ol><p>With these prerequisites in place, you'll be ready to begin implementing the video calling functionality, leveraging both Firebase and VideoSDK for a seamless cross-platform experience.</p><h2 id="connecting-firebase-to-flutter-using-flutterfire-cli">Connecting Firebase to Flutter Using FlutterFire CLI</h2><p/><p>To easily set up Firebase with your Flutter app, follow these steps:</p><h3 id="step-1-create-a-firebase-project">Step 1: Create a Firebase Project</h3><ol><li>Go to the <a href="https://console.firebase.google.com/" rel="noreferrer">Firebase Console</a>.</li><li>Create a new project by following the prompts.</li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-10.02.30-AM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK" loading="lazy" width="2008" height="1306"/></figure><h3 id="step-2-select-the-flutter-option"><strong>Step 2: Select the Flutter Option</strong></h3><ul><li>Once your project is created, navigate to the "Add app" section.</li><li>Choose the Flutter option to proceed.</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-5.37.00-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK" loading="lazy" width="1508" height="910"/></figure><h3 id="step-3-install-firebase-cli"><strong>Step 3: Install Firebase CLI</strong></h3><ul><li>Use npm to globally install the Firebase CLI. Run the following command in your terminal:</li></ul><pre><code class="language-javascript">npm install -g firebase-tools</code></pre><h3 id="step-4-login-to-firebase"><strong>Step 4: Login to Firebase</strong></h3><ul><li>Log in to your Firebase account using the Firebase CLI by running:</li></ul><pre><code class="language-javascript">firebase login</code></pre><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-10.22.19-AM-1.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK" loading="lazy" width="2506" height="562"/></figure><ul><li>This will open a browser window prompting you to sign in with your Google account.</li></ul><h3 id="step-5-configure-firebase-in-flutter-using-flutterfire-cli"><strong>Step 5: Configure Firebase in Flutter Using FlutterFire CLI</strong></h3><ul><li>Use the FlutterFire CLI to connect your Flutter project to Firebase</li><li>Select an existing Firebase project or create a new one.</li><li>Choose the platforms (e.g., Android, iOS) you want to integrate Firebase with.</li><li>This will add new dart file named as firebase_option.dart in your project .</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-10.29.02-AM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK" loading="lazy" width="2466" height="556"/></figure><h3 id="step-6-add-dependency-in-pubspecyaml-file"><strong>Step 6: Add dependency in pubspec.yaml file</strong></h3><ul><li>add firebase_core dependency in your pubspec.yaml file.</li></ul><hr><h2 id="project-structure">Project Structure </h2><pre><code class="language-javascript">Client
│
├── android
│   └── app
│       └── src
│           ├── main
|               ├── java
│               ├── kotlin/com/example/example
│               |   ├── CallConnectionService.kt
│               |   ├── MainActivity.kt
│               |   └── MyFirebaseMessagingService.kt
│               └── res
├── lib
│   |
│   ├── meeting
│   |   ├── api_call.dart
│   |   ├── join_screen.dart
│   |   ├── meeting_controls.dart
│   |   ├── meeting_screen.dart
│   |   └── participant_tile.dart
│   |
│   ├── firebase_options.dart
│   ├── home.dart
│   └── main.dart
│
├── .env
├── pubspec.yaml
└── README.md
</code></pre><h2 id="now-start-with-android-code-mainactivitykt">Now start with android code <br><br>MainActivity.kt</br></br></h2><p>Established the bridge using MethodChannel for communication between Flutter and native side code .we use Android Telecom API to handle native calls . we register phoneAccount , manage incoming calls and open phone account settings when it requires .&nbsp; we also initialise the callconnetionservice.kt class and firebase also from this file .</p><pre><code class="language-kotlin">package com.example.example

import android.content.ComponentName
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.telecom.PhoneAccount
import android.telecom.PhoneAccountHandle
import android.telecom.TelecomManager
import android.util.Log
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import java.lang.Exception
import com.google.firebase.FirebaseApp

class MainActivity : FlutterActivity() {
    private val CHANNEL = "com.example.example/calls"
    private var telecomManager: TelecomManager? = null
    private var phoneAccountHandle: PhoneAccountHandle? = null
    private var methodChannel: MethodChannel? = null

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        FirebaseApp.initializeApp(this)
        Log.d("MainActivity", "Firebase Initialized")
        telecomManager = getSystemService(TELECOM_SERVICE) as TelecomManager
        val componentName = ComponentName(this, CallConnectionService::class.java)
        phoneAccountHandle = PhoneAccountHandle(componentName, "DhirajAccountId")
        methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
         Log.d("MainActivity", "Above the call connection Service!!!")
        CallConnectionService.setFlutterEngine(flutterEngine)
        MyFirebaseMessagingService.setFlutterEngine(flutterEngine)
        Log.d("MainActivity", "Below the call connection Service!!!")
        methodChannel?.setMethodCallHandler { call, result -&gt;
            when (call.method) {
                "registerPhoneAccount" -&gt; {
                    try {
                        registerPhoneAccount()
                        result.success("Phone account registered successfully")
                    } catch (e: Exception) {
                        result.error("ERROR", "Failed to register phone account", e.message)
                    }
                }
                "handleIncomingCall" -&gt; {
                    val callerId = call.argument&lt;String&gt;("callerId")
                    handleIncomingCall(callerId)
                    result.success("Incoming call handled successfully")
                }
                "openPhoneAccountSettings" -&gt; 
                {
                    openPhoneAccountSettings()
                    result.success("Incoming call phone account");
                }
                else -&gt; {
                    result.notImplemented()
                }
            }
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        Log.d("MainActivity", "Initializing Firebase")
       
        super.onCreate(savedInstanceState)
    }
    
    override fun onPause() {
        super.onPause()
        Log.d("MainActivity", "App is paused. Performing necessary tasks.")
        // Perform any cleanup or save operations
    }

    override fun onResume() {
        super.onResume()
        Log.d("MainActivity", "App is resumed. Restoring state or resources.")
        // Restore any states or resources
    }

    override fun onStop() {
        super.onStop()
        Log.d("MainActivity", "App is stopped. Releasing resources.")
        
        // Check for incoming call and handle it
        val callerId = intent.getStringExtra("callerId") // Correct key
        Log.d("MainActivity", "Incoming call from: $callerId")
        if (callerId != null) {
            handleIncomingCall(callerId)
        }
    }

    override fun onStart() {
        super.onStart()
        Log.d("MainActivity", "App is started. Preparing resources.")
        // Initialize or prepare resources
    }

    // Register the phone account with the telecom manager
    private fun registerPhoneAccount() {
        val phoneAccount = PhoneAccount.builder(phoneAccountHandle, "VideoSdk")
            .setCapabilities(PhoneAccount.CAPABILITY_CALL_PROVIDER)
            .build()
        telecomManager?.registerPhoneAccount(phoneAccount)
    }

    // Check if the phone account is registered
    private fun isPhoneAccountRegistered(): Boolean {
        val phoneAccounts = telecomManager?.callCapablePhoneAccounts ?: return false
        return phoneAccounts.contains(phoneAccountHandle)
    }

    // Handle the incoming call or open settings if the account is not registered
    private fun handleIncomingCall(callerId: String?) {
        if (!isPhoneAccountRegistered()) {
            // Open phone account settings if not registered
            openPhoneAccountSettings()
            return
        }
        val extras = Bundle().apply {
            val uri = Uri.fromParts("tel", callerId, null)
            putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, uri)
        }
        try {
            telecomManager?.addNewIncomingCall(phoneAccountHandle, extras)
        } catch (cause: Throwable) {
            Log.e("handleIncomingCall", "Error in addNewIncomingCall", cause)
        }
    }

    // Simulate an incoming call (e.g., during app stop)
    private fun simulateIncomingCall() {
        Log.d("MainActivity", "Simulating an incoming call in onStop.")

        // Simulate a caller ID for testing
        val testCallerId = "1234567890"
        handleIncomingCall(testCallerId)
    }

    // Open phone account settings
    private fun openPhoneAccountSettings() {
        try {
            val intent = Intent(TelecomManager.ACTION_CHANGE_PHONE_ACCOUNTS)
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            startActivity(intent)
        } catch (e: Exception) {
            Log.e("openPhoneAccountSettings", "Unable to open settings", e)
        }
    }
}
</code></pre><h2 id="callconnectionservicekt">CallConnectionService.kt</h2><p>CallConnectionService acts as the bridge between the Android Telecom framework and the flutter app, managing incoming call events. It creates a Connection object to handle call lifecycle actions like answering or rejecting calls , also seamlessly communicating these events back to Flutter via a method channel .</p><pre><code class="language-kotlin">
package com.example.example
import io.flutter.plugin.common.MethodChannel
import android.content.Intent
import android.net.Uri
import android.telecom.Connection
import android.telecom.ConnectionRequest
import android.telecom.ConnectionService
import android.telecom.TelecomManager
import android.util.Log
import io.flutter.embedding.engine.FlutterEngine
class CallConnectionService : ConnectionService() {
companion object {
        private const val CHANNEL = "com.example.example/calls"
        private var methodChannel: MethodChannel? = null
        fun setFlutterEngine(flutterEngine: FlutterEngine) {
            methodChannel = MethodChannel(flutterEngine.dartExecutor, CHANNEL)
        }
    }
    override fun onCreateIncomingConnection(
        connectionManagerPhoneAccount: android.telecom.PhoneAccountHandle?,
        request: ConnectionRequest?
    ): Connection {
        val connection = object : Connection() {
            override fun onAnswer() {
                super.onAnswer()

                val extras = request?.extras
                val roomId = extras?.getString("roomId")
                val callerId = extras?.getString("callerId")

                Log.d("CallConnectionService", "Call Answered")
                Log.d("Room ID:", roomId ?: "null")
                Log.d("Caller ID:", callerId ?: "null")

                // Generate deep link for the meeting screen
                val deepLink = "exampleapp://open/meeting?roomId=$roomId&amp;callerId=$callerId" //creating the deeplink

                val intent = Intent(Intent.ACTION_VIEW).apply {
                    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
                    data = Uri.parse(deepLink)
                }
                startActivity(intent) //again triggering the intent for the //connection with Fluter.
                destroy()
            }

            override fun onReject() {
                super.onReject()

                val extras = request?.extras
                val callerId = extras?.getString("callerId")


                // Generate deep link for the home screen
                val deepLink = "exampleapp://open/home?callerId=$callerId" //same fir the reject call

                val intent = Intent(Intent.ACTION_VIEW).apply {
                    addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
                    data = Uri.parse(deepLink)
                }
                startActivity(intent) //again triggering the intent for the connection with Fluter.
                destroy()
            }
        }
        connection.setAddress(request?.address, TelecomManager.PRESENTATION_ALLOWED)
        connection.setCallerDisplayName("Incoming Call", TelecomManager.PRESENTATION_ALLOWED)
        connection.setInitializing()
        connection.setActive()
        return connection
    }
}
</code></pre><h2 id="myfirebasemessagingservicekt">MyFirebaseMessagingService.kt</h2><p>The MyFirebaseMessagingService handle incoming firebase notification only for background like when the app is in background , and also make call from here </p><pre><code class="language-kotlin">package com.example.example
import android.app.ActivityManager
import android.content.ComponentName
import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.telecom.PhoneAccountHandle
import android.telecom.TelecomManager
import android.util.Log
import androidx.core.app.ActivityCompat
import com.google.firebase.messaging.FirebaseMessagingService
import com.google.firebase.messaging.RemoteMessage
import android.content.pm.PackageManager
import android.Manifest
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import android.os.Handler
import android.os.Looper
class MyFirebaseMessagingService : FirebaseMessagingService() {
    companion object {
        private const val CHANNEL_ID = "call_notifications_channel"
        private const val TAG = "MyFirebaseMessagingService"
        private const val FLUTTER_CHANNEL = "ack"
        var methodChannel: MethodChannel? = null
        fun setFlutterEngine(flutterEngine: FlutterEngine) {
            methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, FLUTTER_CHANNEL)
        }
    }
    private var telecomManager: TelecomManager? = null
    private var phoneAccountHandle: PhoneAccountHandle? = null
    override fun onMessageReceived(remoteMessage: RemoteMessage) {
      
  
        val data = remoteMessage.data
        Log.d(TAG, "Received notification data: $data")
        if (data.isNotEmpty()) {
            val callerId = data["callerInfo"]
            val roomId = data["roomId"]
            val type = data["type"]
            if (callerId != null &amp;&amp; roomId != null &amp;&amp; type == null) {
           
                handleIncomingCall(callerId, roomId)
                // Send data to Flutter on the main thread
                Handler(Looper.getMainLooper()).post {
                    sendToFlutter(callerId, roomId)
                }
            }
        }
    }
    private fun sendToFlutter(callerId: String, roomId: String) {
        if (methodChannel != null) {
            // Ensure this runs on the main thread
            Handler(Looper.getMainLooper()).post {
                methodChannel?.invokeMethod("onIncomingCall", mapOf("callerId" to callerId, "roomId" to roomId))
                
            }
        } else {
            Log.e(TAG, "MethodChannel is not initialized.")
        }
    }
    private fun handleIncomingCall(callerId: String, roomId: String) {
        initializeTelecomManager() // Ensure telecomManager and phoneAccountHandle are initialized
        if (!isPhoneAccountRegistered()) {
            Log.w(TAG, "Phone account not registered. Cannot handle incoming call.")
            return
        }
        if (!hasReadPhoneStatePermission()) {
            Log.e(TAG, "READ_PHONE_STATE permission not granted.")
            return
        }
        val extras = Bundle().apply {
            val uri = Uri.fromParts("tel", callerId, null)
            putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, uri)
            putString("roomId",roomId)
            putString("callerId",callerId)
        }
        try {
            telecomManager?.addNewIncomingCall(phoneAccountHandle, extras)
            Log.d(TAG, "Incoming call handled successfully for Caller ID: $callerId")
        } catch (cause: Throwable) {
            Log.e(TAG, "Error handling incoming call", cause)
        }
    }
    private fun initializeTelecomManager() {
        if (telecomManager == null || phoneAccountHandle == null) {
            telecomManager = getSystemService(Context.TELECOM_SERVICE) as TelecomManager
            val componentName = ComponentName(this, CallConnectionService::class.java)
            phoneAccountHandle = PhoneAccountHandle(componentName, "DhirajAccountId")
            Log.d(TAG, "TelecomManager and PhoneAccountHandle initialized.")
        }
    }
    private fun isPhoneAccountRegistered(): Boolean {
        val phoneAccounts = telecomManager?.callCapablePhoneAccounts ?: return false
        return phoneAccounts.contains(phoneAccountHandle)
    }
    private fun hasReadPhoneStatePermission(): Boolean {
        return ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED
    }
    private fun isAppInBackground(): Boolean {
        val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
        val runningAppProcesses = activityManager.runningAppProcesses ?: return true
        for (processInfo in runningAppProcesses) {
            if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
                &amp;&amp; processInfo.processName == packageName
            ) {
                return false // App is in foreground
            }
        }
        return true // App is in background
    }
}

</code></pre><p>Now go to the server side and setup our server </p><h3 id="step-1-create-a-new-project-directory">Step 1 : Create a new project Directory </h3><pre><code class="language-javascript">mkdir server
cd server 
npm init -y </code></pre><h3 id="step-2-install-required-dependencies">Step 2 : Install required dependencies</h3><pre><code class="language-javascript">npm install express cors morgan firebase-admin uuid</code></pre><h3 id="step-3-set-up-firebase">Step 3 : Set Up Firebase&nbsp;</h3><p>Enable Realtime Database and set the rule true and Firebase Cloud messaging (FCM). </p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-1.04.24-PM-1.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK" loading="lazy" width="1602" height="1032"/></figure><h3 id="step-4">Step 4 : </h3><p>Download the private key by navigating to <strong>Project Settings &gt; Service Accounts</strong>, selecting <strong>Node.js</strong>, and then clicking <strong>Download</strong>.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-1.06.54-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK" loading="lazy" width="1890" height="1218"/></figure><h3 id="step-5">Step 5 : </h3><p>Place this File into your server side and your server side structure look like this.</p><pre><code class="language-javascript">Server
  ├── node_modules/
  ├── server.js
  ├── callkit-3ec73-firebase-adminsdk-ghfto-9d9fc7a362.json
  ├── package-lock.json
  └── package.json</code></pre><h3 id="step-6-now-go-to-serverjs-we-have-to-add-several-api-in-our-serverjs">Step 6 : now go to server.js we have to add several API in our server.js</h3><ol><li>GET /: Returns a "Hello Coding" message to confirm the server is running.</li><li>POST /register-device: Registers a device by storing its unique ID and FCM token in Firebase.</li><li>POST /api/add: Stores call details (callerId, roomId, and calleeId) in memory.</li><li>GET /api/getByCallee/:calleeId: Retrieves call details for a given callee ID from memory.</li><li>POST /send-call-status: Sends a notification to the caller about the status of a call (e.g., accepted, rejected, ended).</li><li>POST /send-notification: Sends a notification to a caller with details about an incoming call, including room ID and VideoSDK token.</li></ol><h3 id="step-7-now-we-add-below-code-to-run-the-server-at-your-ip">Step 7 : Now we add below code to run the server at your ip&nbsp;</h3><pre><code class="language-javascript">const PORT = process.env.PORT || 9000;&nbsp;
const LOCAL_IP = '10.0.0.161'; // Replace with your actual local IP address&nbsp;
app.listen(PORT, LOCAL_IP, () =&gt; {
console.log(Server running on http://${LOCAL_IP}:${PORT});
&nbsp;});&nbsp;</code></pre><h3 id="step-8">Step 8 : </h3><p>we setup ngrok and using this below command we redirect our local ip to temporary public URL that can share outside to your local network ngrok http <u>http://10.0.0.161:9000</u></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-06-at-10.15.09-AM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK" loading="lazy" width="1408" height="780"/></figure><p>It looks like that we can use this <u>https://8190-115-246-20-252.ngrok-free.app</u> as our server url.</p><p> Refer the complete code of <strong>server,js</strong> <a href="https://github.com/videosdk-live/videosdk-rtc-flutter-call-trigger-example/blob/main/Server/server.js" rel="noreferrer">here</a>.</p><p><strong>VideoSDK</strong> is a cutting-edge platform that enables seamless audio and video calling with low latency and robust performance. Start by signing up at <a href="https://videosdk.live/" rel="noopener"><strong>VideoSDK</strong></a>, generate your API token from the dashboard, and integrate real-time calling into your app effortlessly!</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-03-at-2.29.43-PM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK" loading="lazy" width="2902" height="1326"/></figure><p>Now add this token into your .env file </p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Screenshot-2025-01-06-at-10.31.18-AM.png" class="kg-image" alt="Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK" loading="lazy" width="1058" height="314"/></figure><p>Now add all permission for android. In android , we need permission of camera , audio, internet ,wake lock ,call log , post notification and more here is full file of AndroidManifest.xml .</p><pre><code class="language-xml">&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.example"&gt;

    &lt;!-- Hardware features --&gt;
    &lt;uses-feature android:name="android.hardware.camera" /&gt;
    &lt;uses-feature android:name="android.hardware.camera.autofocus" /&gt;

    &lt;!-- Permissions --&gt;
    &lt;uses-permission android:name="android.permission.CAMERA" /&gt;
    &lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
    &lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
    &lt;uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /&gt;
    &lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /&gt;
    &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
    &lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;
    &lt;uses-permission android:name="android.permission.FOREGROUND_SERVICE" /&gt;
    &lt;uses-permission android:name="android.permission.CALL_PHONE" /&gt;
    &lt;uses-permission android:name="android.permission.MANAGE_OWN_CALLS" /&gt;
    &lt;uses-permission android:name="android.permission.READ_PHONE_STATE" /&gt;
    &lt;uses-permission android:name="android.permission.MODIFY_PHONE_STATE" /&gt;
    &lt;uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /&gt;
    &lt;uses-permission android:name="android.permission.READ_CALL_LOG" /&gt;
    &lt;uses-permission android:name="android.permission.WRITE_CALL_LOG" /&gt;
    &lt;uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" /&gt;
    &lt;uses-permission android:name="android.permission.POST_NOTIFICATIONS" /&gt;
    &lt;uses-permission
        android:name="android.permission.BLUETOOTH"
        android:maxSdkVersion="30" /&gt;
    &lt;uses-permission
        android:name="android.permission.BLUETOOTH_ADMIN"
        android:maxSdkVersion="30" /&gt;
    &lt;uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /&gt;

    &lt;application
        android:label="Flutter Telecom App"
        android:icon="@mipmap/ic_launcher"
        android:enableOnBackInvokedCallback="true"&gt;

        &lt;!-- Main Activity --&gt;
        &lt;activity
            android:name=".MainActivity"
            android:launchMode="singleTask"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize"
            android:exported="true"&gt;
            &lt;!-- Specifies an Android theme to apply to this Activity --&gt;
            &lt;meta-data
                android:name="io.flutter.embedding.android.NormalTheme"
                android:resource="@style/NormalTheme" /&gt;
            &lt;!-- Launch screen configuration --&gt;
            &lt;meta-data
                android:name="io.flutter.embedding.android.SplashScreenDrawable"
                android:resource="@drawable/launch_background" /&gt;
            &lt;intent-filter&gt;
                &lt;action android:name="android.intent.action.MAIN" /&gt;
                &lt;category android:name="android.intent.category.LAUNCHER" /&gt;
            &lt;/intent-filter&gt;
              &lt;intent-filter&gt;
                &lt;action android:name="android.intent.action.VIEW" /&gt;
                &lt;category android:name="android.intent.category.DEFAULT" /&gt;
                &lt;category android:name="android.intent.category.BROWSABLE" /&gt;
                &lt;data android:scheme="exampleapp" android:host="open" /&gt;
            &lt;/intent-filter&gt;
        &lt;/activity&gt;

        &lt;!-- Telecom Connection Service --&gt;
        &lt;service
            android:name=".CallConnectionService"
            android:permission="android.permission.BIND_TELECOM_CONNECTION_SERVICE"
            android:exported="true"&gt;
            &lt;intent-filter&gt;
                &lt;action android:name="android.telecom.ConnectionService" /&gt;
            &lt;/intent-filter&gt;
        &lt;/service&gt;
        
&lt;service
    android:name=".MyFirebaseMessagingService"
    android:permission="com.google.android.c2dm.permission.RECEIVE"
    android:exported="true"&gt;
    &lt;intent-filter&gt;
        &lt;action android:name="com.google.firebase.MESSAGING_EVENT" /&gt;
    &lt;/intent-filter&gt;
&lt;/service&gt;

        &lt;!-- Telecom Management Service --&gt;
        &lt;service
            android:name=".MyTelecomService"
            android:exported="true" /&gt;

        &lt;!-- FlutterActivity declaration --&gt;
        &lt;activity
            android:name="io.flutter.embedding.android.FlutterActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:label="Flutter"
            android:theme="@style/LaunchTheme"
            android:exported="true" /&gt;

        &lt;!-- Main Application Metadata --&gt;
        &lt;meta-data android:name="flutterEmbedding" android:value="2" /&gt;

    &lt;/application&gt;
&lt;/manifest&gt;
</code></pre><p>Okay, let's move forward with integrating the VideoSDK into our project. Please refer to the <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">Quickstart</a> documentation provided in the link and follow the initial steps to build the necessary steps till step 4 which is creating a paticipant_tile.dart screen.</p><p>Now, after adding the other files to the Meeting folder, lets create a meeting_screen.dart file through which our meeting will be created, rendered and managed. </p><pre><code class="language-Dart">import 'dart:convert';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import 'package:videosdk_flutter_example/home.dart';

import 'package:videosdk_flutter_example/meeting/meeting_controls.dart';
import './participant_tile.dart';
import 'package:http/http.dart' as http;

class MeetingScreen extends StatefulWidget {
  final String meetingId;
  final String token;
  final String url;
  final String callerId;
  String? source;
  MeetingScreen(
      {Key? key,
      required this.meetingId,
      required this.token,
      required this.callerId,
      required this.url,
      this.source})
      : super(key: key);

  @override
  State&lt;MeetingScreen&gt; createState() =&gt; _MeetingScreenState();
}

class _MeetingScreenState extends State&lt;MeetingScreen&gt; {
  late Room _room;
  var micEnabled = true;
  var camEnabled = true;

  Map&lt;String, Participant&gt; participants = {};

  @override
  void initState() {
    // create room
    if (widget.source == "true") {
      sendnotification(
          widget.url, widget.callerId, "Call Accepted", widget.meetingId);
    }
    _room = VideoSDK.createRoom(
        roomId: widget.meetingId,
        token: widget.token,
        displayName: "John Doe",
        micEnabled: micEnabled,
        camEnabled: camEnabled,
        defaultCameraIndex: kIsWeb
            ? 0
            : 1 // Index of MediaDevices will be used to set default camera
        );

    setMeetingEventListener();

    // Join room
    _room.join();

    super.initState();
  }

  Future&lt;void&gt; sendnotification(String api, callerId, status, roomId) async {
    await sendCallStatus(
        serverUrl: api, callerId: callerId, status: status, roomId: roomId);
  }

  @override
  void setState(fn) {
    if (mounted) {
      super.setState(fn);
    }
  }

  // listening to meeting events
  void setMeetingEventListener() {
    _room.on(Events.roomJoined, () {
      setState(() {
        participants.putIfAbsent(
            _room.localParticipant.id, () =&gt; _room.localParticipant);
      });
    });

    _room.on(
      Events.participantJoined,
      (Participant participant) {
        setState(
          () =&gt; participants.putIfAbsent(participant.id, () =&gt; participant),
        );
      },
    );

    _room.on(Events.participantLeft, (String participantId) {
      if (participants.containsKey(participantId)) {
        setState(
          () =&gt; participants.remove(participantId),
        );
      }
    });

    _room.on(Events.roomLeft, () {
      participants.clear();
      Navigator.pushAndRemoveUntil(
        context,
        MaterialPageRoute(
            builder: (context) =&gt; Home(
                  callerID: widget.callerId,
                )),
        (route) =&gt; false, // Removes all previous routes
      );
    });
  }

  // onbackButton pressed leave the room
  Future&lt;bool&gt; _onWillPop() async {
    _room.leave();
    return true;
  }

  Future&lt;void&gt; sendCallStatus({
    required String serverUrl,
    required String callerId,
    required String status,
    required String roomId,
  }) async {
    final url = Uri.parse('$serverUrl/send-call-status');
    try {
      // Request payload
      final body = jsonEncode({
        'callerId': callerId,
        'status': status,
        'roomId': roomId,
      });

      // Sending the POST request
      final response = await http.post(
        url,
        headers: {
          'Content-Type': 'application/json',
        },
        body: body,
      );

      // Handling the response
      if (response.statusCode == 200) {
        print("Notification sent successfully: ${response.body}");
      } else {
        print("Failed to send notification: ${response.statusCode}");
       
      }
    } catch (e) {
      print("Error sending call status: $e");
    }
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    // ignore: deprecated_member_use
    return WillPopScope(
      onWillPop: () =&gt; _onWillPop(),
      child: Scaffold(
        appBar: AppBar(
          title: const Text('VideoSDK QuickStart'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              Text(widget.meetingId),
              //render all participant
              Expanded(
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: GridView.builder(
                    gridDelegate:
                        const SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                      crossAxisSpacing: 10,
                      mainAxisSpacing: 10,
                      mainAxisExtent: 300,
                    ),
                    itemBuilder: (context, index) {
                      return ParticipantTile(
                          key: Key(participants.values.elementAt(index).id),
                          participant: participants.values.elementAt(index));
                    },
                    itemCount: participants.length,
                  ),
                ),
              ),
              MeetingControls(
                micEnabled: micEnabled,
                camEnabled: camEnabled,
                onToggleMicButtonPressed: () {
                  setState(() {
                    micEnabled = !micEnabled;
                  });
                  micEnabled ? _room.unmuteMic() : _room.muteMic();
                },
                onToggleCameraButtonPressed: () {
                  setState(() {
                    camEnabled = !camEnabled;
                  });
                  camEnabled ? _room.enableCam() : _room.disableCam();
                },
                onLeaveButtonPressed: () {
                  _room.leave();
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}
</code></pre><p>Great, we have successfully added our videosdk meeting screens. Lets deep dive into main.dart file and home.dart file.    <br><br>main.dart</br></br></p><pre><code class="language-Dart">import 'dart:async';

import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

import 'package:flutter_dotenv/flutter_dotenv.dart';

import 'package:videosdk_flutter_example/home.dart';

import 'package:videosdk_flutter_example/meeting/meeting_screen.dart';

String? videoSdkKey = dotenv.env["VIDEO_SDK_KEY"];
String? url = dotenv.env["SERVER_URL"];
@pragma('vm:entry-point')
Future&lt;void&gt; _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  await Firebase.initializeApp();

}

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
  await dotenv.load(fileName: ".env");
  runApp(const MyApp());

  const platform = MethodChannel('com.yourapp/call');
  platform.setMethodCallHandler((call) async {
    if (call.method == "incomingCall") {
      final data = call.arguments as Map;
      final roomId = data["roomId"];
      final callerId = data["callerId"];
    
    }
  });
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: '/',
      onGenerateRoute: (settings) {
        final uri = Uri.parse(settings.name ?? '');
        if (uri.path == '/meeting') {
          final roomId = uri.queryParameters['roomId'];
          final callerId = uri.queryParameters['callerId'];
          print("Callaer id in Main.dart file: $callerId");
          return MaterialPageRoute(
            builder: (context) {
              WidgetsBinding.instance.addPostFrameCallback((_) {
                Navigator.pushAndRemoveUntil(
                  context,
                  MaterialPageRoute(
                    builder: (context) =&gt; MeetingScreen(
                      meetingId: roomId!,
                      token: videoSdkKey!,
                      callerId: callerId!,
                      url: url!,
                      source: "true",
                    ),
                  ),
                  (route) =&gt; false, // Removes all previous routes
                );
              });
              return const SizedBox(); // Placeholder widget (not displayed)
            },
          );
        } else if (uri.path == '/home') {
          final callerId = uri.queryParameters['callerId'];
          return MaterialPageRoute(
            builder: (context) {
              WidgetsBinding.instance.addPostFrameCallback((_) {
                Navigator.pushAndRemoveUntil(
                  context,
                  MaterialPageRoute(
                    builder: (context) =&gt; Home(
                      callerID: callerId!,
                      source: "true",
                    ),
                  ),
                  (route) =&gt; false, // Removes all previous routes
                );
              });
              return const SizedBox(); // Placeholder widget (not displayed)
            },
          );
        } else {
          return MaterialPageRoute(
            builder: (context) {
              WidgetsBinding.instance.addPostFrameCallback((_) {
                Navigator.pushAndRemoveUntil(
                  context,
                  MaterialPageRoute(
                    builder: (context) =&gt; Home(),
                  ),
                  (route) =&gt; false, // Removes all previous routes
                );
              });
              return const SizedBox(); // Placeholder widget (not displayed)
            },
          );
        }
      },
      debugShowCheckedModeBanner: false,
    );
  }
}
</code></pre><p>After creating the main.dart file, now its time to create a home.dart file. In home.dart file we will be working on managing the notification and also the method call which are required. </p><pre><code class="language-dart">Future&lt;void&gt; sendNotification({
    required String callerId,
    required String callerInfo,
    required String roomId,
    required String token,
  }) async {
    final Map&lt;String, dynamic&gt; payload = {
      'callerId': callerId,
      'callerInfo': {'id': callerInfo},
      'videoSDKInfo': {'roomId': roomId, 'token': token},
    };

    try {
      // Send POST request to the API
      final response = await http.post(
        Uri.parse("${apiUrl!}/send-notification"),
        headers: {'Content-Type': 'application/json'},
        body: jsonEncode(payload),
      );

      // Handle the response from the API
      if (response.statusCode == 200) {
       
        if (mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text("Message sent successfully")),
          );
        }
      } else {
        print('Failed to send notification: ${response.body}');
      }
    } catch (e) {
      print('Error occurred while sending notification: $e');
    }
  }


Future makeCall(String callerID) async {
callerId = callerID;
if (await Permission.phone.isDenied) {
await Permission.phone.request();
}
if (await Permission.phone.isGranted) {
try {
final result = await platform
.invokeMethod('handleIncomingCall', {'callerId': callerID});
} catch (e) {
print('Error: $e');
}
} else {
print('Phone permission is not granted');
}
}</code></pre><p>To get entire code for home.dart file you can refer <a href="https://github.com/videosdk-live/videosdk-rtc-flutter-call-trigger-example/blob/main/Client/lib/home.dart" rel="noreferrer">here</a>.</p><h2 id="deep-linking-in-flutter-for-android-seamlessly-transitioning-from-native-to-flutter"><strong>Deep Linking in Flutter for Android: Seamlessly Transitioning from Native to Flutter</strong></h2><p/><blockquote>So basically the concept of Deep linking states that the <em>onclick</em> event has to redirect to the specified app without any user interaction.</blockquote><p>How It Works</p><ol><li><strong>Native Call Trigger</strong>:<br>When a call is initiated while the app is in the background, the native side of the Android app detects the event. This setup ensures that the native platform efficiently handles the call logic.</br></li><li><strong>Handling Call Events</strong>:<br>Upon user interaction (either answering or rejecting the call), the app seamlessly integrates with Flutter. The native side triggers a deep link back into the app, directing the user to a specific Flutter screen depending on the action.</br></li><li><strong>Deep Link Transition</strong>:<br>The deep link opens the required Flutter screen, ensuring that the app behaves as expected, even after transitioning from the background state.</br></li></ol><h4 id="key-implementation">Key Implementation </h4><ul><li><strong>Defining the Deep Link</strong>:<br>I used a URI scheme to define the deep link format. For example:<br><code>myapp://call?action=answered</code> or <code>myapp://call?action=rejected</code>.You can refer the code in CallConnectionService.kt </br></br></li><li><strong>Native Side Configuration</strong>:<br>The native Android code listens for call events and uses <code>Intent</code> to communicate with the Flutter engine. The <code>Intent</code> carries the deep link information to Flutter.</br></li><li><strong>Flutter Integration</strong>:<br>Ge the Deep link and based on the routes redirect it to a particular page which is mention in the link, if call is answered then redirect the user to meeting and if rejected the open the app and send the caller that receiver and rejected the call.</br></li></ul><hr><blockquote>App Reference</blockquote>
<!--kg-card-begin: html-->
<table>
  <tr>
    <td><img src="https://cdn.videosdk.live/website-resources/docs-resources/flutter-call-kit/calling-screen-flutter-android.jpg" alt="Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK" width="200" height="100"/></td>
    <td><img src="https://cdn.videosdk.live/website-resources/docs-resources/flutter-call-kit/home-screen-flutter-android.jpg" alt="Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK" width="200" height="100"/></td>
  </tr>
</table>
<!--kg-card-end: html-->

<!--kg-card-begin: html-->
<video width="900" height="500" controls="" poster="default-image.jpg">
  <source src="https://cdn.videosdk.live/website-resources/docs-resources/flutter_android_callkit.mp4" type="video/mp4">
  <p>Your browser does not support the video tag or the video is unavailable. 
     <img src="default-image.jpg" alt="Build a Video Calling App with Call Trigger in Flutter - Android using Firebase and VideoSDK" width="900" height="500">
  </img></p>
</source></video>

<!--kg-card-end: html-->
<h2 id="conclusion">Conclusion</h2><p>With this, we've successfully built the Flutter Android video calling app using the Telecom framework, VideoSDK, and Firebase. For additional features like chat messaging and screen sharing, feel free to refer to our&nbsp;<a href="https://docs.videosdk.live/" rel="noreferrer">documentation</a>. If you encounter any issues with the implementation, don’t hesitate to reach out to us through our&nbsp;<a href="https://discord.gg/Gpmj6eCq5u" rel="noreferrer">Discord community</a>.</p></hr></hr>]]></content:encoded></item><item><title><![CDATA[Build a Conversational Flow AI Agent with Voice Activity & Turn Detection]]></title><description><![CDATA[Build a production-quality, self-contained Voice Agent featuring advanced conversational flow, voice activity detection (VAD), and turn detection.]]></description><link>https://www.videosdk.live/blog/conversational-flow-vad-turn-detection</link><guid isPermaLink="false">686b66b8d4a340b6b279c5fe</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[#sumit-so]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 14 Jul 2025 10:32:25 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/07/conversational-flow.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2025/07/conversational-flow.png" alt="Build a Conversational Flow AI Agent with Voice Activity & Turn Detection"/><p/><p>In this blog, you'll learn—step by step—how to build a <strong>production-quality, self-contained VideoSDK agent</strong> featuring advanced conversational flow, voice activity detection (VAD), and turn detection. By the end, you'll have a complete, working playground example: just run the script, join the playground, and experience a natural, back-and-forth AI conversation with Retrieval-Augmented Generation (RAG) for smart recommendations!</p><h2 id="what-were-building">What We're Building</h2><p>We’re transforming a complex, API-driven service into a simple, playground-ready <strong>AI Voice Agent</strong> with Python script. This agent will:</p><ul><li>Join a VideoSDK meeting room directly from your terminal</li><li>Support natural conversation with voice activity and turn detection</li><li>Use <strong>RAG (Retrieval-Augmented Generation)</strong> to give smart, context-aware answers (e.g. travel advice)</li><li>Be easy to run and extend for your own use cases</li></ul><h2 id="prerequisites">Prerequisites</h2><p>You’ll need accounts and API keys for:</p><ul><li><a href="https://app.videosdk.live/">VideoSDK</a> (<code>VIDEOSDK_AUTH_TOKEN</code>)</li><li><a href="https://aistudio.google.com/app/apikey">Google AI Studio</a> (<code>GOOGLE_API_KEY</code>)</li><li><a href="https://platform.openai.com/api-keys">OpenAI</a> (<code>OPENAI_API_KEY</code>)</li><li><a href="https://www.pinecone.io/">Pinecone</a> (<code>PINECONE_API_KEY</code>, <code>PINECONE_INDEX_NAME</code>)</li></ul><h2 id="project-architecture">Project Architecture</h2><pre><code class="language-bash">├── .env.example
├── agent.py               # Agent's personality, VAD, RAG, and dialogue logic
├── build_pinecone_store.py  # Utility to build the vector store
├── main.py                # Entrypoint: runs the playground agent
├── rag_handler.py         # Handles the RAG logic with Pinecone
├── requirements.txt       # Python dependencies
├── travel_destinations.csv # Data for the RAG system
└── README.md              # This file
</code></pre><h2 id="project-setup">Project Setup</h2><h3 id="create-and-activate-a-virtual-environment">Create and Activate a Virtual Environment</h3><pre><code class="language-bash">python -m venv .venv
# On Windows:
.venv\Scripts\activate
# On macOS/Linux:
source .ven</code></pre><h3 id="install-the-required-dependencies">Install the Required Dependencies</h3><p>Create a <code>requirements.txt</code> file with:</p><pre><code class="language-bash">videosdk-agents
videosdk-plugins-google
videosdk-plugins-simli
python-dotenv
fastmcp
langchain
pinecone-client
openai
</code></pre><p>Then install:</p><pre><code class="language-bash">pip install -r requirements.txt
</code></pre><h3 id="configure-environment-variables">Configure Environment Variables</h3><p>Copy <code>.env.example</code> to <code>.env</code> and fill in your API keys:</p><pre><code class="language-bash">VIDEOSDK_AUTH_TOKEN=...
GOOGLE_API_KEY=...
OPENAI_API_KEY=...
PINECONE_API_KEY=...
PINECONE_INDEX_NAME</code></pre><h2 id="core-concept-what-is-rag">(Core Concept) What is RAG?</h2><p><strong>Retrieval-Augmented Generation (RAG)</strong> combines the power of language models with external knowledge. When the user asks a question, the agent first searches a knowledge base (using Pinecone) for relevant facts, then provides a personalized answer using those facts. This makes your agent much smarter and context-aware—perfect for things like a travel advisor!</p><h2 id="build-the-knowledge-base">Build the Knowledge Base</h2><p>You must first populate your Pinecone vector store with travel destination data:</p><pre><code class="language-bash">python build_pinecone_store.py
</code></pre><p>This reads <code>travel_destinations.csv</code>, generates embeddings with OpenAI, and uploads them to Pinecone.<br><strong>You must do this before you start the agent!</strong></br></p><h2 id="code-walkthrough">Code Walkthrough</h2><h3 id="mainpy-%E2%80%94-entrypoint-and-session-setup"><code>main.py</code> — Entrypoint and Session Setup</h3><pre><code class="language-python">import asyncio
import sys
import os
import requests
from pathlib import Path
from dotenv import load_dotenv

from videosdk.agents import (
    AgentSession,
    JobContext,
    RoomOptions,
    WorkerJob,
    RealTimePipeline
)
from videosdk.plugins.google import GeminiRealtime, GeminiLiveConfig
from agent import MyVoiceAgent, MyConversationFlow

load_dotenv(override=True)

def get_room_id(auth_token: str) -&gt; str:
    url = "https://api.videosdk.live/v2/rooms"
    headers = {"Authorization": auth_token}
    response = requests.post(url, headers=headers)
    response.raise_for_status()
    return response.json()["roomId"]

async def start_session(context: JobContext):
    model = GeminiRealtime(
        model="gemini-2.0-flash-live-001",
        config=GeminiLiveConfig(
            voice="Nova",
            response_modalities=["AUDIO"]
        )
    )
    pipeline = RealTimePipeline(model=model)

    system_prompt = (
        "You are a knowledgeable and friendly travel advisor AI assistant. "
        "Your goal is to help users find perfect travel destinations based on their interests. "
        "Use the context provided from the knowledge base to give helpful, personalized recommendations. "
        "Be conversational and friendly - travel planning should be exciting!"
    )
    agent = MyVoiceAgent(system_prompt=system_prompt, personality="travel_advisor")
    conversation_flow = MyConversationFlow(agent)

    session = AgentSession(
        agent=agent,
        pipeline=pipeline,
        conversation_flow=conversation_flow
    )

    await context.connect()
    await session.start()
    await asyncio.Event().wait()

def make_context() -&gt; JobContext:
    auth_token = os.getenv("VIDEOSDK_AUTH_TOKEN")
    if not auth_token:
        raise ValueError("VIDEOSDK_AUTH_TOKEN environment variable not set!")
    room_id = get_room_id(auth_token)
    room_options = RoomOptions(
        room_id=room_id,
        auth_token=auth_token,
        name="RAG Travel Agent",
        playground=True
    )
    return JobContext(room_options=room_options)

if __name__ == "__main__":
    print("🚀 Starting AI Agent for VideoSDK Playground...")
    job = WorkerJob(entrypoint=start_session, jobctx=make_context)
    job.start()
</code></pre><h3 id="agentpy-%E2%80%94-personality-conversational-flow-vad-and-rag"><code>agent.py</code> — Personality, Conversational Flow, VAD, and RAG</h3><pre><code class="language-python">import asyncio
from typing import AsyncIterator
from videosdk.agents import Agent, ConversationFlow, function_tool, ChatRole
from rag_handler import search_knowledge_base

class MyVoiceAgent(Agent):
    def __init__(self, system_prompt: str, personality: str):
        super().__init__(instructions=system_prompt)
        self.personality = personality

    async def on_enter(self) -&gt; None:
        await self.session.say("Hey, I'm your friendly travel advisor! Where are you dreaming of going?")

    async def on_exit(self) -&gt; None:
        await self.session.say("Happy travels! Goodbye!")

    @function_tool
    async def end_call(self) -&gt; None:
        await self.session.say("It was great planning with you. Goodbye!")
        await asyncio.sleep(1)
        await self.session.leave()

class MyConversationFlow(ConversationFlow):
    async def run(self, transcript: str) -&gt; AsyncIterator[str]:
        self.agent.chat_context.add_message(role=ChatRole.USER, content=transcript)
        retrieved_context = None
        try:
            retrieved_context = await search_knowledge_base(transcript)
        except Exception as e:
            print(f"Error during RAG retrieval: {e}")
        if retrieved_context:
            self.agent.chat_context.add_message(
                role=ChatRole.SYSTEM, 
                content=f"Here is some relevant context from the travel database: {retrieved_context}"
            )
        async for response_chunk in self.process_with_llm():
            yield response_chunk
</code></pre><h3 id="raghandlerpy-%E2%80%94-pinecone-rag-handler"><code>rag_handler.py</code> — Pinecone RAG Handler</h3><pre><code class="language-python">import os
from typing import List, Dict
from dotenv import load_dotenv
from langchain_openai import OpenAIEmbeddings
from pinecone import Pinecone
import logging

load_dotenv()

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class RAGHandler:
    def __init__(self):
        self.embeddings_model = None
        self.pinecone_index = None
        self.initialized = False

    async def initialize(self):
        if self.initialized:
            return
        try:
            openai_api_key = os.getenv("OPENAI_API_KEY")
            pinecone_api_key = os.getenv("PINECONE_API_KEY")
            pinecone_index_name = os.getenv("PINECONE_INDEX_NAME")
            if not all([openai_api_key, pinecone_api_key, pinecone_index_name]):
                raise ValueError("Missing RAG environment variables!")
            self.embeddings_model = OpenAIEmbeddings(openai_api_key=openai_api_key)
            pc = Pinecone(api_key=pinecone_api_key)
            self.pinecone_index = pc.Index(pinecone_index_name)
            self.initialized = True
            logger.info("RAG Handler initialized successfully.")
        except Exception as e:
            logger.error(f"Failed to initialize RAG Handler: {e}")
            raise

    async def search(self, query: str, top_k: int = 3) -&gt; List[Dict]:
        if not self.initialized:
            await self.initialize()
        query_embedding = self.embeddings_model.embed_query(query)
        search_results = self.pinecone_index.query(
            vector=query_embedding,
            top_k=top_k,
            include_metadata=True
        )
        return [
            {"content": match.metadata.get("text", ""), "score": match.score}
            for match in search_results.matches
        ]

    def format_context_for_llm(self, search_results: List[Dict]) -&gt; str:
        if not search_results:
            return "No relevant information found in the knowledge base."
        context_parts = []
        for i, result in enumerate(search_results, 1):
            context_parts.append(f"Reference {i}:\n{result['content']}\n")
        return "\n".join(context_parts)

rag_handler = RAGHandler()

async def search_knowledge_base(query: str, max_results: int = 3) -&gt; str:
    try:
        search_results = await rag_handler.search(query, top_k=max_results)
        return rag_handler.format_context_for_llm(search_results)
    except Exception as e:
        logger.error(f"Error in search_knowledge_base: {e}")
        return "I apologize, but I'm having trouble accessing the travel database right now."
</code></pre><h3 id="buildpineconestorepy-%E2%80%94-build-the-knowledge-base"><code>build_pinecone_store.py</code> — Build the Knowledge Base</h3><blockquote><em>This script is unchanged from the original. It reads your <code>travel_destinations.csv</code>, generates OpenAI embeddings, and uploads them to Pinecone. Run it before starting the agent!</em></blockquote><h3 id="traveldestinationscsv-%E2%80%94-your-data"><code>travel_destinations.csv</code> — Your Data</h3><blockquote><em>This is your knowledge base: a CSV file of travel destinations to recommend. You can expand it as you wish!</em></blockquote><h2 id="running-the-agent-and-seeing-the-result">Running the Agent and Seeing the Result</h2><ol><li><strong>Talk to your AI agent!</strong><ul><li>Ask travel questions from <a href="https://saaspirate.com/how-ai-agents-change-work/" rel="noreferrer">your AI agent</a>, like "Where should I go for great beaches and food?</li><li>The agent will search your knowledge base and respond in real time, with voice activity and turn detection for smooth conversation!</li></ul></li></ol><p><strong>Open the VideoSDK Playground URL</strong> printed in your terminal.<br>Example:</br></p><pre><code class="language-bash">https://playground.videosdk.live?token=...&amp;meetingId=...</code></pre><p><strong>Run the agent:</strong></p><pre><code class="language-bash">python main.py
</code></pre><p><strong>Build your knowledge base</strong> (if you haven't already):</p><pre><code class="language-bash">python build_pinecone_store.py
</code></pre><h2 id="conclusion-next-steps">Conclusion &amp; Next Steps</h2><p>You now have a fully working, playground-ready conversational AI with:</p><ul><li>Real-time voice and turn-taking</li><li>RAG-powered smart answers</li><li>Easy extensibility (swap out data, add tools, change the agent’s personality)</li></ul><p><strong>Next steps:</strong></p><ul><li>Add new tools (weather, booking, facts)</li><li>Enhance your knowledge base (more CSV data)</li><li>Try different agent personalities or pipelines</li></ul><p>For more, see the <a href="https://docs.videosdk.live/ai_agents/playground">VideoSDK AI Playground documentation</a>.</p>]]></content:encoded></item><item><title><![CDATA[Build AI Avatar Agent with VideoSDK & Simli Face API]]></title><description><![CDATA[Add AI avatar to your VideoSDK agent with Python. Build an interactive, voice-enabled assistant that can answer live weather queries and more.]]></description><link>https://www.videosdk.live/blog/ai-avatar-agent</link><guid isPermaLink="false">686b573cd4a340b6b279c5bd</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[#sumit-so]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 14 Jul 2025 08:42:50 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/07/ai-avatar-demo.png" medium="image"/><content:encoded><![CDATA[<blockquote>An AI avatar agent is a real-time digital assistant that combines conversational intelligence with a responsive visual persona. You build an AI avatar agent efficiently using VideoSDK, Google Gemini, and the Simli Face API. This architecture enables developers to deploy interactive, voice-enabled assistants capable of executing live tasks.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2025/07/ai-avatar-demo.png" alt="Build AI Avatar Agent with VideoSDK & Simli Face API"/><p>Most traditional chatbots fail to capture user attention because they lack a humanizing element. By adding a visual persona, you transform a simple text interface into an engaging interactive experience. This approach drastically improves user retention and task completion rates. In this tutorial, you will learn how to build an AI avatar agent using VideoSDK, Google Gemini, and the <a href="https://docs.videosdk.live/ai_agents/plugins/avatar/simli" rel="noreferrer">Simli</a> Face API in Python. You will deploy a real-time, voice-enabled digital assistant capable of answering live queries.</p><h2 id="what-is-an-ai-avatar-agent">What is an AI Avatar Agent?</h2><p>An <a href="https://docs.videosdk.live/ai_agents/core-components/avatar" rel="noreferrer">AI avatar agent</a> is a sophisticated real-time application that integrates language processing with synchronized visual animation. An AI avatar agent is defined as a virtual persona that uses artificial intelligence to conduct dynamic, voice-enabled conversations with human users.</p><p>These digital assistants move beyond text-based interactions by incorporating facial expressions and lip-syncing that match the generated speech. This creates a highly engaging interface that mimics a real human conversation. An AI avatar agent works by capturing user audio, processing the intent through a large language model, generating a spoken response, and rendering the corresponding facial animations in real time.</p><p>In practice, engineering teams that implement visual avatars report significantly higher user engagement metrics compared to traditional text chatbots. When users see a face that reacts to their input, they stay engaged longer and complete complex flows like onboarding or troubleshooting. The integration requires careful orchestration of multiple pipelines, ensuring that the audio and visual streams remain perfectly synchronized throughout the interaction.</p><h2 id="project-architecture">Project Architecture</h2><pre><code class="language-bash">├── main.py              # Main agent implementation
├── requirements.txt     # Python dependencies
├── mcp_weather.py       # Weather MCP server
├── .env.example         # Environment variables template
└── README.md            # This file</code></pre><h2 id="set-up-your-python-project">Set Up Your Python Project</h2><p>We'll build this project in Python. Start by ensuring your environment is ready and all required dependencies are installed.</p><ul><li>Make sure you've a <code>python &gt;=3.12</code> </li></ul><h3 id="create-and-activate-a-virtual-environment">Create and Activate a Virtual Environment</h3><pre><code class="language-bash">python -m venv .venv
# On Windows
.venv\Scripts\activate
# On macOS/Linux
source .venv/bin/activate
</code></pre><h3 id="install-the-required-dependencies">Install the Required Dependencies</h3><p>Create a <code>requirements.txt</code> file and add these lines:</p><pre><code class="language-bash">videosdk-agents
videosdk-plugins-google
videosdk-plugins-simli
python-dotenv
fastmcp</code></pre><p>Then install them:</p><pre><code class="language-bash">pip install -r requirements.txt
</code></pre><h2 id="the-big-picture-how-the-pieces-connect">The Big Picture: How the Pieces Connect</h2><p>Before diving into the code, let’s map out the core components and how they interact:</p><ul><li><strong>VideoSDK Agent</strong><br>The “director” that orchestrates everything. It manages the session, connects to the playground, and coordinates the avatar, voice, and tools.</br></li><li><strong>Google Gemini (via VideoSDK plugin)</strong><br>The “brain” of your agent, responsible for understanding what you say and generating natural-sounding replies in real time.</br></li><li><strong>Simli Avatar (via VideoSDK plugin)</strong><br>The “face” and “voice” of your agent. It animates and speaks the responses generated by Gemini, making the agent feel alive.</br></li><li><strong>MCP Weather Tool (Model Context Protocol)</strong><br>The “specialist prop master.” When the conversation calls for weather info, the agent calls out to this separate process, which fetches live weather data and returns it as dialogue.</br></li></ul><p><strong>How it all works in a conversation:</strong></p><ol><li>You speak to the avatar in the browser or a mobile application (using the VideoSDK playground).</li><li>The agent (<code>main.py</code>) receives your message, processes it with Gemini, and speaks the response using Simli.</li><li>If you ask about the weather, the agent reaches out to the MCP weather tool (<code>mcp_weather.py</code>), which fetches the answer and brings it into the conversation in real time.</li></ol><p>For more on how the playground works, check out the <a href="https://docs.videosdk.live/ai_agents/playground">VideoSDK AI Playground documentation</a>.</p><h2 id="the-heart-of-the-show-%E2%80%94-the-key-files">The Heart of the Show — The Key Files</h2><h3 id="mainpy-%E2%80%94-the-orchestrator"><code>main.py</code> — The Orchestrator</h3><p>This is the main script where the “performance” comes together:</p><ul><li>It configures your AI agent with a voice, a face, and the ability to call out to external tools (like the weather server).</li><li>When you run it, it spins up a VideoSDK room and connects your agent to the browser-based playground, ready to talk in real time.</li></ul><pre><code class="language-python">import asyncio
import sys
from pathlib import Path
import requests
from videosdk.agents import Agent, AgentSession, RealTimePipeline, JobContext, RoomOptions, WorkerJob, MCPServerStdio
from videosdk.plugins.google import GeminiRealtime, GeminiLiveConfig
from videosdk.plugins.simli import SimliAvatar, SimliConfig
from dotenv import load_dotenv
import os

load_dotenv(override=True)

def get_room_id(auth_token: str) -&gt; str:
    url = "https://api.videosdk.live/v2/rooms"
    headers = {
        "Authorization": auth_token
    }
    response = requests.post(url, headers=headers)
    response.raise_for_status()
    return response.json()["roomId"]

class MyVoiceAgent(Agent):
    def __init__(self):
        mcp_script_weather = Path(__file__).parent / "mcp_weather.py"
        super().__init__(
            instructions="You are VideoSDK's AI Avatar Voice Agent with real-time capabilities. You are a helpful virtual assistant with a visual avatar that can answer questions about weather help with other tasks in real-time.",
            mcp_servers = [
                MCPServerStdio(
                    executable_path=sys.executable,
                    process_arguments= [str(mcp_script_weather)],
                    session_timeout=30
                )
                ]
        )

    async def on_enter(self) -&gt; None:
        await self.session.say("Hello! I'm your real-time AI avatar assistant. How can I help you today?")
    
    async def on_exit(self) -&gt; None:
        await self.session.say("Goodbye! It was great talking with you!")
        

async def start_session(context: JobContext):
    # Initialize Gemini Realtime model
    model = GeminiRealtime(
        model="gemini-2.0-flash-live-001",
        # When GOOGLE_API_KEY is set in .env - DON'T pass api_key parameter
        api_key="xxxxxx", 
        config=GeminiLiveConfig(
            voice="Leda",  # Puck, Charon, Kore, Fenrir, Aoede, Leda, Orus, and Zephyr.
            response_modalities=["AUDIO"]
        )
    )

    # Initialize Simli Avatar
    simli_config = SimliConfig(
        apiKey="xxxxxxxxxxxxx",
        faceId="0c2b8b04-5274-41f1-a21c-d5c98322efa9" # default
    )
    simli_avatar = SimliAvatar(config=simli_config)

    # Create pipeline with avatar
    pipeline = RealTimePipeline(
        model=model,
        avatar=simli_avatar
    )
    
    session = AgentSession(
        agent=MyVoiceAgent(),
        pipeline=pipeline
    )

    try:
        await context.connect()
        await session.start()
        await asyncio.Event().wait()
    finally:
        await session.close()
        await context.shutdown()

def make_context() -&gt; JobContext:
    auth_token = os.getenv("VIDEOSDK_AUTH_TOKEN")
    room_id = get_room_id(auth_token)
    room_options = RoomOptions(
        room_id=room_id,
        auth_token=auth_token,
        name="Simli Avatar Realtime Agent",
        playground=True 
    )
    return JobContext(room_options=room_options)


if __name__ == "__main__":
    job = WorkerJob(entrypoint=start_session, jobctx=make_context)
    job.start() 
</code></pre><h3 id="mcpweatherpy-%E2%80%94-the-weather-specialist-mcp-tool"><code>mcp_weather.py</code> — The Weather Specialist (MCP Tool)</h3><p><strong>About MCP:</strong><br>The <strong>Model Context Protocol (MCP)</strong> allows your agent to “call out” to external specialists when it doesn’t know something itself. In this project, <code>mcp_weather.py</code> is that specialist: a dedicated service that fetches live weather data for any city using the <strong>OpenWeatherMap API</strong>. When you ask your agent about the weather, it seamlessly passes your request to this <strong>MCP tool</strong> and brings the answer back, all in real time.</br></p><pre><code class="language-python">from fastmcp import FastMCP
import httpx
import os
from dotenv import load_dotenv

load_dotenv(override=True)

OPENWEATHER_API_KEY = os.getenv("OPENWEATHER_API_KEY")
# Replace with your actual OpenWeatherMap API key
OPENWEATHER_URL = "https://api.openweathermap.org/data/2.5/weather"

mcp = FastMCP("CurrentWeatherServer")

@mcp.tool()
async def get_current_weather(city: str) -&gt; str:
    """
    Get the current weather for a given city using OpenWeatherMap API.
    """
    params = {
        "q": city,
        "appid": OPENWEATHER_API_KEY,
        "units": "metric"
    }
    async with httpx.AsyncClient() as client:
        try:
            response = await client.get(OPENWEATHER_URL, params=params, timeout=10)
            
            # Better error handling for authorization issues
            if response.status_code == 401:
                return f"Authorization error: Invalid API key. Please check your OpenWeatherMap API key."
            elif response.status_code == 404:
                return f"City '{city}' not found. Please check the spelling."
            
            response.raise_for_status()
            data = response.json()
            weather = data["weather"][0]["description"].capitalize()
            temp = data["main"]["temp"]
            feels_like = data["main"]["feels_like"]
            humidity = data["main"]["humidity"]
            wind_speed = data.get("wind", {}).get("speed", "N/A")
            return (f"Hi Sumit!, Current weather in {city}:\n"
                    f"{weather}, temperature: {temp}°C, feels like: {feels_like}°C.\n"
                    f"Humidity: {humidity}%, Wind speed: {wind_speed} m/s")
        except httpx.RequestError as e:
            return f"Network error: Could not retrieve weather data for {city}: {e}"
        except Exception as e:
            return f"Could not retrieve weather data for {city}: {e}"

if __name__ == "__main__":
    mcp.run(transport="stdio")
</code></pre><h2 id="step-by-step-bringing-your-ai-avatar-to-life">Step-by-Step: Bringing Your AI Avatar to Life</h2><ol><li><strong>Set up your environment variables:</strong><ul><li>Copy <code>.env.example</code> to <code>.env</code></li></ul></li><li><strong>Talk to your AI avatar!</strong><ul><li>Say hello, ask about the weather (“What’s the weather in London?”), or have a general conversation.</li><li>The avatar will speak and respond using Gemini and Simli, and fetch live weather using the MCP tool.</li></ul></li></ol><p><strong>Open the VideoSDK playground URL</strong> printed in your terminal.<br>This will look like:</br></p><pre><code class="language-bash">https://playground.videosdk.live?token=...&amp;meetingId=...</code></pre><p><strong>Run your agent:</strong></p><pre><code class="language-bash">python main.py
</code></pre><p>Fill out the following in <code>.env</code>:</p><pre><code class="language-bash">VIDEOSDK_AUTH_TOKEN=your-videosdk-token
SIMLI_API_KEY=your-simli-api-key
SIMLI_FACE_ID=your-simli-face-id
OPENWEATHER_API_KEY=your-openweathermap-key
GOOGLE_API_KEY=your-google-api-key</code></pre><p><strong>Now step onto the stage, run the code, and meet your creation. The talking avatar is waiting. What will you say first?</strong></p><p>You can dive deeper into the playground and agent capabilities in the <a href="https://docs.videosdk.live/ai_agents/playground">VideoSDK AI Playground documentation</a>.</p><h2 id="real-example-deploying-a-customer-support-avatar">Real Example: Deploying a Customer Support Avatar</h2><p>Integrating an AI avatar agent transforms standard customer support portals into interactive, personalized service experiences. For example, imagine a financial technology company that deploys a VideoSDK-powered avatar to assist users with account navigation and troubleshooting.</p><p>Instead of navigating complex FAQ menus, users simply click a button to initiate a live video call with the avatar. The agent utilizes the Gemini language model to comprehend the user's spoken problem. If the user asks about recent transaction history, the agent seamlessly calls an internal MCP server connected to the banking database. The agent then speaks the transaction details aloud, while the Simli avatar renders appropriate facial expressions.</p><p>In practice, organizations deploying this architecture report a drastic reduction in average resolution time. The visual presence of the avatar encourages users to speak naturally, providing more context to the AI model than they typically do in a text-based chat. The VideoSDK infrastructure ensures that the voice and video remain synchronized even under fluctuating network conditions, preserving the professional appearance of the virtual support representative.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-5--2026--03_08_40-PM.png" class="kg-image" alt="Build AI Avatar Agent with VideoSDK & Simli Face API" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Customer support AI avatar interface</span></figcaption></img></figure><h2 id="definitions-glossary">Definitions Glossary</h2><p>Mastering the terminology is essential for successfully deploying interactive communication systems.</p><p><a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer"><strong>WebRTC</strong></a><strong>:</strong>&nbsp;An open-source project that provides web browsers and mobile applications with real-time communication via simple APIs.&nbsp;</p><p><a href="https://docs.videosdk.live/ai_agents/core-components/avatar" rel="noreferrer"><strong>AI Avatar Agent</strong></a><strong>:</strong>&nbsp;A virtual persona that uses artificial intelligence to conduct dynamic, voice-enabled conversations with human users.&nbsp;</p><p><a href="https://videosdk.live/developer-hub/ai/model-context-protocol" rel="noreferrer"><strong>Model Context Protocol</strong></a><strong>:</strong>&nbsp;An architecture standard that allows AI agents to securely interact with external tools and data sources.&nbsp;</p><p><a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-latency" rel="noreferrer"><strong>Latency</strong></a><strong>:</strong>&nbsp;The total time it takes for a data packet to travel from the source to the destination and back.&nbsp;</p><p><strong>Orchestrator:</strong>&nbsp;A central software component responsible for coordinating the execution and data flow between multiple integrated systems.</p><h2 id="key-takeaways">Key Takeaways</h2><p>Reviewing the core principles ensures a successful deployment of your interactive digital assistant.</p><ul><li>Implementing an AI avatar agent requires orchestrating a cognitive engine, a visual rendering API, and a robust real-time transport layer.</li><li>Maintaining a glass-to-glass latency under 800 milliseconds is critical for preserving the illusion of a natural, responsive conversation.</li><li>VideoSDK serves as the ideal orchestrator by natively managing WebRTC connections and providing seamless plugins for LLMs and visual avatars.</li><li>The Model Context Protocol empowers developers to safely expand the agent's capabilities by integrating standalone, specialized data retrieval tools.</li><li>Production deployments rely on robust error handling to gracefully manage API rate limits and fluctuating network conditions without dropping the session.</li></ul><h2 id="conclusion">Conclusion</h2><p>Building an AI avatar agent fundamentally changes how users interact with automated systems, shifting the paradigm from static text to dynamic, visual conversations. By leveraging VideoSDK, Google Gemini, and the Simli Face API, developers construct highly responsive assistants capable of executing complex tasks in real time. Begin transforming your user experience today by reviewing the VideoSDK documentation and deploying your first interactive digital persona.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><p>Addressing common technical inquiries clarifies the deployment process for interactive digital assistants.</p><h3 id="what-is-the-ideal-latency-for-an-ai-avatar-agent">What is the ideal latency for an AI avatar agent?</h3><p>According to industry benchmarks, an AI avatar agent needs to maintain a glass-to-glass latency of under 800 milliseconds. If the delay exceeds this threshold, human users perceive the conversation as unnatural and abandon the interaction entirely.</p><h3 id="how-does-videosdk-manage-the-real-time-communication">How does VideoSDK manage the real-time communication?</h3><p>VideoSDK acts as the primary orchestrator for the AI avatar agent by managing the underlying WebRTC infrastructure. It handles the continuous transmission of audio and video streams between the client browser and the backend API services, ensuring synchronization without requiring manual pipeline assembly.</p><h3 id="can-i-use-different-language-models-with-videosdk">Can I use different language models with VideoSDK?</h3><p>Yes, VideoSDK supports multiple language models through its plugin architecture. While this implementation utilizes Google Gemini Realtime, developers initialize a different supported model within the real-time pipeline configuration to swap the cognitive engine.</p><h3 id="what-is-the-purpose-of-the-model-context-protocol-mcp">What is the purpose of the Model Context Protocol (MCP)?</h3><p>The Model Context Protocol enables the AI avatar agent to securely interact with external tools and fetch live data during a conversation. By decoupling the tools from the core agent logic, developers scale functionality efficiently without risking the stability of the primary application.</p><h3 id="how-do-i-deploy-the-ai-avatar-agent-securely">How do I deploy the AI avatar agent securely?</h3><p>Secure deployment requires managing authentication entirely on the backend server. Developers generate ephemeral, scoped tokens that the frontend application uses to connect to the VideoSDK room, ensuring that API keys remain protected and unauthorized users stay blocked from the session.</p>]]></content:encoded></item><item><title><![CDATA[How to Build an AI Telephony Agent for Inbound and Outbound Calls]]></title><description><![CDATA[Build an AI telephony agent for inbound and outbound calls. Step-by-step guide to SIP, call automation, and real-time AI voice solutions.]]></description><link>https://www.videosdk.live/blog/ai-telephony-agent-inbound-outbound-calls</link><guid isPermaLink="false">685d2da94ec7927e167c891a</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[#sumit-so]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 14 Jul 2025 08:40:20 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/06/Outbound-Calls.png" medium="image"/><content:encoded><![CDATA[<blockquote>An AI telephony agent connects SIP phone calls to a real-time voice AI stack running speech-to-text, LLM reasoning, and text-to-speech in one session. Build one by wiring Twilio to VideoSDK's agent framework, deploying a FastAPI server for call webhooks, and implementing an Agent class for conversation logic.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2025/06/Outbound-Calls.png" alt="How to Build an AI Telephony Agent for Inbound and Outbound Calls"/><p>Your support queue hits 400 missed calls before noon, and every one routes to voicemail. An AI telephony agent answers those calls in real time, confirms appointments, collects feedback, or places outbound follow-ups without adding headcount. This article defines what an <a href="https://videosdk.live/blog/ai-phone-agent" rel="noreferrer">AI telephony agent</a> is, maps the SIP-to-AI architecture, walks through a Python build with VideoSDK and FastAPI, compares platform options, and covers the production challenges that tutorial posts skip.</p><h2 id="what-is-an-ai-telephony-agent">What Is an AI Telephony Agent?</h2><p>An AI telephony agent is defined as a software system that answers or initiates phone calls over SIP and VoIP networks while running conversational AI logic through speech-to-text, a large language model, and text-to-speech in a single real-time session.</p><p>An AI telephony agent works by receiving an inbound call webhook from a SIP provider, creating a media session in a real-time communication room, bridging the phone audio into that room, and piping the caller's speech through an AI pipeline that generates spoken responses. Outbound agents follow the same pipeline in reverse: your server initiates the call, connects the callee to the AI session, and the agent delivers a scripted or dynamic conversation.</p><p>Unlike traditional IVR systems that play fixed menu trees, AI telephony agents interpret natural language, maintain conversational context across multiple turns, and execute tool calls like checking CRM records or updating appointment databases. According to Grand View Research, the <a href="https://www.grandviewresearch.com/industry-analysis/conversational-ai-market-report" rel="noreferrer">global conversational AI market size</a> was valued at USD 14.3 billion in 2025 and is projected to grow from USD 17.7 billion in 2026 to USD 78.9 billion by 2033, growing at a CAGR of 23.8% from 2026 to 2033. North America is expected to hold a significant share of the global chatbot market, with a revenue share of over 31.1%by 2025..</p><p>Teams building on VideoSDK gain a unified stack where SIP call control, real-time audio transport, and the agent framework (LLM, STT, TTS plugins) run in one integration rather than stitching together separate media, AI, and telephony vendors.</p><h2 id="how-does-an-ai-telephony-agent-work">How Does an AI Telephony Agent Work?</h2><p>An AI telephony agent processes every phone call through five sequential stages: SIP signaling, media bridging, speech recognition, language model reasoning, and speech synthesis back to the caller.</p><h3 id="sip-signaling-and-call-control">SIP Signaling and Call Control</h3><p>When a caller dials your Twilio number, Twilio sends an HTTP webhook to your FastAPI server's&nbsp;<code>/inbound-call</code>&nbsp;endpoint with call metadata (CallSid, From, To). Your server creates a VideoSDK room, retrieves the SIP endpoint for that room, and returns TwiML instructions that connect the phone call into the room via SIP dial. For SIP trunk setup details.</p><h3 id="media-bridging">Media Bridging</h3><p>The SIP provider bridges PSTN audio into the VideoSDK room as a SIP participant. The AI agent joins the same room as a software participant. Both sides share a real-time audio channel where the agent hears the caller and the caller hears the agent's synthesized voice.</p><h3 id="speech-to-text-llm-and-text-to-speech">Speech-to-Text, LLM, and Text-to-Speech</h3><p>The agent framework captures incoming audio, converts it to text via STT (Google Cloud Speech, Deepgram, or similar), sends the transcript to an LLM (Google Gemini, OpenAI GPT, or a custom model), and converts the LLM response to audio via TTS (Google Cloud Text-to-Speech, ElevenLabs, or similar). According to Twilio's Voice API documentation, SIP-connected calls support standard codecs including G.711 (PCMU/PCMA) for PSTN interoperability.</p><h3 id="session-lifecycle">Session Lifecycle</h3><p>For inbound calls, the session starts when the webhook fires and ends when the caller hangs up or the agent calls&nbsp;<code>on_exit</code>. For outbound calls, your server POSTs to&nbsp;<code>/outbound-call</code>, creates the room and agent session first, then initiates the outbound dial so the AI is ready before the callee answers.</p><p>In practice, engineering teams that pre-warm the agent session before connecting the SIP leg report fewer dropped first utterances and lower perceived latency on outbound campaigns.</p><h2 id="architecture-overview-modular-extensible-real-time">Architecture Overview: Modular, Extensible, Real-Time</h2><p>Our architecture separates concerns for maximum flexibility:</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/06/image.png" class="kg-image" alt="How to Build an AI Telephony Agent for Inbound and Outbound Calls" loading="lazy" width="2379" height="1214"/></figure><ul><li><strong>SIP Integration</strong> (VoIP telephony, call control, DTMF, call transfer, call recording)</li><li><strong>AI Voice Agent</strong> (Powered by VideoSDK’s agent framework, integrates LLMs, STT, TTS, sentiment analysis)</li><li><strong>Session Management</strong> (Inbound/outbound call routing, session lifecycle)</li><li><strong>Provider Abstraction</strong> (Easily switch SIP providers—Twilio, Plivo, etc.)</li><li><strong>Pluggable AI Capabilities</strong> (Swap in Google, OpenAI, or custom models)</li></ul><p>You can add features like runtime configuration, call transcription, web dashboards, and more—all with Python.</p><h2 id="project-structure">Project Structure</h2><p>Let’s start by laying out the recommended project structure, just like the demo repo:</p><pre><code class="language-text">ai-telephony-demo/
├── ai/                  # AI and LLM plugins (optional, for custom logic)
├── providers/           # Telephony/SIP provider integrations
├── services/            # Business logic, utilities, and workflow services
├── voice_agent.py       # Core AI voice agent
├── server.py            # FastAPI application and entrypoint
├── config.py            # Environment-driven config
├── requirements.txt     # Python dependencies
</code></pre><h2 id="dependencies">Dependencies</h2><p>Install the dependencies listed in <code>requirements.txt</code>:</p><pre><code class="language-bash">pip install -r requirements.txt
</code></pre><p>Key dependencies include:</p><ul><li><code>fastapi</code> &amp; <code>uvicorn</code> for the server</li><li><code>videosdk</code>, <code>videosdk-agents</code>, and plugins for agent logic</li><li><code>twilio</code>, <code>google-cloud-speech</code>, <code>google-cloud-texttospeech</code> for SIP &amp; AI</li><li><code>python-dotenv</code> for config</li></ul><h2 id="configuration">Configuration</h2><p>Create a <code>.env</code> file in your project root with all the required keys:</p><pre><code class="language-env">VIDEOSDK_AUTH_TOKEN=your_videosdk_auth_token
VIDEOSDK_SIP_USERNAME=your_sip_username
VIDEOSDK_SIP_PASSWORD=your_sip_password
GOOGLE_API_KEY=your_google_api_key
TWILIO_SID=your_twilio_sid
TWILIO_AUTH_TOKEN=your_twilio_auth_token
TWILIO_NUMBER=your_twilio_phone_number
</code></pre><p>Your <code>config.py</code> loads and validates these:</p><pre><code class="language-python">import os
import logging
from dotenv import load_dotenv

load_dotenv()
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

class Config:
    VIDEOSDK_AUTH_TOKEN = os.getenv("VIDEOSDK_AUTH_TOKEN")
    VIDEOSDK_SIP_USERNAME = os.getenv("VIDEOSDK_SIP_USERNAME")
    VIDEOSDK_SIP_PASSWORD = os.getenv("VIDEOSDK_SIP_PASSWORD")
    GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY")
    TWILIO_ACCOUNT_SID = os.getenv("TWILIO_SID")
    TWILIO_AUTH_TOKEN = os.getenv("TWILIO_AUTH_TOKEN")
    TWILIO_NUMBER = os.getenv("TWILIO_NUMBER")

    @classmethod
    def validate(cls):
        required_vars = {
            "VIDEOSDK_AUTH_TOKEN": cls.VIDEOSDK_AUTH_TOKEN,
            "VIDEOSDK_SIP_USERNAME": cls.VIDEOSDK_SIP_USERNAME,
            "VIDEOSDK_SIP_PASSWORD": cls.VIDEOSDK_SIP_PASSWORD,
            "GOOGLE_API_KEY": cls.GOOGLE_API_KEY,
            "TWILIO_SID": cls.TWILIO_ACCOUNT_SID,
            "TWILIO_AUTH_TOKEN": cls.TWILIO_AUTH_TOKEN,
            "TWILIO_NUMBER": cls.TWILIO_NUMBER,
        }
        missing = [v for v, val in required_vars.items() if not val]
        if missing:
            for v in missing:
                logger.error(f"Missing environment variable: {v}")
            raise ValueError(f"Missing required environment variables: {', '.join(missing)}")
        logger.info("All required environment variables are set.")

Config.validate()
</code></pre><h2 id="the-voice-agent-ai-powered-call-automation">The Voice Agent: AI-Powered Call Automation</h2><p>Your agent logic lives in <code>voice_agent.py</code>. Here’s the real implementation from the repo:</p><pre><code class="language-python">import logging
from typing import Optional, List, Any
from videosdk.agents import Agent

logger = logging.getLogger(__name__)

class VoiceAgent(Agent):
    """An outbound call agent specialized for medical appointment scheduling."""

    def __init__(
        self,
        instructions: str = "You are a medical appointment scheduling assistant. Your goal is to confirm upcoming appointments (5th June 2025 at 11:00 AM) and reschedule if needed.",
        tools: Optional[List[Any]] = None,
        context: Optional[dict] = None,
    ) -&gt; None:
        super().__init__(
            instructions=instructions,
            tools=tools or []
        )
        self.context = context or {}
        self.logger = logging.getLogger(__name__)
        
    async def on_enter(self) -&gt; None:
        self.logger.info("Agent entered the session.")
        initial_greeting = self.context.get(
            "initial_greeting",
            "Hello, this is Neha, calling from City Medical Center regarding your upcoming appointment. Is this a good time to speak?"
        )
        await self.session.say(initial_greeting)

    async def on_exit(self) -&gt; None:
        self.logger.info("Call ended")
</code></pre><p>You can customize instructions, context, and plug in different tools/plugins for STT, TTS, or LLMs.</p><h2 id="the-server-handling-calls-routing-and-agent-sessions">The Server: Handling Calls, Routing, and Agent Sessions</h2><p>The <code>server.py</code> file uses FastAPI to handle incoming SIP webhooks, manage sessions, and glue everything together:</p><pre><code class="language-python">import logging
from fastapi import FastAPI, Request, Form, BackgroundTasks, HTTPException
from fastapi.responses import PlainTextResponse
from config import Config
from models import OutboundCallRequest, CallResponse, SessionInfo
from providers import get_provider
from services import VideoSDKService, SessionManager

logger = logging.getLogger(__name__)

app = FastAPI(
    title="VideoSDK AI Agent Call Server (Modular)",
    description="Modular FastAPI server for inbound/outbound calls with VideoSDK AI Agent using different providers.",
    version="2.0.0"
)

videosdk_service = VideoSDKService()
session_manager = SessionManager()
sip_provider = get_provider("twilio")  # Use your SIP provider

@app.get("/health", response_class=PlainTextResponse)
async def health_check():
    active_sessions = session_manager.get_active_sessions_count()
    return f"Server is healthy. Active sessions: {active_sessions}"

@app.post("/inbound-call", response_class=PlainTextResponse)
async def inbound_call(
    request: Request,
    background_tasks: BackgroundTasks,
    CallSid: str = Form(...),
    From: str = Form(...),
    To: str = Form(...),
):
    logger.info(f"Inbound call received from {From} to {To}. CallSid: {CallSid}")
    try:
        room_id = await videosdk_service.create_room()
        session = await session_manager.create_session(room_id, "inbound")
        background_tasks.add_task(session_manager.run_session, session, room_id)
        sip_endpoint = videosdk_service.get_sip_endpoint(room_id)
        twiml = sip_provider.generate_twiml(sip_endpoint)
        logger.info(f"Responding to {sip_provider.get_provider_name()} inbound call {CallSid} with TwiML to dial SIP: {sip_endpoint}")
        return twiml
    except HTTPException as e:
        logger.error(f"Failed to handle inbound call {CallSid}: {e.detail}")
        return PlainTextResponse(f"&lt;Response&gt;&lt;Say&gt;An error occurred: {e.detail}&lt;/Say&gt;&lt;/Response&gt;", status_code=500)
    except Exception as e:
        logger.error(f"Unhandled error in inbound call {CallSid}: {e}", exc_info=True)
        return PlainTextResponse("&lt;Response&gt;&lt;Say&gt;An unexpected error occurred. Please try again later.&lt;/Say&gt;&lt;/Response&gt;", status_code=500)

@app.post("/outbound-call")
async def outbound_call(request_body: OutboundCallRequest, background_tasks: BackgroundTasks):
    to_number = request_body.to_number
    initial_greeting = request_body.initial_greeting
    logger.info(f"Request to initiate outbound call to: {to_number}")

    if not to_number:
        raise HTTPException(status_code=400, detail="'to_number' is required.")

    try:
        room_id = await videosdk_service.create_room()
        session = await session_manager.create_session(
            room_id, 
            "outbound", 
            initial_greeting
        )
        background_tasks.add_task(session_manager.run_session, session, room_id)
        sip_endpoint = videosdk_service.get_sip_endpoint(room_id)
        twiml = sip_provider.generate_twiml(sip_endpoint)
        call_result = sip_provider.initiate_outbound_call(to_number, twiml)
        logger.info(f"Outbound call initiated via {sip_provider.get_provider_name()} to {to_number}. "
                   f"Call SID: {call_result['call_sid']}. VideoSDK Room: {room_id}")
        return CallResponse(
            message="Outbound call initiated successfully",
            twilio_call_sid=call_result['call_sid'],
            videosdk_room_id=room_id
        )
    except HTTPException as e:
        logger.error(f"Failed to initiate outbound call to {to_number}: {e.detail}")
        raise e
    except Exception as e:
        logger.error(f"Unhandled error initiating outbound call to {to_number}: {e}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Failed to initiate outbound call: {e}")

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000) 
</code></pre><h2 id="modular-providers-services-and-models">Modular Providers, Services, and Models</h2><p>The demo repo is designed to be modular and extensible:</p><ul><li><code>providers/</code> contains code for handling different SIP providers (Twilio, Vonage, etc).</li><li><code>services/</code> manages VideoSDK integration, room/session management, and business logic.</li><li><code>models.py</code> defines request/response data for FastAPI endpoints.</li></ul><p>You can easily add or swap providers, business rules, and AI models</p><h2 id="extending-with-mcp-agent2agent-protocol">Extending with MCP &amp; Agent2Agent Protocol</h2><p>To enable advanced features like agent-to-agent transfer, call control, and real-time management:</p><ul><li>Integrate the <a href="https://docs.videosdk.live/ai_agents/mcp-integration">MCP protocol</a> for call control, muting, and participant management.</li><li>Use the <a href="https://docs.videosdk.live/ai_agents/a2a/overview">Agent2Agent protocol</a> to automate handoffs and workflows between agents.</li></ul><p>You can build on the provided classes and add hooks in your <code>VoiceAgent</code> or session logic to coordinate with these protocols.</p><h2 id="running-and-testing">Running and Testing</h2><ol><li>Use tools like ngrok to expose your server to the public internet for SIP webhooks.</li><li>Configure your SIP provider (e.g., Twilio) to point to your <code>/inbound-call</code> endpoint.</li><li>Trigger inbound or outbound calls and watch your AI agent handle real conversations!</li></ol><p>Start your FastAPI server:</p><pre><code class="language-bash">uvicorn server:app --reload
</code></pre><h2 id="key-takeaways">Key Takeaways</h2><ul><li>This open-source project provides a real, modular foundation for AI-powered telephony using SIP, VoIP, and cloud AI.</li><li>The code is production-grade and extensible—just add your workflows, providers, or AI plugins.</li><li>You can enable advanced call control, routing, A2A communication, and more with VideoSDK protocols.</li></ul><h2 id="resources-next-steps">Resources &amp; Next Steps</h2><ul><li>Explore the <a href="https://github.com/videosdk-community/ai-telephony-demo">ai-telephony-demo repo</a> for the full codebase and more docs.</li><li>Learn more about <a href="https://docs.videosdk.live/ai_agents/introduction">VideoSDK AI Agents</a>, <a href="https://docs.videosdk.live/ai_agents/a2a/overview">A2A</a>, and <a href="https://docs.videosdk.live/ai_agents/mcp-integration">MCP</a>.</li><li>Build your own use case: appointment scheduling, customer service automation, or scalable feedback collection!</li></ul><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><p>Developers building AI telephony agents most often ask about definition, implementation steps, SIP integration, outbound capability, routing mechanics, production requirements, and per-call cost.</p><h3 id="what-is-an-ai-telephony-agent-1">What is an AI telephony agent?</h3><p>An AI telephony agent is a software system that answers or places phone calls over SIP and VoIP while running conversational AI through speech-to-text, a large language model, and text-to-speech. The agent interprets natural language, maintains context across turns, and can execute tools like CRM lookups or appointment scheduling during the call.</p><h3 id="how-do-you-build-an-ai-telephony-agent">How do you build an AI telephony agent?</h3><p>Build an AI telephony agent by setting up a Python project with VideoSDK's agent framework, creating a FastAPI server with inbound and outbound webhook endpoints, configuring a SIP provider like Twilio, and implementing a VoiceAgent class with custom instructions and lifecycle hooks. Expose the server publicly, point your phone number's webhook to the inbound endpoint, and test with real calls.</p><h3 id="what-is-sip-integration-for-voice-ai">What is SIP integration for voice AI?</h3><p>SIP integration for voice AI connects PSTN phone calls to a real-time media room where an AI agent processes audio. Your SIP provider sends a webhook when a call arrives, your server creates a room and returns dial instructions, and the provider bridges the caller's audio into the room where STT, LLM, and TTS handle the conversation.</p><h3 id="can-ai-agents-make-outbound-calls">Can AI agents make outbound calls?</h3><p>Yes, AI agents make outbound calls by accepting a target phone number through an API endpoint, pre-creating the agent session and media room, generating TwiML or SIP dial instructions, and initiating the call through the SIP provider. The agent delivers its greeting the moment the callee answers.</p><h3 id="how-does-inbound-call-routing-work-with-ai">How does inbound call routing work with AI?</h3><p>Inbound call routing with AI starts when the SIP provider sends a webhook to your server with call metadata. Your server creates a real-time room, launches the agent session in a background task, and returns instructions that connect the phone call into the room. The agent handles the conversation from the first ring answer through hangup.</p><h3 id="what-do-you-need-to-run-an-ai-phone-agent-in-production">What do you need to run an AI phone agent in production?</h3><p>Running an AI phone agent in production requires a publicly reachable webhook server, valid SIP trunk credentials, VideoSDK auth tokens, STT/LLM/TTS API keys, error handling for failed sessions, latency optimization across the audio pipeline, TCPA compliance for outbound calls, and human handoff triggers for conversations the AI cannot resolve.</p><h3 id="how-much-does-an-ai-telephony-agent-cost">How much does an AI telephony agent cost?</h3><p>An AI telephony agent costs the sum of SIP trunk minutes, real-time media session minutes, LLM token usage, and TTS synthesis charges. A typical 3-minute call with 10 conversational turns costs approximately $0.05 to $0.15 at published provider rates.</p>]]></content:encoded></item><item><title><![CDATA[How to Build a Voice Agent Using Agent2Agent Protocol (A2A) and MCP]]></title><description><![CDATA[Build an AI voice agent with Agent2Agent (A2A) and MCP. Step-by-step guide to SIP, call automation, and scalable agent-to-agent workflows.]]></description><link>https://www.videosdk.live/blog/ai-voice-agent-a2a-mcp</link><guid isPermaLink="false">685ce7404ec7927e167c88c6</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[#sumit-so]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 14 Jul 2025 08:15:21 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/06/Build-a-Voice-Agent-Using-MCP---A2A-Protocols.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2025/06/Build-a-Voice-Agent-Using-MCP---A2A-Protocols.png" alt="How to Build a Voice Agent Using Agent2Agent Protocol (A2A) and MCP"/><p>What if your AI could do more than just answer questions? What if it could coordinate with other AI Agents, handle bookings, and even trigger workflows in your favorite apps? Let’s build that together, step by step.<br>With the Agent-to-Agent (A2A) protocol and Model Context Protocol (MCP), you can turn your Python conversational agent into a powerful, collaborative system. In this blog, you’ll wire up a full-featured, multi-agent AI stack that:</br></p><ul><li>Speaks with users in real time (Gemini TTS/STT, via the VideoSDK pipeline)</li><li>Delegates work to specialist agents (flight, hotel, email) through the <strong>A2A protocol</strong></li><li>Integrates with external tools and workflows (Zapier, calendars, CRMs) using <strong>MCP</strong></li></ul><p>By following each section and copying the code blocks, you’ll build a working conversational AI orchestration layer—one you can extend for travel automation, email workflows, or any complex, multi-step process.</p><h2 id="why-a2a-and-mcp-matter">Why A2A and MCP Matter</h2><p>Most conversational agents do just one thing. But real-world automation demands <em>collaboration</em>: an agent should delegate, coordinate, and call out to other AIs or SaaS tools. <strong>A2A</strong> lets your agents talk to each other—no more brittle monoliths. <strong>MCP</strong> bridges your agents with the outside world, enabling access to tools, APIs, and automations like Zapier. Together, these protocols make your system modular, scalable, and endlessly extensible.</p><h2 id="prerequisites">Prerequisites</h2>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Requirement</th>
<th>Why you need it</th>
</tr>
</thead>
<tbody>
<tr>
<td>Python 3.10+</td>
<td>Enables <code>asyncio</code> concurrency for agents</td>
</tr>
<tr>
<td>VideoSDK account</td>
<td>Needed for <code>VIDEOSDK_AUTH_TOKEN</code> and meetings</td>
</tr>
<tr>
<td>Google AI Studio key</td>
<td>Powers Gemini speech-to-text &amp; text-to-speech</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h2 id="environment-setup">Environment Setup</h2><p>Let’s get our environment ready:</p><pre><code class="language-bash">python -m venv .venv
source .venv/bin/activate        # (Windows: .venv\Scripts\activate)
pip install videosdk-agents==0.7.* \
            videosdk-plugins-google==0.2.* \
            aiohttp python-dotenv
</code></pre><p>Create a <code>.env</code> file in your project root:</p><pre><code class="language-bash">VIDEOSDK_AUTH_TOKEN=your_videosdk_token
GOOGLE_API_KEY=your_google_api_key
ZAPIER_MCP_SERVER=https://hooks.zapier.com/...   # optional for MCP
</code></pre><h2 id="project-layout">Project Layout</h2><p>Here’s how your folder should look:</p><pre><code class="language-bash">a2a-mcp-agents/
├── agents/
│   ├── email_agent.py
│   ├── flight_agent.py
│   ├── hotel_agent.py
│   └── travel_agent.py
├── session_manager.py
└── main.py
</code></pre><p>Create these folders and files as shown. Each agent gets its own file for clarity.</p><h2 id="building-specialist-agents">Building Specialist Agents</h2><p>Specialist agents run “silently” in the background, waiting for A2A messages from other agents. Here’s how to build them.</p><h3 id="emailagent-agentsemailagentpy">EmailAgent (<code>agents/email_agent.py</code>)</h3><pre><code class="language-python">from videosdk.agents import Agent, AgentCard, A2AMessage
import asyncio

class EmailAgent(Agent):
    """Sends confirmations and updates by email."""

    def __init__(self):
        super().__init__(
            agent_id="agent_email_001",
            instructions="You automate booking confirmations, travel updates, and notifications."
        )

    async def handle_send_booking_email(self, message: A2AMessage):
        email_type  = message.content.get("email_type", "")
        details     = message.content.get("details", "")
        recipient   = message.content.get("recipient", "")
        print(f"[EmailAgent] Sending {email_type} to {recipient}")
        await asyncio.sleep(0.5)  # Simulate I/O
        status = "sent"
        await self.a2a.send_message(
            to_agent="travel_agent_1",
            message_type="email_confirmation",
            content={"status": status, "email_type": email_type}
        )

    async def on_enter(self):
        await self.register_a2a(AgentCard(
            id="agent_email_001",
            name="Email Automation Service",
            domain="email",
            capabilities=["send_confirmations", "send_updates"]
        ))
        self.a2a.on_message("send_booking_email", self.handle_send_booking_email)

    async def on_exit(self):
        await self.unregister_a2a()
</code></pre><h3 id="flightagent-agentsflightagentpy">FlightAgent (<code>agents/flight_agent.py</code>)</h3><pre><code class="language-python">from videosdk.agents import Agent, AgentCard, A2AMessage

class FlightAgent(Agent):
    """Finds and books flights."""

    def __init__(self):
        super().__init__(
            agent_id="agent_flight_001",
            instructions="Provide flight options with prices, times, airline names."
        )

    async def handle_flight_search_query(self, message: A2AMessage):
        dest  = message.content["destination"]
        dates = message.content["dates"]
        email = message.content["customer_email"]
        reply = (f"Flights to {dest} on {dates}:\n"
                 f"1) Direct $299 08:00–11:30\n"
                 f"2) Economy Plus $399 14:15–17:45\n"
                 f"3) Premium Eco $549 18:30–22:00")
        await self.a2a.send_message(
            to_agent="travel_agent_1",
            message_type="flight_booking_response",
            content={"response": reply}
        )
        email_agent = self.a2a.registry.find_agents_by_domain("email")[0]
        await self.a2a.send_message(
            to_agent=email_agent,
            message_type="send_booking_email",
            content={"email_type": "flight_options", "details": reply, "recipient": email}
        )

    async def on_enter(self):
        await self.register_a2a(AgentCard(
            id="agent_flight_001",
            name="Skymate",
            domain="flight",
            capabilities=["search_flights"]
        ))
        self.a2a.on_message("flight_search_query", self.handle_flight_search_query)

    async def on_exit(self):
        await self.unregister_a2a()
</code></pre><h3 id="hotelagent-agentshotelagentpy">HotelAgent (<code>agents/hotel_agent.py</code>)</h3><pre><code class="language-python">from videosdk.agents import Agent, AgentCard, A2AMessage

class HotelAgent(Agent):
    """Finds and books hotels."""

    def __init__(self):
        super().__init__(
            agent_id="agent_hotel_001",
            instructions="Suggest hotels with amenities, price, and location."
        )

    async def handle_hotel_search_query(self, message: A2AMessage):
        dest  = message.content["destination"]
        dates = message.content["dates"]
        email = message.content["customer_email"]
        reply = (f"Hotels in {dest} for {dates}:\n"
                 f"1) Grand Plaza $180/night\n"
                 f"2) Comfort Inn $120/night\n"
                 f"3) Luxury Resort $350/night")
        await self.a2a.send_message(
            to_agent="travel_agent_1",
            message_type="hotel_booking_response",
            content={"response": reply}
        )
        email_agent = self.a2a.registry.find_agents_by_domain("email")[0]
        await self.a2a.send_message(
            to_agent=email_agent,
            message_type="send_booking_email",
            content={"email_type": "hotel_options", "details": reply, "recipient": email}
        )

    async def on_enter(self):
        await self.register_a2a(AgentCard(
            id="agent_hotel_001",
            name="Hotel Booker",
            domain="hotel",
            capabilities=["search_hotels"]
        ))
        self.a2a.on_message("hotel_search_query", self.handle_hotel_search_query)

    async def on_exit(self):
        await self.unregister_a2a()
</code></pre><h2 id="orchestrator-agent-travelagent">Orchestrator Agent: TravelAgent</h2><p>The <strong>TravelAgent</strong> is your “voice” agent. It listens to the user, delegates tasks to other agents using A2A, and (optionally) reaches out to external tools through MCP.</p><p><code>agents/travel_agent.py</code>:</p><pre><code class="language-python">from videosdk.agents import Agent, function_tool, AgentCard, A2AMessage, MCPServerHTTP
import asyncio, os
from typing import Dict, Any

class TravelAgent(Agent):
    def __init__(self):
        zapier_url = os.getenv("ZAPIER_MCP_SERVER", "")
        super().__init__(
            agent_id="travel_agent_1",
            instructions="Book complete trips: flights, hotels, emails.",
            mcp_servers=[MCPServerHTTP(url=zapier_url)] if zapier_url else []
        )

    @function_tool
    async def book_travel_package(self, destination: str, travel_dates: str, email: str) -&gt; Dict[str, Any]:
        await self.session.say(f"Looking up options for {destination}…")
        for _ in range(3):
            flights = self.a2a.registry.find_agents_by_domain("flight")
            hotels  = self.a2a.registry.find_agents_by_domain("hotel")
            if flights and hotels:
                break
            await asyncio.sleep(2)
        await self.a2a.send_message(flights[0], "flight_search_query",
                                    {"destination": destination, "dates": travel_dates, "customer_email": email})
        await self.a2a.send_message(hotels[0], "hotel_search_query",
                                    {"destination": destination, "dates": travel_dates, "customer_email": email})
        return {"status": "processing"}

    async def handle_flight_response(self, msg: A2AMessage):
        await self.session.say(f"Flight update: {msg.content['response']}")

    async def handle_hotel_response(self, msg: A2AMessage):
        await self.session.say(f"Hotel update: {msg.content['response']}")

    async def handle_email_confirm(self, msg: A2AMessage):
        await self.session.say("Confirmation email sent.")

    async def on_enter(self):
        await self.register_a2a(AgentCard(
            id="travel_agent_1",
            name="Travel Coordinator",
            domain="travel",
            capabilities=["travel_planning"]
        ))
        self.a2a.on_message("flight_booking_response", self.handle_flight_response)
        self.a2a.on_message("hotel_booking_response", self.handle_hotel_response)
        self.a2a.on_message("email_confirmation",     self.handle_email_confirm)
        await self.session.say("Hello! Where would you like to travel?")

    async def on_exit(self):
        await self.unregister_a2a()
</code></pre><h2 id="wiring-it-all-together">Wiring It All Together</h2><p><code>session_manager.py</code>:</p><pre><code class="language-python">import os, asyncio
from videosdk.agents import AgentSession, RealTimePipeline
from videosdk.plugins.google import GeminiRealtime, GeminiLiveConfig
from google.genai.types import Modality
from agents.travel_agent import TravelAgent
from agents.flight_agent  import FlightAgent
from agents.hotel_agent   import HotelAgent
from agents.email_agent   import EmailAgent

def make_voice_pipeline() -&gt; RealTimePipeline:
    return RealTimePipeline(
        model=GeminiRealtime(
            model="gemini-2.0-flash-exp",
            api_key=os.environ["GOOGLE_API_KEY"],
            config=GeminiLiveConfig(voice="Aoede", response_modalities=[Modality.AUDIO]),
        )
    )

def make_text_pipeline() -&gt; RealTimePipeline:
    return RealTimePipeline(
        model=GeminiRealtime(
            model="gemini-2.0-flash-exp",
            api_key=os.environ["GOOGLE_API_KEY"],
            config=GeminiLiveConfig(response_modalities=[Modality.TEXT]),
        )
    )

async def create_room() -&gt; str:
    import aiohttp
    async with aiohttp.ClientSession() as s:
        async with s.post(
            "https://api.videosdk.live/v2/rooms",
            headers={"Authorization": os.environ["VIDEOSDK_AUTH_TOKEN"], "Content-Type": "application/json"},
        ) as r:
            return (await r.json())["roomId"]

async def start_agents(room_id: str):
    # context.playground = True lets us test in the web UI
    travel = AgentSession(TravelAgent(), make_voice_pipeline(),
                          {"meetingId": room_id, "join_meeting": True, "playground": True})
    flight  = AgentSession(FlightAgent(),  make_text_pipeline(), {"join_meeting": False, "playground": True})
    hotel   = AgentSession(HotelAgent(),   make_text_pipeline(), {"join_meeting": False, "playground": True})
    email   = AgentSession(EmailAgent(),   make_text_pipeline(), {"join_meeting": False, "playground": True})

    await asyncio.gather(flight.start(), hotel.start(), email.start())
    await asyncio.sleep(3)     # allow registry
    await travel.start()
</code></pre><h2 id="application-entry-point">Application Entry Point</h2><p><code>main.py</code>:</p><pre><code class="language-python">#!/usr/bin/env python3
import asyncio, os, signal
from session_manager import create_room, start_agents

def validate_env():
    for var in ("VIDEOSDK_AUTH_TOKEN", "GOOGLE_API_KEY"):
        if var not in os.environ:
            raise RuntimeError(f"{var} is not set")

async def main():
    validate_env()
    room = await create_room()
    print(f"Meeting room created: {room}")
    loop = asyncio.get_running_loop()
    loop.add_signal_handler(signal.SIGINT, loop.stop)
    await start_agents(room)

if __name__ == "__main__":
    asyncio.run(main())
</code></pre><h2 id="try-it-in-the-videosdk-agents-playground">Try It in the VideoSDK Agents Playground</h2><p>When the <strong>TravelAgent</strong> session starts (with <code>playground: True</code> in the context), VideoSDK prints a link like:</p><pre><code class="language-bash">Agent started in playground mode
Interact with agent here at:
https://playground.videosdk.live?token=&lt;auth_token&gt;&amp;meetingId=&lt;meeting_id&gt;</code></pre><p>Open that link in Chrome, give microphone access, and start talking:</p><pre><code class="language-bash">You: I’d like to book a flight to Tokyo next month.
Agent: Looking up options for Tokyo…
Agent: Flight update: Flights to Tokyo on 2025-08-03…
Agent: Hotel update: Hotels in Tokyo…
Agent: Confirmation email sent.</code></pre><ul><li>Hear the agent respond in real time using Gemini TTS.</li><li>Watch as A2A messages coordinate between your specialist agents.</li><li>No client app needed—just use the web playground!</li></ul><blockquote><strong>Tip:</strong> The playground mode is for testing and debugging. Disable <code>playground: True</code> in production for a secure, scalable agent deployment.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li><strong>A2A</strong> enables true agent collaboration, not just single-bot workflows.</li><li><strong>MCP</strong> opens the door to external tools and SaaS integrations.</li><li><strong>VideoSDK Agents Playground</strong> makes it easy to iterate, test, and show off your whole multi-agent system.</li><li>With just a handful of Python files, you can stand up a fully working, extensible, <em>open source</em> conversational AI.</li></ul><p>Now go build your own network of specialist agents—and let them do the heavy lifting for your users and your business!</p>]]></content:encoded></item><item><title><![CDATA[Introducing "NAMO" Real-Time Speech AI Model: On-Device & Hybrid Cloud]]></title><description><![CDATA[NAMO real-time speech AI model is VideoSDK's open-source SSLM with hybrid on-device and cloud inference for low-latency, privacy-first voice agents. Compare architectures, integrate via Agent SDK, and avoid production pitfalls.]]></description><link>https://www.videosdk.live/blog/introducing-namo-real-time-speech-ai-model-on-device-hybrid-cloud</link><guid isPermaLink="false">67dba8584556210426689c2f</guid><category><![CDATA[ANNOUNCEMENT]]></category><dc:creator><![CDATA[Arjun Kava]]></dc:creator><pubDate>Fri, 21 Mar 2025 07:00:00 GMT</pubDate><content:encoded><![CDATA[<p>At VideoSDK, Our mission is to build infrastructure of digital humans that runs on every device. We’re expanding into real-time speech-to-speech and vision AI agents that run privately on-device or in a hybrid cloud setting—delivering up to 98% of GPT-4’s accuracy at just 17.5% of its cost.</p><h2 id="unified-sdk-for-on-device-sslm-cloud-sslm-collaboration">Unified SDK for On-Device SSLM + Cloud SSLM Collaboration </h2><p>Today, we are launching NAMO-SSLM (Small Speech Language Model) hybrid model with state of the art hybrid inferencing engine. </p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/03/Model-Diagram-V3.jpg" class="kg-image" alt="" loading="lazy" width="645" height="160"/></figure><p>Unified SDK for On-Device SSLM + Cloud SSLM </p><p>We’ve developed an inference engine that couples a streamlined, on-device  with a more powerful, cloud-based SSLM, working in tandem for real-time speech use cases. Our engine ensures that most of the heavy lifting—long-context processing and advanced reasoning—occurs only when needed, thereby reducing cloud inference costs without sacrificing performance.</p>
<!--kg-card-begin: html-->
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/CFQFkwWc-XQ?si=4EH-8klYJ663bfb2" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<p>We’ve tackled three key challenges in end-to-end speech models: enabling multi-turn <a href="https://docs.videosdk.live/ai_agents/core-components/rag" rel="noreferrer">RAG</a> for rich contextual responses, silent function calling for real-time tool use without delays, and client-side tool support like canvas and whiteboard via our Agent SDK.</p><h2 id="achieving-20%C3%97-cost-reduction-with-98-cloud-performance"><strong>Achieving 20× Cost Reduction with 98% Cloud Performance</strong></h2><p>Our engine orchestrates a local-remote workflow, delivering real-time speech capabilities on low-latency devices while leveraging cloud infrastructure for complex tasks. This results in a 20× cost reduction while maintaining 98% of cloud performance, ensuring a cost-effective, privacy-friendly, and high-performance solution.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2025/03/NAMO-SSLM-Device---Cloud.png" class="kg-image" alt="" loading="lazy" width="1920" height="1080"><figcaption><span style="white-space: pre-wrap;">Cost Vs Accuracy Tradeoff</span></figcaption></img></figure><h2 id="enterprise-grade-privacy-compliance">Enterprise-Grade Privacy &amp; Compliance</h2><p>NAMO-SSLM keeps sensitive data on-device by default, ensuring documents and conversations never leave the device unless explicitly required. This hybrid design minimizes cloud dependency, reduces risk exposure, and delivers GDPR, HIPAA, and SOC2 compliance—making it more secure and privacy-first than traditional cloud-only models.</p><p>This approach not only meets the pressing need for robust compliance in highly regulated sectors like BFSI and Healthcare, but also benefits any organization demanding rapid, private, and cost-effective AI-driven customer experiences.</p><h2 id="open-sourcing-namo-sslm">Open Sourcing NAMO-SSLM</h2><p>We are excited to open-source <strong>NAMO-SSLM</strong>, small yet powerful real-time multi-modal. The AI landscape is shifting from massive, resource-intensive models to lightweight, optimized small models—and for good reason. Small models (like NAMO-SSLM) offer a compelling mix of efficiency, speed, and cost-effectiveness, making them the smarter choice for real-world applications.</p><p>Key research includes:</p><ul><li><strong>Run on CPU</strong>: Run model real-time on consumer CPU devices.</li><li><strong>Multimodal (voice + vision)</strong>: Native support for real-time speech and vision and OCR capabilites.</li><li><strong>Low Latency, Real-Time Processing</strong>: Real-time streaming support with end to end latency as low as 80ms.</li><li><strong>Multilingual Support</strong>: Enable multi-lang and hybrid language capabilities such as hing-lish. </li><li><strong>Multi-turn RAG</strong>: Supports multi-turn RAG to retrive rich context from while keeping conversation  real-time</li><li><strong>Voiced + Silent Function / Tools Calling</strong>: Function calling support with silent voice with text as well as voice output. </li><li><strong>Client Side Tool Support</strong>: Tool support for building client side UI/UX such as canvas, whiteboard etc. </li></ul>
<!--kg-card-begin: html-->
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/mq-2R7hjQL4?si=aQzz5ZBxq9X0cYgT" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<p/>
<!--kg-card-begin: html-->
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/WKydRV85MOc?si=jUQrSE1MVcno_yBy" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<p/>
<!--kg-card-begin: html-->
<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/YD853cGuc78?si=HQDoE9mipF-13ezv" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen=""/>
<!--kg-card-end: html-->
<p><strong>NAMO-SSLM Github</strong>:  <a href="https://github.com/videosdk-live/namo-sslm">https://github.com/videosdk-live/namo-sslm</a></p><p>The future of AI is efficient, real-time, and accessible on every device. With NAMO-SSLM, we're pioneering a hybrid on-device + cloud approach that delivers 5.7× cost efficiency while maintaining 98% of cloud-level performance.</p><p>Our hybrid architecture enables low-latency, private AI for a wide range of industries:</p><ul><li><strong>Healthcare</strong> – Real-time AI assistants for clinical support</li><li><strong>Banking</strong> – Secure and seamless voice authentication</li><li><strong>Insurance</strong> – AI-powered automated claims processing</li><li><strong>Social</strong> – Instant multilingual voice translation</li><li><strong>Education</strong> – Personalized AI tutors for interactive learning</li><li><strong>Smart Glasses</strong> – Hands-free, AI-driven digital assistants</li><li><strong>Robots</strong> – Conversational AI for intelligent automation</li><li><strong>Gaming</strong> – Realistic, AI-powered NPC interactions</li></ul><p>By open-sourcing NAMO-SSLM, we are empowering developers and businesses to build privacy-first, low-latency AI applications across industries—from healthcare to gaming, smart glasses to education.</p><p>The AI revolution is shifting from large, resource-heavy models to lightweight, real-time, multimodal intelligence. NAMO-SSLM is the future—blending speech and vision AI with real-time processing, multilingual capabilities, and CPU-optimized performance.</p><p>Join us in <strong>building the next generation of digital humans.</strong> 🚀</p><p><a href="https://jobs.videosdk.live/forms/c0d46e347e2171b19b0bc2227031030e612ce9506bba525a4890df1751d4eb6e">Apply now</a></p>]]></content:encoded></item><item><title><![CDATA[HIPAA-Compliant Video Conferencing API: What is BAA & How to build a Compliant Telehealth Call]]></title><description><![CDATA[A HIPAA compliant video conferencing API encrypts all PHI in transit, signs a Business Associate Agreement, and enforces session-scoped access controls. Learn the technical requirements and how to integrate one.]]></description><link>https://www.videosdk.live/blog/hipaa-compliant-video-conferencing-api</link><guid isPermaLink="false">6638814320fab018df10e49e</guid><category><![CDATA[TeleHealth]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Fri, 31 Jan 2025 05:10:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2026/09/ChatGPT-Image-Sep-7--2026--07_18_18-PM.png" medium="image"/><content:encoded><![CDATA[<blockquote>A HIPAA compliant video API is a real-time communication layer that encrypts video, audio, and signaling in transit, keeps no Protected Health Information by default, enforces session-scoped access controls with audit logging, and is backed by a signed Business Associate Agreement (BAA). VideoSDK provides this through TLS and SRTP encryption, JWT-based access, zero default storage, and a BAA add-on on Pay-As-You-Go and Enterprise plans.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/ChatGPT-Image-Sep-7--2026--07_18_18-PM.png" alt="HIPAA-Compliant Video Conferencing API: What is BAA & How to build a Compliant Telehealth Call"/><p>Every month, the U.S. Department of Health and Human Services (HHS) Office for Civil Rights (OCR) adds to its list of healthcare organizations penalized for exposing Protected Health Information (PHI). According to HIPAA Journal's enforcement tracker, OCR imposed 21 financial penalties in 2025, and 789 large breaches affecting roughly 138.5 million people were reported that year. The developer building a telehealth product does not set out to appear on that list. They set out to ship a video consultation feature.</p><p>The problem is that a standard WebRTC video API does not make a product <a href="https://docs.videosdk.live/help_docs/security-and-privacy/hipaa" rel="noreferrer">HIPAA compliant</a>. Compliance requires a specific combination of encryption, access control, audit logging, contractual agreements, and data handling policies. Choosing the wrong API at the start means retrofitting security later, a process that typically costs more than doing it correctly at integration time.</p><p>This article explains what HIPAA actually requires of a video platform, what a BAA covers and what it does not, how encryption and recording rules apply to real-time video, how HIPAA compliant video conferencing platforms compare with building on an API, and what a compliant telehealth call looks like in architecture and code using <a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a>.</p><h2 id="what-is-hipaa">What Is HIPAA?</h2><p>HIPAA is the Health Insurance Portability and Accountability Act, a U.S. federal law enacted in 1996 that sets national standards for protecting individually identifiable health information, known as <a href="https://www.hhs.gov/answers/hipaa/what-is-phi/index.html" rel="noreferrer">Protected Health Information (PHI)</a>.</p><p>Three HIPAA rules matter for a video product. The Privacy Rule governs how PHI may be used and disclosed. The Security Rule (45 CFR Part 164, Subpart C) sets administrative, physical, and technical safeguards for electronic PHI (ePHI). The Breach Notification Rule (45 CFR Part 164, Subpart D) sets the timelines for reporting a breach. Any organization that handles PHI, including healthcare providers, health plans, and technology vendors acting on their behalf, must comply.</p><h2 id="what-is-a-hipaa-compliant-video-api">What is a HIPAA Compliant Video API?</h2><p>A <a href="https://www.videosdk.live/solutions/telehealth" rel="noreferrer">HIPAA compliant video API</a> is defined as a programmable communication layer that satisfies the administrative, physical, and technical safeguard requirements of the HIPAA Security Rule when handling Protected Health Information during video sessions.</p><p>A standard video API works by establishing a server-mediated WebRTC session, routing audio and video streams between participants, and handling session signaling. A HIPAA compliant video API works by adding three layers on top of that baseline: cryptographic protection of all streams and metadata, role-based access controls that enforce least-privilege session access, and formal legal accountability through a Business Associate Agreement between the API vendor and the healthcare organization.</p><p>HIPAA governs any organization that is a "covered entity" (healthcare providers, health plans, and healthcare clearinghouses) or a "business associate" (any vendor that creates, receives, maintains, or transmits PHI on behalf of a covered entity). A video API vendor becomes a business associate the moment its infrastructure carries or stores any PHI, including session metadata that could identify a patient. VideoSDK operates as a business associate under its BAA, encrypts media with SRTP and signaling with TLS, and stores no audio, video, or screen-share data unless the customer explicitly turns on recording. See the <a href="https://docs.videosdk.live/help_docs/security-and-privacy/hipaa">VideoSDK HIPAA compliance documentation</a> for the current control list.</p><p>The same requirements apply whether the product is described as HIPAA compliant <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">video conferencing</a>, HIPAA compliant video chat, or a HIPAA compliant video call inside a mobile app. The label changes with the interface; the safeguards do not.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/09/hippa-1.webp" class="kg-image" alt="HIPAA-Compliant Video Conferencing API: What is BAA & How to build a Compliant Telehealth Call" loading="lazy" width="1536" height="1024"/></figure><h2 id="what-hipaa-actually-requires-of-a-video-platform">What HIPAA Actually Requires of a Video Platform</h2><p>HIPAA compliance is not a certification badge; it is a set of enforceable rules. Any video API used in a healthcare context must satisfy requirements across three domains of the Security Rule, and the checklist below maps each to the regulation.</p><h3 id="technical-safeguards-45-cfr-164312">Technical Safeguards (45 CFR 164.312)</h3><p>The Security Rule's technical safeguards, at <a href="https://www.ecfr.gov/current/title-45/subtitle-A/subchapter-C/part-164/subpart-C/section-164.312">45 CFR 164.312</a>, specify what a system handling ePHI must do:</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Safeguard</th>
<th>What the regulation requires</th>
<th>What it means for a video API</th>
</tr>
</thead>
<tbody>
<tr>
<td>Access control, 164.312(a)</td>
<td>Unique user identification, emergency access, automatic logoff, encryption and decryption</td>
<td>Per-participant tokens scoped to one session, expiring after it ends; roles that separate provider from patient permissions</td>
</tr>
<tr>
<td>Audit controls, 164.312(b)</td>
<td>Mechanisms that record and examine activity in systems containing ePHI</td>
<td>Session and participant event logs: who joined, when, from where, for how long, delivered by webhook to your own log store</td>
</tr>
<tr>
<td>Integrity, 164.312(c)</td>
<td>Protection of ePHI from improper alteration or destruction</td>
<td>SRTP authentication tags on every media packet; signed webhooks so your backend can verify events</td>
</tr>
<tr>
<td>Person or entity authentication, 164.312(d)</td>
<td>Verify that the person seeking access is who they claim to be</td>
<td>Your identity provider authenticates the user; the video token is minted only after that check</td>
</tr>
<tr>
<td>Transmission security, 164.312(e)</td>
<td>Integrity controls and encryption for ePHI in transit</td>
<td>TLS 1.2 or higher for signaling, DTLS-SRTP for media key exchange, SRTP for media</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>A token-based system using <a href="https://www.geeksforgeeks.org/web-tech/json-web-token-jwt/" rel="noreferrer">JSON Web Tokens</a> (JWT, defined in <a href="https://www.rfc-editor.org/rfc/rfc7519">RFC 7519</a>) satisfies the access-control specification when tokens are scoped to specific sessions and cannot be reused. VideoSDK issues session-scoped JWTs with role-based permissions, which is how least-privilege access is enforced.</p><h3 id="administrative-safeguards-45-cfr-164308">Administrative Safeguards (45 CFR 164.308)</h3><p>The most operationally significant administrative requirement, at <a href="https://www.ecfr.gov/current/title-45/subtitle-A/subchapter-C/part-164/subpart-C/section-164.308">45 CFR 164.308(b)</a>, is the business associate contract. A covered entity may permit a business associate to handle ePHI only with satisfactory assurances, documented in a BAA, that the vendor will safeguard it. Operating a telehealth product without a signed BAA from every vendor in the data path is a HIPAA violation on its own, regardless of how strong the encryption is.</p><p>Section 164.308 also requires a documented risk analysis and risk management process. OCR's 2025 enforcement actions were dominated by risk-analysis failures, according to law-firm summaries of the year's settlements, so a video vendor's security documentation should feed directly into your own risk analysis file.</p><h3 id="physical-safeguards-45-cfr-164310">Physical Safeguards (45 CFR 164.310)</h3><p>For a cloud-based video API, the physical safeguards at <a href="https://www.ecfr.gov/current/title-45/subtitle-A/subchapter-C/part-164/subpart-C/section-164.310">45 CFR 164.310</a> translate to data-center controls: restricted physical access, network isolation between customers, and secure disposal of storage media. Healthcare organizations cannot audit these directly, which is why SOC 2 Type II and ISO 27001 reports serve as the accepted proxy. VideoSDK publishes SOC 2 Type II, ISO 27001, GDPR, HIPAA, and CERT-In on its <a href="https://www.videosdk.live/security">security page</a>.</p><h3 id="what-hhs-says-about-telehealth-technology-specifically">What HHS says about telehealth technology specifically</h3><p>HHS's own guidance at <a href="https://telehealth.hhs.gov/providers/telehealth-policy/hipaa-for-telehealth-technology">telehealth.hhs.gov</a> states that providers must use vendors that comply with the HIPAA Rules and will sign a BAA for their video communication products. The COVID-era enforcement discretion that allowed FaceTime, Skype, and consumer Zoom for telehealth <a href="https://www.hhs.gov/hipaa/for-professionals/special-topics/emergency-preparedness/notification-enforcement-discretion-telehealth/index.html">ended on May 11, 2023</a>. Public-facing tools such as Facebook Live and TikTok were never permitted.</p><h3 id="the-2025-proposed-security-rule-update">The 2025 proposed Security Rule update</h3><p>On January 6, 2025, HHS published a <a href="https://www.federalregister.gov/documents/2025/01/06/2024-30983/hipaa-security-rule-to-strengthen-the-cybersecurity-of-electronic-protected-health-information">proposed rule</a> that would make encryption of ePHI at rest and in transit a required specification rather than an addressable one, mandate multi-factor authentication, and remove the required-versus-addressable distinction almost entirely. As of September 2026 no final rule has been issued, and OMB's regulatory agenda targets July 2027 for final action. A video API that already encrypts everything and supports MFA-gated token issuance is positioned for the change; one that treats encryption as optional is not.</p><h2 id="what-a-baa-covers-and-what-it-does-not">What a BAA Covers and What It Does Not</h2><p>A Business Associate Agreement makes the video vendor legally accountable for the PHI it touches, but it does not make your application compliant on its own.</p><p>A BAA is a legally binding contract between a covered entity and its technology vendor. Under 45 CFR 164.504(e), it must define the permitted uses and disclosures of PHI, require the vendor to implement Security Rule safeguards, require breach reporting to the covered entity, flow the same obligations down to the vendor's subcontractors, and require return or destruction of PHI at termination.</p><p><strong>What a video API BAA covers:</strong> the vendor's media servers, signaling, session metadata, recording pipeline, and support staff access. It commits the vendor to the technical safeguards above and to notifying you of a breach.</p><p><strong>What a video API BAA does not cover:</strong> your application code, your database, your identity provider, your cloud storage bucket, patient consent capture, your own staff's access to recordings, and any other vendor in the data path (EHR, scheduling, analytics, error tracking). Each of those needs its own BAA or must be kept out of the PHI path entirely.</p><p><strong>Who signs and at what price:</strong> vendors differ sharply on BAA availability, and this is where evaluations go wrong. VideoSDK offers HIPAA compliance and a BAA as an add-on on Pay-As-You-Go and Enterprise plans, activated from the Dashboard under Billing -&gt; Add-ons; pricing is custom and quoted by sales, and BAA requests and security documentation go to security@videosdk.live. Daily charges $500 per month for its healthcare add-on. Whereby Embedded lists a $16.99 per month HIPAA add-on on its Build plan and includes it on Enterprise. Twilio signs a BAA only for Security Edition or Enterprise Edition accounts. Zoom Video SDK requires a qualifying paid plan and a signed BAA on request. Vonage has a long-standing HIPAA tier priced through sales. Confirm each figure on the vendor's page before budgeting; the point is that a BAA is rarely free and sometimes unavailable at the tier you planned to use.</p><h2 id="encryption-in-transit-at-rest-and-the-end-to-end-question">Encryption: In Transit, at Rest, and the End-to-End Question</h2><p>Encryption in transit is required for a HIPAA compliant video API; end-to-end encryption is not required by HIPAA, and most multi-party video is not end-to-end encrypted.</p><h3 id="in-transit">In transit</h3><p>WebRTC media is protected by SRTP, the Secure Real-time Transport Protocol defined in <a href="https://www.rfc-editor.org/rfc/rfc3711">RFC 3711</a>, with keys negotiated over DTLS as specified in <a href="https://www.rfc-editor.org/rfc/rfc5764">RFC 5764</a>. Signaling, the session setup and join and leave messages, travels over TLS. The <a href="https://www.w3.org/TR/webrtc/">W3C WebRTC specification</a> makes this encryption mandatory; a WebRTC endpoint cannot send unencrypted media. VideoSDK encrypts media with SRTP and signaling with TLS, using AES-128 and AES-256 cipher suites. What differs between vendors is whether metadata and chat are also encrypted and whether the vendor publishes its cipher configuration.</p><h3 id="at-rest">At rest</h3><p>Live video that is never recorded is never at rest. The moment recording is enabled, the file is PHI at rest and must be encrypted. With VideoSDK, recordings are written directly to the customer's own AWS S3, Azure Blob, or GCP bucket using write-only credentials, so at-rest encryption is enforced by the bucket's server-side encryption (AES-256 on S3 SSE) and the customer's key management, not by a shared vendor store.</p><h3 id="the-end-to-end-question">The end-to-end question</h3><p>Multi-party calls routed through a<a href="https://www.videosdk.live/blog/sfu-vs-mcu-vs-mesh-webrtc" rel="noreferrer"> Selective Forwarding Unit (SFU)</a> are not end-to-end encrypted by default. The SFU terminates each participant's SRTP session and re-encrypts media toward the other participants, which means the media server can, in principle, access decrypted frames. This is true of every SFU-based provider, including VideoSDK, Zoom, Daily, and Agora, and it is why the BAA and the vendor's access controls matter as much as the cipher.</p><p>HIPAA does not require end-to-end encryption. The Security Rule requires transmission security and treats the encryption mechanism as addressable, which under the 2025 proposed rule would become required but still without a mandate for E2EE. VideoSDK offers optional end-to-end encryption using <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> insertable frames, in shared-key or per-participant-key modes, documented in the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/security/E2EE">E2EE guide</a>. When E2EE is enabled, server-side recording and transcription are not available, because the server cannot decrypt the media to process it. Choose E2EE when the threat model requires that the vendor never hold plaintext; choose SFU encryption with a BAA when you need recording. For a deeper treatment, see <a href="https://www.videosdk.live/blog/what-is-end-to-end-encryption-e2ee">What is end-to-end encryption and how it secures video calls</a>.</p><h2 id="hipaa-compliant-video-recording-rules">HIPAA Compliant Video Recording Rules</h2><p>Recording a telehealth session is permitted under HIPAA when four conditions are met: consent, encryption, restricted access, and a retention policy.</p><ol><li><strong>Consent.</strong> HIPAA itself does not mandate consent for a provider to record a session as part of treatment, but state wiretap and recording laws do, and eleven U.S. states require all-party consent. Capture consent in the application before recording starts and log it.</li><li><strong>Bring your own bucket.</strong> Recordings should land in storage you control. VideoSDK's recording API accepts a storage configuration for AWS S3, Azure Blob, or GCP Cloud Storage; VideoSDK uploads with write-only access and cannot read the bucket. See <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/recording-and-live-streaming/record-meeting">Record a meeting</a> and <a href="https://docs.videosdk.live/docs/tutorials/user-dashboard/recording-storage-config">Configure recording storage</a>.</li><li><strong>Encryption and access.</strong> Enable server-side encryption, block public access, restrict IAM roles to the clinical application, and turn on access logging so that every read of a recording is auditable under 164.312(b).</li><li><strong>Retention and disposal.</strong> HIPAA requires that documentation be retained for six years, but that applies to policies and compliance records, not automatically to session video. State medical-record laws set retention for clinical content. Define a retention period, enforce it with a bucket lifecycle rule, and document the disposal method.</li></ol><p>Individual-track recording and composite recording both remain available in VideoSDK's HIPAA mode. Post-call transcription and AI-generated summaries do not, because they route audio to additional processors; if you need transcripts, generate them in your own HIPAA-aligned pipeline from the recording in your bucket.</p><h2 id="gdpr-compliant-video-conferencing">GDPR Compliant Video Conferencing</h2><p>If any patient or clinician is in the European Union, the same video product must also satisfy the General Data Protection Regulation, and the controls overlap with HIPAA but are not identical.</p><p><strong>Lawful basis.</strong> Under GDPR Article 6 and, for health data, Article 9, processing needs a lawful basis such as the provision of healthcare under Article 9(2)(h) or explicit consent. Record the basis in your records of processing.</p><p><strong>Data Processing Agreement.</strong> GDPR Article 28 requires a DPA between controller and processor, the GDPR analog of the BAA. VideoSDK provides a DPA on request through security@videosdk.live, and offers GDPR compliance as a Dashboard add-on with custom pricing.</p><p><strong>Data residency.</strong> VideoSDK's geo-fencing restricts media routing to a chosen region; the documented regions are USA, Europe, India, UAE, Singapore, and Australia, and the feature is available on Enterprise plans. Pinning EU sessions to the Europe region keeps media inside the EU, which simplifies the transfer analysis under Chapter V. The docs note that pinning a region far from the user degrades call quality, so use it for compliance rather than as a default.</p><p><strong>Retention and rights.</strong> GDPR adds data-subject rights (access, erasure, portability) and storage limitation. Because VideoSDK stores no media by default and recordings sit in your bucket, erasure requests are handled in your own storage rather than through a vendor ticket.</p><h2 id="hipaa-compliant-video-conferencing-platforms-vs-building-on-an-api">HIPAA Compliant Video Conferencing Platforms vs Building on an API</h2><p>Finished HIPAA compliant video conferencing platforms suit practices that need a room today; a HIPAA compliant video API suits companies whose product is the telehealth experience.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Option</th>
<th>Type</th>
<th>BAA availability</th>
<th>Published cost</th>
<th>Best for</th>
</tr>
</thead>
<tbody>
<tr>
<td>Doxy.me</td>
<td>Finished telehealth platform</td>
<td>Signed on all plans, including free</td>
<td>Free; Professional $35 and Clinic $50 per user per month</td>
<td>Solo practitioners and small clinics</td>
</tr>
<tr>
<td>Zoom for Healthcare</td>
<td>Finished meeting platform</td>
<td>On paid healthcare tier, on request</td>
<td>Per-host, from roughly $15 to $20 per month, quotes above</td>
<td>Practices already standardized on Zoom</td>
</tr>
<tr>
<td>Google Meet (Workspace)</td>
<td>Suite-bundled meeting tool</td>
<td>Business Associate Addendum on paid Workspace</td>
<td>Included in paid Workspace plans</td>
<td>Organizations on Google Workspace</td>
</tr>
<tr>
<td>Apple FaceTime</td>
<td>Consumer app</td>
<td>No BAA offered</td>
<td>Free</td>
<td>Not permitted for PHI</td>
</tr>
<tr>
<td>VideoSDK</td>
<td>Video API and SDKs</td>
<td>Add-on on Pay-As-You-Go and Enterprise</td>
<td>Custom-priced add-on plus usage from $0.004 per participant-minute HD</td>
<td>Telehealth products across web and mobile needing recording, whiteboard, SIP</td>
</tr>
<tr>
<td>Daily</td>
<td>Video API</td>
<td>Healthcare add-on</td>
<td>$500 per month plus $0.004 per participant-minute</td>
<td>Prototypes and web-first telehealth</td>
</tr>
<tr>
<td>Whereby Embedded</td>
<td>Iframe video API</td>
<td>Add-on on Build, included on Enterprise</td>
<td>$16.99 per month add-on plus $0.004 per participant-minute</td>
<td>Small teams embedding a simple room</td>
</tr>
<tr>
<td>Twilio Video</td>
<td>Video API</td>
<td>Security or Enterprise Edition only</td>
<td>Enterprise contract plus $0.004 per participant-minute</td>
<td>Existing Twilio customers</td>
</tr>
<tr>
<td>Vonage Video API</td>
<td>Video API</td>
<td>HIPAA tier via sales</td>
<td>$0.0041 per participant-minute up to 25 publishers</td>
<td>Regulated enterprises already on Vonage</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p><em>Prices and BAA terms from each vendor's pricing or compliance page, September 2026. All are subject to change.</em></p><p><strong>Choose a finished platform when</strong> clinicians need a link that works today, the video session is not your product, and you can live inside the vendor's interface and feature set.</p><p><strong>Choose an API when</strong> the consultation must happen inside your own app under your brand, you need to control the waiting room, the intake flow, and the recording pipeline, you integrate with an EHR or scheduling system programmatically, or you serve web and mobile from one backend. The trade is engineering time: with an API you own the compliance configuration described in the next section.</p><h2 id="reference-architecture-for-a-compliant-telehealth-call">Reference Architecture for a Compliant Telehealth Call</h2><p>A compliant telehealth call on VideoSDK has four components you build and one you rent: an authenticated token server, role-scoped access, an audit log fed by webhooks, recording to your own bucket, and VideoSDK's encrypted media infrastructure under a BAA.</p><p>The flow: your identity provider authenticates the clinician or patient (with MFA for clinicians). Your backend mints a short-lived, role-scoped VideoSDK token and creates a room for the appointment. Both clients join over TLS and SRTP. VideoSDK sends session events to your webhook endpoint, where you write an audit record. If the clinician starts recording, the file uploads directly to your encrypted bucket. VideoSDK retains nothing after the session.</p><h3 id="step-1-authenticate-then-mint-a-role-scoped-token-on-the-server">Step 1: authenticate, then mint a role-scoped token on the server</h3><p>Token generation never happens in the browser. Your backend holds the VideoSDK API secret, and it issues a token only after your identity provider has authenticated the user, with multi-factor authentication for clinicians. The clinician's token carries moderator permissions so they can start recording and remove a participant; the patient's token carries join-only permission. Each token is bound to a single visit's room and expires shortly after the scheduled appointment ends, which satisfies the automatic-logoff and unique-identification points of 164.312(a).</p><h3 id="step-2-create-a-room-per-appointment">Step 2: create a room per appointment</h3><p>Your backend creates a VideoSDK room through the REST API for each scheduled visit and stores the room ID against the appointment record. Keep patient names out of room identifiers and out of your application logs; the join between room and patient lives in your own database, not in anything that leaves your system.</p><h3 id="step-3-join-the-room-and-record-only-to-your-own-bucket">Step 3: join the room and record only to your own bucket</h3><p>Both clients join over TLS signaling and SRTP media using the tokens from Step 1. If the clinician starts a recording, the request names your webhook endpoint and your own storage path, configured once in the VideoSDK dashboard for AWS S3, Azure Blob, or GCP Cloud Storage. VideoSDK uploads with write-only credentials and retains no copy. Capture and log the patient's consent in your application before exposing the record control.</p><h3 id="step-4-build-the-audit-log-from-webhooks">Step 4: build the audit log from webhooks</h3><p>Subscribe your endpoint to VideoSDK's session and participant events, verify each event, and store it with a timestamp, the room ID, the participant identifier from your own identity system, and the source IP. That table is your 164.312(b) audit control. It should live in your logging store with the same access restrictions as the recordings.</p><p>For the room setup and the SDK methods behind each step, see the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a> and the <a href="https://www.videosdk.live/blog/react-js-video-calling">React video chat tutorial</a>; recording parameters and storage configuration are documented in <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/recording-and-live-streaming/record-meeting">Record a meeting</a> and <a href="https://docs.videosdk.live/docs/tutorials/user-dashboard/recording-storage-config">Configure recording storage</a>.</p><h3 id="features-that-change-in-hipaa-mode">Features that change in HIPAA mode</h3><p>When the HIPAA add-on is active, VideoSDK disables live transcription, closed captions, post-call transcription, AI-generated summaries, and HLS and RTMP live streaming, because those paths route media to processors not covered by the HIPAA control set. Composite and individual recording, client-side noise cancellation, whiteboard, polls, quizzes, SIP audio and video, and session-only chat remain available. Map these against your feature list before integration, not after.</p><h2 id="how-to-evaluate-any-hipaa-compliant-video-api-a-decision-checklist">How to Evaluate Any HIPAA Compliant Video API: A Decision Checklist</h2><p>Use this checklist before signing a contract with any video API vendor for a healthcare use case.</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th>Requirement</th>
<th>Questions to ask the vendor</th>
</tr>
</thead>
<tbody>
<tr>
<td>BAA availability</td>
<td>Is the BAA available on the pricing tier I intend to use, and what does it cost?</td>
</tr>
<tr>
<td>Encryption protocols</td>
<td>Do you use TLS 1.2 or higher for signaling and SRTP for media? Do you publish cipher suites? Is E2EE optional, and what does enabling it disable?</td>
</tr>
<tr>
<td>Storage defaults</td>
<td>Does the platform store any session data by default? Where do recordings go, and can your staff read them?</td>
</tr>
<tr>
<td>Third-party certifications</td>
<td>Do you hold a current SOC 2 Type II or ISO 27001 report? Can you provide it under NDA?</td>
</tr>
<tr>
<td>Geo-fencing</td>
<td>Can media routing be restricted to specific regions, and on which plan?</td>
</tr>
<tr>
<td>Feature restrictions</td>
<td>Which features are disabled in HIPAA mode?</td>
</tr>
<tr>
<td>Audit events</td>
<td>Which session and participant events are delivered by webhook, and are they signed?</td>
</tr>
<tr>
<td>Breach notification</td>
<td>What are your incident response and notification timelines, in writing?</td>
</tr>
<tr>
<td>Sub-processor list</td>
<td>Who are your sub-processors, and are they under downstream BAAs?</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>A vendor that cannot answer these questions specifically and in writing is not ready for healthcare production deployments.</p><h2 id="healthcare-teams-building-on-videosdk">Healthcare Teams Building on VideoSDK</h2><p>Two healthcare and therapy companies have published their results on VideoSDK, and their words are quoted verbatim below.</p><p>Examedi, a Y Combinator S21 healthcare-at-home marketplace in Latin America that connects patients with lab tests and telehealth consultations, moved its video to VideoSDK after call failures on a previous provider. Rafael Toro, Head of New Business at Examedi, said: "The speed of implementation, personalized support, and reduced 50% call failures have greatly benefited our telehealth platform." The <a href="https://www.videosdk.live/customers/examedi">Examedi case study</a> reports a 50 percent reduction in call failures and a 4.8 out of 5 user experience rating.</p><p>Talk Your Heart Out (TYHO), an online therapy platform, migrated from Twilio. Shilpa Jain, CEO and Co-Founder, said: "We switched from a major international player to Video SDK due to their responsiveness to feedback, superior product, and better service." The <a href="https://www.videosdk.live/customers/tyho">TYHO case study</a> reports an 88 percent referral rate and 70 percent repeat clients after migration.</p><p>Neither case study is a compliance attestation; they document reliability and support outcomes for healthcare and therapy workloads. Compliance evidence comes from the BAA, the SOC 2 Type II report, and the control list in the HIPAA documentation.</p><h2 id="definitions-glossary">Definitions Glossary</h2><blockquote><strong>HIPAA (Health Insurance Portability and Accountability Act):</strong> A U.S. federal law enacted in 1996 that establishes national standards for protecting Protected Health Information and governs how covered entities and business associates collect, store, and transmit patient data.</blockquote><blockquote><strong>PHI (Protected Health Information):</strong> Any individually identifiable health information created, received, maintained, or transmitted by a covered entity or business associate, including names, diagnoses, appointment dates, medical record numbers, and any data that could identify a patient.</blockquote><blockquote><strong>BAA (Business Associate Agreement):</strong> A legally binding contract between a covered entity and a vendor that defines how PHI will be protected, the vendor's security obligations, breach notification procedures, and permissible uses of the data. VideoSDK provides one under its HIPAA add-on.</blockquote><blockquote><strong>SRTP (Secure Real-time Transport Protocol):</strong> The encryption protocol, defined in RFC 3711, that protects audio and video media in WebRTC, providing confidentiality, integrity verification, and replay protection.</blockquote><blockquote><strong>SFU (Selective Forwarding Unit):</strong> A media server that receives each participant's stream and forwards it to the others. SFU-based calls are encrypted hop by hop, not end to end, unless an additional E2EE layer is enabled.</blockquote><blockquote><strong>Covered Entity:</strong> Under HIPAA, a healthcare provider, health plan, or healthcare clearinghouse that electronically transmits health information in connection with specific transactions.</blockquote><blockquote><strong>Geo-fencing:</strong> The ability to restrict media routing to specific geographic regions, used to enforce data residency requirements. VideoSDK documents USA, Europe, India, UAE, Singapore, and Australia.</blockquote><h2 id="key-takeaways">Key Takeaways</h2><ul><li>A HIPAA compliant video API requires four elements at minimum: a signed BAA, encryption in transit (SRTP for media, TLS for signaling), session-scoped access controls with audit logging, and no default PHI storage.</li><li>HIPAA does not require end-to-end encryption, and multi-party calls through an SFU are not end-to-end encrypted; the BAA and the vendor's access controls carry the weight that E2EE would otherwise carry.</li><li>OCR imposed 21 financial penalties in 2025 and 789 large breaches were reported, per HIPAA Journal; a missing BAA with a video vendor is a standalone violation.</li><li>VideoSDK provides TLS plus SRTP encryption, JWT-based role-scoped access, zero storage by default, recordings written to the customer's own bucket, geo-fencing across six regions, and a custom-priced BAA add-on on Pay-As-You-Go and Enterprise plans.</li><li>Compliance is shared: the API vendor provides infrastructure controls; the developer owns configuration, consent capture, identity, audit storage, and retention policy.</li></ul><h2 id="conclusion">Conclusion</h2><p>A HIPAA compliant video API is not a feature toggle. It is a combination of cryptographic controls, a contractual BAA, infrastructure architecture, and configuration discipline, all of which must be in place before the first patient session. Fortune Business Insights valued the global telehealth market at $186.41 billion in 2025, and OCR's proposed Security Rule would make encryption and MFA mandatory rather than addressable. Building on infrastructure that already meets that bar is cheaper than remediating after launch.</p><p>VideoSDK's HIPAA-aligned API provides TLS plus SRTP encryption, JWT-based access controls, zero default PHI storage, recording to your own bucket, and a BAA add-on for <a href="https://www.videosdk.live/pricing" rel="noreferrer">Pay-As-You-Go</a> and Enterprise accounts. Start with the $20 free credit, no credit card required, at <a href="https://app.videosdk.live/login" rel="noreferrer">VideoSDK</a>, follow the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">React quickstart</a>, and activate the HIPAA add-on from Billing -&gt; Add-ons when your telehealth product is ready for production. <br>Compliance questions go to security@videosdk.live.</br></p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-a-hipaa-compliant-video-api-1">What is a HIPAA compliant video API?</h3><p>A HIPAA compliant video API is a programmable real-time communication layer that satisfies the administrative, physical, and technical safeguards of the HIPAA Security Rule. It encrypts all media and signaling in transit, enforces role-based and session-scoped access controls, logs session activity, signs a Business Associate Agreement with the healthcare organization, and does not retain PHI beyond the session unless the customer enables recording into their own storage.</p><h3 id="is-zoom-hipaa-compliant">Is Zoom HIPAA compliant?</h3><p>Zoom can be HIPAA compliant only on Zoom for Healthcare or another eligible paid plan with a signed BAA and HIPAA settings enabled. Free and standard Pro Zoom accounts do not qualify. The same applies to Zoom Video SDK for developers: a qualifying plan and a signed BAA are required before PHI can flow through it.</p><h3 id="is-facetime-hipaa-compliant">Is FaceTime HIPAA compliant?</h3><p>No. Apple does not sign a Business Associate Agreement for FaceTime, so it cannot be used for telehealth involving PHI. The COVID-era enforcement discretion that tolerated FaceTime for telehealth ended on May 11, 2023.</p><h3 id="is-google-meet-hipaa-compliant">Is Google Meet HIPAA compliant?</h3><p>Google Meet can be used for PHI only under a paid Google Workspace plan where the organization has accepted Google's Business Associate Addendum and configured the HIPAA-relevant settings. Free Google accounts and consumer Meet are not covered.</p><h3 id="does-hipaa-require-end-to-end-encryption-for-video-calls">Does HIPAA require end-to-end encryption for video calls?</h3><p>No. The HIPAA Security Rule requires transmission security and treats the encryption mechanism as an addressable specification, which the 2025 proposed rule would make required but still without mandating end-to-end encryption. Hop-by-hop SRTP encryption through an SFU under a BAA meets the rule. VideoSDK offers optional E2EE for cases where the vendor must never hold plaintext, at the cost of server-side recording and transcription.</p><h3 id="does-using-a-hipaa-compliant-video-api-make-my-entire-app-hipaa-compliant">Does using a HIPAA compliant video API make my entire app HIPAA compliant?</h3><p>No. The API handles the infrastructure layer. The covered entity remains responsible for patient consent, identity and access configuration, audit log storage, data retention, and ensuring no PHI leaks through other parts of the application or other vendors. HIPAA compliance is a shared responsibility between the API vendor and the developer.</p><h3 id="what-is-a-business-associate-agreement-and-why-is-it-required">What is a Business Associate Agreement and why is it required?</h3><p>A Business Associate Agreement is the contract, required by 45 CFR 164.308(b) and 164.504(e), between a covered entity and a vendor that handles PHI on its behalf. It specifies how PHI will be protected, the vendor's security obligations, breach notification duties, and permitted uses. Operating a telehealth product without a signed BAA from every vendor in the data path is a standalone HIPAA violation.</p><h3 id="which-video-features-are-disabled-in-videosdks-hipaa-mode">Which video features are disabled in VideoSDK's HIPAA mode?</h3><p>Live transcription, closed captions, post-call transcription, AI-generated summaries, and HLS and RTMP live streaming are disabled under the HIPAA add-on because they route media to additional processors. Composite and individual recording, client-side noise cancellation, whiteboard, polls, quizzes, SIP audio and video, and session-only chat remain available.</p><h3 id="how-much-does-videosdks-hipaa-compliance-add-on-cost">How much does VideoSDK's HIPAA compliance add-on cost?</h3><p>VideoSDK's HIPAA compliance add-on is custom priced and quoted by sales. It is available on Pay-As-You-Go and Enterprise accounts, activated from the Dashboard under Billing &gt; Add-ons, and includes the BAA and HIPAA-aligned media handling. Usage is billed separately at the standard participant-minute rates.</p><h3 id="can-session-recordings-be-hipaa-compliant">Can session recordings be HIPAA compliant?</h3><p>Yes, when the patient has consented, the recording is encrypted at rest, access is restricted and logged, and a retention policy is enforced. With VideoSDK, recordings upload directly to the customer's own S3, Azure, or GCP bucket with write-only access; the customer's bucket must have server-side encryption, blocked public access, and access logging enabled.</p><h3 id="what-happens-if-my-video-api-vendor-has-a-data-breach">What happens if my video API vendor has a data breach?</h3><p>Under the HIPAA Breach Notification Rule (45 CFR 164.410), a business associate must notify the covered entity without unreasonable delay and no later than 60 days after discovering a breach of unsecured PHI. The covered entity then notifies affected individuals and, for breaches affecting 500 or more people, HHS and the media. Your BAA should set a shorter contractual notification window than the regulatory maximum.</p>]]></content:encoded></item><item><title><![CDATA[What Is Video PD? The Complete Guide to Video Personal Discussion]]></title><description><![CDATA[Video pd (video personal discussion) is a live, regulated video session for customer identity verification and onboarding. Used in BFSI, healthcare, and government. Learn how it works and how to build it with VideoSDK.]]></description><link>https://www.videosdk.live/blog/video-personal-discussion-vpd</link><guid isPermaLink="false">6674299e20fab018df10ec98</guid><category><![CDATA[Industry Update]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Thu, 30 Jan 2025 11:08:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/06/Video-PD.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>Video PD (Video Personal Discussion) is a live, face-to-face video session between a business agent and a customer used to verify identity, conduct a regulated personal discussion, and complete onboarding without requiring branch visits or paper documents. Banks, insurers, and healthcare providers use this approach to cut onboarding time from days to minutes while meeting compliance requirements under India's RBI V-CIP, the EU's EBA guidelines, and FinCEN rules in the United States.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2024/06/Video-PD.jpg" alt="What Is Video PD? The Complete Guide to Video Personal Discussion"/><p>Regulated industries spend billions every year solving a problem that should have been solved years ago: how to verify a customer's identity securely, personally, and at scale without making them visit a physical location. Video pd is the approach most financial institutions have settled on, and adoption has moved from early experiment to regulatory expectation in under five years.</p><p>This guide explains exactly what video personal discussion is, how it works, which industries use it, how it compares to older methods, how to implement it, and what technology stack is required.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-10--2026--03_46_25-PM.png" class="kg-image" alt="What Is Video PD? The Complete Guide to Video Personal Discussion" loading="lazy" width="1774" height="887"><figcaption><span style="white-space: pre-wrap;">Video pd session flow diagram for BFSI onboarding</span></figcaption></img></figure><h2 id="what-is-video-pd">What Is Video PD?</h2><p>Video personal discussion (video pd) is defined as a real-time, video-based interaction between a trained business agent and a customer, used to verify identity, collect required information, and complete regulated onboarding without physical presence.</p><p>The process works by connecting the customer with a business agent through an encrypted <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-video-call" rel="noreferrer">WebRTC video call</a>. During the session, the agent visually verifies the customer's government-issued identity document, captures a live photo or biometric data for liveness detection, asks the structured questions required by the applicable regulatory framework, and records the full session to create a tamper-evident compliance audit trail.</p><p>Video personal discussion builds directly on <a href="https://www.videosdk.live/solutions/video-kyc">Video KYC (Know Your Customer)</a> but extends it to cover the full personal discussion layer. Where Video KYC focuses specifically on identity verification (document check and liveness detection), the complete session encompasses needs assessment, product explanation, consent collection, and signature capture. Most enterprise deployments use Video KYC as phase one of the longer process.</p><h3 id="how-video-pd-differs-from-video-kyc">How Video PD Differs from Video KYC</h3><p>Video KYC and video pd are related but serve different scopes. Video KYC is defined as the process of confirming who the customer is. The personal discussion phase is the full regulated conversation that happens once identity is confirmed.</p><p>A bank onboarding a new loan customer needs Video KYC to establish that the person on the call is who they claim to be. It then needs the structured personal discussion to cover mandatory topics: needs assessment, terms explanation, risk disclosure, and consent capture. The two processes run sequentially in one session, but they carry distinct regulatory requirements in most jurisdictions.</p><h2 id="why-traditional-verification-methods-fail-at-scale">Why Traditional Verification Methods Fail at Scale</h2><p>Traditional customer verification fails modern financial institutions on four measurable dimensions: reach, speed, fraud resistance, and cost.</p><p><strong>Geographical reach:</strong>&nbsp;In-person verification requires the customer to visit a branch, which hard-limits serviceable geography to areas within reach of physical infrastructure. According to the World Bank's 2021 <a href="https://documents1.worldbank.org/curated/en/099818107072234182/pdf/IDU06a834fe908933040670a6560f44e3f4d35b7.pdf" rel="noreferrer">Global Findex Database</a>, approximately 1.4 billion adults globally remain unbanked, the majority in rural or underserved areas where branch access is structurally impossible. Remote video verification removes the geographic constraint entirely.</p><p><strong>Onboarding speed:</strong>&nbsp;Physical document collection and manual review typically takes 3 to 7 business days, during which the customer can drop off or switch to a competitor. A typical video pd session completes the same process in 8 to 15 minutes.</p><p><strong>Fraud vulnerability:</strong>&nbsp;Document scanning and manual authentication are susceptible to forgery and identity spoofing. According to a <a href="https://risk.lexisnexis.com/global/en/about-us/press-room/press-release/20240424-tcof-financial-services-lending" rel="noreferrer">2024 LexisNexis Risk Solutions report</a>, financial services firms lose an average of $4.41 for every $1 of direct fraud loss when factoring in investigation and recovery costs.  Combining liveness detection, AI-powered OCR, and immutable session recording makes document forgery significantly harder to execute undetected.</p><p><strong>Operational cost:</strong>&nbsp;Sending field agents to customer locations for in-person verification costs an average of $50 to $200 per visit when accounting for agent time, travel, and administration. A managed video session typically costs under $5 at scale.</p><p>The cumulative effect of these four failure modes explains why adoption across the BFSI sector moved from optional to expected over a short period.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-2--2026--07_19_16-PM.png" class="kg-image" alt="What Is Video PD? The Complete Guide to Video Personal Discussion" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Traditional verification vs Video PD speed comparison</span></figcaption></img></figure><h2 id="how-a-video-pd-session-works-the-step-by-step-flow">How a Video PD Session Works: The Step-by-Step Flow</h2><p>A regulated video PD session follows a defined sequence that satisfies both the customer experience and the compliance requirements of the applicable regulatory framework.</p><p><strong>Step 1: Customer initiation.</strong>&nbsp;The customer receives a link or app deep-link to begin the session. Modern platforms built on WebRTC run directly in a mobile browser without requiring an app installation, which reduces drop-off at this stage significantly.</p><p><strong>Step 2: Pre-session validation.</strong>&nbsp;Before the agent connects, automated checks run on the customer's device: camera and microphone permissions, network quality assessment, and an initial liveness check to confirm a real person is present.</p><p><strong>Step 3: Agent connection.</strong>&nbsp;A trained agent joins the call. Recording begins from the moment both parties are connected, establishing the start of the audit trail.</p><p><strong>Step 4: Document verification.</strong>&nbsp;The agent asks the customer to display their government-issued identity document to the camera. AI-powered <a href="https://docs.videosdk.live/android/guide/identity-verification/ocr" rel="noreferrer">OCR</a> reads the document data, and a fraud detection layer checks for tampering or forgery. The system cross-references the document against the data the customer provided during pre-registration.</p><p><strong>Step 5: Biometric verification.</strong>&nbsp;A liveness detection check confirms the customer on the call matches the photo on the identity document. This step uses facial geometry comparison, not just a static photo match.</p><p><strong>Step 6: The personal discussion.</strong>&nbsp;The agent conducts the structured regulatory interview required by the applicable framework: needs assessment, product explanation, risk disclosure, and consent capture. This is the core "pd" component that distinguishes a complete video pd implementation from a Video KYC-only flow.</p><p><strong>Step 7: Session close and audit trail.</strong>&nbsp;The recording, document captures, biometric data, and the full interaction log are stored in encrypted, jurisdiction-compliant storage. The audit trail is immutable and available for regulatory inspection.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-10--2026--04_03_55-PM.png" class="kg-image" alt="What Is Video PD? The Complete Guide to Video Personal Discussion" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">Video pd agent portal interface with compliance workflow</span></figcaption></img></figure><h2 id="which-industries-use-video-pd">Which Industries Use Video PD?</h2><p>Video pd is most widely deployed in sectors where regulators require auditable, identity-verified customer interactions before a financial, insurance, or healthcare product can be issued.</p><h3 id="banking-and-financial-services">Banking and Financial Services</h3><p>Banks use video personal discussion for account opening, loan origination, credit card issuance, and investment product onboarding. India's <a href="https://www.rbi.org.in/commonman/english/scripts/notification.aspx?id=2607" rel="noreferrer">Reserve Bank of India</a> (RBI) Video Customer Identification Process (V-CIP) framework, introduced in 2020 and expanded since, explicitly defines this approach as a compliant method for banking KYC. ICICI Bank, one of India's largest private sector banks, has deployed video-based onboarding at scale across its retail banking division. </p><h3 id="insurance">Insurance</h3><p>Insurance providers require detailed customer information to assess risk and set premiums. Remote video personal discussion allows underwriters to conduct virtual risk assessments, verify customer declarations in real time, and collect informed consent for policy terms, all within a single recorded session. This is particularly valuable for life and health insurance products where regulators require evidence of disclosure.</p><h3 id="government-and-public-sector">Government and Public Sector</h3><p>Government agencies use video-based personal discussions for identity verification when issuing documents, processing benefit applications, or conducting regulated interviews at distance. Several Indian state governments have piloted this approach for citizen services, reducing branch queues for document verification by significant margins.</p><h3 id="healthcare">Healthcare</h3><p>Healthcare providers use the video personal discussion process for patient onboarding, telehealth intake, and consent capture before procedures. Under US HIPAA requirements, telehealth platforms that conduct these sessions must meet specific data security and retention standards, including encrypted transmission and secure storage with defined retention periods.</p><h3 id="live-commerce-and-retail">Live Commerce and Retail</h3><p>Online retailers and live commerce platforms use video-based identity verification to validate high-value customer accounts, process age-restricted product onboarding, and provide personalized sales consultations that require identity confirmation before product fulfilment.</p><h2 id="what-are-the-regulatory-frameworks-governing-video-pd">What Are the Regulatory Frameworks Governing Video PD?</h2><p>Regulatory compliance is not optional in video pd deployments; it is the primary design constraint that determines every architectural decision.</p><p>The relevant frameworks by jurisdiction are:</p><ul><li><strong>India (RBI V-CIP):</strong>&nbsp;The Reserve Bank of India's Video Customer Identification Process framework defines the exact technical and procedural requirements for video-based customer identification in banking and financial services, including mandatory session recording, defined liveness detection requirements, and specific data residency rules requiring customer data to remain within India.</li><li><strong>European Union (EBA Remote Onboarding Guidelines):</strong>&nbsp;The European Banking Authority's guidelines on remote onboarding specify the fraud risk controls, biometric verification standards, and audit documentation required for video-based customer identification across EU member states.</li><li><strong>United States (FinCEN CIP Rules):</strong>&nbsp;The Financial Crimes Enforcement Network's Customer Identification Program rules allow video-based identity verification as a compliant method under specific conditions, including defined record-keeping and audit trail requirements.</li><li><strong>Global (ISO/IEC 30107-3 Standard):</strong>&nbsp;The international standard for liveness detection and presentation attack detection defines the technical specifications that biometric verification systems must meet in compliant deployments.</li></ul><p>Engineering teams building a solution must confirm which regulatory frameworks apply to their customer base before selecting a technology stack. A platform that meets RBI V-CIP requirements (Indian data residency, specific recording formats) may require additional configuration to meet GDPR's data minimization and portability requirements for EU customers.</p><h2 id="how-does-videosdk-help-with-the-video-pd-solution">How does VideoSDK help with the video PD solution?</h2><p><a href="https://www.videosdk.live/solutions/video-kyc">VideoSDK</a> is a leading and <strong>best video PD solutions provider</strong> across the globe that helps businesses streamline their personalized experience. We offer a comprehensive suite of features that cater to the diverse needs of businesses and their customers. Some of the key features include:</p><ul><li><a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer"><strong>Secure Video Conferencing</strong></a>: Provides a secure and reliable video conferencing solution that enables real-time, face-to-face interactions between customers and business representatives.</li><li><strong>Identity Verification</strong>: VideoSDK leverages advanced technologies, such as facial recognition, document verification, and QR codes for secure customer identification, ensuring the authenticity of customer identities during the onboarding process. </li><li><strong>Customizable Workflows</strong>: Our end-to-end customized SDK offers the flexibility to customize the onboarding workflow, allowing businesses to tailor the process to their specific requirements and customer needs.</li><li>Compliance and Audit Trails: VideoSDK’s cloud recording feature for detailed audit trail purposes, ensures that businesses can meet regulatory requirements and provide evidence of their customer verification processes.</li><li><strong>Integrations</strong>: Our solutions often integrate with existing systems and identity management platforms, enabling seamless data flow and a unified customer experience.</li><li><strong>Analytics and Reporting</strong>: VideoSDK’s solutions provide businesses with valuable insights and analytics, allowing them to track key performance indicators, identify areas for improvement, and make data-driven decisions.</li></ul><h3 id="features-offered-by-videosdk">Features Offered By VideoSDK</h3><p>VideoSDK solutions come with a range of features that enhance the customer experience and streamline the verification process:</p><ul><li><strong>Accurate Geo-tagging:</strong> Precise location tracking to verify the customer's identity and the authenticity of the interaction.</li><li><strong>Image and Video Capture:</strong> The option to capture and store relevant documents, photographs, and video footage for future reference and compliance purposes.</li><li><strong>Storage Integration:</strong> Own storage integration option with an instant dump feature for real-time recording and audit.</li><li><strong>Secure Data Encryption:</strong> Robust data encryption protocols to protect sensitive customer information and ensure compliance with data privacy regulations.</li><li><strong>Analytics</strong>: Our analytics dashboard provides valuable insights that allow you to track key performance indicators and make data-driven decisions.</li></ul><p>By leveraging these comprehensive features, businesses can enhance their customer onboarding experience, improve operational efficiency, and maintain regulatory compliance, all while strengthening their competitive position in the market.</p><h2 id="common-misconceptions-about-video-pd">Common Misconceptions About Video PD</h2><p>Several widely-held misconceptions cause engineering teams to build incomplete solutions or compliance teams to reject valid implementations.</p><p><strong>Misconception: Video PD and Video KYC are the same thing.</strong>&nbsp;Reality: Video KYC is a subset of video pd. Video KYC covers identity verification only. The full personal discussion includes the needs assessment, product disclosure, and consent capture that a KYC-only session does not address. A bank that deploys Video KYC without the personal discussion layer is not compliant with frameworks like RBI V-CIP for regulated products.</p><p><strong>Misconception: Any video call platform works for video pd.</strong>&nbsp;Reality: A compliant implementation requires specific technical components that general-purpose tools (Zoom, Google Meet) do not provide out of the box: immutable session recording with audit trail, AI-powered document capture, liveness detection integration, and jurisdiction-specific data residency controls. The platform must be purpose-built or purpose-configured for this use case.</p><p><strong>Misconception: This approach is only relevant for India.</strong>&nbsp;Reality: Video-based remote onboarding is deployed across regulated industries in the EU, the United States, Southeast Asia, and the Middle East. The RBI V-CIP framework has made India one of the highest-adoption markets, but this is a global regulatory trend across BFSI and healthcare.</p><p><strong>Misconception: Video PD requires a native mobile app.</strong>&nbsp;Reality: Modern platforms built on WebRTC technology run directly in mobile browsers, eliminating the app installation requirement that causes significant drop-off in customer onboarding funnels. Native iOS and Android SDKs are available for businesses that prefer a fully branded in-app experience, but they are not a technical requirement.</p><h2 id="video-pd-vs-traditional-verification-side-by-side-comparison">Video PD vs. Traditional Verification: Side-by-Side Comparison</h2><table>
<thead>
<tr>
<th>Dimension</th>
<th>Traditional In-Person</th>
<th>Video PD</th>
</tr>
</thead>
<tbody>
<tr>
<td>Onboarding time</td>
<td>3-7 business days</td>
<td>8-15 minutes</td>
</tr>
<tr>
<td>Geographic reach</td>
<td>Branch proximity required</td>
<td>Any internet connection</td>
</tr>
<tr>
<td>Fraud risk</td>
<td>High (document forgery, impersonation)</td>
<td>Low (liveness detection, AI OCR, session recording)</td>
</tr>
<tr>
<td>Per-session cost</td>
<td>$50-$200 (agent travel + admin)</td>
<td>Under $5 at scale</td>
</tr>
<tr>
<td>Audit trail</td>
<td>Paper-based, incomplete</td>
<td>Immutable digital recording</td>
</tr>
<tr>
<td>Customer drop-off</td>
<td>High (friction, travel, wait time)</td>
<td>Low (mobile-first, 15 minutes)</td>
</tr>
<tr>
<td>Regulatory compliance</td>
<td>Manual attestation</td>
<td>Automated, session-level audit log</td>
</tr>
</tbody>
</table>
<h2 id="definitions-glossary">Definitions Glossary</h2><p><strong>Video PD (Video Personal Discussion):</strong>&nbsp;A live, regulated video session between a business agent and a customer used to verify identity and conduct the full structured onboarding discussion required by the applicable regulatory framework.</p><p><strong>Video KYC (Know Your Customer):</strong>&nbsp;The identity verification phase of a video onboarding session, covering document capture and liveness detection. Video KYC is typically the first phase of a video pd session, not a standalone replacement for it.</p><p><a href="https://www.videosdk.live/blog/video-based-identification-procedure-vbip" rel="noreferrer"><strong>V-CIP (Video Customer Identification Process)</strong></a><strong>:</strong>&nbsp;The Reserve Bank of India's regulatory framework defining the technical and procedural requirements for video-based customer identification in Indian banking and financial services.</p><p><a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer"><strong>WebRTC (Web Real-Time Communication)</strong></a><strong>:</strong>&nbsp;The open IETF/W3C standard protocol that enables encrypted, peer-to-peer video and audio communication directly in web browsers and native apps without plugins.</p><p><a href="https://www.videosdk.live/blog/what-is-liveness-detection" rel="noreferrer"><strong>Liveness Detection</strong></a><strong>:</strong>&nbsp;A biometric check that confirms the person on a video call is physically present and not a recorded video or photograph. Liveness detection is a mandatory component of compliant video pd and Video KYC systems.</p><p><strong>AES-256 Encryption:</strong>&nbsp;The Advanced Encryption Standard with a 256-bit key length, widely adopted as the data-at-rest encryption standard for regulated session recording storage.</p><h2 id="key-takeaways">Key Takeaways</h2><ul><li>Video pd (video personal discussion) is a live, regulated video session that combines identity verification with a structured agent-led personal discussion, completing the full onboarding process in 8 to 15 minutes instead of 3 to 7 business days.</li><li>Video pd is not the same as Video KYC; Video KYC covers identity verification only, while the personal discussion layer adds needs assessment, product disclosure, and consent capture that regulators in most BFSI jurisdictions require separately.</li><li>Traditional in-person verification costs $50 to $200 per session and limits serviceable geography to branch proximity; video-based sessions cost under $5 at scale and remove geographic constraints entirely.</li><li>Regulatory compliance is the primary design constraint in any video pd implementation: India's RBI V-CIP, the EU's EBA guidelines, and US FinCEN rules each impose specific requirements on session recording, data residency, and biometric verification that standard video call tools do not meet.</li><li>VideoSDK provides the encrypted video infrastructure, AES-256 cloud recording, and SDK components needed to build a production-ready video pd solution without building the video layer from scratch.</li></ul><h2 id="conclusion">Conclusion</h2><p>Video personal discussion has become the standard method for compliant, scalable remote customer onboarding in regulated industries because it solves four problems simultaneously: geographic reach, onboarding speed, fraud prevention, and operational cost. Any business that still requires customers to visit a branch for identity verification is leaving addressable market and operational efficiency unrealized.</p><p>If you are building a video pd solution, VideoSDK's real-time video infrastructure handles the encrypted session layer, cloud recording for compliance audit trails, and mobile-first delivery across browser and native app. Get started at&nbsp;<a href="https://app.videosdk.live/signup&nbsp;" rel="noreferrer">Signup</a> with $20 in free credit and no credit card required</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-video-pd-in-banking">What is video pd in banking?</h3><p>Video pd in banking is a live, regulated video interaction between a bank agent and a prospective customer, used to verify identity, conduct the mandatory personal discussion required by the applicable compliance framework, and complete account or product onboarding without requiring a branch visit. It is governed by jurisdiction-specific frameworks including India's RBI V-CIP, the EU's EBA remote onboarding guidelines, and FinCEN rules in the United States.</p><h3 id="how-is-video-pd-different-from-video-kyc">How is video pd different from Video KYC?</h3><p>Video pd differs from Video KYC in scope. Video KYC is the identity verification phase of a video session, covering document capture and liveness detection to confirm who the customer is. Video pd extends the session to include the full agent-led personal discussion: product explanation, needs assessment, risk disclosure, and informed consent capture. Most enterprise deployments include Video KYC as the first phase of the video pd session.</p><h3 id="is-video-pd-legally-compliant-for-financial-services">Is video pd legally compliant for financial services?</h3><p>Video pd is legally compliant for financial services when implemented according to the regulatory framework that governs the customer's jurisdiction. India's RBI V-CIP framework, the EU's EBA guidelines, and equivalent rules in over 40 countries explicitly permit video-based customer identification and onboarding for regulated financial products, provided specific technical requirements (session recording, liveness detection, data residency) are met.</p><h3 id="how-long-does-a-video-pd-session-take">How long does a video pd session take?</h3><p>A video pd session typically takes 8 to 15 minutes from customer initiation to session close, including the identity verification phase, the personal discussion, and consent capture. This compares with 3 to 7 business days for traditional in-person or document-mail verification processes.</p><h3 id="what-technology-is-needed-to-build-a-video-pd-solution">What technology is needed to build a video pd solution?</h3><p>Building a compliant video pd solution requires four components: an encrypted WebRTC video platform for the live session, AI-powered OCR and liveness detection for document and biometric verification, cloud recording with jurisdiction-compliant data residency for the audit trail, and an agent portal for session management and compliance checklist workflows. VideoSDK provides the video infrastructure, recording, and SDK layer; document verification and liveness detection typically integrate via third-party APIs.</p><h3 id="can-video-pd-sessions-be-conducted-on-mobile">Can video pd sessions be conducted on mobile?</h3><p>Video pd sessions can be conducted on mobile devices without requiring an app installation. Modern platforms built on WebRTC technology run directly in mobile browsers, eliminating the friction of app downloads and reducing customer drop-off in the onboarding funnel. Native iOS and Android SDKs are available for businesses that prefer a fully branded in-app experience.</p><h3 id="what-data-security-standards-apply-to-video-pd-sessions">What data security standards apply to video PD sessions?</h3><p>Video pd sessions must meet the data security standards of the applicable regulatory framework. These typically include AES-256 encryption for video transmission, secure encrypted storage for session recordings, data residency requirements (RBI V-CIP requires data within India, GDPR applies across the EU, HIPAA governs US healthcare), and audit log retention for the periods each regulator specifies. VideoSDK's infrastructure supports configurable data residency and AES-256 encrypted session storage by default.</p>]]></content:encoded></item><item><title><![CDATA[Understanding Pre-call Integration in Flutter]]></title><description><![CDATA[Discover how to implement Precall Integration in Flutter SDK. Our comprehensive guide helps you enhance your app's communication capabilities, ensuring smooth and efficient user interactions.]]></description><link>https://www.videosdk.live/blog/precall-integration-in-flutter</link><guid isPermaLink="false">6685226720fab018df10f5f6</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 30 Jan 2025 09:45:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/07/Pre-Call-Check-Flutter.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/Pre-Call-Check-Flutter.jpg" alt="Understanding Pre-call Integration in Flutter"/><p>In the dynamic world of video communication, ensuring a smooth and high-quality experience for users is paramount. One critical aspect of achieving this is through the implementation of a <code>Precall</code> system. This system allows users to test and configure their devices before joining a call, ensuring that audio and video are optimal. In this blog, we will explore the <strong>precall</strong> feature provided by VideoSDK's in Flutter SDK, discussing its significance, goals, and step-by-step implementation.</p><h2 id="the-goal-of-precall-integration">The goal of Precall Integration</h2><p>The primary goal of the <strong>precall</strong> feature is to enhance user experience by allowing them to:</p><ul><li>Verify and configure their audio and video devices.</li><li>Troubleshoot any potential issues before joining the actual call.</li></ul><p>By incorporating a <strong>precall</strong> check, developers can significantly reduce the likelihood of technical difficulties during live video sessions, leading to more professional and uninterrupted communication.</p><h2 id="step-by-step-guide-integrating-the-precall-feature">Step-by-Step Guide: Integrating the Precall Feature</h2><h3 id="step-1-verify-permissions">Step 1: Verify Permissions</h3><p>First, ensure that your application has the required permissions to access user devices, including cameras, microphones, and speakers. Use the <code>checkPermissions()</code> method from the VideoSDK class to confirm if these permissions are granted.</p><pre><code class="language-dart">import 'package:videosdk/videosdk.dart';

void checkMediaPermissions() async {
  try {
  //By default both audio and video permissions will be checked.
  Map&lt;String, bool&gt;? checkAudioVideoPermissions = await VideoSDK.checkPermissions();
  //For checking just audio permission.
  Map&lt;String, bool&gt;? checkAudioPermissions = await VideoSDK.checkPermissions(Permissions.audio);
  //For checking just video permission.
  Map&lt;String, bool&gt;? checkVideoPermissions = await VideoSDK.checkPermissions(Permissions.video);
  //For checking both audio and video permissions.
  Map&lt;String, bool&gt;? checkAudioVideoPermissions = await VideoSDK.checkPermissions(Permissions.audio_video);
  } catch (ex) {
    print("Error in checkPermissions()");
  }
  // Output: Map object for both audio and video permission:
  /*
        Map(2)
        0 : {"audio" =&gt; true}
            key: "audio"
            value: true
        1 : {"video" =&gt; true}
            key: "video"
            value: true
    */
};</code></pre><p><strong>Enable Permissions on iOS</strong>: Add the following to your <code>Podfile</code> to check for microphone and camera permissions:</p><pre><code class="language-ruby">post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
    //Add this into your podfile
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        'PERMISSION_CAMERA=1',
        'PERMISSION_MICROPHONE=1',
      ]
    end
  end
end</code></pre><blockquote>Note:  checkPermissions() method is not supported on Desktop Applications and Firefox Browser.</blockquote><blockquote>Note: When microphone and camera permissions are blocked, rendering device lists is not possible:</blockquote><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/image-21.png" class="kg-image" alt="Understanding Pre-call Integration in Flutter" loading="lazy" width="2244" height="1376"/></figure><h3 id="step-2-request-permissions-if-necessary">Step 2: Request Permissions (if Necessary)</h3><p>If the required permissions are not granted, use the <code>requestPermission()</code> method from the VideoSDK class to prompt users to allow access to their devices.</p><p>To request microphone and camera permissions on iOS devices, add the following to your Podfile:</p><pre><code class="language-ruby">post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
    //Add this into your podfile
      config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [
        'PERMISSION_CAMERA=1',
        'PERMISSION_MICROPHONE=1',
      ]
    end
  end
end</code></pre><blockquote>NOTE: In case permissions are blocked by the user, the permission request dialogue cannot be re-rendered programmatically. In such cases, consider providing guidance to users on manually adjusting their permissions.</blockquote><pre><code class="language-dart">void requestMediaPermissions() async {
  try {
      //By default both audio and video permissions will be requested.
      Map&lt;String, bool&gt;? reqAudioVideoPermissions = await VideoSDK.requestPermissions();
      //For requesting just audio permission.
      Map&lt;String, bool&gt;? reqAudioPermissions = await VideoSDK.requestPermissions(Permissions.audio);
      //For requesting just video permission.
      Map&lt;String, bool&gt;? reqVideoPermissions = await VideoSDK.requestPermissions(Permissions.video);
      //For requesting both audio and video permissions.
      Map&lt;String, bool&gt;? reqAudioVideoPermissions = await VideoSDK.requestPermissions(Permissions.audio_video);

  } catch (ex) {
    print("Error in requestPermission ");
  }
};</code></pre><blockquote>Note: The <code>requestPermissions()</code> method is not supported on Desktop Applications and Firefox Browser.</blockquote><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/image-22.png" class="kg-image" alt="Understanding Pre-call Integration in Flutter" loading="lazy" width="2244" height="1389"/></figure><h3 id="step-3-render-device-lists">Step 3: Render Device Lists</h3><p>After obtaining the necessary permissions, fetch and display lists of available video and audio devices using the <code>getVideoDevices()</code> and <code>getAudioDevices()</code> methods from the VideoSDK class. Allow users to select their preferred devices from these lists.</p><blockquote>Note: For iOS devices, the EARPIECE is not supported when a WIRED_HEADSET or BLUETOOTH device is connected. Additionally, WIRED_HEADSET and BLUETOOTH devices cannot be used simultaneously; the most recently connected device takes priority.</blockquote><pre><code class="language-dart">
List&lt;AudioDeviceInfo&gt; audioInputDevices = [];
List&lt;AudioDeviceInfo&gt; audioOutputDevices = [];

const getMediaDevices = async () =&gt; {
  try {
    //Method to get all available video devices.
    List&lt;VideoDeviceInfo&gt;? videoDevices = await VideoSDK.getVideoDevices();
    //Method to get all available Microphones.
    List&lt;AudioDeviceInfo&gt;? audioDevices = await VideoSDK.getAudioDevices();
    for (AudioDeviceInfo device in audioDevices!) {
      //For Mobile Applications
      if (!kIsWeb) {
        if (Platform.isAndroid || Platform.isIOS) {
          audioOutputDevices.add(device);
        }
      } else {
        //For Web and Desktop Applications
          if (device.kind == 'audioinput') {
            audioInputDevices.add(device);
          } else {
            audioOutputDevices.add(device);
          }
        }
      }
  } catch (err) {
    print("Error in getting audio or video devices");
  }
};</code></pre><ul><li>Displaying device lists once permissions are granted:</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/image-23.png" class="kg-image" alt="Understanding Pre-call Integration in Flutter" loading="lazy" width="2244" height="1423"/></figure><h3 id="step-4-handle-device-changes">Step 4: Handle Device Changes</h3><p>Implement the <code>deviceChanged</code> callback in the VideoSDK class to dynamically update and re-render device lists whenever new devices are connected or removed. This ensures that users can seamlessly interact with newly connected devices without any disruptions.</p><blockquote>Note: The <code>deviceChanged</code> event is not supported in macOS applications.</blockquote><pre><code class="language-dart">VideoSDK.on(
  Events.deviceChanged,
  (devices) {
    print("device changed ${devices}");
  },
);</code></pre><h3 id="step-5-ensure-selected-devices-are-used-in-the-meeting">Step 5: Ensure Selected Devices Are Used in the Meeting</h3><p>Make sure all relevant states, such as microphone and camera status (on/off) and selected devices, are transferred from the precall screen to the meeting. This can be achieved by passing these crucial states and media streams to the VideoSDK and Room methods.</p><p><strong>For the video device:</strong></p><ul><li>Create a custom track using the selected <code>CameraID</code> and pass it to the <code>createRoom</code> method.</li></ul><p><strong>For audio devices in web and desktop applications:</strong></p><ul><li>Use the <code>switchAudioDevice</code> method to select the desired audio output device.</li><li>Use the <code>changeMic</code> method to select the desired audio input device once the room is joined.</li></ul><p><strong>For audio devices in mobile applications:</strong></p><ul><li>Use the <code>switchAudioDevice</code> method to select both the input and output audio devices.</li></ul><p>By ensuring this integration, users can smoothly transition from the precall setup to the actual meeting while maintaining their preferred settings.</p><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class MeetingScreen extends StatefulWidget {
  final String meetingId;
  final String token;

  const MeetingScreen(
      {super.key, required this.meetingId, required this.token});

  @override
  State&lt;MeetingScreen&gt; createState() =&gt; _MeetingScreenState();
}

class _MeetingScreenState extends State&lt;MeetingScreen&gt; {
  late Room _room;

  @override
  void initState() {
    //Create a custom track with the selectedVideoDevice Id
    CustomTrack cameraTrack = await VideoSDK.createCameraVideoTrack(
      cameraId: selectedVideoDevice?.deviceId);
    // create room
    _room = VideoSDK.createRoom(
      roomId: widget.meetingId,
      token: widget.token,
      displayName: "John Doe",
      micEnabled: true,
      camEnabled: true,
      customCameraVideoTrack: cameraTrack, //For Video Devices
    );
    registerMeetingEvents(room);
    super.initState();
  }

  //For Audio Devices
void registerMeetingEvents(Room _meeting) {
    // Called when joined in meeting
  _meeting.on(
    Events.roomJoined,
    () {
      //When meeting is joined, call the switchAudioDevice method to switch Audio Output.
      _meeting.switchAudioDevice(widget.selectedAudioOutputDevice!);

      //When meeting is joined, call the changeMic method to switch Audio Input.(Onlyrequired for web and desktop applications)
        if (kIsWeb || Platform.isWindows || Platform.isMacOS) {
          _meeting.changeMic(widget.selectedAudioInputDevice!);
        }
    },
  );
}

  @override
  Widget build(BuildContext context) {
    return YourMeetingWidget();
  }
}</code></pre><p>This example demonstrates best practices for implementing precall functionality and can serve as a starting point for your own implementation.</p><pre><code class="language-terminal">git clone https://github.com/videosdk-live/videosdk-rtc-flutter-sdk-example.git</code></pre><h2 id="conclusion">Conclusion:</h2><p>Effective precall implementation is key to creating a polished and professional video calling experience. By leveraging <a href="https://www.videosdk.live/">VideoSDK's </a>precall capabilities, you can ensure that your users enter calls with properly configured devices and necessary permissions, setting the stage for successful and hassle-free video conferences.</p><p>Remember, the precall phase is your opportunity to address potential issues before they impact the user experience. By investing time in robust precall implementation, you're laying the groundwork for high-quality, reliable video calls that will keep your users coming back.</p>]]></content:encoded></item><item><title><![CDATA[Understanding Interactive Live Streaming API Pricing]]></title><description><![CDATA[Interact with your viewers on a live stream with ease and flexibility. Intergrate interactive live streaming with all affordability ]]></description><link>https://www.videosdk.live/blog/interactive-live-streaming-pricing</link><guid isPermaLink="false">6322de0b5ed4260c94d4fb6f</guid><category><![CDATA[Pricing]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 30 Jan 2025 09:27:00 GMT</pubDate><media:content url="http://assets.videosdk.live/static-assets/ghost/2021/09/Interactive-live-streaming-Pricing-thumbnail--1--1.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://assets.videosdk.live/static-assets/ghost/2021/09/Interactive-live-streaming-Pricing-thumbnail--1--1.jpg" alt="Understanding Interactive Live Streaming API Pricing"/><p>Interactive live streaming has become one of the most engaging platforms to virtually make social, cultural, political, and corporate happenings. After the pandemic, communication over the web has accelerated. </p><p>Interactive live streaming is a web-based live stream that allows interaction between both, the host and the viewers. Usually, streaming platforms are recognized at platforms where the host is the only entity granted with the activity of speech and presentation. However, interactive live streaming allows the participation of both groups- the host and the viewers.</p><h3 id="what-is-interactive-live-streaming">What is Interactive Live Streaming</h3><p><a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">Interactive live streaming</a> refers to real-time video broadcasting where the audience can engage directly with the streamer through features like chat, polls, and Q&amp;A sessions. This technology enables creators and businesses to host immersive events, workshops, and webinars, fostering a dynamic interaction. Key platforms include Twitch, YouTube Live, and proprietary services like VideoSDK, which cater to varied needs from gaming to educational sessions. The technology supports high-definition video and low-latency communication, making it ideal for a wide range of interactive experiences.<br/></p><blockquote>This blog is dedicated to pricing. We bring interactive live streaming to you with the most astounding quality and features along with affordability. We have simplified pricing plans that help in making effective strategies for the users. It makes readers create a clear picture of how we effectively function with pricing. You can always <a href="https://videosdk.live/contact">get in touch</a> with us in case of any query or fix. We are happy to assist you. </blockquote><h2 id="how-to-calculate-the-cost-of-interactive-live-streaming-pricing">How to Calculate the Cost of Interactive Live Streaming Pricing?</h2><p>Interactive live streaming involves cost computation of two entities</p><p><strong>a) The host/ broadcaster and b) The viewers</strong></p><ul><li>The cost is calculated per stream</li><li>We deliver interactive live streaming in two resolutions, 720p (HD) and 1080p (Full HD)</li><li>The calculation is based on the sum of broadcaster and viewer cost</li><li>The stream can address multiple hosts</li><li>Recording and RTMP of stream carry additional costs<br/></li></ul><p><strong>Cost of host</strong>= Unit price (revolution per minute) x number of minutes x Total hosts</p><p><strong>Cost of views</strong>= Unit price (revolution per minute) x number of minutes x Total participants</p><p><strong>Total cost </strong>Cost of Hosts + Cost of Viewers <br/></p><p><strong>At 720p- Cost per host= $ 0.00299, Cost per viewer= $ 0.0015</strong></p><p><strong>At 1080p- Cost per host= $ 0.00699, Cost per viewer= $0.004</strong><br/></p><p>Let’s get a better understanding with some examples</p><p><strong>Examples of Cost Calculations 1</strong> </p><figure class="kg-card kg-image-card"><img src="http://assets.videosdk.live/static-assets/ghost/2021/09/pricing_interactive-live-streaming.jpg" class="kg-image" alt="Understanding Interactive Live Streaming API Pricing" loading="lazy" width="1292" height="717"/></figure><p>Given that; Total streaming minutes= 45, Total Viewers= 1,000 Total Hosts= 1</p><ol><li><strong>At 720p</strong> Total Cost= $ 67.63</li><li><strong>At 1080p Total Cost= $ 180.31 (0.00699 x 45 x 1) + (0.004 x 45 x 1000)</strong><br/></li></ol><p><strong>Let’s take an example with multiple hosts</strong></p><p><strong>Examples of Cost Calculations 2</strong></p><p>Given that; Total streaming minutes= 60, Total Viewers= 2,500 Total Hosts= 6</p><ol><li><strong>At 720p</strong> Total Cost= $ 226.07 (0.00299 x 60x 6) + (0.0015 x 60 x 2500)</li><li><strong>At 1080p</strong> Total Cost= $ 602.51 (0.00699 x 60 x 6) + (0.004 x 60 x 2500)<br/></li></ol><h2 id="comparison-with-other-providers">Comparison with Other Providers</h2><p>Many providers design and develop interactive live streaming with the same approach of enhancing engagement. These companies also allow multiple host streaming along with huge participant viewing numbers. One major difference between videosdk.live and these companies are that they calculate pricing based on the 2K+ on-screen resolution of the hosts. <br/></p><h2 id="what-is-2k-resolution">What is 2K+ resolution?</h2><p>2K+ is a resolution that exceeds the resolution of more than 2160 pixels. The interactive live streaming API providers calculate resolution based on the number of hosts adding up their respective screen resolutions. For example, 4 hosts streaming live at 720p makes a total of 720 x 4= 2,880p which is termed as 2K+ resolution.<br/></p><h2 id="comparison-videosdklive-vs-other-companies">Comparison: Videosdk.live vs. Other Companies</h2><p>The below image describes the units and pricing policies of videosdk.live and other companies that deal with interactive live streaming APIs. We have taken two standard resolutions for comparison. To reckon the pricing, most companies have pricing similar to the estimates we have claimed.<br/></p><figure class="kg-card kg-image-card"><img src="http://assets.videosdk.live/static-assets/ghost/2021/09/pricing-comparison_interactive-live-streaming.jpg" class="kg-image" alt="Understanding Interactive Live Streaming API Pricing" loading="lazy" width="1292" height="1002"/></figure><blockquote>The above chart clearly represents the pricing difference of videosdk.live and other companies. With the same quality, features and deliverables we observe a huge price difference. Interactive live streaming has been an immersively attractive approach for brands and corporates to scale engagement.</blockquote>]]></content:encoded></item><item><title><![CDATA[RTMP Out Explained: How Live Streaming Really Works]]></title><description><![CDATA[This article delves into the intricacies of RTMP Out, a crucial component in the transmission of live video data, exploring its technical details, step-by-step process, and how it enables seamless live streaming across various platforms.]]></description><link>https://www.videosdk.live/blog/rtmp-out-how-live-streaming-really-works</link><guid isPermaLink="false">660d35982a88c204ca9cfaaf</guid><category><![CDATA[RTMP]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Wed, 29 Jan 2025 13:02:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/09/RTMP-Out-Explained_-How-Live-Streaming-Really-Works.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2024/09/RTMP-Out-Explained_-How-Live-Streaming-Really-Works.jpg" alt="RTMP Out Explained: How Live Streaming Really Works"/><p>Live streaming has become an integral part of our world. From watching esports tournaments and concerts to attending virtual classes and webinars, live streams offer a unique way to connect and share experiences in real-time.</p><p>But how exactly does this live video transmission work? This is where RTMP comes in, it is a communication protocol and plays an important role in transmission. This article dives into the inner workings of RTMP Out, exploring its technical details and the step-by-step process of how it enables smooth live streaming.</p><h2 id="what-is-rtmp-and-rtmp-out">What is RTMP and RTMP Out?</h2><p>In simple words, RTMP (Real-Time Messaging Protocol) is a specialized communication protocol designed for the low-latency transmission of live video data over the Internet. Unlike protocols like HTTP (yes, it is related to security as well), which focus on file transfer, RTMP prioritizes real-time communication, ensuring the uninterrupted delivery of live streams.</p><p>RTMP Output is the single-way process of transmitting a live video stream from an encoder to a streaming platform or media server using the Real-Time Messaging Protocol (RTMP).</p><h2 id="different-elements-used-in-rtmp-out">Different Elements Used in RTMP Out</h2><p><strong>Encoder</strong>: An encoder is a (1) software or hardware application responsible for capturing video and audio from a source like a camera, microphone, screen capture card, etc; (2) compressing it into a streamable format, and (3) preparing it for transmission.</p><p><strong>Streaming Platform</strong>: This is the online service that receives the encoded stream from the encoder, distributes it to viewers on various devices, and manages the playback experience. Popular examples include YouTube Live, Twitch, and Facebook Live.</p><p><strong>RTMP Server</strong>: The streaming platform has servers specifically configured to receive incoming RTMP streams. These servers handle the data transfer and make the stream accessible to viewers.</p><h2 id="how-rtmp-out-works">How RTMP Out Works?</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/09/diagram--3--1.png" class="kg-image" alt="RTMP Out Explained: How Live Streaming Really Works" loading="lazy" width="1600" height="990"/></figure><p>Here's a detailed analysis of the process involved in RTMP Out:</p><h3 id="stream-setup-and-configuration">Stream Setup and Configuration:</h3><p>The streamer chooses a streaming platform and sets up an account. The platform provides the streamer with an RTMP server URL and stream key. These act like unique identifiers that allow the platform to recognize and accept the incoming stream from the encoder.</p><p>The streamer opens its encoder software (OBS Studio, XSplit, vMix, etc.) and configures the streaming settings. Within the encoder settings, you'll typically find a dedicated section for "Streaming" or "Output."</p><h3 id="rtmp-and-connection-establishment">RTMP and Connection Establishment:</h3><p>The encoder initiates an RTMP with the streaming platform's RTMP server using the provided URL and stream key. This association establishes a persistent connection between the encoder and the server, ensuring a continuous flow of data for the live stream.</p><h3 id="data-chunking-and-stream-packaging">Data Chunking and Stream Packaging:</h3><p>To ensure efficient data transmission over the internet, the encoder breaks down the compressed video and audio data into smaller manageable units called chunks or packets.</p><p>Each chunk is typically a few hundred bytes in size and contains information about the data type (audio/video), sequence number, and timestamp for proper reassembly at the receiving end. The encoder then packages these data chunks into RTMP messages according to the RTMP protocol specifications.</p><h3 id="sending-the-stream">Sending the Stream:</h3><p>The encoder transmits the RTMP messages containing the video and audio data scraps over the established connection to the streaming platform's RTMP server. RTMP uses TCP (Transmission Control Protocol) for reliable data transfer. </p><p>TCP ensures that the data packets arrive in the correct order and without errors. In case of any errors or missing packets, TCP requests retransmission.</p><h3 id="receives-and-processes-the-stream">Receives and Processes the Stream:</h3><p>RTMP server receives the RTMP messages sent by the encoder. The server unpacks the messages, reassembles the data chunks based on their sequence numbers and timestamps, and buffers the received data.</p><h3 id="stream-distribution-and-playback">Stream Distribution and Playback:</h3><p>The streaming platform processes the reassembled video and audio data and prepares it for delivery to viewers. This might involve further transcoding the stream into different bitrates and resolutions to cater to viewers with varying internet connection speeds and device capabilities. </p><p>The platform then distributes the prepared stream to viewers who have connected to the stream on their devices (computers, phones, tablets). Viewers typically access the stream through the platform's website or dedicated apps. </p><p>The platform employs various protocols like HLS (HTTP Live Streaming) for this delivery, allowing viewers to experience smooth playback even with fluctuating internet connections.</p><h3 id="monitoring-and-stream-management">Monitoring and Stream Management:</h3><p>Monitoring the health of their stream within the encoder software with tools like bitrate meters and frame rate displays provides valuable insights into the stream's performance, including options to control who has access, schedule the stream, and interact with viewers in real time through chat features.</p><h2 id="benefits-of-using-rtmp-out">Benefits of Using RTMP Out</h2><p><strong>Low Latency</strong>: A key benefit of RTMP is its ability to deliver low-latency streams. This means the delay between the action happening in real-time and viewers seeing it on their screens is minimal. This is crucial for interactive live experiences like gaming streams and live auctions where viewers need to react quickly.</p><p><strong>Reliability</strong>: RTMP prioritizes reliable data transmission. By employing error correction and congestion control mechanisms, RTMP ensures that the video stream reaches viewers with minimal interruptions or glitches. This stability is essential for professional live-streaming scenarios.</p><p><strong>Compatibility</strong>: As an open standard, RTMP is widely supported by a vast range of encoder software and streaming platforms. This flexibility allows streamers to choose the tools and services that best suit their needs without worrying about compatibility issues.</p><p><strong>Security</strong>: While not inherently secure, RTMP can be configured with authentication and encryption to protect live streams from unauthorized access. This is important for sensitive content or private events.</p><h2 id="alternatives-to-rtmp-out">Alternatives to RTMP Out</h2><p>RTMP remains a reliable and popular choice for live streaming, but newer protocols have emerged that offer additional functionalities:</p><h3 id="hls-http-live-streaming">HLS (HTTP Live Streaming):</h3><p>HLS is gaining traction due to its ability to deliver adaptive bitrate streams. This means the streaming platform can adjust the video quality based on the viewer's internet connection speed, ensuring smooth playback even for viewers with limited bandwidth. HLS also offers playlist-based delivery, allowing viewers to join the stream mid-broadcast without missing anything.</p><h3 id="rist-reliable-internet-streaming-transport">RIST (Reliable Internet Streaming Transport):</h3><p>This newer protocol offers even lower latency than RTMP and is gaining popularity for real-time broadcasting applications like live sports and news events.</p><hr><p>Understanding RTMP Out allows you to appreciate the technical foundation behind live streaming. While newer protocols are emerging, RTMP remains a robust and widely supported solution for streaming live video content.</p><p>Its low latency, reliability, and compatibility continue to make it a valuable tool for streamers across various platforms. As technology evolves, RTMP will likely coexist with newer options, offering broadcasters the flexibility to choose the protocol that best suits their specific needs and streaming goals.</p></hr>]]></content:encoded></item><item><title><![CDATA[Flutter-WebRTC: A Complete Guide]]></title><description><![CDATA[Learn how to build high-quality real-time video apps with Flutter WebRTC. Get started today and deliver the best user experience with your video apps using Flutter WebRTC.]]></description><link>https://www.videosdk.live/blog/flutter-webrtc</link><guid isPermaLink="false">63e1f61792324379f1d343ab</guid><category><![CDATA[WebRTC]]></category><dc:creator><![CDATA[Yash]]></dc:creator><pubDate>Tue, 28 Jan 2025 16:44:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2023/02/Flutter-WebRTC-7.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2023/02/Flutter-WebRTC-7.jpg" alt="Flutter-WebRTC: A Complete Guide"/><p>In this tutorial, we will discuss the most reliable and widely used RTC framework: WebRTC, the rapidly growing hybrid application development framework. Flutter-WebRTC, and how we can use the framework. I will explain how to create a Flutter-WebRTC app in Just 7 steps. </p><p>Video calling has become a common medium of communication since the pandemic. We saw a very huge wave in real-time communication space (audio and video communication). There are many use cases of RTC in modern businesses, such as video conferencing, <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">real-time streaming</a>, live commerce, education, telemedicine, surveillance, gaming, etc.</p><p>Developers often ask the same questions How to build real-time applications with minimal effort (Me too ?). If you ask such questions, then you are at the right place.</p><p>For those who don't have the time to go through the process step by step, this repository is a great resource for quickly building a <a href="https://github.com/videosdk-live/webrtc">flutter-webrtc github project</a>. (feel free to give it a star ⭐)</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/02/Flutter-WebRTC.jpg" class="kg-image" alt="Flutter-WebRTC: A Complete Guide" loading="lazy" width="1280" height="720"/></figure><h2 id="what-is-flutter">What is Flutter?</h2><p><a href="https://flutter.dev">Flutter</a> is a mobile app development framework based on the <a href="https://dart.dev">Dart</a> programming language, developed by Google. One can develop Android apps, iOS apps, web apps, and desktop apps using the same code with the Flutter Framework. Flutter has a large community, which is why it is the fastest-growing app development framework ever.</p><h2 id="what-is-webrtc">What is WebRTC?</h2><p><a href="https://www.videosdk.live/blog/webrtc">WebRTC</a> is an open-source framework for real-time communication (audio, video, and generic data) adopted by the majority of browsers and can be used on native platforms like Android, iOS, MacOS, Linux, Windows, etc.</p><p>WebRTC relies on three major APIs</p><ul><li>getUserMedia: used to get local audio and video media.</li><li>RTCPeerConnection: establishes a connection with another peer.</li><li>RTCDataChannel: Creates a channel for generic data exchange.</li></ul><h1 id="what-is-flutter-webrtc">What is Flutter-WebRTC?</h1>
<p>Flutter-WebRTC is a plugin for the Flutter framework that enables <a href="https://www.videosdk.live/blog/introduction-to-real-time-communication-sdk" rel="noreferrer">real-time communication</a> (RTC) capabilities in web and mobile applications. It is a collection of communication protocols and APIs that allow direct communication between web browsers and mobile applications without third-party plugins or software. With <a href="https://www.videosdk.live/blog/flutter-webrtc">Flutter-WebRTC</a>, you can easily build video call applications without dealing with the underlying technologies' complexities.</p><h2 id="how-webrtc-works">How WebRTC works?</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2023/02/webrtc-working-1.png" class="kg-image" alt="Flutter-WebRTC: A Complete Guide" loading="lazy" width="800" height="862"><figcaption><span style="white-space: pre-wrap;">Working of WebRTC</span></figcaption></img></figure><p>To understand the workings of WebRTC, we need to understand the following technologies.</p><p><strong>1. Signalling</strong></p><p>WebRTC allows peer-to-peer communication over the web even though a peer has no idea where other peers are and how to connect to them or communicate to them.</p><p>To establish a connection between peers, WebRTC needs clients to exchange metadata to coordinate with them using Signalling. It allows us to communicate over firewalls or work with <a href="https://en.wikipedia.org/wiki/Network_address_translation">NATs</a> (Network Address Translators) . Technology, that is majorly used for signaling is <a href="https://www.videosdk.live/blog/what-is-a-websocket" rel="noreferrer">WebSocket</a>, which allows bidirectional communication between peers and signaling servers.</p><p><strong>2. SDP </strong></p><p><a href="https://en.wikipedia.org/wiki/Session_Description_Protocol">SDP</a> stands for Session Description Protocol. It describes session information like </p><ul><li>sessionId</li><li>session expire time</li><li>Audio/Video Encoding/Formats/Encryption etc...</li><li>Audio/Video IP and Port</li></ul><p>Suppose there are two peers Client A and Client B that will be connected over WebRTC. Then Client A generates and sends an SDP offer (session-related information like codecs it supports) to Client B then Client B responds with SDP Answer (Accept or Reject SDP Offer). SDP is used here for negotiation between two peers.  </p><p><strong>3. ICE</strong></p><p><a href="https://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment">ICE</a> stands for Interactive Connectivity Establishment, which allows peers to connect with other peers. There are many reasons why a straight-up connection between peers will not work. </p><p>It requires bypassing firewalls that could prevent opening connections, giving a unique IP address if like most situations device does not have a public IP Address, and relaying data through a server if the router does not allow it to directly connect with peers. ICE uses <a href="https://en.wikipedia.org/wiki/STUN">STUN</a> or <a href="https://en.wikipedia.org/wiki/Traversal_Using_Relays_around_NAT">TURN</a> servers to accomplish this.</p><h1 id="lets-start-with-flutter-webrtc-project">Let's start with Flutter-WebRTC Project</h1>
<p>First of all, we need to setup signalling server. </p><ul><li><strong>Clone the Flutter-WebRTC repository </strong></li></ul><pre><code class="language-js">git clone https://github.com/videosdk-live/webrtc.git</code></pre><ul><li><strong>Go to webrtc-signalling-server and install dependencies for Flutter-WebRTC App</strong></li></ul><pre><code class="language-js">cd webrtc-signalling-server &amp;&amp; npm install</code></pre><ul><li><strong>Start Signalling Server for Flutter-WebRTC App</strong></li></ul><pre><code class="language-js">npm run start</code></pre><ul><li><strong>Flutter-WebRTC Project Structure</strong></li></ul><pre><code class="language-js">lib
└── main.dart
└── services
	└── signalling.service.dart
└── screens
	└── join_screen.dart
	└── call_screen.dart</code></pre><h1 id="7-steps-to-build-a-flutter-webrtc-video-calling-app">7 Steps to Build a Flutter-WebRTC Video Calling App</h1>
<h2 id="step-1-create-flutter-wrbrtc-app-project">Step 1: Create Flutter-WrbRTC app project</h2>
<pre><code class="language-js">flutter create flutter_webrtc_app</code></pre><h2 id="step-2-add-project-dependency-for-flutter-webrtc-app">Step 2: Add project dependency for Flutter-WebRTC App</h2>
<pre><code class="language-js">flutter pub add flutter_webrtc socket_io_client</code></pre><h2 id="step-3-flutter-wrbrtc-setup-for-ios-and-android">Step 3: Flutter-WrbRTC Setup for IOS and Android</h2>
<ul><li><strong>Flutter-WebRTC iOS Setup</strong><br>Add the following lines to your Info.plist file, located at &lt;project root&gt;/ios/Runner/Info.plist.</br></li></ul><pre><code class="language-js">&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Camera Usage!&lt;/string&gt;
&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Microphone Usage!&lt;/string&gt;</code></pre><p>These lines allows your app to access camera and microphone.</p><p><strong>Note: Refer, if you have trouble with </strong><a href="https://pub.dev/packages/flutter_webrtc#note-for-ios"><strong>iOS setup</strong></a><strong>. </strong></p><ul><li><strong>Flutter-WebRTC Android Setup </strong><br>Add following lines in AndroidManifest.xml, located at &lt;project root&gt;/android/app/src/main/AndroidManifest.xml</br></li></ul><pre><code class="language-js">&lt;uses-feature android:name="android.hardware.camera" /&gt;
&lt;uses-feature android:name="android.hardware.camera.autofocus" /&gt;
&lt;uses-permission android:name="android.permission.CAMERA" /&gt;
&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
&lt;uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /&gt;
&lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /&gt;
&lt;uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" /&gt;
&lt;uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" /&gt;</code></pre><p>If necessary, you will need to increase <code>minSdkVersion</code> of <code>defaultConfig</code> up to <code>23</code> in app level build.gradle file.</p><h2 id="step-4-create-signallingservice-for-flutter-webrtc-app">Step 4: Create SignallingService for Flutter-WebRTC App</h2>
<p>The Signalling Service will deal with the communication to the Signalling Server. Here, we will use <a href="https://socket.io">socket.io</a> client to connect with socker.io server, which is basically a WebSocket Server.</p><pre><code class="language-js">import 'dart:developer';
import 'package:socket_io_client/socket_io_client.dart';

class SignallingService {
  // instance of Socket
  Socket? socket;

  SignallingService._();
  static final instance = SignallingService._();

  init({required String websocketUrl, required String selfCallerID}) {
    // init Socket
    socket = io(websocketUrl, {
      "transports": ['websocket'],
      "query": {"callerId": selfCallerID}
    });

    // listen onConnect event
    socket!.onConnect((data) {
      log("Socket connected !!");
    });

    // listen onConnectError event
    socket!.onConnectError((data) {
      log("Connect Error $data");
    });

    // connect socket
    socket!.connect();
  }
}</code></pre><h2 id="step-5-create-joinscreen-for-flutter-webrtc-app">Step 5: Create JoinScreen for Flutter-WebRTC App</h2>
<p>JoinScreen will be a <a href="https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html">StatefulWidget</a>, which allows the user to join a session. Using this screen, the user can start a session or join a session when some other user calls this user using CallerID.</p><pre><code class="language-js">import 'package:flutter/material.dart';
import 'call_screen.dart';
import '../services/signalling.service.dart';

class JoinScreen extends StatefulWidget {
  final String selfCallerId;

  const JoinScreen({super.key, required this.selfCallerId});

  @override
  State&lt;JoinScreen&gt; createState() =&gt; _JoinScreenState();
}

class _JoinScreenState extends State&lt;JoinScreen&gt; {
  dynamic incomingSDPOffer;
  final remoteCallerIdTextEditingController = TextEditingController();

  @override
  void initState() {
    super.initState();

    // listen for incoming video call
    SignallingService.instance.socket!.on("newCall", (data) {
      if (mounted) {
        // set SDP Offer of incoming call
        setState(() =&gt; incomingSDPOffer = data);
      }
    });
  }

  // join Call
  _joinCall({
    required String callerId,
    required String calleeId,
    dynamic offer,
  }) {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (_) =&gt; CallScreen(
          callerId: callerId,
          calleeId: calleeId,
          offer: offer,
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Theme.of(context).colorScheme.background,
      appBar: AppBar(
        centerTitle: true,
        title: const Text("P2P Call App"),
      ),
      body: SafeArea(
        child: Stack(
          children: [
            Center(
              child: SizedBox(
                width: MediaQuery.of(context).size.width * 0.9,
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    TextField(
                      controller: TextEditingController(
                        text: widget.selfCallerId,
                      ),
                      readOnly: true,
                      textAlign: TextAlign.center,
                      enableInteractiveSelection: false,
                      decoration: InputDecoration(
                        labelText: "Your Caller ID",
                        border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(10.0),
                        ),
                      ),
                    ),
                    const SizedBox(height: 12),
                    TextField(
                      controller: remoteCallerIdTextEditingController,
                      textAlign: TextAlign.center,
                      decoration: InputDecoration(
                        hintText: "Remote Caller ID",
                        alignLabelWithHint: true,
                        border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(10.0),
                        ),
                      ),
                    ),
                    const SizedBox(height: 24),
                    ElevatedButton(
                      style: ElevatedButton.styleFrom(
                        side: const BorderSide(color: Colors.white30),
                      ),
                      child: const Text(
                        "Invite",
                        style: TextStyle(
                          fontSize: 18,
                          color: Colors.white,
                        ),
                      ),
                      onPressed: () {
                        _joinCall(
                          callerId: widget.selfCallerId,
                          calleeId: remoteCallerIdTextEditingController.text,
                        );
                      },
                    ),
                  ],
                ),
              ),
            ),
            if (incomingSDPOffer != null)
              Positioned(
                child: ListTile(
                  title: Text(
                    "Incoming Call from ${incomingSDPOffer["callerId"]}",
                  ),
                  trailing: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      IconButton(
                        icon: const Icon(Icons.call_end),
                        color: Colors.redAccent,
                        onPressed: () {
                          setState(() =&gt; incomingSDPOffer = null);
                        },
                      ),
                      IconButton(
                        icon: const Icon(Icons.call),
                        color: Colors.greenAccent,
                        onPressed: () {
                          _joinCall(
                            callerId: incomingSDPOffer["callerId"]!,
                            calleeId: widget.selfCallerId,
                            offer: incomingSDPOffer["sdpOffer"],
                          );
                        },
                      )
                    ],
                  ),
                ),
              ),
          ],
        ),
      ),
    );
  }
}</code></pre><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/02/Flutter-WebRTC-3.jpg" class="kg-image" alt="Flutter-WebRTC: A Complete Guide" loading="lazy" width="1280" height="720"/></figure><h2 id="step-6-create-callscreen-for-flutter-webrtc-app">Step 6: Create CallScreen for Flutter-WebRTC App</h2>
<p>In CallScreen, we will show a local stream of the user, the remote stream of another user, and controls like toggleCamera, toggleMic, switchCamera, endCall. Here, we will establish RTCPeerConnection between peers, create SDP Offer and SDP Answer, and transmit ICE Candidate related data over signalling server (<a href="https://socket.io">socket.io</a>). </p><pre><code class="language-js">import 'package:flutter/material.dart';
import 'package:flutter_webrtc/flutter_webrtc.dart';
import '../services/signalling.service.dart';

class CallScreen extends StatefulWidget {
  final String callerId, calleeId;
  final dynamic offer;
  const CallScreen({
    super.key,
    this.offer,
    required this.callerId,
    required this.calleeId,
  });

  @override
  State&lt;CallScreen&gt; createState() =&gt; _CallScreenState();
}

class _CallScreenState extends State&lt;CallScreen&gt; {
  // socket instance
  final socket = SignallingService.instance.socket;

  // videoRenderer for localPeer
  final _localRTCVideoRenderer = RTCVideoRenderer();

  // videoRenderer for remotePeer
  final _remoteRTCVideoRenderer = RTCVideoRenderer();

  // mediaStream for localPeer
  MediaStream? _localStream;

  // RTC peer connection
  RTCPeerConnection? _rtcPeerConnection;

  // list of rtcCandidates to be sent over signalling
  List&lt;RTCIceCandidate&gt; rtcIceCadidates = [];

  // media status
  bool isAudioOn = true, isVideoOn = true, isFrontCameraSelected = true;

  @override
  void initState() {
    // initializing renderers 
    _localRTCVideoRenderer.initialize();
    _remoteRTCVideoRenderer.initialize();

    // setup Peer Connection
    _setupPeerConnection();
    super.initState();
  }

  @override
  void setState(fn) {
    if (mounted) {
      super.setState(fn);
    }
  }

  _setupPeerConnection() async {
    // create peer connection
    _rtcPeerConnection = await createPeerConnection({
      'iceServers': [
        {
          'urls': [
            'stun:stun1.l.google.com:19302',
            'stun:stun2.l.google.com:19302'
          ]
        }
      ]
    });

    // listen for remotePeer mediaTrack event
    _rtcPeerConnection!.onTrack = (event) {
      _remoteRTCVideoRenderer.srcObject = event.streams[0];
      setState(() {});
    };

    // get localStream
    _localStream = await navigator.mediaDevices.getUserMedia({
      'audio': isAudioOn,
      'video': isVideoOn
          ? {'facingMode': isFrontCameraSelected ? 'user' : 'environment'}
          : false,
    });

    // add mediaTrack to peerConnection
    _localStream!.getTracks().forEach((track) {
      _rtcPeerConnection!.addTrack(track, _localStream!);
    });

    // set source for local video renderer
    _localRTCVideoRenderer.srcObject = _localStream;
    setState(() {});

    // for Incoming call
    if (widget.offer != null) {
      // listen for Remote IceCandidate
      socket!.on("IceCandidate", (data) {
        String candidate = data["iceCandidate"]["candidate"];
        String sdpMid = data["iceCandidate"]["id"];
        int sdpMLineIndex = data["iceCandidate"]["label"];

        // add iceCandidate
        _rtcPeerConnection!.addCandidate(RTCIceCandidate(
          candidate,
          sdpMid,
          sdpMLineIndex,
        ));
      });

      // set SDP offer as remoteDescription for peerConnection
      await _rtcPeerConnection!.setRemoteDescription(
        RTCSessionDescription(widget.offer["sdp"], widget.offer["type"]),
      );

      // create SDP answer
      RTCSessionDescription answer = await _rtcPeerConnection!.createAnswer();

      // set SDP answer as localDescription for peerConnection
      _rtcPeerConnection!.setLocalDescription(answer);

      // send SDP answer to remote peer over signalling
      socket!.emit("answerCall", {
        "callerId": widget.callerId,
        "sdpAnswer": answer.toMap(),
      });
    }
    // for Outgoing Call
    else {
      // listen for local iceCandidate and add it to the list of IceCandidate
      _rtcPeerConnection!.onIceCandidate =
          (RTCIceCandidate candidate) =&gt; rtcIceCadidates.add(candidate);

      // when call is accepted by remote peer
      socket!.on("callAnswered", (data) async {
        // set SDP answer as remoteDescription for peerConnection
        await _rtcPeerConnection!.setRemoteDescription(
          RTCSessionDescription(
            data["sdpAnswer"]["sdp"],
            data["sdpAnswer"]["type"],
          ),
        );

        // send iceCandidate generated to remote peer over signalling
        for (RTCIceCandidate candidate in rtcIceCadidates) {
          socket!.emit("IceCandidate", {
            "calleeId": widget.calleeId,
            "iceCandidate": {
              "id": candidate.sdpMid,
              "label": candidate.sdpMLineIndex,
              "candidate": candidate.candidate
            }
          });
        }
      });

      // create SDP Offer
      RTCSessionDescription offer = await _rtcPeerConnection!.createOffer();

      // set SDP offer as localDescription for peerConnection
      await _rtcPeerConnection!.setLocalDescription(offer);

      // make a call to remote peer over signalling
      socket!.emit('makeCall', {
        "calleeId": widget.calleeId,
        "sdpOffer": offer.toMap(),
      });
    }
  }

  _leaveCall() {
    Navigator.pop(context);
  }

  _toggleMic() {
    // change status
    isAudioOn = !isAudioOn;
    // enable or disable audio track
    _localStream?.getAudioTracks().forEach((track) {
      track.enabled = isAudioOn;
    });
    setState(() {});
  }

  _toggleCamera() {
    // change status
    isVideoOn = !isVideoOn;

    // enable or disable video track
    _localStream?.getVideoTracks().forEach((track) {
      track.enabled = isVideoOn;
    });
    setState(() {});
  }

  _switchCamera() {
    // change status
    isFrontCameraSelected = !isFrontCameraSelected;

    // switch camera
    _localStream?.getVideoTracks().forEach((track) {
      // ignore: deprecated_member_use
      track.switchCamera();
    });
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Theme.of(context).colorScheme.background,
      appBar: AppBar(
        title: const Text("P2P Call App"),
      ),
      body: SafeArea(
        child: Column(
          children: [
            Expanded(
              child: Stack(children: [
                RTCVideoView(
                  _remoteRTCVideoRenderer,
                  objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
                ),
                Positioned(
                  right: 20,
                  bottom: 20,
                  child: SizedBox(
                    height: 150,
                    width: 120,
                    child: RTCVideoView(
                      _localRTCVideoRenderer,
                      mirror: isFrontCameraSelected,
                      objectFit:
                          RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
                    ),
                  ),
                )
              ]),
            ),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 12),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: [
                  IconButton(
                    icon: Icon(isAudioOn ? Icons.mic : Icons.mic_off),
                    onPressed: _toggleMic,
                  ),
                  IconButton(
                    icon: const Icon(Icons.call_end),
                    iconSize: 30,
                    onPressed: _leaveCall,
                  ),
                  IconButton(
                    icon: const Icon(Icons.cameraswitch),
                    onPressed: _switchCamera,
                  ),
                  IconButton(
                    icon: Icon(isVideoOn ? Icons.videocam : Icons.videocam_off),
                    onPressed: _toggleCamera,
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _localRTCVideoRenderer.dispose();
    _remoteRTCVideoRenderer.dispose();
    _localStream?.dispose();
    _rtcPeerConnection?.dispose();
    super.dispose();
  }
}</code></pre><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/02/Flutter-WebRTC-4.jpg" class="kg-image" alt="Flutter-WebRTC: A Complete Guide" loading="lazy" width="1280" height="720"/></figure><h2 id="step-7-modify-code-in-maindart">Step 7: Modify code in main.dart</h2>
<p>We will pass websocketUrl (signalling server URL) to JoinScreen and create random callerId for user.</p><pre><code class="language-js">import 'dart:math';

import 'package:flutter/material.dart';
import 'screens/join_screen.dart';
import 'services/signalling.service.dart';

void main() {
  // start videoCall app
  runApp(VideoCallApp());
}

class VideoCallApp extends StatelessWidget {
  VideoCallApp({super.key});

  // signalling server url
  final String websocketUrl = "WEB_SOCKET_SERVER_URL";

  // generate callerID of local user
  final String selfCallerID =
      Random().nextInt(999999).toString().padLeft(6, '0');

  @override
  Widget build(BuildContext context) {
    // init signalling service
    SignallingService.instance.init(
      websocketUrl: websocketUrl,
      selfCallerID: selfCallerID,
    );

    // return material app
    return MaterialApp(
      darkTheme: ThemeData.dark().copyWith(
        useMaterial3: true,
        colorScheme: const ColorScheme.dark(),
      ),
      themeMode: ThemeMode.dark,
      home: JoinScreen(selfCallerId: selfCallerID),
    );
  }
}</code></pre><h2 id="woohoo-finally-we-did-it">Woohoo!! Finally, we did it.</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/02/moment_when_your_code_works.jpg" class="kg-image" alt="Flutter-WebRTC: A Complete Guide" loading="lazy" width="500" height="449"/></figure><h2 id="problems-with-p2p-webrtc">Problems with P2P WebRTC</h2><ul><li><strong>Quality of Service: </strong>Quality will decrease as the number of peer connections increases.</li><li><strong>Client-Side Computation: </strong>Low-end devices can not synchronize multiple incoming streams.</li><li><strong>Scalability: </strong>It becomes very difficult for the client to handle computation and network load when the number of peers increases and uploads media at the same time.</li></ul><h2 id="solutions">Solutions</h2><ul><li><strong>MCU (Multipoint Control Unit)</strong></li><li><strong>SFU (Selective Forwarding Unit)</strong></li><li><strong>Video SDK </strong></li></ul><h2 id="integrate-flutter-webrtc-with-videosdk">Integrate Flutter-WebRTC with VideoSDK </h2><p><a href="https://videosdk.live">VideoSDK</a><em> </em>is the most developer-friendly platform for live video and audio SDKs. Video SDK makes integrating live video and audio into your Flutter project considerably easier and faster. You can have a branded, customized, and programmable call-up running in no time with only a few lines of code.</p><p>In addition, VideoSDK provides best-in-class modifications, providing you total control over layout and rights. Plugins may be used to improve the experience, and end-to-end call logs and quality data can be accessed directly from your Video SDK dashboard or via <a href="https://docs.videosdk.live/api-reference/realtime-communication/intro">REST APIs</a>. This amount of data enables developers to debug any issues that arise during a conversation and improve their integrations for the <a href="https://www.commandbar.com/blog/how-to-build-a-frictionless-customer-experience/">best customer experience possible</a>.</p><p>Alternatively, you can follow this quick start guide to <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start">Create a Demo Flutter Project with the VideoSDK.</a> or start with <a href="https://github.com/videosdk-live/videosdk-rtc-flutter-sdk-example">Code Sample</a>.</p>
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Your Page Title</title>
	<!-- Include Tailwind CSS -->
	<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</link></meta></meta></head>

<body>
	<div class="relative w-full overflow-hidden rounded-2xl bg-gradient-to-b from-pink-700 to-purple-900 p-4 text-center shadow-xl">
		<h2 class="mx-auto text-3xl font-bold tracking-tight text-white sm:text-2xl" style="margin-top: 3px; margin-bottom: 12px;">
			Schedule a Demo with Our Live Video Expert!
		</h2>
		<p class="mx-auto mt-3 max-w-xl text-sm text-gray-400">
			Discover how VideoSDK can help you build a cutting-edge real-time video app.
			<span class="font-semibold text-lato"/>
		</p>
		<div class="mt-4 flex items-center justify-center">
			<a href="https://www.videosdk.live/contact" class="rounded-md bg-white px-8 py-3 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white" target="_blank" style="text-decoration: none;color: black;" data-faitracker-click-bind="true">
				Book a call
			</a>	
		</div>
		
	</div>
</body>

</html>
<!--kg-card-end: html-->
<h2 id="more-flutter-resources">More Flutter Resources</h2><ul><li><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/getting-started">Video SDK Flutter SDK Integration Guide</a></li><li><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start">Flutter SDK QuickStart</a></li><li><a href="https://github.com/videosdk-live/videosdk-rtc-flutter-sdk-example">Flutter SDK Github Example</a></li><li><a href="https://www.videosdk.live/blog/video-calling-in-flutter">Build a Flutter Video Calling App with Video SDK</a></li><li><a href="https://youtu.be/4h57eVcaC34">Video Call Flutter app with Video SDK (Android &amp; IOS)</a></li><li><a href="https://pub.dev/packages/videosdk">Official Video SDK flutter plugin: (feel free to give it a star ⭐)</a></li></ul>]]></content:encoded></item><item><title><![CDATA[eKYC: Future of Blockchain Identity Verification]]></title><description><![CDATA[This article delves into how blockchain technology is revolutionizing eKYC processes. By offering a decentralized, immutable, and transparent approach, blockchain enhances security, streamlines identity verification, and ensures regulatory compliance.]]></description><link>https://www.videosdk.live/blog/ekyc-future-of-identity-verification-using-blockchain</link><guid isPermaLink="false">66e1704320fab018df1101ca</guid><category><![CDATA[eKYC]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Tue, 28 Jan 2025 13:00:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/09/Future-of-eKYC_-Blockchain-Identity-Verification.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>eKYC blockchain identity verification combines digital customer onboarding with distributed ledger records that make identity attestations tamper-resistant and reusable across institutions. Blockchain stores cryptographic proofs and consent events instead of raw PII in a single database. Banks, fintechs, and compliance teams use this model to cut repeat KYC, strengthen audit trails, and meet AML regulations faster.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2024/09/Future-of-eKYC_-Blockchain-Identity-Verification.jpg" alt="eKYC: Future of Blockchain Identity Verification"/><p>A customer who completes KYC at one neobank and repeats the same document upload at a second lender within the same month experiences friction that costs both institutions money and erodes trust. eKYC blockchain identity verification addresses that duplication by letting verified identity attestations travel between authorized parties without copying sensitive documents into every new centralized silo. This article defines eKYC, explains how blockchain strengthens identity verification, maps regulatory requirements, compares platform approaches, and covers the production trade-offs that separate a compliant rollout from a pilot that never scales.</p><h2 id="what-is-ekyc">What is eKYC?</h2><p>eKYC is defined as a digital process for verifying a customer's identity remotely using electronic documents, biometric checks, and database validation to satisfy regulatory Know Your Customer requirements without an in-person branch visit.</p><p>eKYC works by capturing government-issued identity documents, running automated authenticity checks through OCR and fraud detection engines, matching the applicant's live biometric sample against the document photo, and recording the verification outcome in a compliance audit trail that regulators can inspect.</p><p>Traditional physical KYC requires the customer to visit a branch or agent location for face-to-face verification with paper documents. eKYC replaces that visit with a digital workflow that completes in minutes on a smartphone or web browser. The Financial Action Task Force (FATF) recognizes <a href="https://www.fatf-gafi.org/en/publications/Financialinclusionandnpoissues/Digital-identity-guidance.html" rel="noreferrer">digital identity</a> systems as tools for meeting anti-money laundering obligations when they meet reliability, independence, and auditability standards outlined in FATF Guidance on Digital Identity.</p><p>Electronic Know Your Customer differs from Video KYC, though teams often combine them. Standard eKYC may rely on document upload and passive biometric matching. Video KYC adds a live agent or automated video session where the verifier confirms liveness, asks dynamic questions, and records the interaction for regulatory evidence. For regulated remote onboarding in India, the Reserve Bank of India's <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc" rel="noreferrer">Video Customer Identification Process (V-CIP)</a> framework requires live interaction during certain account-opening flows.</p><p>In practice, compliance teams that treat eKYC as a one-time document scan without ongoing monitoring discover that synthetic identity fraud still enters downstream transaction monitoring. eKYC is the front door. Blockchain identity verification is the infrastructure that determines how long verified credentials remain trustworthy and portable.</p><p>This section established the definitional boundary between eKYC, physical KYC, and video-assisted verification.</p><h2 id="how-blockchain-enhances-ekyc"><strong>How Blockchain Enhances eKYC?</strong></h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/09/blockchain-based-ekyc.png" class="kg-image" alt="eKYC: Future of Blockchain Identity Verification" loading="lazy" width="1365" height="902"/></figure><p><em>Source: </em><a href="Reimagining KYC Using Blockchain Technology"><em>Reimagining KYC Using Blockchain Technology</em></a></p><p>Blockchain enhances eKYC by replacing centralized identity data silos with tamper-evident, cryptographically signed attestations that authorized institutions verify without re-collecting raw customer documents.</p><p>In a traditional eKYC model, each bank stores a full copy of the customer's passport scan, address proof, and biometric template in its own database. A breach at one institution exposes all stored PII. Blockchain-based eKYC stores hashed identity proofs and verification events on a distributed ledger. When a second institution needs to onboard the same customer, it requests a signed attestation from the verifying party rather than duplicating sensitive files.</p><h3 id="immutable-audit-trails">Immutable Audit Trails</h3><p>Each verification event, consent grant, and credential revocation is written as a ledger transaction with a timestamp and digital signature. Regulators auditing AML compliance can trace exactly when identity was verified, which entity performed the check, and what consent the customer granted. The World Bank's ID4D initiative documents how digital ID systems with strong audit trails support financial inclusion while meeting integrity requirements [EXTERNAL LINK: World Bank ID4D Digital Identity principles].</p><h3 id="smart-contract-compliance-automation">Smart Contract Compliance Automation</h3><p>Smart contracts encode compliance rules as executable logic on the blockchain. A smart contract can enforce that only credentials verified within the last twelve months pass onboarding gates, or that customers from high-risk jurisdictions trigger enhanced due diligence workflows automatically. This reduces manual compliance review for routine cases while preserving human oversight for exceptions.</p><h3 id="reusable-digital-identity">Reusable Digital Identity</h3><p>Banks using blockchain for KYC can issue portable credentials that customers present to insurance providers, payment apps, and lending platforms. HSBC piloted blockchain-based KYC sharing with fintech partners through Tradle's TrustChain network, demonstrating how a verified customer record travels between institutions without repeat document submission. The pilot reduced duplicate verification steps for participating entities, though production adoption requires consortium agreement on governance and liability.</p><h3 id="decentralized-identity-and-user-control">Decentralized Identity and User Control</h3><p>Self-sovereign identity models place credentials in the customer's digital wallet. The customer shares only the minimum attributes a service provider needs (name and age, not full address history) through selective disclosure. This aligns with GDPR data minimization principles and gives users revocation control when a device is compromised.</p><p>Blockchain does not replace the verification act itself. It changes how verification results are stored, shared, and audited. The actual identity check still requires document validation, liveness detection, and database screening. That is where video KYC platforms and biometric engines do the heavy work before any attestation reaches the ledger.</p><p>This section covered how blockchain strengthens auditability, compliance automation, credential reuse, and user-controlled identity sharing in eKYC workflows.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-8--2026--08_17_34-PM.png" class="kg-image" alt="eKYC: Future of Blockchain Identity Verification" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">how blockchain enhances eKYC identity verification architecture</span></figcaption></img></figure><h2 id="what-to-look-for-in-an-ekyc-platform">What to Look for in an eKYC Platform</h2><p>An eKYC platform must combine reliable identity verification, regulatory audit trails, and integration paths that match your jurisdiction's compliance rules before blockchain credential sharing adds any value.</p><h3 id="verification-accuracy-and-liveness-controls">Verification Accuracy and Liveness Controls</h3><p>The platform must defeat presentation attacks during biometric capture. ISO/IEC 30107-3 defines Presentation Attack Detection standards that separate bona fide live captures from spoof artifacts. Your vendor should publish false accept rate and false reject rate metrics or reference third-party evaluations such as NIST FRVT PAD results.</p><h3 id="regulatory-coverage">Regulatory Coverage</h3><p>Confirm the platform supports your target markets. India V-CIP, EU eIDAS assurance levels, US Bank Secrecy Act customer identification program rules, and Singapore MAS notice requirements each impose different evidence standards. A platform certified for one jurisdiction does not automatically satisfy another.</p><h3 id="api-integration-and-developer-experience">API Integration and Developer Experience</h3><p>Engineering teams need REST APIs, webhooks, and SDKs for mobile capture flows. Time-to-integration directly affects onboarding conversion. Platforms with pre-built UI components and sandbox environments reduce pilot timelines from months to weeks.</p><h3 id="video-session-infrastructure">Video Session Infrastructure</h3><p>For regulated video KYC, the platform must deliver sub-second latency, encrypted media transport, session recording with tamper-evident storage, and agent queue management. Packet loss and jitter during a live verification call cause false rejections and abandoned applications.</p><h3 id="blockchain-readiness">Blockchain Readiness</h3><p>If you plan distributed credential sharing, confirm the platform exports standardized verifiable credentials (W3C Verifiable Credentials format) and integrates with your chosen ledger or identity network. Not every eKYC vendor supports blockchain attestation export natively.</p><p>In practice, product teams that select an eKYC vendor based on pricing alone report costly re-platforming when liveness accuracy fails regulatory review or video infrastructure cannot scale past initial pilot volume.</p><p>This section listed the verification, compliance, integration, video, and blockchain criteria that determine eKYC platform fit.</p><h2 id="future-trends-and-innovations-in-ekyc">Future Trends and Innovations in eKYC</h2><h3 id="decentralized-identity-solutions">Decentralized Identity Solutions</h3><p>One of the most promising trends in eKYC is the rise of decentralized identity solutions, where individuals control their own digital identities powered by the blockchain. It allows users to store their identity information securely on their devices and share it with service providers only when necessary. This approach reduces the dependency on centralized databases and gives users greater control over their personal information.</p><h3 id="ai-and-biometrics-in-blockchain-ekyc">AI and Biometrics in Blockchain eKYC</h3><p>The integration of AI and biometrics into blockchain-based eKYC processes is set to further enhance identity verification. AI can analyze patterns and detect anomalies in real-time, improving the accuracy of verification processes.&nbsp;</p><p>Biometrics, such as <a href="https://lenso.ai/en/blog/general/facial-recognition-what-is-it-and-why-do-we-need-it" rel="noreferrer">facial recognition</a> and fingerprint scanning, add a layer of security, ensuring that only the rightful owner of the identity can access services. Together, AI, biometrics, and blockchain initiate a powerful trio that can transform the future of eKYC.</p><p>Moreover, as regulatory requirements become more stringent, businesses will need to adapt their eKYC processes to ensure compliance. This may involve the adoption of more sophisticated verification methods and the implementation of real-time monitoring systems.</p><p>Looking ahead, the future of eKYC is likely to be characterized by greater collaboration between businesses, regulatory bodies, and technology providers. By working together, these stakeholders can create a more secure and efficient identity verification ecosystem that benefits everyone involved.</p><h2 id="conclusion">Conclusion</h2><p>As we look towards the future, the integration of AI, biometrics, and decentralized identity solutions will continue to push the boundaries of what's possible in eKYC, making identity verification not only more secure but also more user-centric.</p><p>Blockchain technology holds the potential to address many of the inherent challenges in traditional eKYC processes. By providing a decentralized, secure, and efficient way to manage identity verification, blockchain can enhance user experience, reduce operational costs, and improve compliance.&nbsp;</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-ekyc-1">What is eKYC?</h3><p>eKYC is Electronic Know Your Customer, a digital process for verifying customer identity remotely using electronic documents, biometric matching, and database validation. eKYC replaces in-person branch visits with smartphone or web-based onboarding that completes in minutes while satisfying regulatory anti-money laundering requirements.</p><h3 id="how-does-blockchain-enhance-ekyc">How does blockchain enhance eKYC?</h3><p>Blockchain enhances eKYC by storing tamper-evident verification attestations and consent records on a distributed ledger instead of duplicating raw identity documents in every institution's centralized database. Authorized parties verify credentials cryptographically without re-collecting sensitive PII, and regulators audit the complete verification history through immutable ledger timestamps.</p><h3 id="what-is-the-difference-between-ekyc-and-traditional-kyc">What is the difference between eKYC and traditional KYC?</h3><p>The difference between eKYC and traditional KYC is the verification channel. Traditional KYC requires in-person visits with physical documents and manual review. eKYC digitizes document capture, biometric checks, and database screening into an automated remote workflow that completes faster and generates structured audit trails for compliance teams.</p><h3 id="is-blockchain-ekyc-compliant-with-aml-regulations">Is blockchain eKYC compliant with AML regulations?</h3><p>Yes, blockchain eKYC is compliant with AML regulations when the verification process itself meets FATF customer due diligence standards for reliable identity proofing, and the blockchain layer provides audit trails, consent logging, and credential revocation capabilities. FATF's technology-neutral guidance applies the same CDD requirements regardless of whether records are stored centrally or on a distributed ledger.</p><h3 id="what-is-decentralized-identity-in-ekyc">What is decentralized identity in eKYC?</h3><p>Decentralized identity in eKYC is a model where customers hold verifiable credentials in a personal digital wallet and share only required attributes with each service provider. Blockchain records issuance and revocation events while the customer controls consent and selective disclosure, reducing dependency on any single institution's centralized database.</p><h3 id="how-does-video-kyc-work-with-blockchain">How does video KYC work with blockchain?</h3><p>Video KYC works with blockchain by using a live video session to verify liveness and document authenticity, then hashing the verification outcome and anchoring it on a permissioned ledger as a verifiable credential. VideoSDK handles the real-time capture and recording. The blockchain stores the tamper-evident attestation that downstream institutions verify without repeating the full video KYC session.</p><h3 id="when-should-you-not-use-blockchain-for-ekyc">When should you not use blockchain for eKYC?</h3><p>You should not use blockchain for eKYC when a single institution serves one market with no credential sharing requirement, verification volume is low, regulators have not published digital KYC guidance, or your team lacks governance frameworks for multi-party liability and revocation management. Centralized eKYC with video verification meets compliance requirements at lower complexity for these scenarios.</p>]]></content:encoded></item><item><title><![CDATA[The Future of Virtual Events: A Complete Guide for 2026]]></title><description><![CDATA[The future of virtual events is hybrid, API-driven, and data-rich. Learn 2026 trends, compare platforms, and see how VideoSDK helps developers build custom virtual event experiences.]]></description><link>https://www.videosdk.live/blog/future-of-virtual-events</link><guid isPermaLink="false">6322de0b5ed4260c94d4fb75</guid><category><![CDATA[virtual events]]></category><dc:creator><![CDATA[Sagar Kava]]></dc:creator><pubDate>Tue, 28 Jan 2025 08:17:00 GMT</pubDate><media:content url="http://assets.videosdk.live/static-assets/ghost/2021/10/Future-of-Virtual-Event--1--1.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>The future of virtual events is hybrid delivery powered by real-time video APIs, AI engagement tools, and global accessibility. Organizations run virtual and in-person tracks together, using platforms like VideoSDK for low-latency streaming and custom networking. Market growth continues as remote attendance becomes standard alongside physical venues.</blockquote><img src="http://assets.videosdk.live/static-assets/ghost/2021/10/Future-of-Virtual-Event--1--1.jpg" alt="The Future of Virtual Events: A Complete Guide for 2026"/><p>Your 2026 conference budget still allocates six figures for a single city venue, yet a growing share of registrants never book a flight. They expect a production-grade virtual track with the same keynotes, networking, and sponsor booths as the in-person crowd. The future of virtual events is not a pandemic workaround. It is a permanent revenue and reach channel that demands real-time infrastructure, measurable engagement, and hybrid design from day one. This article defines virtual events, maps market trends, compares platforms, and covers the production realities most trend posts ignore.</p><h2 id="what-are-virtual-events">What Are Virtual Events?</h2><p><a href="https://www.videosdk.live/solutions/virtual-events" rel="noreferrer">Virtual events</a> are defined as organized gatherings where participants join sessions, networking, and sponsor experiences through internet-connected devices rather than a shared physical venue.</p><p>Virtual events work by routing live audio, video, chat, polls, and breakout interactions through a real-time communication stack, typically WebRTC or adaptive streaming protocols, hosted on a dedicated virtual event platform or a custom application built with <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">video SDK APIs</a>. Attendees register online, receive access links or app credentials, and move between stages, expo halls, and private meeting rooms in a digital environment.</p><p>The format spans internal team meetings, customer webinars, multi-day conferences, trade shows, and hybrid events that run parallel in-person and remote tracks. Unlike a simple video call, production virtual events layer session scheduling, audience segmentation, sponsor analytics, and moderation tools on top of the core media pipeline.</p><p>Teams evaluating infrastructure should read about <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">what WebRTC is</a> to understand the protocol layer beneath most low-latency virtual event experiences.</p><h2 id="how-did-covid-19-accelerate-virtual-events">How Did COVID-19 Accelerate Virtual Events?</h2><p>COVID-19 permanently normalized remote attendance by forcing organizations to replicate conferences, sales kickoffs, and training programs on video platforms within weeks of global lockdowns.</p><p>According to Grand View Research, the <a href="https://www.grandviewresearch.com/industry-analysis/virtual-events-market" rel="noreferrer">global virtual events market size</a> was estimated at USD 98.07 billion in 2024 and is estimated to reach USD 297.16 billion by 2030, growing at a CAGR of 20.0% from 2025 to 2030. Webinar volume rose sharply during the pandemic; ON24 reported a 14% increase in webinar volume in 2020 compared to 2019. According to ON24, ask-me-anything and live Q&amp;A session formats also increased as marketers shifted from in-person field events to digital programming during 2020.</p><p>A Bizzabo survey of event professionals found that 97% of respondents invested in virtual event technology during the pandemic, and a majority planned to maintain virtual or hybrid formats afterward. The driving factors were instant global connectivity, lower venue and travel costs, and attendee convenience from any time zone.</p><p>Post-pandemic, virtual events did not disappear. They became a standard line item in event portfolios. Organizations that treated virtual tracks as temporary stopgaps lost sponsor revenue and attendee reach when in-person-only events resumed.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-9--2026--01_30_17-PM.png" class="kg-image" alt="The Future of Virtual Events: A Complete Guide for 2026" loading="lazy" width="1672" height="941"><figcaption><span style="white-space: pre-wrap;">Global virtual event size by 2030</span></figcaption></img></figure><h2 id="what-are-the-benefits-of-virtual-events">What Are the Benefits of Virtual Events?</h2><p>Virtual events deliver global reach, lower logistics costs, and richer attendee data than most in-person-only formats when production quality matches audience expectations.</p><h3 id="global-reach-and-inclusivity">Global Reach and Inclusivity</h3><p>Virtual events remove geographic, mobility, and visa barriers that exclude qualified attendees from in-person conferences. A developer in Lagos joins the same keynote as an executive in San Francisco without airfare or hotel costs. Language localization through live captions and AI translation expands participation further.</p><h3 id="cost-and-time-savings">Cost and Time Savings</h3><p>Event hosts reduce venue rental, catering, on-site staffing, and printed materials. According to a 2021 EventMB report, organizers reported average cost savings of 75% when shifting from in-person to virtual formats for comparable programming. Attendees save travel time and expenses, which increases registration conversion for paid events.</p><h3 id="flexibility-and-data-collection">Flexibility and Data Collection</h3><p>Virtual platforms capture session attendance duration, poll responses, chat activity, booth visits, and content downloads automatically. In-person events rely on badge scans and post-event surveys that capture a fraction of that behavioral data. Hosts replay sessions on demand, extend content shelf life, and segment follow-up campaigns by actual engagement, not just registration.</p><h3 id="technological-advancements-and-advantages-of-virtual-events">Technological Advancements and Advantages of Virtual Events</h3><p>Long before the pandemic, virtual events still existed. However, no organization found it reasonable to conduct virtual events instead of face-to-face events. Technological advancement at first laid the foundation of virtual events. The scenarios where connecting to clients was not feasible due to distance used virtual events as a channel for communication. <a href="https://www.spotsaas.com/blog/communication-technology-trends/" rel="noreferrer">Communication tools</a> like instant messaging apps, video calling apps, slack, and online webinars also boosted the popularity of virtual events long before the pandemic. <a href="https://www.emailmavlers.com/interactive-email-templates/" rel="noreferrer">Interactive email templates</a> are highly effective communication tools for webinars as they go beyond static content and encourage recipients to engage directly within the email for webinar promotion, reminders, and follow-up.</p><p>Eventually, Covid-19 turned out to be a fuel that ignited the importance of virtual events. What took years for technological evolution only took a few months for COVID-19 to spread the popularity of Virtual events!</p><p>Despite being the only option for communication during a pandemic, Virtual events also delivered exceptional benefits to the hosts. Most stereotypes stated that virtual events would take away the audience from organizations compared to in-person events. However, it turned out to be wrong. Here are many perks that you get from Virtual events.</p><h3 id="extensive-reach-to-the-audience-along-with-inclusivity">Extensive reach to the audience along with inclusivity</h3><p>In-person events, no doubt, made it lively, but there were still a massive number of participants who could not attend virtual events for many challenges. Some of these challenges were personal, while some logistical. However, virtual events enabled all participants to take part across boundaries. Even many businesses achieved long-distance selling points with the help of virtual events.</p><h3 id="saving-cost-and-time">Saving cost and time</h3><p>The virtual events proved to be cost-saving for both ends; including the hosts and the participants. Hosts reduced the cost of hosting events by 75%. Only 25% of the cost got used in setting up the right equipment to make virtual meetings possible. With many organizations already having hardware configurations, they only had to buy a virtual event platform subscription to save even more.</p><p>Besides the presenters, participants also saved costs on logistics. Most participants staying at a farther location joined the virtual meeting at a meeting platform subscription only.</p><h3 id="event-flexibility-and-easy-accumulation-of-powerful-data">Event flexibility and Easy accumulation of powerful data</h3><p>Flexibility is when you can host meetings at multiple event spaces. In-person events were limited to physical venues only. However, virtual events allow hosts to host an event from any location multiple times. The advanced virtual events platforms also make the event more accessible and interactive by offering language options. This helps you increase the number of participants as well.</p><p>The collection of data is a major part of every event. However, in-person events make it difficult to collect insights about several participants, feedback, and many more. Virtual, even, in contrast, offers you easy access to all such vital data. It includes several participants, their feedback, responses, and many more.</p><h3 id="effect-on-virtual-events-and-isolation">Effect on Virtual Events and Isolation</h3><p>Although <a href="https://www.videosdk.live/solutions/virtual-events" rel="noreferrer">virtual events</a> are a great success, they also offer limited interaction between participants and the host. Connectivity issues can sometimes obstruct chats and live interaction sessions. The users may even lose the meeting session temporarily for some time.</p><p>Isolation is a key requirement for current scenarios, but it sometimes proves to be less fruitful during virtual events. The participants, in many cases, fail to connect with the emotions of the host. Isolation also makes it boring to attend long meetings in one place.</p><h2 id="virtual-events-market-size-and-trends-for-2026">Virtual Events Market Size and Trends for 2026</h2><p>The virtual events market continues expanding as hybrid formats, <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">live streaming APIs</a>, and AI engagement tools mature across enterprise and creator use cases.</p><p>According to Grand View Research, North America held the largest regional share of the virtual events market, contributing approximately <a href="https://www.grandviewresearch.com/horizon/outlook/virtual-events-market/north-america" rel="noreferrer">39.8% of global revenue in the 2024</a> baseline period. Growth drivers include cloud video infrastructure, interactive live streaming SDKs, and demand for measurable sponsor ROI in digital expo halls.</p><p>Three trends define the future of virtual events in 2026:</p><ol><li><strong>Hybrid-first design.</strong>&nbsp;Organizers plan in-person and virtual tracks simultaneously, not as afterthoughts.</li><li><strong>API-first platforms.</strong>&nbsp;Developer teams embed video, chat, and breakout logic into branded apps instead of white-labeling generic SaaS portals.</li><li><strong>AI-assisted engagement.</strong>&nbsp;Matchmaking, live translation, session summarization, and automated moderation reduce staffing costs while improving attendee experience.</li></ol><p>The Hopin case illustrates both the opportunity and the risk. Hopin reached a reported <a href="https://www.cnbc.com/2021/08/05/virtual-events-startup-hopin-valued-at-7-75-billion.html" rel="noreferrer">$7.75 billion valuation after raising $450 million in August 2021</a>, then restructured as demand normalized post-pandemic. Market hype alone does not sustain virtual event businesses; production quality, retention, and unit economics do.</p><h3 id="the-fastest-growing-uk-based-virtual-events-startup-is-now-unicornhopin">The fastest-growing UK-based virtual events startup is now unicorn - HOPIN</h3><p>Hopin is a UK-based virtual events unicorn that has recently scaled its valuation to $7.75 Billion. On the 5th of August 2021, the company raised another $ 450 Million in funding to reach its peak. It is one of the fastest-scaling tech startups that has beat many of Europe’s largest private sector companies. In March 2020, with a valuation of $ 5 billion, the startup first gained the fastest scaling company title and is now way bigger. Johnny Boufarhat is the founder of Hopin, who started the firm back in 2019. COVID-19 turned out to be the biggest turnover for the company and made it an event unicorn. The company has grown to 800 employees in 47 nations worldwide. </p><h3 id="a-new-frontier-for-virtual-events-platforms-to-expand">A new frontier for Virtual Events Platforms to expand</h3><p><strong>Hybrid Events </strong></p><p>Hybrid virtual events will be the standard choice in the post-pandemic world. If you're creating time-lapse cutaways of room turnarounds for hybrid recaps, dependable <a href="https://fixthephoto.com/best-projectors-for-presentations.html" rel="noreferrer">projectors for presentations</a> keep in-venue visuals crisp while you shoot. This allows organizers unparalleled reach &amp; profit. Further, this could lead to interesting ideas &amp; avenues where both the virtual &amp; non-virtual could interact, play games, and network. To bridge the physical and digital experience, organizers are increasingly using QR codes generated with tools like&nbsp;<a href="https://www.the-qrcode-generator.com/" rel="noopener noreferrer">The QR Code Generator</a>, Uniqode, Canva, and&nbsp;<a href="https://qrscanner.net/qr-code-generator" rel="noopener noreferrer">QRScanner.net</a>&nbsp; to let in-person attendees instantly access live polls, feedback forms, or event materials from their mobile devices, boosting real-time engagement. To make these interactions more impactful, organizers and attendees can use tools like QR-based event badges, LinkedIn QR codes, or <a href="https://www.uniqode.com/digital-business-card" rel="noreferrer">Uniqode’s business card</a> to exchange contact information instantly during sessions. These digital networking aids help participants follow up easily, especially when time is limited or face-to-face interaction isn’t always feasible.</p><p><strong>Virtual Studio</strong></p><p>The next wave is virtual studios, now these platforms are focusing on extending in the creator economy. Providing first-class studio support for creator platforms like YouTube, Facebook, etc. Zuddi just launched their Studio a month back as a private beta to experiment on the creator market.</p><p><strong>Virtual Co-working</strong></p><p>Apart from this, in the multiverse, a couple of companies are experimenting with virtual offices to drive the engagement of their existing customers with another solution. Companies like SoWork are facilitating virtual work to encourage diversity in the workplace and counter climate change.</p><p> </p><figure class="kg-card kg-image-card"><img src="http://assets.videosdk.live/static-assets/ghost/2021/11/Future-of-Virtual-Event--1-.jpg" class="kg-image" alt="The Future of Virtual Events: A Complete Guide for 2026" loading="lazy" width="1600" height="900"/></figure><h3 id="virtual-events-future-prediction">Virtual Events Future Prediction</h3><p>The future prediction about virtual events states 40.37% growth till the end of 2021. The market impact after the pandemic will remain neutral, as users are well-versed in the benefits of virtual events. Several players are occupying the market. But the North will continue to contribute the highest with a 29% boost. However, professionals predict that the future will bring an amazing amalgamation of in-person and virtual events. </p><p>Virtual is at the frontier of opportunities and unexplored spaces, and we didn’t even mention the gaming industry or the metaverse or VR headsets! The possibilities are yet to be explored. Experts strongly believe that virtual is going to change the status quo. However, there’s a lot of work that needs to be done to make that vision a reality. Startups and event management companies being more strategic about the fact that will revolutionize free-style socializing events.</p><h2 id="why-virtual-events-fail-without-the-right-infrastructure">Why Virtual Events Fail Without the Right Infrastructure</h2><p>Virtual events fail when organizers optimize for registration volume instead of real-time reliability, engagement design, and post-event measurement.</p><p>The most common production failure modes include:</p><ul><li><strong>Latency and A/V quality.</strong>&nbsp;Remote attendees leave when audio drifts, video buffers, or screen shares freeze. WebRTC-based stages with adaptive bitrate outperform raw <a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer">RTMP</a> passthrough for interactive sessions.</li><li><strong>Networking fatigue.</strong>&nbsp;Passive chat boxes do not replicate hallway conversations. Structured speed networking, AI matchmaking, and moderated breakout rotations keep remote attendees connected past the first keynote.</li><li><strong>Sponsor ROI gaps.</strong>&nbsp;Digital expo halls without visit tracking, lead capture, and follow-up automation disappoint sponsors who compare results to in-person booth traffic.</li><li><strong>Moderation overload.</strong>&nbsp;Open chat on large streams attracts spam and derails Q&amp;A. Teams need dedicated moderators and tooling for flagged content, not just a "disable chat" fallback.</li></ul><p>In practice, event teams that treat the virtual track as a lower-budget mirror of the in-person program see 50 to 70% drop-off before the second session. Teams that assign separate virtual producers, engagement hosts, and technical directors retain audiences through full-day programs.</p><p>Acknowledging these limits is not pessimism. It is how organizers allocate budget to the infrastructure and staffing that determine whether the future of virtual events delivers revenue or reputational damage.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-9--2026--01_46_32-PM.png" class="kg-image" alt="The Future of Virtual Events: A Complete Guide for 2026" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">future of virtual events common failure modes and fixes</span></figcaption></img></figure><h2 id="conclusion">Conclusion</h2><p>The future of virtual events belongs to organizations that design hybrid experiences with the same rigor they apply to physical venues. Market growth continues, attendee expectations have risen, and off-the-shelf portals no longer satisfy teams that need branded, data-rich event products. Start by defining your build-vs-buy decision, measure engagement beyond registrations, and invest in real-time infrastructure that survives peak concurrent attendance. If you are building a custom virtual event experience, get your VideoSDK API keys and ship your first interactive stage this week.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-future-of-virtual-events">What is the future of virtual events?</h3><p>The future of virtual events is hybrid delivery where in-person and remote attendees share the same programming, sponsors, and networking through real-time video platforms and AI engagement tools. Organizations treat virtual tracks as permanent revenue channels, not pandemic-era experiments.</p><h3 id="are-virtual-events-still-popular-after-covid">Are virtual events still popular after COVID?</h3><p>Yes, virtual events remain popular after COVID because they extend global reach, reduce travel costs, and generate measurable engagement data. According to Grand View Research, the virtual events market continues growing at a projected 20.0% CAGR from <strong>2025 to 2030</strong>.</p><h3 id="what-are-the-benefits-of-virtual-events-1">What are the benefits of virtual events?</h3><p>The benefits of virtual events include global accessibility, lower logistics costs, flexible scheduling, on-demand replay, and automated analytics on attendance and engagement. Hosts capture behavioral data that in-person badge scans alone cannot provide.</p><h3 id="what-is-a-hybrid-virtual-event">What is a hybrid virtual event?</h3><p>A hybrid virtual event is a conference or meeting that runs a physical venue program alongside a synchronized virtual track for remote attendees. Both audiences access keynotes, sponsors, and networking through shared or parallel digital tools.</p><h3 id="how-do-you-plan-a-virtual-event">How do you plan a virtual event?</h3><p>You plan a virtual event by defining audience goals, choosing a platform or SDK, designing interactive session formats, running a technical rehearsal, staffing virtual-specific roles, and configuring analytics before registration opens. Engagement features should be scheduled into every session, not added as an afterthought.</p><h3 id="which-virtual-event-platform-is-best-for-developers">Which virtual event platform is best for developers?</h3><p>VideoSDK is the best virtual event platform for developers building custom branded experiences that require programmatic control over rooms, roles, and analytics. Zoom Events and RingCentral Events suit teams that prefer turnkey portals over SDK integration.</p><h3 id="can-virtual-events-replace-in-person-conferences-entirely">Can virtual events replace in-person conferences entirely?</h3><p>Virtual events cannot fully replace in-person conferences for relationship-driven industries that depend on unstructured hallway networking and physical product demos. Hybrid formats capture the reach advantages of virtual delivery while preserving high-value in-person interactions.</p>]]></content:encoded></item><item><title><![CDATA[Grow Your Edtech Business]]></title><description><![CDATA[Expand your ed-tech business. Flourish your platform with extraordinary technologies and add value to it.]]></description><link>https://www.videosdk.live/blog/grow-edtech-business</link><guid isPermaLink="false">6322de0b5ed4260c94d4fb68</guid><category><![CDATA[edtech]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 28 Jan 2025 04:19:00 GMT</pubDate><media:content url="http://assets.videosdk.live/static-assets/ghost/2021/07/Integrate-It-Anywhere-2.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://assets.videosdk.live/static-assets/ghost/2021/07/Integrate-It-Anywhere-2.jpg" alt="Grow Your Edtech Business"/><p>Virtual classrooms have today been one of the most useful teaching and learning tools. It has today been one of the trendiest techniques of teaching. Just be in one place and explore all the learning. These classrooms have made learning simpler. This has also become an advantage for tutors as they can engage a large crowd of students at once. These classrooms can also be broadcasted on multiple platforms, multiplying the reach. <br/></p><blockquote>At videosdk.live, we dedicate our products to education. Building several educational classrooms on a virtual platform we always try to make a tutor’s teaching and a student’s learning experience simplified. We have designed several classrooms as per the needs of the tutor. These classrooms are fully functional with amazing attributes and the best part is that they can be fully customized as per the teaching needs.</blockquote><p><br><strong>Our classroom designs</strong></br></p><p><strong>How to create super awesome classrooms with customization and ease</strong></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://assets.videosdk.live/static-assets/ghost/2021/07/one-to-one-video-chat.jpg" class="kg-image" alt="Grow Your Edtech Business" loading="lazy" width="1600" height="900"><figcaption><span style="white-space: pre-wrap;">Small Classrooms</span></figcaption></img></figure><h3 id="1-small-classrooms">1. Small classrooms</h3><p>We also help tutors and students with one-to-one mentoring, <strong>engaging and enhancing personal attention</strong> towards learning. Keeping that in mind, we have designed classrooms where a student and a teacher can converse with each other, making engrossed and attentive learning. The students get personal guidance with a student-teacher ratio of 1:1. Combined with modern educational technology, students can also study with AI to receive additional learning support and personalized assistance outside classroom sessions.<br/></p><p>When an educator focuses on bringing up a leader, he handpicks the students he visions as future leaders and coaches them for the path he aspires, under his guidance. Videosdk.live small classroom platform also fulfills a tutor’s vision to guide students in a small group of 5 to 10 students, giving them personal guidance and attentiveness. <br/></p><p>These classrooms give tutors full-fledged flexibility with operations and customization. The students can<strong> interact, debate and discuss</strong> with each other making the virtual platform a living classroom. We design classrooms with scalability, and high performative facets like whiteboards, media, and document uploads, with active screen sharing, which makes it more lively and engaging. When only certain sections of a workbook or manual are needed, sharing the entire PDF can create unnecessary distraction. Using a <a href="https://www.canva.com/features/extract-pages-from-pdf/" rel="noreferrer">PDF page extractor</a> to save selected pages as a new document with Canva helps instructors upload only the materials relevant to each lesson. This also helps a tutor to derive active communication within the smaller group to make big changes for their better future.<br/></p><p>Small classrooms are fully functional with engaging tools. We allow customization for the classrooms, as per the needs of teaching. To make a small classroom, there is a paramount step that is required before commencing some fruitful learning and discussions. Follow the below link and create a wonderful classroom all with a lively environment.</p><p><a href="https://docs.videosdk.live/docs/tutorials/realtime-communication/prebuilt-sdk/quickstart-prebuilt-js">https://docs.videosdk.live/docs/tutorials/realtime-communication/prebuilt-sdk/quickstart-prebuilt-js</a> </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://assets.videosdk.live/static-assets/ghost/2021/07/Real-time-large-classes.jpg" class="kg-image" alt="Grow Your Edtech Business" loading="lazy" width="1600" height="900"><figcaption><span style="white-space: pre-wrap;">Large Classrooms</span></figcaption></img></figure><h3 id="2-large-classrooms">2. Large classrooms</h3><p>Videosdk.live offers tutors to teach a large number of students at once. These rooms can accommodate 5,000 students at once. The tutor gets the authority of admitting, muting, and unmuting, and screen sharing on his own. These lecture rooms can be made interactive as well as non-interactive by the tutor. Videosdk.live provides amazing features for a large classroom which can be recorded and played on-demand. <br/></p><p>With a full-fledged useful explanation board and amazing real-time audio and video quality, we deliver the participants with screen sharing, query raising, active real-time chat with supportable audio and video quality. We support more than 98% of devices. We make features that can coordinate with a large number of people together, in an unchaotic way. We also develop <strong>highly coordinative audio quality</strong> with 360 spatial audio with voice changing and audio mixer, making the session lively. Our end-to-end encrypted video communication stands for a <strong>secured classroom learning.</strong> <br/></p><p>Large classrooms are worth it when a tutor wants to deliver tutoring to a large number of people at once explaining with unlimited time allotment. Videosdk.live builds this amazing platform for education. Develop a platform for educating a huge number of people within 10 minutes. Catch the below informative link to start a classroom instantly.</p><p><a href="https://docs.videosdk.live/docs/tutorials/realtime-communication/js-sdk/quickstart-js">https://docs.videosdk.live/docs/tutorials/realtime-communication/js-sdk/quickstart-js</a> </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://assets.videosdk.live/static-assets/ghost/2021/07/Go-live-anytime.jpg" class="kg-image" alt="Grow Your Edtech Business" loading="lazy" width="1600" height="900"><figcaption><span style="white-space: pre-wrap;">Live Classrooms</span></figcaption></img></figure><h3 id="3-live-classrooms">3. Live classrooms</h3><p>To an educator who believes that education is something worth delivering to each one, located remotely, but active to learning. What can be better than live classrooms? A live classroom <strong>streams to a million attendees</strong>, where a tutor gets huge engagement and can teach with full flexibility. <br/></p><p>Videosdk.live provides tutors with high-quality streaming, favorable in unstable network conditions. We provide<strong> streaming over multiple platforms</strong> at once, enriching the audience count. With adaptive streaming, we deliver tutors with dedicated features like screen sharing, recording, and on-demand playback. The viewers can communicate via chatbox and can use it to post queries and comments in respect of the tutor.<br/></p><p>Live streaming can be organized to attract huge engagements by the tutor for what he teaches. A tutor can develop a live stream within a few minutes and make his tutoring live over the internet covering mass learning. To make access even more seamless for students joining from different devices or environments, tutors can generate QR codes using <a href="https://www.uniqode.com/qr-code-generator" rel="noreferrer">Uniqode's QR generator</a>, Canva, etc., to enable quick scan-and-join access to live sessions. Build live streaming for the masses within a few minutes. Study the below-given link and make your steaming.</p><p><a href="https://docs.videosdk.live/docs/tutorials/live-streaming/api/quickstart-rest-api">https://docs.videosdk.live/docs/tutorials/live-streaming/api/quickstart-rest-api</a> </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://assets.videosdk.live/static-assets/ghost/2021/07/Upload-video-from-anywhere.jpg" class="kg-image" alt="Grow Your Edtech Business" loading="lazy" width="1600" height="900"><figcaption><span style="white-space: pre-wrap;">Pre-recorded Classrooms</span></figcaption></img></figure><h3 id="4-pre-recorded-classrooms">4. Pre-recorded classrooms</h3><p>Videosdk.live being highly cooperative with the tutor and student, creating pre-recorded rooms of learning. These classrooms are filled up with lectures that are pre-recorded. A tutor, who desires to deliver a lecture but cannot manage live possibilities, <strong>can record a lecture and stream</strong> it at a scheduled time of his choice. These lectures are pre-recorded, encoded in the UI libraries, and hosted once demanded. Once hosted, these lessons can be distributed to your mailing database on platforms like <a href="https://www.getresponse.com/" rel="noreferrer">GetResponse</a>, Brevo, ActiveCampaign or Mailchimp.</p><p>The ease with these classrooms is that a tutor gets to explain his course all at once without any network lags. The students can reach out to the recorded lectures whenever they wish, as per their flexibility. This <strong>uninterrupted lecture recording</strong> can also be attached with slides and videos for better understanding. With adaptive streaming, we ensure secured accessibility for the students.<br/></p><p>Pre-recorded classroom gathers a large engagement of students as they can view these lectures on a loop until completely understood. Also, they can post their queries to the lecturer later and can review them for further help. Take a glance at how to build a pre-recorded classroom. Refer to the link below.</p><p><a href="https://docs.videosdk.live/docs/tutorials/video-on-demand/api/quickstart-rest-api">https://docs.videosdk.live/docs/tutorials/video-on-demand/api/quickstart-rest-api</a> <br/></p><blockquote>Also, refer to our blog that describes how Videosdk.live makes education entertaining and enjoyable gathering masses together. You can refer to this link to learn how we keep education on one of the most dedicated use cases.</blockquote><p><strong>(</strong><a href="https://videosdk.live/blog/engage-ed-tech-business"><strong>Preview Part 1</strong></a><strong>)</strong></p>]]></content:encoded></item><item><title><![CDATA[Engage Your Edtech Business]]></title><description><![CDATA[The education system has shifted all its focus towards growing e-learning classrooms, adapting to new technologies for an augmented teaching and learning system]]></description><link>https://www.videosdk.live/blog/engage-ed-tech-business</link><guid isPermaLink="false">6322de0b5ed4260c94d4fb67</guid><category><![CDATA[edtech]]></category><category><![CDATA[video-conferencing]]></category><category><![CDATA[live-streaming]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 27 Jan 2025 18:10:00 GMT</pubDate><media:content url="http://assets.videosdk.live/static-assets/ghost/2021/07/Real-time-small-classes-2.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://assets.videosdk.live/static-assets/ghost/2021/07/Real-time-small-classes-2.jpg" alt="Engage Your Edtech Business"/><p>The modern education system works on the idea of teaching students in a virtual classroom environment, the reason being, it attracts mass learning. Education, always being a top priority, needs the most advanced technology to date. We all have started learning at big institutes under the guidance of experts, sitting at our homes. It is just because of technology that we have expanded our reach of learning.<br/></p><p>For students, today a student or a learner can reach any place to learn without stepping out of his room. Everything has become virtual. They can reach out to educators from a different city, and also a different country. Simply, Education has no boundaries. This is all possible due to technological advancements in the sector. We can communicate over <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">video conferencing</a>, webinars, live streaming, and also one-to-one meeting with educators. <br/></p><p>For educators, it comes out to be a great opportunity when they can teach over the internet. A tutor or an educator can today teach a student from any part of the world, sitting at his home. The benefits are enormous, it saves time, cost, and energy. Also, the tutor gets a wide reach of students, establishing his student map. Nonetheless, technology in education, aka online learning is a boon towards an educated economy.  <br/></p><p>Videosdk.live looks for the betterment of education with the help of technology. We design products that help towards enhancing the educational growth of the community. We design APIs and SDKs for real-time communication, customizable to the teaching needs concerning a better communication system. We cater products like scalable audio and video streaming, along with live streaming and video conferencing APIs. Being highly dedicated to the promotion of virtual classroom education, we regularly design products that benefit this community.<br/></p><h3 id="how-do-we-build-interactive-classrooms">How do we build interactive classrooms?</h3><p>Online education, or simply ed-tech, requires several technologies to connect a teacher and a learning community. E-learning with videosdk.live comes with enthusiasm. We design products with full customization as per teaching needs. We develop products that ensure effortless management of work on a virtual platform. We look for simplicity, constituting easy-to-use teaching tools. Our products make it possible to connect with large masses at once in the least time.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://assets.videosdk.live/static-assets/ghost/2021/07/Real-time-small-classes-1.jpg" class="kg-image" alt="Engage Your Edtech Business" loading="lazy" width="1600" height="900"><figcaption><span style="white-space: pre-wrap;">Real-time Communication</span></figcaption></img></figure><h3 id="1-real-time-audio-and-video-communication">1. <a href="https://docs.videosdk.live/docs/realtime-communication/intro">Real-time audio and video communication</a></h3><p>Videosdk.live curates a live interactive session with real-time voice, video, and chat support, designed with no lags in connectivity. The educators and students can connect easily with our technologies. A wholesome quality experience where teaching can be done as personal tutoring, teaching a small batch, and teaching a large group. We have developed teaching tools with an extraordinary essence.<br/></p><ul><li><strong>Video conferencing</strong></li></ul><p>A well-developed video conferencing API that makes room for 5000 participants at once, consequently with no time limitations. Secured and stable, one can easily address their presence in a meeting without entering passcodes. We value your time. We provide tutors with host access, whiteboard technology, and supportable screen sharing and the ability to <a href="https://www.uniqode.com/qr-code-generator" rel="noreferrer">incorporate QR codes</a> for quick access. Our scalable video conferencing makes access for more than 98% of devices, aiming technology to not be a barrier in learning.<br/></p><ul><li><strong>Audio conferencing</strong></li></ul><p>Videosdk.live also provides one-to-one and group voice calls. Students and teachers can also communicate with each other for clearing small doubts and queries with audio calls. Voice calls are a faster communication tool for small conversations. We have designed the audio call APIs with cloud recording. We support audio conferencing with more than 5000 participants at once and that’s huge!</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://assets.videosdk.live/static-assets/ghost/2021/07/Go-live-anytime-1.jpg" class="kg-image" alt="Engage Your Edtech Business" loading="lazy" width="1600" height="900"><figcaption><span style="white-space: pre-wrap;">Live Streaming</span></figcaption></img></figure><h3 id="2-live-streaming">2. <a href="https://docs.videosdk.live/docs/live-streaming/intro">Live Streaming</a></h3><p>We provide live streaming with a scalable quality and huge mass access. It can be interactive as well as non-interactive. We support streaming with unlimited participants at a scalable quality for uninterrupted learning. Live streaming supports 98% of devices along with flexible screen resolution and internet bandwidth. We support cloud stream recording with an on-demand video streaming facility. </p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://assets.videosdk.live/static-assets/ghost/2021/07/On-Demand-Courses-1.jpg" class="kg-image" alt="Engage Your Edtech Business" loading="lazy" width="1600" height="900"><figcaption><span style="white-space: pre-wrap;">On-demand Video Streaming</span></figcaption></img></figure><h3 id="3-on-demand-videos">3. <a href="https://docs.videosdk.live/docs/video-on-demand/intro">On-demand Videos</a></h3><p>We provide on-demand video streaming facilities to view the streaming videos and other recorded videos. This makes students help themselves by re-watching the videos for better study help. The teachers can also pre-record videos to help students play videos at their learning speed. We allow the facility of play and pause to make learning at a gradual speed. Our on-demand facility allows watching recorded video meetings and live streaming after being broadcasted. On-demand videos help students in designing a learning pattern, and teachers for reviewing old videos for new and more classified explanations. This also reflects how students now <a href="https://www.mindgrasp.ai/" rel="noreferrer">study with AI</a> tools to revise concepts, understand lessons faster, and follow a more flexible learning pace. These videos can also be repurposed for broader <a href="https://www.distribution.ai/blog/content-distribution" rel="noreferrer">content distribution</a>, helping educators extend their reach.<br/></p><h3 id="how-do-we-make-your-classroom-worth-it">How do we make your classroom worth it?</h3><p>Videosdk.live always focuses on quality. With a never compromising attitude, we make experiences worth sharing in the community. Our quality development with generous attributes makes us mark above the standard level. We look for the best delivery of products to make learning better and qualitative. Our APIs and SDKs make sure that we define a classroom worth learning and teaching, all with a cohesive bond.<br/></p><ol><li><strong>Customization as per need</strong></li></ol><p>Videosdk.live provides full customization to a classroom meeting. All the necessary adjustments can be made with the provided label. We ensure a structured classroom delivery to you and you can even add more stars to it. We are flexible with changes to our APIs for learning and education<br/></p><p><strong>2. Astounding audio and video quality</strong></p><p>With amazing customizable classrooms, the quality of audio and video that we provide is beyond par. Our HD audio and video quality, active speaker switch, noise cancellation, speaker’s window switch and more, make our learning rooms worth employing for education. <br/></p><p><strong>3. Fully functional attributes</strong></p><p>Videosdk.live classrooms contain supreme attributes. We cater to whiteboard, real-time audio, video, and messaging, along with customizations. Supporting quality education, our tools help tutors to keep the students engaged.  <br/></p><p><strong>4. Dedicated scalability</strong></p><p>Focusing on screen resolution and high-quality video delivery, we ensure scalability by supporting a majority of devices. Ensuring that learning must carry on even in unfavorable network conditions, we keep up with the latest technologies to meet the best video and audio quality for the student and teacher community. <br/></p><p>Videosdk.live develops several customized classrooms for effective learning. Want to learn how we benefit educators and students with our exclusive classrooms? <br>Find out how to develop effective and effortless classrooms at videosdk.live. </br></p><p>Click here (<a href="https://app.videosdk.live/dashboard"><strong>Try Now</strong></a>)</p><blockquote><strong>We value education!</strong></blockquote><p><strong>(</strong><a href="https://www.videosdk.live/blog/grow-edtech-business"><strong>Next Part 2</strong></a><strong>)</strong></p>]]></content:encoded></item><item><title><![CDATA[Ultimate Guide to React Icons Enhancing Your Web Projects with Scalable Graphics]]></title><description><![CDATA[Explore the essentials of React Icons in this guide, from setup to advanced usage. Learn how to integrate and style icons within your React projects for improved performance and design.]]></description><link>https://www.videosdk.live/blog/react-icons-guide</link><guid isPermaLink="false">661b9dee2a88c204ca9d0c51</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 27 Jan 2025 04:42:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/luke-peters-B6JINerWMz0-unsplash-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2024/04/luke-peters-B6JINerWMz0-unsplash-1.jpg" alt="Ultimate Guide to React Icons Enhancing Your Web Projects with Scalable Graphics"/><p>React Icons is a library that gives React developers access to over 40,000 SVG icons from Font Awesome, Material Design, Heroicons, Bootstrap Icons, and 25+ other popular icon sets through a single npm package. Each icon renders as a native React component, supports tree-shaking to keep bundle sizes small, and accepts standard CSS props for instant styling. Install with&nbsp;<code>npm install react-icons</code>&nbsp;and import any icon directly by name.</p><h2 id="what-is-the-react-icons-library-and-why-do-developers-use-it">What Is the React Icons Library and Why Do Developers Use It?</h2><p>React Icons is defined as a unified npm package that bundles SVG icon components from more than 25 popular icon collections, letting React developers import any icon in a single line without manually sourcing or hosting SVG files. React Icons works by converting each individual icon into a standalone React component that accepts&nbsp;<code>size</code>,&nbsp;<code>color</code>,&nbsp;<code>className</code>, and&nbsp;<code>style</code>&nbsp;props, making it trivially simple to compose icons into any JSX tree.</p><p>The library was created to solve a specific friction point: every major icon set (Font Awesome, Material Icons, Heroicons, Feather, Bootstrap Icons, Ant Design Icons, Remix Icons, Tabler Icons) ships its own installation, its own import syntax, and its own API. Before React Icons, a team using Font Awesome for toolbar actions, Material Icons for status indicators, and Feather for form fields needed three separate packages, three different import conventions, and three different styling approaches.</p><p>React Icons normalizes all of that. Every icon, regardless of its source library, follows the same import pattern and accepts the same props. A Font Awesome icon and a Material icon behave identically in your codebase once imported.</p><p>The library is maintained as an open-source project and receives regular updates as the upstream icon sets release new versions. As of the most recent release, React Icons includes collections from Font Awesome 6, Material Design Icons, Heroicons 2, Bootstrap Icons 1.11, Ant Design Icons 5, Feather Icons, Ionicons 5, Remix Icons, Tabler Icons, Phosphor Icons, and more.</p><h3 id="diagram-for-installing-react-icons">Diagram for Installing React Icons</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/05/diagram--1-.png" class="kg-image" alt="Ultimate Guide to React Icons Enhancing Your Web Projects with Scalable Graphics" loading="lazy" width="1868" height="882"/></figure><h3 id="installation-and-basic-setup-fro-react-icons">Installation and Basic Setup fro React Icons</h3><p>To get started with <a href="https://www.npmjs.com/package/react-icons">React Icons</a>, you need to install the package via npm, which is straightforward:</p><pre><code class="language-bash">npm install react-icons --save</code></pre><p>Once installed, you can begin using the react icons in your React project by importing them directly from the library. Here's a basic example of how to use an icon:</p><pre><code class="language-javascript">import { FaBeer } from 'react-icons/fa';

function App() {
  return &lt;h3&gt;Let's have a &lt;FaBeer /&gt; tonight!&lt;/h3&gt;;
}
</code></pre><p>This code snippet demonstrates the simplicity of incorporating an icon directly into your React components. The <code>{ FaBeer }</code> import represents a beer icon from the Font Awesome collection, which can be rendered as part of your JSX code.</p><p>React Icons provides a versatile and performance-efficient solution for using icons in React applications. By enabling developers to import only the icons they need, it ensures that the application remains lightweight and fast. As you proceed to integrate React Icons into your projects, you will appreciate the flexibility and aesthetic enhancement they bring to your user interfaces.</p><h2 id="exploring-icon-libraries-and-usage-with-react-icons">Exploring Icon Libraries and Usage with React Icons</h2><p>React Icons amalgamates several popular icon libraries, offering a vast selection of icons suitable for various design needs. This section delves into these libraries, discusses advanced icon configuration, and explores dynamic icon usage, providing you with the tools to enhance your project's visual and interactive aspects.</p><h3 id="icon-libraries-overview">Icon Libraries Overview</h3><p>React Icons integrates icons from multiple libraries, including FontAwesome, MaterialIcons, and Bootstrap Icons, among others. This integration offers a unified way to access a wide range of icons, from social media symbols to <a href="https://www.designmantic.com/how-to/how-to-get-cheap-logo-design-for-business" rel="noreferrer">business icons</a>, all within your React applications.</p><p><strong>FontAwesome:</strong> Known for its comprehensive collection of icons, FontAwesome is frequently used for its versatility and wide acceptance.</p><p><strong>MaterialIcons:</strong> These are grounded in Material Design principles and offer clean, UIUX designs<strong> </strong>and graphics perfect for modern web interfaces.</p><p><strong>Bootstrap Icons:</strong> Bootstrap Icons are specifically designed to work seamlessly with Bootstrap components but are versatile enough to be used in other contexts.</p><p>Using icons from these libraries is straightforward. For instance, to use a heart icon from FontAwesome, you would import it like so:</p><pre><code class="language-js">import { FaHeart } from 'react-icons/fa';</code></pre><p>This single line of code allows you to render a heart icon anywhere within your React components.</p><h3 id="advanced-icon-configuration">Advanced Icon Configuration</h3><p>To globally configure icons in your project, React Icons provides the <code>IconContext.Provider</code>. This component allows you to set default properties for all icons, such as size, color, and style, reducing the need to individually style each icon.</p><p>Here’s how you can set global properties for your icons:</p><pre><code class="language-js">import { IconContext } from 'react-icons';

function App() {
  return (
    &lt;IconContext.Provider value={{ color: 'blue', size: '50px' }}&gt;
      &lt;div&gt;
        &lt;FaHeart /&gt;
        {/* other components */}
      &lt;/div&gt;
    &lt;/IconContext.Provider&gt;
  );
}
</code></pre><p>This configuration sets all icons within the <code>Provider</code> to be blue and 50 pixels in size, ensuring consistency across your app without repeated code.</p><h3 id="dynamic-icon-usage">Dynamic Icon Usage</h3><p>React Icons can also dynamically change based on application state. This is particularly useful for interactive elements like buttons or toggles, where the icon might change in response to user actions.</p><p>For example, you can create a toggle button that switches between a "plus" and "minus" icon based on whether a section is expanded or collapsed:</p><pre><code class="language-js">import { useState } from 'react';
import { AiOutlinePlus, AiOutlineMinus } from 'react-icons/ai';

function ToggleButton() {
  const [isOpen, setIsOpen] = useState(false);

  return (
    &lt;button onClick={() =&gt; setIsOpen(!isOpen)}&gt;
      {isOpen ? &lt;AiOutlineMinus /&gt; : &lt;AiOutlinePlus /&gt;}
    &lt;/button&gt;
  );
}
</code></pre><p>This snippet demonstrates the use of React state to conditionally render different icons, providing an intuitive visual cue for the user.</p><p>The React Icons library not only simplifies the process of integrating icons but also enhances the flexibility and functionality of your UI components. By leveraging the extensive libraries available and utilizing advanced configuration options, you can create a more engaging and visually appealing user experience. In the following sections, we will explore practical applications and best practices to optimize the performance and accessibility of these icons within your projects.</p><p>Practical Applications and Best Practices for React Icons</p><p>In this section, we delve into the practical applications of React Icons within a project, discussing how to optimize their performance and ensure accessibility, alongside tips for effective styling and customization. When building interfaces with sequential steps or interactive flows, React Icons help communicate actions clearly, and an <a href="https://venngage.com/ai-tools/flowchart-generator" rel="noreferrer">AI-powered flowchart creator</a> can also assist in designing structured visuals that complement your UI components. By adhering to these best practices, developers can enhance both the user experience and the technical quality of their applications.</p><h3 id="performance-optimization">Performance Optimization</h3><p>Optimizing the performance of React Icons is crucial for maintaining fast load times and efficient rendering in your application. If your workflow includes prepping SVG assets or running design tools alongside the dev server, a capable <a href="https://fixthephoto.com/best-computer-for-graphic-design.html" rel="noreferrer">computer for graphic design</a> helps keep previews, exports, and builds responsive. Here are several strategies:</p><p><strong>Selective Importing</strong>: Import only the icons you use within your components rather than entire libraries. This minimizes bundle size significantly.</p><pre><code class="language-js">import { FaBeer } from 'react-icons/fa';</code></pre><p>This code demonstrates importing a single icon rather than all FontAwesome icons, which keeps your application lightweight.</p><ol><li><strong>Lazy Loading</strong>: For applications using a large number of icons or large sets, consider lazy loading icons that aren't immediately visible to the user. This can be achieved by dynamic imports in React.</li><li><strong>Use SVGs Appropriately</strong>: Since React Icons are SVG elements, ensure that they are not re-rendered unless necessary. Utilizing React’s memoization or shouldComponentUpdate lifecycle method can prevent unnecessary re-renders.</li></ol><h3 id="accessibility-considerations">Accessibility Considerations</h3><p>Ensuring that icons are accessible is key to creating inclusive web applications. Here are some tips to enhance icon accessibility:</p><ol><li><strong>Aria Labels</strong>: Add appropriate <code>aria-label</code> attributes to icons that serve as interactive elements, providing a text description that screen readers can announce.</li><li><strong>Keyboard Accessibility</strong>: Ensure that icons used as buttons or links are focusable and can be triggered using the keyboard. Wrapping them in <code>&lt;button&gt;</code> or <code>&lt;a&gt;</code> tags can achieve this.</li><li><strong>Semantic HTML</strong>: Use appropriate HTML elements for icons depending on their function. Icons that trigger actions should be buttons, while icons for decoration should use a <code>&lt;span&gt;</code> with <code>role="img"</code> and an aria-label.</li></ol><h2 id="faqs-and-troubleshooting-common-issues-with-react-icons">FAQs and Troubleshooting Common Issues with React Icons</h2><p>In this final section of our comprehensive guide to React Icons, we address some frequently asked questions and provide troubleshooting tips for common issues that developers may encounter while using this library. This segment is designed to enhance your troubleshooting skills and help you resolve typical problems efficiently.</p><h3 id="frequently-asked-questions-faqs">Frequently Asked Questions (FAQs)</h3><p><strong>How do I ensure React Icons are properly aligned with text?</strong></p><ul><li>Icons may not always align perfectly with adjacent text. To fix alignment issues, wrap your icon and text in a flex container and use CSS to align items to the center.</li></ul><pre><code class="language-js">&lt;div style={{ display: 'flex', alignItems: 'center' }}&gt;
  &lt;FaBeer /&gt; &lt;span&gt;Enjoy responsibly!&lt;/span&gt;
&lt;/div&gt;
</code></pre><p><strong>Can I use multiple icon libraries in one project?</strong></p><ul><li>Yes, you can import icons from different libraries within the same project. However, be mindful of the overall size of your bundle and the performance implications of importing many libraries.</li></ul><p><strong>What should I do if an icon does not appear as expected?</strong></p><ul><li>Ensure that the import statement is correct and points to the right library. It’s common to mistakenly import an icon from a different library or misspell the icon name.</li></ul><p><strong>How can I change the color and size of an icon dynamically?</strong></p><ul><li>You can dynamically style icons using inline styles or CSS classes based on state or props. Here’s a simple example with inline styling:</li></ul><p><strong>Are there any accessibility concerns I should be aware of when using icons as buttons?</strong></p><ul><li>When using icons as interactive elements like buttons, ensure they are wrapped in <code>&lt;button&gt;</code> tags, have accessible labels, and are focusable for keyboard-only users.</li></ul><h3 id="troubleshooting-common-issues">Troubleshooting Common Issues</h3><p><strong>Icon Import Errors:</strong></p><ul><li>Double-check your import statements for typos. Use the exact name as defined in the library, and ensure that your project's dependencies include the icon library.</li></ul><p><strong>Icons Not Rendering:</strong></p><ul><li>Verify that the icon components are correctly implemented in the JSX. Check if there are any console errors related to SVG or React component rendering.</li></ul><p><strong>Performance Issues with Large Number of Icons:</strong></p><ul><li>If performance is impacted by the use of many icons, consider implementing code splitting or dynamically importing icons only when they are needed.</li></ul><p><strong>Styling Issues:</strong></p><ul><li>For icons that don’t adopt the style properties, inspect the elements in a browser to see if styles are being overridden. Ensure that styles are not being applied to a parent container instead of directly to the icon.</li></ul><p><strong>Library Conflicts:</strong></p><ul><li>Sometimes, different icon libraries might conflict, especially if they use similar names for different icons. Use aliases in your import statements to resolve these conflicts.</li></ul><pre><code class="language-js">import { FaBeer as BeerIcon } from 'react-icons/fa';
</code></pre><p>By addressing these FAQs and troubleshooting common issues, developers can reduce downtime and frustration, ensuring a smoother development process and a better user experience. As you integrate React Icons into your projects, keep this guide handy to overcome any hurdles with ease.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 Daily.co Alternatives in 2026]]></title><description><![CDATA[Discover an innovative and transformative alternative to Daily.co, revolutionizing your online experience and propelling you to new heights of success. Embrace this golden opportunity to unlock unparalleled potential.]]></description><link>https://www.videosdk.live/blog/daily-co-alternative</link><guid isPermaLink="false">64af84735badc3b21a5955b9</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Sun, 26 Jan 2025 12:55:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2023/07/Daily-alternative.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2023/07/Daily-alternative.jpg" alt="Top 10 Daily.co Alternatives in 2026"/><p>If you're looking for seamless integration of real-time video into your application and seeking an <a href="https://www.videosdk.live/daily-vs-videosdk" rel="noreferrer"><strong>alternative to Daily.co</strong></a>, you've come to the right spot! While Daily.co is a popular option, there are plenty of untapped opportunities available beyond their platform. Stay tuned to discover what you might have been missing out on, particularly if you're already using Daily.co. Get ready to explore new possibilities!</p><h2 id="understanding-the-need-for-a-dailyco-alternative">Understanding the Need for a Daily.co Alternative</h2>
<p>It's important to note that Daily.co is not without issues. One of its main issues is that it's not able to work properly in the latest <a href="https://github.com/daily-co/daily-js/issues/156">chrome on iOS</a> as well as <a href="https://github.com/daily-co/daily-js/issues/132">Firefox</a>. The platform is hindered by legacy code and an unintuitive developer experience, which can impact its overall usability.</p><p>If you're currently a Daily.co customer or considering trying out Daily.co, We recommend reading this blog to gain insights into what potential limitations or missed opportunities you might encounter.</p><p>The <strong>top 10 Daily.co Alternatives</strong> are VideoSDK, Twilio Video, MirrorFly, Agora, Jitsi, Vonage, AWS Chime, EnableX, WhereBy, and SignalWire.</p><blockquote>
<h2 id="top-10-dailyco-alternatives-for-2026">Top 10 Daily.co Alternatives for 2026</h2>
<ul>
<li>VideoSDK</li>
<li>Twilio Video</li>
<li>MirrorFly</li>
<li>Agora</li>
<li>Jitsi</li>
<li>Vonage</li>
<li>AWS Chime SDK</li>
<li>Enablex</li>
<li>Whereby</li>
<li>SignalWire</li>
</ul>
</blockquote>
<h2 id="1-videosdk-seamless-integration-for-enhanced-audio-video-experience">1. VideoSDK: Seamless Integration for Enhanced Audio-Video Experience</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-SDK-for-Real-time-Communication-Live-Streaming-Video-API-7.jpeg" class="kg-image" alt="Top 10 Daily.co Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>Experience the power of <a href="https://www.videosdk.live">VideoSDK</a>, an API designed to seamlessly integrate robust audio-video features into your applications. With minimal effort, you can enhance your app with live audio and video experiences across any platform.</p><h3 id="key-points-about-videosdk">Key points about VideoSDK</h3>
<ul><li>VideoSDK offers simplicity and speed of integration, freeing up your time to focus on developing innovative features that enhance user retention. </li><li>Say goodbye to complex integration processes and unlock a world of possibilities.</li><li>Enjoy the benefits of VideoSDK, including high scalability, <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">adaptive bitrate</a> technology, end-to-end customization, superior quality recordings, in-depth analytics, cross-platform streaming, seamless scaling, and comprehensive platform support. </li><li>It works effortlessly on mobile (Flutter, Android, iOS), web (JavaScript Core SDK + UI Kit), and desktop (Flutter Desktop), allowing you to create immersive video experiences.</li></ul><h3 id="videosdk-pricing">VideoSDK pricing</h3>
<ul><li>Get incredible value with VideoSDK! Take advantage of <a href="https://www.videosdk.live/pricing">$20 free minutes</a> and <a href="https://www.videosdk.live/pricing#pricingCalc">flexible pricing options</a> for video and audio calls. </li><li><strong>Video calls</strong> start at just <strong>$0.003</strong> per participant per minute, while <strong>audio calls</strong> begin at <strong>$0.0006</strong>.</li><li>Additional costs include <strong>$0.015</strong> per minute for <strong>cloud recordings</strong> and <strong>$0.030</strong> per minute for <strong>RTMP output</strong>.</li><li>Plus, enjoy <strong>free 24/7 customer support</strong>.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/daily-vs-videosdk"><strong>Daily and VideoSDK</strong></a><strong>.</strong></blockquote>
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Your Page Title</title>
	<!-- Include Tailwind CSS -->
	<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</link></meta></meta></head>

<body>
	<div class="relative w-full overflow-hidden rounded-2xl bg-gradient-to-b from-pink-700 to-purple-900 p-4 text-center shadow-xl">
		<h3 class="mx-auto text-3xl font-bold tracking-tight text-white sm:text-2xl" style="margin-top: 3px; margin-bottom: 12px;">
			Schedule a Demo with Our Live Video Expert!
		</h3>
		<p class="mx-auto mt-3 max-w-xl text-sm text-gray-400">
			Discover how VideoSDK can help you build a cutting-edge real-time video app.
			<span class="font-semibold text-lato"/>
		</p>
		<div class="mt-4 flex items-center justify-center">
			<a href="https://www.videosdk.live/contact" class="rounded-md bg-white px-8 py-3 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white" target="_blank" style="text-decoration: none;color: black;" data-faitracker-click-bind="true">
				Book a call
			</a>	
		</div>
		
	</div>
</body>

</html>
<!--kg-card-end: html-->
<h2 id="2-twilio-video-versatile-live-video-for-mobile-and-web">2. Twilio Video: Versatile Live Video for Mobile and Web</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Communication-APIs-for-SMS-Voice-Video-Authentication_twilio-6.jpeg" class="kg-image" alt="Top 10 Daily.co Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>Twilio stands as one of the top video SDK solutions, providing businesses with the ability to seamlessly integrate live video into their mobile and web applications.</p><p>The key advantage of utilizing Twilio is its versatility, allowing you to either build an app from the ground up or enhance existing solutions with powerful communication features. Whether you're starting fresh or expanding your app's capabilities, Twilio offers a reliable and comprehensive solution for incorporating live video into your applications.</p><h3 id="key-points-about-twilio">Key points about Twilio</h3>
<ul><li>Twilio provides web, iOS, and Android SDKs for integrating live video into applications.</li><li>Manual configuration and extra code are required for using multiple audio and video inputs.</li><li>Twilio's call insights can track and analyze errors, but additional code is needed for implementation.</li><li>Pricing can be a concern as usage grows, as Twilio lacks a built-in tiering system in the dashboard.</li><li>Twilio supports up to 50 hosts and participants in a call.</li><li>There are no plugins available for easy product development with Twilio.</li><li>The level of customization offered by the Twilio Video SDK may not meet the needs of all developers, resulting in additional code writing.</li></ul><h3 id="pricing-for-twilio">Pricing for Twilio</h3>
<ul><li>The <a href="https://www.twilio.com/en-us/video/pricing">pricing</a> for <a href="https://www.videosdk.live/blog/twilio-video-alternative"><strong>Twilio</strong></a> starts at <strong>$4</strong> per 1,000 minutes. </li><li><strong>Recordings</strong> are charged at <strong>$0.004</strong> per participant minute, <strong>recording compositions</strong> cost <strong>$0.01</strong> per composed minute, and <strong>storage</strong> is priced at <strong>$0.00167</strong> per GB per day after the first 10 GBs.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/twilio-vs-daily"><strong>Daily and Twilio</strong></a><strong>.</strong></blockquote><h2 id="3-mirrorfly-enterprise-grade-in-app-communication">3. MirrorFly: Enterprise-Grade In-App Communication</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Live-Video-Call-API-Best-Video-Chat-SDK-for-Android-iOS-mirrorfly-6.jpeg" class="kg-image" alt="Top 10 Daily.co Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>MirrorFly is an outstanding in-app communication suite designed specifically for enterprises. It offers a wide range of powerful APIs and SDKs that deliver exceptional chat and calling experiences. With over 150 features for chat, voice, and video calling, this cloud-based solution seamlessly integrates to create a robust communication platform.</p><h3 id="key-points-about-mirrorfly">Key points about MirrorFly</h3>
<ul><li>MirrorFly may have limitations when it comes to customization options, which can restrict the ability to tailor the platform to specific branding or user experience needs. </li><li>This can hinder the uniqueness and personalization of communication features. </li><li>Scaling and handling high user volumes may pose challenges for MirrorFly, potentially impacting performance and stability, especially during periods of significant traffic or complex use cases. </li><li>Users have reported mixed experiences with MirrorFly's technical support, with some encountering delays or difficulties in issue resolution. </li><li>MirrorFly's pricing structure may not be suitable for all budgets or use cases, as costs can be higher depending on desired features and scalability requirements.</li><li>Integrating MirrorFly into existing applications or workflows may require considerable effort and technical expertise, as comprehensive documentation and developer resources may be lacking.</li></ul><h3 id="mirrorfly-pricing">MirrorFly pricing</h3>
<ul><li>MirrorFly's <a href="https://www.mirrorfly.com/pricing.php">pricing</a> starts at <strong>$299</strong> per month, making it a higher-cost option to consider.</li></ul><h2 id="4-agora-robust-features-for-engaging-live-interactions">4. Agora: Robust Features for Engaging Live Interactions</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Agora-Real-Time-Voice-and-Video-Engagement-6.jpeg" class="kg-image" alt="Top 10 Daily.co Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>Agora's video calling SDK is packed with features such as embedded voice and video chat, real-time recording, live streaming, and instant messaging, empowering developers to create captivating live in-app experiences.</p><h3 id="key-points-about-agora">Key points about Agora</h3>
<ul><li>Agora's video SDK offers features like embedded voice and video chat, real-time recording, live streaming, and instant messaging.</li><li>Add-ons such as AR facial masks, sound effects, whiteboards, and other features are available for an additional cost.</li><li>Agora's SD-RTN provides global coverage, connecting individuals from over 200 countries and regions with ultra-low latency streaming capabilities.</li><li>The pricing structure can be complex and may not be suitable for businesses with limited budgets.</li><li>Users seeking hands-on support may experience delays as Agora's support team may require additional time to provide assistance.</li></ul><h3 id="agora-pricing">Agora pricing</h3>
<ul><li><a href="https://www.videosdk.live/blog/agora-alternative"><strong>Agora</strong></a> offers Premium and Standard <a href="https://www.agora.io/en/pricing/">pricing</a> options, where the usage duration for audio and video is calculated monthly. </li><li>Video usage is categorized into four types based on resolution, and pricing is determined accordingly. </li><li>The pricing includes <strong>Audio</strong> at <strong>$0.99</strong> per 1,000 participant minutes, <strong>HD Video</strong> at <strong>$3.99</strong> per 1,000 participant minutes, and <strong>Full HD Video</strong> at <strong>$8.99</strong> per 1,000 participant minutes.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/agora-vs-daily"><strong>Daily and Agora</strong></a><strong>.</strong></blockquote><h2 id="5-jitsi-open-source-video-conferencing-for-businesses">5. Jitsi: Open-Source Video Conferencing for Businesses</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Free-Video-Conferencing-Software-for-Web-Mobile-Jitsi-7.jpeg" class="kg-image" alt="Top 10 Daily.co Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>Jitsi is a collection of free, open-source projects that offer versatile video conferencing services for individuals, teams, and organizations. Its most prominent components are Jitsi Meet and Jitsi Videobridge.</p><p>Jitsi Meet functions as an end-client application, similar to Zoom, enabling users to conduct video chats. It provides features such as screen sharing, real-time collaboration, user invitations, and more.</p><h3 id="key-points-about-jitsi">Key points about Jitsi</h3>
<ul><li>Jitsi is free, open-source, and offers end-to-end encryption, allowing code customization.</li><li>The live experience includes features like active speakers, text chatting (web only), room locking, screen sharing, raise/lower hand, push-to-talk mode, and an audio-only option.</li><li>Security is a major concern, as Jitsi lacks adequate privacy and encryption for confidential business meetings.</li><li>Ample storage space is required for storing and saving meeting data offline, posing challenges for businesses with frequent sessions.</li><li>Jitsi Meet has a limitation of handling up to 200 attendees, which can detract from the meeting experience for larger audiences.</li><li>Meetings lasting longer than three hours are not supported, making it inconvenient for large companies, organizations, webinars, and other institutions.</li><li>Video and audio quality in Jitsi Meet is poor, impacting the overall meeting experience for participants and hosts.</li></ul><h3 id="jitsi-pricing">Jitsi pricing</h3>
<ul><li><a href="https://www.videosdk.live/blog/jitsi-alternative"><strong>Jitsi</strong></a> is an open-source platform that is available for <strong>free</strong> usage. </li><li>However, if your business requires advanced features or technical support, it might be worth considering third-party providers that offer commercial support for Jitsi.</li><li>The cost of commercial support can vary based on your specific requirements and the chosen provider.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/jitsi-vs-daily"><strong>Daily and Jitsi</strong></a><strong>.</strong></blockquote><h2 id="6-vonage-reliable-communication-for-rapid-prototyping">6. Vonage: Reliable Communication for Rapid Prototyping</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-API-Fully-Programmable-and-Customizable-Vonage-5.jpeg" class="kg-image" alt="Top 10 Daily.co Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>Despite being acquired by Vonage(Formerly TokBox) and subsequently renamed as the "Vonage API," the industry still commonly refers to TokBox. TokBox's SDKs enable reliable point-to-point communication, making it a viable option for establishing proof of concepts during hackathons or meeting investor deadlines.</p><h3 id="key-points-about-vonage">Key points about Vonage</h3>
<ul><li>The TokBox SDK enables building custom audio/video streams with effects, filters, and AR/VR on mobile devices.</li><li>It supports various use cases like 1:1 video, group video chat, and large-scale broadcast sessions.</li><li>Participants can share screens, exchange messages via chat, and send data during calls.</li><li>One challenge is scaling costs, as the price per stream per minute increases with a growing user base.</li><li>Additional features like recording and interactive broadcasts come at an extra cost.</li><li>After 2,000 connections, the platform switches to CDN delivery, resulting in higher latency.</li><li>Real-time streaming at scale is a struggle, as anything over 3,000 viewers requires switching to HLS, which introduces significant latency.</li></ul><h3 id="vonage-pricing">Vonage pricing</h3>
<ul><li><a href="https://www.videosdk.live/blog/vonage-alternative"><strong>Vonage</strong></a> follows a usage-based <a href="https://www.vonage.com/communications-apis/video/pricing/">pricing</a> model based on the number of participants in a video session, which is dynamically calculated every minute.</li><li>Their <strong>pricing plans</strong> begin at <strong>$9.99</strong> per month and include a free allowance of 2,000 minutes per month across all plans. </li><li>Once the free allowance is used up, users are charged at a rate of <strong>$0.00395</strong> per participant per minute. <strong>Recording</strong> services start at <strong>$0.010</strong> per minute, while <strong>HLS streaming</strong> carries a cost of <strong>$0.003</strong> per minute.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/vonage-vs-daily"><strong>Daily and Vonage</strong></a><strong>.</strong></blockquote><h2 id="7-aws-chime-sdk">7. AWS Chime SDK</h2>
<p>The Amazon Chime SDK is the underlying technology of Amazon Chime, operating without its outer shell or user interface.</p><h3 id="key-points-about-aws-chime-sdk">Key points about AWS Chime SDK</h3>
<ul><li>The Amazon Chime SDK allows up to 25 participants (or 50 for mobile users) in a video meeting.</li><li>Simulcast technology ensures consistent video quality across different devices and networks.</li><li>All calls, videos, and chats are encrypted for enhanced security.</li><li>It lacks certain features like polling, auto-sync with Google Calendar, and background blur effects.</li><li>Compatibility issues have been reported in Linux environments and with participants using the Safari browser.</li><li>Customer support experiences can vary, with inconsistent query resolution times depending on the support agent.</li></ul><h3 id="aws-chime-pricing">AWS Chime pricing</h3>
<ul><li><a href="https://www.videosdk.live/blog/amazon-chime-sdk-alternative"><strong>AWS Chime</strong></a>'s <strong>free basic plan</strong> allows users to have one-on-one audio/video calls and group chats.</li><li><strong>The Plus plan</strong>, <a href="https://aws.amazon.com/chime/pricing/">priced</a> at <strong>$2.50</strong> per monthly user, provides additional features including <strong>screen sharing</strong>, <strong>remote desktop control</strong>, <strong>1 GB of message history</strong> per user, and <strong>Active Directory integration</strong>.</li><li><strong>The Pro plan</strong>, priced at <strong>$15</strong> per user per month, includes all the features of the Plus plan and allows for <strong>meetings</strong> with three or more participants.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/amazon-chime-sdk-vs-daily"><strong>Daily and AWS Chime</strong></a><strong>.</strong></blockquote><h2 id="8-enablex">8. EnableX</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-Call-API-Video-Chat-API-Voice-API-Video-Conferencing_enebleX-7.jpeg" class="kg-image" alt="Top 10 Daily.co Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>The EnableX SDK provides video and audio calling capabilities along with collaborative features such as a whiteboard, screen sharing, annotation, recording, host control, and chat. With the SDK, you can utilize a video builder to deploy custom video-calling solutions directly into your application. It allows you to create personalized live video streams with a custom user interface, hosting options, billing integration, and other essential functionalities tailored to your specific needs.</p><h3 id="key-points-about-enablex">Key points about EnableX</h3>
<ul><li>EnableX provides a self-service portal with reporting capabilities and live analytics to track quality and facilitate online payments.</li><li>The SDK supports JavaScript, PHP, and Python programming languages.</li><li>Users can stream live content directly from your app/site or on platforms like YouTube and Facebook for broader audience reach.</li><li>The support team's response time may take up to 72 hours, which may be a potential drawback for users in need of timely assistance.</li></ul><h3 id="enablex-pricing">EnableX pricing</h3>
<ul><li>EnableX <a href="https://www.enablex.io/cpaas/pricing/our-pricing">pricing</a> starts at <strong>$0.004</strong> per minute per participant for rooms with <strong>up to 50 people</strong>. </li><li>If you require hosting larger meetings or events, you can reach out to their sales team for custom pricing options.</li><li>EnableX also provides a <strong>recording option</strong> priced at <strong>$0.010</strong> per minute per participant. </li><li>Additionally, if you need to transcode your video into a <strong>different format</strong>, it is available at a rate of <strong>$0.010</strong> per minute. </li><li>For <strong>additional storage</strong> or <strong>RTMP streaming</strong>, you can obtain them for <strong>$0.05</strong> per GB per month and <strong>$0.10</strong> per minute, respectively.</li></ul><h2 id="9-whereby">9. Whereby</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-Calling-API-for-Web-and-App-Developers-Whereby-7.jpeg" class="kg-image" alt="Top 10 Daily.co Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>Whereby is a straightforward and user-friendly video conferencing platform that caters to basic small- to medium-sized meetings. However, it may not be the ideal choice for larger businesses or those in need of more advanced features.</p><h3 id="key-points-about-whereby">Key points about Whereby</h3>
<ul><li>Whereby allows basic customization of the video interface, but it has limited options and doesn't support a fully custom experience.</li><li>Video calls can be embedded directly within websites, mobile apps, and web products, eliminating the need for external links or apps.</li><li>Whereby offers a seamless video conferencing experience, but it may lack advanced features found in other tools. </li><li>The maximum capacity is 50 participants.</li><li>Screen sharing for mobile users and customization option for the host interface may be limited.</li><li>Whereby does not offer a virtual background feature, and some users have reported issues with the mobile app, which may impact the overall user experience.</li></ul><h3 id="whereby-pricing">Whereby pricing</h3>
<ul><li>Whereby follows a <a href="https://whereby.com/information/pricing">pricing</a> model that begins at <strong>$6.99</strong> per month, offering up to 2,000 user minutes that are renewed monthly. </li><li>Once the allocated minutes are used up, an additional charge of <strong>$0.004</strong> per minute is applicable. </li><li>The platform also provides options for <strong>cloud recording</strong> and <strong>live streaming</strong>, which are charged at a rate of <strong>$0.01</strong> per minute.</li><li><strong>Email</strong> and <strong>chat support</strong> are available for <strong>free</strong> to all users, ensuring that assistance is readily accessible when needed. </li><li><strong>Paid</strong> support plans offer additional features such as <strong>technical onboarding</strong>, <strong>customer success management</strong>, and <strong>HIPAA compliance</strong>.</li></ul><h2 id="10-signalwire">10. SignalWire</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Building-The-Software-Defined-Telecom-Network-SignalWire-6.jpeg" class="kg-image" alt="Top 10 Daily.co Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>SignalWire is a platform powered by APIs, specifically designed to help developers seamlessly integrate live and on-demand video experiences into their applications. Its primary goal is to simplify video encoding, delivery, and renditions, ensuring a smooth and uninterrupted video streaming experience for users.</p><h3 id="overview-of-signalwire">Overview of SignalWire</h3>
<ul><li>SignalWire provides an SDK that enables the integration of real-time video and live streams into web, iOS, and Android applications. </li><li>Each video call can accommodate up to 100 participants in a real-time <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> environment. </li><li>However, it's important to note that the SDK does not offer built-in support for managing disruptions or user publish-subscribe logic, which developers will need to implement separately.</li></ul><h3 id="signalwire-pricing">SignalWire pricing</h3>
<ul><li>SignalWire utilizes a <a href="https://signalwire.com/pricing/video">pricing</a> model based on per-minute usage. </li><li>The pricing includes <strong>$0.0060</strong> per minute for <strong>HD video calls</strong> and <strong>$0.012</strong> for <strong>Full HD video calls</strong>. </li><li>The actual cost may vary depending on the desired video quality for your application.</li><li>In addition, SignalWire offers additional features such as <strong>recording</strong>, which is available at a rate of <strong>$0.0045</strong> per minute. </li><li>This allows you to capture and store video content for future use. </li><li>The platform also provides <strong>streaming capabilities</strong>, priced at <strong>$0.10</strong> per minute, allowing you to broadcast your video content in real-time.</li></ul><h2 id="certainly">Certainly!</h2>
<p><a href="https://www.videosdk.live">VideoSDK</a> stands out as an SDK that prioritizes fast and seamless integration. With a low-code solution, developers can quickly build live video experiences in their applications, deploying custom video conferencing solutions in under 10 minutes. Unlike other SDKs, VideoSDK offers a streamlined process with easy creation and embedding of live video experiences, enabling real-time connections, communication, and collaboration.</p><h2 id="still-skeptical">Still skeptical?</h2>
<p>Immerse yourself in the possibilities of VideoSDK by taking a deep dive into its comprehensive <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start" rel="noopener noreferrer">Quickstart guide</a>. Explore the potential with the <a href="https://docs.videosdk.live/code-sample" rel="noopener noreferrer">powerful sample app</a> exclusively designed for Video SDK. Sign up now and start your integration journey, and don't miss out on the chance to claim your <a href="https://www.videosdk.live/pricing" rel="noopener noreferrer">complimentary $20 free credit</a> to unlock the full potential of Video SDK. Our dedicated team is always ready to assist you whenever you need support. Get ready to showcase your creativity and build remarkable experiences with Video SDK. Let the world see what you can create!</p>]]></content:encoded></item><item><title><![CDATA[What is Computer Emergency Response Team (CERT)? Why is it Important Globally?]]></title><description><![CDATA[Discover the types of CERTs and their importance in maintaining digital security across organizations, industries, and nations.]]></description><link>https://www.videosdk.live/blog/what-is-cert</link><guid isPermaLink="false">66d6d6d220fab018df10fea0</guid><category><![CDATA[CERT]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Sun, 26 Jan 2025 11:54:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-CERT.png" medium="image"/><content:encoded><![CDATA[<blockquote>A Computer Emergency Response Team (CERT) is a specialized group that coordinates detection, analysis, and recovery from cybersecurity incidents across organizations, industries, or national borders. CERT teams share threat intelligence, manage vulnerabilities, and help victims contain breaches faster than isolated internal IT teams can alone. Every organization handling sensitive real-time data benefits from knowing how CERT coordination works.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-CERT.png" alt="What is Computer Emergency Response Team (CERT)? Why is it Important Globally?"/><p>A ransomware attack on a telehealth platform does not stop at one hospital network. Stolen session tokens from a live-streaming API can expose thousands of concurrent viewers before your on-call engineer finishes reading the first alert. <a href="https://en.wikipedia.org/wiki/Indian_Computer_Emergency_Response_Team" rel="noreferrer">Computer Emergency Response Teams</a> exist because no single company can outrun coordinated cyber threats alone. This article defines what CERT is, explains how CERT teams operate, compares CERT types worldwide, and shows what engineering and security leaders building real-time applications should do before an incident forces the question.</p><h2 id="what-is-cert-computer-emergency-response-team">What Is CERT (Computer Emergency Response Team)?</h2><p>A Computer Emergency Response Team (CERT) is defined as a formally organized group of cybersecurity professionals responsible for preventing, detecting, responding to, and recovering from information security incidents within a defined scope such as a nation, industry sector, or large enterprise.</p><p>CERT works by collecting incident reports, analyzing attack patterns, coordinating containment actions, and distributing actionable advisories to affected organizations and partner teams. When a vulnerability affects software used across an industry, a CERT team often publishes a coordinated disclosure timeline so vendors patch systems before exploit code spreads widely.</p><p>The CERT model originated in November 1988 when the <a href="https://www.sei.cmu.edu/history-of-innovation/fostering-growth-in-professional-cyber-incident-management/" rel="noreferrer">CERT Coordination Center (CERT/CC)</a> was established at Carnegie Mellon University's Software Engineering Institute following the Morris worm incident. That founding event established the template still used today: a trusted neutral party that bridges victims, vendors, law enforcement, and peer response teams during active crises.</p><p>For teams building real-time communication products, CERT relevance is direct. Video calling, live streaming, and <a href="https://www.videosdk.live/voice-agents" rel="noreferrer">AI voice agents</a> handle authentication tokens, media streams, and user metadata that attackers target during credential stuffing, DDoS, and supply-chain campaigns. Understanding CERT is part of building a defensible architecture, not just a compliance checkbox.</p><h2 id="how-does-a-cert-work">How Does a CERT Work?</h2><p>A CERT operates through a repeatable incident pipeline that moves from initial report intake to coordinated recovery, with threat intelligence flowing outward at every stage.</p><p>Most CERT teams follow a four-phase model aligned with NIST Special Publication 800-61 Rev. 2 (Computer Security Incident Handling Guide): preparation, detection and analysis, containment eradication and recovery, and post-incident activity. Each phase has defined outputs. Preparation produces contact lists and communication trees. Detection produces validated incident tickets. Containment produces isolated systems and preserved logs. Post-incident activity produces after-action reports shared with peer CERTs.</p><p>When a developer reports an API key leak affecting a live streaming deployment, the CERT intake desk assigns severity based on scope, affected user count, and exploit availability. Analysts correlate the report with ongoing campaigns tracked by national CERTs such as US-CERT (now part of CISA) or CERT-In in India. If the attack vector matches a known vulnerability in a third-party dependency, the CERT publishes a sector advisory so other organizations patch before they become the next victim.</p><p>CERT teams also maintain secure communication channels. During major incidents, public email is avoided in favor of encrypted mailing lists, dedicated portals, and pre-registered phone bridges established during preparation phase exercises.</p><p>This section explained the end-to-end CERT workflow from first report through coordinated recovery and intelligence sharing.</p><h2 id="why-do-you-need-cert">Why do you need CERT?</h2><ul><li><strong>Incident Response</strong>: CERTs help organizations respond to and recover from cybersecurity incidents, minimizing the damage caused by attacks. They have the expertise to detect, analyze, and mitigate threats quickly, helping reduce downtime and prevent future incidents. A&nbsp;well-defined <a href="https://www.wiz.io/academy/incident-response-plan" rel="noreferrer">incident response plan</a>&nbsp;is essential in guiding these actions effectively and ensuring a coordinated approach.</li><li><strong>Threat Intelligence Sharing</strong>: CERTs collect and analyze data on emerging threats and vulnerabilities, which they share with clients and the broader cybersecurity community. This proactive approach helps organizations stay ahead of potential threats by applying necessary patches and security measures.</li><li><strong>Vulnerability Management</strong>: They identify security weaknesses in systems and provide actionable advice to address them. This includes offering guidance on <a href="https://www.motadata.com/patch-management-software/" rel="noreferrer">patch management</a> and securing systems, reducing the risk of exploitation by cybercriminals.</li><li><strong>Public Awareness</strong>: CERTs play an important role in educating the public and organizations on cybersecurity best practices. They conduct training and awareness programs to help users adopt secure behaviors and reduce the likelihood of falling victim to attacks.</li><li><strong>Global Coordination</strong>: CERTs collaborate with other security organizations, law enforcement, and international partners to respond to large-scale incidents and enhance the overall cybersecurity ecosystem. This global network strengthens the collective defense against cyber threats.</li></ul><h2 id="what-are-the-different-types-of-certs-worldwide">What Are the Different Types of CERTs Worldwide?</h2><p>Global cybersecurity defense relies on layered CERT structures where national teams, industry-specific teams, and vendor-aligned groups each cover a distinct scope of responsibility.</p><p><strong>National and regional CERTs</strong>&nbsp;serve government and critical infrastructure within a country or region. Examples include CISA (which absorbed US-CERT functions) in the United States, <a href="https://www.cert-in.org.in/" rel="noreferrer">CERT-In </a>under India's Ministry of Electronics and IT, and <a href="https://www.jpcert.or.jp/" rel="noreferrer">JPCERT/CC</a> in Japan. These teams publish national advisories, coordinate cross-ministry response, and often mandate reporting timelines for regulated sectors.</p><p><strong>Industry-specific CERTs</strong>&nbsp;focus on vertical threat patterns that generic national teams lack depth to address daily. ISACs (Information Sharing and Analysis Centers) in finance, healthcare, and energy function as sector CERTs. They translate broad CVE alerts into guidance specific to electronic health record systems, trading platforms, or SCADA environments.</p><p><strong>Enterprise and vendor CERTs</strong>&nbsp;operate inside large technology companies or cloud providers. Microsoft MSRC, Google TAG, and AWS Security teams coordinate disclosure and patching for their own product ecosystems. For developers, vendor CERT advisories often arrive faster than national bulletins when the vulnerability is in a managed SDK or API.</p><p><strong>Global coordination networks</strong>&nbsp;connect independent CERTs. FIRST provides membership standards, conference channels, and trusted peering for over 600 teams globally. CERT/CC at Carnegie Mellon continues research on vulnerability coordination and publishes the Vulnerability Notes Database.</p><p>If you operate a real-time communication product, you interact with multiple CERT layers simultaneously: your cloud provider's security team, your industry's ISAC, and your national CERT for regulatory reporting obligations.</p><p>This section mapped the four major CERT categories and their scopes of responsibility.</p><p>Overall, CERTs are essential in the global effort to enhance cybersecurity readiness, response, and resilience against the ever-evolving threat landscape.</p><h2 id="common-misconceptions-about-cert-teams">Common Misconceptions About CERT Teams</h2><p>Several widely repeated beliefs about CERT teams are inaccurate, and those inaccuracies delay reporting during the critical first hours of an active incident.</p><p><strong>Misconception 1: CERT teams only serve governments.</strong>&nbsp;National CERTs like CERT-In and JPCERT/CC are government-affiliated, but enterprise CSIRTs, vendor response teams, and industry ISACs all follow CERT coordination models. Private companies benefit from FIRST membership and vendor CERT advisories regardless of government reporting obligations.</p><p><strong>Misconception 2: Reporting to a CERT means public disclosure of your breach.</strong>&nbsp;Coordinated disclosure processes allow affected organizations to patch and prepare customer communications before advisories go public. Early confidential reporting to a trusted CERT often reduces total exposure compared to silent internal containment that misses linked attack indicators.</p><p><strong>Misconception 3: Small companies are too insignificant for CERT attention.</strong>&nbsp;Automated scanning campaigns do not discriminate by company size. A compromised OAuth token on a 50-person startup's video chat feature can serve as a pivot point into larger partner organizations. Sector CERTs track attack patterns across all reporting entities.</p><p><strong>Misconception 4: CERT involvement replaces your internal security team.</strong>&nbsp;External CERT coordination supplements CSIRT and SOC functions. You still own access revocation, customer notification, and system recovery. CERT teams provide intelligence, coordination channels, and peer context your internal team lacks.</p><p><strong>Misconception 5: Compliance certification eliminates the need for CERT relationships.</strong>&nbsp;SOC 2 and ISO 27001 audits verify process existence. They do not provide real-time IOC feeds during an active zero-day affecting your WebRTC dependency chain. CERT relationships fill that operational gap.</p><p>Correcting these misconceptions early helps engineering leaders report faster and coordinate more effectively when incidents touch live production systems.</p><p>This section debunked five common CERT myths that delay effective incident coordination.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-8--2026--06_22_28-PM.png" class="kg-image" alt="What is Computer Emergency Response Team (CERT)? Why is it Important Globally?" loading="lazy" width="1536" height="1024"/></figure><h2 id="the-cert-incident-response-lifecycle-explained">The CERT Incident Response Lifecycle Explained</h2><p>The CERT incident response lifecycle provides a structured sequence that prevents teams from skipping evidence preservation or releasing premature public statements during high-pressure breaches.</p><p><a href="https://nvlpubs.nist.gov/nistpubs/specialpublications/nist.sp.800-61r2.pdf" rel="noreferrer">NIST SP 800-61 Rev. 2</a> defines four lifecycle phases that most CERT and CSIRT teams adapt to their organizational context:</p><h3 id="preparation">Preparation</h3><p>Preparation includes maintaining contact lists for CSIRT members, external CERT liaisons, legal counsel, and executive decision-makers. Run tabletop exercises simulating a live streaming API key leak or a DDoS against your signaling cluster. Verify that on-call engineers can reach VideoSDK support and cloud provider security contacts without searching email archives during an incident.</p><h3 id="detection-and-analysis">Detection and Analysis</h3><p>Detection converts raw alerts into validated incidents. SOC tools flag anomalies. CSIRT analysts determine scope: which rooms, users, or API endpoints are affected. CERT teams at the sector level correlate your report with campaigns targeting similar infrastructure.</p><h3 id="containment-eradication-and-recovery">Containment, Eradication, and Recovery</h3><p>Containment stops active damage. For real-time platforms, this means rotating compromised tokens, disabling affected API keys, isolating compromised media nodes, and potentially pausing live sessions with user notification. Eradication removes attacker persistence mechanisms. Recovery restores services with patched dependencies and verified configurations.</p><h3 id="post-incident-activity">Post-Incident Activity</h3><p>Post-incident reviews produce after-action reports, updated detection rules, and shared advisories. Lessons learned feed back into preparation phase updates. Organizations that skip this phase repeat the same containment mistakes during the next campaign.</p><p>This section walked through all four NIST-aligned lifecycle phases and their outputs for CERT-coordinated response.</p><h2 id="how-to-prepare-your-organization-for-cert-coordination">How to Prepare Your Organization for CERT Coordination</h2><p>Preparation before an incident determines whether your first CERT contact is a structured report or a panicked email missing the data analysts need.</p><p>Follow these steps to build CERT readiness into your security program:</p><ol><li><strong>Identify your reporting CERTs.</strong>&nbsp;Determine which national CERT covers your jurisdiction, which industry ISAC serves your sector, and which vendor CERTs cover your critical dependencies including your real-time communication SDK and cloud provider.</li><li><strong>Register contact points.</strong>&nbsp;Submit official security contact information to national CERT portals where registration is available. Assign a primary and backup contact who understands your production architecture.</li><li><strong>Document your communication stack.</strong>&nbsp;Create a one-page diagram showing authentication flow, media path, recording storage, and webhook integrations. Attach this to your internal incident response plan.</li><li><strong>Define severity thresholds.</strong>&nbsp;Write clear criteria for P1 through P4 incidents specific to live session abuse, credential leaks, and DDoS events. Align thresholds with escalation timelines in your CSIRT charter.</li><li><strong>Run a tabletop exercise.</strong>&nbsp;Simulate a coordinated disclosure affecting your WebRTC dependency chain. Time how long it takes to identify affected services, rotate credentials, and draft a customer status page update.</li><li><strong>Establish secure reporting channels.</strong>&nbsp;Store encrypted contact methods for external CERTs separately from production systems that attackers might compromise during an active breach.</li></ol><p>Teams using VideoSDK should include SDK token generation endpoints, webhook URLs, and recording storage locations in this documentation so CSIRT analysts can act without waiting for engineering archaeology.</p><p>This section provided six actionable steps for CERT coordination readiness before a live incident occurs.</p><h2 id="conclusion">Conclusion</h2><p>Understanding what CERT is and how CERT teams operate gives engineering and security leaders a concrete framework for incident readiness beyond compliance audits. National CERTs, sector ISACs, and vendor response teams each play a distinct role, and real-time platforms add session-specific surfaces that generic playbooks often miss. Map your dependencies, define live session severity levels, and establish CSIRT-to-CERT contacts before your first production incident. If you are building video, audio, or AI voice applications, start with a platform that bakes session security into the integration path.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-cert-in-cybersecurity">What is CERT in cybersecurity?</h3><p>CERT in cybersecurity stands for Computer Emergency Response Team, a group that coordinates the detection, analysis, containment, and recovery from information security incidents. CERT teams share threat advisories, manage vulnerability disclosures, and connect affected organizations with peer response teams and law enforcement when attacks cross organizational boundaries.</p><h3 id="why-is-cert-important-globally">Why is CERT important globally?</h3><p>CERT is important globally because cyber attacks routinely cross national and sector boundaries, and no single organization holds complete visibility into coordinated campaigns. Global CERT networks like FIRST enable trusted intelligence sharing so a breach pattern detected in one country triggers defensive actions in others before the same exploit chain reaches their infrastructure.</p><h3 id="how-many-types-of-certs-exist">How many types of CERTs exist?</h3><p>Multiple types of CERTs exist including national and regional CERTs (such as CISA in the US and CERT-In in India), industry-specific ISACs, enterprise and vendor CERT teams inside large technology companies, and global coordination bodies like FIRST and CERT/CC. Each type covers a different scope from national critical infrastructure to single-vendor product ecosystems.</p><h3 id="what-is-the-difference-between-cert-and-csirt">What is the difference between CERT and CSIRT?</h3><p>The difference between CERT and CSIRT is scope and orientation. A CERT typically coordinates response across multiple organizations or an entire sector and publishes external advisories. A CSIRT handles incidents within one organization, executing internal containment and reporting outward to CERTs when the attack exceeds internal capacity.</p><h3 id="how-does-a-cert-handle-a-security-incident">How does a CERT handle a security incident?</h3><p>A CERT handles a security incident by receiving and validating reports, analyzing attack scope and indicators, coordinating containment guidance with affected organizations, supporting recovery actions, and publishing threat advisories to peer teams. The process follows structured phases including preparation, detection, containment, recovery, and post-incident review aligned with frameworks like NIST SP 800-61.</p><h3 id="when-should-a-company-contact-a-cert">When should a company contact a CERT?</h3><p>A company should contact a CERT when it detects an incident that may affect customers, partners, or sector infrastructure beyond its internal boundary, when a vulnerability disclosure requires coordinated patching across dependencies, or when national regulations mandate breach reporting to an official CERT portal within a defined timeframe.</p><h3 id="is-videosdk-relevant-to-cert-and-incident-response-planning">Is VideoSDK relevant to CERT and incident response planning?</h3><p>VideoSDK is relevant to CERT and incident response planning for teams building real-time video, audio, and live streaming applications because session authentication, media transport, and recording storage create incident surfaces that CSIRT teams must document before an active breach. VideoSDK provides token-based session control and encrypted WebRTC transport that integrates into a CERT-aligned security architecture alongside SOC monitoring and CSIRT response procedures.</p>]]></content:encoded></item><item><title><![CDATA[Video KYC vs Traditional KYC: What's the Difference?]]></title><description><![CDATA[This article compares traditional in-person KYC with innovative Video KYC methods, highlighting their pros and cons.]]></description><link>https://www.videosdk.live/blog/video-kyc-vs-traditional-kyc</link><guid isPermaLink="false">66db01e620fab018df110099</guid><category><![CDATA[Video KYC]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Sun, 26 Jan 2025 11:52:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/09/Difference-between-Traditional-KYC-and-Video-KYC--1-.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2024/09/Difference-between-Traditional-KYC-and-Video-KYC--1-.jpg" alt="Video KYC vs Traditional KYC: What's the Difference?"/><p>We know that customer verification processes, aka <a href="https://www.swift.com/your-needs/financial-crime-cyber-security/know-your-customer-kyc/kyc-process" rel="noreferrer">Know Your Customer (KYC)</a> processes, have become essential for businesses and their customers against fraud, money laundering, and other illegal activities, particularly in the financial sector.</p><p>These processes ensure that institutions can accurately identify and verify their customers, thereby mitigating risks associated with fraud and compliance violations.</p><p>As technology evolves, so do the methods of customer verification, With the advent of digital technologies like eKYC and <a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">Video KYC</a>. This innovative method promises to streamline the verification process, offering both convenience and enhanced security.</p><p>In this article, we'll explore the key differences between Video KYC and traditional KYC customer verification, and highlight the advantages and challenges of each KYC process and the implications for the future of financial services.</p><h2 id="what-is-traditional-kyc-physical-kyc"><strong>What is Traditional KYC (Physical KYC)?</strong></h2><p>Traditional KYC customer verification, often referred to as in-person or physical KYC, has been the standard method employed by financial institutions for decades. These established methods are used by businesses, particularly in the financial sector to collect personal information and documentation, such as government-issued identification (Aadhar card, PAN card, Passport), proof of address (Electricity bill or Voter ID), and sometimes even financial history (Passbook, Bank Statement) to confirm the identity of their clients before initiating services.</p><p>Historically, this method has been the pillar of KYC (Know Your Customer) protocols, which were designed to reduce fraud and ensure compliance with regulatory requirements. However, as digital interactions have surged, limitations such as time consumption, inconvenience, and higher operational costs have initiated the search for more efficient alternatives like eKYC and Video KYC.</p><h3 id="the-regular-kyc-procedure">The Regular KYC Procedure</h3><ol><li><strong>Document Collection</strong>: Customers are required to provide various identification documents, such as government-issued IDs, proof of address, and sometimes additional supporting documents like utility bills or bank statements.</li><li><strong>In-Person Visit</strong>: The customer must visit a branch or designated location to present these documents in person. This step allows bank representatives to physically examine the documents and verify their authenticity.</li><li><strong>Face-to-Face Interview</strong>: A bank employee questions the customer to gather additional information and assess the risk profile.</li><li><strong>Document Verification</strong>: The collected documents are scrutinized for authenticity, often involving manual checks and comparisons against databases.</li><li><strong>Data Entry</strong>: Customer information is manually entered into the bank's systems, a process prone to human error.</li><li><strong>Approval Process</strong>: The compiled information undergoes review by relevant departments for final approval.</li></ol><h3 id="challenges-and-limitations-of-the-traditional-approach">Challenges and Limitations of the Traditional Approach</h3><ul><li><strong>Time-Consuming</strong>: The entire process can take days or weeks to complete, leading to delays in account opening or service activation.</li><li><strong>Resource-Intensive</strong>: It requires significant human resources like verification agents and physical infrastructure to manage in-person verifications.</li><li><strong>Geographical Limitations</strong>: Customers must be physically present, which can be inconvenient for most customers or impossible for those in remote areas or different countries.</li><li><strong>Paperwork Burden</strong>: The dependency on physical documents increases the risk of loss, damage, or misusage of sensitive information.</li><li><strong>Inconsistent Experience</strong>: The quality of verification can differ depending on the skills and training of individual bank employees.</li></ul><p>Despite these challenges, traditional customer verification has been the popular KYC process due to its perceived reliability and the comfort of face-to-face interactions. But as we'll explore in the following sections, the emergence of Video KYC is offering a more efficient and technologically advanced alternative.</p><h2 id="what-is-video-kyc"><strong>What is Video KYC?</strong></h2><p><a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">Video KYC</a> (Know Your Customer) is a digital approach to verifying customer identities through live video interactions, allowing financial institutions to authenticate customers remotely without the need for physical presence. This process is also called Digital KYC because its innovative method combines digital technology with the security of face-to-face interactions, making it very important in the digital banking landscape.</p><p>The Video KYC process involves a customer starting a video call with a trained agent, during which they present their identification documents like Aadhar, PAN, or Passport for verification. Then, Advanced technologies such as facial recognition and <a href="https://www.videosdk.live/blog/what-is-liveness-detection">liveness detection</a> are used to ensure that the individual is physically present and their identity matches with provided documents.</p><p>Additionally, <a href="https://aws.amazon.com/what-is/ocr/">Optical Character Recognition (OCR)</a> technology is used to extract and verify information from these documents in real-time. This innovative approach allows customers to complete their KYC requirements remotely, using video conferencing technology and advanced authentication methods.</p><h2 id="the-importance-of-video-kyc">The Importance of Video KYC</h2><p>Video KYC represents a significant leap forward in customer verification processes, leveraging digital technology to create a more efficient, accessible, and secure experience.</p><p>Key features of Video KYC include:</p><ol><li><strong>Remote Verification</strong>: Customers can complete the KYC process from anywhere with an internet connection and a device with a camera.</li><li><strong>Real-time Document Scanning</strong>: Advanced OCR (Optical Character Recognition) technology enables instant document verification.</li><li><strong>Facial Recognition</strong>: AI-powered facial recognition tools enhance identity verification accuracy.</li><li><strong>Geo-tagging and Timestamp</strong>: These features add an extra layer of security to the verification process.</li><li><strong>Recorded Sessions</strong>: Video KYC sessions are recorded for audit and compliance purposes.</li></ol><p>The regulatory framework supporting Video KYC has evolved rapidly, with many countries now recognizing its validity. For instance, the <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc">Reserve Bank of India (RBI) issued guidelines</a> in January 2020 allowing banks and other regulated entities to use Video KYC for customer onboarding.</p><h2 id="comparison-between-video-kyc-vs-traditional-kyc"><strong>Comparison between Video KYC vs Traditional KYC </strong></h2><p>While traditional customer verification methods have been the standard for decades, the emergence of Video KYC has introduced a more efficient and convenient alternative. Let's compare the two approaches:</p>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th><strong>Feature</strong></th>
<th><strong>Traditional Verification</strong></th>
<th><strong>Video KYC</strong></th>
</tr>
</thead>
<tbody>
<tr>
<td>Process</td>
<td>Involves in-person visits to branches or offices, where customers must physically show their identification documents</td>
<td>Allows customers to complete the verification process remotely through live video calls</td>
</tr>
<tr>
<td>Document Submission</td>
<td>Submit physical copies of their documents.</td>
<td>Enables digital document submission in front of the camera during the video call</td>
</tr>
<tr>
<td>Time Efficiency</td>
<td>Time-consuming and prone to delays due to manual processes and human error</td>
<td>Streamlines process through automation, allowing for faster customer onboarding and reduced waiting times</td>
</tr>
<tr>
<td>Customer Experience</td>
<td>Inconvenient for customers, requiring them to visit branches and wait in line</td>
<td>Offers convenience and tech-savvy experience that aligns with digital banking trends.</td>
</tr>
<tr>
<td>Security and Fraud Prevention</td>
<td>Relies on human expertise to detect forgeries and impersonation attempts.</td>
<td>Utilizes AI and machine learning to reduce fraud detection, including deepfake prevention techniques.</td>
</tr>
<tr>
<td>Geographical Limitations</td>
<td>Limited by physical branch locations, challenging for remote or international customers.</td>
<td>Eliminates geographical barriers, allowing banks to reach a wider customer base</td>
</tr>
<tr>
<td>Cost</td>
<td>High operational costs due to physical infrastructure, staff, and paper-based processes.</td>
<td>Significantly lower costs, with reduced need for physical branches and streamlined digital processes.</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<h2 id="advantages-of-video-kyc">Advantages of Video KYC</h2><p>Video KYC offers several convincing advantages that improve both customer experience and operational efficiency for financial institutions.</p><ul><li><strong>Enhanced Customer Onboarding</strong>: Faster processes lead to improved customer satisfaction and reduced dropoff rates during account opening.</li><li><strong>Reduced Operational Costs</strong>: Banks can significantly cut expenses of physical infrastructure and manual processing.</li><li><strong>Improved Accuracy</strong>: AI-powered systems reduce human errors in data entry and document verification.</li><li><strong>Scalability</strong>: Video KYC allows financial institutions to handle higher volumes of verifications without increases in resources.</li><li><strong>Data Security</strong>: Digital processes often provide better encryption and security measures for sensitive customer information.</li></ul><p>These advantages make Video KYC important option for both financial institutions and customers, driving its increasing adoption across the global financial sector.</p><h2 id="challenges-in-video-kyc">Challenges in Video KYC</h2><p>While Video KYC offers numerous advantages, it also presents some challenges that financial institutions must address, like:</p><ul><li><strong>Technology Infrastructure</strong>: Building an in-house <a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">Video KYC structure</a> requires robust IT systems and capable of handling video streaming, data processing, and secure storage.</li><li><strong>Data Privacy and Security</strong>: With increased digital interactions, ensuring the protection of sensitive customer data becomes paramount. <a href="https://insiderone.com/best-customer-data-platform/" rel="noreferrer">Customer data platforms</a> can help organizations manage and unify customer information securely, improving data governance and reducing risks.</li><li><strong>Regulatory Compliance</strong>: As a relatively new technology, Video KYC must navigate evolving regulatory landscapes across different jurisdictions.</li><li><strong>Digital Divide</strong>: Not all customers may have access to the internet or necessary technology. Might be possible that they feel uncomfortable with digital processes.</li></ul><h2 id="implementation-of-video-kyc">Implementation of Video KYC</h2><p>To successfully implement Video KYC, financial institutions should consider the following best practices:</p><ul><li><strong>Selecting the Right Solution</strong>: Choose the right <a href="https://www.videosdk.live/">Video KYC infrastructure</a> that aligns with your specific needs, regulatory requirements, and customer base.</li><li><strong>Staff Training</strong>: Ensure that employees are well-trained in using the new infrastructure and can go through the process very effectively. A structured <a href="https://www.qooper.io/blog/mentor-mentee-roles-and-expectations" rel="noreferrer">mentor mentee</a> program can further support this, allowing experienced staff to guide newer team members and accelerate knowledge transfer.</li><li><strong>System Integration</strong>: Seamlessly integrate with existing customer onboarding and workflow management systems.</li><li><strong>User Experience Design</strong>: Create a user-friendly interface that caters to customers with varying levels of technical proficiency.</li><li><strong>Continuous Monitoring and Improvement</strong>: Regularly assess the performance of your video KYC system and make necessary adjustments based on feedback and emerging technologies.</li></ul><h2 id="future-of-kyc-trends-and-predictions">Future of KYC: Trends and Predictions</h2><p>The KYC landscape continues to evolve rapidly. Some key trends to watch include:</p><ol><li><strong>AI and Machine Learning</strong>: Advanced algorithms will further enhance fraud detection and automate complex verification processes.</li><li><strong>Biometric Advancements</strong>: Innovations in biometric technology, such as behavioral biometrics, will provide even more secure authentication methods.</li><li><strong>Blockchain and Decentralized Identity</strong>: Blockchain technology could revolutionize KYC by creating secure, decentralized identity verification systems.</li><li><strong>Regulatory Technology (RegTech)</strong>: The growth of <a href="https://www.videosdk.live/blog/what-is-regtech">RegTech</a> solutions will help financial institutions navigate complex and changing KYC regulations more efficiently.</li></ol><p>As we look to the future, the key for financial institutions will be to balance innovation with security and regulatory compliance, ensuring that digital KYC processes remain robust, efficient, and user-friendly in an increasingly digital world.</p><p>While traditional methods have served well for decades, the digital age demands more efficient, secure, and customer-friendly solutions. Staying up-to-date on emerging trends, banks, and other financial institutions, providers can successfully leverage Video KYC to streamline their operations and meet the evolving needs of their customers.</p>]]></content:encoded></item><item><title><![CDATA[Cloud Recording and RTMP Pricing]]></title><description><![CDATA[Cloud record and stream to multiple streaming platforms with the most affordable pricing. Enjoy streaming to Youtube, Twitch, Facebook, and more]]></description><link>https://www.videosdk.live/blog/cloud-recording-and-rtmp-pricing</link><guid isPermaLink="false">6322de0b5ed4260c94d4fb70</guid><category><![CDATA[Pricing]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Sun, 26 Jan 2025 09:35:00 GMT</pubDate><media:content url="http://assets.videosdk.live/static-assets/ghost/2021/09/Cloud-Recording---RTMP-thumbnail-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://assets.videosdk.live/static-assets/ghost/2021/09/Cloud-Recording---RTMP-thumbnail-1.jpg" alt="Cloud Recording and RTMP Pricing"/><p>Audio and video calling has become an important approach for majorly all corporates and entities. These calling APIs increase demand when accompanied by additional functions and attractive deliverables. API developers supplement features with various features and functions for attracting clients but the most important of all is cloud recording and RTMP. These additionals are becoming important. <br/></p><blockquote>This blog describes the two important functions- Cloud Recording and  RTMP, with their pricing. Stay tuned!</blockquote><h2 id="cloud-recording">Cloud Recording</h2><p>Cloud Recording refers to the storage of the video meeting which the host puts on recording to retrieve the meeting data for future use. It is a computer data recording system that records and stores video meetings in digital pools, typically called “the cloud”.<br/></p><p>Videosdk.live has consistently provided RTC services with cloud recording function and here we present you the pricing. Do note, our cloud recording feature is designed at our clients’ comfort. We provide various recording options to ease the workflow of our clients.<br/></p><p>There are two ways of cloud recording</p><p><strong>a) Only cloud recording  b) Recording with storage and streaming</strong><br/></p><h3 id="only-cloud-recording">Only Cloud Recording</h3><p>When a host believes in recording only the meeting from our video calling API and desires to store the recording in his cloud, he looks for this option. Videosdk.live provides users with the option of only recording the meeting and then transcode and transfer it to their cloud. This makes it easy to link your storage directly with your workflow, ensuring seamless access and management of your recordings. Additionally, you can leverage <a href="https://cloudchipr.com/blog/best-cloud-cost-optimization-tools" rel="noreferrer">cloud cost optimizations tools</a> to manage storage expenses efficiently.<br/></p><p>When a user chooses this option we assure:</p><ul><li>Only the cost of recording is charged</li><li>The cost of cloud recording is a one-time charge</li><li>There is no cost levied for storage and streaming</li><li>The meeting is recorded on our cloud</li><li>Users can transfer recorded meetings to their cloud</li><li>There is no transfer cost</li><li>The cost is computed on the number of meeting minutes and not the number of a participants<br/></li></ul><p><strong>Calculation of cost</strong></p><figure class="kg-card kg-image-card"><img src="http://assets.videosdk.live/static-assets/ghost/2021/09/CLoud.jpg" class="kg-image" alt="Cloud Recording and RTMP Pricing" loading="lazy" width="1600" height="1040"/></figure><p><strong>Cost = total recording minutes x cost per minute</strong><br/></p><p>Let’s understand the concept with some examples.</p><p><strong>Our Cost per minute= $ 0.0015 for a month</strong><br/></p><p><strong>Example 1</strong></p><p>Total minutes= 20</p><p>Cost of cloud recording= 20 x 0.0015 = $ 0.03<br/></p><p><strong>Example 2</strong></p><p>Total minutes = 160</p><p>Cost of cloud recording = 160 x 0.0015 = $ 0.24<br/></p><h3 id="cloud-recording-with-storage-and-streaming">Cloud Recording with storage and streaming</h3><p>Videosdk.live also provides cloud recording with storage and streaming. The host when makes this choice, we supplement with all three services. The video meeting is recorded along with storage and streaming<br/></p><p>When a user chooses to record along with storage and streaming, these points must be noted</p><ul><li>The cost is charged for all three functions [Recording, Storage, and Streaming]</li><li>All three functions have independent pricing</li><li>The cost of Storage is recurring per month</li><li>The streaming costs are charged as per the number of views</li><li>The cost of cloud recording is a one-time charge<br/></li></ul><p><strong>Calculation of cost</strong></p><p><strong>Cost of delivery(no.of views)= Total views x Total Minutes x $0.0010</strong><br/></p><p>Let’s understand the concept with some examples.</p><p><strong>Example 1</strong></p><p><strong>Total minutes= 30, Total Views= 90</strong><br/></p><p>Cost of recording= 30x 0.0015 = $0.045</p><p>Cost of storage= 30 x 0.003= $0.09</p><p>Cost of delivery= 30 x 90 x 0.0010= $2.7<br/></p><p><strong>Example 2</strong></p><p><strong>Total Minutes= 100, Total Views= 200</strong></p><p>Cost of recording= 100 x 0.0015 = $0.15</p><p>Cost of storage= 100 x 0.003= $0.3</p><p>Cost of delivery= 100 x 200 x 0.0010= $20<br/></p><h2 id="real-time-messaging-protocol-rtmp">Real-Time Messaging Protocol (RTMP)</h2><p>RTMP an abbreviate for Real-Time Messaging Protocol helps in the smooth transmission of data. RTMP helps streamers in streaming a large amount of data of audio, video, and other formats. It helps streaming data on multiple platforms with no trouble. It is used widely for real-time communication, live streaming, on-demand video streaming, and more.<br/></p><blockquote>Videosdk.live brings its RTMP prices with amazing features. Our RTMP functions make streamers enable easy transmission of videos to several different platforms like YouTube, Twitch, Facebook, and more.</blockquote><p>At videosdk.live, with our RTMP,</p><ul><li>You can re-stream to unlimited streaming platforms</li><li>The cost is charged as per the RTMP minutes</li><li>RTMP per video is a one-time cost<br/></li></ul><p><strong>Calculation of cost of RTMP</strong></p><figure class="kg-card kg-image-card"><img src="http://assets.videosdk.live/static-assets/ghost/2021/09/RTMP.jpg" class="kg-image" alt="Cloud Recording and RTMP Pricing" loading="lazy" width="1600" height="1040"/></figure><p><strong>Cost of RTMP per minute= Total RTMP minutes x $0.0025</strong><br/></p><p><strong>Example 1</strong></p><p>Total minutes= 60</p><p>Cost of RTMP= 60 x 0.0025= $0.15<br/></p><p><strong>Example 2</strong></p><p>Total Minutes= 200</p><p>Cost of RTMP= 200 x 0.0025= $0.5<br/></p><blockquote>Videosdk.live aims for delivering products with a qualitative aspect. All our services including cloud recording and RTMP are served with an astounding quality at affordable prices. Our additive functions- cloud recording and RTMP are some outstanding examples of quality.</blockquote>]]></content:encoded></item><item><title><![CDATA[Building a Virtual Event Platform with Prebuilt SDK]]></title><description><![CDATA[Learn how to build a virtual events platform in 5 easy steps. a step-by-step tutorial Prebulit SDK to help create a live virtual event on your platform.]]></description><link>https://www.videosdk.live/blog/building-a-virtual-event-platform-with-prebuilt-sdk</link><guid isPermaLink="false">6322de0b5ed4260c94d4fb8b</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[virtual events]]></category><dc:creator><![CDATA[Sagar Kava]]></dc:creator><pubDate>Sat, 25 Jan 2025 13:45:00 GMT</pubDate><media:content url="http://assets.videosdk.live/static-assets/ghost/2022/05/Virtual-event-platform.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://assets.videosdk.live/static-assets/ghost/2022/05/Virtual-event-platform.jpg" alt="Building a Virtual Event Platform with Prebuilt SDK"/><p>Build your virtual event platform with VideoSDK using PreBuild APIs within minutes.</p><p>Building a <a href="https://www.videosdk.live/solutions/virtual-events" rel="noreferrer">virtual event</a> platform is an excellent idea since the virtual event industry is growing rapidly with an estimated valuation to reach $774 billion by 2030. The only problem is finding the best video SDK to integrate into your app. And no doubt the are many Video SDKs out in the market but many are overpriced or lacking in features &amp; customization or simply lack quality customer support. But with Video SDK we try to solve all the current industry dilemmas and provide you the best experience possible! </p><h3 id="why-choose-videosdk-to-build-your-virtual-event-platform">Why choose VideoSDK to build your Virtual event platform?</h3><p>VideoSDK is a video &amp; audio conferencing service you can integrate into your app within a few minutes. It helps you build the best virtual event platform with <a href="https://www.videosdk.live/pricing">$20 free credit</a>. 100+ startups are using <a href="https://www.videosdk.live/">VideoSDK</a> to build powerful platforms in the Virtual event space. We provide PreBuild as well as <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/getting-started">advanced virtual event platform features</a> to integrate into your app. </p><p>If you are building a virtual events platform using Low-Code or No-Code apps then check out our below tutorials.</p><ul><li>How to embed “Video Calling API” on any low-code web builder?</li><li>How to build a video calling app with Bubble.io?</li><li><a href="https://www.videosdk.live/blog/video-calling-wordpress">How to build a video calling app on WordPress?</a></li></ul><h2 id="the-steps-to-build-a-virtual-event-platform-using-prebuilt-sdk">The steps to build a virtual event platform using Prebuilt SDK</h2><p>Following the below steps will guide you to quickly build the best virtual event platform. Make sure to follow them accordingly and if you face any issues go ahead then go ahead and join our <a href="https://discord.com/invite/Gpmj6eCq5u">discord community</a> and we will solve your issues the right way!</p><h2 id="1-create-a-videosdk-account-and-generate-api-key">1: Create a VideoSDK account and generate API Key</h2><p><a href="https://app.vidoesdk.live/"><strong>Sign Up</strong></a> on Video SDK to create your free account. Once you set up the account go to <a href="https://app.videosdk.live/settings/api-keys" rel="noopener noreferrer">settings&gt;api-keys</a> and generate a new <strong>API key</strong> for integration. (For more info, you can follow <a href="https://docs.videosdk.live/docs/guide/prebuilt-video-and-audio-calling/signup-and-create-api" rel="noopener noreferrer">How to generate API Key?</a>)</p><h2 id="2-setup-a-meeting-in-your-virtual-event-platform">2: Setup a meeting in your virtual event platform </h2><p>Create a <code>index.html</code> file and add the following <code>&lt;script&gt;</code> tag at the end of your code's <code>&lt;body&gt;</code> tag. Initialize <code>VideoSDKMeeting</code> after the script gets loaded. Replace the <code>apiKey</code> with the one generated in <strong>Step 1</strong>.</p><pre><code class="language-js">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
  &lt;head&gt;
    &lt;meta charset="UTF-8" /&gt;
    &lt;meta http-equiv="X-UA-Compatible" content="IE=edge" /&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0" /&gt;
    &lt;title&gt;Videosdk.live RTC&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
&lt;script&gt;
  var script = document.createElement("script");
  script.type = "text/javascript";

  script.addEventListener("load", function (event) {
    const meeting = new VideoSDKMeeting();

    const config = {
      name: "John Doe",
      apiKey: "&lt;API KEY&gt;", // generated in step 1
      meetingId: "milkyway", // enter your meeting id

      containerId: null,
      redirectOnLeave: "https://www.videosdk.live/",

      micEnabled: true,
      webcamEnabled: true,
      participantCanToggleSelfWebcam: true,
      participantCanToggleSelfMic: true,

      chatEnabled: true,
      screenShareEnabled: true,
      pollEnabled: true,
      whiteboardEnabled: true,
      raiseHandEnabled: true,

      recordingEnabled: true,
      recordingWebhookUrl: "https://www.videosdk.live/callback",
      recordingAWSDirPath: `/meeting-recordings/${meetingId}/`, // automatically save recording in this s3 path
      autoStartRecording: true, // auto start recording on participant joined

      brandingEnabled: true,
      brandLogoURL: "https://picsum.photos/200",
      brandName: "Awesome startup",
      poweredBy: true,

      participantCanLeave: true, // if false, leave button won't be visible

      // Live stream meeting to youtube
      livestream: {
        autoStart: true,
        outputs: [
          // {
          //   url: "rtmp://x.rtmp.youtube.com/live2",
          //   streamKey: "&lt;STREAM KEY FROM YOUTUBE&gt;",
          // },
        ],
      },

      permissions: {
        askToJoin: false, // Ask joined participants for entry in meeting
        toggleParticipantMic: true, // Can toggle other participant's mic
        toggleParticipantWebcam: true, // Can toggle other participant's webcam
        drawOnWhiteboard: true, // Can draw on whiteboard
        toggleWhiteboard: true, // Can toggle whiteboard
        toggleRecording: true, // Can toggle meeting recording
        removeParticipant: true, // Can remove participant
        endMeeting: true, // Can end meeting
      },

      joinScreen: {
        visible: true, // Show the join screen ?
        title: "Daily scrum", // Meeting title
        meetingUrl: window.location.href, // Meeting joining url
      },

      pin: {
        allowed: true, // participant can pin any participant in meeting
        layout: "SPOTLIGHT", // meeting layout - GRID | SPOTLIGHT | SIDEBAR
      },

      leftScreen: {
        // visible when redirect on leave not provieded
        actionButton: {
          // optional action button
          label: "Video SDK Live", // action button label
          href: "https://videosdk.live/", // action button href
        },
      },

      notificationSoundEnabled: true,

      maxResolution: "sd", // "hd" or "sd"
    };

    meeting.init(config);
  });

  script.src =
    "https://sdk.videosdk.live/rtc-js-prebuilt/0.3.1/rtc-js-prebuilt.js";
  document.getElementsByTagName("head")[0].appendChild(script);
&lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre><h2 id="3-generate-your-unique-meeting-link">3: Generate your unique meeting link </h2><p>Create createMeeting.htm and add <code>createMeeting()</code> function<a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/dynamic-meeting-link#step-2-create-createmeetinghtml-and-add-createmeeting-function">​</a></p><p>Add a <code>&lt;script&gt;</code> which will contain <code>createMeeting()</code> which will create and redirect to a new meeting. And add this method to <code>onClick</code> of <code>&lt;button&gt;</code></p><p>Your <code>&lt;body&gt;</code> should look something like this.</p><pre><code class="language-js">&lt;body&gt;
  &lt;script&gt;
    // Function to create meeting ID
    function createMeeting() {
          let meetingId =  'xxxxyxxx'.replace(/[xy]/g, function(c) {
              var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r &amp; 0x3 | 0x8);
              return v.toString(16);
          });
          console.log("http://"+ window.location.host + "?meetingId="+ meetingId)
          document.getElementById("copyInput").value = "https://"+ window.location.host + "/meeting.html?meetingId="+ meetingId;
    }

    // Function to copy the link
    function copyFunction() {
      /* Get the text field */
      var copyText = document.getElementById("copyInput");

      /* Select the text field */
      copyText.select();
      copyText.setSelectionRange(0, 99999); /* For mobile devices */

      /* Copy the text inside the text field */
      navigator.clipboard.writeText(copyText.value);
    }
  &lt;/script&gt;
  &lt;div&gt;
    &lt;button onclick="createMeeting()"&gt;Create Meeting&lt;/button&gt;
    &lt;br/&gt;
    &lt;input type="text" id="copyInput"&gt;
    &lt;button onclick="myFunction()"&gt;Copy Link&lt;/button&gt;
  &lt;/div&gt;
&lt;/body&gt;</code></pre><h2 id="4-update-to-take-the-meetingid-from-the-url%E2%80%8B">4: Update to take the meetingId from the URL.<a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/dynamic-meeting-link#step-2-update-your-meetinghtml-to-take-the-meetingid-from-the-url">​</a></h2><p>In this way, you will be able to access meetingId from the URL and each unique URL will work as a different room</p><pre><code class="language-js">//...
&lt;script&gt;

   script.addEventListener("load", function (event) {
      //Get URL query parameters
      const url = new URLSearchParams(window.location.search);

      //...

      const config = {
        // ...
        meetingId: url.get("meetingId"), // Get meeting id from params.
        // ...
      };

      const meeting = new VideoSDKMeeting();
      meeting.init(config);
    });

&lt;/script&gt;

//...</code></pre><h2 id="5-run-and-test">5: Run and test</h2><p>Install an HTTP server if you don't already have one and run the server to join the meeting from the browser.<a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/dynamic-meeting-link#step-3-run-and-test">​</a></p><ul><li>Node.js</li></ul><pre><code class="language-js">$ npm install -g live-server
$ live-server --port=8000</code></pre><h4 id="find-the-npm-run-start-for-python-php-wamp-and-xampp-here">Find the NPM run start for Python, PHP, WAMP, and XAMPP <a href="https://docs.videosdk.live/prebuilt/guide/prebuilt-video-and-audio-calling/quick-start">here</a>.</h4>
<h3 id="prebuild-sdk-features-list"><br>PreBuild SDK features list</br></h3><p/><p>Below are the features of the virtual event platform. They can be easily implemented into your virtual event app. Simply input the 'true' or 'false' value in the<em> &lt;permission object</em> &gt; to your features for reference see the below video. </p>
<!--kg-card-begin: html-->
<iframe width="560" height="315" src="https://www.youtube.com/embed/o8DIxmT1Ubg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""/>
<!--kg-card-end: html-->
<h3 id="build-a-custom-virtual-event-platform"><br>Build a custom virtual event platform</br></h3><p/><p>With Video SDK you can create a huge number of custom features. They are very helpful because the custom features are specific to your industry niche. For example, in a <a href="https://www.theknowledgeacademy.com/courses/project-management-courses/" rel="noreferrer">project management course</a>, these features can support live collaboration, breakout discussions, and hands-on training exercises. We have kept the implementation of these features as simple as possible for our developers as well as no code developers. </p><p><strong>Interactive live streaming</strong> - <a href="https://docs.videosdk.live/api-reference/realtime-communication/start-hlsStream">Host up to 50,000 participants</a> on your virtual event platform in a single meeting. </p><p><strong>Break out room</strong> - Utilize the breakout rooms to flexibly merge meetings or transfer hosts to participants &amp; vice versa &amp; more.</p><p><strong>Custom video track</strong> - Integrate <a href="https://www.banuba.com/facear-sdk/face-filters?utm_source=adwords&amp;utm_medium=ppc&amp;utm_campaign=Brand+USA+Canada+India&amp;utm_term=banuba&amp;hsa_tgt=kwd-325576249823&amp;hsa_grp=133935013084&amp;hsa_mt=b&amp;hsa_cam=15897989032&amp;hsa_ver=3&amp;hsa_src=g&amp;hsa_net=adwords&amp;hsa_kw=banuba&amp;hsa_acc=6834955494&amp;hsa_ad=575300001743&amp;gclid=Cj0KCQjwyYKUBhDJARIsAMj9lkGud5Fj_CV8UOxiYTPkpt9YYQWOSJVS-emzsFTBSpouX7HpNCSIm6IaAq1_EALw_wcB">Banuba</a> a Face Filter SDK that provides awesome Filters and detailed analytics such as face tracking, background subtraction, &amp; more.</p><h3 id="open-source-projects">Open source projects</h3><p/><ul>
<li><strong><a href="https://github.com/videosdk-live/videosdk-rtc-react-prebuilt-ui">Prebuilt React SDK</a> UI Kit available on GitHub for free</strong></li>
</ul>
<p>You can go to GitHub &amp; and use our PreBuild SDK UI kit as it is open source. This means you can use our PreBuild video SDK for free as well as customize it as per your needs for your virtual event platform.</p><h3 id="conclusion">Conclusion</h3><p><br>Congrats on integrating Video SDK in your virtual event app! If you wish to add functionalities like chat messaging, and screen sharing, you can always check out our <a href="https://docs.videosdk.live/">documentation</a>. If you face any difficulty with the implementation you can check out the <a href="https://github.com/videosdk-live/videosdk-rtc-javascript-sdk-example">example on GitHub</a> or connect with us on our <a href="https://discord.gg/Gpmj6eCq5u">discord community</a>.<br/></br></p>]]></content:encoded></item><item><title><![CDATA[Building or Buying Video Calling API: Comprehensive Guide]]></title><description><![CDATA[The audio and video calling trends have increased. Being an entity it leaves a question that whether a company should build API on its own or purchase it from some reliable managed services. Let's discuss!]]></description><link>https://www.videosdk.live/blog/build-or-buy-video-calling-api</link><guid isPermaLink="false">6322de0b5ed4260c94d4fb6a</guid><category><![CDATA[video-conferencing]]></category><dc:creator><![CDATA[Sagar Kava]]></dc:creator><pubDate>Sat, 25 Jan 2025 13:26:00 GMT</pubDate><media:content url="http://assets.videosdk.live/static-assets/ghost/2021/08/Blog-Thumbnail--1-.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://assets.videosdk.live/static-assets/ghost/2021/08/Blog-Thumbnail--1-.jpg" alt="Building or Buying Video Calling API: Comprehensive Guide"/><p>Communication has always been a crucial part of developing interactions with a community. With the advent of technology, face-to-face communication has also changed its conduct. The audio and video calls have become a crucial interaction source between two people, a group, a business, and a corporate organization among all sectors with the emergence of the COVID-19 pandemic. The questions arise, <br/></p><ul><li><em>How did these apps shift to video calling so rapidly?</em></li><li><em>Do they manually build it or do they arrange it from some development source? </em><br/></li></ul><blockquote>Well currently, real-time communication is in increasing demand. This blog guides whether a company should build its Video and audio calling API or count on a more reliable managed service for the same.</blockquote><figure class="kg-card kg-image-card kg-width-wide"><img src="http://assets.videosdk.live/static-assets/ghost/2021/08/Table.png" class="kg-image" alt="Building or Buying Video Calling API: Comprehensive Guide" loading="lazy" width="1432" height="678"/></figure><h2 id="building-audio-and-video-calling-api">Building audio and video calling API</h2><p>Developing audio and video calling API by a business is a matter of utmost care as it involves a high amount of R&amp;D. A company developing these APIs has to build vast technical support. Observe the technology changes &amp; advancements to keep their platform updated all the time.</p><p>The companies exclusively planning to distribute these APIs as a <em>platform</em> shall invest in building them, as they serve a purpose, and are accustomed to technological advancements. These companies supplement considerable resources and knowledge for the development of these APIs, making work adaptive. Building an audio and video calling API with <a href="https://www.mavlers.com/salesforce-marketing-cloud-services/" rel="noreferrer">Salesforce Marketing Cloud services</a> is an interesting and slightly unconventional integration, as Salesforce Marketing Cloud is primarily focused on marketing automation and customer engagement.</p><h3 id="observations-while-developing-apis-on-your-own">Observations while developing APIs on your own</h3><p><strong>A well-defined Budget</strong></p><p>A company needs to invest a huge amount of money, as it involves high development costs concerning <a href="https://uxpilot.ai/website-design-templates" rel="noreferrer">UI/UX design</a>, database management, cloud services, scaling, security, etc. It also includes costs of infrastructure, hosting, maintenance, salaries to personnel, and more, increasing the overall budget.</p><p><strong>Manpower Costs</strong></p><p>Developing audio and video calling APIs involves a huge development team. It requires a skilled force to work on specialized device platforms like Android, iOS, web, etc. Instead of hiring manpower for these activities, a company can prefer a purchase, and make that team occupied in the primary goals of the company. </p><p><strong>Time Investment</strong></p><p>Developing an API involves a huge time investment. While developing APIs on its own, involves opportunity costs, and above all the chances of successful development in one go is a question of concern for the company.</p><p><strong>Scalability</strong></p><p>When a company develops audio and video calling API on its own, it is hard to comply with scalability. The open-source aid generally can scale only up to 50-100 participants in one video call. In the case of allowing a huge participant count in one meeting, managed services make the effort. It can scale 5000+ participants at once.</p><p><strong>Change Resilience</strong></p><p>A company developing APIs as a feature of their application lacks resilience to change. They need to comply regularly with new technologies and upgrades. This problem arises when companies do not keep up with the changing factors. Buying an API with managed services looks at upgrades and changes regularly.</p><h2 id="buying-audio-and-video-calling-api">Buying audio and video calling API</h2><figure class="kg-card kg-image-card"><img src="http://assets.videosdk.live/static-assets/ghost/2021/08/Buy-video-calling-API.jpg" class="kg-image" alt="Building or Buying Video Calling API: Comprehensive Guide" loading="lazy" width="2000" height="400"/></figure><p>When a company decides to buy <a href="https://www.videosdk.live/audio-video-conferencing">audio and video calling APIs</a>, it considerably looks to integrate these APIs as a feature for their application and not as a dedicated platform. Here, buying APIs is a more defined approach than building them. Developers are fully acquainted with the latest technologies and innovations, serving dedicated security, customization, and support. Companies who keep calling APIs as their secondary function must invest in buying them.</p><p>Corporations and organizations engaged in businesses like health, education, e-commerce, retail, and other similar industries should always choose to buy APIs from managed services. These services are easy to integrate and also facilitate security, customizations, upgradation, and technical support for the APIs. They are reliable and induce low risk.</p><h3 id="observations-while-purchasing-apis">Observations while purchasing APIs</h3><p><strong>Cost-effective</strong></p><p>Readymade audio and video calling APIs include features like call encryption, HIPAA compliance, spatial audio, chat support, and other elements. These costs are huge if a company develops every single one of them on its own. Rather when it purchases APIs, the overall effective cost is lower. This brings these APIs to qualify the cost worth for a company.</p><p><strong>Saves time and efforts</strong></p><p>Buying audio and video calling API from managed services saves a lot of time and development efforts for a company. It merely needs to comply with technical requirements for integration. The companies just need to invest very little to integrate the purchased APIs into their application.</p><p><strong>Customization</strong></p><p>A purchased API is often designed with customization primacy. A company can easily alter the design and the contents as per its requirements without digging deep into the low-level specifications. Contrarily, a company that designs API on its own usually lacks customization as it incurs huge costs of development. </p><p><strong>Secured communication</strong></p><p>A managed video calling service by a company comes with end-to-end encryption. This denotes that communication between two persons, or a group is fully secured and no one other than the participants can access it. A company generally neglects security in the initial phase of development due to higher costs.</p><p><strong>Scalability</strong></p><p>Managed services can scale participants to more than 5,000 in one meeting. Whereas, open sources can scale not more than 100-150 participants. It is also believed that if a company has just begun its journey into the corporates, it must always keep its trust towards these services for scalable support. </p><p><strong>Support</strong></p><p>On purchasing APIs, there is a provision of support and consultancy to the company. From help in customizing the desired API to upgradation with changes in technology, buying an API is useful. Some services also provide 24x7 technical support.</p><p><strong>Prevents platform abuse</strong></p><p>A company is protected from platform abuse by purchasing video and audio calling APIs from managed services. The services are developed with security that prevents happening of any sort of trouble, malpractice, or misuse of the APIs in use.<br/></p><figure class="kg-card kg-image-card"><img src="http://assets.videosdk.live/static-assets/ghost/2021/08/build-vs-buy-1.jpg" class="kg-image" alt="Building or Buying Video Calling API: Comprehensive Guide" loading="lazy" width="2000" height="400"/></figure><h2 id="the-final-verdict">The Final Verdict</h2><p>Audio and video calling are always considered the most attractive feature of any application. Therefore, a company that deals in real-time communication with its clients and consumers aspires to create it in the most astounding approach. Apart from looks, security, and quality of a meeting are the most concerning factors. All of these are possible approaches for a company but at huge costs. Managed services offer all these features, and they are more secure than the ones a company develops.<br/></p><blockquote><a href="https://www.videosdk.live/">VideoSDK  </a>is a platform that develops audio and video calling APIs for their clients from various industries to ease their functioning by simple integrations along with upgradation, customization, and security. We support you in your dedicated work. Sign in to the <a href="https://app.videosdk.live/">Dashboard</a> and start building your desired Audio and video calling API.<br/></blockquote>]]></content:encoded></item><item><title><![CDATA[Live Webinar - Create a Low Latency Live Streaming App in React Native ⚛️]]></title><description><![CDATA[Register this workshop to build the sample app or integrate the low latency live streaming within your React Native app.]]></description><link>https://www.videosdk.live/blog/create-a-low-latency-live-streaming-app-in-react-native</link><guid isPermaLink="false">6322de0b5ed4260c94d4fb77</guid><dc:creator><![CDATA[Sagar Kava]]></dc:creator><pubDate>Sat, 25 Jan 2025 08:58:00 GMT</pubDate><media:content url="http://assets.videosdk.live/static-assets/ghost/2021/11/React-native-Live-streaming-1.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: html--><iframe width="560" height="315" src="https://www.youtube.com/embed/BQ1vWEC5WrE" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""/><!--kg-card-end: html--><img src="http://assets.videosdk.live/static-assets/ghost/2021/11/React-native-Live-streaming-1.png" alt="Live Webinar - Create a Low Latency Live Streaming App in React Native ⚛️"/><p><br>Register this workshop to build the sample app or integrate the low latency live streaming within your React Native app.<br><br>Tuesday, 16 Nov 06:00 PM<br><br>? In the session, we covered<br><br>➟ Introduction to <a href="https://www.linkedin.com/feed/hashtag/?keywords=videosdk&amp;highlightedUpdateUrns=urn%3Ali%3Aactivity%3A6864207216082206720">#VideoSDK</a><br>➟ How React Native Video SDK works?<br>➟ Integration of React Native SDK<br>➟ Go Live<br>➟ Various Use Cases<br>➟ Q&amp;A Session and More.<br><br>The <a href="https://videosdk.live">Video SDK</a> React Native SDK is available now to help you quickly add voice, video, and live broadcasting to your mobile applications on iOS and Android. You can get the <a href="https://github.com/videosdk-live/videosdk-rtc-react-native-sdk-example">Video SDK React Native SDK here on Github.</a> <br><br>This code sample demonstrates a one-to-one and group video call application built with <a href="https://docs.videosdk.live/docs/realtime-communication/sdk-reference/react-native-sdk/setup" rel="nofollow">Video SDK RTC React Native SDK</a> and <a href="https://docs.videosdk.live/docs/realtime-communication/sdk-reference/react-sdk/setup" rel="nofollow">Video SDK RTC React SDK</a></br></br></br></br></br></br></br></br></br></br></br></br></br></br></br></br></p><h3 id="features"><br>Features</br></h3><ul><li>Built for serverless video calling experience in Android and iOS.</li><li>Scale it up to 5,000 participants with low code.</li><li>10,000 minutes free on a monthly basis</li><li>Video API with real-time audio, video, and data streams</li><li>5,000+ participants support</li><li>Chat support with rich media.</li><li>Screen sharing with HD and Full HD.</li><li>Play the real-time video in a meeting</li><li>Connect it with social media such as Facebook, Youtube, etc (RTMP out support).</li><li>Intelligent speaker switch</li><li>Record your meetings on cloud</li><li>Customize UI and build other rich features with our new data streams such as whiteboard, poll, Q &amp; A, etc.</li></ul><figure class="kg-card kg-image-card"><img src="http://assets.videosdk.live/static-assets/ghost/2021/11/Untitled-design--32-.png" class="kg-image" alt="Live Webinar - Create a Low Latency Live Streaming App in React Native ⚛️" loading="lazy" width="891" height="194" srcset="http://assets.videosdk.live/static-assets/ghost/size/w600/2021/11/Untitled-design--32-.png 600w, http://assets.videosdk.live/static-assets/ghost/2021/11/Untitled-design--32-.png 891w" sizes="(min-width: 720px) 720px"/></figure>]]></content:encoded></item><item><title><![CDATA[Build an Android Live Streaming Video Chat App Using Kotlin?]]></title><description><![CDATA[In this article, we'll guide you through the process of building an Android(Kotlin) live-streaming app using VideoSDK. ]]></description><link>https://www.videosdk.live/blog/android-live-streaming</link><guid isPermaLink="false">642c269d2c7661a49f381e90</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Fri, 24 Jan 2025 13:33:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/HTTP-Live-Streaming-Kotlin-2.png" medium="image"/><content:encoded><![CDATA[<h2 id="tldr">tl;dr</h2>
<img src="https://assets.videosdk.live/static-assets/ghost/2024/04/HTTP-Live-Streaming-Kotlin-2.png" alt="Build an Android Live Streaming Video Chat App Using Kotlin?"/><p><a href="https://www.videosdk.live/blog/what-is-http-live-streaming"><strong>HTTP Live Streaming</strong></a> (HLS) is a widely adopted streaming protocol developed by Apple Inc. to transmit audio and video content over the internet. It operates on a client-server model, delivering a seamless and adaptive streaming experience. HLS has gained popularity due to its compatibility with various devices and browsers, making it an ideal choice for content delivery.</p><p>You've likely consumed a fair amount of live streams if you're an avid consumer of online content in the present day. With live streaming becoming the preferred source of learning and entertainment for many, it's hard to miss out on live broadcasts, whether it's for attending online classes, following sports events, watching fitness lessons, or engaging with celebrities.</p><p>If you're a developer looking to build a top-notch live streaming experience in your Android app, this article is for you.</p><h2 id="why-videosdk-is-your-go-to-for-live-streaming">Why VideoSDK is Your Go-To for Live Streaming?</h2><p><a href="https://www.videosdk.live/">VideoSDK </a>is a perfect choice for those seeking a live-streaming platform that offers the necessary features to create high-quality streams. The platform supports screen sharing and real-time Messaging, allows broadcasters to invite audience members to the stage, and supports 100 Participants, ensuring that your live streams are interactive and engaging. With VideoSDK, you can also use your own customized layout template for live streaming. Additionally, VideoSDK caters to users in the United Kingdom, Australia, USA, India, UAE, Canada, and Nigeria.</p><p>In terms of integration, VideoSDK offers a simple and quick integration process, allowing you to seamlessly integrate live streaming into your app. This ensures that you can enjoy the benefits of live streaming without any technical difficulties or lengthy implementation processes.</p><p>Furthermore, VideoSDK is <a href="https://www.videosdk.live/pricing">budget-friendly</a>, making it an affordable option for businesses of all sizes. You can enjoy the benefits of a feature-rich live-streaming platform without breaking the bank, making it an ideal choice for startups and small businesses.</p><h2 id="build-a-live-streaming-android-app">Build a live-streaming Android App</h2><p>The below steps will give you all the information to quickly build an interactive live-streaming <a href="https://uxpilot.ai/mobile-design-templates/android" rel="noreferrer">android app</a>. Please carefully follow along, and if you have any trouble, let us know right away on <a href="https://discord.gg/f2WsNDN9S5">Discord</a>, and we will be happy to help you.</p><h3 id="prerequisite">Prerequisite</h3><ul><li><a href="https://www.oracle.com/in/java/technologies/downloads/">Java Development Kit</a>.</li><li><a href="https://developer.android.com/studio">Android Studio 3.0</a> or later.</li><li>Android SDK API Level 21 or higher.</li><li>A mobile device that runs Android 5.0 or later.</li><li>A token from the VideoSDK <a href="https://app.videosdk.live/api-keys">dashboard</a></li></ul><h3 id="create-a-new-project">Create a new project</h3><p>In Android Studio, create a Phone and Tablet Android project with an Empty Activity.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/04/android_new_project.png" class="kg-image" alt="Build an Android Live Streaming Video Chat App Using Kotlin?" loading="lazy" width="899" height="652"/></figure><p>The next step is to provide a name. We have set the name as HLSDemo.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/04/Screenshot-from-2023-04-05-12-18-04.png" class="kg-image" alt="Build an Android Live Streaming Video Chat App Using Kotlin?" loading="lazy" width="887" height="641"/></figure><h2 id="integrate-videosdk">Integrate VideoSDK</h2><p>Add the repository to the project's <code>settings.gradle</code> file.</p>
<pre><code class="language-js">dependencyResolutionManagement{
  repositories {
    // ...
    google()
    mavenCentral()
    maven { url 'https://jitpack.io' }
    maven { url "https://maven.aliyun.com/repository/jcenter" }
  }
}</code></pre><p>Add the following dependency to your app's <code>build.gradle</code>.</p><pre><code class="language-js">dependencies {
  implementation 'live.videosdk:rtc-android-sdk:0.1.26'

  // library to perform Network call to generate a meeting id
  implementation 'com.amitshekhar.android:android-networking:1.0.2'

  // other app dependencies
  }</code></pre><blockquote>If your project has set <code>android.useAndroidX=true</code>, then set <code>android.enableJetifier=true</code> in the <code>gradle.properties</code> file to migrate your project to AndroidX and avoid duplicate class conflict.</blockquote><h3 id="add-permissions-to-your-project">Add permissions to your project</h3><p><br>In <code>/app/Manifests/AndroidManifest.xml</code>, add the following permissions after <code>&lt;/application&gt;</code>.</br></p><pre><code class="language-js">&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/&gt;
&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
&lt;uses-permission android:name="android.permission.CAMERA" /&gt;</code></pre><h3 id="structure-of-project">Structure of project</h3><p>We will create two activities and two fragments. First activity is <code>JoinActivity</code> , which allows users to create/join the meeting, and another one is <code>MeetingActivity</code> , which will initialize meetings and replace <code>mainLayout</code> with <code>SpeakerFragment</code> or with <code>ViewerFragment</code> according to the user's choice.</p><p>Our project structure would look like this.</p><pre><code class="language-js">  app
   ├── java
   │    ├── packagename
   │         ├── JoinActivity
   │         ├── MeetingActivity
   │         ├── SpeakerAdapter
   │         ├── SpeakerFragment
   |         ├── ViewerFragment
   ├── res
   │    ├── layout
   │    │    ├── activity_join.xml
   │    │    ├── activity_meeting.xml
   |    |    ├── fragment_speaker.xml
   |    |    ├── fragment_viewer.xml
   │    │    ├── item_remote_peer.xml</code></pre><blockquote>You have to set <code>JoinActivity</code> as Launcher activity.</blockquote><h3 id="app-architecture">App Architecture</h3>
<!--kg-card-begin: html-->
<center>

<img src="https://cdn.videosdk.live/website-resources/docs-resources/android_ils_quickstart_app_structure.png" alt="Build an Android Live Streaming Video Chat App Using Kotlin?"/>

</center>
<!--kg-card-end: html-->
<h2 id="essential-steps-for-building-the-video-calling-functionality">Essential Steps for Building the Video Calling Functionality</h2><h3 id="step-1-creating-joining-screen">Step 1: Creating Joining Screen</h3><p>Create a new Activity named <code>JoinActivity</code></p><h4 id="11-creating-ui-for-joining-the-screen">1.1 Creating UI for Joining the Screen</h4>
<p>The Joining screen will include :</p><ol><li><strong>Create Button</strong> - This button will create a new meeting for you.</li><li><strong>TextField for Meeting ID</strong> - This text field will contain the meeting ID you want to join.</li><li><strong>Join as Host Button</strong> - This button will join the meeting as <strong>host </strong>with <code>meetingId</code> you provided.</li><li><strong>Join as Viewer Button</strong> - This button will join the meeting as a <strong>viewer</strong> with <code>meetingId</code> you provided.</li></ol><p>In <code>/app/res/layout/activity_join.xml</code> file, replace the content with the following.</p><pre><code class="language-js">&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/createorjoinlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black"
    android:gravity="center"
    android:orientation="vertical"&gt;

    &lt;Button
        android:id="@+id/btnCreateMeeting"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Create Meeting"
        android:textAllCaps="false" /&gt;

    &lt;TextView
        android:id="@+id/tvText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingVertical="5sp"
        android:text="OR"
        android:textColor="@color/white"
        android:textSize="20sp" /&gt;

    &lt;EditText
        android:id="@+id/etMeetingId"
        android:theme="@android:style/Theme.Holo"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:hint="Enter Meeting Id"
        android:textColor="@color/white"
        android:textColorHint="@color/white" /&gt;

    &lt;Button
        android:id="@+id/btnJoinHostMeeting"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8sp"
        android:text="Join as Host"
        android:textAllCaps="false" /&gt;

    &lt;Button
        android:id="@+id/btnJoinViewerMeeting"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Join as Viewer"
        android:textAllCaps="false" /&gt;

&lt;/LinearLayout&gt;</code></pre><h4 id="12-integration-of-create-meeting-api">1.2 Integration of Create Meeting API</h4>
<ol>
<li>Create field <code>sampleToken</code> in <code>JoinActivity</code> which will hold the generated token from the <a href="https://app.videosdk.live/api-keys">VideoSDK dashboard</a>. This token will be used in the VideoSDK config as well as generating meetingId.</li>
</ol>
<pre><code class="language-js">class JoinActivity : AppCompatActivity() {

  //Replace with the token you generated from the VideoSDK Dashboard
  private var sampleToken = ""

  override fun onCreate(savedInstanceState: Bundle?) {
    //...
  }
}</code></pre><ol start="2">
<li>
<p>On the <strong>Join Button as Host</strong> <code>onClick</code> events, we will navigate to <code>MeetingActivity</code> with token, meetingId, and mode as <code>CONFERENCE</code>.</p>
</li>
<li>
<p>On the <strong>Join Button as Viewer</strong> <code>onClick</code> events, we will navigate to <code>MeetingActivity</code> with token, meetingId, and mode as <code>Viewer</code>.</p>
</li>
</ol>
<pre><code class="language-js">class JoinActivity : AppCompatActivity() {

   //Replace with the token you generated from the VideoSDK Dashboard
   private var sampleToken = "" 

   override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_join)

      val btnCreate = findViewById&lt;Button&gt;(R.id.btnCreateMeeting)
      val btnJoinHost = findViewById&lt;Button&gt;(R.id.btnJoinHostMeeting)
      val btnJoinViewer = findViewById&lt;Button&gt;(R.id.btnJoinViewerMeeting)
      val etMeetingId = findViewById&lt;EditText&gt;(R.id.etMeetingId)

      // create meeting and join as Host
      btnCreate.setOnClickListener {
          createMeeting(
              sampleToken
          )
      }

      // Join as Host
      btnJoinHost.setOnClickListener {
          val intent = Intent(this@JoinActivity, MeetingActivity::class.java)
          intent.putExtra("token", sampleToken)
          intent.putExtra("meetingId", etMeetingId.text.toString().trim { it &lt;= ' ' })
          intent.putExtra("mode", "CONFERENCE")
          startActivity(intent)
      }

      // Join as Viewer
      btnJoinViewer.setOnClickListener {
          val intent = Intent(this@JoinActivity, MeetingActivity::class.java)
          intent.putExtra("token", sampleToken)
          intent.putExtra("meetingId", etMeetingId.text.toString().trim { it &lt;= ' ' })
          intent.putExtra("mode", "VIEWER")
          startActivity(intent)
      }
    }

    private fun createMeeting(token: String) {
      // we will explore this method in the next step
    }</code></pre><ol start="4">
<li>For the <strong>Create Button</strong>, under <code>createMeeting</code> method we will generate meetingId by calling API and navigating to <code>MeetingActivity</code> with the token, generated meetingId, and mode as <code>CONFERENCE</code>.</li>
</ol>
<pre><code class="language-js">class JoinActivity : AppCompatActivity() {
  //...onCreate
 private fun createMeeting(token: String) {
  // we will make an API call to VideoSDK Server to get a roomId
  AndroidNetworking.post("https://api.videosdk.live/v2/rooms")
      .addHeaders("Authorization", token) //we will pass the token in the Headers
      .build()
      .getAsJSONObject(object : JSONObjectRequestListener {
          override fun onResponse(response: JSONObject) {
            try {
              // response will contain `roomId`
              val meetingId = response.getString("roomId")

              // starting the MeetingActivity with received roomId and our sampleToken
              val intent = Intent(this@JoinActivity, MeetingActivity::class.java)
              intent.putExtra("token", sampleToken)
              intent.putExtra("meetingId", meetingId)
              intent.putExtra("mode", "CONFERENCE")
              startActivity(intent)
            } catch (e: JSONException) {
                e.printStackTrace()
            }
          }

          override fun onError(anError: ANError) {
            anError.printStackTrace()
            Toast.makeText(this@JoinActivity, anError.message, Toast.LENGTH_SHORT)
                .show()
          }
      })
  }
}</code></pre><ol start="5">
<li>Our App is completely based on audio and video commutation, that's why we need to ask for runtime permissions <code>RECORD_AUDIO</code> and <code>CAMERA</code>. So, we will implement permission logic on <code>JoinActivity</code>.</li>
</ol>
<pre><code class="language-js">class JoinActivity : AppCompatActivity() {
  companion object {
    private const val PERMISSION_REQ_ID = 22
    private val REQUESTED_PERMISSIONS = arrayOf(
        Manifest.permission.RECORD_AUDIO,
        Manifest.permission.CAMERA
    )
  }

  private fun checkSelfPermission(permission: String, requestCode: Int) {
    if (ContextCompat.checkSelfPermission(this, permission) !=
        PackageManager.PERMISSION_GRANTED
    ) {
        ActivityCompat.requestPermissions(this, REQUESTED_PERMISSIONS, requestCode)
    }
  }

  override fun onCreate(savedInstanceState: Bundle?) {
    //... button listeneres
    checkSelfPermission(REQUESTED_PERMISSIONS[0], PERMISSION_REQ_ID)
    checkSelfPermission(REQUESTED_PERMISSIONS[1], PERMISSION_REQ_ID)
  }
}</code></pre><blockquote>You will get <code>Unresolved reference: MeetingActivity</code> error, but don't worry. It will automatically solved once you create <code>MeetingActivity</code>.</blockquote><h3 id="step-2-creating-meeting-screen">Step 2: Creating Meeting Screen</h3><p>Create a new Activity named <code>MeetingActivity</code>.</p><h4 id="21-creating-the-ui-for-the-meeting-screen">2.1 Creating the UI for the Meeting Screen</h4>
<p>In <code>/app/res/layout/activity_meeting.xml</code> file, replace the content with the following.</p><pre><code class="language-js">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black"
    tools:context=".MeetingActivity"&gt;

    &lt;TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Creating a meeting for you"
        android:textColor="@color/white"
        android:textFontWeight="700"
        android:textSize="20sp" /&gt;

&lt;/RelativeLayout&gt;</code></pre><h4 id="22-initializing-the-meeting">2.2 Initializing the Meeting</h4>
<p>After getting the token, meetigId, and mode from <code>JoinActivity</code>,</p><ol>
<li>Initialize <strong>VideoSDK</strong>.</li>
<li>Configure <strong>VideoSDK</strong> with the token.</li>
<li>Initialize the meeting with required params such as <code>meetingId</code>, <code>participantName</code>, <code>micEnabled</code>, <code>webcamEnabled</code> , <code>mode</code>, and more.</li>
<li>Join the room with <code>meeting.join()</code> method.</li>
<li>Add <code>MeetingEventListener</code> for listening  <strong>Meeting Join</strong> event.</li>
<li>Check mode of <code>localParticipant</code>, If the mode is <strong>CONFERENCE</strong> then we will replace mainLayout with <code>SpeakerFragment</code> otherwise, replace it with <code>ViewerFragment</code>.</li>
</ol>
<pre><code class="language-java">class MeetingActivity : AppCompatActivity() {
  var meeting: Meeting? = null
      private set

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_meeting)

    val meetingId = intent.getStringExtra("meetingId")
    val token = intent.getStringExtra("token")
    val mode = intent.getStringExtra("mode")
    val localParticipantName = "John Doe"
    val streamEnable = mode == "CONFERENCE"

    // initialize VideoSDK
    VideoSDK.initialize(applicationContext)

    // Configuration VideoSDK with Token
    VideoSDK.config(token)

    // Initialize VideoSDK Meeting
    meeting = VideoSDK.initMeeting(
      this@MeetingActivity, meetingId, participantName,
      micEnabled, webcamEnabled,null, null, false, null, null)

    // join Meeting
    meeting!!.join()

    // if mode is CONFERENCE than replace mainLayout with SpeakerFragment otherwise with ViewerFragment
    meeting!!.addEventListener(object : MeetingEventListener() {
      override fun onMeetingJoined() {
          if (meeting != null) {
            if (mode == "CONFERENCE") {
              //pin the local partcipant
              meeting!!.localParticipant.pin("SHARE_AND_CAM")
              supportFragmentManager
                  .beginTransaction()
                  .replace(R.id.mainLayout, SpeakerFragment(), "MainFragment")
                  .commit()
              } else if (mode == "VIEWER") {
                supportFragmentManager
                    .beginTransaction()
                    .replace(R.id.mainLayout, ViewerFragment(), "viewerFragment")
                    .commit()
              }
          }
      }
    })
  }
}</code></pre><h3 id="step-3-implement-speakerview">Step 3: Implement SpeakerView</h3><p>After successfully entering the meeting, it's time to render the speaker's view and manage controls such as toggling the webcam/mic, start/stop HLS, and leave the meeting.</p><ul><li>Create a new fragment named <code>SpeakerFragment</code>.</li><li>In <code>/app/res/layout/fragment_speaker.xml</code> file, replace the content with the following.</li></ul><pre><code class="language-js">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".SpeakerFragment"&gt;

    &lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginVertical="8sp"
        android:paddingHorizontal="10sp"&gt;

        &lt;TextView
            android:id="@+id/tvMeetingId"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Meeting Id : "
            android:textColor="@color/white"
            android:textSize="18sp"
            android:layout_weight="3"/&gt;

        &lt;Button
            android:id="@+id/btnLeave"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Leave"
            android:textAllCaps="false"
            android:layout_weight="1"/&gt;

    &lt;/LinearLayout&gt;

    &lt;TextView
        android:id="@+id/tvHlsState"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Current HLS State : NOT_STARTED"
        android:textColor="@color/white"
        android:textSize="18sp" /&gt;

    &lt;androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvParticipants"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginVertical="10sp"
        android:layout_weight="1" /&gt;

    &lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"&gt;

        &lt;Button
            android:id="@+id/btnHLS"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Start HLS"
            android:textAllCaps="false" /&gt;

        &lt;Button
            android:id="@+id/btnWebcam"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginHorizontal="5sp"
            android:text="Toggle Webcam"
            android:textAllCaps="false" /&gt;

        &lt;Button
            android:id="@+id/btnMic"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Toggle Mic"
            android:textAllCaps="false" /&gt;

    &lt;/LinearLayout&gt;

&lt;/LinearLayout&gt;</code></pre><p>Now, let's set a listener for buttons allowing the participant to toggle media.</p>
<pre><code class="language-js">class SpeakerFragment : Fragment() {
  private var micEnabled = true
  private var webcamEnabled = true
  private var hlsEnabled = false
  private var btnMic: Button? = null
  private var btnWebcam: Button? = null
  private var btnHls: Button? = null
  private var btnLeave: Button? = null
  private var tvMeetingId: TextView? = null
  private var tvHlsState: TextView? = null
  override fun onAttach(context: Context) {
    super.onAttach(context)
    mContext = context
    if (context is Activity) {
      mActivity = context
      // getting meeting object from Meeting Activity
      meeting = (mActivity as MeetingActivity?)!!.meeting
    }
  }

  override fun onCreateView(
      inflater: LayoutInflater, container: ViewGroup?,
      savedInstanceState: Bundle?
  ): View? {
    // Inflate the layout for this fragment
    val view = inflater.inflate(R.layout.fragment_speaker, container, false)
    btnMic = view.findViewById(R.id.btnMic)
    btnWebcam = view.findViewById(R.id.btnWebcam)
    btnHls = view.findViewById(R.id.btnHLS)
    btnLeave = view.findViewById(R.id.btnLeave)
    tvMeetingId = view.findViewById(R.id.tvMeetingId)
    tvHlsState = view.findViewById(R.id.tvHlsState)
    if (meeting != null) {
      tvMeetingId!!.text = "Meeting Id : " + meeting!!.meetingId
      setActionListeners()
    }
    return view
  }

  private fun setActionListeners() {}

  companion object {
    private var mActivity: Activity? = null
    private var mContext: Context? = null
    private var meeting: Meeting? = null
  }
}</code></pre><pre><code class="language-js">private fun setActionListeners() {
    btnMic!!.setOnClickListener {
      if (micEnabled) {
        meeting!!.muteMic()
        Toast.makeText(mContext, "Mic Muted", Toast.LENGTH_SHORT).show()
      } else {
        meeting!!.unmuteMic()
        Toast.makeText(
            mContext,
            "Mic Enabled",
            Toast.LENGTH_SHORT
        ).show()
      }
      micEnabled = !micEnabled
    }
    btnWebcam!!.setOnClickListener {
      if (webcamEnabled) {
        meeting!!.disableWebcam()
        Toast.makeText(
            mContext,
            "Webcam Disabled",
            Toast.LENGTH_SHORT
        ).show()
      } else {
        meeting!!.enableWebcam()
        Toast.makeText(
            mContext,
            "Webcam Enabled",
            Toast.LENGTH_SHORT
        ).show()
      }
      webcamEnabled = !webcamEnabled
    }
    btnLeave!!.setOnClickListener { meeting!!.leave() }
    btnHls!!.setOnClickListener {
      if (!hlsEnabled) {
        val config = JSONObject()
        val layout = JSONObject()
        JsonUtils.jsonPut(layout, "type", "SPOTLIGHT")
        JsonUtils.jsonPut(layout, "priority", "PIN")
        JsonUtils.jsonPut(layout, "gridSize", 4)
        JsonUtils.jsonPut(config, "layout", layout)
        JsonUtils.jsonPut(config, "orientation", "portrait")
        JsonUtils.jsonPut(config, "theme", "DARK")
        JsonUtils.jsonPut(config, "quality", "high")
        meeting!!.startHls(config)
      } else {
        meeting!!.stopHls()
      }
    }
  }</code></pre><p>After adding listeners for buttons, let's add <code>MeetingEventListener</code> to the meeting and remove all listeners in <code>onDestroy()</code> method.</p>
<pre><code class="language-js">class SpeakerFragment : Fragment() {

  override fun onCreateView(
      inflater: LayoutInflater, container: ViewGroup?,
      savedInstanceState: Bundle?
  ): View? {
    //...
    if (meeting != null) {
      //...
      // add Listener to the meeting
      meeting!!.addEventListener(meetingEventListener)
    }
    return view
  }

  private val meetingEventListener: MeetingEventListener = object : MeetingEventListener() {
      override fun onMeetingLeft() {
        // unpin the local participant
        meeting!!.localParticipant.unpin("SHARE_AND_CAM")
        if (isAdded) {
          val intents = Intent(mContext, JoinActivity::class.java)
          intents.addFlags(
              Intent.FLAG_ACTIVITY_NEW_TASK
                      or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK
          )
          startActivity(intents)
          mActivity!!.finish()
        }
      }

      @RequiresApi(api = Build.VERSION_CODES.P)
      override fun onHlsStateChanged(HlsState: JSONObject) {
        if (HlsState.has("status")) {
          try {
              tvHlsState!!.text = "Current HLS State : " + HlsState.getString("status")
              if (HlsState.getString("status") == "HLS_STARTED") {
                hlsEnabled = true
                btnHls!!.text = "Stop HLS"
              }
              if (HlsState.getString("status") == "HLS_STOPPED") {
                hlsEnabled = false
                btnHls!!.text = "Start HLS"
              }
            } catch (e: JSONException) {
                e.printStackTrace()
            }
        }
      }
  }

  override fun onDestroy() {
      mContext = null
      mActivity = null
      if (meeting != null) {
          meeting!!.removeAllListeners()
          meeting = null
      }
      super.onDestroy()
  }
}</code></pre><p>The next step is to render the speaker's view. With <code>RecyclerView</code>, we will display a list of participants who joined the meeting as a <code>host</code>.</p>
<p>Create a new layout for the participant view named <code>item_remote_peer.xml</code> in the <code>res/layout</code> folder.</p>
<pre><code class="language-js">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:background="@color/cardview_dark_background"
    tools:layout_height="200dp"&gt;

    &lt;live.videosdk.rtc.android.VideoView
        android:id="@+id/participantView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" /&gt;

    &lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:background="#99000000"
        android:orientation="horizontal"&gt;

        &lt;TextView
            android:id="@+id/tvName"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:padding="4dp"
            android:textColor="@color/white" /&gt;

    &lt;/LinearLayout&gt;

&lt;/FrameLayout&gt;</code></pre><p>Create a recycler view adapter named <code>SpeakerAdapter</code> which will show the participant list. Create <code>PeerViewHolder</code> the adapter that will extend <code>RecyclerView.ViewHolder</code>.</p>
<pre><code class="language-js">class SpeakerAdapter(private val meeting: Meeting) :
    RecyclerView.Adapter&lt;SpeakerAdapter.PeerViewHolder?&gt;() {
    private var participantList: MutableList&lt;Participant&gt; = ArrayList()

    init {
      updateParticipantList()
      // adding Meeting Event listener to get the participant join/leave event in the meeting.
      meeting.addEventListener(object : MeetingEventListener() {
        override fun onParticipantJoined(participant: Participant) {
          // check participant join as Host/Speaker or not
          if (participant.mode == "CONFERENCE") {
              // pin the participant
              participant.pin("SHARE_AND_CAM")
              // add participant in participantList
              participantList.add(participant)
          }
          notifyDataSetChanged()
        }

        override fun onParticipantLeft(participant: Participant) {
          var pos = -1
          for (i in participantList.indices) {
              if (participantList[i].id == participant.id) {
                  pos = i
                  break
              }
          }
          if (participantList.contains(participant)) {
              // unpin participant who left the meeting
              participant.unpin("SHARE_AND_CAM")
              // remove participant from participantList
              participantList.remove(participant)
          }
          if (pos &gt;= 0) {
              notifyItemRemoved(pos)
          }
        }
      })
    }

    private fun updateParticipantList() {
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PeerViewHolder {
    }

    override fun onBindViewHolder(holder: PeerViewHolder, position: Int) {
    }

    override fun getItemCount(): Int {
    }

    class PeerViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    }
}</code></pre><pre><code class="language-js">private fun updateParticipantList() {
      // adding the local participant(You) to the list
      participantList.add(meeting.localParticipant)

      // adding participants who join as Host/Speaker
      val participants: Iterator&lt;Participant&gt; = meeting.participants.values.iterator()
      for (i in 0 until meeting.participants.size) {
        val participant = participants.next()
        if (participant.mode == "CONFERENCE") {
            // pin the participant
            participant.pin("SHARE_AND_CAM")
            // add participant in participantList
            participantList.add(participant)
        }
      }
    }</code></pre><pre><code class="language-js">override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PeerViewHolder {
      return PeerViewHolder(
          LayoutInflater.from(parent.context).inflate(R.layout.item_remote_peer, parent, false)
      )
    }

    override fun onBindViewHolder(holder: PeerViewHolder, position: Int) {
      val participant = participantList[position]
      holder.tvName.text = participant.displayName

      // adding the initial video stream for the participant into the 'VideoView'
      for ((_, stream) in participant.streams) {
        if (stream.kind.equals("video", ignoreCase = true)) {
          holder.participantView.visibility = View.VISIBLE
          val videoTrack = stream.track as VideoTrack
          holder.participantView.addTrack(videoTrack)
          break
        }
      }

      // add Listener to the participant which will update start or stop the video stream of that participant
      participant.addEventListener(object : ParticipantEventListener() {
        override fun onStreamEnabled(stream: Stream) {
          if (stream.kind.equals("video", ignoreCase = true)) {
            holder.participantView.visibility = View.VISIBLE
            val videoTrack = stream.track as VideoTrack
            holder.participantView.addTrack(videoTrack)
          }
        }

        override fun onStreamDisabled(stream: Stream) {
          if (stream.kind.equals("video", ignoreCase = true)) {
            holder.participantView.removeTrack()
            holder.participantView.visibility = View.GONE
          }
        }
      })
    }

    override fun getItemCount(): Int {
      return participantList.size
    }

    class PeerViewHolder(view: View) : RecyclerView.ViewHolder(view) {
      // 'VideoView' to show Video Stream
      var participantView: VideoView
      var tvName: TextView

      init {
        tvName = view.findViewById(R.id.tvName)
        participantView = view.findViewById(R.id.participantView)
      }
    }
</code></pre><p>Add this adapter to the <code>SpeakerFragment</code></p>
<pre><code class="language-js">override fun onCreateView(
      inflater: LayoutInflater, container: ViewGroup?,
      savedInstanceState: Bundle?
  ): View? {
    //...
    if (meeting != null) {
      //...
      val rvParticipants = view.findViewById&lt;RecyclerView&gt;(R.id.rvParticipants)
      rvParticipants.layoutManager = GridLayoutManager(mContext, 2)
      rvParticipants.adapter = SpeakerAdapter(meeting!!)
  }
}</code></pre><h3 id="step-4-implement-viewerview">Step 4: Implement ViewerView</h3><p>When the host starts the live streaming, the viewer will be able to see the live streaming.<br>
To implement player view, we are going to use <code>ExoPlayer</code>. It will be helpful to play HLS stream.<br>
Let's first add the dependency to the project.</br></br></p>
<pre><code class="language-js">dependencies {
  implementation 'com.google.android.exoplayer:exoplayer:2.18.5'
  // other app dependencies
}</code></pre><p>Now, we create a new Fragment named <code>ViewerFragment</code>.</p><h4 id="creating-the-ui-for-viewer-fragment">Creating the UI for Viewer Fragment</h4>
<p>The Viewer Fragment will include :</p><ul><li><strong>TextView for Meeting Id</strong> - The meeting ID that you have joined with, will be displayed in this text view.</li><li><strong>Leave Button</strong> - This button will leave the meeting.</li><li><strong>waitingLayout</strong> - This is the textView that will be shown when there is no active HLS.</li><li><strong>StyledPlayerView</strong> -  This is a media player that will display live streaming.</li></ul><p>In <code>/app/res/layout/fragment_viewer.xml</code> file, replace the content with the following.</p><pre><code class="language-js">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black"
    tools:context=".ViewerFragment"&gt;

    &lt;LinearLayout
        android:id="@+id/meetingLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingHorizontal="12sp"
        android:paddingVertical="5sp"&gt;

        &lt;TextView
            android:id="@+id/meetingId"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:text="Meeting Id : "
            android:textColor="@color/white"
            android:textSize="20sp" /&gt;

        &lt;Button
            android:id="@+id/btnLeave"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Leave" /&gt;

    &lt;/LinearLayout&gt;

    &lt;TextView
        android:id="@+id/waitingLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Waiting for host \n to start the live streaming"
        android:textColor="@color/white"
        android:textFontWeight="700"
        android:textSize="20sp"
        android:gravity="center"/&gt;

    &lt;com.google.android.exoplayer2.ui.StyledPlayerView
        android:id="@+id/player_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone"
        app:resize_mode="fixed_width"
        app:show_buffering="when_playing"
        app:show_subtitle_button="false"
        app:use_artwork="false"
        app:show_next_button="false"
        app:show_previous_button="false"
        app:use_controller="true"
        android:layout_below="@id/meetingLayout"/&gt;

&lt;/RelativeLayout&gt;</code></pre><h4 id="initialize-player-and-play-hls-stream">Initialize player and Play HLS stream</h4>
<p>Initialize the player and play the HLS when the meeting HLS state is HLS_PLAYABLE, and release it when the HLS state is HLS_STOPPED. Whenever the meeting HLS state changes, the event onHlsStateChanged will be triggered.</p>
<pre><code class="language-js">class ViewerFragment : Fragment() {
  private var meeting: Meeting? = null
  private var playerView: StyledPlayerView? = null
  private var waitingLayout: TextView? = null
  private var player: ExoPlayer? = null
  private var dataSourceFactory: DefaultHttpDataSource.Factory? = null
  private val startAutoPlay = true
  private var downStreamUrl: String? = ""

  override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
  ): View? {
    // Inflate the layout for this fragment
    val view = inflater.inflate(R.layout.fragment_viewer, container, false)
    playerView = view.findViewById(R.id.player_view)
    waitingLayout = view.findViewById(R.id.waitingLayout)
    if (meeting != null) {
        // set MeetingId to TextView
        (view.findViewById&lt;View&gt;(R.id.meetingId) as TextView).text =
            "Meeting Id : " + meeting!!.meetingId
        // leave the meeting on btnLeave click
        (view.findViewById&lt;View&gt;(R.id.btnLeave) as Button).setOnClickListener { meeting!!.leave() }
        // add listener to meeting
        meeting!!.addEventListener(meetingEventListener)
    }
    return view
  }

  override fun onAttach(context: Context) {
      super.onAttach(context)
      mContext = context
      if (context is Activity) {
        mActivity = context
        // get meeting object from MeetingActivity
        meeting = (mActivity as MeetingActivity?)!!.meeting
      }
  }

  private val meetingEventListener: MeetingEventListener = object : MeetingEventListener() {}

  override fun onDestroy() {
  }

  companion object {
    private var mActivity: Activity? = null
    private var mContext: Context? = null
  }
}</code></pre><pre><code class="language-js">private val meetingEventListener: MeetingEventListener = object : MeetingEventListener() {
      override fun onMeetingLeft() {
        if (isAdded) {
          val intents = Intent(mContext, JoinActivity::class.java)
          intents.addFlags(
              Intent.FLAG_ACTIVITY_NEW_TASK
                      or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_CLEAR_TASK
          )
          startActivity(intents)
          mActivity!!.finish()
        }
      }

      @RequiresApi(api = Build.VERSION_CODES.P)
      override fun onHlsStateChanged(HlsState: JSONObject) {
        if (HlsState.has("status")) {
            try {
              if (HlsState.getString("status") == "HLS_PLAYABLE" &amp;&amp; HlsState.has("downstreamUrl")) {
                downStreamUrl = HlsState.getString("downstreamUrl")
                waitingLayout!!.visibility = View.GONE
                playerView!!.visibility = View.VISIBLE
                // initialize player
                initializePlayer()
              }
              if (HlsState.getString("status") == "HLS_STOPPED") {
                // release the player
                releasePlayer()
                downStreamUrl = null
                waitingLayout!!.text = "Host has stopped \n the live streaming"
                waitingLayout!!.visibility = View.VISIBLE
                playerView!!.visibility = View.GONE
              }
            } catch (e: JSONException) {
                e.printStackTrace()
            }
          }
      }
  }
  
  private fun initializePlayer() {
  }
	
   private fun releasePlayer() {
   }</code></pre><pre><code class="language-js">private fun initializePlayer() {
    if (player == null) {
      dataSourceFactory = DefaultHttpDataSource.Factory()
      val mediaSource = HlsMediaSource.Factory(dataSourceFactory!!).createMediaSource(
          MediaItem.fromUri(Uri.parse(downStreamUrl))
      )
      val playerBuilder = ExoPlayer.Builder( /* context = */mContext!!)
      player = playerBuilder.build()
      // auto play when player is ready
      player!!.playWhenReady = startAutoPlay
      player!!.setMediaSource(mediaSource)
      // if you want display setting for player then remove this line
      playerView!!.findViewById&lt;View&gt;(com.google.android.exoplayer2.ui.R.id.exo_settings).visibility =
          View.GONE
      playerView!!.player = player
    }
    player!!.prepare()
  }
</code></pre><pre><code class="language-js"> private fun releasePlayer() {
    if (player != null) {
      player!!.release()
      player = null
      dataSourceFactory = null
      playerView!!.player = null
    }
  }

  override fun onDestroy() {
    mContext = null
    mActivity = null
    downStreamUrl = null
    releasePlayer()
    if (meeting != null) {
        meeting!!.removeAllListeners()
        meeting = null
    }
    super.onDestroy()
  }</code></pre><p>This is how the viewer will see their screen.</p>

<!--kg-card-begin: html-->
<iframe width="560" height="315" src="https://www.youtube.com/embed/NIqR32ajQBc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen=""/>
<!--kg-card-end: html-->
<h3 id="run-your-app">Run your App</h3><p><strong>Tadaa!!</strong> Our app is ready for live streaming. Easy, isn't it? <br>Install and run the app on two different devices and make sure both of them are connected to the internet. You should expect it to work as shown in the video below:</br></p><center> 
<p><img src="https://assets.videosdk.live/static-assets/ghost/2023/04/done-its-done.gif" alt="Build an Android Live Streaming Video Chat App Using Kotlin?" loading="lazy"><br>
</br></img></p></center><p/>
<h2 id="conclusion">Conclusion</h2><p>In this blog, we have learned what VideoSDK is and how to create your own Live Streaming Android App with the VideoSDK.</p><p>Go ahead and create advanced features like screen-sharing, Real-Time messaging, and others. Browse Our <a href="https://docs.videosdk.live/">Documentation</a>.</p><p>To see the full implementation of the app, check out <a href="https://github.com/videosdk-live/videosdk-rtc-android-java-sdk-example/tree/one-to-one-demo">This</a> GitHub repository.</p><p>If you face any problems or have questions, Feel free to join our <a href="https://discord.gg/Gpmj6eCq5u">Discord Community</a>.</p><p>To unlock the full potential of VideoSDK and create easy-to-use video experiences, developers are encouraged to sign up for VideoSDK and further explore its features. </p><p><a href="https://www.videosdk.live/signup"><strong>Sign up with VideoSDK</strong></a> today and Get <strong>10000 minutes free</strong> to take your video app to the next level!</p><h2 id="more-android-resources">More Android Resources</h2><ul><li><a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/concept-and-architecture">Build an Android Video Calling App - docs</a></li><li><a href="https://youtu.be/Kj7jS3dbJFA">Build an Android Video Calling App using Android Studio and Video SDK</a> - Youtube</li><li><a href="https://github.com/videosdk-live/quickstart/tree/main/android-rtc">quickstart/android-rtc</a></li><li><a href="https://github.com/videosdk-live/quickstart/tree/main/android-hls">quickstart/android-hls</a></li><li><a href="https://github.com/videosdk-live/videosdk-rtc-android-java-sdk-example">videosdk-rtc-android-java-sdk-example</a></li><li><a href="https://github.com/videosdk-live/videosdk-rtc-android-kotlin-sdk-example">videosdk-rtc-android-kotlin-sdk-example</a></li><li><a href="https://github.com/videosdk-live/videosdk-hls-android-java-example">videosdk-hls-android-java-example</a></li><li><a href="https://github.com/videosdk-live/videosdk-hls-android-kotlin-example">videosdk-hls-android-kotlin-example</a></li></ul>]]></content:encoded></item><item><title><![CDATA[How VideoSDK Overrides Codecs?]]></title><description><![CDATA[The article explores VideoSDK's features including codec selection, dynamic switching, custom configuration, fallback mechanisms, and low-latency optimizations.]]></description><link>https://www.videosdk.live/blog/how-video-sdk-overrides-codecs</link><guid isPermaLink="false">66d6d30d20fab018df10fe78</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Fri, 24 Jan 2025 12:19:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/09/How-VideoSDK-overrides-Codecs.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2024/09/How-VideoSDK-overrides-Codecs.jpg" alt="How VideoSDK Overrides Codecs?"/><p>VideoSDK offers the capability to dynamically override and manage codecs throughout video and audio sessions, allowing developers to adapt media streams based on specific needs like network conditions, device performance, or application requirements. Here’s how Video SDK typically handles codec overriding:</p><h2 id="codec-selection">Codec Selection</h2><p>The VideoSDK provides APIs to select the desired codec for encoding and decoding video streams. It includes support for widely used codecs such as H.264, H.265 (HEVC), VP9, and the newly emerging AV1 codec. Developers can choose the most appropriate codec by considering a variety of factors, including quality expectations, bitrate limitations, and compatibility with devices.</p><h2 id="dynamic-codec-switching">Dynamic Codec Switching</h2><p>VideoSDK enables dynamic switching of codecs during an ongoing session without interrupting the media stream. This is often handled internally by the SDK based on predefined conditions such as bandwidth changes, CPU usage, or packet loss.</p><p>The SDK monitors network conditions and automatically switches to a more suitable codec if the current one becomes inefficient. For example, it might switch from VP9 to VP8 or H.264 to reduce computational load or improve compatibility.</p><h2 id="custom-codec-configuration">Custom Codec Configuration</h2><p>The SDK provides detailed control over codec parameters via a configuration API. Developers can adjust settings like:</p><ul><li><strong>Bitrate</strong>: Controlling the target bitrate for encoding to optimize quality vs file size tradeoffs.</li><li><strong>Resolution</strong>: Specifying the desired resolution for encoding or decoding.</li><li><strong>Frame rate</strong>: Setting the frame rate for smooth playback.</li><li><strong>Encoding presets</strong>: Choosing presets optimized for different use cases like low-latency streaming or high-quality offline encoding.</li></ul><p>This level of flexibility enables developers to customize default codec settings to their specific needs and enhance performance.</p><h2 id="fallback-mechanisms">Fallback Mechanisms</h2><p>VideoSDK includes fallback mechanisms where, if a preferred codec fails (due to unsupported devices or insufficient resources), it automatically falls back to the next best available codec. This ensures that the session continues smoothly even under suboptimal conditions.</p><h2 id="codec-prioritization-and-negotiation">Codec Prioritization and Negotiation</h2><p>During session setup, VideoSDK negotiates codec capabilities between participants, prioritizing preferred codecs. If a codec mismatch occurs, the SDK adapts by choosing a mutually supported codec, ensuring compatibility.</p><p>Developers can influence this process by specifying codec priorities or excluding certain codecs from the negotiation process.</p><h2 id="support-for-low-latency-codecs">Support for Low-Latency Codecs</h2><p>For applications requiring low-latency communication, VideoSDK supports codecs optimized for minimal delay, such as VP8 or OPUS, and can override higher-latency codecs when real-time interaction is critical.</p><h2 id="api-access-for-codec-control">API Access for Codec Control</h2><p>VideoSDK provides APIs that give developers direct access to codec control, allowing them to implement custom codec-switching logic. For instance, you can create event listeners that trigger codec changes based on real-time network analytics or user-defined conditions.</p>]]></content:encoded></item><item><title><![CDATA[Why Video PD and Relationship Management are Important in Banking?]]></title><description><![CDATA[This article explores how these innovations are revolutionizing customer interactions, streamlining operations, and providing banks with a competitive edge. ]]></description><link>https://www.videosdk.live/blog/videopd-and-relationship-management</link><guid isPermaLink="false">66d8296220fab018df10ff81</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Thu, 23 Jan 2025 12:19:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-Video-PD-and-RM_-Why-are-They-Important-in-Banking_.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-Video-PD-and-RM_-Why-are-They-Important-in-Banking_.jpg" alt="Why Video PD and Relationship Management are Important in Banking?"/><p>In an era where technology is reshaping every aspect of our lives, the banking sector is no exception. As financial institutions aim to enhance customer experiences and streamline operations, two innovative concepts have emerged as game-changers: <a href="https://www.videosdk.live/blog/video-personal-discussion-vpd">Video Personal Discussion (Video PD)</a> and Relationship Management (RM).</p><p>Video PD leverages <a href="https://www.videosdk.live/">video technology</a> to facilitate real-time, personalized interactions between banks and their customers, making processes like onboarding and verification more efficient and engaging. On the other hand, RM surrounds the strategies and tools that banks use to manage and nurture customer relationships, focusing on personalization and data-driven insights.</p><p>Together, Video PD and RM are revolutionizing the way banks operate, allowing them to meet the evolving needs of customers while maintaining a competitive edge in a rapidly changing landscape.</p><p>In this article, we will explore what Video PD and RM are, how they function, and their significance in the banking industry. By understanding these concepts, banks can harness their potential to drive customer satisfaction and operational efficiency.</p><h2 id="understanding-video-pd">Understanding Video PD</h2><h3 id="definition-and-functionality">Definition and Functionality</h3><p><a href="https://www.videosdk.live/blog/video-personal-discussion-vpd">Video Personal Discussion (Video PD)</a> is a cutting-edge technology that facilitates real-time, face-to-face interactions between banks and their customers through secure video calls. This innovative approach allows financial institutions to conduct customer onboarding, verification, and support in a more personalized manner, enhancing the overall customer experience.</p><p>Video PD integrates various features such as <a href="https://www.videosdk.live/blog/what-is-liveness-detection">liveness detection</a>, document sharing, and identity verification, making it an effective tool for streamlining banking processes.</p><h3 id="comparison-with-traditional-customer-verification-methods"><strong>Comparison with Traditional Customer Verification Methods</strong></h3><p>Traditional customer verification methods often involve in-person meetings, extensive paperwork, and time-consuming processes that can lead to customer frustration and drop-offs. These methods are limited by geographical constraints and can be prone to errors and fraud. In contrast, Video PD eliminates the need for physical visits, allowing banks to connect with customers remotely, thereby accelerating the onboarding process and improving efficiency.</p><p><strong>Key Features of Video PD</strong></p><ol><li><strong>Real-Time Interaction</strong>: Video PD enables live discussions, fostering a personal connection that builds trust between banks and customers.</li><li><strong>Document Sharing</strong>: Customers can securely upload necessary documents during the call, simplifying the verification process.</li><li><strong>Identity Verification</strong>: Advanced technologies like facial recognition and <a href="https://aws.amazon.com/what-is/ocr/">Optical Character Recognition (OCR)</a> ensure accurate identity checks.</li><li><strong>Audit Trails</strong>: All interactions are recorded for compliance and auditing purposes, providing a reliable record of the verification process.</li><li><strong>Accessibility</strong>: Video PD breaks geographical barriers, allowing banks to serve a wider audience, including those in remote areas.</li></ol><p>These features collectively enhance the customer onboarding experience, making Video PD a vital tool for modern banking practices.</p><h2 id="understanding-relationship-management-rm"><strong>Understanding Relationship Management (RM)</strong></h2><h3 id="definition-and-scope-of-rm-in-banking"><strong>Definition and Scope of RM in Banking</strong></h3><p>Relationship Management (RM) in banking refers to the strategies and practices employed by financial institutions to foster and maintain strong relationships with their customers. It encompasses a wide range of activities, from personalized customer service and engagement to data-driven insights that help banks understand customer needs and preferences. By leveraging <a href="https://www.pragmaticcoders.com/blog/data-science-in-finance" rel="noreferrer">data science in finance</a>, banks can more precisely tailor their RM strategies, ultimately enhancing customer loyalty and satisfaction. RM aims to create long-term relationships that benefit both the bank and its clients, ultimately enhancing customer loyalty and satisfaction.</p><h3 id="importance-of-personalized-interactions-and-data-analytics"><strong>Importance of Personalized Interactions and Data Analytics</strong></h3><p>Personalized interactions are crucial in today’s competitive banking landscape. Customers expect tailored services that cater to their unique financial situations and goals. RM leverages data analytics to gather insights into customer behavior, preferences, and transaction history, enabling banks to deliver customized solutions and proactive support. This personalization not only enhances the customer experience but also increases retention rates.</p><h3 id="how-rm-integrates-with-technology-to-enhance-customer-service"><strong>How RM Integrates with Technology to Enhance Customer Service?</strong></h3><p>The integration of <a href="https://www.videosdk.live/">video technology</a> in RM has revolutionized customer service in banking. Advanced Customer Relationship Management <a href="https://www.saasadviser.co/software/crm-software" rel="noreferrer">CRM software</a> enables banks to track customer interactions, manage inquiries, and automate follow-ups efficiently.</p><p>Additionally, the use of Artificial Intelligence (AI) and machine learning allows for predictive analytics, helping banks anticipate customer needs and offer relevant products and services. By combining personalized service with technological advancements, RM enhances overall customer satisfaction and drives business growth.</p><h2 id="importance-of-video-pd-and-rm-in-banking"><strong>Importance of Video PD and RM in Banking</strong></h2><h3 id="enhanced-customer-experience"><strong>Enhanced Customer Experience</strong></h3><p>Video PD and Relationship Management (RM) significantly improve customer engagement and satisfaction by offering personalized interactions. <a href="https://www.videosdk.live/blog/video-personal-discussion-vpd">Video PD</a> allows customers to connect face-to-face with bank representatives, creating a more intimate and trustworthy environment.</p><p>This personal touch helps banks better understand customer needs and preferences, leading to tailored solutions that enhance the overall experience. Furthermore, RM utilizes data analytics to provide insights into customer behavior, enabling banks to proactively address issues and offer relevant services. Together, these technologies foster deeper relationships and increase customer loyalty.</p><h3 id="operational-efficiency"><strong>Operational Efficiency</strong></h3><p>The integration of Video PD and RM streamlines banking processes, reducing costs and improving turnaround times. Video PD eliminates the need for in-person meetings and lengthy paperwork, allowing for quicker onboarding and verification. This efficiency not only saves time for both customers and banks but also reduces operational costs associated with traditional methods.</p><p>RM systems enhance workflow by automating customer interactions and follow-ups, ensuring that no inquiries fall through the cracks. As a result, banks can operate more effectively while delivering faster service to their clients.</p><h3 id="fraud-prevention-and-security"><strong>Fraud Prevention and Security</strong></h3><p>Video PD enhances security through real-time verification and identity checks. By utilizing advanced technologies such as facial recognition and document verification during live video interactions, banks can ensure the authenticity of their customers. This robust identity verification process significantly reduces the risk of fraud compared to traditional methods, which can be susceptible to manipulation. Additionally, the ability to record video interactions provides an audit trail that enhances compliance with regulatory standards, further bolstering security measures.</p><h3 id="competitive-advantage"><strong>Competitive Advantage</strong></h3><p>Banks that leverage Video PD and RM can differentiate themselves in a crowded market. By offering innovative, personalized services, these institutions can attract and retain customers more effectively. The convenience of remote interactions through Video PD appeals to a tech-savvy customer base that values efficiency and flexibility. Moreover, banks that successfully implement these technologies can position themselves as leaders in customer service, enhancing their reputation and building a loyal clientele. In an increasingly digital world, adopting Video PD and RM is not just an option; it is essential for maintaining a competitive edge in the banking industry.</p><h2 id="practical-applications-and-case-studies"><strong>Practical Applications and Case Studies</strong></h2><h3 id="use-cases-of-video-pd"><strong>Use Cases of Video PD</strong></h3><p>Video Personal Discussion (Video PD) has a wide range of practical applications in banking, particularly in customer onboarding, <a href="https://www.videosdk.live/solutions/video-kyc">Know Your Customer (KYC)</a> processes, and remote support. For customer onboarding, Video PD allows banks to conduct virtual meetings where customers can present identification documents and complete necessary forms in real-time. This approach not only accelerates the onboarding process but also enhances the customer experience by providing a personal touch.</p><p>In KYC processes, Video PD enables banks to verify customer identities through live video interactions, ensuring compliance with regulatory requirements while minimizing the risk of fraud. Additionally, for remote support, banks can utilize Video PD to assist customers with complex inquiries, providing a face-to-face interaction that fosters trust and clarity.</p><h3 id="future-trends"><strong>Future Trends</strong></h3><p>Looking ahead, the future of Video PD and RM in banking is bright, with emerging technologies like Artificial Intelligence (AI) and machine learning set to play a pivotal role. These technologies can enhance Video PD by automating document verification and providing predictive analytics that help banks anticipate customer needs. </p><p>The integration of AI-driven chatbots with Video PD can further streamline customer interactions, making the banking experience more efficient and personalized. As these technologies evolve, banks that embrace them will be better positioned to meet the demands of a dynamic financial landscape.</p>]]></content:encoded></item><item><title><![CDATA[What is Server to Server (S2S) Communication?]]></title><description><![CDATA[Server-to-server (S2S) communication is the direct exchange of data between backend systems without any client device involved. Learn the protocols, security model, real-world use cases, and how VideoSDK's S2S API enables programmatic control of real-time video meetings.]]></description><link>https://www.videosdk.live/blog/server-to-server-s2s-communication</link><guid isPermaLink="false">66d6d6b520fab018df10fe98</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Thu, 23 Jan 2025 12:18:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-Server-to-Server-Communication_-1.png" medium="image"/><content:encoded><![CDATA[<blockquote>Server-to-server (S2S) communication is the direct exchange of data between two servers without any client device in between. It works by using protocols like REST APIs, gRPC, WebSocket, or message queues to pass requests and responses between backend systems. S2S is the backbone of microservices, real-time data pipelines, and scalable cloud architectures that handle millions of concurrent operations.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-Server-to-Server-Communication_-1.png" alt="What is Server to Server (S2S) Communication?"/><p>Most backend systems you interact with every day, from payment processors to video conferencing platforms, rely on dozens of server-to-server calls happening invisibly behind the scenes. When a payment triggers a fraud check, when a video call session gets created programmatically, or when a CRM syncs with a marketing tool, that is S2S communication at work.</p><p>This article covers what server-to-server communication is, how it works across different protocols, the real security and latency challenges teams face, and how VideoSDK uses S2S to give developers programmatic control over real-time audio and video sessions.</p><h2 id="what-is-server-to-server-s2s-communication">What Is Server-to-Server (S2S) Communication?</h2><p>Server-to-server (S2S) communication is defined as the direct exchange of data, requests, and responses between two or more server-side systems without any end-user client acting as an intermediary.</p><p>S2S works by having one server act as a requesting agent (the client in the exchange) and another act as the responder, using standardized protocols like HTTP/HTTPS, <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-vs-grpc-comparison#what-is-grpc" rel="noreferrer">gRPC</a>, <a href="https://www.videosdk.live/blog/what-is-a-websocket" rel="noreferrer">WebSocket</a>, or message queue systems to structure those exchanges. The key distinction from client-server communication is that no browser, mobile app, or user device participates in the request-response cycle.</p><p>A practical example: when a user clicks "Start Meeting" in a video app, the frontend sends one request to its own backend. That backend then makes a separate S2S call to a communication platform like VideoSDK to provision a meeting room, generate tokens, and configure participant permissions. The user sees a single action. Behind the scenes, multiple server-to-server requests fired in milliseconds.</p><p>S2S is foundational to microservices architecture, where applications are broken into small independent services that must talk to each other. It is also central to cloud-native systems, third-party API integrations, webhook delivery, and real-time event processing pipelines.</p><h2 id="importance-of-server-to-server-s2s-communication">Importance of Server to Server (S2S) Communication</h2><h3 id="seamless-operations">Seamless Operations</h3><p>Server to Server (S2S) is critical for maintaining seamless operations in environments with high data traffic. It ensures that multiple servers can work together efficiently to handle large volumes of requests simultaneously.</p><h3 id="real-time-data-handling">Real-time Data Handling</h3><p>Server to Server (S2S) enables real-time data processing and synchronization, which is essential for applications that require immediate updates, such as management systems and management (CRM) tools.</p><h3 id="enhanced-user-experience">Enhanced User Experience</h3><p>By ensuring that data is consistently updated across servers, Server to Server contributes to a better user experience. Users benefit from faster response times and more reliable services, which can lead to higher satisfaction and retention.</p><h3 id="scalability">Scalability</h3><p>Server to Server architecture supports the easy addition of more servers as demand increases. This scalability is vital for businesses experiencing growth, as it allows them to enhance their infrastructure without significant changes to the existing setup.</p><h2 id="key-aspects-of-server-to-server-s2s-communication">Key Aspects of Server to Server (S2S) Communication</h2><h3 id="direct-communication">Direct Communication</h3><p>S2S (Server-to-Server) allows servers to exchange data and requests directly, which minimizes latency and enhances performance. This is particularly useful in scenarios where rapid data exchange is crucial, such as real-time analytics.</p><h3 id="load-distribution">Load Distribution</h3><p>By enabling servers to communicate with one another,  Server to Server (S2S) helps distribute workloads evenly. This ensures that no single server becomes a bottleneck, thereby improving overall system reliability and efficiency.</p><h3 id="data-synchronization">Data Synchronization</h3><p>In a typical Server-to-Server setup, servers can synchronize data across different systems. For example, one server might handle user requests, while another processes transactions and a third manages user data. Server to Server (S2S) ensures that all these servers remain updated with the latest information, which is critical for maintaining consistency and accuracy in operations.</p><h3 id="protocols-and-technologies">Protocols and Technologies</h3><p>Various protocols facilitate Server to Server (S2S) communication using APIs (Application Programming Interfaces) or other standardized protocols like HTTP, HTTPS, WebSocket, gRPC, or even custom protocols. These protocols define how servers communicate, ensuring that data is exchanged in a structured and reliable manner.</p><h3 id="security-and-authentication">Security and Authentication</h3><p>Since no direct client is involved, security measures are critical. Common methods include <a href="https://www.videosdk.live/blog/api-key-vs-api-token" rel="noreferrer">API keys</a>, OAuth tokens, SSL/TLS for encrypted communication, and mutual authentication methods to ensure only authorized servers can communicate.</p><h2 id="protocols-and-methods">Protocols and Methods</h2><ul><li><strong>RESTful APIs</strong>: Using HTTP/HTTPS requests to GET, POST, PUT, and DELETE data.</li><li><strong>SOAP</strong>: A protocol for exchanging structured information in the implementation of web services.</li><li><strong>gRPC:</strong> A high-performance, open-source framework that uses HTTP/2 for transport, protocol buffers as the interface description language, and provides features like authentication, load balancing, and more.</li><li><strong>Message Queues</strong>: Systems like RabbitMQ, Kafka, or AWS SQS that enable asynchronous communication between servers.</li></ul><h2 id="challenges-in-server-to-server-communication">Challenges in Server-to-Server Communication</h2><p>While S2S (Server-to-Server) communication offers many advantages, it also presents challenges:</p><h3 id="network-latency">Network Latency</h3><p>The physical distance between servers can introduce latency, affecting the speed of data transfer. Optimizing network paths and using efficient data transfer protocols can mitigate this issue.</p><h3 id="security-concerns">Security Concerns</h3><p>As servers communicate directly, ensuring data security during transmission is crucial. Implementing encryption and secure protocols can help protect sensitive information from unauthorized access.</p><h3 id="complexity-in-management">Complexity in Management</h3><p>Managing multiple servers and ensuring they communicate effectively can be complex. Proper monitoring and management tools are necessary to maintain performance and reliability.</p><p>You can notice that Server to Server (S2S) communication is a foundational aspect of modern network architecture, enabling efficient data exchange, load balancing, and synchronization across multiple servers. Its importance is particularly evident in high-traffic environments where seamless operations and real-time data handling are critical for success.</p><h2 id="s2s-protocol-comparison-which-should-you-use">S2S Protocol Comparison: Which Should You Use?</h2><p>Choosing the wrong S2S protocol adds latency, complexity, or reliability risk to your backend. This table maps each protocol to its strengths and the right use case.</p><table>
<thead>
<tr>
<th>Protocol</th>
<th>Latency</th>
<th>Connection Type</th>
<th>Best For</th>
<th>Payload Format</th>
</tr>
</thead>
<tbody>
<tr>
<td>REST (HTTP/HTTPS)</td>
<td>Medium (10-100ms)</td>
<td>Stateless</td>
<td>Standard API calls, webhooks, session management</td>
<td>JSON / XML</td>
</tr>
<tr>
<td>gRPC</td>
<td>Low (1-10ms)</td>
<td>Persistent (HTTP/2)</td>
<td>High-frequency internal microservices, streaming</td>
<td>Protocol Buffers (binary)</td>
</tr>
<tr>
<td>WebSocket</td>
<td>Very Low (sub-5ms)</td>
<td>Persistent full-duplex</td>
<td>Real-time event push, live data streaming</td>
<td>Text / Binary</td>
</tr>
<tr>
<td>Message Queue (Kafka/RabbitMQ)</td>
<td>Variable (queue-dependent)</td>
<td>Asynchronous</td>
<td>Background jobs, guaranteed delivery, event sourcing</td>
<td>Any serialized format</td>
</tr>
<tr>
<td>SOAP</td>
<td>Medium-High</td>
<td>Stateless</td>
<td>Enterprise/legacy systems requiring formal contracts</td>
<td>XML</td>
</tr>
</tbody>
</table>
<h2 id="key-security-considerations-for-s2s-communication">Key Security Considerations for S2S Communication</h2><p>Server-to-server communication requires strict authentication and encryption because both endpoints are trusted infrastructure, and a breach in one server can compromise the other.</p><h3 id="authentication-methods">Authentication Methods</h3><p>The three most common S2S authentication approaches are:</p><ol><li><a href="https://videosdk.live/blog/api-key-vs-api-token#what-is-api-key" rel="noreferrer"><strong>API Keys</strong></a>&nbsp;— A shared secret included in request headers. Simple to implement but requires rotation policies and should never be logged or exposed in transit. VideoSDK's server-side SDK uses API keys scoped to project-level permissions.</li><li><strong>OAuth 2.0 Client Credentials Flow</strong>&nbsp;— The requesting server presents a client ID and secret to an authorization server, receives a short-lived JWT access token, and uses that token for subsequent S2S calls. This is the most secure approach for production systems because tokens expire automatically and carry scoped permissions.</li><li><strong>Mutual TLS (mTLS)</strong>&nbsp;— Both servers present valid X.509 certificates to each other, verifying identities at the transport layer. mTLS is the standard for zero-trust architectures and service meshes like Istio and Linkerd.</li></ol><h3 id="encryption-in-transit">Encryption in Transit</h3><p>All S2S communication should use TLS 1.2 or TLS 1.3 to encrypt data in transit. Sending sensitive data over plain HTTP between internal services is a common mistake that creates attack surfaces even inside private networks. VideoSDK enforces TLS across all S2S endpoints by default.</p><h3 id="rate-limiting-and-ip-allowlisting">Rate Limiting and IP Allowlisting</h3><p>Production S2S integrations should enforce rate limits on both sides to prevent accidental or malicious request floods from cascading through the system. IP allowlisting adds a network-level layer, ensuring that only known server IP ranges can initiate S2S calls.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-server-to-server-s2s-communication-1">What is server-to-server (S2S) communication?</h3><p>Server-to-server (S2S) communication is the direct exchange of data, requests, and responses between two server-side systems without any client device or browser participating in the transaction. S2S is the standard communication model for microservices architectures, third-party API integrations, cloud service coordination, and real-time backend event processing. It differs from client-server communication in that no end user initiates or mediates the request.</p><h3 id="what-protocols-are-used-for-s2s-communication">What protocols are used for S2S communication?</h3><p>The most common S2S protocols are REST over HTTPS for standard API calls, gRPC for high-performance binary communication between internal services, WebSocket for real-time full-duplex event streaming, and message queue systems like Apache Kafka and RabbitMQ for asynchronous, guaranteed-delivery communication. SOAP is still used in legacy enterprise environments. The right choice depends on your latency requirements, data volume, and whether the communication is synchronous or event-driven.</p><h3 id="how-is-s2s-communication-secured">How is S2S communication secured?</h3><p>S2S communication is secured through three layers: encryption (TLS 1.2 or 1.3 for all data in transit), authentication (API keys for simple cases, OAuth 2.0 client credentials for production systems, or mutual TLS for zero-trust architectures), and network controls (IP allowlisting and rate limiting to prevent unauthorized calls and traffic floods). Skipping any layer creates a vulnerability even inside private internal networks.</p><h3 id="what-is-the-difference-between-s2s-and-client-server-communication">What is the difference between S2S and client-server communication?</h3><p>The main difference between S2S and client-server communication is the initiating party. In client-server communication, a user-facing device (browser, mobile app) sends a request to a server. In S2S communication, one server sends requests directly to another server, with no user device involved. S2S calls are typically used for backend automation, data synchronization, and service coordination, while client-server calls handle direct user interactions.</p><h3 id="what-is-s2s-communication-used-for-in-real-time-video-applications">What is S2S communication used for in real-time video applications?</h3><p>In real-time video applications, S2S communication is used to programmatically manage the meeting lifecycle from the backend. This includes creating meeting rooms before participants join, generating secure participant tokens server-side, triggering cloud recordings based on application events, ejecting participants programmatically, and receiving real-time meeting state webhooks. VideoSDK's S2S API supports all of these use cases, giving backend teams full programmatic control without requiring client-side SDK involvement.</p><h3 id="what-are-the-biggest-challenges-in-s2s-communication">What are the biggest challenges in S2S communication?</h3><p>The biggest challenges in S2S communication are network latency between geographically distributed services, cascading failure risk when dependent services go down, difficulty tracing and debugging requests across multiple service hops, and maintaining data consistency when multiple servers hold overlapping data. Teams address these with circuit breaker patterns for resilience, distributed tracing tools like OpenTelemetry for observability, and geographic co-location of related services to reduce latency.</p><h3 id="can-s2s-communication-be-used-without-exposing-api-credentials-to-the-client">Can S2S communication be used without exposing API credentials to the client?</h3><p>Yes, S2S communication is specifically designed to keep credentials server-side and hidden from client devices. By handling token generation, session creation, and API authentication exclusively in your backend server, you ensure that sensitive API keys and secrets never travel to a user's browser or mobile app. VideoSDK's recommended integration pattern uses S2S token generation precisely for this reason, generating short-lived, permission-scoped tokens on the server before delivering them to the client for meeting access.</p>]]></content:encoded></item><item><title><![CDATA[Audio Calling API Pricing]]></title><description><![CDATA[Pricing with no surprises. Study the affordability and quality of several entities and make a choice! Experience well-defined audio calling.
]]></description><link>https://www.videosdk.live/audio-calling-api-pricing/</link><guid isPermaLink="false">6322de0b5ed4260c94d4fb6c</guid><category><![CDATA[Pricing]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 23 Jan 2025 11:38:00 GMT</pubDate><media:content url="http://assets.videosdk.live/static-assets/ghost/2021/09/audio-calling-Pricing-thumbnail.jpg" medium="image"/><content:encoded><![CDATA[<img src="http://assets.videosdk.live/static-assets/ghost/2021/09/audio-calling-Pricing-thumbnail.jpg" alt="Audio Calling API Pricing"/><p>Videosdk.live brings its pricing for audio communication. With the best-supported quality, we deliver audio at the most affordable pricing. This blog makes the reader understand that how our pricing policies always come out to be an effective deal.<br/></p><p><strong>The audio communication API pricing.</strong></p><p><strong>Get $20 free on signup!</strong><br/></p><p>Audio calling APIs play an important role in real-time communication. Being commonly used in big corporates and smaller entities, it deals with clients and customers efficiently. Although it is believed that video calling is an important aspect of communicating over the web, it is just incomplete without audio. <br/></p><blockquote>Before we begin with the audio communication pricing, we commit to deliver you the best quality experience to enlarge engagement. With our effective pricing, we add value features to our platform too. We aspire that each client makes a worthful experience. </blockquote><ul><li>There is no necessity to speak to sales support to get acknowledged with pricing. You can view pricing policies here</li></ul><h2 id="how-to-calculate-participant-minutes">How to calculate Participant Minutes?</h2><p>Participant Minutes are the total number of minutes spent by each participant in one meeting. Videosdk.live calculates Participant Minutes based on the number of participants present in a meeting. The computation is simple.</p><p><strong>Participant Minutes = Number of participants(N) x Minutes Consumed(M)</strong><br>The reference below will make you understand the calculation effortlessly.</br></p><figure class="kg-card kg-image-card kg-width-wide kg-card-hascaption"><img src="http://assets.videosdk.live/static-assets/ghost/2021/09/PArticipant--Minutes.jpg" class="kg-image" alt="Audio Calling API Pricing" loading="lazy" width="2000" height="477"><figcaption><span style="white-space: pre-wrap;">6 Participants x 20 Minutes = 120 Participant Minutes</span></figcaption></img></figure><h2 id="free-plan">Free Plan</h2><p>We have secured and kept $20 free on signup, which means, on signup you will get $20 for free for trying out the features. After consuming $20, you will have to add credit card to start the pay as you go pricing. A question may arise that how do these credits deduct with usage? It can be illustrated with some examples.<br/></p><p><strong>Example:</strong></p><p><strong><em>Audio Conferencing of 50 participants for 40 minutes</em></strong></p><ul><li>Total Minutes consumed - 50 Participants x 40 Minutes = 2,000 Participant Minutes  <strong>BUT, </strong>these minutes are free, there is no cost to be borne by you.</li><li><strong>On a very simple calculation, your free minutes will be Deducted by 2,000 Free Minutes.</strong></li><li><strong>Remaining Free Minutes = 10,000 - 2,000 = 8,000 Minutes</strong></li><li>Similarly, the participant minutes of your next meeting will be further deducted from the remaining free minutes.<br/></li></ul><p><strong><em>Get a bonus example</em></strong></p><blockquote>On an estimation, we calculated that, if 6 Participants show up their presence for 50 minutes in a meeting, regularly for 30 days, they can manage <strong>30 FREE audio meetings each month!! </strong></blockquote><h2 id="pro-plan">Pro Plan</h2><p>After consumption of the first 10,000 free minutes, you are charged with the paid plan. Keeping it user-friendly, we have designed manageable affordable pricing. These pro plans are recommended for companies to scale engagement and make profits.<br/></p><p>The calculation is simple;</p><p><strong>Pricing = Number of participants x Meeting minutes x Unit Price per minute</strong></p><p><strong>Videosdk.live Price per minute = $ 0.00060</strong><br/></p><p><strong>Example:</strong></p><p>In an audio calling meeting Total Participants (N)= 50, Total Minutes consumed (M)= 100. The Total Participant Minutes (PM)= 5000.</p><p><strong>On calculation: Total Price= N x M x Price per minute =  50 x 100x 0.0006 = $3</strong></p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://assets.videosdk.live/static-assets/ghost/2021/09/pro-plan-pricing.jpg" class="kg-image" alt="Audio Calling API Pricing" loading="lazy" width="1189" height="997"><figcaption><span style="white-space: pre-wrap;">50 Participants x 100 Minutes x 0.00060 = $3.00</span></figcaption></img></figure><h2 id="enterprise-plan"><strong>Enterprise Plan</strong></h2><p>An Enterprise Plan is a plan for companies dedicated to accounts management, support, and other technicalities. We bring this plan to promote mass engagement at affordable prices.</p><blockquote><a href="https://videosdk.live/contact">Contact Support</a> for the best pricing deals.</blockquote><p><strong>Other Audio calling API providers</strong></p><p>Several other API providers indulge in developing audio calling APIs keeping up with identical approaches. The only contrasting point between Videosdk.live and other providers is price. <br/></p><p>There is no elaborated calculation</p><p><strong>Pricing = Number of participants x Meeting minutes x Unit Price per minute</strong></p><blockquote>Other companies Price per minute = $ 0.00099</blockquote><p><strong>Calculation with the same example:</strong></p><p>In an audio calling meeting Total Participants (N)= 50, Total Minutes consumed (M)= 100. The Total Participant Minutes (PM)= 5000.</p><p><strong>On calculation: Total Price= N x M x Price per minute =  50 x 100x 0.00099 = $5 (approx)</strong><br/></p><h2 id="price-comparison%E2%80%9Cvideosdklive-vs-other-api-providers%E2%80%9D">Price Comparison- “videosdk.live vs. other API providers”</h2><figure class="kg-card kg-image-card kg-width-wide"><img src="http://assets.videosdk.live/static-assets/ghost/2021/09/pricing-table_audio-call--1-.jpg" class="kg-image" alt="Audio Calling API Pricing" loading="lazy" width="1567" height="717"/></figure><blockquote>Videosdk.live and other companies comply with alike features and there is no difference in quality at all. The approach is identical but the prices vary. You can always get in touch with us through our <a href="https://www.videosdk.live/contact">fastest support chain</a>. We welcome all your queries.</blockquote>]]></content:encoded></item><item><title><![CDATA[How to Build Live Streaming Video Call App in Java?]]></title><description><![CDATA[Discover how to build a scalable Android live streaming app in Java. Learn the architecture of mobile video streaming, how to handle network fluctuations, and follow a complete step-by-step tutorial using VideoSDK.]]></description><link>https://www.videosdk.live/blog/android-java-interactive-live-streaming</link><guid isPermaLink="false">649434178ecddeab7f1791db</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Wed, 22 Jan 2025 06:17:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/HTTP-Live-Streaming-Java-2.png" medium="image"/><content:encoded><![CDATA[<blockquote>Building a live streaming app in Android (Java) requires integrating a real-time media SDK to handle video encoding, signaling, and stream distribution. VideoSDK provides a complete infrastructure layer that bypasses the complexity of raw WebRTC implementation. This allows Android developers to launch interactive, low-latency broadcasts with minimal custom backend code.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/HTTP-Live-Streaming-Java-2.png" alt="How to Build Live Streaming Video Call App in Java?"/><p>Video streaming is no longer a niche feature reserved for massive social media giants. Pick the wrong streaming architecture, and you spend three weeks refactoring your entire media pipeline while users complain about dropped frames and excessive battery drain. Building custom WebRTC implementations on Android demands deep knowledge of C++ and complex state management. This guide covers how to bypass those hurdles. You will learn the core concepts of mobile video architecture and follow a step-by-step tutorial to build a complete Android live streaming app in Java using <a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a>.</p><h2 id="what-is-interactive-live-streaming-in-android">What Is Interactive Live Streaming in Android?</h2><p><a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">Interactive live streaming</a> in Android is defined as a real-time broadcast protocol that allows viewers to participate through video, audio, or text with sub-second latency. Instead of passively consuming pre-recorded media, users actively engage with the host and other participants. This shift from one-way broadcasting to multi-directional communication changes the technical requirements of the application entirely.</p><p>Interactive live streaming in Android works by capturing media from the device's camera and microphone, encoding it into network-friendly packets, and transmitting it over a <a href="https://www.videosdk.live/developer-hub/webtransport/low-latency" rel="noreferrer">low-latency</a> transport layer like <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a>. When developers implement this technology, they must manage a constant stream of high-bandwidth data without locking the main UI thread. Android devices span a massive range of hardware capabilities, from flagship phones with dedicated hardware encoders to budget devices that struggle with basic software rendering.</p><p>The streaming engine must dynamically adjust video resolution and bitrate based on both the device's thermal state and the current network conditions. According to a 2023 Ericsson Mobility Report, varying cellular network speeds account for the majority of mobile video buffering issues. Therefore, handling network fluctuations gracefully is just as critical as the video rendering itself.</p><h2 id="integrating-hls-with-videosdk-on-android">Integrating HLS with VideoSDK on Android</h2><p>Follow the steps to create the necessary environment to add HTTP live streaming in your Android live app. You can find the code sample for Quickstart <a href="https://www.videosdk.live/">here</a>.</p><h3 id="prerequisites">Prerequisites</h3><p>First of all, your development environment should meet the following requirements:</p><ul><li><a href="https://www.oracle.com/in/java/technologies/downloads/">Java Development Kit.</a></li><li><a href="https://developer.android.com/studio?gclid=Cj0KCQjw4s-kBhDqARIsAN-ipH1LHN3BHD8E8boP9bhHZMQKve-7beXh5xlozj9hspl3Oc1FmGduOd8aAlm7EALw_wcB&amp;gclsrc=aw.ds">Android Studio</a> 3.0 or later.</li><li>Android SDK API Level 21 or higher.</li><li>A mobile device that runs Android 5.0 or later.</li></ul><blockquote>You should use a VideoSDK account to generate tokens. Visit VideoSDK <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer">dashboard</a> to generate a token.</blockquote><h3 id="create-a-new-android-project">Create a new Android Project</h3><p>For a new project in Android Studio, create a Phone and Tablet Android project with an Empty activity.</p><p>Video SDK Android Quick Start New Project</p><blockquote><strong>CAUTION</strong>: After creating the project, Android Studio automatically starts gradle sync. Ensure that the sync succeeds before you continue.</blockquote><p>Add the repositories to the project's <code>settings.gradle</code> file.</p><pre><code class="language-groovy">dependencyResolutionManagement{
  repositories {
    // ...
    google()
    mavenCentral()
    maven { url 'https://jitpack.io' }
    maven { url "https://maven.aliyun.com/repository/jcenter" }
  }
}
</code></pre><p>Add the following dependency to your app's <code>app/build.gradle</code>.</p><pre><code class="language-groovy">dependencies {
  implementation 'live.videosdk:rtc-android-sdk:0.1.26'

  // library to perform Network call to generate a meeting id
  implementation 'com.amitshekhar.android:android-networking:1.0.2'

  // Other dependencies specific to your app
}
</code></pre><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">ℹ️</div><div class="kg-callout-text">Android SDK compatible with <code spellcheck="false" style="white-space: pre-wrap;">armeabi-v7a</code>, <code spellcheck="false" style="white-space: pre-wrap;">arm64-v8a</code>, <code spellcheck="false" style="white-space: pre-wrap;">x86_64</code> architectures. If you want to run the application in an emulator, choose ABI <code spellcheck="false" style="white-space: pre-wrap;">x86_64</code> when creating a device.</div></div><h3 id="add-permissions-to-your-project">Add permissions to your project</h3><p>In <code>/app/Manifests/AndroidManifest.xml</code>, add the following permissions after <code>&lt;/application&gt;</code>.</p><pre><code class="language-java">&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/&gt;
&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
&lt;uses-permission android:name="android.permission.CAMERA" /&gt;</code></pre><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">⚠️</div><div class="kg-callout-text">If your project has set <code spellcheck="false" style="white-space: pre-wrap;">android.useAndroidX = true</code>, then set <code spellcheck="false" style="white-space: pre-wrap;">android.enableJetifier = true</code> in the <code spellcheck="false" style="white-space: pre-wrap;">gradle.properties</code> file to migrate your project to AndroidX and avoid duplicate class conflicts.</div></div><h3 id="structure-of-the-project">Structure of the project</h3><p>Your project structure should look like this:</p><pre><code class="language-js">app
   ├── java
   │    ├── packagename
   │         ├── JoinActivity
   │         ├── MeetingActivity
   │         ├── SpeakerAdapter
   │         ├── SpeakerFragment
   |         ├── ViewerFragment
   ├── res
   │    ├── layout
   │    │    ├── activity_join.xml
   │    │    ├── activity_meeting.xml
   |    |    ├── fragment_speaker.xml
   |    |    ├── fragment_viewer.xml
   │    │    ├── item_remote_peer.xml
</code></pre>
<blockquote><strong>NOTE</strong>: You have to set <code>JoinActivity</code> as the Launcher activity.</blockquote><h3 id="app-architecture">App Architecture</h3>
<!--kg-card-begin: html-->
<center>

<img src="https://cdn.videosdk.live/website-resources/docs-resources/android_ils_quickstart_app_structure.png" alt="How to Build Live Streaming Video Call App in Java?"/>

</center>
<!--kg-card-end: html-->
<h2 id="build-an-android-live-video-streaming-app">Build an Android Live Video Streaming App</h2><h3 id="step-1-creating-joining-screen">Step 1: Creating Joining Screen</h3><p>Create a new Activity named <code>JoinActivity</code>.</p><h4 id="a-creating-ui">(a) Creating UI</h4>
<p>The joining screen includes:</p><ul><li><strong>Create Button</strong>: Creates a new meeting.</li><li><strong>TextField for Meeting ID</strong>: Contains the meeting ID you want to join.</li><li><strong>Join as Host Button</strong>: Joins the meeting as the host with the provided <code>meetingId</code>.</li><li><strong>Join as Viewer Button</strong>: Joins the meeting as a viewer with the provided <code>meetingId</code>.</li></ul><p>In the <code>/app/res/layout/activity_join.xml</code> file, replace the content with the following:</p><pre><code class="language-js">&lt;?xml version="1.0" encoding="utf-8"?&gt;

&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/createorjoinlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black"
    android:gravity="center"
    android:orientation="vertical"&gt;

    &lt;Button
        android:id="@+id/btnCreateMeeting"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Create Meeting"
        android:textAllCaps="false" /&gt;

    &lt;TextView
        android:id="@+id/tvText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingVertical="5sp"
        android:text="OR"
        android:textColor="@color/white"
        android:textSize="20sp" /&gt;

    &lt;EditText
        android:id="@+id/etMeetingId"
        android:theme="@android:style/Theme.Holo"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:hint="Enter Meeting Id"
        android:textColor="@color/white"
        android:textColorHint="@color/white" /&gt;

    &lt;Button
        android:id="@+id/btnJoinHostMeeting"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8sp"
        android:text="Join as Host"
        android:textAllCaps="false" /&gt;

    &lt;Button
        android:id="@+id/btnJoinViewerMeeting"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Join as Viewer"
        android:textAllCaps="false" /&gt;

&lt;/LinearLayout&gt;
</code></pre>
<h4 id="b-integration-of-create-meeting-api">(b) Integration of Create Meeting API</h4>
<p>Create field <code>sampleToken</code> in <code>JoinActivity</code> that will hold the generated token from the <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer">VideoSDK dashboard</a>. This token will be used in the VideoSDK config as well as in generating <code>meetingId</code>.</p><pre><code class="language-js">public class JoinActivity extends AppCompatActivity {

  //Replace with the token you generated from the VideoSDK Dashboard
  private String sampleToken ="";

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    //...
  }
}
</code></pre>
<p>On the <strong>Join Button as Host</strong> <code>onClick</code> events, we will navigate to <code>MeetingActivity</code> with token, <code>meetingId</code>and mode as <code>CONFERENCE</code>.</p><p>On the <strong>Join Button as Viewer</strong> <code>onClick</code> events, we will navigate to <code>MeetingActivity</code> with token, <code>meetingId</code>and mode as <code>Viewer</code>.</p><pre><code class="language-js">public class JoinActivity extends AppCompatActivity {

  //Replace with the token you generated from the VideoSDK Dashboard
  private String sampleToken ="";

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_join);

    final Button btnCreate = findViewById(R.id.btnCreateMeeting);
    final Button btnJoinHost = findViewById(R.id.btnJoinHostMeeting);
    final Button btnJoinViewer = findViewById(R.id.btnJoinViewerMeeting);
    final EditText etMeetingId = findViewById(R.id.etMeetingId);

    // create meeting and join as Host
    btnCreate.setOnClickListener(v -&gt; createMeeting(sampleToken));

    // Join as Host
    btnJoinHost.setOnClickListener(v -&gt; {
        Intent intent = new Intent(JoinActivity.this, MeetingActivity.class);
        intent.putExtra("token", sampleToken);
        intent.putExtra("meetingId", etMeetingId.getText().toString().trim());
        intent.putExtra("mode", "CONFERENCE");
        startActivity(intent);
    });

    // Join as Viewer
    btnJoinViewer.setOnClickListener(v -&gt; {
        Intent intent = new Intent(JoinActivity.this, MeetingActivity.class);
        intent.putExtra("token", sampleToken);
        intent.putExtra("meetingId", etMeetingId.getText().toString().trim());
        intent.putExtra("mode", "VIEWER");
        startActivity(intent);
    });
  }

  private void createMeeting(String token) {
    // we will explore this method in the next step
  }
}
</code></pre>
<p>For <strong>Create Button</strong> under <code>createMeeting</code> method, we will generate <code>meetingId</code>by calling API and navigating to <code>MeetingActivity</code> with the token, generated <code>meetingId</code>and mode as <code>CONFERENCE</code>.</p><pre><code class="language-js">public class JoinActivity extends AppCompatActivity {
  //...onCreate

  private void createMeeting(String token) {
    // we will make an API call to VideoSDK Server to get a roomId
    AndroidNetworking.post("https://api.videosdk.live/v2/rooms")
          .addHeaders("Authorization", token) //we will pass the token in the Headers
          .build()
          .getAsJSONObject(new JSONObjectRequestListener() {
              @Override
              public void onResponse(JSONObject response) {
                try {
                  // response will contain `roomId`
                  final String meetingId = response.getString("roomId");

                  // starting the MeetingActivity with received roomId and our sampleToken
                  Intent intent = new Intent(JoinActivity.this, MeetingActivity.class);
                  intent.putExtra("token", sampleToken);
                  intent.putExtra("meetingId", meetingId);
                  intent.putExtra("mode", "CONFERENCE");
                  startActivity(intent);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
              }

              @Override
              public void onError(ANError anError) {
                anError.printStackTrace();
                Toast.makeText(JoinActivity.this, anError.getMessage(), Toast.LENGTH_SHORT).show();
              }
          });
  }
}
</code></pre>
<div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">⚠️</div><div class="kg-callout-text">Don't get confused between Room and Meeting keywords, both are the same thing.</div></div><p>Our Android live app is completely based on audio and video communication, that's why we need to ask for runtime permissions <code>RECORD_AUDIO</code> and <code>CAMERA</code>. So, we will implement permission logic on <code>JoinActivity</code>.</p><pre><code class="language-js">public class JoinActivity extends AppCompatActivity {
  private static final int PERMISSION_REQ_ID = 22;

  private static final String[] REQUESTED_PERMISSIONS = {
    Manifest.permission.RECORD_AUDIO,
    Manifest.permission.CAMERA
  };

  private void checkSelfPermission(String permission, int requestCode) {
    if (ContextCompat.checkSelfPermission(this, permission) !=
            PackageManager.PERMISSION_GRANTED) {
      ActivityCompat.requestPermissions(this, REQUESTED_PERMISSIONS, requestCode);
    }
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    //... button listeneres
   checkSelfPermission(REQUESTED_PERMISSIONS[0], PERMISSION_REQ_ID);
   checkSelfPermission(REQUESTED_PERMISSIONS[1], PERMISSION_REQ_ID);
  }
}
</code></pre>
<h3 id="step-2-creating-meeting-screen">Step 2: Creating Meeting Screen</h3><p>Create a new Activity named <code>MeetingActivity</code>. In <code>/app/res/layout/activity_meeting.xml</code> file, replace the content with the following.</p><pre><code class="language-js">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black"
    tools:context=".MeetingActivity"&gt;

    &lt;TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="Creating a meeting for you"
        android:textColor="@color/white"
        android:textFontWeight="700"
        android:textSize="20sp" /&gt;

&lt;/RelativeLayout&gt;
</code></pre>
<h4 id="b-initializing-the-meeting">(b) Initializing the Meeting</h4>
<p>After getting the token, <code>meetingId</code>and mode from <code>JoinActivity</code>,</p><ol><li>Initialize <strong>VideoSDK</strong>.</li><li>Configure <strong>VideoSDK</strong> with the token.</li><li>Initialize the meeting with required params such as <code>meetingId</code>, <code>participantName</code>, <code>micEnabled</code>, <code>webcamEnabled</code>, <code>mode</code> and more.</li><li>Join the room with <code>meeting.join()</code> method.</li><li>Add <code>MeetingEventListener</code> for listening <strong>Meeting Join</strong> event.</li><li>Check mode of <code>localParticipant</code>, If the mode is <strong>CONFERENCE,</strong> We will replace <code>mainLayout</code> with <code>SpeakerFragment</code> otherwise, replace it with <code>ViewerFragment</code>.</li></ol><pre><code class="language-js">public class MeetingActivity extends AppCompatActivity {
  private Meeting meeting;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_meeting);

    final String meetingId = getIntent().getStringExtra("meetingId");
    String token = getIntent().getStringExtra("token");
    String mode = getIntent().getStringExtra("mode");
    String localParticipantName = "John Doe";
    boolean streamEnable = mode.equals("CONFERENCE");

    // initialize VideoSDK
    VideoSDK.initialize(getApplicationContext());

    // Configuration VideoSDK with Token
    VideoSDK.config(token);

    // Initialize VideoSDK Meeting
    meeting = VideoSDK.initMeeting(
            MeetingActivity.this, meetingId, participantName,
            micEnabled, webcamEnabled,null, null, false, null, null);

    // join Meeting
    meeting.join();

    // if mode is CONFERENCE than replace mainLayout with SpeakerFragment otherwise with ViewerFragment
    meeting.addEventListener(new MeetingEventListener() {
        @Override
        public void onMeetingJoined() {
          if (meeting != null) {
            if (mode.equals("CONFERENCE")) {
              //pin the local partcipant
              meeting.getLocalParticipant().pin("SHARE_AND_CAM");
              getSupportFragmentManager()
                  .beginTransaction()
                  .replace(R.id.mainLayout, new SpeakerFragment(), "MainFragment")
                  .commit();
            } else if (mode.equals("VIEWER")) {
              getSupportFragmentManager()
                  .beginTransaction()
                  .replace(R.id.mainLayout, new ViewerFragment(), "viewerFragment")
                  .commit();
            }
          }
        }
      });
  }
  public Meeting getMeeting() {
      return meeting;
  }
}
</code></pre>
<h3 id="step-3-implement-speakerview%E2%80%8B">Step 3: Implement <code>SpeakerView​</code></h3><p>After successfully entering the meeting, render the speaker's view and manage controls such as toggling the webcam/mic, start/stop HLS, and leaving the meeting.</p><p>Create a new fragment named <code>SpeakerFragment</code>. In <code>/app/res/layout/fragment_speaker.xml</code> file, replace the content with the following.</p><pre><code class="language-js">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".SpeakerFragment"&gt;

    &lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginVertical="8sp"
        android:paddingHorizontal="10sp"&gt;

        &lt;TextView
            android:id="@+id/tvMeetingId"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Meeting Id : "
            android:textColor="@color/white"
            android:textSize="18sp"
            android:layout_weight="3"/&gt;

        &lt;Button
            android:id="@+id/btnLeave"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:text="Leave"
            android:textAllCaps="false"
            android:layout_weight="1"/&gt;

    &lt;/LinearLayout&gt;

    &lt;TextView
        android:id="@+id/tvHlsState"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Current HLS State : NOT_STARTED"
        android:textColor="@color/white"
        android:textSize="18sp" /&gt;

    &lt;androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rvParticipants"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginVertical="10sp"
        android:layout_weight="1" /&gt;

    &lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"&gt;

        &lt;Button
            android:id="@+id/btnHLS"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Start HLS"
            android:textAllCaps="false" /&gt;

        &lt;Button
            android:id="@+id/btnWebcam"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginHorizontal="5sp"
            android:text="Toggle Webcam"
            android:textAllCaps="false" /&gt;

        &lt;Button
            android:id="@+id/btnMic"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Toggle Mic"
            android:textAllCaps="false" /&gt;

    &lt;/LinearLayout&gt;

&lt;/LinearLayout&gt;
</code></pre>
<p>Now, let's set the listener for buttons allowing the participant to toggle media.</p><pre><code class="language-js">public class SpeakerFragment extends Fragment {

  private static Activity mActivity;
  private static Context mContext;
  private static Meeting meeting;
  private boolean micEnabled = true;
  private boolean webcamEnabled = true;
  private boolean hlsEnabled = false;
  private Button btnMic, btnWebcam, btnHls, btnLeave;
  private TextView tvMeetingId, tvHlsState;

  public SpeakerFragment() {
    // Required empty public constructor
  }

  @Override
  public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    mContext = context;
    if (context instanceof Activity) {
      mActivity = (Activity) context;
      // getting meeting object from Meeting Activity
      meeting = ((MeetingActivity) mActivity).getMeeting();
    }
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                            Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_speaker, container, false);
    btnMic = view.findViewById(R.id.btnMic);
    btnWebcam = view.findViewById(R.id.btnWebcam);
    btnHls = view.findViewById(R.id.btnHLS);
    btnLeave = view.findViewById(R.id.btnLeave);

    tvMeetingId = view.findViewById(R.id.tvMeetingId);
    tvHlsState = view.findViewById(R.id.tvHlsState);

    if (meeting != null) {
        tvMeetingId.setText("Meeting Id : " + meeting.getMeetingId());
        setActionListeners();
    }
    return view;
  }

  private void setActionListeners() {
    btnMic.setOnClickListener(v -&gt; {
        if (micEnabled) {
          meeting.muteMic();
          Toast.makeText(mContext,"Mic Muted",Toast.LENGTH_SHORT).show();
        } else {
          meeting.unmuteMic();
          Toast.makeText(mContext,"Mic Enabled",Toast.LENGTH_SHORT).show();
        }
        micEnabled=!micEnabled;
    });

    btnWebcam.setOnClickListener(v -&gt; {
        if (webcamEnabled) {
          meeting.disableWebcam();
          Toast.makeText(mContext,"Webcam Disabled",Toast.LENGTH_SHORT).show();
        } else {
          meeting.enableWebcam();
          Toast.makeText(mContext,"Webcam Enabled",Toast.LENGTH_SHORT).show();
        }
        webcamEnabled=!webcamEnabled;
    });

    btnLeave.setOnClickListener(v -&gt; meeting.leave());

    btnHls.setOnClickListener(v -&gt; {
      if (!hlsEnabled) {
        JSONObject config = new JSONObject();
        JSONObject layout = new JSONObject();
        JsonUtils.jsonPut(layout, "type", "SPOTLIGHT");
        JsonUtils.jsonPut(layout, "priority", "PIN");
        JsonUtils.jsonPut(layout, "gridSize", 4);
        JsonUtils.jsonPut(config, "layout", layout);
        JsonUtils.jsonPut(config, "orientation", "portrait");
        JsonUtils.jsonPut(config, "theme", "DARK");
        JsonUtils.jsonPut(config, "quality", "high");
        meeting.startHls(config);
      } else {
        meeting.stopHls();
      }
    });
  }
}
</code></pre>
<p>After adding listeners for buttons, let's add <code>MeetingEventListener</code> to the meeting and remove all the listeners in <code>onDestroy()</code> method.</p><pre><code class="language-js">public class SpeakerFragment extends Fragment {

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                            Bundle savedInstanceState) {
    //...
    if (meeting != null) {
        //...
        // add Listener to the meeting
        meeting.addEventListener(meetingEventListener);
    }
    return view;
  }

  private final MeetingEventListener meetingEventListener = new MeetingEventListener() {
    @Override
    public void onMeetingLeft() {
      //unpin local participant
      meeting.getLocalParticipant().unpin("SHARE_AND_CAM");
      if (isAdded()) {
        Intent intents = new Intent(mContext, JoinActivity.class);
        intents.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        startActivity(intents);
        mActivity.finish();
      }
    }

    @RequiresApi(api = Build.VERSION_CODES.P)
    @Override
    public void onHlsStateChanged(JSONObject HlsState) {
        if (HlsState.has("status")) {
          try {
            tvHlsState.setText("Current HLS State : " + HlsState.getString("status"));
            if (HlsState.getString("status").equals("HLS_STARTED")) {
                hlsEnabled=true;
                btnHls.setText("Stop HLS");
            }
            if (HlsState.getString("status").equals("HLS_STOPPED")) {
                hlsEnabled = false;
                btnHls.setText("Start HLS");
            }
          } catch (JSONException e) {
              e.printStackTrace();
          }
        }
    }
  };

  @Override
  public void onDestroy() {
    mContext = null;
    mActivity = null;
    if (meeting != null) {
        meeting.removeAllListeners();
        meeting = null;
    }
    super.onDestroy();
  }

}
</code></pre>
<p>The next step is to render the speaker's view. With <code>RecyclerView</code>, we will display the list of participants who have joined the meeting as <code>host</code>.</p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">?</div><div class="kg-callout-text">- Here the participant's video is displayed using <code spellcheck="false" style="white-space: pre-wrap;">VideoView</code>, but you may also use <code spellcheck="false" style="white-space: pre-wrap;">SurfaceViewRender</code> for the same.- For <code spellcheck="false" style="white-space: pre-wrap;">VideoView</code>, SDK version should be <code spellcheck="false" style="white-space: pre-wrap;">0.1.13</code> or higher.- To know more about <code spellcheck="false" style="white-space: pre-wrap;">VideoView</code>, please visit <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/render-media/display-video/understand-videoView-component">here</a>.</div></div><p>Create a new layout for the participant view named <code>item_remote_peer.xml</code> in the <code>res/layout</code> folder.</p><pre><code class="language-js">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:background="@color/cardview_dark_background"
    tools:layout_height="200dp"&gt;

    &lt;live.videosdk.rtc.android.VideoView
        android:id="@+id/participantView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" /&gt;

    &lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:background="#99000000"
        android:orientation="horizontal"&gt;

        &lt;TextView
            android:id="@+id/tvName"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center"
            android:padding="4dp"
            android:textColor="@color/white" /&gt;

    &lt;/LinearLayout&gt;

&lt;/FrameLayout&gt;
</code></pre>
<p>Create a recycler view adapter  <code>SpeakerAdapter</code> that will show the participant list. Create <code>PeerViewHolder</code> in an adapter that will extend <code>RecyclerView.ViewHolder</code>.</p><pre><code class="language-js">public class SpeakerAdapter extends RecyclerView.Adapter&lt;SpeakerAdapter.PeerViewHolder&gt; {
  private List&lt;Participant&gt; participantList = new ArrayList&lt;&gt;();
  private final Meeting meeting;
  public SpeakerAdapter(Meeting meeting) {
    this.meeting = meeting;

    updateParticipantList();

    // adding Meeting Event listener to get the participant join/leave event in the meeting.
    meeting.addEventListener(new MeetingEventListener() {
      @Override
      public void onParticipantJoined(Participant participant) {
        // check participant join as Host/Speaker or not
        if (participant.getMode().equals("CONFERENCE")) {
          // pin the participant
          participant.pin("SHARE_AND_CAM");
          // add participant in participantList
          participantList.add(participant);
        }
        notifyDataSetChanged();
      }

      @Override
      public void onParticipantLeft(Participant participant) {
        int pos = -1;
        for (int i = 0; i &lt; participantList.size(); i++) {
          if (participantList.get(i).getId().equals(participant.getId())) {
            pos = i;
            break;
          }
        }
        if(participantList.contains(participant)) {
          // unpin participant who left the meeting
          participant.unpin("SHARE_AND_CAM");
          // remove participant from the list
          participantList.remove(participant);
        }
        if (pos &gt;= 0) {
            notifyItemRemoved(pos);
        }
      }
    });
  }

  private void updateParticipantList() {
    participantList = new ArrayList&lt;&gt;();

    // adding the local participant(You) to the list
    participantList.add(meeting.getLocalParticipant());

    // adding participants who join as Host/Speaker
    Iterator&lt;Participant&gt; participants = meeting.getParticipants().values().iterator();
    for (int i = 0; i &lt; meeting.getParticipants().size(); i++) {
      final Participant participant = participants.next();
      if (participant.getMode().equals("CONFERENCE")) {
        // pin the participant
        participant.pin("SHARE_AND_CAM");
        // add participant in participantList
        participantList.add(participant);
      }
    }
  }

  @NonNull
  @Override
  public PeerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    return new PeerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_remote_peer, parent, false));
  }

  @Override
  public void onBindViewHolder(@NonNull PeerViewHolder holder, int position) {
    Participant participant = participantList.get(position);

    holder.tvName.setText(participant.getDisplayName());

    // adding the initial video stream for the participant into the 'VideoView'
    for (Map.Entry&lt;String, Stream&gt; entry : participant.getStreams().entrySet()) {
      Stream stream = entry.getValue();
      if (stream.getKind().equalsIgnoreCase("video")) {
        holder.participantView.setVisibility(View.VISIBLE);
        VideoTrack videoTrack = (VideoTrack) stream.getTrack();
        holder.participantView.addTrack(videoTrack);
        break;
      }
    }

    // add Listener to the participant which will update start or stop the video stream of that participant
    participant.addEventListener(new ParticipantEventListener() {
        @Override
        public void onStreamEnabled(Stream stream) {
          if (stream.getKind().equalsIgnoreCase("video")) {
            holder.participantView.setVisibility(View.VISIBLE);
            VideoTrack videoTrack = (VideoTrack) stream.getTrack();
            holder.participantView.addTrack(videoTrack);
          }
        }

        @Override
        public void onStreamDisabled(Stream stream) {
          if (stream.getKind().equalsIgnoreCase("video")) {
            holder.participantView.removeTrack();
            holder.participantView.setVisibility(View.GONE);
          }
        }
    });
  }

  @Override
  public int getItemCount() {
    return participantList.size();
  }

  static class PeerViewHolder extends RecyclerView.ViewHolder {
    // 'VideoView' to show Video Stream
    public VideoView participantView;
    public TextView tvName;
    public View itemView;

    PeerViewHolder(@NonNull View view) {
        super(view);
        itemView = view;
        tvName = view.findViewById(R.id.tvName);
        participantView = view.findViewById(R.id.participantView);
    }
  }
}
</code></pre>
<p>Add this adapter to the <code>SpeakerFragment</code>.</p><pre><code class="language-js"> @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                            Bundle savedInstanceState) {
    //...
    if (meeting != null) {
      //...
      final RecyclerView rvParticipants = view.findViewById(R.id.rvParticipants);
      rvParticipants.setLayoutManager(new GridLayoutManager(mContext, 2));
      rvParticipants.setAdapter(new SpeakerAdapter(meeting));
    }
}
</code></pre>
<h3 id="step-4-implement-viewerview">Step 4: Implement ViewerView</h3><p>When the host starts live streaming, The viewer can see the live streaming.</p><p>To implement the player view, We're going to use <code>ExoPlayer</code>. It will be helpful to play the HLS stream.</p><p>But first, Let's add a dependency to the project.</p><pre><code class="language-js">dependencies {
  implementation 'com.google.android.exoplayer:exoplayer:2.18.5'
  // other app dependencies
  }
</code></pre>
<p>Create a new Fragment named <code>ViewerFragment</code></p><h4 id="a-creating-ui">(a) Creating UI</h4>
<p>The Viewer Fragment will include :</p><ol><li><strong>TextView for Meeting ID</strong> - The meeting ID that you joined will be displayed in this text view.</li><li><strong>Leave Button</strong> - This button will leave the meeting.</li><li><strong>waitingLayout</strong> - This textView will be shown when there is no active HLS.</li><li><strong>StyledPlayerView</strong> - This is a media player that will display live streaming.</li></ol><p>In <code>/app/res/layout/fragment_viewer.xml</code> file, replace the content with the following.</p><pre><code class="language-js">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/black"
    tools:context=".ViewerFragment"&gt;

    &lt;LinearLayout
        android:id="@+id/meetingLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingHorizontal="12sp"
        android:paddingVertical="5sp"&gt;

        &lt;TextView
            android:id="@+id/meetingId"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="3"
            android:text="Meeting Id : "
            android:textColor="@color/white"
            android:textSize="20sp" /&gt;

        &lt;Button
            android:id="@+id/btnLeave"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="Leave" /&gt;

    &lt;/LinearLayout&gt;

    &lt;TextView
        android:id="@+id/waitingLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Waiting for host \n to start the live streaming"
        android:textColor="@color/white"
        android:textFontWeight="700"
        android:textSize="20sp"
        android:gravity="center"/&gt;

    &lt;com.google.android.exoplayer2.ui.StyledPlayerView
        android:id="@+id/player_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone"
        app:resize_mode="fixed_width"
        app:show_buffering="when_playing"
        app:show_subtitle_button="false"
        app:use_artwork="false"
        app:show_next_button="false"
        app:show_previous_button="false"
        app:use_controller="true"
        android:layout_below="@id/meetingLayout"/&gt;

&lt;/RelativeLayout&gt;
</code></pre>
<h4 id="b-initialize-player-and-play-hls-stream">(b) Initialize player and Play HLS stream</h4>
<p>Initialize the player and play the HLS when the HLS state is <code>HLS_PLAYABLE</code>, and release it when the HLS state is <code>HLS_STOPPED</code>. Whenever the meeting HLS state changes, the event <code>onHlsStateChanged</code> will be triggered.</p><pre><code class="language-js">public class ViewerFragment extends Fragment {

  private Meeting meeting;
  protected StyledPlayerView playerView;
  private TextView waitingLayout;
  protected @Nullable
  ExoPlayer player;

  private DefaultHttpDataSource.Factory dataSourceFactory;
  private boolean startAutoPlay=true;
  private String downStreamUrl = "";
  private static Activity mActivity;
  private static Context mContext;

  public ViewerFragment() {
      // Required empty public constructor
  }

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
  }

  @Override
  public View onCreateView(LayoutInflater inflater, ViewGroup container,
                            Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view = inflater.inflate(R.layout.fragment_viewer, container, false);

    playerView = view.findViewById(R.id.player_view);

    waitingLayout = view.findViewById(R.id.waitingLayout);
    if(meeting != null) {
      // set MeetingId to TextView
      ((TextView) view.findViewById(R.id.meetingId)).setText("Meeting Id : " + meeting.getMeetingId());
      // leave the meeting on btnLeave click
      ((Button) view.findViewById(R.id.btnLeave)).setOnClickListener(v -&gt; meeting.leave());
      // add listener to meeting
      meeting.addEventListener(meetingEventListener);
    }
    return view;
  }


  @Override
  public void onAttach(@NonNull Context context) {
    super.onAttach(context);
    mContext = context;
    if (context instanceof Activity) {
      mActivity = (Activity) context;
      // get meeting object from MeetingActivity
      meeting = ((MeetingActivity) mActivity).getMeeting();
    }
  }

  private final MeetingEventListener meetingEventListener = new MeetingEventListener() {

      @Override
      public void onMeetingLeft() {
        if (isAdded()) {
          Intent intents = new Intent(mContext, JoinActivity.class);
          intents.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                  | Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_CLEAR_TASK);
          startActivity(intents);
          mActivity.finish();
        }
      }

      @RequiresApi(api = Build.VERSION_CODES.P)
      @Override
      public void onHlsStateChanged(JSONObject HlsState) {
        if (HlsState.has("status")) {
          try {
            if (HlsState.getString("status").equals("HLS_PLAYABLE") &amp;&amp; HlsState.has("downstreamUrl")) {
              downStreamUrl = HlsState.getString("downstreamUrl");
              waitingLayout.setVisibility(View.GONE);
              playerView.setVisibility(View.VISIBLE);
              // initialize player
              initializePlayer();
            }
            if (HlsState.getString("status").equals("HLS_STOPPED")) {
              // release the player
              releasePlayer();
              downStreamUrl = null;
              waitingLayout.setText("Host has stopped \n the live streaming");
              waitingLayout.setVisibility(View.VISIBLE);
              playerView.setVisibility(View.GONE);
            }
          } catch (JSONException e) {
              e.printStackTrace();
          }
        }
    }
  };

  protected void initializePlayer() {
    if (player == null) {
      dataSourceFactory = new DefaultHttpDataSource.Factory();
      HlsMediaSource mediaSource = new HlsMediaSource.Factory(dataSourceFactory).createMediaSource(
              MediaItem.fromUri(Uri.parse(this.downStreamUrl)));
      ExoPlayer.Builder playerBuilder =
              new ExoPlayer.Builder(/* context= */ mContext);
      player = playerBuilder.build();
      // auto play when player is ready
      player.setPlayWhenReady(startAutoPlay);
      player.setMediaSource(mediaSource);
      // if you want display setting for player then remove this line
      playerView.findViewById(com.google.android.exoplayer2.ui.R.id.exo_settings).setVisibility(View.GONE);
      playerView.setPlayer(player);
    }
    player.prepare();
  }

  protected void releasePlayer() {
    if (player != null) {
      player.release();
      player = null;
      dataSourceFactory = null;
      playerView.setPlayer(/* player= */ null);
    }
  }

  @Override
  public void onDestroy() {
    mContext = null;
    mActivity = null;
    downStreamUrl = null;
    releasePlayer();
    if (meeting != null) {
      meeting.removeAllListeners();
      meeting = null;
    }
    super.onDestroy();
  }

}
</code></pre>
<h2 id="final-output">Final Output</h2><p>Congratulations! Following this tutorial, you have successfully integrated HTTP live streaming capabilities into your Android app using <strong>VideoSDK</strong>. Let's recap what you have accomplished:</p><ul><li>Created a user-friendly joining screen allowing users to enter a meeting ID and join as a host or viewer.</li><li>Implemented the necessary logic to generate meeting IDs and handle different roles (host/viewer).</li><li>Developed a meeting screen where users can participate in HTTP live-streaming sessions, engage with the stream, chat with other participants, and have real-time discussions.</li></ul><p>To unlock the full potential of VideoSDK and create easy-to-use video experiences, developers are encouraged to sign up for VideoSDK and further explore its features. </p><p><a href="https://www.videosdk.live/signup"><strong>Sign up with VideoSDK</strong></a> today and Get <strong>10000 minutes free</strong> to take your Android video app to the next level!</p><h2 id="more-android-resources">More Android Resources</h2>
<ul><li><a href="https://www.videosdk.live/blog/1-on-1-video-chat">Android<em> </em>One-To-One Video Calling App with Java</a></li><li><a href="https://www.videosdk.live/blog/android-live-streaming">Android Live Streaming App using Kotlin</a></li><li><a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/concept-and-architecture">Build Android Video Calling App - docs</a></li><li><a href="https://youtu.be/Kj7jS3dbJFA">Build Android Video Calling App using Android Studio and VideoSDK</a></li><li><a href="https://github.com/videosdk-live/quickstart/tree/main/android-rtc">quickstart/android-rtc</a></li><li><a href="https://github.com/videosdk-live/quickstart/tree/main/android-hls">quickstart/android-hls</a></li><li><a href="https://github.com/videosdk-live/videosdk-rtc-android-java-sdk-example">videosdk-rtc-android-java-sdk-example</a></li><li><a href="https://github.com/videosdk-live/videosdk-rtc-android-kotlin-sdk-example">videosdk-rtc-android-kotlin-sdk-example</a></li><li><a href="https://github.com/videosdk-live/videosdk-hls-android-java-example">videosdk-hls-android-java-example</a></li><li><a href="https://github.com/videosdk-live/videosdk-hls-android-kotlin-example">videosdk-hls-android-kotlin-example</a></li></ul>]]></content:encoded></item><item><title><![CDATA[Build vs Buy VCIP Infrastructure: Complete Guide]]></title><description><![CDATA[This article compares building video KYC infrastructure to be costly and time-consuming and defines its limitations and why a buy ready-to-use InfraTech solution would be beneficial.]]></description><link>https://www.videosdk.live/blog/build-vs-buy-video-kyc-infrastructure</link><guid isPermaLink="false">651fee6e9eadee0b8b9eb4e2</guid><category><![CDATA[Video KYC]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Tue, 21 Jan 2025 11:31:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2023/10/Build-vs-Buy-Hero-img.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2023/10/Build-vs-Buy-Hero-img.jpg" alt="Build vs Buy VCIP Infrastructure: Complete Guide"/><p>The decision to build or buy a Video KYC (V-CIP) infrastructure is one of the most consequential technology choices a bank, NBFC, or fintech company makes. Get it wrong and you face regulatory penalties, customer drop-offs, or a fraud incident that bypasses your own system. Get it right and you shorten customer onboarding from days to minutes, reduce operational costs, and stay ahead of an evolving compliance landscape.</p><p>As per <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc">RBI regulations</a>, the video KYC verification process starts with collecting the customer’s consent to use their personal information for verification. To comply with these regulations, there are only two options available for any Financial Institution - building an in-house video KYC solution or buying a ready-to-use VCIP infrastructure. In this article, we try to give you an answer to that question and represent overall information about build vs buy video KYC infrastructure.</p><h2 id="understanding-vcip-infrastructure">Understanding VCIP Infrastructure</h2><p>VCIP Infrastructure is a framework that starts with onboarding a customer to complete the process with the <strong>end-to-end secure</strong> and reliable approach in a particular session. The purpose of this framework differs from user to user according to their scenario.</p><figure class="kg-card kg-image-card kg-width-wide"><img src="https://assets.videosdk.live/static-assets/ghost/2023/10/Build-vs-Buy-Architecture-1.jpg" class="kg-image" alt="Build vs Buy VCIP Infrastructure: Complete Guide" loading="lazy" width="2049" height="1149"/></figure><h2 id="what-is-needed-to-build-complete-vcip-kyc-solution">What is Needed to Build Complete VCIP KYC Solution?</h2><p>Building an in-house VCIP KYC Solution implicates diverse features and technologies to securely verify identities through video calls. To start, it is crucial to follow an effective implementation process.</p><h3 id="tech-stack"><strong>Tech Stack</strong></h3><p>To ensure compatibility with the desired tech stack, it is important to choose tools and technologies that seamlessly integrate with the chosen components. Leveraging the appropriate technology frameworks like <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start"><strong>JavaScript,</strong></a><strong> </strong><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/concept-and-architecture"><strong>React,</strong></a><strong> </strong><a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/concept-and-architecture"><strong>React Native,</strong></a><strong> </strong><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/concept-and-architecture"><strong>Flutter,</strong></a><strong> </strong><a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/concept-and-architecture"><strong>Android,</strong></a><strong> and </strong><a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/getting-started"><strong>iOS</strong></a> ensures compatibility with the tech stack.</p><h3 id="software-platform"><strong>Software Platform</strong></h3><p>To develop a web application for video KYC, use open-source platforms like JITSI, JANUS, or any similar private platforms. These platforms offer flexibility and customization options, but they come with certain limitations with scalability. But it is costly when you need custom features to enhance, also they may lack enterprise-grade security features required for identity verification and fraud prevention.</p><h3 id="team-of-executives"><strong>Team of Executives</strong></h3><p>To build video KYC Infrastructure, it is important to have a well-structured team in place. Team executives will play a crucial role in maintaining video KYC solutions and implementing and managing the infrastructure. They will be responsible for ensuring compliance with regulatory guidelines and integrating necessary features. </p><h2 id="the-challenge-of-building-video-kyc-infrastructure">The Challenge of Building Video KYC Infrastructure</h2><p>When choosing between building and buying Video KYC infrastructure, organizations must consider factors such as implementation process, tech stack compatibility, software platform features, team requirements, deployment options, compliance management, identity verification capabilities, security measures, scalability, data security, and customization options.</p><p>If the video KYC infrastructure is built using JITSI and JANUS's core features, they should add some more layers to be compatible. These must have extra layers that can provide <strong>enterprise-grade security</strong> features and additional capabilities.</p><h2 id="building-in-house-kyc-infra-vs-buy-video-kyc-infratech-solution">Building In-house KYC Infra v\s Buy  Video KYC InfraTech Solution</h2><table>
<thead>
<tr>
<th/>
<th>Requirements for Building KYC Infrastructure</th>
<th>Buy Ready-to-use InfraTech Framework</th>
</tr>
</thead>
<tbody>
<tr>
<td>Compliance Management</td>
<td>Organizations need to incorporate compliance management solutions to ensure regulatory compliance. (Not available in Open Source Platforms)</td>
<td>Provides built-in compliance management solutions to ensure regulatory compliance with RBI Guidelines for CERT-in and VAPT acceptance.</td>
</tr>
<tr>
<td>Complete On-Premises Deployment</td>
<td>Allows organizations to have complete control over data security by deploying the solution on their own servers. (Sometime lack when high demand)</td>
<td>Offers a solution hosted on the provider's servers, ensuring data security and protection.</td>
</tr>
<tr>
<td>Face Match Comparison</td>
<td>Requires integrating AI algorithms to compare customer's face with the photo on their government-issued ID for identity verification. Additional integration with third-party identity verification services may be needed.</td>
<td>Offers AI-powered face match comparison for identity verification, with integrated third-party identity verification services for enhanced authenticity.</td>
</tr>
<tr>
<td>Geo-Location Capture and IP Check</td>
<td>Requires capturing customer's location and performing IP checks to prevent fraud and unauthorized access.</td>
<td>Offers built-in geo-location capture and IP check features for fraud prevention.</td>
</tr>
<tr>
<td>End-to-End Encryption for Video</td>
<td>Requires implementing advanced encryption algorithms and protocols to secure data exchanged during video calls.</td>
<td>Provides end-to-end encryption for video calls to ensure data privacy and security.</td>
</tr>
<tr>
<td>Unlimited Video Storage and Instant Retrieval</td>
<td>Organizations need to provide unlimited video storage to meet compliance requirements.</td>
<td>Offers unlimited video storage and instant retrieval of video recordings for compliance purposes.</td>
</tr>
<tr>
<td>Battling Security Threats</td>
<td>Organizations need to implement robust security measures to detect and prevent security threats such as fake identity documents and pre-recorded videos.</td>
<td>Provides advanced security measures to battle security threats, ensuring protection against fraud and illegal activities.</td>
</tr>
<tr>
<td>Real-Time OVD Verification</td>
<td>Requires instant verification of government-issued identity documents for compliance.</td>
<td>Offers real-time verification of government-issued identity documents for regulatory compliance.</td>
</tr>
<tr>
<td>Cost Analysis</td>
<td>Consider the cost of hiring and retaining skilled personnel, development tools, infrastructure, and ongoing maintenance.</td>
<td>Evaluate the upfront purchase cost, licensing fees, and ongoing subscription or maintenance fees. Compare these costs over time.</td>
</tr>
<tr>
<td>Time-to-Market</td>
<td>Developing an in-house solution may take longer, especially if it requires research and development from scratch.</td>
<td>Purchasing an existing solution can significantly reduce time-to-market as the product is already developed and ready to use.</td>
</tr>
<tr>
<td>Customization Needs</td>
<td>If your organization requires a highly customized solution tailored to specific requirements, building in-house may be the better option.</td>
<td>Third-party solutions may have limitations in terms of customization. Evaluate if the available features meet your needs without extensive modification.</td>
</tr>
</tbody>
</table>
<h3 id="additional-core-regulatory-layers">Additional Core Regulatory Layers</h3>
<!--kg-card-begin: html-->
<table>
<thead>
<tr>
<th/>
<th>Build Framework</th>
<th>Buy Framework</th>
</tr>
</thead>
<tbody>
<tr>
<td>Flexibility</td>
<td>Depends on the organization's requirements and size, requiring high-end customization to support different customer journeys.</td>
<td>Offers high-end customization to accommodate diverse customer needs and ensure a smooth and personalized KYC experience.</td>
</tr>
<tr>
<td>Auto Scalability</td>
<td>Organizations need to ensure their infrastructure can scale up or down based on customer volume.</td>
<td>Provides auto scalability to handle sudden spikes in customer volume without performance issues or downtime.</td>
</tr>
<tr>
<td>Data Security</td>
<td>Requires implementing robust data encryption and security measures to protect customer data from unauthorized access or breaches.</td>
<td>Ensures data security by implementing robust encryption, firewall proxy support, and purging mechanisms to protect customer data.</td>
</tr>
</tbody>
</table>
<!--kg-card-end: html-->
<p>So, building a new infrastructure from scratch can be expensive, requiring substantial investments in technology, resources, and expertise. <strong>First Layer Solution</strong> <strong>providers</strong> solve this issue very efficiently. By using a ready-to-use infrastructure, organizations can avoid the need to build their own internal stack from scratch and instead leverage a pre-built </p><h2 id="benefits-of-buying-video-kyc-infratech-solution">Benefits of Buying Video KYC InfraTech Solution</h2><p>Requirements of BFSI organizations differ depending on their size and specific needs. For example, consumer fintech startups and small union banks may have different priorities than mid-sized or large banks for VCIP. It's crucial for organizations to carefully consider their unique needs and choose the right video KYC infrastructure.</p><p>One of the significant advantages of opting for <a href="https://www.videosdk.live/solutions/video-kyc">Video KYC InfraTech Solutions</a> is security and cost-effectiveness. This type of PaaS solution has all types of features. This not only streamlines the onboarding process but also reduces operational costs, minimizes fraud, and ensures compliance with regulatory guidelines. The first-layer solution provider offers customization options, scalability, and reliability, allowing organizations to efficiently onboard more customers.</p><p>This cost advantage allows organizations to allocate their resources more efficiently and focus on other critical areas of their business. Thus, a ready-to-use infrastructure provides not only the benefits mentioned above but also a cost-effective for organizations looking to implement video KYC solutions efficiently.</p><h2 id="which-should-be-good-for-financial-organizations">Which Should Be Good for Financial Organizations?</h2><p>The decision to build or buy video KYC infrastructure is crucial for organizations in the BFSI sector. Building an in-house infrastructure requires significant investments in technology, resources, and expertise. On the other hand, buying a ready-to-use solution offers cost-effectiveness, streamlined onboarding processes, reduced operational costs, and compliance with regulatory guidelines.</p><p>Both Options are good but buying a ready-to-use VCIP infrastructure from a Video solution expert offers several advantages. They obtain compliance with CERT-in and VAPT from the RBI. They affirm their commitment to maintaining the highest standards of security and regulatory compliance. </p><p>When it comes to choosing the best company to look out for, <a href="https://www.videosdk.live/">VideoSDK </a>stands out from the competition. Banks and fintech companies can benefit from a better identity verification SDK or solution by leveraging VideoSDK's pre-built infrastructure without the need to build their own internal stack from scratch. This not only saves time and resources but also ensures a streamlined onboarding process, reduced operational costs and minimized fraud.</p><p>With VideoSDK, organizations can trust in their customization options, scalability, and reliability, enabling them to efficiently onboard more customers while remaining compliant with regulatory guidelines. Choose <a href="https://www.videosdk.live/about-us">VideoSDK </a>for a comprehensive and reliable video KYC solution that puts security and compliance at the forefront.</p><p>You can <a href="https://www.videosdk.live/contact">talk with our team</a> if you have any questions regarding Video KYC compliances or Infrastructure.</p><p/>]]></content:encoded></item><item><title><![CDATA[What is Custom Delivery Protocol?]]></title><description><![CDATA[This article explores common use cases for CDP, key features, a step-by-step approach to implementation, and the advantages and challenges of developing custom protocols.]]></description><link>https://www.videosdk.live/blog/what-is-custom-delivery-protocol</link><guid isPermaLink="false">66d6d25720fab018df10fe6a</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Tue, 21 Jan 2025 10:49:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-Custom-Delivery-Protocol_.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-Custom-Delivery-Protocol_.jpg" alt="What is Custom Delivery Protocol?"/><p>Custom Delivery Protocol refers to a bespoke communication method designed to transmit data between client and server systems. Unlike standard protocols such as HTTP, <a href="https://www.videosdk.live/developer-hub/websocket/websocket-guide">WebSockets</a>, or <a href="https://www.videosdk.live/blog/what-is-rtp-protocol">RTP</a>, CDP is tailored to address specific needs that off-the-shelf protocols cannot efficiently handle. This customization allows for optimized performance, enhanced security, and improved reliability in data transmission.</p><h2 id="common-use-cases-for-custom-delivery-protocols">Common use cases for custom delivery protocols</h2><p>CDP finds application in various industries and situations where standard protocols fall short:</p><ul><li><strong>Video Conferencing and Streaming</strong>: Enhancing the quality of video and audio transmission beyond traditional protocols.</li><li><strong>Internet of Things (IoT)</strong>: Facilitating efficient data transmission between devices with limited resources.</li><li><strong>High-Frequency Trading</strong>: Shaving critical milliseconds off trade execution where speed is paramount.</li><li><strong>Online Gaming</strong>: Reduced lag and improved responsiveness in multiplayer environments.</li></ul><h2 id="key-features-of-custom-delivery-protocol">Key Features of Custom Delivery Protocol</h2><ol><li><strong>Optimized Data Flow</strong>: CDP ensures efficient data transmission by reducing latency, minimizing bandwidth usage, and increasing throughput based on specific application requirements.</li><li><strong>Advanced Security Measures</strong>: With CDP, developers can integrate custom security protocols, encryption standards, and authentication mechanisms to meet unique security needs.</li><li><strong>Robust Error Handling</strong>: CDP implements more advanced error detection, correction, and data recovery techniques than standard protocol capabilities.</li><li><strong>Low Latency Communication</strong>: Especially beneficial for real-time applications such as <a href="https://www.videosdk.live/audio-video-conferencing">video conferencing</a>, gaming, or live streaming where minimal latency is important.</li><li><strong>Customizable Quality of Service (QoS)</strong>: CDP allows for tailored QoS settings, ensuring reliable data delivery even under varying network conditions.</li><li><strong>Protocol Flexibility</strong>: The ability to modify and extend protocol rules as needed enables adaptation to new requirements without a complete system overhaul.</li></ol><h2 id="creating-a-custom-delivery-protocol-a-step-by-step-approach">Creating a Custom Delivery Protocol: A Step-by-Step Approach</h2><p>For those looking to implement CDP in their messaging system, here's a general process:</p><ol><li><strong>Define Protocol Attributes</strong>: Start by defining Protocol Attribute Definitions (DPADs) in your system's Enterprise Designer.</li><li><strong>Configure Messaging and Packaging Attributes</strong>: Set the protocol's Messaging Attribute Definitions (MADs) and Packaging Attribute Definitions (PADs).</li><li><strong>Create Delivery Actions</strong>: Establish delivery action groups and actions under Custom Protocols in Host Explorer.</li><li><strong>Fine-Tune Parameters</strong>: Modify parameter settings for delivery actions as needed to optimize performance.</li></ol><p>Once defined, custom protocols can be assigned to B2B hosts and used to efficiently deliver messages between trading partners.</p><h2 id="advantages-of-implementing-a-custom-delivery-protocol">Advantages of implementing a custom delivery protocol</h2><ol><li><strong>Performance Tuning</strong>: CDP outperforms standard alternatives by focusing on the specific data flow needs of each use case.</li><li><strong>Enhanced Security</strong>: Allows the implementation of advanced or industry-specific security measures.</li><li><strong>Customization</strong>: Provides flexibility to add or remove features as application needs evolve.</li></ol><h2 id="challenges-in-developing-custom-delivery-protocols">Challenges in developing custom delivery protocols</h2><p>Although the benefits are significant, implementing CDP comes with its own set of challenges:</p><ol><li><strong>Complexity</strong>: Developing custom protocols requires deep expertise in networking, data structures, and security.</li><li><strong>Continuous Maintenance</strong>: Regular support and updates are required, especially to address emerging security vulnerabilities.</li><li><strong>Interoperability issues</strong>: Custom protocols can face challenges when interacting with standard systems, often requiring additional gateways or adapters.</li></ol><p>As digital communication continues to evolve, the role of Custom Delivery Protocols is set to grow. With the increasing demand for real-time, secure, and efficient data transmission across various industries, CDP offers a flexible and powerful solution for specialized communication needs.</p><p>As we move towards an increasingly connected world, the ability to customize and control data transmission at this level will undoubtedly become a crucial competitive advantage. Businesses and developers can ensure that their data delivery is not only optimized and secure, but also tailored to meet the unique demands of their specific applications and industries. </p>]]></content:encoded></item><item><title><![CDATA[10 Best Amazon Chime SDK Alternatives for Developers in 2026]]></title><description><![CDATA[The top Amazon Chime SDK alternatives for 2026 ranked by SDK coverage, latency, pricing, and recording capability, with a developer-focused decision guide for migrating off Chime SDK.]]></description><link>https://www.videosdk.live/blog/amazon-chime-sdk-alternative</link><guid isPermaLink="false">64abba985badc3b21a58f657</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 21 Jan 2025 06:04:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2023/07/AWS-Chime-Alternative.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>The top Amazon Chime SDK alternatives in 2026 include VideoSDK, Twilio Video, Agora, Vonage, Jitsi, MirrorFly, SignalWire, EnableX, ApiRTC, and Whereby. VideoSDK is the top Amazon Chime SDK alternative for developer teams in 2026 because it provides unified SDKs for React, React Native, Flutter, iOS, and Android at predictable per-minute pricing, without assembling separate AWS services for recording, analytics, or media pipelines. Evaluate total cost, latency, recording needs, and migration effort before switching from Chime SDK.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2023/07/AWS-Chime-Alternative.jpg" alt="10 Best Amazon Chime SDK Alternatives for Developers in 2026"/><p>Amazon Chime SDK attracts teams already running on AWS infrastructure, but rising participant-minute bills, hidden media pipeline costs, and SDK integration friction on React Native and Flutter push engineering leads to explore Amazon Chime alternatives before the next product deadline. Picking the wrong platform costs months of migration work. This article evaluates ten Amazon Chime alternatives against the criteria that matter most in production: latency, SDK coverage, pricing predictability, and recording architecture.</p><h2 id="what-is-amazon-chime-sdk">What Is Amazon Chime SDK?</h2><p>Amazon Chime SDK is defined as AWS's real-time communication toolkit that lets developers embed audio calling, video calling, and messaging into applications using WebRTC-based infrastructure hosted on Amazon Web Services. Amazon Chime SDK works by routing media traffic through AWS media services, with developers combining the Chime SDK client library with separate AWS services (Amazon Kinesis Video Streams for recording, AWS Lambda for session management, Amazon S3 for storage) to build a complete communication stack.</p><p>Amazon Chime SDK is best known for deep AWS ecosystem integration, IAM-based access control, and HIPAA-eligible configuration for healthcare teams. Its limitations are equally well-documented: pricing complexity increases as teams add recording and composition, mobile SDK integration requires manual handling of disruptions, and interactive live streaming is not a native first-class feature.</p><p>Teams that run outside AWS or need multi-platform SDK coverage with predictable all-in pricing are the most likely to benefit from evaluating Amazon Chime SDK alternatives.</p><h2 id="how-we-evaluated-these-amazon-chime-alternatives">How We Evaluated These Amazon Chime Alternatives</h2><p>Every tool on this list was evaluated against five criteria that production engineering teams consistently cite when switching from Amazon Chime SDK.</p><ul><li><strong>Latency and protocol:</strong>&nbsp;Does the platform publish measured latency ranges for <a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu#what-is-sfu-selective-forwarding-unit" rel="noreferrer">WebRTC SFU</a>, MCU, or <a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer">HLS</a> delivery? Interactive use cases (telehealth, live tutoring, support calls) need sub-500ms mouth-to-ear delay. Broadcast webinars tolerate 15 to 30 seconds.</li><li><strong>SDK platform coverage:</strong>&nbsp;Does the SDK cover React, React Native, Flutter, iOS, Android, and web natively in a single product? Or does multi-platform coverage require assembling separate libraries?</li><li><strong>Pricing transparency:</strong>&nbsp;Is participant-minute pricing published without contacting sales? Are recording, transcoding, RTMP output, and storage charges listed explicitly?</li><li><strong>Recording architecture:</strong>&nbsp;Is server-side recording a first-class API or a separate assembly of media services?</li><li><strong>Migration effort:</strong>&nbsp;Does the platform provide documented migration guides, prebuilt UI components, or a REST API for room management that reduces porting time from Chime SDK?</li></ul><blockquote>
<h2 id="top-10-amazon-chime-alternatives-for-2026">Top 10 Amazon Chime Alternatives for 2026</h2>
<ul>
<li><strong>VideoSDK</strong></li>
<li><strong>Twilio Video</strong></li>
<li><strong>MirrorFly</strong></li>
<li><strong>Agora</strong></li>
<li><strong>Vonage</strong></li>
<li><strong>ApiRTC</strong></li>
<li><strong>Jitsi</strong></li>
<li><strong>SignalWire</strong></li>
<li><strong>Enablex</strong></li>
<li><strong>Whereby</strong></li>
</ul>
</blockquote>
<h2 id="1-videosdk-best-for-multi-platform-sdk-coverage-without-aws-lock-in">1. VideoSDK: Best for Multi-Platform SDK Coverage Without AWS Lock-In</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-SDK-for-Real-time-Communication-Live-Streaming-Video-API-4.jpeg" class="kg-image" alt="10 Best Amazon Chime SDK Alternatives for Developers in 2026" loading="lazy" width="1920" height="967"/></figure><p><a href="https://www.videosdk.live/" rel="noreferrer">VideoSDK</a> is a developer-first real-time communication platform providing <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">audio and video calling APIs</a>, <a href="https://www.videosdk.live/interactive-live-streaming" rel="noreferrer">interactive live streaming</a>, <a href="https://www.videosdk.live/voice-agents" rel="noreferrer">AI voice agents</a>, and telephony (SIP) in a single product with unified SDKs across React, React Native, Flutter, iOS, Android, Unity, and Python.</p><p><strong>Key features:</strong></p><ul><li>Unified SDK across 8 platforms with prebuilt UI components for React and React Native, reducing the integration surface compared to assembling Chime SDK with separate Lambda functions</li><li>Sub-80ms global latency for peer-to-peer audio calls on VideoSDK's distributed edge infrastructure</li><li>Interactive live streaming (sub-3-second latency) as a first-class API, not an add-on service</li><li>Server-side cloud recording, real-time transcription, and session analytics in one platform</li><li>AI Voice Agents framework (STT plus LLM plus TTS pipeline) for teams building voice AI on top of their calling infrastructure</li><li>SIP trunk integration with Twilio, Plivo, and other PSTN providers for connecting calls to traditional phone networks</li><li>Free tier with $20 credit, no credit card required, and no hard limits during exploration</li></ul><p><strong>Pricing:</strong> Video calls at $0.004 per participant-minute, audio calls at $0.001 per participant-minute, AI agent sessions at $0.01 per minute, cloud recording at $0.015 per minute. Enterprise plans include VPC deployment and a 99.99% uptime SLA with custom pricing. (Note: Verify Pricing at <a href="https://www.videosdk.live/pricing" rel="noreferrer">VideoSDK pricing page</a>.)</p><p><strong>Best for:</strong>&nbsp;Engineering teams migrating off Amazon Chime SDK who need multi-platform mobile SDK support, interactive live streaming, or AI voice features without managing multiple vendor accounts.</p><p><strong>Limitation:</strong>&nbsp;VideoSDK does not offer an on-premises deployment option outside enterprise VPC contracts. Teams requiring full self-hosted infrastructure should evaluate Jitsi instead.</p><p>Start building with VideoSDK's free tier ($20 credit, no credit card required):&nbsp;<a href="https://app.videosdk.live/signup" rel="noreferrer">Sign up now</a>.</p><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/amazon-chime-sdk-vs-videosdk"><strong>AWS Chime and VideoSDK</strong></a><strong>.</strong></blockquote>
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Your Page Title</title>
	<!-- Include Tailwind CSS -->
	<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</link></meta></meta></head>

<body>
	<div class="relative w-full overflow-hidden rounded-2xl bg-gradient-to-b from-pink-700 to-purple-900 p-4 text-center shadow-xl">
		<h3 class="mx-auto text-3xl font-bold tracking-tight text-white sm:text-2xl" style="margin-top: 3px; margin-bottom: 12px;">
			Schedule a Demo with Our Live Video Expert!
		</h3>
		<p class="mx-auto mt-3 max-w-xl text-sm text-gray-400">
			Discover how VideoSDK can help you build a cutting-edge real-time video app.
			<span class="font-semibold text-lato"/>
		</p>
		<div class="mt-4 flex items-center justify-center">
			<a href="https://www.videosdk.live/contact" class="rounded-md bg-white px-8 py-3 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white" target="_blank" style="text-decoration: none;color: black;" data-faitracker-click-bind="true">
				Book a call
			</a>	
		</div>
		
	</div>
</body>

</html>
<!--kg-card-end: html-->
<h2 id="2-twilio-video-best-for-teams-already-deep-in-twilios-communication-stack">2. Twilio Video: Best for Teams Already Deep in Twilio's Communication Stack</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Communication-APIs-for-SMS-Voice-Video-Authentication_twilio-3.jpeg" class="kg-image" alt="10 Best Amazon Chime SDK Alternatives for Developers in 2026" loading="lazy" width="1920" height="967"/></figure><p><a href="https://www.twilio.com/docs/video" rel="nofollow noreferrer">Twilio Video</a> is a WebRTC-based video conferencing API providing SDKs for web, iOS, and Android with programmable video rooms supporting up to 50 participants per session.</p><p><strong>Key features:</strong></p><ul><li>Twilio SDKs for web, iOS, and Android with REST API for room management</li><li>Call quality insights dashboard for error analysis and session diagnostics</li><li>Deep integration with Twilio's messaging, voice, and authentication products for teams building unified communication stacks</li><li>Network quality signals for client-side adaptive bitrate management</li></ul><p><strong>Pricing:</strong> Twilio Video Group Rooms start at approximately $4 per 1,000 participant-minutes. Recording and composition are billed separately. Free tier includes limited test minutes. (Note: Verify Pricing at the <a href="https://www.twilio.com/en-us/video/pricing" rel="noreferrer nofollow"><strong>Twilio</strong>'s pricing</a> page.)</p><p><strong>Best for:</strong>&nbsp;Teams that already use Twilio for SMS, voice, or two-factor authentication and want to consolidate their communication vendor.</p><p><strong>Limitation:</strong>&nbsp;Twilio Video has announced end-of-life for its Programmable Video product. Teams evaluating Twilio as an Amazon Chime alternative should factor the migration risk of a second platform change into their decision.</p><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/twilio-vs-amazon-chime-sdk"><strong>AWS Chime and Twilio</strong></a><strong>.</strong></blockquote><h2 id="3-mirrorfly-best-for-enterprise-self-hosted-in-app-communication">3. MirrorFly: Best for Enterprise Self-Hosted In-App Communication</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Live-Video-Call-API-Best-Video-Chat-SDK-for-Android-iOS-mirrorfly-3.jpeg" class="kg-image" alt="10 Best Amazon Chime SDK Alternatives for Developers in 2026" loading="lazy" width="1920" height="967"/></figure><p><a href="https://www.mirrorfly.com/" rel="nofollow noreferrer">MirrorFly</a> is an enterprise-grade in-app communication platform providing a self-hosted suite of over 150 chat, voice, and video calling features delivered via APIs and SDKs for iOS, Android, and web applications.</p><p><strong>Key features:</strong></p><ul><li>Self-hosted deployment option for teams requiring full data sovereignty and on-premises infrastructure</li><li>Over 150 prebuilt chat, voice, and video features including screen sharing, file transfer, and message threading</li><li>White-label solution allowing complete UI customization with no MirrorFly branding</li><li>Compliance-ready architecture for HIPAA, GDPR, and enterprise security audits</li><li>Role-based access control and admin dashboard for managing users at scale</li></ul><p><strong>Pricing:</strong> MirrorFly pricing starts at $299 per month for cloud-hosted plans. Self-hosted enterprise licensing is quoted on request. (Note: Verify Pricing at <a href="https://www.mirrorfly.com/pricing.php" rel="noreferrer nofollow">MirrorFly's pricing</a> page.)</p><p><strong>Best for:</strong>&nbsp;Regulated-industry enterprises (healthcare, fintech, legal) that require full data control via self-hosted deployment and need a deep feature set without building from scratch.</p><p><strong>Limitation:</strong>&nbsp;MirrorFly's pricing floor makes it one of the higher-cost options for early-stage teams or startups. Teams that do not require self-hosting will find VideoSDK or Agora more cost-effective at lower usage volumes.</p><h2 id="4-agora-best-for-asia-pacific-latency-and-high-participant-live-streaming">4. Agora: Best for Asia-Pacific Latency and High-Participant Live Streaming</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Agora-Real-Time-Voice-and-Video-Engagement-3.jpeg" class="kg-image" alt="10 Best Amazon Chime SDK Alternatives for Developers in 2026" loading="lazy" width="1920" height="967"/></figure><p><a href="https://www.agora.io/en/" rel="nofollow noreferrer">Agora</a> is a real-time engagement platform providing video calling, interactive live streaming, and virtual interactive sessions with a global SD-RTN (Software Defined Real-time Network) infrastructure optimized for Asia-Pacific regions.</p><p><strong>Key features:</strong></p><ul><li>SD-RTN global network with published sub-400ms end-to-end latency for 1-to-1 and small group calls</li><li>Interactive live streaming supporting audiences of 1 million viewers with host-to-audience latency under 3 seconds</li><li>SDKs for iOS, Android, web, Unity, Electron, Flutter, and React Native</li><li>Agora Extensions Marketplace for third-party AI features including noise suppression and virtual backgrounds</li><li>Co-hosting, pinning, and audience interaction features for broadcast use cases</li></ul><p><strong>Pricing:</strong> Agora video calling starts at approximately $3.99 per 1,000 minutes. Voice calling starts at $0.99 per 1,000 minutes. Recording and cloud transcoding are billed at additional rates. (Note: Verify Pricing at Agora <a href="https://www.agora.io/en/pricing/" rel="noreferrer nofollow">pricing</a>&nbsp; page.)</p><p><strong>Best for:</strong>&nbsp;Applications requiring strong Asia-Pacific infrastructure coverage, high-audience interactive live streaming, or virtual event features.</p><p><strong>Limitation:</strong>&nbsp;Customization options for the video call interface require deeper SDK knowledge than VideoSDK's prebuilt components. Advanced recording and transcription features carry additional charges that compound at scale.</p><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/agora-vs-amazon-chime-sdk"><strong>AWS Chime and Agora</strong></a><strong>.</strong></blockquote><h2 id="5-vonage-best-for-established-telehealth-and-edtech-workflows">5. Vonage: Best for Established Telehealth and EdTech Workflows</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-API-Fully-Programmable-and-Customizable-Vonage-2.jpeg" class="kg-image" alt="10 Best Amazon Chime SDK Alternatives for Developers in 2026" loading="lazy" width="1920" height="967"/></figure><p><a href="https://www.vonage.com/communications-apis/video/" rel="noreferrer nofollow">Vonage Video API</a>, formerly known as OpenTok, is a WebRTC-based programmable video platform providing video conferencing, live streaming, and interactive broadcast tools for web and mobile applications, now owned by Ericsson.</p><p><strong>Key features:</strong></p><ul><li>WebRTC video conferencing supporting up to 25 video participants and up to 200 audio-only participants</li><li>Interactive live streaming (broadcast mode) for audiences beyond the core participant limit</li><li>Collaborative features including screen sharing, chat, and whiteboard</li><li>Dial-in PSTN audio for participants in 60 countries</li><li>Session archiving (server-side recording) as a managed service</li></ul><p><strong>Pricing:</strong> Vonage Video API plans start at approximately $9.99 per month with 2,000 free included minutes. Additional usage is billed per minute, with advanced features (broadcast, archiving) billed at separate rates. (Note: Verify Pricing at Vonage <a href="https://www.vonage.com/communications-apis/video/pricing/" rel="nofollow noreferrer">pricing</a> page.)</p><p><strong>Best for:</strong>&nbsp;Telehealth providers and EdTech platforms with established OpenTok deployments who need to maintain existing integrations while scaling participant count.</p><p><strong>Limitation:</strong>&nbsp;Vonage's acquisition by Ericsson has introduced uncertainty about the product roadmap. Teams considering Vonage for new builds should confirm the current supported SDK versions and roadmap before committing.</p><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/vonage-vs-amazon-chime-sdk"><strong>AWS Chime and Vonage</strong></a><strong>.</strong></blockquote><h2 id="6-apirtc-best-for-webrtc-native-paas-with-minimal-server-management">6. ApiRTC: Best for WebRTC-Native PaaS With Minimal Server Management</h2>
<p><a href="https://apirtc.com/" rel="noreferrer nofollow">ApiRTC</a> is a PaaS (Platform as a Service) by Apizee that simplifies WebRTC integration for web and mobile applications, providing a JavaScript SDK and managed signaling infrastructure for developers who want to add real-time communication without running their own WebRTC servers.</p><p><strong>Key features:</strong></p><ul><li>Managed WebRTC signaling infrastructure so developers skip STUN and TURN server configuration</li><li>JavaScript SDK for web integration with minimal code required for basic video and audio sessions</li><li>Screen sharing, file transfer, and annotation features included in the base SDK</li><li>Video quality adaptation based on available network bandwidth</li></ul><p><strong>Pricing:</strong> ApiRTC basic subscription starts at approximately $54.37 per month. Enterprise pricing is available on request. (Note: Verify Pricing at <a href="https://apirtc.com/pricing/" rel="noreferrer nofollow">ApiRTC pricing</a> page.)</p><p><strong>Best for:</strong>&nbsp;Smaller development teams or web-focused agencies that need managed WebRTC infrastructure without the complexity of self-hosting signaling servers and have primarily web-based applications.</p><p><strong>Limitation:</strong>&nbsp;ApiRTC's subscription entry price is comparatively high for teams at early usage volumes. Mobile SDK coverage and cross-platform support are more limited than VideoSDK or Agora, making it less suitable for native iOS and Android builds.</p><h2 id="7-jitsi-best-for-self-hosted-open-source-video-conferencing">7. Jitsi: Best for Self-Hosted Open-Source Video Conferencing</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Free-Video-Conferencing-Software-for-Web-Mobile-Jitsi-4.jpeg" class="kg-image" alt="10 Best Amazon Chime SDK Alternatives for Developers in 2026" loading="lazy" width="1920" height="967"/></figure><p><a href="https://jitsi.org/" rel="noreferrer nofollow">Jitsi</a>&nbsp;is an open-source video conferencing platform comprising Jitsi Meet (the browser and mobile front-end) and Jitsi Videobridge (the WebRTC SFU media server), licensed under Apache 2.0 and maintained by the 8x8 open-source community.</p><p><strong>Key features:</strong></p><ul><li>Fully <a href="https://github.com/jitsi/jitsi-meet" rel="noreferrer">open-source under Apache 2.0 license</a> with no per-minute costs for self-hosted deployments</li><li>Jitsi Videobridge implements a WebRTC SFU architecture supporting multi-party calls at low server CPU overhead</li><li>End-to-end encryption support via the Insertable Streams API (browser-based calls)</li><li>Screen sharing and collaboration features built into Jitsi Meet</li><li>Jitsi as a Service (JaaS) managed cloud offering from 8x8 for teams that prefer not to self-host</li></ul><p><strong>Pricing:</strong>&nbsp;Self-hosted Jitsi is free. Jitsi as a Service (JaaS) pricing starts at $99 per month. Self-hosted costs are infrastructure-only (compute, bandwidth, TURN server). </p><p><strong>Best for:</strong>&nbsp;Teams requiring full data sovereignty with no recurring SaaS licensing costs, open-source contributors, and organizations in jurisdictions with strict data residency requirements.</p><p><strong>Limitation:</strong>&nbsp;Self-hosting Jitsi requires configuring and maintaining STUN and TURN servers, deploying the Jitsi Videobridge, and designing the user interface independently. Bandwidth management during network degradation is the host's responsibility, not Jitsi's.</p><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/amazon-chime-sdk-vs-jitsi"><strong>AWS Chime and Jitsi</strong></a><strong>.</strong></blockquote><h2 id="8-signalwire-best-for-developers-combining-video-with-programmable-telephony">8. SignalWire: Best for Developers Combining Video with Programmable Telephony</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Building-The-Software-Defined-Telecom-Network-SignalWire-3.jpeg" class="kg-image" alt="10 Best Amazon Chime SDK Alternatives for Developers in 2026" loading="lazy" width="1920" height="967"/></figure><p><a href="https://signalwire.com/" rel="nofollow noreferrer">SignalWire</a> is a cloud communications platform providing programmable voice, video, and messaging APIs built on an open-source FreeSWITCH foundation, designed for developers integrating video calls alongside PSTN telephony and SIP infrastructure.</p><p><strong>Key features:</strong></p><ul><li>Video rooms supporting up to 100 participants with SDKs for web, iOS, and Android</li><li>Native integration with SignalWire's PSTN telephony, SIP trunking, and SMS APIs</li><li>Relay SDK for event-driven application logic that handles call state, participant events, and session routing</li><li>HD and Full HD video options with per-resolution pricing</li><li>Recording and RTMP streaming as add-on features billed separately</li></ul><p><strong>Pricing:</strong>&nbsp;SignalWire video pricing is per-minute based on resolution (HD or Full HD). Recording and streaming carry separate rates. Trial credits available on signup. (Note: Verify Pricing at SignalWire <a href="https://signalwire.com/pricing/video" rel="nofollow noreferrer">pricing</a> page.)</p><p><strong>Best for:</strong>&nbsp;Developers building applications that combine video conferencing with PSTN calling, SIP integration, or SMS workflows in a single programmable platform.</p><p><strong>Limitation:</strong>&nbsp;Application logic for disruption handling, reconnection, and user management must be implemented by the developer. SignalWire does not provide prebuilt UI components comparable to VideoSDK or Agora.</p><h2 id="9-enablex-best-for-south-and-southeast-asia-infrastructure-coverage">9. EnableX: Best for South and Southeast Asia Infrastructure Coverage</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-Call-API-Video-Chat-API-Voice-API-Video-Conferencing_enebleX-4.jpeg" class="kg-image" alt="10 Best Amazon Chime SDK Alternatives for Developers in 2026" loading="lazy" width="1920" height="967"/></figure><p><a href="https://www.enablex.io/" rel="noreferrer nofollow">EnableX</a>&nbsp; is a CPaaS (Communications Platform as a Service) providing live video, voice, and messaging SDKs for JavaScript, PHP, and Python, with infrastructure optimized for South Asia and Southeast Asia deployments.</p><p><strong>Key features:</strong></p><ul><li>Video calling and live streaming SDKs for JavaScript, PHP, and Python</li><li>Supports up to 50 participants per video session with additional capacity at enterprise tiers</li><li>Customizable video layouts, floor control, and moderator features for virtual event use cases</li><li>First-class support for South Asia and Southeast Asia infrastructure with regional edge nodes</li></ul><p><strong>Pricing:</strong> EnableX starts at $0.004 per participant-minute for up to 50 participants. Recording, transcoding, storage, and RTMP streaming carry additional charges per minute. (Note: Verify Pricing at <a href="https://www.enablex.io/cpaas/pricing/video-call-api-pricing" rel="noreferrer nofollow">EnableX pricing</a> page.)</p><p><strong>Best for:</strong>&nbsp;Product teams serving South Asian or Southeast Asian markets where EnableX's regional infrastructure provides latency advantages, and teams building in PHP or Python backend stacks.</p><p><strong>Limitation:</strong>&nbsp;EnableX's SDK language support (JavaScript, PHP, Python) is narrower than VideoSDK or Agora's cross-platform coverage. Teams building native iOS, Android, or Flutter apps will need to verify current mobile SDK availability before committing.</p><h2 id="10-whereby-browser-based-meetings-with-simple-setup">10. Whereby: Browser-Based Meetings with Simple Setup</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-Calling-API-for-Web-and-App-Developers-Whereby-4.jpeg" class="kg-image" alt="10 Best Amazon Chime SDK Alternatives for Developers in 2026" loading="lazy" width="1920" height="967"/></figure><p><a href="https://whereby.com/" rel="noreferrer nofollow">Whereby</a> is a browser-based video meeting platform that provides a Whereby Embedded API for developers to integrate video meetings into web applications without managing WebRTC infrastructure, media servers, or recording pipelines.</p><p><strong>Key features:</strong></p><ul><li>Permanent room URLs that require no downloads or registrations for participants</li><li>Whereby Embedded API allows iframe-based or programmatic video room integration into any web application</li><li>Hybrid meeting features with echo reduction and no dedicated hardware requirement</li><li>End-to-end encryption with GDPR-compliant data handling</li><li>Breakout rooms, screen sharing, and recording available on higher tiers</li></ul><p><strong>Pricing:</strong> Whereby plans for embedded use start at $6.99 per month for basic embedding. Higher tiers with recording, branding removal, and API access are billed at monthly flat rates. (Note: Verify Pricing at Whereby <a href="https://whereby.com/information/pricing" rel="noreferrer nofollow"><strong>pricing</strong></a> page.)</p><p><strong>Best for:</strong>&nbsp;Web application teams that need fast video meeting integration without custom SDK implementation, non-technical teams embedding video into content platforms or no-code tools, and European teams prioritizing GDPR-native data handling.</p><p><strong>Limitation:</strong>&nbsp;Whereby Embedded is not a programmable SDK in the same sense as Chime SDK or VideoSDK. Teams needing custom media control, recording pipelines, AI feature integration, or native mobile calling will outgrow Whereby's embed-first architecture quickly.</p><h2 id="certainly">Certainly!</h2>
<p>Among the mentioned video conferencing SDKs, <a href="https://www.videosdk.live/">VideoSDK</a> stands out for its emphasis on fast and seamless integration. It offers a low-code solution that enables developers to quickly build live video experiences in their applications. With VideoSDK, custom video conferencing solutions can be created and deployed in under 10 minutes, reducing integration time and effort. Unlike other SDKs with longer integration times or limited customization options, VideoSDK prioritizes a streamlined process. By leveraging Video SDK, developers can effortlessly create and embed live video experiences, facilitating real-time connections, communication, and collaboration for users.</p><h2 id="amazon-chime-alternatives-comparison-table">Amazon Chime Alternatives Comparison Table</h2><table>
<thead>
<tr>
<th>Tool</th>
<th>Key Strength</th>
<th>Pricing Model</th>
<th>Best For</th>
</tr>
</thead>
<tbody>
<tr>
<td>VideoSDK</td>
<td>Multi-platform SDK + AI voice agents</td>
<td>Per participant-minute</td>
<td>Multi-platform builds, AI voice, migration from Chime</td>
</tr>
<tr>
<td>Twilio Video</td>
<td>Twilio ecosystem depth</td>
<td>Per participant-minute</td>
<td>Existing Twilio stack consolidation</td>
</tr>
<tr>
<td>Agora</td>
<td>Asia-Pacific latency, large audiences</td>
<td>Per 1,000 minutes</td>
<td>APAC deployments, interactive live streaming</td>
</tr>
<tr>
<td>MirrorFly</td>
<td>Self-hosted, 150+ features</td>
<td>Monthly flat rate from $299</td>
<td>Enterprise data sovereignty</td>
</tr>
<tr>
<td>Vonage Video API</td>
<td>Telehealth/EdTech workflows, OpenTok migration</td>
<td>Monthly + per minute</td>
<td>Established OpenTok integrations</td>
</tr>
<tr>
<td>Jitsi</td>
<td>Open-source, zero per-minute cost</td>
<td>Infrastructure-only (self-host)</td>
<td>Full data control, open-source builds</td>
</tr>
<tr>
<td>SignalWire</td>
<td>Video plus programmable PSTN telephony</td>
<td>Per minute by resolution</td>
<td>Combined video and telephony apps</td>
</tr>
<tr>
<td>EnableX</td>
<td>South/Southeast Asia infrastructure</td>
<td>Per participant-minute</td>
<td>APAC web/PHP/Python stack teams</td>
</tr>
<tr>
<td>ApiRTC</td>
<td>Managed WebRTC PaaS</td>
<td>Monthly subscription</td>
<td>Web-only, minimal server management</td>
</tr>
<tr>
<td>Whereby Embedded</td>
<td>Iframe embed, no-code setup</td>
<td>Monthly flat rate</td>
<td>No-code/low-code web embedding</td>
</tr>
</tbody>
</table>
<h2 id="how-to-choose-the-right-amazon-chime-alternative">How to Choose the Right Amazon Chime Alternative</h2><p>Choosing the right Amazon Chime alternative depends on four production constraints: your platform targets, your pricing elasticity, your recording requirements, and your deployment model.</p><p><strong>If you need native iOS, Android, React Native, and Flutter SDKs in one product,</strong>&nbsp;VideoSDK is the right choice because it provides unified cross-platform coverage without assembling separate libraries per platform. Chime SDK requires platform-specific integration work that VideoSDK handles through a single SDK surface.</p><p><strong>If you are already using Twilio for SMS, voice, or authentication,</strong>&nbsp;Twilio Video is the logical consolidation choice, but verify the current product lifecycle status before committing to new builds. </p><p><strong>If your user base is concentrated in Asia-Pacific and you need interactive live streaming at scale,</strong>&nbsp;Agora's SD-RTN infrastructure and sub-400ms latency benchmarks make it the strongest technical choice for that geography.</p><p><strong>If your organization requires full data sovereignty with zero per-minute SaaS costs,</strong>&nbsp;Jitsi self-hosted is the only option on this list that meets both requirements simultaneously. Factor in the infrastructure and maintenance cost before assuming it is "free."</p><p><strong>If you are building in regulated industries (healthcare, fintech, legal) and need a self-hosted enterprise feature suite,</strong>&nbsp;MirrorFly's self-hosted deployment with HIPAA and GDPR configuration is the strongest fit, though its pricing floor is the highest on this list.</p><p><strong>If you are integrating video into a web app quickly without writing SDK code,</strong>&nbsp;Whereby Embedded's iframe-based integration is the fastest path to a working implementation. It is not the right choice for mobile applications or teams needing custom media control.</p><p><strong>If your application combines video conferencing with PSTN calling or SIP infrastructure,</strong>&nbsp;SignalWire provides native telephony plus video in one programmable platform without the separate AWS service assembly that Chime SDK requires.</p><h2 id="definitions-glossary">Definitions Glossary</h2><p><a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer"><strong>WebRTC (Web Real-Time Communication)</strong></a><strong>:</strong>&nbsp;An open-source protocol standard developed by the W3C and IETF that enables real-time audio and video communication directly between browsers and native applications without plugins.</p><p><a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu#what-is-sfu-selective-forwarding-unit" rel="noreferrer"><strong>SFU (Selective Forwarding Unit)</strong></a><strong>:</strong>&nbsp;A media server architecture used in multi-party WebRTC calls where each participant's media stream is forwarded selectively to other participants rather than mixed, reducing server CPU overhead and supporting larger sessions than MCU architectures.</p><p><a href="https://www.videosdk.live/developer-hub/stun-turn-server/what-is-a-turn-server" rel="noreferrer"><strong>TURN (Traversal Using Relays around NAT)</strong></a><strong>:</strong>&nbsp;A relay server protocol used in WebRTC when direct peer-to-peer connection between clients fails due to firewall or NAT restrictions. All Amazon Chime alternatives that offer managed infrastructure include TURN handling.</p><p><a href="https://www.vonage.com/resources/articles/what-is-cpaas-and-why-should-you-care/" rel="nofollow noreferrer"><strong>CPaaS (Communications Platform as a Service)</strong></a><strong>:</strong>&nbsp;A cloud-based delivery model for real-time communication APIs that allows developers to add voice, video, and messaging to applications without building or maintaining the underlying telecom infrastructure.</p><p><a href="https://www.videosdk.live/developer-hub/sip/sip-protocol-architecture-guide" rel="noreferrer"><strong>SIP (Session Initiation Protocol)</strong></a><strong>:</strong>&nbsp;The signaling standard used for initiating, managing, and terminating voice and video sessions over IP networks, including connections to the PSTN (Public Switched Telephone Network).</p><p><strong>Participant-minute:</strong>&nbsp;The billing unit used by most real-time communication platforms. One participant watching or participating in a session for one minute counts as one participant-minute. A 10-person call running for 30 minutes generates 300 participant-minutes.</p><h2 id="key-takeaways">Key Takeaways</h2><ul><li>VideoSDK is the strongest all-platform Amazon Chime alternative for developer teams in 2026, offering unified SDKs for React, React Native, Flutter, iOS, and Android at published per-minute pricing with AI voice agent support built into the same platform.</li><li>Twilio Video is a known quantity in the Amazon Chime alternatives market but carries product lifecycle risk that new builds should factor into the evaluation. </li><li>Jitsi is the only free, fully self-hosted option on this list, but infrastructure and maintenance costs are real and must be estimated alongside zero per-minute licensing.</li><li>Agora provides the strongest Asia-Pacific latency and high-audience live streaming capabilities among the managed platforms, making it the best choice for APAC-primary deployments.</li><li>All pricing figures in this article carry note flags. Per-minute rates shift frequently across this market; verify directly with each vendor before building cost models.</li><li>The next action for teams migrating from Amazon Chime SDK is to run a multi-platform SDK integration test with a VideoSDK free-tier account before committing to a full migration:&nbsp;<a href="https://app.videosdk.live/signup" rel="noreferrer">Sign up now</a>.</li></ul><h2 id="conclusion">Conclusion</h2><p>Amazon Chime alternatives range from fully managed multi-platform SDKs to open-source self-hosted infrastructure, and the right choice depends entirely on your platform targets, regional latency requirements, and deployment model constraints. VideoSDK is the leading Amazon Chime alternative for developer teams that need predictable pricing, unified cross-platform SDK coverage, and AI voice features in one product without assembling AWS service dependencies. Start building with VideoSDK's free tier ($20 credit, no credit card required) and run your first video call in under 10 minutes:&nbsp;<a href="https://app.videosdk.live/signup" rel="noreferrer">Sign up now</a>.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-best-amazon-chime-alternative-for-mobile-app-development">What is the best Amazon Chime alternative for mobile app development?</h3><p>The best Amazon Chime alternative for mobile app development is VideoSDK because it provides a single unified SDK covering React Native, Flutter, iOS, and Android with prebuilt UI components. Amazon Chime SDK's mobile integration requires platform-specific handling that VideoSDK abstracts away, reducing integration time for teams building across multiple platforms simultaneously.</p><h3 id="are-amazon-chime-alternatives-cheaper-than-chime-sdk">Are Amazon Chime alternatives cheaper than Chime SDK?</h3><p>Several Amazon Chime alternatives are cheaper at comparable usage volumes when recording and media pipeline costs are included. Amazon Chime SDK's base video rate appears competitive, but adding Amazon Kinesis Video Streams for recording, S3 for storage, and Lambda for session management raises the effective per-minute cost significantly. VideoSDK, Agora, and SignalWire all publish all-in per-minute rates that include infrastructure without requiring separate AWS service assembly.</p><h3 id="can-amazon-chime-sdk-be-replaced-without-rewriting-the-entire-application">Can Amazon Chime SDK be replaced without rewriting the entire application?</h3><p>Amazon Chime SDK can be replaced with partial rewrites in most cases because the core integration points (session creation, participant management, media tracks) map to equivalent APIs in VideoSDK, Agora, and Vonage. The most significant rework involves recording pipelines and session event handling. VideoSDK provides a REST API for room management that reduces porting effort compared to rebuilding around new event models.</p><h3 id="what-is-the-best-open-source-alternative-to-amazon-chime-sdk">What is the best open-source alternative to Amazon Chime SDK?</h3><p>Jitsi is the best open-source alternative to Amazon Chime SDK for teams requiring full self-hosted deployment at zero licensing cost. Jitsi Videobridge implements a WebRTC SFU architecture under an Apache 2.0 license, and the 8x8 community maintains active development. Teams that need managed infrastructure without per-minute cost can also evaluate Jitsi as a Service (JaaS) from 8x8.</p><h3 id="which-amazon-chime-alternative-is-best-for-hipaa-compliant-telehealth">Which Amazon Chime alternative is best for HIPAA-compliant telehealth?</h3><p>MirrorFly is the strongest Amazon Chime alternative for HIPAA-compliant telehealth requiring self-hosted data control, while VideoSDK and Amazon Chime SDK both offer HIPAA-eligible configurations on enterprise plans. VideoSDK's enterprise tier includes VPC deployment with dedicated infrastructure and a 99.99% uptime SLA. Always verify HIPAA Business Associate Agreement (BAA) availability directly with any vendor before deployment in covered healthcare contexts.</p><h3 id="does-twilio-video-work-as-an-amazon-chime-alternative-in-2026">Does Twilio Video work as an Amazon Chime alternative in 2026?</h3><p>Twilio Video works as an Amazon Chime alternative for existing Twilio customers consolidating their communication stack, but teams evaluating it for new builds should confirm the current product lifecycle status before committing. Teams moving off Amazon Chime SDK may face a second migration if Twilio Video reaches end-of-life during the product's lifespan.</p><h3 id="how-long-does-it-take-to-migrate-from-amazon-chime-sdk-to-videosdk">How long does it take to migrate from Amazon Chime SDK to VideoSDK?</h3><p>Migration from Amazon Chime SDK to VideoSDK typically takes between one and three weeks for a team with an existing Chime integration, based on practitioner implementations. The core audio and video session logic ports quickly using VideoSDK's REST API for room management. Recording pipeline migration and custom media processing require additional time depending on how deeply the application depends on AWS Kinesis Video Streams. <a href="https://docs.videosdk.live/" rel="noreferrer">VideoSDK's documentation</a>&nbsp;covers the core migration steps for React, React Native, Flutter, iOS, and Android.</p><h2 id="still-skeptical">Still skeptical?</h2>
<p>Explore VideoSDK's comprehensive <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">Quickstart guide</a> and discover the potential with our exclusive <a href="https://docs.videosdk.live/code-sample">sample app</a>. <a href="https://app.videosdk.live/">Sign up</a> today to begin your integration journey and claim your <a href="https://www.videosdk.live/pricing">complimentary $20 free credit</a>, unlocking the full power of VideoSDK. Our dedicated team is always ready to assist you whenever needed. Prepare to witness the incredible experiences you can create using VideoSDK's exceptional capabilities. Unleash your creativity and showcase your creations to the world!</p>]]></content:encoded></item><item><title><![CDATA[How to Integrate Active Speaker Indication in React Native Video Calling App?]]></title><description><![CDATA[Integrating Active Speaker Indication in a React Native video call app for Android enhances user experience by providing visual cues for identifying the current speaker.]]></description><link>https://www.videosdk.live/blog/active-speaker-indication-in-react-native-video-call-app</link><guid isPermaLink="false">660f78902a88c204ca9cfccc</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[React Native]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Mon, 20 Jan 2025 12:38:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/Active-Speaker-React-Native.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/Active-Speaker-React-Native.jpg" alt="How to Integrate Active Speaker Indication in React Native Video Calling App?"/><p>Consider a video call with numerous participants in a discussion. Wouldn't it be helpful to be able to easily identify who is speaking at any given moment throughout the constantly changing sequence of ideas? </p><p>By including active speaker indication in your React Native video call app, you can provide users with visual signals that make it simpler for them to follow conversations and stay interested, resulting in a more seamless and engaging communication experience.</p><p>By integrating Active Speaker Indication, Users can easily identify who is speaking, leading to smoother conversations and reduced confusion. Active speaker indication simplifies the user interface, making it more intuitive and user-friendly. </p><p>In group calls, participants can quickly focus on the current speaker, leading to more efficient meetings and discussions. Users feel more connected when they can easily identify who is speaking, leading to increased engagement and participation.</p><p>This feature can be incredibly useful in a variety of circumstances, including remote work sets, virtual classrooms, webinars, and social gatherings held via video conferences.</p><h2 id="getting-started-with-videosdk">Getting Started with VideoSDK</h2><p>To take advantage of the Active Speaker functionality, we must use the capabilities that the VideoSDK offers. Before diving into the implementation steps, ensure you complete the necessary prerequisites.</p><h3 id="create-a-videosdk-account">Create a VideoSDK Account</h3><p>Go to your <a href="https://app.videosdk.live/dashboard/">VideoSDK dashboard</a> and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.</p><h3 id="generate-your-auth-token">Generate your Auth Token</h3><p>Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token is crucial in authorizing your application to use VideoSDK features. For a more visual understanding of the account creation and token generation process, consider referring to the <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/authentication-and-token">provided tutorial</a>.</p><h3 id="prerequisites">Prerequisites</h3><p>Make sure your development environment meets the following requirements:</p><ul><li>Node.js v12+</li><li>NPM v6+ (comes installed with newer Node versions)</li><li>Android Studio or Xcode installed</li></ul><h2 id="%E2%AC%87%EF%B8%8F-integrate-videosdk%E2%80%8B"><strong>⬇️ </strong>Integrate VideoSDK<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start#videosdk-installation">​</a></h2><p>It is necessary to set up VideoSDK within your project before going into the details of integrating the Active Speaker feature. Installing VideoSDK using NPM or Yarn will depend on the needs of your project.</p><ul><li>For NPM </li></ul><pre><code class="language-npm">npm install "@videosdk.live/react-native-sdk"  "@videosdk.live/react-native-incallmanager"</code></pre><ul><li>For Yarn</li></ul><pre><code class="language-yarn">yarn add "@videosdk.live/react-native-sdk" "@videosdk.live/react-native-incallmanager"</code></pre><h3 id="project-configuration">Project Configuration</h3><p>Before integrating the Active Speaker functionality, ensure that your project is correctly prepared to handle the integration. This setup consists of a sequence of steps for configuring rights, dependencies, and platform-specific parameters so that VideoSDK can function seamlessly inside your application context.</p><h3 id="android-setup">Android Setup</h3>
<ul><li>Add the required permissions in the <code>AndroidManifest.xml</code> file.</li></ul><pre><code class="language-js">&lt;manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.cool.app"
&gt;
    &lt;!-- Give all the required permissions to app --&gt;
    &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
    &lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
    &lt;!-- Needed to communicate with already-paired Bluetooth devices. (Legacy up to Android 11) --&gt;
    &lt;uses-permission
        android:name="android.permission.BLUETOOTH"
        android:maxSdkVersion="30" /&gt;
    &lt;uses-permission
        android:name="android.permission.BLUETOOTH_ADMIN"
        android:maxSdkVersion="30" /&gt;

    &lt;!-- Needed to communicate with already-paired Bluetooth devices. (Android 12 upwards)--&gt;
    &lt;uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /&gt;

    &lt;uses-permission android:name="android.permission.CAMERA" /&gt;
    &lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /&gt;
    &lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
    &lt;uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /&gt;
    &lt;uses-permission android:name="android.permission.FOREGROUND_SERVICE"/&gt;
    &lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;

    &lt;application&gt;
   &lt;meta-data
      android:name="live.videosdk.rnfgservice.notification_channel_name"
      android:value="Meeting Notification"
     /&gt;
    &lt;meta-data
    android:name="live.videosdk.rnfgservice.notification_channel_description"
    android:value="Whenever meeting started notification will appear."
    /&gt;
    &lt;meta-data
    android:name="live.videosdk.rnfgservice.notification_color"
    android:resource="@color/red"
    /&gt;
    &lt;service android:name="live.videosdk.rnfgservice.ForegroundService" android:foregroundServiceType="mediaProjection"&gt;&lt;/service&gt;
    &lt;service android:name="live.videosdk.rnfgservice.ForegroundServiceTask"&gt;&lt;/service&gt;
  &lt;/application&gt;
&lt;/manifest&gt;</code></pre><ul><li>Update your <code>colors.xml</code> file for internal dependencies: </li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">&lt;resources&gt;
  &lt;item name="red" type="color"&gt;
    #FC0303
  &lt;/item&gt;
  &lt;integer-array name="androidcolors"&gt;
    &lt;item&gt;@color/red&lt;/item&gt;
  &lt;/integer-array&gt;
&lt;/resources&gt;</code></pre><figcaption><p><span style="white-space: pre-wrap;">android/app/src/main/res/values/colors.xml</span></p></figcaption></figure><ul><li>Link the necessary VideoSDK Dependencies</li></ul><pre><code class="language-js">  dependencies {
   implementation project(':rnwebrtc')
   implementation project(':rnfgservice')
  }</code></pre><figure class="kg-card kg-code-card"><pre><code class="language-js">include ':rnwebrtc'
project(':rnwebrtc').projectDir = new File(rootProject.projectDir, '../node_modules/@videosdk.live/react-native-webrtc/android')

include ':rnfgservice'
project(':rnfgservice').projectDir = new File(rootProject.projectDir, '../node_modules/@videosdk.live/react-native-foreground-service/android')</code></pre><figcaption><p><span style="white-space: pre-wrap;">android/settings.gradle</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">import live.videosdk.rnwebrtc.WebRTCModulePackage;
import live.videosdk.rnfgservice.ForegroundServicePackage;

public class MainApplication extends Application implements ReactApplication {
  private static List&lt;ReactPackage&gt; getPackages() {
      @SuppressWarnings("UnnecessaryLocalVariable")
      List&lt;ReactPackage&gt; packages = new PackageList(this).getPackages();
      // Packages that cannot be autolinked yet can be added manually here, for example:

      packages.add(new ForegroundServicePackage());
      packages.add(new WebRTCModulePackage());

      return packages;
  }
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">MainApplication.java</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">/* This one fixes a weird WebRTC runtime problem on some devices. */
android.enableDexingArtifactTransform.desugaring=false</code></pre><figcaption><p><span style="white-space: pre-wrap;">android/gradle.properties</span></p></figcaption></figure><ul><li>Include the following line in your <code>proguard-rules.pro</code> file (optional: if you are using Proguard)</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">-keep class org.webrtc.** { *; }</code></pre><figcaption><p><span style="white-space: pre-wrap;">android/app/proguard-rules.pro</span></p></figcaption></figure><ul><li>In your <code>build.gradle</code> file, update the minimum OS/SDK version to <code>23</code>.</li></ul><pre><code class="language-js">buildscript {
  ext {
      minSdkVersion = 23
  }
}</code></pre><h3 id="ios-setup%E2%80%8B">iOS Setup​</h3>
<blockquote>IMPORTANT: Ensure that you are using CocoaPods version 1.10 or later.</blockquote><ul><li>To update CocoaPods, you can reinstall  <code>gem</code> using the following command:</li></ul><pre><code class="language-swift">$ sudo gem install cocoapods</code></pre><ul><li>Manually link react-native-incall-manager (if it is not linked automatically).</li></ul><p>Select <code>Your_Xcode_Project/TARGETS/BuildSettings</code>, in Header Search Paths, add <code>"$(SRCROOT)/../node_modules/@videosdk.live/react-native-incall-manager/ios/RNInCallManager"</code></p><ul><li>Change the path of <code>react-native-webrtc</code> using the following command:</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">pod ‘react-native-webrtc’, :path =&gt; ‘../node_modules/@videosdk.live/react-native-webrtc’</code></pre><figcaption><p><span style="white-space: pre-wrap;">Podfile</span></p></figcaption></figure><ul><li>Change the version of your platform.</li></ul><p>You need to change the platform field in the Podfile to 12.0 or above because <strong>react-native-webrtc</strong> doesn't support iOS versions earlier than 12.0. Update the line: platform: ios, ‘12.0’.</p><ul><li>Install pods.</li></ul><p>After updating the version, you need to install the pods by running the following command:</p><pre><code class="language-swift">Pod install</code></pre><ul><li>Add <strong><code>libreact-native-webrtc.a</code></strong> binary.</li></ul><p>Add the <strong><code>libreact-native-webrtc.a</code></strong> binary to the "Link Binary With Libraries" section in the target of your main project folder.</p><ul><li>Declare permissions in <strong>Info.plis</strong>t :</li></ul><p>Add the following lines to your info.plist file located at :</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
&lt;string&gt;Camera permission description&lt;/string&gt;
&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;Microphone permission description&lt;/string&gt;</code></pre><figcaption><p><span style="white-space: pre-wrap;">project folder/ios/projectname/info.plist</span></p></figcaption></figure><h4 id="register-service">Register Service</h4>
<p>Register VideoSDK services in your root <code>index.js</code> file for the initialization service.</p><pre><code class="language-js">import { AppRegistry } from "react-native";
import App from "./App";
import { name as appName } from "./app.json";
import { register } from "@videosdk.live/react-native-sdk";

register();

AppRegistry.registerComponent(appName, () =&gt; App);</code></pre><h2 id="essential-steps-for-building-the-video-calling-functionality">Essential Steps for Building the Video Calling Functionality</h2><p>By following essential steps, you can seamlessly implement video into your applications with VideoSDK, which provides a robust set of tools and APIs to facilitate the integration of video capabilities into applications.</p><h3 id="step-1-get-started-with-apijs%E2%80%8B">Step 1: Get started with api.js<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start#step-1--get-started-with-apijs">​</a></h3><p>Before moving on, you must create an API request to generate a unique meetingId. You will need an authentication token, which you can create either through the <a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples" rel="noopener noreferrer">videosdk-rtc-api-server-examples</a> or directly from the <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer">VideoSDK Dashboard</a> for developers.</p><pre><code class="language-js">export const token = "&lt;Generated-from-dashbaord&gt;";
// API call to create meeting
export const createMeeting = async ({ token }) =&gt; {
  const res = await fetch(`https://api.videosdk.live/v2/rooms`, {
    method: "POST",
    headers: {
      authorization: `${token}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({}),
  });

  const { roomId } = await res.json();
  return roomId;
};</code></pre><h3 id="step-2-wireframe-appjs-with-all-the-components%E2%80%8B">Step 2: Wireframe App.js with all the components<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start#step-2-wireframe-appjs-with-all-the-components">​</a></h3><p>To build up a wireframe of <em>App.js</em>, you need to use VideoSDK Hooks and Context Providers. VideoSDK provides MeetingProvider, MeetingConsumer, useMeeting, and useParticipant hooks.</p><p>First, you need to understand the <strong>Context Provider</strong> and Consumer. Context is primarily used when some data needs to be accessible by many components at different nesting levels.</p><ul><li><strong>MeetingProvider</strong>: This is the Context Provider. It accepts value <code>config</code> and <code>token</code> as props. The Provider component accepts a value prop to be passed to consuming components that are descendants of this Provider. One Provider can be connected to many consumers. Providers can be nested to override values deeper within the tree.</li><li><strong>MeetingConsumer</strong>: This is the Context Consumer. All consumers that are descendants of a Provider will re-render whenever the Provider’s value prop changes.</li><li><strong>useMeeting</strong>: This is the meeting hook API. It includes all the information related to meetings such as <em>join</em>, <em>leave</em>, <em>enable</em>/<em>disable</em> the mic or webcam, etc.</li><li><strong>useParticipant</strong>: This is the participant hook API. It is responsible for handling all the events and props related to one particular participant such as <strong>name</strong>, <strong>webcamStream</strong>, <strong>micStream</strong>, etc.</li></ul><p>The Meeting Context provides a way to listen for any changes that occur when a participant joins the meeting or makes modifications to their microphone, camera, and other settings.</p><p>Begin by making a few changes to the code in the <em>App.js</em> file.</p><pre><code class="language-js">import React, { useState } from "react";
import {
  SafeAreaView,
  TouchableOpacity,
  Text,
  TextInput,
  View,
  FlatList,
} from "react-native";
import {
  MeetingProvider,
  useMeeting,
  useParticipant,
  MediaStream,
  RTCView,
} from "@videosdk.live/react-native-sdk";
import { createMeeting, token } from "./api";

function JoinScreen(props) {
  return null;
}

function ControlsContainer() {
  return null;
}

function MeetingView() {
  return null;
}

export default function App() {
  const [meetingId, setMeetingId] = useState(null);

  const getMeetingId = async (id) =&gt; {
    const meetingId = id == null ? await createMeeting({ token }) : id;
    setMeetingId(meetingId);
  };

  return meetingId ? (
    &lt;SafeAreaView style={{ flex: 1, backgroundColor: "#F6F6FF" }}&gt;
      &lt;MeetingProvider
        config={{
          meetingId,
          micEnabled: false,
          webcamEnabled: true,
          name: "Test User",
        }}
        token={token}
      &gt;
        &lt;MeetingView /&gt;
      &lt;/MeetingProvider&gt;
    &lt;/SafeAreaView&gt;
  ) : (
    &lt;JoinScreen getMeetingId={getMeetingId} /&gt;
  );
}</code></pre><h3 id="step-3-implement-join-screen%E2%80%8B">Step 3: Implement Join Screen<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start#step-3--implement-join-screen">​</a></h3><p>The join screen will serve as a medium to either schedule a new meeting or join an existing one. </p><figure class="kg-card kg-code-card"><pre><code class="language-js">function JoinScreen(props) {
  const [meetingVal, setMeetingVal] = useState("");
  return (
    &lt;SafeAreaView
      style={{
        flex: 1,
        backgroundColor: "#F6F6FF",
        justifyContent: "center",
        paddingHorizontal: 6 * 10,
      }}
    &gt;
      &lt;TouchableOpacity
        onPress={() =&gt; {
          props.getMeetingId();
        }}
        style={{ backgroundColor: "#1178F8", padding: 12, borderRadius: 6 }}
      &gt;
        &lt;Text style={{ color: "white", alignSelf: "center", fontSize: 18 }}&gt;
          Create Meeting
        &lt;/Text&gt;
      &lt;/TouchableOpacity&gt;

      &lt;Text
        style={{
          alignSelf: "center",
          fontSize: 22,
          marginVertical: 16,
          fontStyle: "italic",
          color: "grey",
        }}
      &gt;
        ---------- OR ----------
      &lt;/Text&gt;
      &lt;TextInput
        value={meetingVal}
        onChangeText={setMeetingVal}
        placeholder={"XXXX-XXXX-XXXX"}
        style={{
          padding: 12,
          borderWidth: 1,
          borderRadius: 6,
          fontStyle: "italic",
        }}
      /&gt;
      &lt;TouchableOpacity
        style={{
          backgroundColor: "#1178F8",
          padding: 12,
          marginTop: 14,
          borderRadius: 6,
        }}
        onPress={() =&gt; {
          props.getMeetingId(meetingVal);
        }}
      &gt;
        &lt;Text style={{ color: "white", alignSelf: "center", fontSize: 18 }}&gt;
          Join Meeting
        &lt;/Text&gt;
      &lt;/TouchableOpacity&gt;
    &lt;/SafeAreaView&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">JoinScreen Component</span></p></figcaption></figure><h3 id="step-4-implement-controls%E2%80%8B">Step 4: Implement Controls<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start#step-4--implement-controls">​</a></h3><p>The next step is to create a <code>ControlsContainer</code> component to manage features such as Join/leave a Meeting and Enable/Disable the Webcam or  Mic.</p><p>In this step, the <code>useMeeting</code> hook is utilized to acquire all the required methods such as <code>join()</code>, <code>leave()</code>, <code>toggleWebcam</code> and <code>toggleMic</code>.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">const Button = ({ onPress, buttonText, backgroundColor }) =&gt; {
  return (
    &lt;TouchableOpacity
      onPress={onPress}
      style={{
        backgroundColor: backgroundColor,
        justifyContent: "center",
        alignItems: "center",
        padding: 12,
        borderRadius: 4,
      }}
    &gt;
      &lt;Text style={{ color: "white", fontSize: 12 }}&gt;{buttonText}&lt;/Text&gt;
    &lt;/TouchableOpacity&gt;
  );
};

function ControlsContainer({ join, leave, toggleWebcam, toggleMic }) {
  return (
    &lt;View
      style={{
        padding: 24,
        flexDirection: "row",
        justifyContent: "space-between",
      }}
    &gt;
      &lt;Button
        onPress={() =&gt; {
          join();
        }}
        buttonText={"Join"}
        backgroundColor={"#1178F8"}
      /&gt;
      &lt;Button
        onPress={() =&gt; {
          toggleWebcam();
        }}
        buttonText={"Toggle Webcam"}
        backgroundColor={"#1178F8"}
      /&gt;
      &lt;Button
        onPress={() =&gt; {
          toggleMic();
        }}
        buttonText={"Toggle Mic"}
        backgroundColor={"#1178F8"}
      /&gt;
      &lt;Button
        onPress={() =&gt; {
          leave();
        }}
        buttonText={"Leave"}
        backgroundColor={"#FF0000"}
      /&gt;
    &lt;/View&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">ControlsContainer Component</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">function ParticipantList() {
  return null;
}
function MeetingView() {
  const { join, leave, toggleWebcam, toggleMic, meetingId } = useMeeting({});

  return (
    &lt;View style={{ flex: 1 }}&gt;
      {meetingId ? (
        &lt;Text style={{ fontSize: 18, padding: 12 }}&gt;
          Meeting Id :{meetingId}
        &lt;/Text&gt;
      ) : null}
      &lt;ParticipantList /&gt;
      &lt;ControlsContainer
        join={join}
        leave={leave}
        toggleWebcam={toggleWebcam}
        toggleMic={toggleMic}
      /&gt;
    &lt;/View&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">MeetingView Component</span></p></figcaption></figure><h3 id="step-5-render-participant-list%E2%80%8B">Step 5: Render Participant List<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start#step-5--render-participant-list">​</a></h3><p>After implementing the controls, the next step is to render the joined participants.</p><p>You can get all the joined <code>participants</code> from the <code>useMeeting</code> Hook.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">function ParticipantView() {
  return null;
}

function ParticipantList({ participants }) {
  return participants.length &gt; 0 ? (
    &lt;FlatList
      data={participants}
      renderItem={({ item }) =&gt; {
        return &lt;ParticipantView participantId={item} /&gt;;
      }}
    /&gt;
  ) : (
    &lt;View
      style={{
        flex: 1,
        backgroundColor: "#F6F6FF",
        justifyContent: "center",
        alignItems: "center",
      }}
    &gt;
      &lt;Text style={{ fontSize: 20 }}&gt;Press Join button to enter meeting.&lt;/Text&gt;
    &lt;/View&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">ParticipantList Component</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">function MeetingView() {
  // Get `participants` from useMeeting Hook
  const { join, leave, toggleWebcam, toggleMic, participants } = useMeeting({});
  const participantsArrId = [...participants.keys()];

  return (
    &lt;View style={{ flex: 1 }}&gt;
      &lt;ParticipantList participants={participantsArrId} /&gt;
      &lt;ControlsContainer
        join={join}
        leave={leave}
        toggleWebcam={toggleWebcam}
        toggleMic={toggleMic}
      /&gt;
    &lt;/View&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">MeetingView Component</span></p></figcaption></figure><h3 id="step-6-handling-participants-media%E2%80%8B">Step 6: Handling Participant's Media<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start#step-6--handling-participants-media">​</a></h3><p>Before Handling the Participant's Media, you need to understand a couple of concepts.</p><h4 id="1-useparticipant-hook">1. useParticipant Hook</h4>
<p>The <code>useParticipant</code> hook is responsible for handling all the properties and events of one particular participant who joined the meeting. It will take <code>participantId</code> as argument.</p><pre><code class="language-useParticipant Hook Example">const { webcamStream, webcamOn, displayName } = useParticipant(participantId);</code></pre><h4 id="2-mediastream-api">2. MediaStream API</h4>
<p>The MediaStream API is beneficial for adding a MediaTrack into the <code>RTCView</code> component, enabling the playback of audio or video.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">&lt;RTCView
  streamURL={new MediaStream([webcamStream.track]).toURL()}
  objectFit={"cover"}
  style={{
    height: 300,
    marginVertical: 8,
    marginHorizontal: 8,
  }}
/&gt;</code></pre><figcaption><p><span style="white-space: pre-wrap;">useParticipant Hook Example</span></p></figcaption></figure><h4 id="rendering-participant-media">Rendering Participant Media</h4>
<figure class="kg-card kg-code-card"><pre><code class="language-js">function ParticipantView({ participantId }) {
  const { webcamStream, webcamOn } = useParticipant(participantId);

  return webcamOn &amp;&amp; webcamStream ? (
    &lt;RTCView
      streamURL={new MediaStream([webcamStream.track]).toURL()}
      objectFit={"cover"}
      style={{
        height: 300,
        marginVertical: 8,
        marginHorizontal: 8,
      }}
    /&gt;
  ) : (
    &lt;View
      style={{
        backgroundColor: "grey",
        height: 300,
        justifyContent: "center",
        alignItems: "center",
      }}
    &gt;
      &lt;Text style={{ fontSize: 16 }}&gt;NO MEDIA&lt;/Text&gt;
    &lt;/View&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">ParticipantView Component</span></p></figcaption></figure><p>Congratulations! By following these steps, you're on your way to unlocking the video within your application. Now, we are moving forward to integrate the feature that builds immersive video experiences for your users!</p><h2 id="integrate-active-speaker-indication-feature">Integrate Active Speaker Indication Feature</h2><p>The Active Speaker Indication feature allows you to identify the participant who is currently the active speaker in a meeting. This feature proves especially valuable in larger meetings or webinars, where numerous participants can make it challenging to identify the active speaker.</p><p>Whenever any participant speaks in a meeting, the <code>onSpeakerChanged</code> event will trigger, providing the participant ID of the active speaker.</p><p>For example, the meeting is running with <strong>Alice</strong> and <strong>Bob</strong>. Whenever any of them speaks, <code>onSpeakerChanged</code> event will trigger and return the speaker's <code>participantId</code>.</p><pre><code class="language-js">import { useMeeting } from "@videosdk.live/react-native-sdk";

const MeetingView = () =&gt; {
  /** useMeeting hooks events */
  const {
    /** Methods */
  } = useMeeting({
    onSpeakerChanged: (activeSpeakerId) =&gt; {
      console.log("Active Speaker participantId", activeSpeakerId);
    },
  });
};</code></pre><p>To integrate the Active Speaker Indication feature into your app, you can refer to the UI provided in the Android blog of the VideoSDK React Native SDK example repository available at <a href="https://github.com/videosdk-live/videosdk-rtc-react-native-sdk-example">GitHub - videosdk-live/videosdk-rtc-react-native-sdk-example</a>. The provided UI showcases how ASI can be seamlessly integrated into your app's interface, providing visual cues to highlight the active speaker during video calls.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/videosdk-live/videosdk-rtc-react-native-sdk-example"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - videosdk-live/videosdk-rtc-react-native-sdk-example: WebRTC based video conferencing SDK for React Native (Android / iOS)</div><div class="kg-bookmark-description">WebRTC based video conferencing SDK for React Native (Android / iOS) - videosdk-live/videosdk-rtc-react-native-sdk-example</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="How to Integrate Active Speaker Indication in React Native Video Calling App?"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">videosdk-live</span></img></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/f57930fc172abe10bc434d0849dff6a41a10f17023b7af84e47d6e6229939cb2/videosdk-live/videosdk-rtc-react-native-sdk-example" alt="How to Integrate Active Speaker Indication in React Native Video Calling App?" onerror="this.style.display = 'none'"/></div></a></figure><h2 id="%E2%9C%A8-want-to-add-more-features-to-react-native-video-calling-app">✨ Want to Add More Features to React Native Video Calling App?</h2><p>If you found this guide helpful and want to explore more features for your React Native video-calling app,</p><p><strong>? Check out these additional resources:</strong></p><ul><li>? RTMP Live Stream: <a href="https://www.videosdk.live/blog/integrate-rtmp-in-react-native-video-app">Link</a></li><li>? Image Capture Feature: <a href="https://www.videosdk.live/blog/integrate-image-capture-in-react-native-for-android-app">Link</a></li><li>?️ Screen Share Feature in Android: <a href="https://www.videosdk.live/blog/integrate-screen-share-in-react-native-android-video-call-app">Link</a></li><li>?️ Screen Share Feature in iOS: <a href="https://www.videosdk.live/blog/integrate-screen-share-in-react-native-ios-video-call-app">Link</a></li><li>? Chat Feature: <a href="https://www.videosdk.live/blog/integrate-chat-feature-in-react-native-video-call-app">Link</a></li><li>?️ Picture-in-Picture (PiP) Mode: <a href="https://www.videosdk.live/blog/picture-in-picture-pip-in-react-native">Link</a></li></ul><h2 id="conclusion">Conclusion</h2><p>In conclusion, integrating Active Speaker Indication enriches the React Native video call app, enhancing communication by providing users with intuitive cues to identify the active speaker effectively. Use cases extend to virtual meetings, online classes, and remote collaboration, where clear identification of the active speaker streamlines interactions and boosts productivity. </p><p>Additionally, it enhances accessibility for users with hearing impairments, facilitating a more inclusive experience for all participants.</p><p>If you are new here and want to build an interactive React Native app with free resources, you can <a href="https://www.videosdk.live/signup">Sign up with VideoSDK</a> and get ? <em>10000 free minutes every month</em>. This will help your new video-calling app go to the next level without any costs associated with initial usage, allowing you to focus on building and scaling your application effectively.</p>]]></content:encoded></item><item><title><![CDATA[What is Codec Switching?]]></title><description><![CDATA[The article explores the role of codecs, the importance of codec switching, common codecs used in streaming, and how the switching process works, highlighting its significance in video conferencing, VoIP services, and streaming platforms.]]></description><link>https://www.videosdk.live/blog/what-is-codec-switching</link><guid isPermaLink="false">66d55ca320fab018df10fe33</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Mon, 20 Jan 2025 06:57:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-Codec-Switching_-2.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-Codec-Switching_-2.jpg" alt="What is Codec Switching?"/><p>Codec switching refers to the dynamic process of changing the codec (coder-decoder) used for encoding or decoding audio and video streams during transmission. This technology is important in streaming media, where fluctuating network conditions and diverse device specifications necessitate on-the-fly adjustments to maintain optimal performance and user satisfaction.</p><h2 id="the-role-of-codecs-in-streaming">The Role of Codecs in Streaming</h2><p>Before we delve further into codec switching, it's essential to understand the fundamental role of <a href="https://www.streamingmedia.com/Articles/ReadArticle.aspx?ArticleID=74487">codecs</a> in the streaming ecosystem. A codec is a specialized technology that compresses and decompresses multimedia files, facilitating efficient transmission and playback.</p><p>Codecs can be categorized into two main types:</p><ol><li><strong>Lossy Codecs</strong>: These are more commonly used in streaming due to their ability to significantly reduce file sizes while sacrificing some quality.</li><li><strong>Lossless Codecs</strong>: These preserve the original quality but result in larger file sizes.</li></ol><h2 id="the-importance-of-codec-switching">The Importance of Codec Switching</h2><h3 id="1-enabling-adaptive-streaming">1. Enabling Adaptive Streaming</h3><p><a href="https://getstream.io/glossary/video-codecs/">Adaptive bitrate streaming</a> heavily relies on codec switching. In this approach, multiple versions of a video are encoded at different bitrates. The streaming service can then seamlessly switch between these versions based on the viewer's current internet speed and device capabilities, ensuring a smooth viewing experience without buffering interruptions.</p><h3 id="2-optimizing-quality">2. Optimizing Quality</h3><p>Codec switching allows streaming platforms to deliver higher-quality streams when bandwidth permits and revert to lower-quality streams when bandwidth is constrained. This flexibility is crucial for maintaining user satisfaction across various network conditions.</p><h3 id="3-enhancing-device-compatibility">3. Enhancing Device Compatibility</h3><p>Different devices often support different codecs. By implementing codec switching, streaming services can deliver the most compatible format for each user's device, enhancing accessibility and overall user experience.</p><h2 id="common-codecs-in-streaming">Common Codecs in Streaming</h2><p>Several codecs are widely used in the streaming industry, each with its strengths:</p><ul><li><a href="https://corp.kaltura.com/blog/video-codec/"><strong>H.264</strong></a>: This codec is extensively used for video streaming due to its excellent balance of quality and compression efficiency.</li><li><strong>H.265 (HEVC)</strong>: Offering better compression than H.264, this codec is particularly suitable for high-resolution content like 4K streaming.</li><li><strong>AV1</strong>: An emerging open-source codec that promises improved efficiency and quality, potentially replacing older codecs.</li><li><strong>AAC</strong>: This codec is commonly used for audio and provides good quality at lower bitrates.</li></ul><h2 id="how-codec-switching-works">How Codec Switching Works</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/09/Flowchart-of-the-adaptive-codec-switching-1.png" class="kg-image" alt="What is Codec Switching?" loading="lazy" width="2570" height="1108"/></figure><p>The process of codec switching involves several key steps:</p><ol><li><strong>Network Monitoring</strong>: The system continuously monitors network conditions such as bandwidth, latency, jitter, and packet loss.</li><li><strong>Decision Making</strong>: Based on the monitored data, the system decides whether to switch codecs to maintain optimal performance.</li><li><strong>Seamless Transition</strong>: The switch occurs in real time, often with minimal disruption to the user. This is achieved by temporarily buffering the live media stream and gradually transitioning from one codec to another.</li><li><strong>Negotiation</strong>: During a session, devices negotiate which codecs are supported and can be switched to during the live streaming process.</li></ol><h2 id="use-cases-of-codec-switching">Use Cases of Codec Switching</h2><p>Codec switching finds applications in various domains:</p><ul><li><a href="https://www.videosdk.live/audio-video-conferencing"><strong>Video Conferencing</strong></a>: Ensures uninterrupted communication during fluctuating internet conditions.</li><li><a href="https://www.videosdk.live/developer-hub/sip/voip"><strong>VoIP Services</strong></a>: Enhances call quality by adapting codecs based on real-time network analysis.</li><li><a href="https://www.videosdk.live/interactive-live-streaming"><strong>Streaming Platforms</strong></a>: Optimizes the quality of live streams by adjusting to viewers' available bandwidth.</li></ul><p>As streaming continues to dominate the digital media landscape, technologies like codec switching play an increasingly vital role in ensuring high-quality, uninterrupted viewing experiences. By dynamically adapting to network conditions and device capabilities, codec switching allows streaming services to deliver optimal performance across a wide range of scenarios. As codecs continue to evolve and improve, we can expect even more efficient and seamless streaming experiences in the future.</p>]]></content:encoded></item><item><title><![CDATA[Best Amazon Chime SDK Competitors in 2025]]></title><description><![CDATA[Explore AWS Chime SDK's competition by comparing AWS Chime SDK with its competitors in the realm of real-time communication.]]></description><link>https://www.videosdk.live/blog/amazon-chime-sdk-competitors</link><guid isPermaLink="false">64b525319eadee0b8b9e71d1</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 20 Jan 2025 06:19:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2023/08/AWZ-Chime-competitors-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2023/08/AWZ-Chime-competitors-1.jpg" alt="Best Amazon Chime SDK Competitors in 2025"/><p>If you're currently exploring <strong>video communication APIs</strong>, the Amazon Chime SDK stands out as a noteworthy option among several contenders that might align with your requirements. It offers a robust set of features and functionalities that could potentially meet your needs.</p><p>However, navigating the landscape of <a href="https://www.videosdk.live/blog/amazon-chime-sdk-alternative">alternatives to Amazon Chime</a> SDK and finding the ideal fit can indeed be a complex task, given the diverse array of choices available. Before delving into the world of video API offerings, it's crucial to establish your project's budget, primary use case, and the essential features you require.</p><p>In the dynamic realm of video conferencing, choosing the right SDK is paramount for a seamless virtual collaboration experience. This article delves into the landscape of Amazon Chime SDK competitors in 2024, offering insights into key players and helping you make informed decisions for your conferencing needs.</p><h2 id="amazon-chime-sdk">Amazon Chime SDK</h2>
<p>AWS Chime SDK stands out as a versatile solution, providing developers with powerful tools to embed video and audio calling, screen sharing, and messaging into applications. As the technological landscape evolves, exploring the alternatives becomes imperative.</p><h3 id="key-points-about-amazon-chime-sdk">Key points about Amazon Chime SDK</h3>
<ul><li>The Amazon Chime SDK allows for video meetings with a <strong>maximum of 25 participants</strong> (50 for mobile users), making it a suitable platform for effective collaboration among users. </li><li>However, it's important to note that some specific features are <strong>not available</strong> in the Amazon Chime SDK, such as <strong>polling</strong>, <strong>auto-sync with Google Calendar</strong>, and <strong>background blur</strong> effects. </li><li>This limitation might impact users who require these functionalities for their applications.</li><li>Additionally, there have been reported <strong>compatibility issues</strong> in Linux environments, and participants using the Safari browser might encounter <strong>challenges</strong> while using the SDK. </li><li>These issues can potentially affect the overall user experience, especially for those using this platform.</li><li>It's worth mentioning that <strong>customer support experiences</strong> with the Amazon Chime SDK <strong>can vary</strong>. </li><li>Some users have reported <strong>inconsistent</strong> query resolution times, and the <strong>quality of support</strong> can depend on the specific support agent assigned to the case. </li><li>This aspect might impact the level of assistance users receive when troubleshooting issues or seeking guidance.</li></ul><h3 id="amazon-chime-sdk-pricing">Amazon Chime SDK pricing</h3>
<p>Amazon Chime SDK offers a <strong>tiered </strong><a href="https://aws.amazon.com/chime/pricing/"><strong>pricing</strong></a><strong> model</strong> that caters to users with varying collaboration needs:</p><ol><li><strong>Free Basic Plan</strong>: The free basic plan enables users to engage in <strong>one-on-one audio/video calls</strong> and <strong>group chats</strong> without any cost. This plan provides essential communication features for users who require simple interactions.</li><li><strong>Plus Plan</strong>: For users who need <strong>additional features and functionalities</strong>, there is the Plus plan available at <strong>$2.50</strong> per month per user. This plan includes additions such as <strong>screen sharing</strong>, <strong>remote desktop control</strong>, <strong>1 GB of message history per user</strong>, and <strong>integration with Active Directory</strong>.</li><li><strong>Pro Plan</strong>: The Pro plan, priced at <strong>$15</strong> per user per month, is designed for more extensive collaboration needs. This comprehensive plan encompasses all the features of the Plus plan and allows for meetings with <strong>three or more participants</strong>. It's suitable for larger group discussions, presentations, and more complex collaboration scenarios.</li></ol><h2 id="direct-comparison-aws-chime-sdk-vs-top-competitors">Direct Comparison: AWS Chime SDK vs Top Competitors</h2>
<p>The <strong>top competitors of AWS Chime SDK </strong>are VideoSDK,  100ms, WebRTC, <a href="https://www.videosdk.live/blog/jitsi-competitors">Jitsi</a>, Daily, and LiveKit.</p><p>Let's compare Chime with each of the above competitors.</p><h2 id="1-aws-chime-sdk-vs-videosdk">1. AWS Chime SDK vs VideoSDK</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/08/AWS-Chime-vs-Videosdk.png" class="kg-image" alt="Best Amazon Chime SDK Competitors in 2025" loading="lazy" width="1429" height="525"/></figure><p>VideoSDK offers developers a seamless API that simplifies incorporating robust, scalable, and dependable audio-video capabilities into their applications. With only a few lines of code, developers can introduce live audio and video experiences to various platforms within minutes. One of the primary benefits of opting for the <a href="https://www.videosdk.live/">VideoSDK</a> is its remarkable ease of integration. This characteristic enables developers to concentrate their efforts on crafting innovative features that contribute to enhanced user engagement and retention.</p>
<!--kg-card-begin: html-->
<table border="2px black" cellspacing="0px" style="border-radius: 10px;">
    <tr>
        <td/>
        <td><strong>AWS Chime SDK pricing</strong></td>
        <td><strong>Video SDK pricing</strong></td>
    </tr>
    <tr>
        <td><strong>Video calling</strong></td>
        <td>Starts from <strong>$1.7</strong> per 1,000 minutes</td>
        <td>Starts from <strong>$2</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>Interactive live streaming</strong></td>
        <td>NA</td>
        <td>Starts from <strong>$1</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>RTMP</strong></td>
        <td>NA</td>
        <td>
            <strong>$15</strong> per 1,000 minutes, No limit on participants
        </td>
    </tr>
    <tr>
        <td><strong>Cloud Recording<strong/></strong></td>
        <td><strong>$12.5</strong> per 1,000 minutes</td>
        <td>
            <strong>$15</strong> per 1,000 minutes, No limit on participants
        </td>
    </tr>
</table>
<!--kg-card-end: html-->
<blockquote>Here's a detailed comparison of <a href="https://www.videosdk.live/amazon-chime-sdk-vs-videosdk">AWS Chime SDK vs Video SDK</a>.</blockquote><h2 id="2-aws-chime-sdk-vs-100ms">2. AWS Chime SDK vs 100ms</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/08/AWS-Chime-vs-100ms.jpg" class="kg-image" alt="Best Amazon Chime SDK Competitors in 2025" loading="lazy" width="1429" height="525"/></figure><p><a href="https://www.videosdk.live/blog/100ms-alternative">100ms</a> offers a cloud platform that empowers developers to effortlessly incorporate video and audio conferencing into a variety of applications, including web, Android, and iOS platforms. This platform is equipped with a range of powerful tools, including REST APIs, software development kits (SDKs), and an intuitive user-friendly dashboard. These tools collectively streamline the process of capturing, distributing, recording, and displaying live interactive audio and video content.</p>
<!--kg-card-begin: html-->
<table border="2px black" cellspacing="0px" style="border-radius: 10px;">
    <tr>
        <td/>
        <td><strong>AWS Chime SDK pricing</strong></td>
        <td><strong>100ms pricing</strong></td>
    </tr>
    <tr>
        <td><strong>Video calling</strong></td>
        <td>Starts from <strong>$1.7</strong> per 1,000 minutes</td>
        <td>Starts from <strong>$4</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>Interactive live streaming</strong></td>
        <td>NA</td>
        <td>Starts from <strong>$4</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>RTMP</strong></td>
        <td>NA</td>
        <td><strong>$40</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>Cloud Recording<strong/></strong></td>
        <td><strong>$12.5</strong> per 1,000 minutes</td>
        <td><strong>$13.5</strong> per 1,000 minutes</td>
    </tr>
</table>
<!--kg-card-end: html-->
<blockquote>Here's a detailed comparison of <a href="https://www.videosdk.live/amazon-chime-sdk-vs-100ms">AWS Chime SDK vs 100ms</a>.</blockquote><h2 id="3-aws-chime-sdk-vs-webrtc">3. AWS Chime SDK vs WebRTC</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/08/AWS-Chime-vs-WebRTC.jpg" class="kg-image" alt="Best Amazon Chime SDK Competitors in 2025" loading="lazy" width="1429" height="525"/></figure><p>WebRTC is an open-source project that empowers web browsers to integrate Real-Time Communications (RTC) capabilities through user-friendly JavaScript APIs. The various components of <a href="https://www.videosdk.live/blog/webrtc-alternative">WebRTC</a> have been meticulously optimized to effectively facilitate real-time communication functionalities within web browsers. This initiative enables developers to seamlessly embed features like audio and video calls, chat, file sharing, and more directly into their web applications, creating dynamic and interactive user experiences.</p>
<!--kg-card-begin: html-->
<table border="2px black" cellspacing="0px" style="border-radius: 10px;">
    <tr>
        <td/>
        <td><strong>AWS Chime SDK pricing</strong></td>
        <td><strong>WebRTC pricing</strong></td>
    </tr>
    <tr>
        <td><strong>Video calling</strong></td>
        <td>Starts from <strong>$1.7</strong> per 1,000 minutes</td>
        <td>NA</td>
    </tr>
    <tr>
        <td><strong>Interactive live streaming</strong></td>
        <td>NA</td>
        <td>NA</td>
    </tr>
    <tr>
        <td><strong>RTMP</strong></td>
        <td>NA</td>
        <td>NA</td>
    </tr>
    <tr>
        <td><strong>Cloud Recording<strong/></strong></td>
        <td><strong>$12.5</strong> per 1,000 minutes</td>
        <td>NA</td>
    </tr>
</table>
<!--kg-card-end: html-->
<blockquote>Here's a detailed comparison of <a href="https://www.videosdk.live/amazon-chime-sdk-vs-webrtc">AWS Chime SDK vs WebRTC</a>.</blockquote><h2 id="4-aws-chime-sdk-vs-jitsi">4. AWS Chime SDK vs Jitsi</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/08/AWS-Chime-vs-Jitsi-Meet.jpg" class="kg-image" alt="Best Amazon Chime SDK Competitors in 2025" loading="lazy" width="1429" height="525"/></figure><p>Jitsi is an open-source platform that focuses on simplifying the process of video conferencing. It offers a user-friendly experience that doesn't require any downloads or plugins, which makes it an attractive option for individuals or businesses seeking a straightforward and cost-effective solution for live video communication. With <a href="https://www.videosdk.live/blog/jitsi-alternative">Jitsi</a>, users can easily initiate video calls, participate in virtual meetings, and collaborate seamlessly without the need for extensive technical know-how or complex setups.</p>
<!--kg-card-begin: html-->
<table border="2px black" cellspacing="0px" style="border-radius: 10px;">
    <tr>
        <td/>
        <td><strong>AWS Chime SDK pricing</strong></td>
        <td><strong>Jitsi pricing</strong></td>
    </tr>
    <tr>
        <td><strong>Video calling</strong></td>
        <td>Starts from <strong>$1.7</strong> per 1,000 minutes</td>
        <td>NA</td>
    </tr>
    <tr>
        <td><strong>Interactive live streaming</strong></td>
        <td>NA</td>
        <td>NA</td>
    </tr>
    <tr>
        <td><strong>RTMP</strong></td>
        <td>NA</td>
        <td>NA</td>
    </tr>
    <tr>
        <td><strong>Cloud Recording<strong/></strong></td>
        <td><strong>$12.5</strong> per 1,000 minutes</td>
        <td>NA</td>
    </tr>
</table>
<!--kg-card-end: html-->
<blockquote>Here's a detailed comparison of <a href="https://www.videosdk.live/amazon-chime-sdk-vs-jitsi">AWS Chime SDK vs Jitsi</a>.</blockquote><h2 id="5-aws-chime-sdk-vs-daily">5. AWS Chime SDK vs Daily</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/08/AWS-Chime-vs-Daily.jpg" class="kg-image" alt="Best Amazon Chime SDK Competitors in 2025" loading="lazy" width="1429" height="525"/></figure><p>Daily is a developer-friendly platform that empowers developers to effortlessly integrate real-time video and audio calls into their applications, directly within web browsers. With <a href="https://www.videosdk.live/blog/daily-co-alternative">Daily</a>'s tools and features, developers can easily handle the complex backend aspects of video calls across different platforms.</p>
<!--kg-card-begin: html-->
<table border="2px black" cellspacing="0px" style="border-radius: 10px;">
    <tr>
        <td/>
        <td><strong>AWS Chime SDK pricing</strong></td>
        <td><strong>Daily pricing</strong></td>
    </tr>
    <tr>
        <td><strong>Video calling</strong></td>
        <td>Starts from <strong>$1.7</strong> per 1,000 minutes</td>
        <td>Starts from <strong>$4</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>Interactive live streaming</strong></td>
        <td>NA</td>
        <td>Starts from <strong>$1.2</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>RTMP</strong></td>
        <td>NA</td>
        <td><strong>$15</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>Cloud Recording<strong/></strong></td>
        <td><strong>$12.5</strong> per 1,000 minutes</td>
        <td><strong>$13.49</strong> per 1,000 minutes</td>
    </tr>
</table>
<!--kg-card-end: html-->
<blockquote>Here's a detailed comparison of <a href="https://www.videosdk.live/amazon-chime-sdk-vs-daily">AWS Chime SDK vs Daily</a>.</blockquote><h2 id="6-aws-chime-sdk-vs-livekit">6. AWS Chime SDK vs LiveKit</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/08/AWS-Chime-vs-LiveKIt.jpg" class="kg-image" alt="Best Amazon Chime SDK Competitors in 2025" loading="lazy" width="1429" height="525"/></figure><p>Livekit offers a comprehensive solution for developers who want to integrate live video and audio capabilities into their native applications. With its set of software development kits (SDKs), <a href="https://www.videosdk.live/blog/livekit-alternative">Livekit</a> makes it seamless to incorporate various real-time communication features into your applications, enhancing user engagement and interaction.</p>
<!--kg-card-begin: html-->
<table border="2px black" cellspacing="0px" style="border-radius: 10px;">
    <tr>
        <td/>
        <td><strong>AWS Chime SDK pricing</strong></td>
        <td><strong>LiveKit pricing</strong></td>
    </tr>
    <tr>
        <td><strong>Video calling</strong></td>
        <td>Starts from <strong>$1.7</strong> per 1,000 minutes</td>
        <td>Starts from <strong>$20</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>Interactive live streaming</strong></td>
        <td>NA</td>
        <td>
            <strong>$69</strong> per hour (upto 500 viewers only and doesn't support Full HD)
        </td>
    </tr>
    <tr>
        <td><strong>RTMP</strong></td>
        <td>NA</td>
        <td>No accurate data available</td>
    </tr>
    <tr>
        <td><strong>Cloud Recording<strong/></strong></td>
        <td><strong>$12.5</strong> per 1,000 minutes</td>
        <td>No accurate data available</td>
    </tr>
</table>
<!--kg-card-end: html-->
<blockquote>Here's a detailed comparison of <a href="https://www.videosdk.live/amazon-chime-sdk-vs-livekit">AWS Chime SDK vs LiveKit</a>.</blockquote><h2 id="have-you-determined-whether-chime-aligns-with-your-requirements-or-have-you-found-an-alternative">Have you determined whether Chime aligns with your requirements, or have you found an alternative?</h2>
<p>The alternatives to AWS Chime SDK that were previously discussed offer a diverse set of solutions for developers aiming to enhance in-app user experiences. However, if your requirements extend beyond simple in-app communication and you're seeking a more comprehensive engagement strategy that incorporates voice and video functionalities, solutions like <a href="https://www.videosdk.live/signup/">Video SDK</a> could potentially align better with your needs. These solutions provide the necessary tools and features to create immersive and interactive experiences for your users, allowing you to offer more than just text-based communication. By exploring these options, you can take your application's user experience to the next level and provide a richer communication environment for your users.</p><p>Taking into account your specific requirements, budget limitations, and the essential features you're seeking, AWS Chime SDK may not align perfectly with your needs. To ensure a well-informed decision, it's advisable to explore the alternatives that were discussed earlier. Some of these alternatives, such as Video SDK, offer free trial options that allow you to test their capabilities in real-world projects. By doing so, you can gain a better understanding of how well they meet your needs before making a significant commitment. Additionally, it's important to remember that if your requirements change over time, you have the flexibility to transition away from AWS Chime SDK to a solution that better suits your evolving needs.</p>]]></content:encoded></item><item><title><![CDATA[How to Integrate Active Speaker in Android(Java) Video Chat App?]]></title><description><![CDATA[In this article, Learn how to use the VideoSDK to add an active speaker indicating to your Android(Java) video app. ]]></description><link>https://www.videosdk.live/blog/active-speaker-in-java-video-chat-app</link><guid isPermaLink="false">65fbec9b2a88c204ca9cec05</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Sun, 19 Jan 2025 16:20:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/Active-Speaker-Android.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/Active-Speaker-Android.jpg" alt="How to Integrate Active Speaker in Android(Java) Video Chat App?"/><p>Have you ever been on a crowded video call where you can hear the conversation, but you have no idea who is actually talking? Video conferences with numerous participants can be confusing, making it difficult to follow the conversation and engage effectively.</p><p>This is where the <strong>Active Speaker indication</strong> comes in! This is an expert guide for Android developers who want to implement active speaker highlighting in their video apps (built with Java) using VideoSDK.</p><p>Highlighting the active speaker is especially beneficial in large meetings or webinars where numerous participants are present, which can lead to confusion about who is speaking at which time. By including this feature, you can improve the user experience on large group calls, encouraging more participation and better engagement.</p><h2 id="goals">Goals</h2><p>By the End of this Article:</p><ol><li>Create a <a href="https://www.videosdk.live/signup">VideoSDK account</a> and generate your VideoSDK auth token.</li><li>Integrate the VideoSDK library and dependencies into your project.</li><li>Implement core functionalities for video calls using VideoSDK</li><li>Enable active speaker indication</li></ol><h2 id="getting-started-with-videosdk">Getting Started with VideoSDK</h2><p>To take advantage of the active speaker highlighting functionality, we will need to use the capabilities that the VideoSDK offers. Before we dive into the implementation steps, let's make sure you complete the necessary prerequisites.</p><h3 id="create-a-videosdk-account">Create a VideoSDK Account</h3><p>Go to your <a href="https://app.videosdk.live/dashboard/">VideoSDK dashboard</a> and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.</p><h3 id="generate-your-auth-token">Generate your Auth Token</h3><p>Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token plays a crucial role in authorizing your application to use VideoSDK features.</p><p>For a more visual understanding of the account creation and token generation process, consider referring to the <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/authentication-and-token#1-generating-token-from-dashboard">provided tutorial</a>.</p><h3 id="prerequisites-and-setup">Prerequisites and Setup</h3><p>Make sure your development environment meets the following requirements:</p><ul><li>Java Development Kit is supported.</li><li>Android Studio version 3.0 or later.</li><li>Android SDK API level 21 or higher.</li><li>A mobile device with Android 5.0 or later version.</li></ul><h2 id="integrate-videosdk">Integrate VideoSDK</h2><p>Following the account creation and token generation steps, we'll guide you through the process of adding the VideoSDK library and other dependencies to your project. We'll also ensure your app has the required permissions to access features like audio recording, camera usage, and internet connectivity, all crucial for a seamless video experience.</p><h3 id="step-a-add-the-repositories-to-the-projects-settingsgradle-file">Step (a): Add the repositories to the project's <code>settings.gradle</code> file.</h3><pre><code class="language-Java">dependencyResolutionManagement{
  repositories {
    // ...
    google()
    mavenCentral()
    maven { url 'https://jitpack.io' }
    maven { url "https://maven.aliyun.com/repository/jcenter" }
  }
}
</code></pre><h3 id="step-b-include-the-following-dependency-within-your-applications-buildgradle-file">Step (b): Include the following dependency within your application's <code>build.gradle</code> file:</h3><pre><code class="language-Java">dependencies {
  implementation 'live.videosdk:rtc-android-sdk:0.1.26'

  // library to perform Network call to generate a meeting id
  implementation 'com.amitshekhar.android:android-networking:1.0.2'

  // Other dependencies specific to your app
}
</code></pre><blockquote>If your project has set <code>android.useAndroidX=true</code>, then set <code>android.enableJetifier=true</code> in the <code>gradle.properties</code> file to migrate your project to AndroidX and avoid duplicate class conflict.</blockquote><h3 id="step-c-add-permissions-to-your-project">Step (c): Add permissions to your project</h3><p>In <code>/app/Manifests/AndroidManifest.xml</code>, add the following permissions after <code>&lt;/application&gt;</code>.</p><pre><code class="language-Java">&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
&lt;uses-permission android:name="android.permission.CAMERA" /&gt;
</code></pre><p>These permissions are essential for enabling core functionalities like audio recording, internet connectivity for real-time communication, and camera access for video streams within your video application.</p><h2 id="essential-steps-for-building-the-video-calling-functionality">Essential Steps for Building the Video Calling Functionality</h2><p>We'll now delve into the functionalities that make your video application after set up your project with VideoSDK. This section outlines the essential steps for implementing core functionalities within your app.</p><p>This section will guide you through four key aspects:</p><h3 id="step-1-generate-a-meetingid">Step 1: Generate a <code>meetingId</code></h3><p>Now, we can create the <code>meetingId</code> from the VideoSDK's rooms API. You can refer to this <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/setup-call/initialize-meeting#generating-meeting-id">documentation</a> to generate meetingId.</p><h3 id="step-2-initializing-the-meeting">Step 2: Initializing the Meeting</h3><p>After getting <code>meetingId</code> , the next step involves initializing the meeting for that we need to,</p><ol><li>Initialize VideoSDK.</li><li>Configure <strong>VideoSDK</strong> with a token.</li><li>Initialize the meeting with required params such as <code>meetingId</code>, <code>participantName</code>, <code>micEnabled</code>, <code>webcamEnabled</code> and more.</li><li>Add <code>MeetingEventListener</code> for listening events such as Meeting Join/Left and Participant Join/Left.</li><li>Join the room with <code>meeting.join()</code> method.</li></ol><p>Please copy the .xml file of the <code>MeetingActivity</code> from <a href="https://github.com/videosdk-live/quickstart/blob/main/android-rtc/Videosdk_android_kotlin_quickstart/app/src/main/res/layout/activity_meeting.xml">here</a>.</p><pre><code class="language-Java">public class MeetingActivity extends AppCompatActivity {
  // declare the variables we will be using to handle the meeting
  private Meeting meeting;
  private boolean micEnabled = true;
  private boolean webcamEnabled = true;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_meeting);

    final String token = ""; // Replace with the token you generated from the VideoSDK Dashboard
    final String meetingId = ""; // Replace with the meetingId you have generated
    final String participantName = "John Doe";

    // 1. Initialize VideoSDK
    VideoSDK.initialize(applicationContext);

    // 2. Configuration VideoSDK with Token
    VideoSDK.config(token);

    // 3. Initialize VideoSDK Meeting
    meeting = VideoSDK.initMeeting(
            MeetingActivity.this, meetingId, participantName,
            micEnabled, webcamEnabled,null, null, false, null, null);

    // 4. Add event listener for listening upcoming events
    meeting.addEventListener(meetingEventListener);

    // 5. Join VideoSDK Meeting
    meeting.join();

    ((TextView)findViewById(R.id.tvMeetingId)).setText(meetingId);
  }

  // creating the MeetingEventListener
  private final MeetingEventListener meetingEventListener = new MeetingEventListener() {
    @Override
    public void onMeetingJoined() {
      Log.d("#meeting", "onMeetingJoined()");
    }

    @Override
    public void onMeetingLeft() {
      Log.d("#meeting", "onMeetingLeft()");
      meeting = null;
      if (!isDestroyed()) finish();
    }

    @Override
    public void onParticipantJoined(Participant participant) {
      Toast.makeText(MeetingActivity.this, participant.getDisplayName() + " joined", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onParticipantLeft(Participant participant) {
      Toast.makeText(MeetingActivity.this, participant.getDisplayName() + " left", Toast.LENGTH_SHORT).show();
    }
  };
}</code></pre><h3 id="step-3-handle-local-participant-media">Step 3: Handle Local Participant Media</h3><p>After successfully entering the meeting, it's time to manage the webcam and microphone for the local participant (you).</p><p>To enable or disable the webcam, we'll use the <code>Meeting</code> class methods <code>enableWebcam()</code> and <code>disableWebcam()</code>, respectively. Similarly, to mute or unmute the microphone, we'll utilize the methods <code>muteMic()</code> and <code>unmuteMic()</code></p><pre><code class="language-Java">public class MeetingActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_meeting);
    //...Meeting Setup is Here

    // actions
    setActionListeners();
  }

  private void setActionListeners() {
    // toggle mic
    findViewById(R.id.btnMic).setOnClickListener(view -&gt; {
      if (micEnabled) {
        // this will mute the local participant's mic
        meeting.muteMic();
        Toast.makeText(MeetingActivity.this, "Mic Disabled", Toast.LENGTH_SHORT).show();
      } else {
        // this will unmute the local participant's mic
        meeting.unmuteMic();
        Toast.makeText(MeetingActivity.this, "Mic Enabled", Toast.LENGTH_SHORT).show();
      }
      micEnabled=!micEnabled;
    });

    // toggle webcam
    findViewById(R.id.btnWebcam).setOnClickListener(view -&gt; {
      if (webcamEnabled) {
        // this will disable the local participant webcam
        meeting.disableWebcam();
        Toast.makeText(MeetingActivity.this, "Webcam Disabled", Toast.LENGTH_SHORT).show();
      } else {
        // this will enable the local participant webcam
        meeting.enableWebcam();
        Toast.makeText(MeetingActivity.this, "Webcam Enabled", Toast.LENGTH_SHORT).show();
      }
      webcamEnabled=!webcamEnabled;
    });

    // leave meeting
    findViewById(R.id.btnLeave).setOnClickListener(view -&gt; {
      // this will make the local participant leave the meeting
      meeting.leave();
    });
  }
}</code></pre><h3 id="step-4-handling-the-participants-view">Step 4: Handling the Participants' View</h3><p>To display a list of participants in your video UI, we'll utilize a <code>RecyclerView</code>.</p><p><strong>(a)</strong> This involves creating a new layout for the participant view named <code>item_remote_peer.xml</code> in the <code>res/layout</code> folder. You can copy <code>item_remote_peer.xml </code>file from <a href="https://github.com/videosdk-live/quickstart/blob/main/android-rtc/Videosdk_android_kotlin_quickstart/app/src/main/res/layout/item_remote_peer.xml">here</a>.</p><p><strong>(b)</strong> Create a RecyclerView adapter <code>ParticipantAdapter</code> which will be responsible for displaying the participant list. Within this adapter, define a <code>PeerViewHolder</code> class that extends <code>RecyclerView.ViewHolder</code>.</p><pre><code class="language-Java">public class ParticipantAdapter extends RecyclerView.Adapter&lt;ParticipantAdapter.PeerViewHolder&gt; {

  @NonNull
  @Override
  public PeerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
      return new PeerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_remote_peer, parent, false));
  }

  @Override
  public void onBindViewHolder(@NonNull PeerViewHolder holder, int position) {
  }

  @Override
  public int getItemCount() {
      return 0;
  }

  static class PeerViewHolder extends RecyclerView.ViewHolder {
    // 'VideoView' to show Video Stream
    public VideoView participantView;
    public TextView tvName;
    public View itemView;

    PeerViewHolder(@NonNull View view) {
        super(view);
        itemView = view;
        tvName = view.findViewById(R.id.tvName);
        participantView = view.findViewById(R.id.participantView);
    }
  }
}</code></pre><p><strong>(c)</strong> Now, we will render a list of <code>Participant</code> for the meeting. We will initialize this list in the constructor of the <code>ParticipantAdapter</code></p><pre><code class="language-Java">public class ParticipantAdapter extends RecyclerView.Adapter&lt;ParticipantAdapter.PeerViewHolder&gt; {

  // creating a empty list which will store all participants
  private final List&lt;Participant&gt; participants = new ArrayList&lt;&gt;();

  public ParticipantAdapter(Meeting meeting) {
    // adding the local participant(You) to the list
    participants.add(meeting.getLocalParticipant());

    // adding Meeting Event listener to get the participant join/leave event in the meeting.
    meeting.addEventListener(new MeetingEventListener() {
      @Override
      public void onParticipantJoined(Participant participant) {
        // add participant to the list
        participants.add(participant);
        notifyItemInserted(participants.size() - 1);
      }

      @Override
      public void onParticipantLeft(Participant participant) {
        int pos = -1;
        for (int i = 0; i &lt; participants.size(); i++) {
          if (participants.get(i).getId().equals(participant.getId())) {
            pos = i;
            break;
          }
        }
        // remove participant from the list
        participants.remove(participant);

        if (pos &gt;= 0) {
          notifyItemRemoved(pos);
        }
      }
    });
  }

  // replace getItemCount() method with following.
  // this method returns the size of total number of participants
  @Override
  public int getItemCount() {
    return participants.size();
  }
  //...
}</code></pre><p><strong>(d)</strong> We have listed our participants. Let's set up the view holder to display a participant video.</p><pre><code class="language-Java">public class ParticipantAdapter extends RecyclerView.Adapter&lt;ParticipantAdapter.PeerViewHolder&gt; {

  // replace onBindViewHolder() method with following.
  @Override
  public void onBindViewHolder(@NonNull PeerViewHolder holder, int position) {
    Participant participant = participants.get(position);

    holder.tvName.setText(participant.getDisplayName());

    // adding the initial video stream for the participant into the 'VideoView'
    for (Map.Entry&lt;String, Stream&gt; entry : participant.getStreams().entrySet()) {
      Stream stream = entry.getValue();
      if (stream.getKind().equalsIgnoreCase("video")) {
        holder.participantView.setVisibility(View.VISIBLE);
        VideoTrack videoTrack = (VideoTrack) stream.getTrack();
        holder.participantView.addTrack(videoTrack)
        break;
      }
    }
    // add Listener to the participant which will update start or stop the video stream of that participant
    participant.addEventListener(new ParticipantEventListener() {
      @Override
      public void onStreamEnabled(Stream stream) {
        if (stream.getKind().equalsIgnoreCase("video")) {
          holder.participantView.setVisibility(View.VISIBLE);
          VideoTrack videoTrack = (VideoTrack) stream.getTrack();
          holder.participantView.addTrack(videoTrack)
        }
      }

      @Override
      public void onStreamDisabled(Stream stream) {
        if (stream.getKind().equalsIgnoreCase("video")) {
          holder.participantView.removeTrack();
          holder.participantView.setVisibility(View.GONE);
        }
      }
    });
  }
}</code></pre><p><strong>(e)</strong> Now, add this adapter to the <code>MeetingActivity</code></p><pre><code class="language-Java">@Override
protected void onCreate(Bundle savedInstanceState) {
  //Meeting Setup...
  //...
  final RecyclerView rvParticipants = findViewById(R.id.rvParticipants);
  rvParticipants.setLayoutManager(new GridLayoutManager(this, 2));
  rvParticipants.setAdapter(new ParticipantAdapter(meeting));
}</code></pre><h2 id="active-speaker-integration">Active speaker Integration</h2><p>The active speaker highlight feature aims to visually indicate the participant currently speaking in the video call. This functionality is especially valuable in scenarios with a large number of participants, where it can be difficult to identify the source of the incoming audio.</p><p>This is how we can integrate this feature with VideoSDK. Every time a participant actively speaks during the meeting, the <code><a href="https://docs.videosdk.live/android/api/sdk-reference/meeting-class/meeting-event-listener-class#onspeakerchanged">onSpeakerChanged</a></code> event is triggered. This event transmits the participant ID of the person who is currently speaking.</p><p>By capturing this event and leveraging the participant ID, you can visually highlight the corresponding participant in your application's user interface. This can be achieved by modifying the user interface element that represents the speaking participant, such as changing the background color or adding a visual indicator.</p><pre><code class="language-Java">private final MeetingEventListener meetingEventListener = new MeetingEventListener() {
    @Override
    public void onSpeakerChanged(String participantId) {
        Toast.makeText(MainActivity.this, "Active Speaker participantId" + participantId, Toast.LENGTH_SHORT).show();
        super.onSpeakerChanged(participantId);
    }
};</code></pre><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/03/Screenshot_20240319_181033_Android-VideoSDK-App--2--1.jpg" class="kg-image" alt="How to Integrate Active Speaker in Android(Java) Video Chat App?" loading="lazy" width="396" height="800"/></figure><p>To implement the dynamic speaker detection UI featured in the above image, feel free to check out our <a href="https://github.com/videosdk-live/videosdk-rtc-android-java-sdk-example">GitHub repository</a>.</p><h2 id="conclusion"><strong>Conclusion</strong></h2><p>This expert guide has provided Android developers with complete instructions on how to implement active speaker highlighting in their video apps using VideoSDK. By visually indicating the active speaker, you can reduce confusion and improve engagement among participants.</p><p>To unlock the full potential of VideoSDK and create easy-to-use video experiences, developers are encouraged to sign up for VideoSDK and further explore its features. Start implementing Active Speaker Highlighting today to improve your video app functionality and user engagement.</p><p><a href="https://www.videosdk.live/signup"><strong>Sign up with VideoSDK</strong></a> today and Get <strong>10000 Free Minutes </strong>to<strong> </strong>take your video app to the next level!</p>]]></content:encoded></item><item><title><![CDATA[What is Liveness Detection and How it Works? Complete Guide]]></title><description><![CDATA[Understand the importance of liveness detection, its working principles, active and passive detection methods, applications in finance and healthcare, and how its real-time analysis and AI integration are revolutionizing identity verification and fraud prevention.]]></description><link>https://www.videosdk.live/blog/what-is-liveness-detection</link><guid isPermaLink="false">66d6d6fe20fab018df10fea7</guid><category><![CDATA[Liveness Detection]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Sun, 19 Jan 2025 11:01:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-Liveness-Detection_-and-How-it-Works_.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>Liveness detection verifies that a biometric sample comes from a live person, not a photo, mask, replay video, or deepfake. Algorithms analyze movement, skin texture, depth maps, and challenge-response actions to defeat presentation attacks during identity checks. Banks, healthcare platforms, and remote onboarding flows use liveness detection to meet KYC rules and block synthetic identity fraud.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-Liveness-Detection_-and-How-it-Works_.jpg" alt="What is Liveness Detection and How it Works? Complete Guide"/><p>A fraudster holding a printed photo in front of a selfie camera can pass a basic face match in seconds. A deepfake video loop defeats naive "blink to verify" prompts if your pipeline never validates server-side timing. Liveness detection exists because matching a face to an ID document is not enough when the face itself can be faked. This article defines liveness detection, explains how presentation attack detection algorithms work, compares active and passive methods, and covers the production decisions that separate a compliant video KYC flow from a checkbox that fraudsters bypass.</p><h2 id="what-is-liveness-detection">What Is Liveness Detection?</h2><p>Liveness detection is defined as a biometric security process that determines whether a presented face, fingerprint, voice sample, or iris scan originates from a physically present live subject rather than a spoof artifact such as a photograph, video replay, 3D mask, or synthetic deepfake.</p><p>Liveness detection works by analyzing signals that are difficult to reproduce in fake media: involuntary micro-movements, skin texture at pixel level, depth geometry from structured light or stereo cameras, and responses to randomized challenge prompts. The output is a liveness score or pass/fail decision that gates downstream identity verification steps such as document OCR, database checks, and account activation.</p><p>Presentation Attack Detection (PAD), standardized under <a href="https://www.iso.org/standard/79520.html" rel="noreferrer">ISO/IEC 30107-3</a>, is the technical discipline behind liveness detection. A PAD system classifies biometric captures into bona fide (live) or attack (spoof) presentations. NIST evaluates vendor PAD performance through the <a href="https://www.nist.gov/programs-projects/face-recognition-vendor-test-frvt" rel="noreferrer">Face Recognition Vendor Test (FRVT)</a> Presentation Attack Detection track, publishing Attack Presentation Classification Error Rate (APCER) and Bona Fide Presentation Classification Error Rate (BPCER) metrics that teams use to compare solutions.</p><p>Liveness detection differs from simple face recognition. Face recognition answers "who is this person?" Liveness detection answers "is this person physically present right now?" Production identity systems run both checks in sequence because a correct identity match on a spoofed face is still fraud.</p><p>This section established the definitional boundary between liveness detection, presentation attack detection, and face recognition.</p><h2 id="why-is-liveness-detection-important">Why is Liveness Detection Important?</h2><p>Liveness detection is a regulatory requirement for remote customer onboarding in banking, telecom, and government digital services because static biometric matching cannot stop presentation attacks at scale.</p><p>Regulators increasingly mandate live verification during <a href="https://www.videosdk.live/blog/rbi-compliance-for-video-kyc" rel="noreferrer">digital KYC</a>. The <a href="https://www.rbi.org.in/commonman/english/scripts/notification.aspx?id=2607" rel="noreferrer">Reserve Bank of India's Master Direction on KYC</a> requires live capture of customer images during <a href="https://www.videosdk.live/blog/video-based-identification-procedure-vbip" rel="noreferrer">Video Customer Identification Process (V-CIP)</a> for remote bank account opening. The European Union eIDAS framework sets assurance levels for remote identity proofing where liveness checks support higher LoA (Level of Assurance) ratings. In the United States, state biometric privacy laws such as Illinois BIPA require informed consent and retention limits when facial geometry is collected, making liveness audit trails part of legal defensibility.</p><p>The fraud economics make passive face matching alone unsustainable. According to <a href="https://javelinstrategy.com/research/2024-identity-fraud-study-resolving-shattered-identity-crisis" rel="noreferrer">Javelin Strategy and Research's 2024</a> Identity Fraud Study, total identity fraud losses in the United States reached $23 billion. A significant share involves synthetic identities and document fraud during remote onboarding, precisely the attack surface liveness detection targets.</p><p>Beyond compliance, liveness detection protects operational trust. Telehealth platforms use video liveness to confirm the correct patient joined a session. HR tech vendors verify remote job applicants before background checks. Insurance carriers confirm claimants during virtual damage assessments. Each scenario shares the same failure mode: a spoofed biometric breaks the chain of trust that the entire session depends on.</p><p>In practice, engineering teams that ship <a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">video KYC</a> without server-side liveness validation report higher chargeback rates and manual review queues within the first quarter of launch. Liveness is not a UX inconvenience. It is the control that keeps automated onboarding from becoming automated fraud intake.</p><p>This section covered why regulators, fraud trends, and operational risk all require liveness checks beyond basic biometrics.</p><h2 id="how-does-liveness-detection-work">How Does Liveness Detection Work?</h2><p>Liveness detection works through a layered pipeline that captures biometric video, extracts anti-spoofing features, scores presentation attack probability, and returns a pass/fail decision before identity matching proceeds.</p><h3 id="capture-layer">Capture Layer</h3><p>The capture layer acquires face video through a device camera, often inside a mobile SDK or browser WebRTC session. Quality checks run first: face centering, lighting thresholds, blur detection, and minimum resolution. Poor captures are rejected before liveness scoring to avoid false rejections caused by bad input rather than spoofing.</p><h3 id="feature-extraction">Feature Extraction</h3><p>Algorithms extract features that distinguish live skin from printed or displayed faces. Common signals include:</p><ul><li><strong>Texture analysis:</strong>&nbsp;Live skin shows micro-texture patterns that printers and LCD screens smooth out.</li><li><strong>Depth and geometry:</strong>&nbsp;Structured light, time-of-flight sensors, or stereo cameras build 3D face maps. Flat photos fail depth consistency checks.</li><li><strong>Motion analysis:</strong>&nbsp;Micro-expressions, pulse-driven color shifts (rPPG), and natural head movement patterns differ from rigid mask or screen movement.</li><li><strong>Reflection and moiré detection:</strong>&nbsp;Screen replays produce refresh-rate banding and unnatural glare in corneal reflections.</li></ul><h3 id="challenge-response-active-path">Challenge-Response (Active Path)</h3><p>In active liveness, the system issues randomized prompts: turn head left, smile, read a four-digit number, or follow an on-screen dot. The server validates that the response sequence, timing, and motion trajectory match a live human performing the instruction in real time. Pre-recorded videos fail when challenges are randomized per session.</p><h3 id="scoring-and-decision">Scoring and Decision</h3><p>A PAD classifier outputs a liveness confidence score. Teams set thresholds trading Attack Presentation Classification Error Rate (APCER) against Bona Fide Presentation Classification Error Rate (BPCER). Stricter thresholds block more spoofs but increase false rejections for legitimate users in low-light or older-device conditions.</p><p>Server-side validation is non-negotiable for production. Client-only liveness checks are vulnerable to API tampering, virtual camera injection, and modified app binaries. The authoritative decision must run on infrastructure you control, fed by a that delivers tamper-resistant media streams.</p><p>This section walked through capture, feature extraction, challenge-response, and server-side scoring as the core liveness pipeline.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-8--2026--07_19_50-PM.png" class="kg-image" alt="What is Liveness Detection and How it Works? Complete Guide" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">How liveness detection works step by step flowchart</span></figcaption></img></figure><h2 id="what-is-active-passive-liveness-detection">What is Active &amp; Passive Liveness Detection?</h2><h3 id="active-liveness-detection">Active Liveness Detection</h3><p>The active liveness detection method involves user interaction, asking the user to perform specific actions like blinking, smiling, nodding, or turning their head. It verifies liveness by checking if these actions are performed correctly and in real time. This method is considered more robust against spoofing attacks.</p><h3 id="passive-liveness-detection">Passive Liveness Detection</h3><p>This Passive Liveness Detection method does not require user interaction and uses signals from the captured biometric data to determine liveness. Techniques include analyzing texture (e.g. <a href="https://www.ijsr.net/archive/v2i5/IJSROFF2013212.pdf">skin texture analysis</a>), checking for reflections in eyes, or detecting micro-movements like subtle changes in facial expression. It relies on AI and machine learning models designed with <a href="https://www.chromatix.com.au/ai/why-ai-might-not-be-sustainable/" rel="noreferrer">sustainable intelligence</a> to accurately identify patterns associated with real human features while optimizing efficiency and resource use.</p><h2 id="use-of-liveness-detection">Use of Liveness Detection</h2><ul><li><strong>Financial Services: </strong>To secure transactions and prevent identity fraud in services like mobile banking and ATM access, the use of video liveness detection become very important factor.</li><li><strong>Digital Onboarding:</strong> For verifying identities during online registration processes, especially in remote setups. Video solutions are used to perform live liveness checks during the onboarding process for banks, telecom providers, and HR tech services that require identity verification.</li><li><strong>Healthcare:</strong> In telehealth, video liveness detection ensures that the right patient or healthcare provider is involved in a session, maintaining the integrity of virtual consultations.</li></ul><h2 id="what-spoofing-attacks-does-liveness-detection-stop">What Spoofing Attacks Does Liveness Detection Stop?</h2><p>Liveness detection stops presentation attacks where an impostor presents a fake biometric sample to a sensor, including print attacks, screen replays, 3D masks, injection attacks, and generative deepfakes.</p><p>Understanding attack types determines which liveness layer your product needs. Shallow articles list "photo and video" without naming the production attack classes NIST PAD evaluations actually test.</p><h3 id="print-and-screen-replay-attacks">Print and Screen Replay Attacks</h3><p>Print attacks use photographs or document scans held in front of a camera. Screen replay attacks display a video of the genuine user on a phone or monitor. Basic texture and moiré detection catch most print and screen attacks. Active challenge-response defeats replay when the displayed video cannot respond to a server-generated random prompt issued after capture starts.</p><h3 id="3d-mask-and-silicone-face-attacks">3D Mask and Silicone Face Attacks</h3><p>High-quality silicone masks replicate skin texture and depth. Depth-sensing cameras and multi-frame motion analysis detect unnatural rigidity and lack of micro-expression. These attacks are expensive to produce, so they target high-value accounts rather than mass signup flows.</p><h3 id="virtual-camera-and-injection-attacks">Virtual Camera and Injection Attacks</h3><p>Injection attacks feed synthetic video directly into the application pipeline, bypassing the physical camera. Attackers use virtual camera drivers, browser DevTools media overrides, or modified mobile apps to inject pre-recorded or real-time deepfake streams. Client-side liveness alone cannot stop injection. Production systems validate session integrity through secure WebRTC channels, device attestation where available, and server-side frame provenance checks.</p><h3 id="deepfake-and-generative-ai-attacks">Deepfake and Generative AI Attacks</h3><p>Generative adversarial models produce synthetic faces that pass casual inspection. According to <a href="https://www.enisa.europa.eu/publications/enisa-threat-landscape-2025" rel="noreferrer">ENISA's 2025 threat landscape report on deepfake threats</a>, synthetic media attacks against remote identity verification are an escalating risk for online onboarding systems. PAD models trained on generative attack datasets, combined with active randomized challenges, provide the current industry defense stack.</p><p>This section mapped the four major presentation attack categories to the liveness techniques that defeat each one.</p><h2 id="how-can-videosdk-be-useful-in-liveness-detection">How can VideoSDK be useful in Liveness Detection?</h2><p>Video solutions play a significant role in enhancing liveness detection algorithms by providing dynamic, real-time data that can be analyzed to verify the authenticity of a user's identity. Here’s how <a href="https://www.videosdk.live/">VideoSDK’s</a> latest Infratech contributes to liveness detection:</p><h3 id="1-real-time-analysis">1. <strong>Real-Time Analysis</strong></h3><p>VideoSDK enables the real-time monitoring of facial movements and expressions, helping algorithms to analyze subtle, involuntary actions such as blinking, head tilting, and micro-expressions. These movements are difficult to replicate in static images or pre-recorded videos, thus helping to distinguish between a live person and a spoof attempt.</p><h3 id="2-3d-depth-and-movement-analysis"><strong>2. 3D Depth and Movement Analysis</strong></h3><p>VideoSDK can capture depth information and analyze movements, providing a way to distinguish between 2D representations (like photos or screens) and real 3D faces. This is achieved using stereoscopic cameras or depth-sensing technologies in advanced video solutions.</p><h3 id="3-enhanced-texture-and-depth-analysis">3. <strong>Enhanced Texture and Depth Analysis</strong></h3><p>VideoSDK can improve texture analysis by capturing a range of lighting conditions and angles, which can reveal unique skin textures and other characteristics of a live face. Additionally, advanced depth-sensing technologies can create a 3D map of the face from video data, further distinguishing between real and fake representations.</p><h3 id="4-challenge-response-interactions">4. <strong>Challenge-Response Interactions</strong></h3><p>VideoSDK can facilitate interactive liveness checks, where the system prompts users to perform specific actions, such as moving their heads or making facial expressions. This interactive element ensures that the subject is engaging in real-time, providing a robust verification process that is harder to spoof.</p><h3 id="5-integration-with-ai-and-machine-learning">5. <strong>Integration with AI and Machine Learning</strong></h3><p>VideoSDK data can be used to train machine learning models that improve the accuracy of liveness detection. By analyzing portions of video footage, these models can learn to identify subtle differences between real and fake faces, enhancing the overall security of biometric systems.</p><h3 id="6-compliance-and-audit-trails"><strong>6. Compliance and Audit Trails:</strong></h3><p>VideoSDK provides recordings for a verifiable audit trail of the liveness check, which is valuable for compliance purposes in regulated industries. This ensures that organizations can demonstrate adherence to security standards and regulations.</p><p>Leveraging the dynamic capabilities of VideoSDK, liveness detection becomes more robust, user-friendly, and effective in preventing fraudulent activities, thereby safeguarding both users and service providers.</p><h2 id="what-are-the-major-challenges-in-liveness-detection">What are the Major Challenges in Liveness Detection?</h2><ul><li><strong>Accuracy:</strong> Balancing between high accuracy and low false rejection rates can be difficult, especially in diverse lighting conditions or with various skin tones.</li><li><strong>Spoofing Attacks:</strong> As technology advances, so do the methods to trick liveness detection systems, that's why it requires continuous improvement and updates.</li><li><strong>User Experience:</strong> Active liveness checks can sometimes be intrusive or cumbersome, affecting user satisfaction.</li></ul><p>If you are considering integrating liveness detection in your system or want to build a new tech stack to reduce spoofing and deepfake, VideoSDk is the leading enterprise-grade Infratech solution, which provides the best and most accurate liveness detection system. VideoSDK enhances security and reliability for sure and provides an additional layer of protection against fraudulent attempts. </p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-liveness-detection-1">What is liveness detection?</h3><p>Liveness detection is a biometric security process that confirms a presented face, fingerprint, or voice sample comes from a live physically present person rather than a photo, mask, screen replay, or deepfake. It works by analyzing texture, depth, motion, and challenge-response behavior to classify biometric captures as bona fide or spoofed. Financial services, healthcare, and remote onboarding platforms use liveness detection to meet KYC regulations and block presentation attacks.</p><h3 id="how-does-liveness-detection-work-1">How does liveness detection work?</h3><p>Liveness detection works by capturing biometric video, extracting anti-spoofing features such as skin texture and depth geometry, optionally prompting the user with randomized challenges, and scoring the capture with a Presentation Attack Detection model on server infrastructure. The system returns a pass/fail decision or confidence score that gates subsequent identity matching and document verification steps. Server-side scoring is required because client-only checks are vulnerable to tampering.</p><h3 id="what-is-the-difference-between-active-and-passive-liveness-detection">What is the difference between active and passive liveness detection?</h3><p>The difference between active and passive liveness detection is that active liveness requires users to perform prompted actions like head turns or blinks, while passive liveness analyzes a single frame or short clip without visible instructions. Active liveness provides stronger spoof resistance for high-risk financial onboarding. Passive liveness reduces user friction for low-risk consumer signup flows. Most regulated V-CIP implementations use active liveness or a combination of both.</p><h3 id="can-liveness-detection-stop-deepfakes">Can liveness detection stop deepfakes?</h3><p>Liveness detection stops many deepfake attacks when systems use server-randomized active challenges, continuously retrained PAD models, and injection-resistant video transport. Pre-rendered deepfakes fail active challenges that request unpredictable movements after capture begins. Advanced real-time deepfake injection remains an active threat, which is why ENISA and NIST recommend combining liveness checks with document verification, device attestation, and ongoing fraud monitoring.</p><h3 id="is-liveness-detection-required-for-kyc">Is liveness detection required for KYC?</h3><p>Liveness detection is required for remote video KYC in jurisdictions that mandate live customer presence during digital onboarding. India's RBI V-CIP rules require live capture and interaction during video KYC for bank account opening. The EU eIDAS framework references liveness as part of higher-assurance remote identity proofing. Requirements vary by country, industry, and risk tier, so compliance teams must map local regulations before launch.</p><h3 id="what-is-presentation-attack-detection-pad">What is Presentation Attack Detection (PAD)?</h3><p>Presentation Attack Detection (PAD) is the technical field and ISO/IEC 30107 standard framework for detecting biometric spoofing attempts. PAD systems measure Attack Presentation Classification Error Rate (APCER) and Bona Fide Presentation Classification Error Rate (BPCER) to quantify how often spoofs pass and live users fail. Liveness detection is the user-facing application of PAD in identity verification products.</p><h3 id="how-do-you-choose-a-liveness-detection-provider">How do you choose a liveness detection provider?</h3><p>Choose a liveness detection provider by evaluating PAD benchmark scores from NIST FRVT, ISO/IEC 30107 compliance testing, APCER/BPCER performance on your target device population, and integration fit with your real-time video infrastructure. Pair a certified PAD engine with a video SDK that supports challenge-response orchestration, encrypted session recording, and server-side validation. Test against your own red-team attack library before production launch, not only vendor marketing claims.</p>]]></content:encoded></item><item><title><![CDATA[Top 10 Agora Alternatives in 2026]]></title><description><![CDATA[Discover a powerful Agora alternative that will revolutionize your online experience. Maximize your potential and take control of your success today.]]></description><link>https://www.videosdk.live/blog/agora-alternative</link><guid isPermaLink="false">64a3ecfc8ecddeab7f17f4ad</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Sun, 19 Jan 2025 05:16:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2023/07/Agora-alternative-1.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2023/07/Agora-alternative-1.jpg" alt="Top 10 Agora Alternatives in 2026"/><p>Looking for an <a href="https://www.videosdk.live/alternative/agora-vs-videosdk" rel="noreferrer"><strong>Agora alternative</strong></a> to seamlessly integrate real-time video into your application? Chances are you've come across Agora. Established in 2013, Agora was among the pioneers in developing a developer platform that offers broadcast, voice, and video calls for mobile and web applications through its software development kit (SDK).</p><p>While Agora's platform was groundbreaking during the early 2010s, it has fallen behind in releasing significant updates over the years, leaving room for innovative platforms like <a href="https://www.videosdk.live">VideoSDK</a> to provide a refreshing approach to live video.</p><p>PS: If you happen to be an Agora customer, I encourage you to keep reading to discover what you might be missing out on by sticking with the platform.</p><h2 id="choosing-the-right-agora-alternative">Choosing the Right Agora Alternative</h2>
<p>Undoubtedly, live video is challenging, and <a href="https://www.videosdk.live/blog/agora-competitors">Agora</a> only adds to the complexity. Merely building a basic live experience in your app with Agora requires integrating and paying for the various SDKs it offers. Therefore, when searching for an alternative live video solution, keep an eye out for the following:</p><h3 id="prioritize-customization">Prioritize Customization</h3>
<p>In an <strong>Agora alternative</strong>, prioritize customization. Choose an SDK that gives developers full control over the user interface (UI) and overall experience. Look for low-code prebuilt UI options to speed up initial setup, saving time and effort. Striking a balance between customization and user-friendly prebuilt options enables you to create a unique and engaging live video experience without extensive development. Customization ensures the alternative SDK meets your specific requirements, delivering a personalized and seamless solution.</p><h3 id="demand-high-adaptive-bitrate">Demand High Adaptive Bitrate</h3>
<p>Look for an <strong>alternative SDK</strong> that offers high <a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer">adaptive bitrate</a> technology, especially if your platform supports features like video translation, where maintaining consistent stream quality is essential for accurate and seamless user experiences. This ensures that your live video streams are optimized for different network conditions, providing a smooth and uninterrupted viewing experience for your users. Adaptive bitrate automatically adjusts the stream quality based on available bandwidth, resulting in optimal video quality without buffering or interruptions.</p><h3 id="comprehensive-single-sdk">Comprehensive Single SDK</h3>
<p>Building a live service in your application shouldn't necessitate mixing and matching dozens of SDKs. Instead, opt for a comprehensive single SDK that offers everything you require, from video calling to voice calling, streaming, and beyond.</p><h3 id="open-source-and-third-party-integrations">Open Source and Third-Party Integrations</h3>
<p>Consider whether open-source solutions like Jitsi provide the flexibility and transparency needed for your project. Additionally, assess the SDK’s compatibility with third-party tools for enhanced functionality and media management.</p><h3 id="transparent-pricing">Transparent Pricing</h3>
<p>It is crucial to consider the pricing structure of the <strong>alternative SDK</strong>. Look for a solution that offers transparent and competitive pricing, without hidden fees or additional costs. Ideally, the SDK should provide built-in collaboration features, eliminating the need for integrating multiple SDKs separately. This not only simplifies the development process but also helps to optimize costs by offering all the necessary features in one package.</p><h3 id="comprehensive-single-sdk">Comprehensive Single SDK</h3>
<p>Building a live service in your application shouldn't necessitate mixing and matching dozens of SDKs. Instead, opt for a comprehensive single SDK that offers everything you require, from video calling to voice calling, streaming, and beyond.</p><p>With that in mind, let's delve into this guide, where we'll explore the leading players that deserve your consideration in the video SDK market.</p><p><strong>Agora alternatives</strong> are available to overcome issues like Customization, Network Management, Collaborative Features, Pricing, Security, and Customer support.</p><p>The top 10 Agora Alternatives are VideoSDK, Jitsi, Twilio, EnableX, Zoom Video SDK, TokBox OpenTok [Vonage], Whereby, AWS Chime, Daily, and SignalWire. These alternatives and competitors offer a variety of features, pricing choices, and more, enabling you to make an informed choice according to your specific requirements.</p><blockquote>
<h2 id="top-10-alternatives-to-agora-2026">Top 10 Alternatives to Agora 2026</h2>
<ul>
<li>VideoSDK</li>
<li>Jitsi</li>
<li>Twilio</li>
<li>Enablex</li>
<li>Zoom Video SDK</li>
<li>TokBox Opentok [Vonage]</li>
<li>Whereby</li>
<li>AWS Chime</li>
<li>Daily</li>
<li>SignalWire</li>
</ul>
</blockquote>
<p>These alternatives and competitors offer a variety of features, pricing choices, and more, enabling you to make an informed choice according to your specific requirements.</p><h3 id="1-videosdk">1. VideoSDK</h3>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-SDK-for-Real-time-Communication-Live-Streaming-Video-API.jpeg" class="kg-image" alt="Top 10 Agora Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><ul><li><a href="https://www.videosdk.live">VideoSDK</a> provides an API that allows developers to easily add powerful, extensible, scalable, and resilient audio-video features to their apps with just a few lines of code. Add live audio and video experiences to any platform in minutes.</li><li>The key advantage of using Video SDK is it’s quite easy and quick to integrate, allowing you to focus more on building innovative features to enhance user retention.</li></ul><h4 id="detailed-features-of-videosdk">Detailed Features of VideoSDK</h4>
<ul><li><strong>High scalability</strong>: Video SDK’s high scalability with infinite room and zero maintenance ensures uninterrupted availability, and that too with &lt;99ms latency. It supports up to 300 attendees, including 50 presenters, and empowers large-scale collaborations. This advanced infrastructure enables global reach and success in the digital landscape.</li><li><strong>High adaptive bitrate</strong>: Video SDK offers high adaptive bitrate technology for an immersive audio-video experience. It auto-adjusts stream quality under bandwidth constraints and adapts to varying network conditions. With a global infrastructure and secure usage in restricted network environments, Video SDK delivers optimal performance and seamless streaming.</li><li><strong>End-to-end customized SDK</strong>: With their end-to-end customized SDK, you have the power to fully customize the UI to meet your unique needs. Their code samples help accelerate your time-to-market, while template layouts can be easily customized in any orientation. Leveraging their PubSub feature, you can build engaging and interactive features, enhancing the overall user experience.</li><li><strong>Quality Recordings</strong>: Experience high-quality recordings on any connection with Video SDK. Their solution supports 1080p video recording capability, ensuring crystal-clear and detailed footage. With programmable layouts and custom templates, you can tailor the recording experience to your specific requirements. Easily store your recordings in the Video SDK cloud or popular cloud storage providers such as AWS, GCP, or Azure. Access your recordings conveniently from the dashboard itself, providing seamless management and retrieval of your valuable content.</li><li><strong>Detailed analytics</strong>: Gain access to in-depth analytics on video call metrics, including participant interactions and duration, allowing you to analyze participant interest throughout the session.</li><li><strong>Cross-platform streaming</strong>: Stream live events to millions of viewers across platforms such as YouTube, LinkedIn, Facebook, and more with built-in <a href="https://www.videosdk.live/developer-hub/rtmp/rtmp-vs-srt" rel="noreferrer">RTMP</a> support.</li><li><strong>Seamless scaling</strong>: Effortlessly scale live audio/video within your web app, accommodating from just a few users to over 10,000 and reaching millions of viewers through RTMP output.</li><li><strong>Platform support</strong>: Build your live video app for a specific platform and seamlessly run it across browsers, devices, and operating systems with minimal development efforts.</li><li><strong>Mobile</strong>: Flutter, Android (Java/Kotlin), iOS (Objective-C/Swift), React Native </li><li><strong>Web</strong>: JavaScript Core SDK + UI Kit for React JS, Angular, Web Components for other frameworks </li><li><strong>Desktop</strong>: Flutter Desktop</li></ul><h4 id="videosdk-pricing">VideoSDK Pricing</h4>
<ul><li>Video SDK offers <a href="https://www.videosdk.live/pricing" rel="noreferrer">$20 free credit</a> that renew monthly. You only start paying once you exhaust the free minutes. </li><li>The best thing is, that pricing for video and audio calls is considered separately. Pricing for <strong>video calls</strong> begins at <strong>$0.002</strong> per participant per minute and for <strong>audio calls</strong>, it begins at <strong>$0.0006</strong> per participant per minute. </li><li>The additional cost for <strong>cloud recordings</strong> is <strong>$0.015</strong> per minute and <strong>RTMP output</strong> is <strong>$0.030</strong> per minute. You can estimate your costs using their <a href="https://www.videosdk.live/pricing#pricingCalc">pricing calculator</a>.</li><li>Video SDK provides free <strong>24/7</strong> support to all customers. Their dedicated team is available to assist you through your preferred communication channel whenever you need help with basic queries, upcoming events, or technical requirements.</li></ul><blockquote><strong>Here's a detailed comparison of  </strong><a href="https://www.videosdk.live/alternative/agora-vs-videosdk"><strong>Agora and Video SDK</strong></a><strong>.</strong></blockquote>
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Your Page Title</title>
	<!-- Include Tailwind CSS -->
	<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</link></meta></meta></head>

<body>
	<div class="relative w-full overflow-hidden rounded-2xl bg-gradient-to-b from-pink-700 to-purple-900 p-4 text-center shadow-xl">
		<h4 class="mx-auto text-3xl font-bold tracking-tight text-white sm:text-2xl" style="margin-top: 3px; margin-bottom: 12px;">
			Schedule a Demo with Our Live Video Expert!
		</h4>
		<p class="mx-auto mt-3 max-w-xl text-sm text-gray-400">
			Discover how VideoSDK can help you build a cutting-edge real-time video app.
			<span class="font-semibold text-lato"/>
		</p>
		<div class="mt-4 flex items-center justify-center">
			<a href="https://www.videosdk.live/contact" class="rounded-md bg-white px-8 py-3 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white" target="_blank" style="text-decoration: none;color: black;" data-faitracker-click-bind="true">
				Book a call
			</a>	
		</div>
		
	</div>
</body>

</html>
<!--kg-card-end: html-->
<h3 id="2-jitsi">2. Jitsi</h3>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Free-Video-Conferencing-Software-for-Web-Mobile-Jitsi.jpeg" class="kg-image" alt="Top 10 Agora Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>Jitsi is a collection of open-source projects that enable you to build and deploy video conferencing solutions within your applications. Their most well-known offerings are Jitsi Meet and Jitsi Videobridge.</p><p>Jitsi Meet is a JavaScript-based client application that facilitates video chatting. It allows you to share screens, collaborate in real time, invite users, and more. You can access the conference via a web browser or Android/iOS apps.</p><p>Jitsi Videobridge is an XMPP server (Prosody) capable of hosting large-scale video chats. It is WebRTC-compatible and provides default encryption.</p><h4 id="key-points-about-jitsi">Key points about Jitsi</h4>
<ul><li>Jitsi is free, open-source, and offers end-to-end encryption, giving you the ability to review and modify the code according to your requirements.</li><li>The live experience includes features such as active speakers, text chatting (web only), room locking, screen sharing, raise/lower hand, push-to-talk mode, audio-only option, and more.</li><li>However, certain essential features like shared text documents based on Etherpad, streaming, telephone dial-in to a conference, dial-out to a telephone participant, and more, only work if Jibri is configured.</li><li>Recording a call requires additional effort. You need to live stream your conference to YouTube and access the recording from there or set up Jibri for this purpose.</li><li>Obtaining support to resolve issues can take over 48 hours.</li><li>The tool does not automatically manage user bandwidth in the event of network instability, potentially resulting in a blank screen.</li></ul><h4 id="pricing-for-jitsi">Pricing for Jitsi</h4>
<ul><li><a href="https://www.videosdk.live/blog/jitsi-alternative"><strong>Jitsi</strong></a> is 100% open source and available for <strong>free</strong> usage and development.</li><li>However, you are responsible for setting up your own servers and creating the UI from scratch. Product support comes at an additional cost.</li></ul><blockquote><strong>Here's a detailed comparison of  </strong><a href="https://www.videosdk.live/agora-vs-jitsi"><strong>Agora and Jitsi</strong></a><strong>.</strong></blockquote><h3 id="3-twilio">3. Twilio</h3>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Communication-APIs-for-SMS-Voice-Video-Authentication_twilio.jpeg" class="kg-image" alt="Top 10 Agora Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>Twilio initially focused on automating phone calls and SMS services but has now expanded its offerings to provide developers with a range of APIs for building business communication across various channels.</p><p>Twilio allows you to either create an app from scratch or enhance an existing solution with communication features. The SDK supports multiple programming languages, including Java and Ruby.</p><h4 id="key-points-about-twilio">Key Points about Twilio</h4>
<ul><li>Twilio provides web, iOS, and Android SDKs. However, when utilizing multiple audio and video inputs, developers need to manually configure them, requiring additional code implementation.</li><li>In case a user's call drops or any issues arise during the call, Twilio offers call insights to track and analyze errors.</li><li>Twilio supports a maximum of 50 hosts within a call and a total of 50 participants, including hosts.</li><li>Twilio does not offer any plugins to simplify product development.</li><li>With the SDK, you will need to allocate engineering resources to handle hard coding for various edge cases that can potentially disrupt a user's video call.</li></ul><h4 id="pricing-for-twilio">Pricing for Twilio</h4>
<ul><li><a href="https://www.videosdk.live/blog/twilio-video-alternative"><strong>Twilio</strong></a>'s <a href="https://www.twilio.com/en-us/video/pricing">pricing</a> starts at <strong>$4</strong> per 1,000 minutes. </li><li>Additionally, there are costs associated with <strong>recordings</strong>, which amount to <strong>$0.004</strong> per participant minute, <strong>recording compositions</strong> priced at <strong>$0.01</strong> per composed minute, and <strong>storage</strong> fees of <strong>$0.00167</strong> per GB per day after the first 10 GBs.</li><li>Twilio's free support plan includes API status notifications and email support during business hours. </li><li>Users can opt for additional services such as 24/7 live chat support, a support escalation line, quarterly status reviews, and guaranteed response times at an extra cost. </li><li>The price for these services varies, usually based on a percentage of the monthly plan or a specific minimum amount (ranging from <strong>$250</strong>/month to <strong>$5,000</strong>/month).</li></ul><blockquote><strong>Here's a detailed comparison of  </strong><a href="https://www.videosdk.live/agora-vs-twilio"><strong>Agora and Twilio</strong></a><strong>.</strong></blockquote><h3 id="4-enablex">4. EnableX</h3>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-Call-API-Video-Chat-API-Voice-API-Video-Conferencing_enebleX.jpeg" class="kg-image" alt="Top 10 Agora Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>EnableX offers live video, voice, and messaging SDKs that serve as fundamental building blocks to expedite the development of live experiences in your applications. It primarily targets service providers, ISVs, SIs, and developers.</p><h4 id="key-points-about-enablex">Key points about EnableX</h4>
<ul><li>The SDK provides a video builder that allows you to implement a customized video-calling solution into your application. </li><li>Alternatively, you can create personalized live video streams with tailored UI, hosting capabilities, billing integration, and other essential functionalities. </li><li>The self-service portal grants you access to reporting features and live analytics, enabling you to monitor quality and facilitate online payments from clients. </li><li>The SDK supports a limited range of programming languages, including JavaScript, PHP, and Python. </li><li>It enables your users to stream live content directly from your app or website, as well as stream directly on platforms like YouTube or Facebook for unlimited reach. </li><li>Please note that the support team may take up to 72 hours to respond to your support requests. Integrating the SDK into your application may require several weeks. </li><li>The SDK does not optimize users' videos in the event of device or network issues.</li></ul><h4 id="enablex-pricing">EnableX pricing</h4>
<ul><li>The SDK is <a href="https://www.enablex.io/cpaas/pricing/our-pricing">priced</a> at <strong>$0.004</strong> per participant minute for up to <strong>50 participants</strong> per room. </li><li>For pricing involving over 50 participants, it is necessary to contact their sales team. </li><li>The <strong>recording</strong> is charged at <strong>$0.10</strong> per participant per minute, <strong>transcoding</strong> at <strong>$0.10</strong> per minute, and <strong>storage</strong> at <strong>$0.05</strong> per GB per month. </li><li><a href="https://www.videosdk.live/developer-hub/rtmp/custom-rtmp" rel="noreferrer"><strong>RTMP streaming</strong></a> incurs a cost of <strong>$0.10</strong> per minute.</li></ul><h3 id="5-zoom-video-sdk">5. Zoom Video SDK</h3>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-SDK-from-Zoom-Zoom.jpeg" class="kg-image" alt="Top 10 Agora Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>The Zoom Video SDK empowers developers to create customized live video-based applications utilizing the technology behind Zoom.</p><p>Zoom introduced the Video SDK as they recognized that the traditional Zoom client might not meet all customer requirements. By providing access to the underlying Zoom technology, customers can unlock additional benefits.</p><p>The SDK offers a comprehensive set of services, including video, audio, screen sharing, chat, data streams, and more. Developers have the flexibility to utilize all of these features or select specific ones based on their application's needs. Additionally, the Video SDK provides robust server-side APIs and webhooks.</p><h4 id="zoom-video-sdk-at-a-glance">Zoom Video SDK at a glance</h4>
<ul><li>With the Zoom Video SDK, you can build applications with customizable video compositions, supporting up to 1,000 co-hosts/participants per session. The SDK offers limited customization options for the live video itself. </li><li>It enables you to incorporate screen sharing, third-party live streaming, and in-session chat, while also providing control over the call's layout. </li><li>Zoom supports seven major languages and offers an open translation extensibility, facilitating international growth and enhancing user experience. The SDK only supports the predetermined roles of a host and participant. </li><li>This limitation may pose challenges for use cases that require customized permissions for peers. Unless you opt for paid support plans, you will receive slower email support. </li><li>The SDK provides partial assistance in managing user bandwidth consumption during network degradation.</li></ul><h4 id="zoom-video-sdk-pricing">Zoom Video SDK pricing</h4>
<ul><li><a href="https://www.videosdk.live/blog/zoom-video-sdk-alternative"><strong>Zoom</strong></a> provides 10,000 free minutes per month, and <a href="https://zoom.us/buy/videosdk">charges</a> apply only once you exceed this limit. Pricing starts at <strong>$0.31</strong> per user minute, with <strong>recordings</strong> available for <strong>$100</strong> per month for 1 TB of storage. Telephony services are priced at <strong>$100</strong> per month.</li><li>Zoom offers three customer support plans: <strong>Access</strong>, <strong>Premier</strong>, and <strong>Premier+</strong>. For detailed pricing information, it is necessary to contact Zoom directly.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/agora-vs-zoom"><strong>Agora and Zoom</strong></a><strong>.</strong></blockquote><h3 id="6-vonage-video-api-formerly-tokbox-opentok">6. Vonage Video API (Formerly TokBox OpenTok)</h3>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-API-Fully-Programmable-and-Customizable-Vonage.jpeg" class="kg-image" alt="Top 10 Agora Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>Vonage Video API is a viable option for creating customized video experiences in mobile, web, or desktop applications.</p><p>Opentok was established in 2008 when the company shifted its business strategy from providing a struggling consumer video conference product to offering the underlying technology. This allows companies to embed a video conference component into their websites.</p><p>In addition to live video, the API encompasses voice, messaging, and screen-sharing capabilities. It provides client libraries for web, iOS, Android, Windows, and Linux, along with server-side SDKs and a REST API.</p><h4 id="vonage-at-a-glance">Vonage at a glance</h4>
<ul><li>The SDK enables the creation of custom audio/video streams on mobile devices with various effects, filters, and AR/VR integration. </li><li>It supports use cases such as one-on-one video calls, group video chats, and large-scale broadcast sessions. </li><li>Calls can consist of video and voice, voice-only, or a combination. Participants in a call can share screens, exchange data, and chat with each other. </li><li>The SDK provides performance data for detailed session analysis through the account dashboard or via its insights API. </li><li>All voice, video, and signaling traffic is encrypted using AES-128 or AES-256 encryption. </li><li>Additionally, video recordings can be optionally encrypted with AES-256. The SDK complies with GDPR and HIPAA regulations. </li><li>It supports a maximum of 55 participants per call. The company offers chat-based support, which may take up to 72 hours to respond to your inquiries.</li><li>During a stream, you can have up to 2,000 concurrent room participants. The platform does not handle the live video backend, so you need to allocate resources to develop edge case management capabilities.</li></ul><h4 id="vonage-pricing">Vonage pricing</h4>
<ul><li> Vonage follows a usage-based <a href="https://www.vonage.com/communications-apis/video/pricing/">pricing</a> model, calculated dynamically for each minute based on the number of participants in a video session. </li><li>Plans start at <strong>$9.99</strong> per month, which includes free 2,000 minutes per month across all plans. </li><li>After exhausting the free minutes, pricing is set at <strong>$0.00395</strong> per participant minute. <strong>Recording</strong> starts at <strong>$0.10</strong> per minute, and <strong>HLS streaming</strong> is priced at <strong>$0.15</strong> per minute.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/agora-vs-vonage"><strong>Agora and Vonage</strong></a><strong>.</strong></blockquote><h3 id="7-whereby">7. Whereby</h3>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-Calling-API-for-Web-and-App-Developers-Whereby.jpeg" class="kg-image" alt="Top 10 Agora Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>Whereby offers browser-based meetings that can be accessed through a permanent room owned by each user. Guests can join meetings by simply clicking a link, without requiring any downloads or registrations. They have recently introduced a hybrid meeting solution for distributed teams, which reduces echo and eliminates the need for expensive meeting hardware.</p><h4 id="whereby-at-a-glance">Whereby at a glance</h4>
<ul><li>The tool allows you to customize the video interface by adding logos, colors, and buttons using their no-code interface editor. </li><li>However, the customization options are limited, and you cannot create a completely custom experience with Whereby. </li><li>It enables you to offer video calls seamlessly from your website, mobile apps, or other web products, without the need for external links or apps. </li><li>Whereby emphasizes data privacy and GDPR compliance. They do not mine or sell user data, and all content is encrypted. </li><li>The SDK provides basic collaborative features such as screen sharing, recording, picture-in-picture, and text chat. </li><li>However, it does not offer the ability to add more interactive elements through APIs. </li><li>The SDK does not automatically handle user-host publish-subscribe logic, requiring manual implementation on your end.</li></ul><h4 id="whereby-pricing">Whereby pricing</h4>
<ul><li>Whereby offers <a href="https://whereby.com/information/pricing">pricing</a> plans starting at <strong>$6.99</strong> per month, which includes up to 2,000 user minutes that renew monthly. </li><li><strong>Additional minutes</strong> are charged at <strong>$0.004</strong> per minute, and <strong>cloud recording</strong> and <strong>live streaming</strong> are available at <strong>$0.01</strong> per minute.</li><li><strong>Email</strong> and <strong>chat</strong> support are provided for <strong>free</strong> to all accounts. <strong>Technical onboarding</strong>, <strong>customer success manager</strong>, and <strong>HIPAA</strong> compliance options are available for <strong>enterprise plans</strong>.</li></ul><h3 id="8-aws-chime">8. AWS Chime</h3>
<p><a href="https://www.videosdk.live/blog/amazon-chime-sdk-alternative"><strong>AWS Chime</strong></a> is a video conferencing tool provided by Amazon Web Services, primarily designed for business users. It offers features such as VoIP calling, video messaging, and virtual meetings, allowing users to host or join remote meetings through the service.</p><h4 id="heres-an-overview-of-aws-chime">Here's an overview of AWS Chime</h4>
<ul><li>Conduct and attend online meetings with high-definition video, audio, dial-in numbers, and in-room video conference support.</li><li>Collaborative features include screen sharing, remote desktop control, and individual/group text-based chats.</li><li>Host team meetings with up to 250 participants, and manage meeting controls, recording, scheduling, delegate assignments, etc.</li><li>Enhanced security using AWS Identity and Access Management policies, enabling user administration, policy management, and SSO setup.</li><li>Supports audio recording in .m4a format and converts screen shares to video (.mp4). However, the attendee recording is not available.</li><li>Session analytics are not available unless you opt for the enterprise plan, which comes at a higher price.</li><li>Basic bandwidth management capabilities to handle minor disruptions in the user's network.</li><li>The platform does not provide edge case management capabilities, which means you are responsible for handling such scenarios.</li></ul><h4 id="aws-chime-pricing">AWS Chime pricing</h4>
<ul><li><strong>Basic Tier</strong>: <a href="https://aws.amazon.com/chime/pricing/"><strong>Free</strong></a>, includes <strong>one-on-one audio and video calls</strong> and <strong>group chat</strong>.</li><li><strong>Plus Tier</strong>: <strong>$2.50</strong> per user per month, includes all <strong>basic features</strong>, <strong>screen sharing</strong>, <strong>remote desktop control</strong>, <strong>1 GB message history per user</strong>, and <strong>Active Directory integration</strong>.</li><li><strong>Pro Tier</strong>: <strong>$15</strong> per user per month, includes all <strong>Plus features</strong>, allows <strong>scheduling and hosting</strong> meetings for three or more people (<strong>up to 100 attendees</strong>), <strong>meeting recording</strong>, <strong>Outlook integration</strong>, and more.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/agora-vs-amazon-chime-sdk"><strong>Agora and AWS Chime</strong></a><strong>.</strong></blockquote><h3 id="9-daily">9. Daily</h3>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/WebRTC-Video-Audio-APIs-for-Every-Developer-Daily.jpeg" class="kg-image" alt="Top 10 Agora Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>Daily is a platform that enables developers to build real-time video and audio calls that work directly in the browser. It provides SDKs and APIs to handle common backend video call use cases across different platforms.</p><h4 id="heres-an-overview-of-daily">Here's an overview of Daily</h4>
<ul><li>Two main approaches: <a href="https://www.videosdk.live/blog/daily-co-alternative"><strong>Daily</strong></a> Client SDKs allow developers to build custom UIs by interacting with Daily's core APIs. Daily Prebuilt is an embeddable video chat widget that can be added to any web app with fewer lines of code.</li><li>Collaborative features include HD screen sharing, breakout rooms, raise a hand, live transcription, whiteboard, and customizable text chat to enhance the user experience.</li><li>Prerecorded video can be embedded, interactive real-time calls can be hosted with up to 1,000 people, and live streaming to millions is possible with minimal latency. Real-time call data is available for debugging and optimization.</li><li>Mobile SDKs are currently in the beta phase of development, so their evolution and ability to solve specific use cases may vary.</li><li>Support response time can take up to 72 hours to resolve issues.</li><li>Users need to add their own publish-subscribe logic to manage live video interactions.</li><li>The platform does not have built-in edge case management capabilities.</li></ul><h4 id="daily-pricing">Daily pricing</h4>
<ul><li><strong>$0.004</strong> per participant minute, with free 10,000 minutes refreshed per month.</li><li>Additional charges for <strong>audio</strong> <strong>$0.00099 </strong>per<strong> </strong>user minute, <strong>streaming</strong> <strong>$0.0012 </strong>per<strong> </strong>minute, <strong>RTMP output</strong> <strong>$0.015 </strong>per minute, and <strong>recording</strong> <strong>$0.01349 </strong>per GB.</li><li><strong>Email</strong> and <strong>chat support</strong> are available for <strong>free</strong> for all accounts. </li><li><strong>Advanced support features</strong> are available through add-on packages starting from <strong>$250</strong> per month.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/agora-vs-daily"><strong>Agora and Daily</strong></a><strong>.</strong></blockquote><h3 id="10-signalwire">10. SignalWire</h3>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Building-The-Software-Defined-Telecom-Network-SignalWire.jpeg" class="kg-image" alt="Top 10 Agora Alternatives in 2026" loading="lazy" width="1920" height="967"/></figure><p>SignalWire is an API-driven platform that allows developers to integrate live and on-demand video experiences into their applications. It simplifies video encoding, delivery, and renditions, aiming to provide a seamless video streaming experience.</p><h4 id="heres-a-summary-of-signalwire">Here's a summary of SignalWire</h4>
<ul><li>The SDK enables developers to embed real-time video and live streams into their applications. It supports web, iOS, and Android SDKs for building applications with live video capabilities.</li><li>Each call supports up to 100 participants in a real-time <a href="https://www.videosdk.live/blog/webrtc">webRTC</a> environment with their video enabled.</li><li>The SDK does not include built-in support for managing video call disruptions or handling the publish-subscribe logic of meeting users. These aspects would need to be implemented separately.</li></ul><h4 id="signalwire-pricing">SignalWire pricing</h4>
<ul><li><a href="https://signalwire.com/pricing/video">Pricing</a> includes <strong>$0.0060</strong> per minute for <strong>HD</strong> and <strong>$0.012</strong> for a <strong>Full HD</strong> video call.</li><li>Additional features such as <strong>recording</strong> cost <strong>$0.0045</strong> per minute, and <strong>streaming</strong> is priced at <strong>$0.10</strong> per minute.</li></ul><h2 id="certainly">Certainly!</h2>
<p>While all the video conferencing SDKs mentioned offer various features and capabilities, <a href="https://www.videosdk.live">VideoSDK</a> stands out as an SDK that prioritizes a fast and seamless integration experience.</p><p>Video SDK offers a low-code solution that allows developers to quickly build live video experiences in their applications. With VideoSDK, it is possible to create and deploy custom video conferencing solutions in under 10 minutes, significantly reducing the time and effort required for integration.</p><p>Unlike other SDKs that may have longer integration times or limited customization options, <a href="https://www.videosdk.live">VideoSDK</a> aims to provide a streamlined process. By leveraging Video SDK, developers can create and embed live video experiences with ease, allowing users to connect, communicate, and collaborate in real-time.</p><h2 id="still-skeptical">Still skeptical?</h2>
<p>Take a deep dive into Video SDK's comprehensive <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">Quickstart guide</a> and immerse yourself in the possibilities with our <a href="https://docs.videosdk.live/code-sample">powerful sample app</a>, built exclusively for Video SDK.</p><p>Embark on your integration journey today and seize the opportunity to claim your <a href="https://www.videosdk.live/pricing">complimentary $20 free</a>, allowing you to unleash the full potential of Video SDK. And if you ever need assistance along the way, our dedicated team is just a click away, ready to support you.</p><p>Get ready and <a href="https://app.videosdk.live">sign up</a> to witness the remarkable experiences you can create using the extraordinary capabilities of Video SDK. Unleash your creativity and let the world see what you can build!</p>]]></content:encoded></item><item><title><![CDATA[How to Integrate Active Speaker in Android(Kotlin) Video Chat App?]]></title><description><![CDATA[In this article, we explore how to use VideoSDK to build active speaker highlighting in Android(Kotlin) video applications.]]></description><link>https://www.videosdk.live/blog/active-speaker-in-kotlin-video-chat-app</link><guid isPermaLink="false">65fbd25f2a88c204ca9ceb42</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Sat, 18 Jan 2025 16:20:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/Active-Speaker-Kotlin.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/Active-Speaker-Kotlin.jpg" alt="How to Integrate Active Speaker in Android(Kotlin) Video Chat App?"/><p>Imagine an active video conference with multiple participants. In group calls, it is important to identify the active speaker. By integrating <strong>Active Speaker Indication</strong> feature into your Android (Kotlin) video chat application, you can enhance the user experience by providing visual cues that highlight who is currently speaking.</p><p>This guide will cover everything through the step-by-step process of implementing active speaker signaling in your application using the VideoSDK. Available through VideoSDK, it transforms your Android video chat application by visually highlighting the currently speaking participant, ensuring a smooth and informative experience for your users during video calls.</p><h2 id="goals">Goals</h2><p>By the End of this Article:</p><ol><li>Create a <a href="https://app.videosdk.live/signup">VideoSDK account</a> and generate your VideoSDK auth token.</li><li>Integrate the VideoSDK library and dependencies into your project.</li><li>Implement core functionalities for video calls using VideoSDK</li><li>Enable active speaker indication</li></ol><h2 id="getting-started-with-videosdk">Getting Started with VideoSDK</h2><p>To take advantage of the active speaker highlighting functionality, we will need to use the capabilities that the VideoSDK offers. Before we dive into the implementation steps, let's make sure you complete the necessary prerequisites.</p><h3 id="create-a-videosdk-account">Create a VideoSDK Account</h3><p>Go to your <a href="https://app.videosdk.live/dashboard/">VideoSDK dashboard</a> and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.</p><h3 id="generate-your-auth-token">Generate your Auth Token</h3><p>Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token plays a crucial role in authorizing your application to use VideoSDK features.</p><p>For a more visual understanding of the account creation and token generation process, consider referring to the <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/authentication-and-token#1-generating-token-from-dashboard">provided tutorial</a>.</p><h3 id="prerequisites-and-setup">Prerequisites and Setup</h3><p>Make sure your development environment meets the following requirements:</p><ul><li>Java Development Kit is supported.</li><li>Android Studio version 3.0 or later.</li><li>Android SDK API level 21 or higher.</li><li>A mobile device with Android 5.0 or later version.</li></ul><h2 id="integrate-videosdk">Integrate VideoSDK</h2><p>Following the account creation and token generation steps, we'll guide you through the process of adding the VideoSDK library and other dependencies to your project. We'll also ensure your app has the required permissions to access features like audio recording, camera usage, and internet connectivity, all crucial for a seamless video experience.</p><h3 id="step-a-add-the-repositories-to-the-projects-settingsgradle-file">Step (a): Add the repositories to the project's <code>settings.gradle</code> file.</h3><pre><code class="language-kotlin">dependencyResolutionManagement {
  repositories {
    // ...
    google()
    mavenCentral()
    maven { url '&lt;https://jitpack.io&gt;' }
    maven { url "&lt;https://maven.aliyun.com/repository/jcenter&gt;" }
  }
}
</code></pre><h3 id="step-b-include-the-following-dependency-within-your-applications-buildgradle-file">Step (b): Include the following dependency within your application's <code>build.gradle</code> file:</h3><pre><code class="language-kotlin">dependencies {
  implementation 'live.videosdk:rtc-android-sdk:0.1.26'

  // library to perform Network call to generate a meeting id
  implementation 'com.amitshekhar.android:android-networking:1.0.2'

  // Other dependencies specific to your app
}
</code></pre><blockquote>If your project has set <code>android.useAndroidX=true</code>, then set <code>android.enableJetifier=true</code> in the <code>gradle.properties</code> file to migrate your project to AndroidX and avoid duplicate class conflict.</blockquote><h3 id="step-c-add-permissions-to-your-project">Step (c): Add permissions to your project</h3><p>In <code>/app/Manifests/AndroidManifest.xml</code>, add the following permissions after <code>&lt;/application&gt;</code>.</p><pre><code class="language-kotlin">&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
&lt;uses-permission android:name="android.permission.CAMERA" /&gt;
</code></pre><p>These permissions are essential for enabling core functionalities like audio recording, internet connectivity for real-time communication, and camera access for video streams within your video application.</p><h2 id="essential-steps-for-building-the-video-calling-functionality">Essential Steps for Building the Video Calling Functionality</h2><p>We'll now set up the functionalities that make your video application after setting up your project with VideoSDK. This section outlines the essential steps for implementing core functionalities within your app. This section will guide you through four key aspects.</p><h3 id="step-1-generate-a-meetingid">Step 1: Generate a <code>meetingId</code></h3><p>Now, we can create the <code>meetingId</code> from the VideoSDK's rooms API. You can refer to this <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/setup-call/initialize-meeting#generating-meeting-id">documentation</a> to generate meetingId.</p><h3 id="step-2-initializing-the-meeting">Step 2: Initializing the Meeting</h3><p>After getting <code>meetingId</code> , the next step involves initializing the meeting for that we need to,</p><ol><li>Initialize VideoSDK.</li><li>Configure <strong>VideoSDK</strong> with a token.</li><li>Initialize the meeting with required params such as <code>meetingId</code>, <code>participantName</code>, <code>micEnabled</code>, <code>webcamEnabled</code> and more.</li><li>Add <code>MeetingEventListener</code> for listening events such as Meeting Join/Left and Participant Join/Left.</li><li>Join the room with <code>meeting.join()</code> a method.</li></ol><p>Please copy the .xml file of the <code>MeetingActivity</code> from <a href="https://github.com/videosdk-live/quickstart/blob/main/android-rtc/Videosdk_android_kotlin_quickstart/app/src/main/res/layout/activity_meeting.xml">here</a>.</p><pre><code class="language-kotlin">class MeetingActivity : AppCompatActivity() {
  // declare the variables we will be using to handle the meeting
  private var meeting: Meeting? = null
  private var micEnabled = true
  private var webcamEnabled = true

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_meeting)

    val token = "" // Replace with the token you generated from the VideoSDK Dashboard
    val meetingId = "" // Replace with the meetingId you have generated
    val participantName = "John Doe"
    
    // 1. Initialize VideoSDK
    VideoSDK.initialize(applicationContext)

    // 2. Configuration VideoSDK with Token
    VideoSDK.config(token)

    // 3. Initialize VideoSDK Meeting
    meeting = VideoSDK.initMeeting(
      this@MeetingActivity, meetingId, participantName,
      micEnabled, webcamEnabled,null, null, false, null, null)

    // 4. Add event listener for listening upcoming events
    meeting!!.addEventListener(meetingEventListener)

    // 5. Join VideoSDK Meeting
    meeting!!.join()

    (findViewById&lt;View&gt;(R.id.tvMeetingId) as TextView).text = meetingId
  }

  // creating the MeetingEventListener
  private val meetingEventListener: MeetingEventListener = object : MeetingEventListener() {
    override fun onMeetingJoined() {
      Log.d("#meeting", "onMeetingJoined()")
    }

    override fun onMeetingLeft() {
      Log.d("#meeting", "onMeetingLeft()")
      meeting = null
      if (!isDestroyed) finish()
    }

    override fun onParticipantJoined(participant: Participant) {
      Toast.makeText(
        this@MeetingActivity, participant.displayName + " joined",
        Toast.LENGTH_SHORT
      ).show()
    }

    override fun onParticipantLeft(participant: Participant) {
      Toast.makeText(
         this@MeetingActivity, participant.displayName + " left",
         Toast.LENGTH_SHORT
      ).show()
    }
  }
}
</code></pre><h3 id="step-3-handle-local-participant-media">Step 3: Handle Local Participant Media</h3><p>After successfully entering the meeting, it's time to manage the webcam and microphone for the local participant (you).</p><p>To enable or disable the webcam, we'll use the <code>Meeting</code> class methods <code>enableWebcam()</code> and <code>disableWebcam()</code>, respectively. Similarly, to mute or unmute the microphone, we'll utilize the methods <code>muteMic()</code> and <code>unmuteMic()</code></p><pre><code class="language-kotlin">class MeetingActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_meeting)
    //...Meeting Setup is Here

    // actions
    setActionListeners()
  }

  private fun setActionListeners() {
    // toggle mic
    findViewById&lt;View&gt;(R.id.btnMic).setOnClickListener { view: View? -&gt;
      if (micEnabled) {
        // this will mute the local participant's mic
        meeting!!.muteMic()
        Toast.makeText(this@MeetingActivity, "Mic Muted", Toast.LENGTH_SHORT).show()
      } else {
        // this will unmute the local participant's mic
        meeting!!.unmuteMic()
        Toast.makeText(this@MeetingActivity, "Mic Enabled", Toast.LENGTH_SHORT).show()
      }
        micEnabled=!micEnabled
    }

    // toggle webcam
    findViewById&lt;View&gt;(R.id.btnWebcam).setOnClickListener { view: View? -&gt;
      if (webcamEnabled) {
        // this will disable the local participant webcam
        meeting!!.disableWebcam()
        Toast.makeText(this@MeetingActivity, "Webcam Disabled", Toast.LENGTH_SHORT).show()
      } else {
        // this will enable the local participant webcam
        meeting!!.enableWebcam()
        Toast.makeText(this@MeetingActivity, "Webcam Enabled", Toast.LENGTH_SHORT).show()
      }
       webcamEnabled=!webcamEnabled
    }

    // leave meeting
    findViewById&lt;View&gt;(R.id.btnLeave).setOnClickListener { view: View? -&gt;
      // this will make the local participant leave the meeting
      meeting!!.leave()
    }
  }
}
</code></pre><h3 id="step-4-handling-the-participants-view">Step 4: Handling the Participants' View</h3><p>To display a list of participants in your video UI, we'll utilize a <code>RecyclerView</code>.</p><p><strong>(a)</strong> This involves creating a new layout for the participant view named <code>item_remote_peer.xml</code> in the <code>res/layout</code> folder. You can copy <code>item_remote_peer.xml </code>file from <a href="https://github.com/videosdk-live/quickstart/blob/main/android-rtc/Videosdk_android_kotlin_quickstart/app/src/main/res/layout/item_remote_peer.xml">here</a>.</p><p><strong>(b)</strong> Create a RecyclerView adapter <code>ParticipantAdapter</code> which will be responsible for displaying the participant list. Within this adapter, define a <code>PeerViewHolder</code> class that extends <code>RecyclerView.ViewHolder</code>.</p><pre><code class="language-kotlin">class ParticipantAdapter(meeting: Meeting) : RecyclerView.Adapter&lt;ParticipantAdapter.PeerViewHolder&gt;() {

  override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PeerViewHolder {
    return PeerViewHolder(
      LayoutInflater.from(parent.context)
        .inflate(R.layout.item_remote_peer, parent, false)
    )
  }

  override fun onBindViewHolder(holder: PeerViewHolder, position: Int) {
  }

  override fun getItemCount(): Int {
    return 0
  }

  class PeerViewHolder(view: View) : RecyclerView.ViewHolder(view) {
    // 'VideoView' to show Video Stream
    var participantView: VideoView
    var tvName: TextView

    init {
        tvName = view.findViewById(R.id.tvName)
        participantView = view.findViewById(R.id.participantView)
    }
  }
}
</code></pre><p><strong>(c)</strong> Now, we will render a list of <code>Participant</code> for the meeting. We will initialize this list in the constructor of the <code>ParticipantAdapter</code></p><pre><code class="language-kotlin">class ParticipantAdapter(meeting: Meeting) :
    RecyclerView.Adapter&lt;ParticipantAdapter.PeerViewHolder&gt;() {

  // creating a empty list which will store all participants
  private val participants: MutableList&lt;Participant&gt; = ArrayList()

  init {
    // adding the local participant(You) to the list
    participants.add(meeting.localParticipant)

    // adding Meeting Event listener to get the participant join/leave event in the meeting.
    meeting.addEventListener(object : MeetingEventListener() {
      override fun onParticipantJoined(participant: Participant) {
        // add participant to the list
        participants.add(participant)
        notifyItemInserted(participants.size - 1)
      }

      override fun onParticipantLeft(participant: Participant) {
        var pos = -1
        for (i in participants.indices) {
          if (participants[i].id == participant.id) {
            pos = i
            break
          }
        }
        // remove participant from the list
        participants.remove(participant)
        if (pos &gt;= 0) {
          notifyItemRemoved(pos)
        }
      }
    })
  }

  // replace getItemCount() method with following.
  // this method returns the size of total number of participants
  override fun getItemCount(): Int {
    return participants.size
  }
  //...
}
</code></pre><p><strong>(d)</strong> We have listed our participants. Let's set up the view holder to display a participant video.</p><pre><code class="language-kotlin">class ParticipantAdapter(meeting: Meeting) :
    RecyclerView.Adapter&lt;ParticipantAdapter.PeerViewHolder&gt;() {

  // replace onBindViewHolder() method with following.
  override fun onBindViewHolder(holder: PeerViewHolder, position: Int) {
    val participant = participants[position]

    holder.tvName.text = participant.displayName

    // adding the initial video stream for the participant into the 'VideoView'
    for ((_, stream) in participant.streams) {
      if (stream.kind.equals("video", ignoreCase = true)) {
        holder.participantView.visibility = View.VISIBLE
        val videoTrack = stream.track as VideoTrack
        holder.participantView.addTrack(videoTrack)
        break
      }
    }

    // add Listener to the participant which will update start or stop the video stream of that participant
    participant.addEventListener(object : ParticipantEventListener() {
      override fun onStreamEnabled(stream: Stream) {
        if (stream.kind.equals("video", ignoreCase = true)) {
          holder.participantView.visibility = View.VISIBLE
          val videoTrack = stream.track as VideoTrack
          holder.participantView.addTrack(videoTrack)
       }
      }

      override fun onStreamDisabled(stream: Stream) {
        if (stream.kind.equals("video", ignoreCase = true)) {
          holder.participantView.removeTrack()
          holder.participantView.visibility = View.GONE
        }
      }
    })
  }
}
</code></pre><p><strong>(e)</strong> Now, add this adapter to the <code>MeetingActivity</code></p><pre><code class="language-kotlin">override fun onCreate(savedInstanceState: Bundle?) {
  // Meeting Setup...
  //...
  val rvParticipants = findViewById&lt;RecyclerView&gt;(R.id.rvParticipants)
  rvParticipants.layoutManager = GridLayoutManager(this, 2)
  rvParticipants.adapter = ParticipantAdapter(meeting!!)
}
</code></pre><h2 id="integrate-active-speaker-indication">Integrate Active Speaker Indication</h2><p>Once you've successfully installed VideoSDK in your Android app, it's time to integrate the Active Speaker Indication feature. This functionality utilizes real-time audio analysis to point to the participant who's speaking at any given moment. VideoSDK then provides this information to your app, allowing you to integrate visual cues into your user interface. Once you've successfully installed VideoSDK in your Android app, it's time to integrate the Active Speaker Indication feature. This functionality utilizes real-time audio analysis to point to the participant who's speaking at any given moment. Text-to-speech can further enhance this by providing audible cues for participants. You can also integrate <a href="https://www.adobe.com/express/feature/ai/audio/voiceover" rel="noreferrer">text to AI voice</a> technology to convert speaker notifications or chat messages into natural-sounding audio for improved accessibility and engagement. VideoSDK then provides this information to your app, allowing you to integrate visual cues into your user interface.</p><p>The active speaker highlight feature aims to visually indicate the participant currently speaking in the video call. This functionality is especially valuable in scenarios with a large number of participants, where it can be difficult to identify the source of the incoming audio.</p><p>This is how we can integrate this feature with VideoSDK. Every time a participant actively speaks during the meeting, the <a href="https://docs.videosdk.live/android/api/sdk-reference/meeting-class/meeting-event-listener-class#onspeakerchanged"><code>onSpeakerChanged</code></a> event is triggered. This event transmits the participant ID of the person who is currently speaking.</p><p>By capturing this event and leveraging the participant ID, you can visually highlight the corresponding participant in your application's user interface. This can be achieved by modifying the user interface element that represents the speaking participant, such as changing the background color or adding a visual indicator.</p><pre><code class="language-kotlin">private final MeetingEventListener meetingEventListener = new MeetingEventListener() {
    @Override
    public void onSpeakerChanged(String participantId) {
        Toast.makeText(MainActivity.this, "Active Speaker participantId" + participantId, Toast.LENGTH_SHORT).show();
        super.onSpeakerChanged(participantId);
    }
};
</code></pre><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/03/Screenshot_20240319_181033_Android-VideoSDK-App--2-.jpg" class="kg-image" alt="How to Integrate Active Speaker in Android(Kotlin) Video Chat App?" loading="lazy" width="396" height="800"/></figure><p>To implement the dynamic speaker detection UI featured in the above image, feel free to check out our <a href="https://github.com/videosdk-live/videosdk-rtc-android-kotlin-sdk-example">GitHub repository</a>.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/videosdk-live/videosdk-rtc-android-kotlin-sdk-example"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - videosdk-live/videosdk-rtc-android-kotlin-sdk-example: WebRTC based video conferencing SDK for Android (Kotlin)</div><div class="kg-bookmark-description">WebRTC based video conferencing SDK for Android (Kotlin) - videosdk-live/videosdk-rtc-android-kotlin-sdk-example</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="How to Integrate Active Speaker in Android(Kotlin) Video Chat App?"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">videosdk-live</span></img></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/67e89b2860333e9273193b829f48464ca203e0c9b6c22c3908faf4ca585a8940/videosdk-live/videosdk-rtc-android-kotlin-sdk-example" alt="How to Integrate Active Speaker in Android(Kotlin) Video Chat App?" onerror="this.style.display = 'none'"/></div></a></figure><h2 id="conclusion"><strong>Conclusion</strong></h2><p>This guide has equipped you with the knowledge to integrate active speaker signals into your Android video chat application using the VideoSDK. With this feature, you enhance the user experience by providing clear visual cues that enhance communication and participation in your video calls.</p><p>To unlock the full potential of VideoSDK, we encourage you to sign up for VideoSDK and further explore its features. Start implementing VideoSDK and Active Speaker Indication today to improve your video app's functionality and user engagement.</p><p><a href="https://www.videosdk.live/signup"><strong>Sign up with VideoSDK</strong></a> today and Get <strong>10,000 Free Minutes to </strong>take your video app to the next level!</p>]]></content:encoded></item><item><title><![CDATA[RegTech (Regulatory Technology): Complete Guide on Compliance]]></title><description><![CDATA[Regulatory Technology (RegTech) has emerged as a transformative solution for enterprises facing complex regulatory structures in the modern financial environment. ]]></description><link>https://www.videosdk.live/blog/what-is-regtech</link><guid isPermaLink="false">66d54ac320fab018df10fe0b</guid><category><![CDATA[RegTech]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Sat, 18 Jan 2025 06:29:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-RegTech_-Understand-its-importance-in-Banking-and-Fintech.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>RegTech (regulatory technology) uses automation, AI, and data analytics to help financial institutions meet KYC, AML, and reporting obligations faster. RegTech tools monitor transactions in real time, generate regulatory filings, and adapt when compliance rules change. Banks, insurers, and fintech teams adopt RegTech to cut manual compliance costs and limit penalty risk.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2024/09/What-is-RegTech_-Understand-its-importance-in-Banking-and-Fintech.jpg" alt="RegTech (Regulatory Technology): Complete Guide on Compliance"/><p>A single missed suspicious activity report can trigger seven-figure fines. A manual KYC review queue that takes days loses customers to competitors who onboard in minutes. RegTech exists because compliance teams cannot scale linear headcount against exponentially growing transaction volumes and regulatory complexity. This article defines regulatory technology, explains how RegTech platforms work, compares leading solution categories, and covers the implementation decisions that separate a compliant digital operation from a manual process that breaks under audit pressure.</p><h2 id="what-is-regulatory-technology-regtech">What is Regulatory Technology (RegTech)?</h2><p>RegTech is defined as the application of technology, including cloud computing, artificial intelligence, machine learning, and big data analytics, to automate and streamline regulatory compliance processes for financial institutions and other regulated industries.</p><p>RegTech works by ingesting structured and unstructured data from transactions, customer records, and external watchlists, then applying rule engines and predictive models to detect violations, generate audit trails, and produce regulator-ready reports without manual spreadsheet workflows. The <a href="https://www.fca.org.uk/firms/innovation/regtech" rel="noreferrer">UK's Financial Conduct Authority (FCA)</a> popularised the term "RegTech" in 2015 to describe startups building compliance automation alongside the FinTech wave.</p><p>Regulatory technology differs from traditional compliance software in three ways. First, RegTech platforms prioritize real-time monitoring over periodic batch reviews. Second, they use machine learning to detect novel fraud patterns that static rule sets miss. Third, they ship regulatory update modules so compliance teams adapt to new rules without rebuilding internal systems from scratch.</p><p>The 2008 global financial crisis accelerated RegTech adoption because regulators tightened capital requirements, transaction reporting standards, and customer due diligence rules simultaneously. According to <a href="https://www.deloitte.com/lu/en/Industries/technology/analysis/regtech-companies-compliance.html" rel="noreferrer">Deloitte's RegTech research</a> program, institutions that delayed automation faced rising operational costs as compliance headcount grew faster than revenue.</p><p>RegTech serves banking, insurance, capital markets, payment processors, and increasingly any company that handles regulated financial data under GDPR, PCI DSS, or sector-specific frameworks.</p><p>This section establishes what RegTech is, how it operates mechanically, and why the category emerged after the post-crisis regulatory expansion.</p><h2 id="how-regtech-is-becoming-a-key-aspect-of-compliance-needs">How RegTech is Becoming a Key Aspect of Compliance Needs?</h2><p>Regulatory Technology (RegTech) solutions provide an extensive collection of functionalities aimed at streamlining compliance processes including:</p><h3 id="automation-of-compliance-processes">Automation of Compliance Processes: </h3><p>RegTech leverages automation to streamline various compliance-related tasks, including regulatory reporting, risk management, identity verification, transaction monitoring, and fraud detection.</p><h3 id="data-management-and-analysis">Data Management and Analysis: </h3><p>RegTech enables companies to handle and analyze vast volumes of data required for regulatory compliance by harnessing advanced analytics, machine learning, and artificial intelligence. This capability allows for the detection of patterns, anomalies, and potential risks.</p><h3 id="real-time-monitoring">Real-Time Monitoring: </h3><p>RegTech tools provide real-time monitoring of transactions and activities, allowing for immediate responses to any regulatory breaches or emerging risks.</p><h3 id="adaptability-to-regulatory-changes">Adaptability to Regulatory Changes: </h3><p>RegTech solutions are designed to be flexible and adaptable, ensuring that businesses can quickly implement necessary adjustments in response to evolving regulatory landscapes.</p><h3 id="cost-reduction-and-efficiency">Cost Reduction and Efficiency: </h3><p>The automation of compliance tasks significantly reduces the time and resources traditionally required for manual processes. This efficiency not only cuts costs but also helps companies avoid big fines and penalties associated with non-compliance.</p><h2 id="what-is-the-importance-of-regtech-for-financial-institutions">What is the Importance of RegTech for Financial Institutions?</h2><p>The financial services industry has been at the forefront of RegTech adoption. As regulatory needs boosted, the need for more robust compliance mechanisms became obvious. <a href="https://www.pwc.in/industries/financial-services/fintech/fintech-insights/regtech-a-new-disruption-in-the-financial-services-space.html">RegTech in banking</a> has since become an essential tool for managing risk, reducing costs, and ensuring adherence to complex regulatory requirements.</p><h3 id="kyc-and-aml-solutions">KYC and AML Solutions:</h3><p>Automated Know Your Customer (KYC) and Anti-Money Laundering (AML) checks with KYC and <a href="https://www.idenfy.com/blog/best-aml-software-providers/" rel="noreferrer">AML software</a> help verify customer identities and prevent illicit activities, enhancing the overall security of banking operations.</p><h3 id="enhanced-detection-capabilities">Enhanced Detection Capabilities: </h3><p>RegTech solutions utilize advanced technologies to monitor financial transactions in real time, detecting suspicious patterns and anomalies that may indicate fraudulent activity or money laundering.</p><h3 id="improved-accuracy-and-efficiency">Improved Accuracy and Efficiency: </h3><p>RegTech reduces human error and increases the speed and accuracy of detecting potential financial crimes by automating compliance processes.</p><h3 id="advanced-data-analysis">Advanced-Data Analysis: </h3><p>RegTech's ability to analyze vast amounts of data quickly and accurately allows financial institutions to identify high-risk behaviors and potential threats more effectively.</p><h3 id="streamlined-regulatory-reporting">Streamlined Regulatory Reporting: </h3><p>Automated documentation and reporting processes ensure timely submission of suspicious activity reports to regulatory authorities, maintaining transparency and compliance.</p><h3 id="adaptability-to-new-threats">Adaptability to New Threats: </h3><p>As financial criminals become increasingly sophisticated, RegTech solutions can be rapidly adapted to detect and combat new types of financial crimes.</p><h2 id="challenges-of-regulatory-technology">Challenges of Regulatory Technology</h2><p>While RegTech has proven highly effective in enhancing regulatory compliance and combating financial crimes, some challenges remain:</p><ul><li><strong>Data Security</strong>: The increased reliance on data processing and storage raises concerns about potential data breaches and cybersecurity risks. To mitigate these risks, <a href="https://controld.com/blog/best-internet-filtering-software/" rel="noreferrer">internet filtering software</a> helps restrict access to malicious or untrusted online content, reducing exposure to cyber threats and strengthening overall data security.</li><li><strong>Regulatory Uncertainty</strong>: The rapid pace of technological advancement can sometimes outpace regulatory guidance, creating uncertainty for institutions implementing RegTech solutions.</li><li><strong>Talent Gap</strong>: Effectively leveraging RegTech requires specialized skills in areas like <a href="https://professional-education-gl.mit.edu/mit-online-data-science-program" rel="noreferrer">applied data science</a> and AI, posing a challenge for many organizations in attracting and retaining the right talent. The <a href="https://www.mygreatlearning.com/artificial-intelligence/courses" rel="noreferrer">Artificial Intelligence course</a> will help in guidance of data usage, managing access, and overseeing related tasks in blockchain technology.</li></ul><h2 id="future-of-regulatory-technology">Future of Regulatory Technology</h2><p>Despite these challenges, the future of RegTech looks promising. As regulatory environments continue to grow more complex, the need for compliance intensifies. By 2027, the <a href="https://www.cbinsights.com/research/regtech-regulation-compliance-market-map/">global RegTech market</a> is projected to exceed $28 billion, underscoring its critical role in modern business operations.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/09/Reg-Tech-2017-VF4.png" class="kg-image" alt="RegTech (Regulatory Technology): Complete Guide on Compliance" loading="lazy" width="1822" height="1536"/></figure><p>Regulatory Technology represents a significant leap forward in how organizations manage regulatory compliance. By leveraging advanced technologies such as AI, machine learning, and <a href="https://intellias.com/big-data-analytics-telecom/">big data</a> analytics. RegTech is revolutionizing it, and paving the way for a more secure and efficient financial ecosystem.</p><p>For businesses looking to stay ahead in an increasingly complex regulatory environment, embracing RegTech solutions is not just an option, it's essential for maintaining compliance, reducing risks, and focusing on core business operations in the digital age.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-regtech">What is RegTech?</h3><p>RegTech (regulatory technology) is technology that automates and streamlines regulatory compliance processes for financial institutions and other regulated industries. RegTech platforms handle KYC identity verification, AML transaction monitoring, regulatory reporting, and compliance workflow management using cloud computing, artificial intelligence, and data analytics. The UK's Financial Conduct Authority popularized the term in 2015.</p><h3 id="how-does-regtech-work">How does RegTech work?</h3><p>RegTech works by ingesting transaction and customer data through APIs, applying compliance rules and machine learning models to detect violations, generating real-time alerts for suspicious activity, and producing regulator-ready reports with immutable audit trails. The pipeline runs continuously rather than in periodic manual review cycles.</p><h3 id="what-is-the-difference-between-regtech-and-fintech">What is the difference between RegTech and FinTech?</h3><p>The difference between RegTech and FinTech is that FinTech delivers customer-facing financial products like mobile banking and payment apps, while RegTech automates compliance obligations like KYC verification, AML monitoring, and regulatory reporting inside regulated institutions. A neobank app is FinTech; the transaction monitoring engine inside it is RegTech.</p><h3 id="what-are-the-benefits-of-regtech-for-banks">What are the benefits of RegTech for banks?</h3><p>RegTech benefits for banks include faster KYC onboarding, reduced AML false positive rates through machine learning prioritization, automated regulatory report generation, lower compliance operational costs, and audit-ready documentation that satisfies examiner requests. Banks also reduce penalty exposure by detecting suspicious activity before regulators identify gaps during examinations.</p><h3 id="is-regtech-only-for-financial-services">Is RegTech only for financial services?</h3><p>RegTech is not only for financial services. While banking and insurance drove early adoption, healthcare organizations use RegTech for HIPAA compliance automation, energy companies use it for environmental reporting under CSRD, and any organization subject to GDPR, PCI DSS, or sector-specific regulations benefits from compliance automation technology.</p><h3 id="what-is-the-future-of-regtech">What is the future of RegTech?</h3><p>The future of RegTech includes deeper AI integration for predictive compliance, expanded cryptocurrency AML monitoring, real-time cross-border regulatory reporting, and embedded compliance modules inside every FinTech product by default. According to Juniper Research, the global RegTech market is forecast to exceed $28 billion by 2027, reflecting sustained investment as regulatory complexity continues to increase across jurisdictions.</p><h3 id="how-do-you-choose-the-right-regtech-vendor">How do you choose the right RegTech vendor?</h3><p>Choose the right RegTech vendor by matching the platform to your highest-priority compliance function first, verifying regulatory coverage for your operating jurisdictions, auditing data integration requirements against your source systems, running a 60 to 90 day parallel pilot, and confirming the vendor publishes tracked regulatory content updates. For <a href="https://www.videosdk.live/solutions/video-kyc" rel="noreferrer">video KYC</a> workflows, prioritize VideoSDK for real-time video infrastructure and pair it with a certified identity verification provider for biometric scoring.</p>]]></content:encoded></item><item><title><![CDATA[10 Best 100ms.live Alternatives in 2026 (Tested & Compared)]]></title><description><![CDATA[Discover a revolutionary and transformative alternative to 100ms, unlocking a remarkable online experience that propels you to unprecedented success. Embrace this golden opportunity to unleash unparalleled potential and embark on a journey to new heights.]]></description><link>https://www.videosdk.live/blog/100ms-alternative</link><guid isPermaLink="false">64b0e97a9eadee0b8b9e6ec8</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Sat, 18 Jan 2025 04:32:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2023/07/100ms-alternative.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2023/07/100ms-alternative.jpg" alt="10 Best 100ms.live Alternatives in 2026 (Tested & Compared)"/><p>If you're <strong>searching for an </strong><a href="https://www.videosdk.live/100ms-vs-videosdk" rel="noreferrer"><strong>alternative to 100ms.live</strong></a> that offers effortless integration of real-time video into your application, you've landed at the perfect spot! While 100ms.live is undoubtedly a well-known option, there exists a vast array of untapped opportunities outside their platform.</p><p>100ms is a real-time communication platform offering developers APIs and SDKs to embed live video into applications. VideoSDK leads the market as the best alternative by providing a more robust WebRTC architecture, simpler integration patterns, and significantly better developer support for production-grade applications.</p><h2 id="what-is-a-100ms">What is a 100ms?</h2><p>100ms is defined as a cloud platform offering APIs and SDKs for integrating live interactive audio and video conferencing into applications. 100ms works by routing media through cloud infrastructure rather than relying strictly on peer-to-peer connections. The platform provides a dashboard for managing live sessions, recording, and playback functionalities.</p><p>Many teams initially select 100ms for its pre-built templates and quick-start components. The fundamental distinction between 100ms and its competitors often centers on the balance between abstraction and developer control. Some teams find that the high level of abstraction in 100ms limits their ability to build deeply customized native experiences.</p><h2 id="why-consider-alternatives-to-100mslive">Why Consider Alternatives to 100ms.live?</h2>
<p><strong>Finding an alternative to 100ms.live</strong> may be necessary for many reasons such as needing <a href="https://github.com/100mslive/100ms-android/issues/213">better performance</a>, better <a href="https://github.com/100mslive/100ms-flutter/issues/1424">user experience</a>, more features, increased customization, or cost considerations. By evaluating these factors, developers can make informed decisions that align with their project goals and enhance the overall video experience for their users.</p><p>The <strong>top 10 100ms.live Alternatives</strong> are VideoSDK, Twilio, MirrorFly, Agora, Jitsi, Vonage, AWS Chime, EnableX, WhereBy, and SignalWire.</p><blockquote>
<h2 id="10-best-100mslive-alternatives-for-2024">10 Best 100ms.live Alternatives for 2024</h2>
<ul>
<li>VideoSDK</li>
<li>Twilio Video</li>
<li>MirrorFly</li>
<li>Agora</li>
<li>Jitsi</li>
<li>Vonage</li>
<li>AWS Chime SDK</li>
<li>Enablex</li>
<li>Whereby</li>
<li>SignalWire</li>
</ul>
</blockquote>
<h2 id="1-videosdk-seamless-integration-and-comprehensive-features">1. VideoSDK: Seamless Integration and Comprehensive Features</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-SDK-for-Real-time-Communication-Live-Streaming-Video-API-5.jpeg" class="kg-image" alt="10 Best 100ms.live Alternatives in 2026 (Tested & Compared)" loading="lazy" width="1920" height="967"/></figure><p>Immerse yourself in the amazing capabilities of <a href="https://www.videosdk.live">VideoSDK</a>, an API designed to seamlessly integrate robust audio and video features into your applications. With minimal effort, you can enhance your app by providing live audio and video experiences across different platforms. Elevate your user experience and take your application to the next level with VideoSDK's powerful features.</p><h3 id="key-points-about-videosdk">Key points about VideoSDK</h3>
<ul><li>VideoSDK offers a seamless integration experience, combining simplicity and speed to enable you to focus on developing innovative features that enhance user retention. Say goodbye to complex integration processes and unlock a world of possibilities.</li><li>With VideoSDK, you can enjoy the benefits of exceptional scalability, adaptive bitrate technology for optimal video quality, extensive customization options to tailor the user experience, high-quality recording capabilities, comprehensive analytics to gain valuable insights, cross-platform streaming for broader reach, effortless scalability to accommodate growing needs, and robust support across various platforms.</li><li>Whether you're developing for mobile (Flutter, Android, iOS), web (JavaScript Core SDK + UI Kit), or desktop (Flutter Desktop), Video SDK empowers you to effortlessly create immersive and engaging video experiences.</li></ul><h3 id="videosdk-pricing">VideoSDK pricing</h3>
<ul><li>Experience the extraordinary value of Video SDK! Take full advantage of our generous offer of <a href="https://www.videosdk.live/pricing">$20 free credit</a> and enjoy <a href="https://www.videosdk.live/pricing#pricingCalc">flexible pricing</a> options for both video and audio calls.</li><li>With Video SDK, you can enjoy <strong>video calls</strong> starting at an incredible rate of <strong>only $0.003</strong> per participant per minute, allowing you to connect with others without breaking the bank. </li><li>Additionally, their <strong>audio calls</strong> are available at a minimal cost of just <strong>$0.0006</strong> per minute, ensuring affordable communication options.</li><li>To enhance your experience, they offer <strong>cloud recordings</strong> at an affordable rate of <strong>$0.015</strong> per minute, allowing you to capture and preserve important moments. </li><li>For those who require <strong>RTMP output</strong>, they provide competitive pricing at <strong>$0.030</strong> per minute, ensuring seamless streaming capabilities.</li><li>Rest assured that their dedicated support team is available to assist you <strong>24/7</strong>, providing prompt and reliable customer support whenever you need it.</li><li>Upgrade your video capabilities today and embark on a new level of excellence with VideoSDK!</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/100ms-vs-videosdk"><strong>100ms and VideoSDK</strong></a><strong>.</strong></blockquote>
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Your Page Title</title>
	<!-- Include Tailwind CSS -->
	<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</link></meta></meta></head>

<body>
	<div class="relative w-full overflow-hidden rounded-2xl bg-gradient-to-b from-pink-700 to-purple-900 p-4 text-center shadow-xl">
		<h3 class="mx-auto text-3xl font-bold tracking-tight text-white sm:text-2xl" style="margin-top: 3px; margin-bottom: 12px;">
			Schedule a Demo with Our Live Video Expert!
		</h3>
		<p class="mx-auto mt-3 max-w-xl text-sm text-gray-400">
			Discover how VideoSDK can help you build a cutting-edge real-time video app.
			<span class="font-semibold text-lato"/>
		</p>
		<div class="mt-4 flex items-center justify-center">
			<a href="https://www.videosdk.live/contact" class="rounded-md bg-white px-8 py-3 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white" target="_blank" style="text-decoration: none;color: black;" data-faitracker-click-bind="true">
				Book a call
			</a>	
		</div>
		
	</div>
</body>

</html>
<!--kg-card-end: html-->
<h2 id="2-twilio-video-versatile-and-reliable-video-integration">2. Twilio Video: Versatile and Reliable Video Integration</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Communication-APIs-for-SMS-Voice-Video-Authentication_twilio-4.jpeg" class="kg-image" alt="10 Best 100ms.live Alternatives in 2026 (Tested & Compared)" loading="lazy" width="1920" height="967"/></figure><p>Twilio is a top-tier video SDK solution that enables businesses to easily integrate live video into their mobile and web applications. One of the notable strengths of Twilio is its versatility, allowing you to either create a new app from the ground up or enhance your existing solutions with powerful communication features. Whether you're starting fresh or expanding the capabilities of your app, Twilio offers a dependable and comprehensive solution for seamlessly integrating live video into your applications.</p><h3 id="key-points-about-twilio">Key points about Twilio</h3>
<ul><li>Twilio offers web, iOS, and Android SDKs that enable seamless integration of live video into applications, providing developers with versatile tools to enhance their user experiences.</li><li>However, when using Twilio, manual configuration and additional code are required for utilizing multiple audio and video inputs, which may increase development complexity.</li><li>Twilio's call insights feature allows for error tracking and analysis, but implementing it requires additional code integration.</li><li>As usage grows, pricing can become a concern, as Twilio lacks a built-in tiering system in the dashboard to accommodate scaling needs effectively.</li><li>In terms of call capacity, Twilio supports up to 50 hosts and participants, which may be sufficient for many use cases.</li><li>It's worth noting that Twilio does not provide plugins for easy product development, which may require developers to invest additional time and effort.</li><li>Lastly, while Twilio offers customization options, the level of customization provided by the Twilio Video SDK may not meet the specific requirements of all developers, potentially necessitating additional code development.</li></ul><h3 id="pricing-for-twilio">Pricing for Twilio</h3>
<ul><li><a href="https://www.videosdk.live/blog/twilio-video-alternative"><strong>Twilio</strong></a> offers <a href="https://www.twilio.com/en-us/video/pricing">pricing</a> starting at <strong>$4</strong> per 1,000 minutes for their <strong>video services</strong>.</li><li>Additionally, they charge <strong>$0.004</strong> per participant minute for <strong>recordings</strong>, <strong>$0.01</strong> per composed minute for <strong>recording compositions</strong>, and <strong>storage</strong> costs <strong>$0.00167</strong> per GB per day after the initial 10 GB.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/twilio-vs-100ms"><strong>100ms and Twilio</strong></a><strong>.</strong></blockquote><h2 id="3-mirrorfly-enterprise-level-communication-with-extensive-features">3. MirrorFly: Enterprise-Level Communication with Extensive Features</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Live-Video-Call-API-Best-Video-Chat-SDK-for-Android-iOS-mirrorfly-4.jpeg" class="kg-image" alt="10 Best 100ms.live Alternatives in 2026 (Tested & Compared)" loading="lazy" width="1920" height="967"/></figure><p>MirrorFly is an outstanding in-app communication suite designed specifically for enterprises. It offers a wide range of powerful APIs and SDKs that deliver exceptional chat and calling experiences. With over 150 remarkable features for chat, voice, and video calling, this cloud-based solution seamlessly integrates to create a robust communication platform.</p><h3 id="key-points-about-mirrorfly">Key points about MirrorFly</h3>
<ul><li>MirrorFly may have limited customization options, which can restrict the ability to tailor the platform according to specific branding or user experience requirements. This may limit the uniqueness and personalization of the communication features.</li><li>MirrorFly may face difficulties in scaling for larger applications or handling a high volume of users. The platform may struggle to maintain performance and stability when dealing with significant traffic or complex use cases.</li><li>Users have reported mixed experiences with MirrorFly's technical support. Some have found it lacking in responsiveness, leading to delays or difficulties in resolving issues or addressing concerns.</li><li>MirrorFly's pricing structure may not be suitable for all budgets or use cases. Depending on the desired features and scalability requirements, the costs associated with using MirrorFly may be higher compared to alternative communication platforms.</li><li>Integrating MirrorFly into existing applications or workflows may require significant effort and technical expertise. The platform might lack comprehensive documentation or robust developer resources, making the integration process challenging or time-consuming.</li></ul><h3 id="mirrorfly-pricing">MirrorFly pricing</h3>
<ul><li>MirrorFly's <a href="https://www.mirrorfly.com/pricing.php">pricing</a> starts at <strong>$299</strong> per month, making it a higher-cost option to consider.</li></ul><h2 id="4-agora-global-coverage-with-extensive-video-calling-features">4. Agora: Global Coverage with Extensive Video Calling Features</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Agora-Real-Time-Voice-and-Video-Engagement-4.jpeg" class="kg-image" alt="10 Best 100ms.live Alternatives in 2026 (Tested & Compared)" loading="lazy" width="1920" height="967"/></figure><p>Agora's video calling SDK provides a wide range of features, such as embedded voice and video chat, real-time recording, live streaming, and instant messaging. These features empower developers to create engaging and immersive live experiences within their applications.</p><h3 id="key-points-about-agora">Key points about Agora</h3>
<ul><li>Agora's video SDK offers embedded voice and video chat, real-time recording, live streaming, and instant messaging.</li><li>Additional add-ons like AR facial masks, sound effects, and whiteboards are available at an extra cost.</li><li>Agora's SD-RTN ensures extensive global coverage with ultra-low latency streaming capabilities.</li><li>The pricing structure may be complex and may not be suitable for businesses with limited budgets.</li><li>Users seeking hands-on support may experience delays as Agora's support team may require additional time to provide assistance.</li></ul><h3 id="agora-pricing">Agora pricing</h3>
<ul><li><a href="https://www.videosdk.live/blog/agora-alternative"><strong>Agora</strong></a> offers <strong>Premium</strong> and <strong>Standard </strong><a href="https://www.agora.io/en/pricing/"><strong>pricing</strong> </a>options for their services. The pricing is based on the usage duration of audio and video calls, calculated on a monthly basis. </li><li>It is categorized into four types, depending on the video resolution, providing flexibility and cost-effectiveness. </li><li>The pricing structure includes <strong>Audio calls</strong> at <strong>$0.99</strong> per 1,000 participant minutes, <strong>HD Video calls</strong> at <strong>$3.99</strong> per 1,000 participant minutes, and <strong>Full HD Video calls</strong> at <strong>$8.99</strong> per 1,000 participant minutes.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/agora-vs-100ms"><strong>100ms and Agora</strong></a><strong>.</strong> </blockquote><h2 id="5-jitsi-open-source-flexibility">5. Jitsi: Open-Source Flexibility</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Free-Video-Conferencing-Software-for-Web-Mobile-Jitsi-5.jpeg" class="kg-image" alt="10 Best 100ms.live Alternatives in 2026 (Tested & Compared)" loading="lazy" width="1920" height="967"/></figure><p>Jitsi is a collection of multiple open-source projects aimed at enabling video conferencing. As an open-source platform, it provides the flexibility to customize and utilize it according to your specific needs and requirements. The core components of Jitsi include Jitsi Meet, Jitsi Videobridge, Jibri, and Jigsai, each playing a distinct role within the Jitsi ecosystem.</p><h3 id="key-points-about-jitsi">Key points about Jitsi</h3>
<ul><li>Jitsi is an open-source and free platform that offers users the freedom to utilize it according to their preferences and requirements. </li><li>One of its prominent projects, Jitsi Meet, provides a range of features such as text sharing via Etherpad, room locking, text chatting (web only), raising hands, YouTube video access during calls, audio-only calls, and integrations with third-party apps. </li><li>However, Jitsi Meet alone does not include essential collaborative features like screen sharing, recording, or telephone dial-in to a conference. To access these features, additional setup of projects like Jibri and Jigsai is necessary, which can involve more time, resources, and coding efforts. </li><li>This additional setup may make Jitsi less suitable for users seeking a low-code option. While Jitsi ensures end-to-end encryption for video calls, it does not cover chat or polls, so users prioritizing robust security may need to consider additional measures. </li><li>It's worth noting that Jitsi can consume a significant amount of bandwidth due to the functioning of Jitsi Videobridge. </li><li>For large organizations requiring an SDK for frequent long video sessions with a substantial number of participants, Jitsi might not meet their specific needs and could feel less satisfactory in comparison.</li></ul><h3 id="jitsi-pricing">Jitsi pricing</h3>
<ul><li><a href="https://www.videosdk.live/blog/jitsi-alternative"><strong>Jitsi</strong></a> is available for <strong>free</strong>, which means you don't have to pay for any of its components. </li><li>However, it's worth mentioning that there is no dedicated technical support provided. If you encounter any issues or need assistance, you can seek help from the community of contributors who actively participate in the Jitsi project.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/100ms-vs-jitsi"><strong>100ms and Jitsi</strong></a><strong>.</strong></blockquote><h2 id="6-vonage-comprehensive-communication-sdk">6. Vonage: Comprehensive Communication SDK</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-API-Fully-Programmable-and-Customizable-Vonage-3.jpeg" class="kg-image" alt="10 Best 100ms.live Alternatives in 2026 (Tested & Compared)" loading="lazy" width="1920" height="967"/></figure><p>Even though it has been acquired by Vonage and renamed as the "Vonage API," TokBox is still commonly referred to by its original name. TokBox's SDKs enable developers to establish reliable point-to-point communication, making it an ideal option for creating proof of concepts during hackathons or meeting investor deadlines. With Vonage's SDKs, developers have the necessary tools to build secure and seamless communication experiences within their applications.</p><h3 id="key-points-about-vonage">Key points about Vonage</h3>
<ul><li>The TokBox SDK empowers developers to create customized audio/video streams with various effects, filters, and AR/VR capabilities on mobile devices.</li><li>It offers support for diverse use cases, including 1:1 video calls, group video chat, and large-scale broadcast sessions. </li><li>Participants in a call can easily share screens, exchange messages through chat, and send data in real-time.</li><li>However, TokBox does pose some challenges. As the user base grows, scaling costs can become a concern since the price per stream per minute increases.</li><li>Additional features like recording and interactive broadcast come at an extra cost, which should be taken into account when considering the platform.</li><li>Additionally, once the number of connections reaches 2,000, the platform switches to CDN delivery, resulting in higher latency. </li><li>Real-time streaming at scale can be challenging, as accommodating over 3,000 viewers requires switching to HLS, which introduces significant latency.</li></ul><h3 id="vonage-pricing">Vonage pricing</h3>
<ul><li><a href="https://www.videosdk.live/blog/vonage-alternative"><strong>Vonage</strong></a> adopts a usage-based <a href="https://www.vonage.com/communications-apis/video/pricing/">pricing</a> model for their video sessions, with the cost determined by the number of participants and dynamically calculated every minute. </li><li>Their <strong>pricing plans</strong> begin at <strong>$9.99</strong> per month and include a generous free allowance of 2,000 minutes per month for all plans.</li><li>Once the free allowance is consumed, users are billed at a rate of <strong>$0.00395</strong> per participant per minute for the additional usage. </li><li>For those interested in <strong>recording</strong> services, Vonage offers them starting at <strong>$0.010</strong> per minute. </li><li>If <strong>HLS streaming</strong> is required, it is priced at <strong>$0.003</strong> per minute. These additional services come with their respective costs to enhance the video experience.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/vonage-vs-100ms"><strong>100ms and Vonage</strong></a><strong>.</strong></blockquote><h2 id="7-aws-chime-sdk-customizable-real-time-communication">7. AWS Chime SDK: Customizable Real-Time Communication</h2>
<p>The <a href="https://www.videosdk.live/amazon-chime-sdk-vs-videosdk" rel="noreferrer">Amazon Chime SDK</a> operates as the foundational technology of Amazon Chime, operating separately from its user interface and external shell. It provides the essential building blocks for integrating real-time audio and video communication into applications, enabling developers to create customized communication experiences tailored to their specific needs.</p><h3 id="key-points-about-aws-chime-sdk">Key points about AWS Chime SDK</h3>
<ul><li>The Amazon Chime SDK enables video meetings with a maximum of 25 participants (50 for mobile users), facilitating effective collaboration. </li><li>With the integration of simulcast technology, it ensures that video quality remains consistent across various devices and networks.</li><li>To prioritize security, the Amazon Chime SDK encrypts all calls, videos, and chats, providing a secure communication environment.</li><li>However, it is worth noting that certain features like polling, auto-sync with Google Calendar, and background blur effects are not available in the Amazon Chime SDK.</li><li>Compatibility issues have been reported in Linux environments, and participants using the Safari browser may also encounter challenges while using the SDK.</li><li>Customer support experiences may vary, as query resolution times are inconsistent and can depend on the specific support agent assigned to the case.</li></ul><h3 id="aws-chime-pricing">AWS Chime pricing</h3>
<ul><li>The <strong>free basic plan</strong> offered by <a href="https://www.videosdk.live/blog/amazon-chime-sdk-alternative"><strong>Amazon Chime</strong></a> allows users to engage in <strong>one-on-one audio/video calls</strong> and <strong>group chats</strong> without any <a href="https://aws.amazon.com/chime/pricing/">cost</a>.</li><li>For users who require additional features and functionalities, the <strong>Plus plan</strong> is available at a price of <strong>$2.50</strong> per month per user. This plan includes valuable additions such as <strong>screen sharing</strong>, <strong>remote desktop control</strong>, <strong>1 GB of message history</strong> per user, and <strong>Active Directory integration</strong>.</li><li>For more extensive collaboration needs, the <strong>Pro plan</strong> is available at a cost of <strong>$15</strong> per user per month. It encompasses all the features of the Plus plan and enables <strong>meetings</strong> with <strong>three</strong> or more participants, making it suitable for larger group discussions and presentations.</li></ul><blockquote><strong>Here's a detailed comparison of </strong><a href="https://www.videosdk.live/amazon-chime-sdk-vs-100ms"><strong>100ms and AWS Chime</strong></a><strong>.</strong></blockquote><h2 id="8-enablex-customized-video-calling-experiences">8. EnableX: Customized Video Calling Experiences</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-Call-API-Video-Chat-API-Voice-API-Video-Conferencing_enebleX-5.jpeg" class="kg-image" alt="10 Best 100ms.live Alternatives in 2026 (Tested & Compared)" loading="lazy" width="1920" height="967"/></figure><p>The EnableX SDK offers a wide range of capabilities, including video and audio calling, as well as collaborative features such as a whiteboard, screen sharing, annotation, recording, host control, and chat. With this SDK, you can easily integrate these functionalities into your application. It provides a video builder tool that allows you to create customized video-calling solutions that align with your application's requirements. You have the flexibility to personalize the live video streams with a custom user interface, choose appropriate hosting options, integrate billing functionality, and implement other essential features that cater to your specific needs.</p><h3 id="key-points-about-enablex">Key points about EnableX</h3>
<ul><li>EnableX offers a self-service portal that allows users to access reporting capabilities and live analytics. This portal enables users to track the quality of their communication experiences and facilitate online payments.</li><li>The EnableX SDK supports popular programming languages such as JavaScript, PHP, and Python. This broad language support makes it easier for developers to integrate the SDK into their applications.</li><li>With EnableX, users have the flexibility to stream live content directly from their app or website. They can also leverage popular platforms like YouTube and Facebook to reach a wider audience and extend the reach of their live content.</li><li>It's worth noting that the response time of EnableX's support team may take up to 72 hours. This extended wait time for assistance could be a potential drawback for users who require prompt and timely support.</li></ul><h3 id="enablex-pricing">EnableX pricing</h3>
<ul><li>EnableX offers <a href="https://www.enablex.io/cpaas/pricing/our-pricing"><strong>pricing</strong></a><strong> plans</strong> that start at <strong>$0.004</strong> per minute per participant for rooms with <strong>up to 50 people</strong>. If you require hosting larger meetings or events, you can contact their sales team for custom pricing options.</li><li><strong>Recording</strong> functionality is available at a rate of <strong>$0.010</strong> per minute per participant. This allows you to capture and save your video sessions for future reference.</li><li>If you need to <strong>transcode</strong> your video into a different format, EnableX provides this service at a rate of <strong>$0.010</strong> per minute. This enables you to convert your video content into a format that suits your specific requirements.</li><li><strong>Additional storage</strong> can be obtained at a cost of <strong>$0.05</strong> per gigabyte (GB) per month. This allows you to expand your storage capacity to accommodate your growing video content.</li><li>For those who require <a href="https://www.videosdk.live/developer-hub/rtmp/rtmp-protocol" rel="noreferrer"><strong>RTMP (Real-Time Messaging Protocol) </strong></a><strong>streaming</strong>, EnableX offers this feature at a rate of <strong>$0.10</strong> per minute. RTMP streaming enables you to deliver your video content in real-time to various platforms and devices.</li><li>Please note that the pricing may vary depending on your specific needs and requirements.</li></ul><h2 id="9-whereby-effective-small-scale-video-conferencing">9. Whereby: Effective Small-Scale Video Conferencing</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Video-Calling-API-for-Web-and-App-Developers-Whereby-5.jpeg" class="kg-image" alt="10 Best 100ms.live Alternatives in 2026 (Tested & Compared)" loading="lazy" width="1920" height="967"/></figure><p>Whereby is a user-friendly <a href="https://www.videosdk.live/audio-video-conferencing" rel="noreferrer">video conferencing platform</a> specifically designed for small to medium-sized meetings. It offers a straightforward and easy-to-use experience for users. However, it may not be the ideal choice for larger businesses or those in need of more advanced features that cater to their specific requirements.</p><h3 id="key-points-about-whereby">Key points about Whereby</h3>
<ul><li>Basic customization options are available for the video interface, but they are limited and do not support a fully custom experience.</li><li>Video calls can be embedded directly into websites, mobile apps, and web products, eliminating the need for external links or apps.</li><li>Whereby offers a seamless video conferencing experience, but it may lack advanced features compared to other tools.</li><li>The maximum capacity for meetings on Whereby is 50 participants.</li><li>Screen sharing for mobile users and customization options for the host interface may be limited.</li><li>Whereby does not have a virtual background feature, and some users have reported issues with the mobile app, which can impact the overall user experience.</li></ul><h3 id="whereby-pricing">Whereby pricing</h3>
<ul><li>Whereby <a href="https://whereby.com/information/pricing">pricing</a> starts at <strong>$6.99</strong> per month.</li><li>The <strong>basic plan</strong> includes <strong>up to 2,000 user minutes per month</strong>.</li><li><strong>Additional minutes</strong> are charged at <strong>$0.004</strong> per minute.</li><li><strong>Cloud recording</strong> and <strong>live streaming</strong> options are available at <strong>$0.01</strong> per minute.</li><li><strong>Email</strong> and <strong>chat support</strong> are provided <strong>free</strong> of charge.</li><li><strong>Paid</strong> support plans offer features like <strong>technical onboarding</strong> and <strong>customer success management</strong>.</li><li><strong>HIPAA</strong> compliance is also available as part of the <strong>paid</strong> support plans.</li></ul><h2 id="10-signalwire-video-integration-with-flexible-pricing">10. SignalWire: Video Integration with Flexible Pricing</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Building-The-Software-Defined-Telecom-Network-SignalWire-4.jpeg" class="kg-image" alt="10 Best 100ms.live Alternatives in 2026 (Tested & Compared)" loading="lazy" width="1920" height="967"/></figure><p>SignalWire is a platform that leverages APIs to empower developers in seamlessly integrating live and on-demand video experiences into their applications. Its primary goal is to simplify the processes of video encoding, delivery, and renditions, ensuring a smooth and uninterrupted video streaming experience for users.</p><h3 id="overview-of-signalwire">Overview of SignalWire</h3>
<ul><li>SignalWire offers an SDK that enables developers to integrate real-time video and live streams into web, iOS, and Android applications. The SDK allows for video calls with up to 100 participants in a real-time webRTC environment.</li><li>However, it is important to note that the SDK does not provide built-in support for managing disruptions or user publish-subscribe logic, which developers will need to implement separately.</li></ul><h3 id="signalwire-pricing">SignalWire pricing</h3>
<ul><li>SignalWire utilizes a <a href="https://signalwire.com/pricing/video">pricing</a> model based on per-minute usage. </li><li>For <strong>HD video calls</strong>, the pricing is <strong>$0.0060</strong> per minute, while for <strong>Full HD video calls</strong>, it is <strong>$0.012</strong> per minute. The actual cost may vary depending on the desired video quality for your application.</li><li>In addition, SignalWire offers additional features such as <strong>recording</strong>, which is available at a rate of <strong>$0.0045</strong> per minute. This allows you to capture and store video content for future use. </li><li>The platform also provides <strong>streaming</strong> capabilities priced at <strong>$0.10</strong> per minute, enabling you to broadcast your video content in real-time.</li></ul><h2 id="certainly">Certainly!</h2>
<p><a href="https://www.videosdk.live">VideoSDK</a> stands out as an SDK that prioritizes fast and seamless integration. With a low-code solution, developers can quickly build live video experiences in their applications, deploying custom video conferencing solutions in under 10 minutes. Unlike other SDKs, Video SDK offers a streamlined process with easy creation and embedding of live video experiences, enabling real-time connections, communication, and collaboration.</p><h2 id="still-skeptical">Still skeptical?</h2>
<p>Immerse yourself in the possibilities of VideoSDK by taking a deep dive into its comprehensive <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start">Quickstart guide</a>. Explore the potential with the powerful <a href="https://docs.videosdk.live/code-sample">sample app</a> exclusively designed for Video SDK. Sign up now and start your integration journey, and don't miss out on the chance to claim your <a href="https://www.videosdk.live/pricing">complimentary $20 free credit</a> to unlock the full potential of Video SDK. Our dedicated team is always ready to assist you whenever you need support. Get ready to showcase your creativity and build remarkable experiences with Video SDK. Let the world see what you can create!</p><h2 id="faqs">FAQs</h2>
<h3 id="what-is-the-main-difference-between-100ms-and-videosdk">What is the main difference between 100ms and VideoSDK?</h3><p>The main difference between 100ms and VideoSDK is that VideoSDK offers vastly superior developer ergonomics and more flexible UI customization. VideoSDK also provides a more transparent and scalable pricing model for growing applications.</p><h3 id="is-there-a-free-100ms-alternative">Is there a free 100ms alternative?</h3><p>Yes, there is a free 100ms alternative available through open-source projects like Jitsi or LiveKit. Additionally, VideoSDK offers a generous perpetual free tier of 10,000 minutes every month for developers.</p><h3 id="can-i-migrate-from-100ms-to-another-video-api-easily">Can I migrate from 100ms to another video API easily?</h3><p>Yes, you can migrate from 100ms to another video API easily if your application architecture cleanly separates the UI layer from the video logic. Providers like VideoSDK offer extensive migration guides and drop-in UI components to speed up the transition.</p><h3 id="which-100ms-alternative-is-best-for-react-native">Which 100ms alternative is best for React Native?</h3><p>The best 100ms alternative for React Native is VideoSDK because of its highly optimized, native-feeling React Native SDK. It provides pre-built components that handle complex state management and background states automatically.</p><h3 id="why-do-developers-switch-away-from-100ms">Why do developers switch away from 100ms?</h3><p>Developers switch away from 100ms primarily because they hit customization roadblocks with the pre-built UI templates. Teams also cite complex documentation and difficult debugging experiences as major drivers for migration.</p>]]></content:encoded></item><item><title><![CDATA[10 Best Voice Call APIs & SDKs]]></title><description><![CDATA[The best voice call APIs in 2026 include VideoSDK, Twilio, Agora, Plivo, and Vonage. This guide compares ten platforms on pricing, SDK coverage, PSTN support, compliance, and production reliability so you pick the right API.]]></description><link>https://www.videosdk.live/blog/10-best-audio-calling-api</link><guid isPermaLink="false">64ed90d99eadee0b8b9e82a9</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 17 Jan 2025 11:32:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2023/08/10-Audio--Calling.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>The best voice call APIs in 2026 include VideoSDK, Twilio, Agora, Sendbird, Plivo, Sinch, EnableX, Vonage, and MessageBird. VideoSDK ranks first for developer teams needing fast WebRTC voice SDK integration with sub-second latency across web and mobile. Select based on latency, PSTN support, participant limits, and total cost including recording and transcription.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2023/08/10-Audio--Calling.jpg" alt="10 Best Voice Call APIs & SDKs"/><p>A dropped support call during a billing dispute costs you a customer. A gaming voice channel that lags behind gameplay breaks immersion. Your team needs embedded voice calling, but building WebRTC audio infrastructure from scratch consumes months of engineering time on codec negotiation, TURN relays, echo cancellation, and cross-platform SDK maintenance. This article defines what voice call APIs are, provides a step-by-step evaluation framework, compares the ten leading platforms with VideoSDK listed first, and covers hidden costs, production pitfalls, and scenarios where a managed API is not the right fit.</p><h2 id="what-is-a-voice-call-api">What Is a Voice Call API?</h2><p>A voice call API is defined as a programmatic interface that lets developers embed real-time, bidirectional audio communication into web, mobile, and desktop applications without building VoIP infrastructure from scratch.</p><p>A voice call API works by exposing REST endpoints and client SDK methods for session creation, participant management, audio stream routing, recording, and analytics while the vendor operates signaling servers, STUN/TURN relays, and media routing clusters globally. Your application calls&nbsp;<code>createMeeting()</code>&nbsp;or equivalent methods; the platform handles encrypted audio transport, bandwidth adaptation, noise suppression, and session state.</p><p>Voice call APIs differ from raw in scope. <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> is a browser protocol for peer-to-peer media. A voice call API is a managed Communications Platform as a Service (CPaaS) layer that wraps WebRTC (or proprietary protocols) with multi-platform SDKs, PSTN bridging, compliance controls, and operational tooling. You integrate the SDK; the vendor maintains uptime, scaling, and protocol updates.</p><p>According to Grand View Research, the <a href="https://www.grandviewresearch.com/industry-analysis/mobile-voip-market" rel="noreferrer">global mobile VoIP market size</a> was valued at USD 44.99 billion in 2023 and is projected to grow at a CAGR of 12.9% from 2024 to 2030. That growth tracks with the shift from custom SIP stacks toward API-first platforms that let product teams ship voice features in weeks instead of quarters.</p><h2 id="what-should-you-look-for-in-a-voice-call-api">What Should You Look for in a Voice Call API?</h2><p>A voice call API must match your latency target, audio quality profile, SDK platform coverage, and PSTN requirements before per-minute price becomes the deciding factor.</p><p><strong>Latency and audio quality.</strong>&nbsp;Interactive gaming, telehealth consultations, and customer support calls need sub-300ms mouth-to-ear delay. Verify whether the provider routes audio through WebRTC SFUs, Opus codec optimization, and geographic edge nodes close to your users.</p><p><strong>Participant limits and room models.</strong>&nbsp;Some APIs cap active speakers at 25 participants while others scale to thousands with role-based publishing. Document your peak concurrent users per room and total concurrent sessions before comparing vendors.</p><p><strong>SDK breadth.</strong>&nbsp;If your product ships on iOS, Android, React Native, Flutter, and web simultaneously, confirm unified SDK coverage. VideoSDK provides client libraries across all five platforms with optional pre-built UI kits, reducing the integration surface compared to stitching separate audio and PSTN vendors.</p><p><strong>PSTN and SIP support.</strong>&nbsp;If your application bridges in-app voice to traditional phone numbers, confirm programmatic PSTN termination, SIP trunking, and per-minute carrier rates. Not every WebRTC-first API includes carrier connectivity.</p><p><strong>Recording and compliance.</strong>&nbsp;Regulated industries need server-side recording, encrypted storage, audit trails, and HIPAA Business Associate Agreements. Confirm whether recording is a first-class API or a bolt-on with separate billing.</p><p><strong>Pricing transparency.</strong>&nbsp;Per-participant-minute billing is standard, but PSTN termination, transcription, storage fees, and support tiers inflate bills beyond headline rates. Model total monthly cost at projected scale, not demo-day usage.</p><p>In practice, engineering teams that evaluate voice call APIs on price alone without testing under throttled mobile networks report rework cycles averaging three to six weeks when production conditions expose SDK gaps.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-8--2026--07_03_33-PM.png" class="kg-image" alt="10 Best Voice Call APIs & SDKs" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">what to look for in a voice call API </span></figcaption></img></figure><h2 id="key-features-to-look-for-in-an-audio-call-api">Key Features to Look for in an Audio Call API</h2>
<p>Voice calling APIs serve as the essential bridges that empower companies to seamlessly incorporate voice call functionality into their applications, facilitating connectivity and enabling business transactions to thrive.</p><p>In a sea of voice conferencing system APIs available in the market, it's imperative to navigate based on specific criteria to pinpoint the optimal voice API for your needs.</p><p>Let's delve into four crucial criteria that should guide your selection process:</p><ol><li><strong>Variety in API Features:</strong> Seek out an API that boasts a diverse range of features, enhancing the capabilities and distinctiveness of your application.</li><li><strong>Popularity and Market Demand:</strong> Gauge the popularity and demand for the API in the market. This assessment helps you gauge the API's value and relevance in the broader landscape.</li><li><strong>Cost and Investment:</strong> The financial aspect plays a pivotal role in any development endeavor. It's essential to thoroughly evaluate the pricing and investment required for the chosen APIs, as it significantly shapes your development journey.</li><li><strong>Compatibility and Ease of Integration:</strong> Prioritize APIs that align seamlessly with your existing infrastructure. Ensuring compatibility and ease of integration into your pre-existing or ongoing projects is paramount.</li></ol><p>Discover the top 10 voice call APIs to revolutionize your VoIP and programmable voice apps. These APIs empower developers to build advanced communication solutions with ease, from call routing to real-time analytics. Enhance your app's capabilities with industry-leading APIs for an unparalleled user experience</p><h2 id="top-10-audio-call-apis-sdks-in-2026">Top 10 Audio Call APIs &amp; SDKs in 2026</h2>
<p>The <strong>10 best voice-calling APIs and SDKs</strong> are Video SDK, Twilio, MirrorFly, Agora, Sendbird, Plivo, Sinch, EnableX, Vonage, and MessageBird.</p><h2 id="1-videosdk-a-synthesis-of-speed-and-flexibility">1. VideoSDK: A Synthesis of Speed and Flexibility</h2>
<p>Step into the realm of <a href="https://www.videosdk.live/">VideoSDK</a>, an <strong>extraordinary</strong> integration solution that has garnered a reputation for its remarkable speed in seamlessly infusing audio calling capabilities into applications, all accomplished within an astonishing <strong>10-minute</strong> span. This platform represents a paradigm shift in <strong>efficiency</strong>, offering a harmonious blend that caters to the needs of both end-users and developers alike.</p><p>A standout feature of Video SDK is its <strong>inherent versatility</strong>, a quality that resonates through its <strong>cross-platform</strong> compatibility. It effortlessly spans an impressive array of programming languages and frameworks, encompassing the likes of <strong>JavaScript</strong>, <strong>React JS</strong>, <strong>React Native</strong>, <strong>Android</strong>, <strong>Flutter</strong>, and <strong>iOS</strong>.</p><h3 id="features-offered-by-videosdk">Features offered by VideoSDK</h3>
<ul><li>High availability with zero maintenance</li><li><strong>Unlimited parallel room</strong> in real-time</li><li>Support up to <strong>300 attendees,</strong> including 50 presenters</li><li><strong>Global Infrastructure</strong> for every use case.</li><li>100% Fully <strong>customizable UI</strong></li><li>Accelerate your time-to-market with our <strong>code samples</strong></li><li>Customize <strong>template layouts,</strong> in any orientation</li><li>PubSub feature to <strong>build engaging features.</strong></li></ul>
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Your Page Title</title>
	<!-- Include Tailwind CSS -->
	<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</link></meta></meta></head>

<body>
	<div class="relative w-full overflow-hidden rounded-2xl bg-gradient-to-b from-pink-700 to-purple-900 p-4 text-center shadow-xl">
		<h3 class="mx-auto text-3xl font-bold tracking-tight text-white sm:text-2xl" style="margin-top: 3px; margin-bottom: 12px;">
			Schedule a Demo with Our Live Video Expert!
		</h3>
		<p class="mx-auto mt-3 max-w-xl text-sm text-gray-400">
			Discover how VideoSDK can help you build a cutting-edge real-time video app.
			<span class="font-semibold text-lato"/>
		</p>
		<div class="mt-4 flex items-center justify-center">
			<a href="https://www.videosdk.live/contact" class="rounded-md bg-white px-8 py-3 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white" target="_blank" style="text-decoration: none;color: black;" data-faitracker-click-bind="true">
				Book a call
			</a>	
		</div>
		
	</div>
</body>

</html>
<!--kg-card-end: html-->
<h2 id="2-twilio-enhancing-phone-services-with-programmable-voice-api">2. Twilio: Enhancing Phone Services with Programmable Voice API</h2>
<ul><li>Twilio is a widely known programmable voice API that aims to enhance phone services by enabling users to engage in phone calls and manage text messaging.</li><li>While it aspires to facilitate personalized interactions and engage users on a broad scale, there are certain considerations worth noting.</li><li>The REST API does offer voice chat capabilities, yet its implementation for routine purposes might be accompanied by certain limitations.</li><li>Additionally, while it provides access to carrier networks and tools to address communication challenges, there could be certain complexities associated with solving these issues.</li></ul><blockquote>
<p>See how Twilio compares with its <a href="https://www.videosdk.live/blog/twilio-video-competitors">competitors</a></p>
</blockquote>
<h2 id="3-mirrorfly-white-label-voice-api-for-unlimited-communication">3. MirrorFly: White-Label Voice API for Unlimited Communication</h2>
<ul><li>There's no need for different <a href="https://www.videosdk.live/developer-hub/sip/what-is-session-initiation-protocol-sip" rel="noreferrer">SIP</a> and voice call APIs for each feature MirrorFly covers everything with its single platform. As a leading voice and video API provider, MirrorFly offers a customized self-hosted solution that covers everything without any limitations. From unlimited audio conferencing to WebRTC video capabilities, this API platform provides complete flexibility to developers.</li><li>MirrorFly voice SDK platform<strong> </strong>is best for its global infrastructure and flexible hosting options. Users can choose between on-cloud/on-premise hosting and deployment on their own servers.</li><li>Our key features include Unlimited one-on-one and group calls, 100% customizable voice API, SIP/VoIP calls, and more.</li></ul><h2 id="4-agora-real-time-voice-calls-with-cross-platform-support">4. Agora: Real-Time Voice Calls with Cross-Platform Support</h2>
<ul><li>Although Agora's voice call API offers real-time voice interactions and the convenience of cross-platform support, some users have reported occasional <strong>connectivity issues</strong> and a <strong>learning curve</strong> when integrating the API into their applications. </li><li>It's important to thoroughly test the API within your specific use case to ensure its performance meets your <strong>expectations</strong> and <strong>requirements</strong>.</li></ul><blockquote>
<p>See how Agora compares with its <a href="https://www.videosdk.live/blog/agora-competitors">competitors</a></p>
</blockquote>
<h2 id="5-sendbird-proven-infrastructure-with-integration-challenges">5. Sendbird: Proven Infrastructure with Integration Challenges</h2>
<ul><li>While SendBird offers a proven managed infrastructure for voice communication, some users have reported occasional challenges with the integration process and a learning curve when using the APIs.</li><li>Additionally, the pricing structure might not be the most budget-friendly option for smaller businesses or startups.</li><li>It's recommended to thoroughly assess your project's requirements and budget before committing to SendBird's voice API.</li></ul><h2 id="6-plivo-comprehensive-voice-and-text-integration">6. Plivo: Comprehensive Voice and Text Integration</h2>
<ul><li>While Plivo does provide a wide range of carrier network connections and the ability to embed voice calling and text messaging into apps, some users have encountered <strong>challenges</strong> in terms of the <strong>complexity</strong> of the API documentation and <strong>integration process</strong>. </li><li>Additionally, there have been reports of occasional <strong>latency issues</strong> during voice calls. </li><li>It's important to carefully review the documentation and consider the potential learning curve before opting for Plivo's voice-calling APIs. </li></ul><h2 id="7-sinch-communication-apis-with-quality-concerns">7. Sinch: Communication APIs with Quality Concerns</h2>
<ul><li>While Sinch does offer a range of communication APIs, including voice calls, some users have expressed concerns about the <strong>quality</strong> and <strong>reliability</strong> of the voice calls when using their APIs.</li><li>Reports of <strong>call drops</strong> and <strong>audio quality</strong> issues have been noted in certain cases.</li><li>It's important to thoroughly test Sinch's voice APIs for your specific use case to ensure that the <strong>call quality</strong> meets your standards and that there are no unexpected <strong>interruptions</strong> during critical communication moments.</li></ul><h2 id="8-enablex-rich-voice-calls-with-user-experience">8. EnableX: Rich Voice Calls with User Experience</h2>
<ul><li>While EnableX does offer a range of voice calling features through its APIs, some users have reported challenges with the overall user experience and the quality of voice calls.</li><li><strong>Delays</strong> in call setup, <strong>audio disruptions</strong>, and occasional <strong>call drops</strong> have been reported by certain users, impacting the seamless communication experience that is essential for audio-calling applications.</li><li>It's recommended to thoroughly evaluate EnableX's voice calling capabilities and conduct extensive testing to ensure that the platform meets your <strong>performance</strong> and <strong>reliability</strong> expectations.</li></ul><h2 id="9-vonage">9. Vonage</h2>
<ul><li>While Vonage's voice chat API does bring innovative features to the table, some users have reported <strong>challenges</strong> with the <strong>integration</strong> and <strong>customization</strong> process.</li><li>The flexibility touted by the API might come with a learning curve, and developers might find themselves needing to invest <strong>additional time</strong> to fully adapt the API to their specific business needs.</li><li>Furthermore, the <strong>voice control</strong> and <strong>voice bot features</strong>, while promising, may <strong>require careful implementation</strong> and tuning to achieve the desired level of performance and user satisfaction.</li><li>It's advised to thoroughly assess the API's documentation and support resources to ensure smooth integration and optimal utilization of its advanced voice features.</li></ul><blockquote>
<p>See how Vonage compares with its <a href="https://www.videosdk.live/blog/vonage-competitors">competitors</a></p>
</blockquote>
<h2 id="10-messagebird">10. Messagebird</h2>
<ul><li>While MessageBird offers a range of communication channels and features, some users have highlighted certain <strong>limitations</strong> in the voice API's <strong>performance</strong> and <strong>reliability</strong>. </li><li>Reports suggest that occasional <strong>call drops</strong> or <strong>delays</strong> might occur, which could impact the quality of real-time voice communication. </li><li>Additionally, the <strong>pricing structure</strong> for MessageBird's voice API might <strong>not</strong> be the most <strong>cost-effective</strong> solution for businesses with high call volumes, as the <strong>costs can escalate</strong> with increased usage. </li><li>Prospective users should carefully evaluate the API's performance and pricing against their specific requirements to determine whether it aligns well with their communication needs.</li></ul><h2 id="elevate-your-audio-calling-app-with-the-ideal-audio-calling-api-integration-today">Elevate Your Audio Calling App with the Ideal Audio Calling API Integration Today</h2>
<p>Embracing the power of voice communication, numerous platforms have emerged, catering to the global demand for interactive conversations. This comprehensive article dives into the realm of voice chat APIs, presenting an array of 10 prominent options that expedite the creation of voice call applications with efficiency and minimal resources.</p><p>Among these, <a href="https://www.videosdk.live/signup/">VideoSDK</a>'s voice-call API stands as a standout recommendation, celebrated for its exceptional attributes and robust support. Notably, Video SDK's offering boasts the remarkable capability of <strong>ultra-low latency</strong>, empowering developers to craft applications that seamlessly accommodate <strong>up to 10,000</strong> users per audio call.</p><h2 id="conclusion">Conclusion</h2><p>The best voice call APIs in 2026 give your team production-grade real-time audio without owning global media infrastructure. VideoSDK leads for multi-platform SDK coverage and unified pricing, while Twilio, Agora, Sendbird, Plivo, Sinch, EnableX, Vonage, and MessageBird each fit specific scale, PSTN, compliance, and budget profiles. Run a timed proof of concept in your target geographies, model hidden costs, and validate compliance before committing. Sign up for a free VideoSDK account to test your first voice session in under ten minutes.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-are-the-best-voice-call-apis">What are the best voice call APIs?</h3><p>The best voice call APIs in 2026 are VideoSDK, Twilio, MirrorFly, Agora, Sendbird, Plivo, Sinch, EnableX, Vonage, and MessageBird. VideoSDK ranks first for teams needing fast multi-platform SDK integration with transparent per-minute audio pricing. The right choice depends on your participant count, PSTN requirements, compliance needs, and total cost at projected scale.</p><h3 id="what-is-a-voice-call-api-1">What is a voice call API?</h3><p>A voice call API is a programmatic interface that lets developers embed real-time bidirectional audio into applications through REST endpoints and client SDKs. The API provider operates signaling servers, TURN relays, and media routing infrastructure so your team does not build WebRTC stacks from scratch. Your application creates sessions via API calls and participants join through platform-specific SDKs.</p><h3 id="how-much-does-a-voice-call-api-cost">How much does a voice call API cost?</h3><p>Voice call API costs typically range from $0.0006 to $0.014 per participant-minute depending on the provider and whether the session includes PSTN bridging. Additional charges apply for cloud recording ($0.0025 to $0.10 per minute), transcription, PSTN termination, storage, and support tiers. Most providers offer free monthly minute allocations between 2,000 and 10,000 minutes for development and testing.</p><h3 id="what-features-should-a-voice-calling-sdk-include">What features should a voice calling SDK include?</h3><p>A production-ready voice calling SDK should include one-to-one and group calling, microphone mute and device switching, noise suppression, echo cancellation, adaptive audio bitrate, cloud recording, and cross-platform support for web and mobile. Advanced features like real-time transcription, push-to-talk, PSTN bridging, and PubSub messaging differentiate platforms for gaming, telehealth, and customer support use cases.</p><h3 id="is-videosdk-better-than-twilio-for-voice-calling">Is VideoSDK better than Twilio for voice calling?</h3><p>VideoSDK is better than Twilio for teams prioritizing in-app voice-first multi-platform SDK integration with unified conferencing and live streaming pricing. Twilio is better for products where PSTN termination, programmable IVR, and SMS are primary channels alongside in-app voice. Run a proof of concept on your target platforms and compare total monthly cost including recording and PSTN fees.</p><h3 id="can-you-build-voice-calling-without-an-api">Can you build voice calling without an API?</h3><p>You can build voice calling without a managed API by implementing raw WebRTC with self-hosted signaling and SFU servers using open-source projects like Jitsi or LiveKit. This approach requires dedicated engineering expertise for NAT traversal, codec negotiation, cross-platform SDK maintenance, and global infrastructure operations. Managed voice call APIs trade per-minute fees for faster time-to-market and operational reliability.</p><h3 id="how-do-you-test-a-voice-call-api-before-production">How do you test a voice call API before production?</h3><p>Test a voice call API by implementing join, leave, mute, and recording on every target platform, then throttling network speed to 3G and simulating 20 to 30% packet loss. Measure time-to-first-audio, voice continuity during packet loss, and automatic reconnection after network drops. Load-test at twice your projected peak concurrent sessions and validate compliance documentation for your industry.</p>]]></content:encoded></item><item><title><![CDATA[How to Build 1on1 Video Chat App in Kotlin for Android?]]></title><description><![CDATA[Learn how to build a 1-to-1 video chat app on Android using VideoSDK's Kotlin SDK. Covers setup, two-activity architecture, production hardening, and SDK comparison for two-participant video calls.]]></description><link>https://www.videosdk.live/blog/1-to-1-video-chat-app-on-android-using-videosdk</link><guid isPermaLink="false">63c0e689bd44f53bde5d069e</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 17 Jan 2025 11:18:00 GMT</pubDate><media:content url="http://assets.videosdk.live/static-assets/ghost/2023/01/Android-meme--2-.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>A 1-to-1 video chat app on Android using VideoSDK connects two participants in a shared meeting room through VideoSDK's Kotlin SDK. Add the rtc-android-sdk dependency, build Join and Meeting activities, and bind local and remote video streams. VideoSDK handles signaling, TURN routing, and codec negotiation without custom WebRTC infrastructure.</blockquote><img src="http://assets.videosdk.live/static-assets/ghost/2023/01/Android-meme--2-.jpg" alt="How to Build 1on1 Video Chat App in Kotlin for Android?"/><p>A telehealth patient who waits fifteen seconds for a doctor's video feed to appear abandons the session before diagnosis begins. Building a 1-to-1 video chat app on Android using VideoSDK gives Kotlin teams a two-screen architecture (join and meeting) backed by managed WebRTC infrastructure instead of months spent operating TURN clusters and signaling servers. This article defines the 1-to-1 pattern, compares SDK options, covers production trade-offs most tutorials skip, and walks through a complete VideoSDK integration you can run on two Android devices today.</p><h2 id="goals">Goals</h2><p>By the end of this blog, you will be able to:</p><ul><li>Understand what VideoSDK is.</li><li>Create a Video SDK account and generate a token.</li><li>Create a 1-to-1 video chat app using Android and Video SDK.</li></ul><figure class="kg-card kg-image-card"><img src="http://assets.videosdk.live/static-assets/ghost/2023/01/meeting_screen-1--1-.jpg" class="kg-image" alt="How to Build 1on1 Video Chat App in Kotlin for Android?" loading="lazy" width="270" height="567"/></figure><h2 id="what-is-videosdk">What is VideoSDK?</h2><p>VideoSDK is a versatile platform that empowers developers across the USA &amp; India to create rich in-app experiences by embedding real-time video, voice, recording, live streaming, and messaging functionalities. Available in JavaScript, ReactJS, React-Native, iOS, <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/getting-started">Android</a>, and Flutter, VideoSDK allows for seamless integration into diverse application frameworks. Additionally, VideoSDK offers a pre-built SDK designed for rapid deployment, enabling developers in the US &amp; India to integrate sophisticated real-time communication features with their applications in just 10 minutes.</p><p><strong>✨ Awesome, right?</strong></p><p>Let's create a 1-to-1 video calling in Kotlin Android using the VideoSDK. But first, we need to create a VideoSDK account and generate a token.</p><h3 id="set-up-your-videosdk-account-and-generate-a-token">Set up your VideoSDK account and generate a token.</h3><ul><li>A Video SDK Token (<a href="https://app.videosdk.live/api-keys?utm_source=google&amp;utm_medium=blog&amp;utm_campaign=1-to-1+video+chat+app+on+android+kotlin">Dashboard &gt; Api-Key</a>) (<a href="https://youtu.be/RLOA0U62tOc">Video Tutorial</a>)</li></ul>
<!--kg-card-begin: html-->
<iframe type="text/html" frameborder="0" width="560" height="315" src="https://www.youtube.com/embed/RLOA0U62tOc" allowfullscreen=""/>
<!--kg-card-end: html-->
<h3 id="%EF%B8%8F-prerequisites-setup-of-the-project">?️ Prerequisites &amp; Setup of the project</h3>
<p>Before proceeding, ensure that your development environment meets the following requirements:</p><ul><li>Java Development Kit.</li><li>Android <a href="https://developer.android.com/studio/">Studio</a> 3.0 or later.</li><li>Android SDK API Level 21 or higher.</li><li>A mobile device that runs Android 5.0 or later.</li></ul><h3 id="create-a-new-project">Create a new project</h3>
<ul>
<li>Let’s start by creating a new project. In Android Studio, create a Phone and Tablet Android project with an Empty Activity.</li>
</ul>
<figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://assets.videosdk.live/static-assets/ghost/2023/01/android_new_project.png" class="kg-image" alt="How to Build 1on1 Video Chat App in Kotlin for Android?" loading="lazy" width="899" height="652"><figcaption><span style="white-space: pre-wrap;">Create a new Android project</span></figcaption></img></figure><ul>
<li>The next step is to provide a name. We will name it as OneToOneDemo.</li>
</ul>
<figure class="kg-card kg-image-card kg-card-hascaption"><img src="http://assets.videosdk.live/static-assets/ghost/2023/01/name_project.png" class="kg-image" alt="How to Build 1on1 Video Chat App in Kotlin for Android?" loading="lazy" width="899" height="652"><figcaption><span style="white-space: pre-wrap;">Setting name for Android project</span></figcaption></img></figure><h3 id="integrating-videosdk-into-your-android-app">Integrating VideoSDK into Your Android App</h3>
<ul>
<li><strong>Add the repository to the project's <code>settings.gradle</code> file.</strong></li>
</ul>
<pre><code class="language-js">dependencyResolutionManagement{
  repositories {
    // ...
    google()
    mavenCentral()
    maven { url 'https://jitpack.io' }
    maven { url "https://maven.aliyun.com/repository/jcenter" }
  }
}</code></pre><ul>
<li><strong>Add the following dependency to your app's <code>build.gradle</code>.</strong></li>
</ul>
<pre><code class="language-js">dependencies {
  implementation 'live.videosdk:rtc-android-sdk:0.1.13'

  // library to perform Network call to generate a meeting id
  implementation 'com.amitshekhar.android:android-networking:1.0.2'

  // other app dependencies
  }</code></pre><blockquote>If your project has set <code>android.useAndroidX=true</code>, then set <code>android.enableJetifier=true</code> in the <code>gradle.properties</code> file to migrate your project to AndroidX and avoid duplicate class conflict.</blockquote><ul>
<li><strong>Add permissions to your project</strong></li>
</ul>
<p>In <code>/app/Manifests/AndroidManifest.xml</code>, add the following permissions after <code>&lt;/application&gt;</code>.</p><pre><code class="language-js">&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
&lt;uses-permission android:name="android.permission.CAMERA" /&gt;</code></pre><h2 id="build-1on1-video-call-app-on-android">Build 1on1 Video Call App on Android</h2>
<h3 id="step-1-android-video-chat-sdk-structure-of-project">STEP 1: Android Video Chat SDK Structure of Project</h3><p>We will create two screens. The first screen is <code>Joining screen</code>, which allows the user to create/join the meeting, and the other is <code>Meeting screen</code> , which will show participants a Whatsapp-like view. </p><p>Our project structure would look like this.</p><pre><code class="language-js">   app
   ├── java
   │    ├── packagename
   │         ├── JoinActivity
   │         ├── MeetingActivity
   ├── res
   │    ├── layout
   │    │    ├── activity_join.xml
   │    │    ├── activity_meeting.xml</code></pre><blockquote>You have to set <code>JoinActivity</code> as Launcher activity.</blockquote><ul><li><strong>Creating Joining Screen</strong></li></ul><p>Create a new Activity named <code>JoinActivity</code></p><h3 id="step-2android-video-chat-sdk-creating-ui-for-joining-screen">STEP 2:Android Video Chat SDK Creating UI for Joining Screen</h3>
<p>The Joining screen will include:</p><ol><li><strong>Create Button</strong> - This button will create a new meeting for you.</li><li><strong>TextField for Meeting ID</strong> - This text field will contain the meeting ID you want to join.</li><li><strong>Join Button</strong> - This button will join the meeting with <code>meetingId</code> you provided.</li></ol><p>In <code>/app/res/layout/activity_join.xml</code> file, replace the content with the following.</p><pre><code class="language-js">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".JoinActivity"&gt;

    &lt;com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/material_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:contentInsetStart="0dp"
        android:background="?attr/colorPrimary"
        app:titleTextColor="@color/white" /&gt;

    &lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"&gt;


        &lt;Button
            android:id="@+id/btnCreateMeeting"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="16dp"
            android:text="Create Meeting" /&gt;

        &lt;TextView
            style="@style/TextAppearance.AppCompat.Headline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="OR" /&gt;

        &lt;com.google.android.material.textfield.TextInputLayout        	style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginVertical="16dp"
            android:hint="Enter Meeting ID"&gt;

            &lt;EditText
                android:id="@+id/etMeetingId"
                android:layout_width="250dp"
                android:layout_height="wrap_content" /&gt;
        &lt;/com.google.android.material.textfield.TextInputLayout&gt;

        &lt;Button
            android:id="@+id/btnJoinMeeting"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Join Meeting" /&gt;
    &lt;/LinearLayout&gt;

&lt;/LinearLayout&gt;</code></pre><h3 id="step-3-android-video-chat-sdk-integration-of-create-meeting-api">STEP 3: Android Video Chat SDK Integration of Create Meeting API</h3>
<ol>
<li>Create a field <code>sampleToken</code> in <code>JoinActivity</code> which will hold the generated token from the <a href="https://app.videosdk.live/api-keys">Video SDK dashboard</a>. This token will be used in the Video SDK config as well as generating meetingId.</li>
</ol>
<pre><code class="language-js">class JoinActivity : AppCompatActivity() {

  //Replace with the token you generated from the Video SDK Dashboard
  private var sampleToken = ""

  override fun onCreate(savedInstanceState: Bundle?) {
    //...
  }
}</code></pre><ol start="2">
<li>On the <strong>Join Button</strong> <code>onClick</code> event, we will navigate to <code>MeetingActivity</code> with token and meetingId.</li>
</ol>
<pre><code class="language-js">class JoinActivity : AppCompatActivity() {

   //Replace with the token you generated from the VideoSDK Dashboard
   private var sampleToken = "" 

   override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_join)

        val btnCreate = findViewById&lt;Button&gt;(R.id.btnCreateMeeting)
        val btnJoin = findViewById&lt;Button&gt;(R.id.btnJoinMeeting)
        val etMeetingId = findViewById&lt;EditText&gt;(R.id.etMeetingId)

		//set title
        val toolbar = findViewById&lt;Toolbar&gt;(R.id.material_toolbar)
        toolbar.title = "OneToOneDemo"
        setSupportActionBar(toolbar)
        
        btnCreate.setOnClickListener { v: View? -&gt;
            // we will explore this method in the next step
            createMeeting(sampleToken)
        }
        btnJoin.setOnClickListener { v: View? -&gt;
            val intent = Intent(this@JoinActivity, MeetingActivity::class.java)
            intent.putExtra("token", sampleToken)
            intent.putExtra("meetingId", etMeetingId.text.toString())
            startActivity(intent)
        }
    }

    private fun createMeeting(token: String) {
    }
}</code></pre><ol start="3">
<li>For the <strong>Create Button</strong>, under <code>createMeeting</code> method we will generate meetingId by calling API and navigating to <code>MeetingActivity</code> with token and generated meetingId.</li>
</ol>
<pre><code class="language-js">class JoinActivity : AppCompatActivity() {
  //...onCreate
 private fun createMeeting(token: String) {
    // we will make an API call to VideoSDK Server to get a roomId
    AndroidNetworking.post("https://api.videosdk.live/v2/rooms")
      .addHeaders("Authorization", token) //we will pass the token in the Headers
      .build()
      .getAsJSONObject(object : JSONObjectRequestListener {
          override fun onResponse(response: JSONObject) {
              try {
                  // response will contain `roomId`
                  val meetingId = response.getString("roomId")

                  // starting the MeetingActivity with received roomId and our sampleToken
                  val intent = Intent(this@JoinActivity, MeetingActivity::class.java)
                  intent.putExtra("token", sampleToken)
                  intent.putExtra("meetingId", meetingId)
                  startActivity(intent)
              } catch (e: JSONException) {
                  e.printStackTrace()
              }
          }

          override fun onError(anError: ANError) {
              anError.printStackTrace()
                    Toast.makeText(
                        this@JoinActivity, anError.message,
                        Toast.LENGTH_SHORT
                    ).show()
          }
      })
  }
}</code></pre><ol start="4">
<li>Our App is completely based on audio and video commutation, that's why we need to ask for runtime permissions <code>RECORD_AUDIO</code> and <code>CAMERA</code>. So, we will implement permission logic on <code>JoinActivity</code>.</li>
</ol>
<pre><code class="language-js">class JoinActivity : AppCompatActivity() {
    companion object {
        private const val PERMISSION_REQ_ID = 22
        private val REQUESTED_PERMISSIONS = arrayOf(
            Manifest.permission.RECORD_AUDIO,
            Manifest.permission.CAMERA
        )
    }

  private fun checkSelfPermission(permission: String, requestCode: Int): Boolean {
        if (ContextCompat.checkSelfPermission(this, permission) !=
            PackageManager.PERMISSION_GRANTED)
        {
            ActivityCompat.requestPermissions(this, REQUESTED_PERMISSIONS, requestCode)
            return false
        }
        return true
    }

  override fun onCreate(savedInstanceState: Bundle?) {
    //... button listeneres
    checkSelfPermission(REQUESTED_PERMISSIONS[0], PERMISSION_REQ_ID)
    checkSelfPermission(REQUESTED_PERMISSIONS[1], PERMISSION_REQ_ID)
  }
}</code></pre><blockquote>You will get <code>Unresolved reference: MeetingActivity</code> error, but don't worry. It will be solved automatically once you create <code>MeetingActivity</code>.</blockquote><ol start="5">
<li>The Joining screen is now complete, and it is time to create the participant's view in the Meeting screen. The Joining screen will look like this:</li>
</ol>
<figure class="kg-card kg-image-card"><img src="http://assets.videosdk.live/static-assets/ghost/2023/01/joining_screen.jpg" class="kg-image" alt="How to Build 1on1 Video Chat App in Kotlin for Android?" loading="lazy" width="297" height="600"/></figure><p><strong>Creating Meeting Screen</strong><br>Create a new Activity named <code>MeetingActivity</code>.</br></p><h3 id="step-4-video-chat-android-sdk-creating-the-ui-for-meeting-screen">STEP 4: Video Chat Android SDK Creating the UI for Meeting Screen</h3>
<p>In <code>/app/res/layout/activity_meeting.xml</code> file, replace the content with the following.</p><pre><code class="language-js">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:animateLayoutChanges="true"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MeetingActivity"&gt;

    &lt;com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/material_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/black"
        app:contentInsetStart="0dp"
        app:titleTextColor="@color/white"&gt;

        &lt;LinearLayout
            android:id="@+id/meetingLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:layout_marginTop="10dp"
            android:orientation="horizontal"&gt;

            &lt;RelativeLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"&gt;

                &lt;TextView
                    android:id="@+id/txtMeetingId"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:fontFamily="sans-serif-medium"
                    android:textColor="@color/white"
                    android:textFontWeight="600"
                    android:textSize="16sp" /&gt;

                &lt;ImageButton
                    android:id="@+id/btnCopyContent"
                    android:layout_width="22dp"
                    android:layout_height="22sp"
                    android:layout_marginLeft="7dp"
                    android:layout_toRightOf="@+id/txtMeetingId"
                    android:backgroundTint="@color/black"
                    android:src="@drawable/ic_outline_content_copy_24" /&gt;

            &lt;/RelativeLayout&gt;

        &lt;/LinearLayout&gt;

        &lt;LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end"
            android:layout_marginEnd="10dp"&gt;

            &lt;ImageButton
                android:id="@+id/btnSwitchCameraMode"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:background="@color/black"
                android:contentDescription="Switch Camera mode"
                android:src="@drawable/ic_baseline_flip_camera_android_24" /&gt;

        &lt;/LinearLayout&gt;

    &lt;/com.google.android.material.appbar.MaterialToolbar&gt;

    &lt;FrameLayout
        android:id="@+id/participants_frameLayout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="@color/black"&gt;

        &lt;androidx.cardview.widget.CardView
            android:id="@+id/ParticipantCard"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginLeft="12dp"
            android:layout_marginTop="3dp"
            android:layout_marginRight="12dp"
            android:layout_marginBottom="3dp"
            android:backgroundTint="#2B3034"
            android:visibility="gone"
            app:cardCornerRadius="8dp"
            app:strokeColor="#2B3034"&gt;

            &lt;ImageView
                android:layout_width="150dp"
                android:layout_height="150dp"
                android:layout_gravity="center"
                android:src="@drawable/ic_baseline_person_24" /&gt;

            &lt;live.videosdk.rtc.android.VideoView
                android:id="@+id/participantView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:visibility="gone" /&gt;

        &lt;/androidx.cardview.widget.CardView&gt;

        &lt;FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"&gt;

        &lt;/FrameLayout&gt;

        &lt;androidx.cardview.widget.CardView
            android:id="@+id/LocalCard"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginLeft="12dp"
            android:layout_marginTop="3dp"
            android:layout_marginRight="12dp"
            android:layout_marginBottom="3dp"
            android:backgroundTint="#1A1C22"
            app:cardCornerRadius="8dp"
            app:strokeColor="#1A1C22"&gt;

            &lt;ImageView
                android:id="@+id/localParticipant_img"
                android:layout_width="150dp"
                android:layout_height="150dp"
                android:layout_gravity="center"
                android:src="@drawable/ic_baseline_person_24" /&gt;

            &lt;live.videosdk.rtc.android.VideoView
                android:id="@+id/localView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:visibility="gone" /&gt;

        &lt;/androidx.cardview.widget.CardView&gt;

    &lt;/FrameLayout&gt;
    
    &lt;!-- add bottombar here--&gt;

&lt;/LinearLayout&gt;</code></pre><pre><code class="language-js">&lt;com.google.android.material.bottomappbar.BottomAppBar
        android:id="@+id/bottomAppbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:animateLayoutChanges="true"
        android:backgroundTint="@color/black"
        android:gravity="center_horizontal"
        android:paddingVertical="5dp"
        tools:ignore="BottomAppBar"&gt;

        &lt;RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingStart="16dp"
            android:paddingEnd="16dp"&gt;

            &lt;com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/btnLeave"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:contentDescription="Leave Meeting"
                android:src="@drawable/ic_end_call"
                app:backgroundTint="#FF5D5D"
                app:fabSize="normal"
                app:tint="@color/white" /&gt;

            &lt;com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/btnMic"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="90dp"
                android:layout_toEndOf="@+id/btnLeave"
                android:contentDescription="Toggle Mic"
                android:src="@drawable/ic_mic_off"
                app:backgroundTint="@color/white"
                app:borderWidth="1dp"
                app:fabSize="normal" /&gt;

            &lt;com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/btnWebcam"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="90dp"
                android:layout_toEndOf="@+id/btnMic"
                android:backgroundTint="@color/white"
                android:contentDescription="Toggle Camera"
                android:src="@drawable/ic_video_camera_off"
                app:backgroundTint="@color/white"
                app:borderWidth="1dp"
                app:fabSize="normal" /&gt;

        &lt;/RelativeLayout&gt;

    &lt;/com.google.android.material.bottomappbar.BottomAppBar&gt;

</code></pre><blockquote>Copy required icons from <a href="https://github.com/videosdk-live/videosdk-rtc-android-kotlin-sdk-example/tree/one-to-one-demo/app/src/main/res/drawable">here</a> and paste in your project's `<code>res/drawable<br>res/drawable</br></code> folder.</blockquote><h3 id="step-5-video-chat-android-sdk-initializing-the-meeting">STEP 5: Video Chat Android SDK Initializing the Meeting</h3>
<p>After getting the token and meetingId from <code>JoinActivity</code> we need to,</p><ol>
<li>Initialize <strong>VideoSDK</strong></li>
<li>Configure <strong>VideoSDK</strong> with the token.</li>
<li>Initialize the meeting with required params such as <code>meetingId</code>, <code>participantName</code>, <code>micEnabled</code>, <code>webcamEnabled</code>,<code>participantId</code> and map of <code>CustomStreamTrack</code>.</li>
<li>Join the room with <code>meeting.join()</code> method.</li>
</ol>
<pre><code class="language-js">class MeetingActivity : AppCompatActivity() {

    private var meeting: Meeting? = null
    private var micEnabled = true
    private var webcamEnabled = true

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_meeting)

        //
        val toolbar = findViewById&lt;Toolbar&gt;(R.id.material_toolbar)
        toolbar.title = ""
        setSupportActionBar(toolbar)

        //
        val token = intent.getStringExtra("token")
        val meetingId = intent.getStringExtra("meetingId")

        // set participant name
        val localParticipantName = "Alex"

        // Initialize VideoSDK
        VideoSDK.initialize(applicationContext)

        // pass the token generated from api server
        VideoSDK.config(token)

        // create a new meeting instance
        meeting = VideoSDK.initMeeting(
            this@MeetingActivity, meetingId, localParticipantName,
            micEnabled, webcamEnabled, null, null
        )

        // join the meeting
        meeting?.join()

        //
        val textMeetingId = findViewById&lt;TextView&gt;(R.id.txtMeetingId)
        textMeetingId.text = meetingId

	 // copy meetingId to clipboard
        (findViewById&lt;View&gt;(R.id.btnCopyContent) as ImageButton).setOnClickListener {
            if (meetingId != null) {
                copyTextToClipboard(meetingId)
            }
        }
   }
      
      private fun copyTextToClipboard(text: String) {
        val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager
        val clip = ClipData.newPlainText("Copied text", text)
        clipboard.setPrimaryClip(clip)
        Toast.makeText(this@MeetingActivity, "Copied to clipboard!", Toast.LENGTH_SHORT).show()
    }

}</code></pre><h3 id="step-6-video-chat-android-sdk-handle-local-participant-media">? STEP 6: Video Chat Android SDK Handle Local Participant Media</h3>
<p>We need to implement clicks for the following <code>Views</code>:</p><ul><li><strong>Mic Button</strong></li><li><strong>Webcam Button</strong></li><li><strong>Switch Camera Button</strong></li><li><strong>Leave Button</strong></li></ul><p>Add the following implementation:</p><pre><code class="language-js">class MeetingActivity : AppCompatActivity() {

	private var btnWebcam: FloatingActionButton? = null
    private var btnMic: FloatingActionButton? = null
    private var btnLeave: FloatingActionButton? = null
    private var btnSwitchCameraMode: ImageButton? = null
    
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_meeting)
    
    //
    btnLeave = findViewById(R.id.btnLeave)
    btnSwitchCameraMode = findViewById(R.id.btnSwitchCameraMode)
    btnMic = findViewById(R.id.btnMic)
    btnWebcam = findViewById(R.id.btnWebcam)
        
    //...

    // actions
    setActionListeners()
  }
  
  private fun setActionListeners() {
        // Toggle mic
        btnMic!!.setOnClickListener { toggleMic() }

        // Toggle webcam
        btnWebcam!!.setOnClickListener { toggleWebCam() }

        // Leave meeting
        btnLeave!!.setOnClickListener { 
            // this will make the local participant leave the meeting
       	    meeting!!.leave()
        }

        // Switch camera
        btnSwitchCameraMode!!.setOnClickListener { 
        //a participant can change stream from front/rear camera during the meeting.
            meeting!!.changeWebcam() 
        }
    
   }
}</code></pre><pre><code class="language-js">private fun toggleMic() {
        if (micEnabled) {
            // this will mute the local participant's mic
            meeting!!.muteMic()
        } else {
             // this will unmute the local participant's mic
            meeting!!.unmuteMic()
        }
        micEnabled = !micEnabled  
    	// change mic icon according to micEnable status
        toggleMicIcon()
    }

    @SuppressLint("ResourceType")
    private fun toggleMicIcon() {
        if (micEnabled) {
            btnMic!!.setImageResource(R.drawable.ic_mic_on)
            btnMic!!.setColorFilter(Color.WHITE)
            var buttonDrawable = btnMic!!.background
            buttonDrawable = DrawableCompat.wrap(buttonDrawable!!)
            if (buttonDrawable != null) DrawableCompat.setTint(buttonDrawable, Color.TRANSPARENT)
            btnMic!!.background = buttonDrawable
        } else {
            btnMic!!.setImageResource(R.drawable.ic_mic_off)
            btnMic!!.setColorFilter(Color.BLACK)
            var buttonDrawable = btnMic!!.background
            buttonDrawable = DrawableCompat.wrap(buttonDrawable!!)
            if (buttonDrawable != null) DrawableCompat.setTint(buttonDrawable, Color.WHITE)
            btnMic!!.background = buttonDrawable
        }
    }</code></pre><pre><code class="language-js">private fun toggleWebCam() {
        if (webcamEnabled) {
        // this will disable the local participant webcam
            meeting!!.disableWebcam()
        } else {
        // this will enable the local participant webcam
            meeting!!.enableWebcam()
        }
        webcamEnabled = !webcamEnabled
        // change webCam icon according to webcamEnabled status
        toggleWebcamIcon()
    }

    @SuppressLint("ResourceType")
    private fun toggleWebcamIcon() {
        if (webcamEnabled) {
            btnWebcam!!.setImageResource(R.drawable.ic_video_camera)
            btnWebcam!!.setColorFilter(Color.WHITE)
            var buttonDrawable = btnWebcam!!.background
            buttonDrawable = DrawableCompat.wrap(buttonDrawable!!)
            if (buttonDrawable != null) DrawableCompat.setTint(buttonDrawable, Color.TRANSPARENT)
            btnWebcam!!.background = buttonDrawable
        } else {
            btnWebcam!!.setImageResource(R.drawable.ic_video_camera_off)
            btnWebcam!!.setColorFilter(Color.BLACK)
            var buttonDrawable = btnWebcam!!.background
            buttonDrawable = DrawableCompat.wrap(buttonDrawable!!)
            if (buttonDrawable != null) DrawableCompat.setTint(buttonDrawable, Color.WHITE)
            btnWebcam!!.background = buttonDrawable
        }
    }</code></pre><h3 id="step-7-setting-up-local-participant-view">STEP 7: Setting up Local participant view</h3>
<p>To set up participant view, we have to implement all the methods of <code>ParticipantEventListener</code> abstract Class and add the listener to <code>Participant</code> class using the <code>addEventListener()</code> method of <code>Participant</code> Class. <code>ParticipantEventListener</code> class has two methods :</p>
<ol>
<li><code>onStreamEnabled</code> - Whenever any participant enables mic/webcam in the meeting, <code>onStreamEnabled</code> the event will trigger and return <code>Stream</code>.</li>
<li><code>onStreamDisabled</code> - Whenever any participant disables mic/webcam in the meeting, <code>onStreamDisabled</code> the event will trigger and return <code>Stream</code>.</li>
</ol>
<pre><code class="language-js">class MeetingActivity : AppCompatActivity() {

    private var localView: VideoView? = null
    private var participantView: VideoView? = null
    
    private var localCard: CardView? = null
    private var participantCard: CardView? = null
    private var localParticipantImg: ImageView? = null
    
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_meeting)
    
    //... 
    
    localCard = findViewById(R.id.LocalCard)
    participantCard = findViewById(R.id.ParticipantCard)
    localView = findViewById(R.id.localView)
    participantView = findViewById(R.id.participantView)          		localParticipantImg = findViewById(R.id.localParticipant_img)
        
    //...

    // setup local participant view
    setLocalListeners()
  }

  private fun setLocalListeners() {
        meeting!!.localParticipant
            .addEventListener(object : ParticipantEventListener() {
                override fun onStreamEnabled(stream: Stream) {
                    if (stream.kind.equals("video", ignoreCase = true)) {
                        val track = stream.track as VideoTrack
                        localView!!.visibility = View.VISIBLE
                        localView!!.addTrack(track)
                        localView!!.setZOrderMediaOverlay(true)
                        (localCard as View?)!!.bringToFront()
                    }
                }

                override fun onStreamDisabled(stream: Stream) {
                    if (stream.kind.equals("video", ignoreCase = true)) {
                        localView!!.removeTrack()
                        localView!!.visibility = View.GONE
                    }
                }
            })
    }
}</code></pre><h3 id="step-8-setting-up-remote-participant-view">STEP 8: Setting up Remote participant view</h3>
<pre><code class="language-js">private val participantEventListener: ParticipantEventListener =
        object : ParticipantEventListener() {
        // trigger when participant enabled mic/webcam
            override fun onStreamEnabled(stream: Stream) {
                if (stream.kind.equals("video", ignoreCase = true)) {
                    localView!!.setZOrderMediaOverlay(true)
                    (localCard as View?)!!.bringToFront()
                    val track = stream.track as VideoTrack
                    participantView!!.visibility = View.VISIBLE
                    participantView!!.addTrack(track)
                }
            }

	// trigger when participant disabled mic/webcam
            override fun onStreamDisabled(stream: Stream) {
                if (stream.kind.equals("video", ignoreCase = true)) {
                    participantView!!.removeTrack()
                    participantView!!.visibility = View.GONE
                }
            }
        }</code></pre><h3 id="step-9-handle-meeting-events-manage-participants-view">STEP 9: Handle meeting events &amp; manage participant's view</h3>
<ul>
<li>Add <code>MeetingEventListener</code> for listening events such as Meeting Join/Left and Participant Join/Left.</li>
</ul>
<pre><code class="language-js">class MeetingActivity : AppCompatActivity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_meeting)
    //...

    // handle meeting events
    meeting!!.addEventListener(meetingEventListener)
  }
  
  private val meetingEventListener: MeetingEventListener = object : MeetingEventListener() {
        override fun onMeetingJoined() {
        // change mic,webCam icon after meeting successfully joined
            toggleMicIcon()
            toggleWebcamIcon()
        }

        override fun onMeetingLeft() {
            if (!isDestroyed) {
                val intent = Intent(this@MeetingActivity, JoinActivity::class.java)
                startActivity(intent)
                finish()
            }
        }

        override fun onParticipantJoined(participant: Participant) {
        // Display local participant as miniView when other participant joined
            changeLocalParticipantView(true)
            Toast.makeText(
                this@MeetingActivity, participant.displayName + " joined",
                Toast.LENGTH_SHORT
            ).show()
            participant.addEventListener(participantEventListener)
        }

        override fun onParticipantLeft(participant: Participant) {
        // Display local participant as largeView when other participant left
            changeLocalParticipantView(false)
            Toast.makeText(
                this@MeetingActivity, participant.displayName + " left",
                Toast.LENGTH_SHORT
            ).show()
        }
    }
}</code></pre><ul>
<li><code>changeLocalParticipantView(isMiniView: Boolean)</code> function handles whether the video of a local participant is displayed as a MiniView or a LargeView.</li>
<li>If the meeting has only one participant (local participant), then the local participant is displayed as LargeView.</li>
<li>When another participant (other than the local participant) joins,<code>changeLocalParticipantView(true)</code> is called. As a result, the local participant is shown as MiniView, while the other participant is shown as LargeView.</li>
</ul>
<pre><code class="language-js">private fun changeLocalParticipantView(isMiniView: Boolean) {
        if (isMiniView) {
            // show localCard as miniView
            localCard!!.layoutParams =
                FrameLayout.LayoutParams(300, 430, Gravity.RIGHT or Gravity.BOTTOM)
            val cardViewMarginParams = localCard!!.layoutParams as MarginLayoutParams
            cardViewMarginParams.setMargins(30, 0, 60, 40)
            localCard!!.requestLayout()
            // set height-width of localParticipant_img
            localParticipantImg!!.layoutParams = FrameLayout.LayoutParams(150, 150, Gravity.CENTER)
            (localCard as View?)!!.bringToFront()
            participantCard!!.visibility = View.VISIBLE
        } else {
            // show localCard as largeView
            localCard!!.layoutParams =
                FrameLayout.LayoutParams(
                    ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.MATCH_PARENT
                )
            val cardViewMarginParams = localCard!!.layoutParams as MarginLayoutParams
            cardViewMarginParams.setMargins(30, 5, 30, 30)
            localCard!!.requestLayout()
            // set height-width of localParticipant_img
            localParticipantImg!!.layoutParams = FrameLayout.LayoutParams(400, 400, Gravity.CENTER)
            participantCard!!.visibility = View.GONE
        }
    }</code></pre><h3 id="step-10-destroying-everything">STEP 10: Destroying everything</h3>
<p>We need to release resources when the app is closed and is no longer being used. Override the <code>onDestroy</code> with the following code:</p><pre><code class="language-js">override fun onDestroy() {
        if (meeting != null) {
            meeting!!.removeAllListeners()
            meeting!!.localParticipant.removeAllListeners()
            meeting!!.leave()
            meeting = null
        }
        if (participantView != null) {
            participantView!!.visibility = View.GONE
            participantView!!.releaseSurfaceViewRenderer()
        }
        if (localView != null) {
            localView!!.visibility = View.GONE
            localView!!.releaseSurfaceViewRenderer()
        }
        super.onDestroy()
    }</code></pre><p>This is how the meeting screen will seem with two participants.</p><blockquote>
<p><code>java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.</code><br>
If you face this error at Runtime include these lines in <code>theme.xml</code> file.<br>
<code>&lt;item name="windowActionBar"&gt;false&lt;/item&gt;</code><br>
<code>&lt;item name="windowNoTitle"&gt;true&lt;/item&gt;</code></br></br></br></p>
</blockquote>
<h2 id="1-to-1-video-chat-app-demo">1-to-1 Video Chat App Demo</h2><p><strong>Tadaa!!</strong> Our app is ready. Easy, right? </p><figure class="kg-card kg-image-card"><img src="http://assets.videosdk.live/static-assets/ghost/2023/01/Add-a-heading.gif" class="kg-image" alt="How to Build 1on1 Video Chat App in Kotlin for Android?" loading="lazy" width="320" height="240"/></figure><p>I hope you enjoyed following along and collaborating on the development of a 1-to-1 video chat Android app using the Video SDK.<br><br>Install and run the app on two different devices and make sure that they are connected to the internet. You should expect it to work as shown in the video below:</br></br></p>
<!--kg-card-begin: html-->
<iframe type="text/html" frameborder="0" width="560" height="315" src="https://www.youtube.com/embed/Kj7jS3dbJFA" allowfullscreen=""/>
<!--kg-card-end: html-->
<blockquote><br>This app only supports 2 participant,it does not manage more than 2 participants. <a href="https://github.com/videosdk-live/videosdk-rtc-android-kotlin-sdk-example">If you want to handle more than 2 participants then checkout our Group chat example here.</a></br></blockquote><h2 id="conclusion">Conclusion</h2><p>In this blog, we learned what VideoSDK is, how to obtain an access token from the VideoSDK <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer"><strong>Dashboard</strong></a>, and how to make a video call on Android VideoSDK. Go ahead and create advanced features like screen-sharing, chat, and others. Browse Our <a href="https://docs.videosdk.live/" rel="noopener noreferrer">Documentation</a>.</p><p>To see the full implementation of the app, check out the GitHub repository: <a href="https://github.com/videosdk-live/videosdk-rtc-android-kotlin-sdk-example/tree/one-to-one-demo">https://github.com/videosdk-live/videosdk-rtc-android-kotlin-sdk-example/tree/one-to-one-demo</a></p><p>If you have any questions or comments, I invite you to <a href="https://discord.gg/Gpmj6eCq5u">Join the Video SDK Developer Discord</a> community.</p><h2 id="resources">Resources</h2><ul><li><a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/getting-started">Get Started with Android Documentation</a></li><li><a href="https://youtu.be/Kj7jS3dbJFA">Build an Android Video Calling App using Android Studio and Video SDK</a></li><li><a href="https://www.videosdk.live/blog/react-native-android-video-calling-app-with-callkeep">Build a React Native Android Video Calling App with ?Callkeep using ? Firebase and Video SDK</a></li><li><a href="https://www.videosdk.live/blog/video-calling-in-flutter">Build a Flutter Video Calling App with Video SDK</a></li></ul><p><br/></p><p/>]]></content:encoded></item><item><title><![CDATA[2024 Rewind: The Rise of Digital-Human Intelligence]]></title><description><![CDATA[As 2024 wraps up, it’s the perfect time to pause, reflect, and share some of the incredible things we’ve accomplished at VideoSDK this year. It’s been a year of building connections, empowering developers, and creating real impact around the world.
]]></description><link>https://www.videosdk.live/blog/2024-year-in-review</link><guid isPermaLink="false">6787c7e64556210426689ae4</guid><category><![CDATA[year-in-review]]></category><dc:creator><![CDATA[Sagar Kava]]></dc:creator><pubDate>Thu, 16 Jan 2025 16:50:59 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2025/01/Thumbnail.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Thumbnail.jpg" alt="2024 Rewind: The Rise of Digital-Human Intelligence"/><p>As 2024 wraps up, it’s the perfect time to pause, reflect, and share some of the incredible things we’ve accomplished at VideoSDK this year. It’s been a year of building connections, empowering developers, and creating real impact around the world.</p><p>Let’s take a look back at the milestones we’ve hit, the lives we’ve touched, and what’s next in our story.</p><h2 id="lives-we%E2%80%99ve-touched"><strong>Lives We’ve Touched</strong></h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Lives-we-touched.jpg" class="kg-image" alt="2024 Rewind: The Rise of Digital-Human Intelligence" loading="lazy" width="3840" height="2160"/></figure><p>In India, over 2.8 million people verified their identities effortlessly with our video KYC solution, saving time and building trust on a massive scale. In the MENA region, we bridged the gap between patients and doctors, enabling 50,000 medical consultations and improving access to healthcare. Around the world, we powered online interviews for more than 40,000 people, helping them unlock exciting career opportunities. And on a lighter note, we brought smiles to 76 million people who stayed connected with their loved ones through social apps.</p><h2 id="numbers-that-make-us-proud"><strong>Numbers That Make Us Proud</strong></h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Number-that-make-us-proud.jpg" class="kg-image" alt="2024 Rewind: The Rise of Digital-Human Intelligence" loading="lazy" width="3840" height="2160"/></figure><p>Every month, more than 1 million participants from over 150 countries rely on VideoSDK for smooth and uninterrupted communication. This year alone, our npm and pub.dev packages have been downloaded over 10 million times. With our SDK, developers have built over 5,000 apps, empowering innovative solutions across diverse industries.&nbsp;</p><h2 id="scaling-to-new-heights"><strong>Scaling to New Heights</strong></h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Scaling-to-new-heights-1.jpg" class="kg-image" alt="2024 Rewind: The Rise of Digital-Human Intelligence" loading="lazy" width="3840" height="2160"/></figure><p>We also pushed our infrastructure to new heights. Imagine handling 9060 concurrent sessions with 970 users at peak, and delivering 5+ TB of recordings. That’s the scale we’re talking about.</p><h2 id="a-year-of-exceptional-support"><strong>A Year of Exceptional Support</strong></h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Execptional-Customer-Support.jpg" class="kg-image" alt="2024 Rewind: The Rise of Digital-Human Intelligence" loading="lazy" width="3840" height="2160"/></figure><p>Of course, great products need great support, and our team showed up in a big way. This year, we resolved over 1027 support tickets, keeping our average resolution time under 3 hours. And here’s the cherry on top: our <strong>91% customer satisfaction score</strong> (CSAT). Knowing our users trust us and love what we do keeps us going.</p><h2 id="leaving-our-mark-at-global-tech-and-fintech-events"><strong>Leaving Our Mark at Global Tech and Fintech Events</strong></h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/event-1.jpg" class="kg-image" alt="2024 Rewind: The Rise of Digital-Human Intelligence" loading="lazy" width="3840" height="2160"/></figure><p>We showcased our innovative Agent-assisted &amp; Agentless KYC solution at the Global Fintech Fest (GFF), gaining significant interest from many BFSI giants. We also spoke at the Google Developers Group Surat (GDG Surat) event, sharing insights on 'Developer's role in building real-time human-digital worker ecosystems,' highlighting the evolving landscape of application building with the developer community.</p><h2 id="meet-the-future-of-ai"><strong>Meet the Future of AI</strong></h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2025/01/Character-SDK.jpg" class="kg-image" alt="2024 Rewind: The Rise of Digital-Human Intelligence" loading="lazy" width="3840" height="2160"/></figure><p>This year, we introduced <strong>Character SDK - </strong>a multimodal AI agent that can see, hear, and respond like never before. Its launch on Product Hunt was a moment to remember—earning us titles like&nbsp;</p><ul><li>#1 Product of the Day</li><li>#1 Product of the Week in the Developer Tool category</li><li>#2 Product of the Month in AI</li><li>#3 Product of the Month overall</li></ul><p>From creating AI companions that think, learn, and act, to simplifying workflows, Character SDK is shaping the future of technology in ways we couldn’t have imagined.</p><h2 id="looking-ahead"><strong>Looking Ahead</strong></h2><p>As we step into 2025, we’re filled with gratitude and excitement. Thank you for being a part of our journey this year. Here’s to pushing boundaries, making an impact, and creating even more meaningful connections in the year ahead.</p><p>Let’s make it amazing—together!</p>]]></content:encoded></item><item><title><![CDATA[How to build a 1-on-1 Video Chat App in Android with Java & VideoSDK]]></title><description><![CDATA[In this tutorial, You'll learn about a 1 on 1 video chat app. Also, a Step-by-Step Guide for building an Android video chat app using Java with VideoSDK.]]></description><link>https://www.videosdk.live/blog/1-on-1-video-chat</link><guid isPermaLink="false">63c7bfeabd44f53bde5d11b1</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Thu, 16 Jan 2025 05:21:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2023/06/1_1_android_conf-1.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2023/06/1_1_android_conf-1.jpg" alt="How to build a 1-on-1 Video Chat App in Android with Java & VideoSDK"/><p>Remote communication has become the most important part of communication after the pandemic. It will likely play a significant role in the future too. Today's mobile applications often include voice or video chat functionality. But it's extremely complex and takes a lot of time to build. This is where <a href="https://www.videosdk.live">VideoSDK</a> comes into the picture.</p><p>VideoSDK is a platform that allows developers to create rich in-app experiences such as embedding real-time video, voice, real-time recording, live streaming, and real-time messaging.<br><br>VideoSDK is available for <a href="https://en.wikipedia.org/wiki/JavaScript">JavaScript</a>, <a href="https://en.wikipedia.org/wiki/React_(software)">ReactJS</a>, <a href="https://en.wikipedia.org/wiki/React_Native">React-Native</a>, <a href="https://en.wikipedia.org/wiki/IOS">IOS</a>, <a href="https://en.wikipedia.org/wiki/Android_(operating_system)">Android,</a> and <a href="https://en.wikipedia.org/wiki/Flutter_(software)">Flutter</a> to be integrated seamlessly. VideoSDK also provides a Pre-built SDK that enables the opportunity to integrate real-time communication with your application in just 10 minutes!</br></br></p><p>Let's create a 1 on 1 video chat/call app using VideoSDK. But first, we need to create a VideoSDK account and generate the token.</p><h2 id="requirement">Requirement</h2><p>First of all, Your development environment should meet the following requirements:</p><ul><li><a href="https://www.oracle.com/in/java/technologies/downloads/">Java Development Kit.</a></li><li><a href="https://developer.android.com/studio">Android Studio</a> 3.0 or later.</li><li>Android SDK API Level 21 or higher.</li><li>A mobile device that runs Android 5.0 or later.</li></ul><h2 id="setup-the-project">Setup the project</h2><h3 id="step-1-create-a-new-project">STEP 1: Create a new project</h3><ul><li>Let’s start by creating a new project. In Android Studio, create a new project with an Empty Activity.</li><li>Then, provide a name. We will name it as OneToOneDemo.</li></ul><h3 id="step-2-integrate-videosdk">STEP 2: Integrate VideoSDK</h3><ul><li>Add the repository to <code>settings.gradle</code> file.</li></ul><pre><code class="language-javascript">dependencyResolutionManagement{
  repositories {
    // ...
    google()
    mavenCentral()
    maven { url 'https://jitpack.io' }
    maven { url "https://maven.aliyun.com/repository/jcenter" }
  }
}</code></pre><ul>
<li>Add the following dependencies in <code>build.gradle</code> file.</li>
</ul>
<pre><code class="language-javascript">dependencies {
  implementation 'live.videosdk:rtc-android-sdk:0.1.13'

  // library to perform Network call to generate a meeting id
  implementation 'com.amitshekhar.android:android-networking:1.0.2'

  // other app dependencies
  }</code></pre><blockquote>If your project has set <code>android.useAndroidX = true</code>, then set <code>android.enableJetifier = true</code> in the <code>gradle.properties</code> file to migrate your project to AndroidX and avoid duplicate class conflict.</blockquote><h3 id="step-3-add-permissions-to-your-project">STEP 3: Add permissions to your project</h3>
<p>In <code>/app/Manifests/AndroidManifest.xml</code>, add the following permissions after <code>&lt;/application&gt;</code>.</p><pre><code class="language-javascript">&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
&lt;uses-permission android:name="android.permission.CAMERA" /&gt;</code></pre><h3 id="step-4-getting-started-with-the-code">STEP 4: Getting started with the code!</h3>
<h4 id="a-structure-of-project">(a) Structure of project</h4>
<p>We'll create two screens. The first screen will be <code>Joining screen</code> that allows users to create/join the meeting, and another one is <code>Meeting screen</code> that will show participants like WhatsApp views. </p><p>Our project structure would look like this.</p><pre><code class="language-javascript">   app
   ├── java
   │    ├── packagename
   │         ├── JoinActivity
   │         ├── MeetingActivity
   ├── res
   │    ├── layout
   │    │    ├── activity_join.xml
   │    │    ├── activity_meeting.xml</code></pre><blockquote>You have to set <code>JoinActivity</code> as Launcher activity.</blockquote><h4 id="b-creating-joining-screen">(b) Creating Joining Screen</h4>
<p>Create a new Activity named <code>JoinActivity</code></p><h4 id="c-creating-ui-for-joining-the-screen">(c) Creating UI for Joining the Screen</h4>
<p>The Joining screen will include :</p><ol><li><strong>Create Button</strong> - Creates a new meeting.</li><li><strong>TextField for MeetingID</strong> - Contains the <code>meetingId</code> you want to join.</li><li><strong>Join Button</strong> - Joins the meeting with the <code>meetingId</code> provided.</li></ol><p>In <code>/app/res/layout/activity_join.xml</code> file, replace the content with the following.</p><pre><code class="language-javascript">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".JoinActivity"&gt;

    &lt;com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/material_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:contentInsetStart="0dp"
        android:background="?attr/colorPrimary"
        app:titleTextColor="@color/white" /&gt;

    &lt;LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"&gt;


        &lt;Button
            android:id="@+id/btnCreateMeeting"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="16dp"
            android:text="Create Meeting" /&gt;

        &lt;TextView
            style="@style/TextAppearance.AppCompat.Headline"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="OR" /&gt;

        &lt;com.google.android.material.textfield.TextInputLayout        	style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginVertical="16dp"
            android:hint="Enter Meeting ID"&gt;

            &lt;EditText
                android:id="@+id/etMeetingId"
                android:layout_width="250dp"
                android:layout_height="wrap_content" /&gt;
        &lt;/com.google.android.material.textfield.TextInputLayout&gt;

        &lt;Button
            android:id="@+id/btnJoinMeeting"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Join Meeting" /&gt;
    &lt;/LinearLayout&gt;

&lt;/LinearLayout&gt;</code></pre><h4 id="d-integration-of-create-meeting-api">(d) Integration of Create Meeting API</h4>
<p>You need to create a field <code>sampleToken</code> in <code>JoinActivity</code> that holds the generated token from the <a href="https://app.videosdk.live/api-keys">VideoSDK dashboard</a>. This token will be used in the VideoSDK config as well as generating meetingId.</p>
<pre><code class="language-javascript">public class JoinActivity extends AppCompatActivity {

  //Replace with the token you generated from the VideoSDK Dashboard
  private String sampleToken = ""; 

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    //...
  }
}</code></pre><p>On <strong>Join Button</strong> <code>onClick</code> the event, it will navigate to <code>MeetingActivity</code> with token and meetingId.</p>
<pre><code class="language-javascript">public class JoinActivity extends AppCompatActivity {

  //Replace with the token you generated from the VideoSDK Dashboard
  private String sampleToken =""; 

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_join);

    final Button btnCreate = findViewById(R.id.btnCreateMeeting);
    final Button btnJoin = findViewById(R.id.btnJoinMeeting);
    final EditText etMeetingId = findViewById(R.id.etMeetingId);

    //set title
    Toolbar toolbar = findViewById(R.id.material_toolbar);
    toolbar.setTitle("OneToOneDemo");
    setSupportActionBar(toolbar);
        
    btnCreate.setOnClickListener(v -&gt; {
      // we will explore this method in the next step
      createMeeting(sampleToken);
    });

    btnJoin.setOnClickListener(v -&gt; {
      Intent intent = new Intent(JoinActivity.this, MeetingActivity.class);
      intent.putExtra("token", sampleToken);
      intent.putExtra("meetingId", etMeetingId.getText().toString());
      startActivity(intent);
    });
  }

  private void createMeeting(String token) {
  }
}</code></pre><p>For the <strong>Create Button</strong>, under <code>createMeeting</code> method we will generate <code>meetingId</code> by calling API and navigating to <code>MeetingActivity</code> with token and generated meetingId.</p>
<pre><code class="language-javascript">public class JoinActivity extends AppCompatActivity {
  //...onCreate

  private void createMeeting(String token) {
      // we will make an API call to VideoSDK Server to get a roomId
      AndroidNetworking.post("https://api.videosdk.live/v2/rooms")
        .addHeaders("Authorization", token) //we will pass the token in the Headers
        .build()
        .getAsJSONObject(new JSONObjectRequestListener() {
            @Override
            public void onResponse(JSONObject response) {
                try {
                    // response will contain `roomId`
                    final String meetingId = response.getString("roomId");

                    // starting the MeetingActivity with received roomId and our sampleToken
                    Intent intent = new Intent(JoinActivity.this, MeetingActivity.class);
                    intent.putExtra("token", sampleToken);
                    intent.putExtra("meetingId", meetingId);
                    startActivity(intent);
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void onError(ANError anError) {
                anError.printStackTrace();
                Toast.makeText(JoinActivity.this, anError.getMessage(), Toast.LENGTH_SHORT).show();
            }
        });
  }
}</code></pre><p>Our App is completely based on audio and video commutation, that's why we need to ask for runtime permissions <code>RECORD_AUDIO</code> and <code>CAMERA</code>. So, we will implement permission logic on <code>JoinActivity</code>.</p>
<pre><code class="language-javascript">public class JoinActivity extends AppCompatActivity {
  private static final int PERMISSION_REQ_ID = 22;

  private static final String[] REQUESTED_PERMISSIONS = {
    Manifest.permission.RECORD_AUDIO,
    Manifest.permission.CAMERA
  };

  private boolean checkSelfPermission(String permission, int requestCode) {
    if (ContextCompat.checkSelfPermission(this, permission) != PackageManager.PERMISSION_GRANTED) {
      ActivityCompat.requestPermissions(this, REQUESTED_PERMISSIONS, requestCode);
      return false;
    }
    return true;
  }

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    //... button listeneres
    checkSelfPermission(REQUESTED_PERMISSIONS[0], PERMISSION_REQ_ID);
    checkSelfPermission(REQUESTED_PERMISSIONS[1], PERMISSION_REQ_ID);
  }
}</code></pre><blockquote>You'll get <code>Unresolved reference: MeetingActivity</code> error, but don't worry. It will be solved automatically once you create <code>MeetingActivity</code>.</blockquote><p>We're done with the Joining screen now, and it is time to create the participant's view in the Meeting screen.</p>
<h3 id="step-5-creating-meeting-screen">STEP 5: Creating Meeting Screen</h3>
<p>Create a new Activity named <code>MeetingActivity</code>.</p><h4 id="a-creating-the-ui-for-the-meeting-screen">(a) Creating the UI for the Meeting Screen</h4>
<p>In <code>/app/res/layout/activity_meeting.xml</code> file, replace the content with the following.</p><pre><code class="language-javascript">&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/mainLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:animateLayoutChanges="true"
    android:gravity="center"
    android:orientation="vertical"
    tools:context=".MeetingActivity"&gt;

    &lt;com.google.android.material.appbar.MaterialToolbar
        android:id="@+id/material_toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="@color/black"
        app:contentInsetStart="0dp"
        app:titleTextColor="@color/white"&gt;

        &lt;LinearLayout
            android:id="@+id/meetingLayout"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:layout_marginTop="10dp"
            android:orientation="horizontal"&gt;

            &lt;RelativeLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"&gt;

                &lt;TextView
                    android:id="@+id/txtMeetingId"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:fontFamily="sans-serif-medium"
                    android:textColor="@color/white"
                    android:textFontWeight="600"
                    android:textSize="16sp" /&gt;

                &lt;ImageButton
                    android:id="@+id/btnCopyContent"
                    android:layout_width="22dp"
                    android:layout_height="22sp"
                    android:layout_marginLeft="7dp"
                    android:layout_toRightOf="@+id/txtMeetingId"
                    android:backgroundTint="@color/black"
                    android:src="@drawable/ic_outline_content_copy_24" /&gt;

            &lt;/RelativeLayout&gt;

        &lt;/LinearLayout&gt;

        &lt;LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end"
            android:layout_marginEnd="10dp"&gt;

            &lt;ImageButton
                android:id="@+id/btnSwitchCameraMode"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:background="@color/black"
                android:contentDescription="Switch Camera mode"
                android:src="@drawable/ic_baseline_flip_camera_android_24" /&gt;

        &lt;/LinearLayout&gt;

    &lt;/com.google.android.material.appbar.MaterialToolbar&gt;

    &lt;FrameLayout
        android:id="@+id/participants_frameLayout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="@color/black"&gt;

        &lt;androidx.cardview.widget.CardView
            android:id="@+id/ParticipantCard"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginLeft="12dp"
            android:layout_marginTop="3dp"
            android:layout_marginRight="12dp"
            android:layout_marginBottom="3dp"
            android:backgroundTint="#2B3034"
            android:visibility="gone"
            app:cardCornerRadius="8dp"
            app:strokeColor="#2B3034"&gt;

            &lt;ImageView
                android:layout_width="150dp"
                android:layout_height="150dp"
                android:layout_gravity="center"
                android:src="@drawable/ic_baseline_person_24" /&gt;

            &lt;live.videosdk.rtc.android.VideoView
                android:id="@+id/participantView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:visibility="gone" /&gt;

        &lt;/androidx.cardview.widget.CardView&gt;

        &lt;FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"&gt;

        &lt;/FrameLayout&gt;

        &lt;androidx.cardview.widget.CardView
            android:id="@+id/LocalCard"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginLeft="12dp"
            android:layout_marginTop="3dp"
            android:layout_marginRight="12dp"
            android:layout_marginBottom="3dp"
            android:backgroundTint="#1A1C22"
            app:cardCornerRadius="8dp"
            app:strokeColor="#1A1C22"&gt;

            &lt;ImageView
                android:id="@+id/localParticipant_img"
                android:layout_width="150dp"
                android:layout_height="150dp"
                android:layout_gravity="center"
                android:src="@drawable/ic_baseline_person_24" /&gt;

            &lt;live.videosdk.rtc.android.VideoView
                android:id="@+id/localView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:visibility="gone" /&gt;

        &lt;/androidx.cardview.widget.CardView&gt;

    &lt;/FrameLayout&gt;
    
    &lt;!-- add bottombar here--&gt;

&lt;/LinearLayout&gt;</code></pre><pre><code class="language-javascript">&lt;com.google.android.material.bottomappbar.BottomAppBar
        android:id="@+id/bottomAppbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:animateLayoutChanges="true"
        android:backgroundTint="@color/black"
        android:gravity="center_horizontal"
        android:paddingVertical="5dp"
        tools:ignore="BottomAppBar"&gt;

        &lt;RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:paddingStart="16dp"
            android:paddingEnd="16dp"&gt;

            &lt;com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/btnLeave"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:contentDescription="Leave Meeting"
                android:src="@drawable/ic_end_call"
                app:backgroundTint="#FF5D5D"
                app:fabSize="normal"
                app:tint="@color/white" /&gt;

            &lt;com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/btnMic"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="90dp"
                android:layout_toEndOf="@+id/btnLeave"
                android:contentDescription="Toggle Mic"
                android:src="@drawable/ic_mic_off"
                app:backgroundTint="@color/white"
                app:borderWidth="1dp"
                app:fabSize="normal" /&gt;

            &lt;com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/btnWebcam"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginStart="90dp"
                android:layout_toEndOf="@+id/btnMic"
                android:backgroundTint="@color/white"
                android:contentDescription="Toggle Camera"
                android:src="@drawable/ic_video_camera_off"
                app:backgroundTint="@color/white"
                app:borderWidth="1dp"
                app:fabSize="normal" /&gt;

        &lt;/RelativeLayout&gt;

    &lt;/com.google.android.material.bottomappbar.BottomAppBar&gt;

</code></pre><blockquote>Copy required icons from <a href="https://github.com/videosdk-live/videosdk-rtc-android-kotlin-sdk-example/tree/one-to-one-demo/app/src/main/res/drawable">here</a> and paste in your project's <code>res/drawable<br>res/drawable</br></code> folder.</blockquote><h4 id="b-initializing-the-meeting">(b) Initializing the Meeting</h4>
<p>After getting the token and meetingId from <code>JoinActivity</code>, we need to</p><ul><li>Step 1: Initialize <strong>VideoSDK</strong></li><li>Step 2: Configure <strong>VideoSDK</strong> with the token.</li><li>Step 3: Initialize the meeting with required params such as <code>meetingId</code>, <code>participantName</code>, <code>micEnabled</code>, <code>webcamEnabled</code>,<code>participantId</code> and map of <code>CustomStreamTrack</code>.</li><li>Step 4: Join the room with <code>meeting.join()</code> method.</li></ul><pre><code class="language-javascript">public class MeetingActivity extends AppCompatActivity {

    private static Meeting meeting;
    private boolean micEnabled = true;
    private boolean webcamEnabled = true;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_meeting);

        //
        Toolbar toolbar = findViewById(R.id.material_toolbar);
        toolbar.setTitle("");
        setSupportActionBar(toolbar);

        //
        String token = getIntent().getStringExtra("token");
        final String meetingId = getIntent().getStringExtra("meetingId");

        // set participant name
        String localParticipantName = "Alex";

        // Initialize VideoSDK
        VideoSDK.initialize(getApplicationContext());

        // pass the token generated from api server
        VideoSDK.config(token);

        // create a new meeting instance
        meeting = VideoSDK.initMeeting(
                MeetingActivity.this, meetingId, localParticipantName,
                micEnabled, webcamEnabled, null, null
        );

        // join the meeting
        if (meeting != null) meeting.join();

        //
        TextView textMeetingId = findViewById(R.id.txtMeetingId);
        textMeetingId.setText(meetingId);

	 // copy meetingId to clipboard
         ((ImageButton) findViewById(R.id.btnCopyContent)).setOnClickListener(v -&gt; copyTextToClipboard(meetingId));

   }
      
      private void copyTextToClipboard(String text) {
        ClipboardManager clipboard = (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
        ClipData clip = ClipData.newPlainText("Copied text", text);
        clipboard.setPrimaryClip(clip);

        Toast.makeText(MeetingActivity.this, "Copied to clipboard!", Toast.LENGTH_SHORT).show();
    }

}</code></pre><h3 id="step-6-handle-local-participant-media">STEP 6: Handle Local Participant Media</h3>
<p>We need to implement clicks for the following <code>Views</code>:</p><ul><li>Mic Button</li><li>Webcam Button</li><li>Switch Camera Button</li><li>Leave Button</li></ul><p>Add the following implementation:</p><pre><code class="language-javascript">public class MeetingActivity extends AppCompatActivity {

	private FloatingActionButton btnWebcam, btnMic, btnLeave;
    private ImageButton btnSwitchCameraMode;
    
  @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_meeting);
    
    //
    btnMic = findViewById(R.id.btnMic);
    btnWebcam = findViewById(R.id.btnWebcam);
    btnLeave = findViewById(R.id.btnLeave);
    btnSwitchCameraMode = findViewById(R.id.btnSwitchCameraMode);
        
    //...

    // actions
    setActionListeners();
  }
  
  private void setActionListeners() {
        // Toggle mic
        btnMic.setOnClickListener(view -&gt; toggleMic());

        // Toggle webcam
        btnWebcam.setOnClickListener(view -&gt; toggleWebCam());
        
        // Leave meeting
        btnLeave.setOnClickListener(view -&gt; {
            // this will make the local participant leave the meeting
            meeting.leave();
        });

        // Switch camera
        btnSwitchCameraMode.setOnClickListener(view -&gt; {
            //a participant can change stream from front/rear camera during the meeting.
            meeting.changeWebcam();
        });
    
   }
}</code></pre><pre><code class="language-javascript">private void toggleMic() {
        if (micEnabled) {
            // this will mute the local participant's mic
            meeting.muteMic();
        } else {
            // this will unmute the local participant's mic
            meeting.unmuteMic();
        }
        micEnabled = !micEnabled;
        // change mic icon according to micEnable status
        toggleMicIcon();
    }

    @SuppressLint("ResourceType")
    private void toggleMicIcon() {
        if (micEnabled) {
            btnMic.setImageResource(R.drawable.ic_mic_on);
            btnMic.setColorFilter(Color.WHITE);
            Drawable buttonDrawable = btnMic.getBackground();
            buttonDrawable = DrawableCompat.wrap(buttonDrawable);
            //the color is a direct color int and not a color resource
            if (buttonDrawable != null) DrawableCompat.setTint(buttonDrawable, Color.TRANSPARENT);
            btnMic.setBackground(buttonDrawable);

        } else {
            btnMic.setImageResource(R.drawable.ic_mic_off);
            btnMic.setColorFilter(Color.BLACK);
            Drawable buttonDrawable = btnMic.getBackground();
            buttonDrawable = DrawableCompat.wrap(buttonDrawable);
            //the color is a direct color int and not a color resource
            if (buttonDrawable != null) DrawableCompat.setTint(buttonDrawable, Color.WHITE);
            btnMic.setBackground(buttonDrawable);
        }
    }</code></pre><pre><code class="language-javascript">private void toggleWebCam() {
        if (webcamEnabled) {
            // this will disable the local participant webcam
            meeting.disableWebcam();
        } else {
            // this will enable the local participant webcam
            meeting.enableWebcam();
        }
        webcamEnabled = !webcamEnabled;
        // change webCam icon according to webcamEnabled status
        toggleWebcamIcon();
    }

    @SuppressLint("ResourceType")
    private void toggleWebcamIcon() {
        if (webcamEnabled) {
            btnWebcam.setImageResource(R.drawable.ic_video_camera);
            btnWebcam.setColorFilter(Color.WHITE);
            Drawable buttonDrawable = btnWebcam.getBackground();
            buttonDrawable = DrawableCompat.wrap(buttonDrawable);
            //the color is a direct color int and not a color resource
            if (buttonDrawable != null) DrawableCompat.setTint(buttonDrawable, Color.TRANSPARENT);
            btnWebcam.setBackground(buttonDrawable);

        } else {
            btnWebcam.setImageResource(R.drawable.ic_video_camera_off);
            btnWebcam.setColorFilter(Color.BLACK);
            Drawable buttonDrawable = btnWebcam.getBackground();
            buttonDrawable = DrawableCompat.wrap(buttonDrawable);
            //the color is a direct color int and not a color resource
            if (buttonDrawable != null) DrawableCompat.setTint(buttonDrawable, Color.WHITE);
            btnWebcam.setBackground(buttonDrawable);
        }
    }</code></pre><h4 id="a-setting-up-local-participant-view">(a) Setting up Local participant view</h4>
<p>To set up participant view, we have to implement all the methods of the <code>ParticipantEventListener</code> Abstract Class and add the listener to <code>Participant</code> class using the <code>addEventListener()</code> method of <code>Participant</code> Class. <code>ParticipantEventListener</code> class has two methods :</p>
<ol>
<li><code>onStreamEnabled</code> - Whenever a participant enables mic/webcam in the meeting, This event will be triggered and return <code>Stream</code>.</li>
<li><code>onStreamDisabled</code> - Whenever a participant disables mic/webcam in the meeting, This event will be triggered and return <code>Stream</code>.</li>
</ol>
<pre><code class="language-javascript">public class MeetingActivity extends AppCompatActivity {

    private VideoView localView;
    private VideoView participantView;
    private CardView localCard, participantCard;
    private ImageView localParticipantImg;
    
  @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_meeting);
    
    //... 
    
    localCard = findViewById(R.id.LocalCard);
    participantCard = findViewById(R.id.ParticipantCard);
    localView = findViewById(R.id.localView);
    participantView = findViewById(R.id.localParticipant);
    localParticipantImg = findViewById(R.id.localParticipant_img);
        
    //...

    // setup local participant view
    setLocalListeners();
  }

  private void setLocalListeners() {
        meeting.getLocalParticipant().addEventListener(new ParticipantEventListener() {
            @Override
            public void onStreamEnabled(Stream stream) {
                if (stream.getKind().equalsIgnoreCase("video")) {
                    VideoTrack track = (VideoTrack) stream.getTrack();
                    localView.setVisibility(View.VISIBLE);
                    localView.addTrack(track);
                    localView.setZOrderMediaOverlay(true);
                    localCard.bringToFront();
                }
            }

            @Override
            public void onStreamDisabled(Stream stream) {
                if (stream.getKind().equalsIgnoreCase("video")) {
                    localView.removeTrack();
                    localView.setVisibility(View.GONE);
                }
            }
        });
    }
}</code></pre><h4 id="b-setting-up-remote-participant-view">(b) Setting up Remote participant view</h4>
<pre><code class="language-javascript">private final ParticipantEventListener participantEventListener = new ParticipantEventListener() {
        // trigger when participant enabled mic/webcam
        @Override
        public void onStreamEnabled(Stream stream) {
            if (stream.getKind().equalsIgnoreCase("video")) {
                localView.setZOrderMediaOverlay(true);
                localCard.bringToFront();
                VideoTrack track = (VideoTrack) stream.getTrack();
                participantView.setVisibility(View.VISIBLE);
                participantView.addTrack(track);
            }
        }

        // trigger when participant disabled mic/webcam
        @Override
        public void onStreamDisabled(Stream stream) {
            if (stream.getKind().equalsIgnoreCase("video")) {
                participantView.removeTrack();
                participantView.setVisibility(View.GONE);
            }
        }
    };
</code></pre><h4 id="c-handle-meeting-events-manage-participants-view">(c) Handle meeting events &amp; manage participant's view</h4>
<p>Add <code>MeetingEventListener</code> for listening events such as Meeting Join/Left and Participant Join/Left.</p>
<pre><code class="language-javascript">public class MeetingActivity extends AppCompatActivity {
  @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_meeting);
    //...

    // handle meeting events
    meeting.addEventListener(meetingEventListener);
  }
  
  private final MeetingEventListener meetingEventListener = new MeetingEventListener() {
        @Override
        public void onMeetingJoined() {
            // change mic,webCam icon after meeting successfully joined
            toggleMicIcon();
            toggleWebcamIcon();
        }

        @Override
        public void onMeetingLeft() {
            if (!isDestroyed()) {
                Intent intent = new Intent(MeetingActivity.this, JoinActivity.class);
                startActivity(intent);
                finish();
            }
        }

        @Override
        public void onParticipantJoined(Participant participant) {
            // Display local participant as miniView when other participant joined
            changeLocalParticipantView(true);
            Toast.makeText(MeetingActivity.this, participant.getDisplayName() + " joined",
                    Toast.LENGTH_SHORT).show();
            participant.addEventListener(participantEventListener);
        }

        @Override
        public void onParticipantLeft(Participant participant) {
            // Display local participant as largeView when other participant left
            changeLocalParticipantView(false);
            Toast.makeText(MeetingActivity.this, participant.getDisplayName() + " left",
                    Toast.LENGTH_SHORT).show();
        }
    };
}</code></pre><ul>
<li><code>changeLocalParticipantView(isMiniView: Boolean)</code> function first checks whether the video of a local participant is displayed as a MiniView or a LargeView.</li>
<li>If the meeting has only one participant (local participant), then the local participant is displayed as LargeView.</li>
<li>When another participant (other than the local participant) joins, <code>changeLocalParticipantView(true)</code> is called. As a result, the local participant is shown as MiniView, while the other participant is shown as LargeView.</li>
</ul>
<pre><code class="language-javascript">private void changeLocalParticipantView(boolean isMiniView) {
        if(isMiniView)
        {
            // show localCard as miniView
            localCard.setLayoutParams(new CardView.LayoutParams(300, 430, Gravity.RIGHT | Gravity.BOTTOM));
            ViewGroup.MarginLayoutParams cardViewMarginParams = (ViewGroup.MarginLayoutParams) localCard.getLayoutParams();
            cardViewMarginParams.setMargins(30, 0, 60, 40);
            localCard.requestLayout();
            // set height-width of localParticipant_img
            localParticipantImg.setLayoutParams(new FrameLayout.LayoutParams(150, 150, Gravity.CENTER));
            participantCard.setVisibility(View.VISIBLE);
        }else{
            // show localCard as largeView
            localCard.setLayoutParams(new CardView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            ViewGroup.MarginLayoutParams cardViewMarginParams = (ViewGroup.MarginLayoutParams) localCard.getLayoutParams();
            cardViewMarginParams.setMargins(30, 5, 30, 30);
            localCard.requestLayout();
            // set height-width of localParticipant_img
            localParticipantImg.setLayoutParams(new FrameLayout.LayoutParams(400, 400, Gravity.CENTER));
            participantCard.setVisibility(View.GONE);
        }
    }</code></pre><h4 id="d-destroying-everything">(d) Destroying everything</h4>
<p>We need to release resources when the app is closed and is no longer being used. Override the <code>onDestroy</code> with the following code:</p><pre><code class="language-javascript">protected void onDestroy() {
        if(meeting !=null)
        {
            meeting.removeAllListeners();
            meeting.getLocalParticipant().removeAllListeners();
            meeting.leave();
            meeting = null;
        }
        if (participantView != null) {
            participantView.setVisibility(View.GONE);
            participantView.releaseSurfaceViewRenderer();
        }

        if (localView != null) {
            localView.setVisibility(View.GONE);
            localView.releaseSurfaceViewRenderer();
        }

        super.onDestroy();
    }</code></pre><blockquote>
<p><code>java.lang.IllegalStateException: This Activity already has an action bar supplied by the window decor. Do not request Window.FEATURE_SUPPORT_ACTION_BAR and set windowActionBar to false in your theme to use a Toolbar instead.</code><br>
If you face this error at Runtime, Include these lines in <code>theme.xml</code> file.<br>
<code>&lt;item name="windowActionBar"&gt;false&lt;/item&gt;</code><br>
<code>&lt;item name="windowNoTitle"&gt;true&lt;/item&gt;</code></br></br></br></p>
</blockquote>
<h3 id="app-demo">App Demo</h3>
<p>Tadaa!! Our app is ready. Easy, isn't it? <br>Install and run the app on two different devices and make sure that they are connected to the internet.</br></p><blockquote>This app only supports 2 participants, it does not manage more than 2 participants. If you want to handle more than 2 participant then checkout our <strong>Group call</strong> example <a href="https://github.com/videosdk-live/videosdk-rtc-android-java-sdk-example">HERE</a>.</blockquote><h2 id="conclusion">Conclusion</h2><ul><li>In this blog, we have learned what videoSDK is, how to obtain an access token from the VideoSDK <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer">Dashboard</a>, and how to create a one-to-one <a href="https://www.contus.com/blog/build-a-live-video-chat-app/" rel="noopener noreferrer">video chat app</a> with the VideoSDK.</li><li>Go ahead and create advanced features like screen-sharing, chat, and others. Browse Our <a href="https://docs.videosdk.live/">Documentation</a>.</li><li>To see the full implementation of the app, check out this <a href="https://github.com/videosdk-live/videosdk-rtc-android-java-sdk-example/tree/one-to-one-demo">GitHub Repository</a>.</li><li>If you face any problems or have questions, Please join our <a href="https://discord.gg/Gpmj6eCq5u">Discord Community</a>.</li></ul>
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Your Page Title</title>
	<!-- Include Tailwind CSS -->
	<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</link></meta></meta></head>

<body>
	<div class="relative w-full overflow-hidden rounded-2xl bg-gradient-to-b from-pink-700 to-purple-900 p-4 text-center shadow-xl">
		<h2 class="mx-auto text-3xl font-bold tracking-tight text-white sm:text-2xl" style="margin-top: 3px; margin-bottom: 12px;">
			Schedule a Demo with Our Live Video Expert!
		</h2>
		<p class="mx-auto mt-3 max-w-xl text-sm text-gray-400">
			Discover how VideoSDK can help you build a cutting-edge real-time video app.
			<span class="font-semibold text-lato"/>
		</p>
		<div class="mt-4 flex items-center justify-center">
			<a href="https://www.videosdk.live/contact" class="rounded-md bg-white px-8 py-3 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white" target="_blank" style="text-decoration: none;color: black;" data-faitracker-click-bind="true">
				Book a call
			</a>
		</div>
		<svg viewBox="0 0 1024 1024" class="absolute left-1/2 top-1/2 -z-10 h-[64rem] w-[64rem] -translate-x-1/2 [mask-image:radial-gradient(closest-side,white,transparent)]" aria-hidden="true">
			
			<defs>
				<radialGradient id="827591b1-ce8c-4110-b064-7cb85a0b1217">
					<stop stop-color="#CB4371"/>
					<stop offset="0.5" stop-color="#AE49B0"/>
					<stop offset="1" stop-color="#493BB9"/>
				</radialGradient>
			</defs>
		</svg>
	</div>
</body>

</html>
<!--kg-card-end: html-->
<h2 id="more-android-resources">More Android Resources</h2>
<ul><li><a href="https://www.videosdk.live/blog/android-java-interactive-live-streaming">Android Live Streaming app with Java</a></li><li><a href="https://www.videosdk.live/blog/1-to-1-video-chat-app-on-android-using-videosdk">Android One-To-One video calling app with Kotlin</a></li><li><a href="https://www.videosdk.live/blog/android-live-streaming">Android Interactive Live Streaming App with Kotlin</a></li><li><a href="https://github.com/videosdk-live/videosdk-rtc-android-kotlin-sdk-example">Android Video Conferencing App with Kotlin example code</a></li><li><a href="https://github.com/videosdk-live/videosdk-hls-android-kotlin-example">Android Interactive Live Streaming App with Kotlin example code</a></li><li><a href="https://github.com/videosdk-live/videosdk-hls-android-java-example">Android Interactive Live Streaming App with Java example code</a></li><li><a href="https://github.com/videosdk-live/videosdk-rtc-android-java-sdk-example">Android Video Conferencing App with Java example code</a></li></ul>]]></content:encoded></item><item><title><![CDATA[RTMP vs HLS | Choosing the Best Streaming Protocol for Your Needs?]]></title><description><![CDATA[RTMP and HLS serve different roles in live streaming: RTMP handles low-latency ingest, HLS handles scalable delivery. Most production pipelines use both. Learn exactly which to use and when with VideoSDK.]]></description><link>https://www.videosdk.live/blog/rtmp-vs-hls</link><guid isPermaLink="false">65a520f66c68429b5fdf0f3d</guid><dc:creator><![CDATA[Chetan Sandanshiv]]></dc:creator><pubDate>Wed, 15 Jan 2025 11:35:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/01/RTMP-vs-HLS.png" medium="image"/><content:encoded><![CDATA[<h2 id="what-is-the-streaming-protocol">What is the streaming protocol?</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/01/RTMP-vs-HLS.png" alt="RTMP vs HLS | Choosing the Best Streaming Protocol for Your Needs?"/><p>The Streaming Protocol governs the transmission of multimedia content over the internet, ensuring real-time delivery. Various protocols, such as RTMP (Real-Time Messaging Protocol) and HLS (<a href="https://www.videosdk.live/blog/what-is-http-live-streaming">HTTP Live Streaming</a>). RTMP excels in low-latency live video streaming, while HLS breaks content into small chunks, enabling adaptive streaming. These protocols collectively enhance the user experience by optimizing playback and minimizing buffering for diverse streaming needs.</p><h2 id="what-is-rtmp-real-time-messaging-protocol">What is RTMP (Real-Time Messaging Protocol)?</h2><p>RTMP, or <a href="https://www.videosdk.live/blog/what-is-rtmp">Real-Time Messaging Protocol</a>, is a proprietary protocol developed by Adobe Systems for high-performance audio, video, and data transmission over the Internet.<strong> </strong>RTMP was initially designed for streaming audio, video, and data between a Flash player and a server. It gained popularity for its low latency and real-time capabilities, making it suitable for interactive and live-streaming applications.</p><h3 id="how-does-rtmp-work-in-video-streaming">How Does RTMP Work in Video Streaming?</h3><p>RTMP (Real-Time Messaging Protocol) is used for streaming audio, video, and data over the internet. It operates by establishing a persistent connection between a server and a client, allowing for low-latency transmission of media. RTMP divides the stream into small packets, ensuring efficient delivery and reducing buffering. It's commonly used in live broadcasts and interactive applications due to its ability to provide real-time communication, making it ideal for platforms like Twitch and Facebook Live.</p><h2 id="advantages-and-disadvantages-of-rtmp">Advantages and disadvantages of RTMP:</h2><h3 id="advantages">Advantages:</h3><ul><li>Low-latency streaming.</li><li>Real-time communication capabilities.</li><li>Widely supported by Flash players.</li></ul><h3 id="disadvantages">Disadvantages:</h3><ul><li>Lack of native browser support.</li><li>Security concerns, as RTMP doesn't encrypt data by default.</li></ul><h2 id="what-is-hlshttp-live-streaming">What is HLS(HTTP Live Streaming)?</h2><p>HLS, or <a href="https://www.videosdk.live/blog/what-is-http-live-streaming">HTTP Live Streaming</a>, is an adaptive streaming protocol developed by Apple. It breaks down video files into small chunks and delivers them over standard HTTP protocols. HLS was introduced by Apple in 2009 to support video streaming on iOS devices. It has since become a widely adopted protocol due to its compatibility with various devices and browsers.</p><h3 id="how-does-hls-work-in-live-streaming">How Does HLS Work in Live Streaming?</h3><p>HTTP Live Streaming (HLS) breaks video content into small, manageable chunks. These chunks are delivered over HTTP, allowing adaptive streaming. A manifest file, usually in M3U8 format, contains information about the chunks, enabling devices to adapt to varying network conditions and dynamically switch between different quality levels for smooth playback.</p><h2 id="advantages-and-disadvantages-of-hls">Advantages and disadvantages of HLS:</h2><h3 id="advantages-1">Advantages:</h3><ul><li>Broad compatibility with devices and browsers.</li><li>Effective adaptive streaming for varying network conditions.</li><li>Improved security as data is transmitted over standard HTTP.</li></ul><h3 id="disadvantages-1">Disadvantages:</h3><ul><li>Higher latency compared to RTMP.</li><li>Increased complexity in server-side implementations.</li></ul><h2 id="hls-vs-rtmp-a-direct-comparision">HLS vs RTMP: A Direct Comparision</h2><p><strong>Comparison of streaming quality: </strong>While RTMP offers low-latency streaming suitable for real-time applications, HLS provides adaptive streaming for improved video quality under varying network conditions.</p><p><strong>Latency considerations for live streaming: </strong>RTMP excels in low-latency scenarios, making it ideal for live broadcasts and interactive applications. HLS, on the other hand, has slightly higher latency due to its chunk-based delivery system.</p><p><strong>Device and browser compatibility: </strong>HLS boasts broad compatibility across devices and browsers, making it a versatile choice for reaching a diverse audience. RTMP, however, may require additional plugins for certain browsers.</p><p><strong>Adaptive streaming capabilities: </strong>HLS stands out with its adaptive bitrate streaming, adjusting video quality based on network conditions. RTMP provides consistent quality but may struggle with varying bandwidth.</p><p><strong>Security features: </strong>HLS, transmitting data over HTTP, offers improved security. RTMP, lacking default encryption, may raise security concerns, but encryption can be implemented separately.</p><p>Below is the comparison table between RTMP (Real-Time Messaging Protocol) and HLS (HTTP Live Streaming).</p><table>
<thead>
<tr>
<th>Feature</th>
<th>RTMP</th>
<th>HLS</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>Protocol Type</strong></td>
<td>Proprietary protocol developed by Adobe.</td>
<td>HTTP-based protocol developed by Apple.</td>
</tr>
<tr>
<td><strong>Streaming Method</strong></td>
<td>Real-time streaming.</td>
<td>Adaptive streaming with chunks.</td>
</tr>
<tr>
<td><strong>Latency</strong></td>
<td>Lower latency (2-3 seconds typically).</td>
<td>Higher latency (10-30 seconds typically).</td>
</tr>
<tr>
<td><strong>Compatibility</strong></td>
<td>Widely supported in Flash-based players.</td>
<td>Widely supported on various platforms and devices (HTML5, iOS, Android, etc.).</td>
</tr>
<tr>
<td><strong>Firewall/Proxy Friendly</strong></td>
<td>May encounter issues with firewalls/proxies.</td>
<td>Generally more firewall/proxy-friendly as it uses standard HTTP ports (80, 443).</td>
</tr>
<tr>
<td><strong>Adaptive Bitrate (ABR)</strong></td>
<td>Limited support for ABR.</td>
<td>Designed for ABR with multiple quality levels and adaptive streaming.</td>
</tr>
<tr>
<td><strong>Live Streaming Focus</strong></td>
<td>Primarily designed for live streaming.</td>
<td>Supports both live and on-demand streaming.</td>
</tr>
<tr>
<td><strong>Encoding Overhead</strong></td>
<td>Lower encoding overhead.</td>
<td>Higher encoding overhead due to multiple bitrate renditions.</td>
</tr>
<tr>
<td><strong>Supported Devices</strong></td>
<td>Historically Flash-based, limited on mobile.</td>
<td>Widespread support on various devices, including mobile and smart TVs.</td>
</tr>
<tr>
<td><strong>Playback Continuity</strong></td>
<td>More susceptible to interruptions and buffering.</td>
<td>More robust in handling network fluctuations with adaptive streaming.</td>
</tr>
<tr>
<td><strong>Use Cases</strong></td>
<td>Older live streaming scenarios, interactive applications.</td>
<td>Mainly used for on-demand video streaming, live events, and broadcasts.</td>
</tr>
<tr>
<td><strong>Development Status</strong></td>
<td>Adobe has officially deprecated RTMP.</td>
<td>HLS is widely adopted and continues to be a standard for HTTP-based streaming.</td>
</tr>
<tr>
<td><strong>Security</strong></td>
<td>Limited security features.</td>
<td>Improved security with HTTPS transport.</td>
</tr>
</tbody>
</table>
<h2 id="use-cases">Use Cases:</h2><p><strong>Common scenarios where RTMP excels:</strong></p><ul><li>Real-time applications like live gaming and video conferencing.</li><li>Low-latency requirements for interactive streaming.</li></ul><p><strong>Situations where HLS is the preferred choice:</strong></p><ul><li>Wide distribution across diverse devices and browsers.</li><li>Adaptive streaming for varying network conditions.</li></ul><h2 id="which-streaming-protocol-is-best-for-you">Which Streaming Protocol is Best for You?</h2><p>The best protocol choice depends on which part of the streaming pipeline you are optimizing and what latency your use case requires.</p><p><strong>Choose RTMP when:</strong></p><ul><li>You are connecting a hardware encoder or broadcasting software (OBS, Wirecast) to a media server.</li><li>You need sub-3-second latency for live sports commentary, auction bidding, or interactive game shows.</li><li>Your infrastructure is encoder-to-server, not server-to-viewer.</li></ul><p><strong>Choose HLS (or LL-HLS) when:</strong></p><ul><li>You are delivering video to end viewers across browsers, phones, smart TVs, or set-top boxes.</li><li>Your audience exceeds a few hundred concurrent viewers and you need CDN-level scale.</li><li>You need adaptive bitrate playback to handle viewers on variable mobile connections.</li><li>You need HTTPS encryption at the transport layer by default.</li></ul><p><strong>Use both together when:</strong></p><ul><li>You are building any production live streaming product. The standard pipeline is: Encoder sends RTMP to ingest server, ingest server transcodes and packages as HLS, CDN delivers HLS segments to viewers.</li></ul><p>For interactive broadcasts where viewer latency matters (Q&amp;A sessions, live shopping, real-time events), <a href="https://www.videosdk.live/developer-hub/hls/hls-low-latency" rel="noreferrer">LL-HLS</a> at 2-3 seconds is now a practical replacement for legacy RTMP delivery workarounds.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-3--2026--03_32_33-PM.png" class="kg-image" alt="RTMP vs HLS | Choosing the Best Streaming Protocol for Your Needs?" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">production live streaming architecture RTMP ingest HLS delivery</span></figcaption></img></figure><h2 id="the-role-of-videosdk-in-enhancing-streaming">The Role of VideoSDK in E<strong>nhancing Streaming </strong></h2><p><a href="https://www.videosdk.live/">VideoSDK </a>offers real-time audio-video SDKs, providing flexibility, scalability, and control for seamless integration of <a href="https://www.videosdk.live/audio-video-conferencing">audio-video conferencing</a> and <a href="https://www.videosdk.live/interactive-live-streaming">interactive live streaming</a> into web and mobile apps.</p><h3 id="features-that-make-videosdk-stand-out">Features that make VideoSDK stand out:</h3><ul><li>Real-time capabilities for interactive applications.</li><li>Compatibility with both RTMP and HLS for versatile streaming options.</li></ul><p><em>Have questions about integrating HLS &amp; LL-HTTP and VideoSDK? Our team offers </em><a href="https://www.videosdk.live/contact?utm_source=blog&amp;utm_medium=google&amp;utm_campaign=organic"><em>expert advice</em></a><em> tailored to your unique needs. Unlock the full potential—</em><a href="https://www.videosdk.live/blog/what-is-http-live-streaming?utm_source=blog&amp;utm_medium=google&amp;utm_campaign=organic"><em>sign up </em></a><em>now to access resources and join our </em><a href="https://discord.com/invite/Qfm8j4YAUJ?utm_source=blog&amp;utm_medium=google&amp;utm_campaign=organic"><em>developer community</em></a><em>. Schedule a demo to see features in action and discover how our solutions meet your streaming app needs.</em></p><h2 id="real-world-example-rtmp-ingest-with-hls-delivery">Real-World Example: RTMP Ingest with HLS Delivery</h2><p>Consider a live education platform serving 50,000 concurrent students across 80 countries on mobile and desktop.</p><p>Using RTMP only would be impossible for delivery: no modern browser plays RTMP natively, and a stateful RTMP connection cannot leverage CDN caching to serve 50,000 simultaneous viewers.</p><p>Using HLS only would be impossible for ingest: the instructor's OBS setup and classroom capture hardware output RTMP, not HLS segments.</p><p>The production architecture is OBS on the instructor's machine streams RTMP to VideoSDK's ingest endpoint at roughly 1.5 seconds of ingest latency. VideoSDK transcodes this into 5 ABR renditions and packages as LL-HLS. Students' players fetch HLS segments from the CDN at 3-5 seconds of viewer latency. Total end-to-end latency for a student in a different country is approximately 5-7 seconds, well within the threshold for live Q&amp;A interaction.</p><p>This is a typical architecture that hundreds of platforms use in production with VideoSDK.</p><h2 id="definitions-glossary">Definitions Glossary</h2><p><a href="https://www.videosdk.live/blog/what-is-rtmp" rel="noreferrer"><strong>RTMP (Real-Time Messaging Protocol)</strong></a><strong>:</strong>&nbsp;A proprietary streaming protocol developed by Adobe that maintains a persistent TCP connection between an encoder and a media server, achieving 1-3 seconds of live streaming latency.</p><p><a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer"><strong>HLS (HTTP Live Streaming)</strong></a><strong>:</strong>&nbsp;An adaptive bitrate streaming protocol developed by Apple that segments video into short files delivered over HTTP, enabling broad device compatibility and automatic quality adjustment based on viewer bandwidth.</p><p><a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming" rel="noreferrer"><strong>Adaptive Bitrate Streaming (ABR)</strong></a><strong>:</strong>&nbsp;A technique where the video player automatically switches between multiple quality renditions of a stream in real time based on the viewer's available network bandwidth, preventing buffering.</p><p><a href="https://www.videosdk.live/developer-hub/hls/hls-low-latency" rel="noreferrer"><strong>Low-Latency HLS (LL-HLS)</strong></a><strong>:</strong>&nbsp;An extension of the HLS protocol introduced by Apple in 2019 that uses smaller partial segments and proactive server push to reduce delivery latency from 10-30 seconds down to 2-5 seconds.</p><p><a href="https://www.videosdk.live/developer-hub/hls/hls-stream-m3u8" rel="noreferrer"><strong>M3U8 Manifest</strong></a><strong>:</strong>&nbsp;A playlist file in UTF-8 encoded M3U format that HLS players use to discover the segment URLs, quality renditions, and timing information for an HLS stream.</p><h2 id="key-takeaways">Key Takeaways</h2><ul><li>RTMP is the universal standard for sending a live stream from an encoder to a media server, achieving 1-3 seconds of ingest latency, but it cannot be played in modern browsers or on mobile devices without conversion.</li><li>HLS is the dominant delivery protocol for end viewers because it works natively in every modern browser and mobile OS, supports adaptive bitrate streaming, and scales to millions of viewers via CDN.</li><li>Most production live streaming architectures use RTMP for ingest and HLS for delivery: these protocols are complementary layers, not competing alternatives.</li><li>Low-Latency HLS (LL-HLS) reduces viewer-facing HLS latency to 2-5 seconds, making it viable for interactive broadcasts that previously required more complex real-time protocols.</li><li>VideoSDK provides a unified API that handles both RTMP ingest and HLS delivery as a managed service, eliminating the infrastructure complexity of running and scaling your own streaming pipeline.</li></ul><h2 id="conclusion">Conclusion</h2><p>The RTMP vs HLS debate resolves cleanly once you map each protocol to its role: RTMP for getting the stream in, HLS for getting it out to viewers at any scale. Building a production streaming product means handling both, which is exactly what VideoSDK makes simple through a single developer-friendly platform. Start your free VideoSDK account and launch a working RTMP-in, HLS-out live stream in under 30 minutes.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-the-main-difference-between-rtmp-and-hls">What is the main difference between RTMP and HLS?</h3><p>RTMP differs from HLS in that RTMP maintains a persistent TCP connection for low-latency media ingest (1-3 seconds) while HLS delivers video as small HTTP segments with adaptive bitrate switching (10-30 seconds for standard HLS, 2-5 seconds for LL-HLS). RTMP is used by encoders to push streams to a media server; HLS is used by that server to deliver the stream to viewers across browsers and mobile devices.</p><h3 id="is-rtmp-still-used-in-2026">Is RTMP still used in 2026?</h3><p>Yes, RTMP is still actively used in 2026 as the dominant ingest protocol for live streaming, despite Adobe deprecating the Flash Player. Every major platform including YouTube Live, Twitch, and Facebook Live continues to accept RTMP ingest streams from broadcasters using OBS, Wirecast, and similar tools. What changed is that RTMP is no longer used for browser playback, which is now handled exclusively by HLS or WebRTC. [UPDATE: verify date]</p><h3 id="which-protocol-has-lower-latency-rtmp-or-hls">Which protocol has lower latency, RTMP or HLS?</h3><p>RTMP has significantly lower latency than standard HLS. RTMP achieves 1-3 seconds of ingest latency compared to HLS's 10-30 seconds of typical delivery latency. However, Low-Latency HLS (LL-HLS) closes this gap to 2-5 seconds, making it suitable for interactive live streaming scenarios that previously required RTMP or WebRTC for viewer delivery.</p><h3 id="can-i-use-rtmp-and-hls-together-in-the-same-application">Can I use RTMP and HLS together in the same application?</h3><p>Yes, using RTMP and HLS together in the same application is the standard production architecture for live streaming. The typical pipeline is: an encoder sends a stream via RTMP to an ingest server, the server transcodes and packages the stream as HLS, and a CDN delivers HLS segments to viewers. VideoSDK manages this entire pipeline as a single managed service through one unified API.</p><h3 id="does-videosdk-support-both-rtmp-and-hls">Does VideoSDK support both RTMP and HLS?</h3><p>Yes, VideoSDK supports both RTMP ingest and HLS delivery, including Low-Latency HLS (LL-HLS). VideoSDK provides a managed RTMP ingest endpoint that accepts streams from any standard broadcasting software, automatically transcodes them into multiple ABR renditions, and serves the output as HLS playback URLs via CDN. Developers integrate both capabilities through VideoSDK's SDK and REST API without managing any streaming infrastructure themselves.</p><h3 id="what-latency-can-i-expect-with-hls-vs-rtmp">What latency can I expect with HLS vs RTMP?</h3><p>With RTMP, you can expect 1-3 seconds of latency from the encoder to the ingest server. With standard HLS delivery to viewers, expect 10-30 seconds of latency depending on segment duration and player buffering. With Low-Latency HLS (LL-HLS), viewer-facing latency drops to 2-5 seconds. Total end-to-end latency in a production pipeline using RTMP ingest and LL-HLS delivery typically lands at 3-7 seconds. [UPDATE: verify with VideoSDK performance benchmarks]</p><h3 id="is-hls-more-secure-than-rtmp">Is HLS more secure than RTMP?</h3><p>Yes, HLS is more secure than RTMP by default because HLS transmits data over standard HTTPS, providing transport-layer encryption without additional configuration. RTMP transmits data unencrypted by default over TCP port 1935. To secure an RTMP stream, you must use RTMPS (RTMP over TLS), which wraps the RTMP connection in SSL/TLS encryption, similar to how HTTPS wraps HTTP. Most modern streaming platforms enforce RTMPS for all ingest connections.</p>]]></content:encoded></item><item><title><![CDATA[How to Integrate VideoSDK with Expo (React Native)?]]></title><description><![CDATA[Learn how to seamlessly integrate the VideoSDK with your Expo (React Native) project and add real-time video communication features to your mobile application.]]></description><link>https://www.videosdk.live/blog/integrate-videosdk-with-expo-react-native</link><guid isPermaLink="false">664b0fd020fab018df10e5b2</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Wed, 15 Jan 2025 09:31:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/05/Integrate-Video-SDK-with-Expo--React-Native--1.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/05/Integrate-Video-SDK-with-Expo--React-Native--1.jpg" alt="How to Integrate VideoSDK with Expo (React Native)?"/><p>Integrating a Video SDK with Expo (React Native) can be a powerful way to add real-time video communication features to your mobile application. In this guide, we'll walk you through the process of integrating the VideoSDK with your Expo project, step by step. By the end of this tutorial, you'll have a solid understanding of how to set up and configure the VideoSDK, and use its features in your Expo app.</p><h2 id="getting-started">Getting Started</h2><p>We must use the capabilities that the <a href="https://www.videosdk.live/">VideoSDK</a> offers. Before dipping into the implementation steps, ensure you complete the necessary prerequisites.</p><h3 id="create-a-videosdk-account">Create a VideoSDK Account</h3><p>Go to your  <a href="https://app.videosdk.live/">VideoSDK dashboard</a> and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.</p><h3 id="generate-your-auth-token">Generate your Auth Token</h3><p>Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token is crucial in authorizing your application to use VideoSDK features.</p><p>For a more visual understanding of the account creation and token generation process, consider referring to the <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/authentication-and-token">provided tutorial</a>.</p><h3 id="prerequisites-and-setup">Prerequisites and Setup</h3><p>Make sure your development environment meets the following requirements:</p><ul><li>Node.js v12+</li><li>NPM v6+ (comes installed with newer Node versions)</li></ul><h3 id="project-structure">Project Structure</h3><p>Directory Structure</p><pre><code class="language-js">   root
   ├── node_modules
   ├── App.js
   ├── api.js
</code></pre><h3 id="install-videosdk-config">Install VideoSDK Config.</h3><p>It is necessary to set up VideoSDK within your project before going into the details. Installing VideoSDK using NPM or Yarn will depend on the needs of your project.</p><p>For NPM</p><pre><code class="language-js">npm install "@videosdk.live/react-native-sdk"  "@videosdk.live/react-native-incallmanager"
</code></pre><p>For Yarn</p><pre><code class="language-js">yarn add "@videosdk.live/react-native-sdk" "@videosdk.live/react-native-incallmanager"
</code></pre><h2 id="integrating-react-native-videosdk-with-expo">Integrating React Native VideoSDK with Expo</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/05/react-native-with-expo.png" class="kg-image" alt="How to Integrate VideoSDK with Expo (React Native)?" loading="lazy" width="1940" height="1206"/></figure><p>This guide details integrating VideoSDK seamlessly into your Expo project. Expo is a popular framework for building cross-platform mobile applications using React Native.</p><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-text">Our SDK utilizes native code and cannot be directly used in the Expo Go app. However, you can leverage the <code spellcheck="false" style="white-space: pre-wrap;">expo-dev-client</code> library to run your Expo app with a development build for testing purposes.</div></div><h3 id="creating-a-new-expo-project">Creating a New Expo Project</h3><p>Open your terminal and run the following command to create a new Expo project:</p><pre><code class="language-js">npx create-expo-app my-video-app
</code></pre><ul><li>Replace  <code>my-video-app</code>  with your desired project name.</li></ul><p>Navigate to your project directory:</p><pre><code class="language-js">cd my-video-app
</code></pre><h3 id="installing-the-videosdk">Installing the VideoSDK</h3><p>Use the following commands to install the VideoSDK and its dependencies:</p><pre><code class="language-js">npx expo install @videosdk.live/react-native-sdk
npx expo install @videosdk.live/react-native-webrtc
npx expo install @videosdk.live/react-native-incallmanager
npx expo install @videosdk.live/react-native-react-native-foreground-service
npx expo install @videosdk.live/expo-config-plugin
npx expo install @config-plugins/react-native-webrtc
</code></pre><h3 id="adding-configuration-plugins">Adding Configuration Plugins</h3><p>Update your  <code>app.json</code>  file to include the configuration plugins:</p><pre><code class="language-js">{
  "expo": {
    // ...
    "plugins": [
      "@videosdk.live/expo-config-plugin",
      [
        "@config-plugins/react-native-webrtc",
        {
          "cameraPermission": "Allow $(PRODUCT_NAME) to access your camera",
          "microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone"
        }
      ]
    ]
  }
}
</code></pre><p>This adds the  <code>@videosdk.live/expo-config-plugin</code>  and  <code>@config-plugins/react-native-webrtc</code>  plugins.<br>The  <code>@config-plugins/react-native-webrtc</code>  plugin configuration optionally allows you to customize permission request messages for iOS.</br></p><h3 id="updating-native-folders">Updating Native Folders</h3><p>Run the following command to update the native folders with the added plugins:</p><pre><code class="language-js">npx expo prebuild
</code></pre><h3 id="troubleshooting-expo-50-compatibility">Troubleshooting: Expo 50+ Compatibility</h3><p>Expo versions above 50 use  <code>event-target-shim@5</code>, which conflicts with  <code>react-native-webrtc</code>'s dependency on  <code>event-target-shim@6</code>. To resolve this:</p><p>if the project doesn't have  <code>metro.config.js</code>  file, then create a new  <code>metro.config.js</code>  file and paste below code.</p><pre><code class="language-js">const { getDefaultConfig } = require("expo/metro-config");
const resolveFrom = require("resolve-from");

/** @type {import('expo/metro-config').MetroConfig} */
const config = getDefaultConfig(__dirname);

config.resolver.resolveRequest = (context, moduleName, platform) =&gt; {
  if (
    // If the bundle is resolving "event-target-shim" from a module that is part of "react-native-webrtc".
    moduleName.startsWith("event-target-shim") &amp;&amp;
    context.originModulePath.includes("@videosdk.live/react-native-webrtc")
  ) {
    const updatedModuleName = moduleName.endsWith("/index")
      ? moduleName.replace("/index", "")
      : moduleName;

    // Resolve event-target-shim relative to the react-native-webrtc package to use v6.
    // React Native requires v5 which is not compatible with react-native-webrtc.
    const eventTargetShimPath = resolveFrom(
      context.originModulePath,
      updatedModuleName
    );

    return {
      filePath: eventTargetShimPath,
      type: "sourceFile",
    };
  }

  // Ensure you call the default resolver.
  return context.resolveRequest(context, moduleName, platform);
};

module.exports = config;
</code></pre><h3 id="registering-services">Registering Services</h3><p>In your project's main  <code>App.js</code>  file, register the VideoSDK services:</p><pre><code class="language-js">import { register } from "@videosdk.live/react-native-sdk";
import { registerRootComponent } from "expo";

// Register VideoSDK services before app component registration
register();
registerRootComponent(App);

export default function App() {}
</code></pre><p>After installing the VideoSDK in your Expo project, you can start using its features to add real-time video communication to your app. The VideoSDK provides a comprehensive set of APIs and components that allow you to create, join, and manage video meetings, as well as control various aspects of the meeting experience.</p><h2 id="essential-steps-to-implement-the-video-calling-functionality">Essential Steps to Implement the Video Calling Functionality<br/></h2><h3 id="step-1-get-started-with-apijs">Step 1: Get started with api.js</h3><p>Before moving on, you must create an API request to generate a unique meetingId. You will need an authentication token, which you can create either through the <a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples">videosdk-rtc-api-server-examples</a> or directly from the  <a href="https://app.videosdk.live/api-keys">VideoSDK Dashboard</a> for developers.</p><pre><code class="language-js">export const token = "&lt;Generated-from-dashbaord&gt;";
// API call to create meeting
export const createMeeting = async ({ token }) =&gt; {
  const res = await fetch(`https://api.videosdk.live/v2/rooms`, {
    method: "POST",
    headers: {
      authorization: `${token}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({}),
  });

  const { roomId } = await res.json();
  return roomId;
};
</code></pre><h3 id="step-2-wireframe-appjs-with-all-the-components">Step 2: Wireframe App.js with all the components</h3><p>To build up a wireframe of App.js, you need to use VideoSDK Hooks and Context Providers. VideoSDK provides MeetingProvider, MeetingConsumer, useMeeting, and useParticipant hooks.</p><p>First, you need to understand the  <strong>Context Provider </strong>and Consumer. Context is primarily used when some data needs to be accessible by many components at different nesting levels.</p><ul><li><strong>MeetingProvider</strong>: This is the Context Provider. It accepts value  <code>config</code>  and  <code>token</code>  as a prop. The Provider component accepts a value prop to be passed to consuming components that are descendants of this Provider. One Provider can be connected to many consumers. Providers can be nested to override values deeper within the tree.</li><li><strong>MeetingConsumer</strong>: This is the Context Consumer. All consumers that are descendants of a Provider will re-render whenever the Provider’s value prop changes.</li><li><strong>useMeeting</strong>: This is the meeting hook API. It includes all the information related to meetings such as join, leave, enable/disable the mic or webcam, etc.</li><li><strong>useParticipant</strong>: This is the participant hook API. It is responsible for handling all the events and props related to one particular participant such as <strong>name</strong>,  <strong>webcamStream</strong>,  <strong>micStream</strong>, etc.</li></ul><p>The Meeting Context provides a way to listen for any changes that occur when a participant joins the meeting or makes modifications to their microphone, camera, and other settings.</p><p>Begin by making a few changes to the code in the  <strong>App.js</strong>  file.</p><pre><code class="language-js">import React, { useState } from "react";
import {
  SafeAreaView,
  TouchableOpacity,
  Text,
  TextInput,
  View,
  FlatList,
} from "react-native";
import {
  MeetingProvider,
  useMeeting,
  useParticipant,
  MediaStream,
  RTCView,
} from "@videosdk.live/react-native-sdk";
import { createMeeting, token } from "./api";

function JoinScreen(props) {
  return null;
}

function ControlsContainer() {
  return null;
}

function MeetingView() {
  return null;
}

export default function App() {
  const [meetingId, setMeetingId] = useState(null);

  const getMeetingId = async (id) =&gt; {
    const meetingId = id == null ? await createMeeting({ token }) : id;
    setMeetingId(meetingId);
  };

  return meetingId ? (
    &lt;SafeAreaView style={{ flex: 1, backgroundColor: "#F6F6FF" }}&gt;
      &lt;MeetingProvider
        config={{
          meetingId,
          micEnabled: false,
          webcamEnabled: true,
          name: "Test User",
        }}
        token={token}
      &gt;
        &lt;MeetingView /&gt;
      &lt;/MeetingProvider&gt;
    &lt;/SafeAreaView&gt;
  ) : (
    &lt;JoinScreen getMeetingId={getMeetingId} /&gt;
  );
}
</code></pre><h3 id="step-3-implement-join-screen">Step 3: Implement Join Screen</h3><p>The join screen will serve as a medium to either schedule a new meeting or join an existing one.</p><pre><code class="language-js">function JoinScreen(props) {
  const [meetingVal, setMeetingVal] = useState("");
  return (
    &lt;SafeAreaView
      style={{
        flex: 1,
        backgroundColor: "#F6F6FF",
        justifyContent: "center",
        paddingHorizontal: 6 * 10,
      }}
    &gt;
      &lt;TouchableOpacity
        onPress={() =&gt; {
          props.getMeetingId();
        }}
        style={{ backgroundColor: "#1178F8", padding: 12, borderRadius: 6 }}
      &gt;
        &lt;Text style={{ color: "white", alignSelf: "center", fontSize: 18 }}&gt;
          Create Meeting
        &lt;/Text&gt;
      &lt;/TouchableOpacity&gt;

      &lt;Text
        style={{
          alignSelf: "center",
          fontSize: 22,
          marginVertical: 16,
          fontStyle: "italic",
          color: "grey",
        }}
      &gt;
        ---------- OR ----------
      &lt;/Text&gt;
      &lt;TextInput
        value={meetingVal}
        onChangeText={setMeetingVal}
        placeholder={"XXXX-XXXX-XXXX"}
        style={{
          padding: 12,
          borderWidth: 1,
          borderRadius: 6,
          fontStyle: "italic",
        }}
      /&gt;
      &lt;TouchableOpacity
        style={{
          backgroundColor: "#1178F8",
          padding: 12,
          marginTop: 14,
          borderRadius: 6,
        }}
        onPress={() =&gt; {
          props.getMeetingId(meetingVal);
        }}
      &gt;
        &lt;Text style={{ color: "white", alignSelf: "center", fontSize: 18 }}&gt;
          Join Meeting
        &lt;/Text&gt;
      &lt;/TouchableOpacity&gt;
    &lt;/SafeAreaView&gt;
  );
}
</code></pre><h3 id="step-4-implement-controls">Step 4: Implement Controls</h3><p>The next step is to create a  <code>ControlsContainer</code>  component to manage features such as Join or leave a Meeting and Enable or Disable the Webcam/Mic.</p><p>In this step, the  <code>useMeeting</code>  hook is utilized to acquire all the required methods such as  <code>join()</code>,  <code>leave()</code>,  <code>toggleWebcam</code>  and  <code>toggleMic</code>.	</p><pre><code class="language-js">const Button = ({ onPress, buttonText, backgroundColor }) =&gt; {
  return (
    &lt;TouchableOpacity
      onPress={onPress}
      style={{
        backgroundColor: backgroundColor,
        justifyContent: "center",
        alignItems: "center",
        padding: 12,
        borderRadius: 4,
      }}
    &gt;
      &lt;Text style={{ color: "white", fontSize: 12 }}&gt;{buttonText}&lt;/Text&gt;
    &lt;/TouchableOpacity&gt;
  );
};

function ControlsContainer({ join, leave, toggleWebcam, toggleMic }) {
  return (
    &lt;View
      style={{
        padding: 24,
        flexDirection: "row",
        justifyContent: "space-between",
      }}
    &gt;
      &lt;Button
        onPress={() =&gt; {
          join();
        }}
        buttonText={"Join"}
        backgroundColor={"#1178F8"}
      /&gt;
      &lt;Button
        onPress={() =&gt; {
          toggleWebcam();
        }}
        buttonText={"Toggle Webcam"}
        backgroundColor={"#1178F8"}
      /&gt;
      &lt;Button
        onPress={() =&gt; {
          toggleMic();
        }}
        buttonText={"Toggle Mic"}
        backgroundColor={"#1178F8"}
      /&gt;
      &lt;Button
        onPress={() =&gt; {
          leave();
        }}
        buttonText={"Leave"}
        backgroundColor={"#FF0000"}
      /&gt;
    &lt;/View&gt;
  );
}
</code></pre><p>ControlsContainer Component</p><pre><code class="language-js">function ParticipantList() {
  return null;
}
function MeetingView() {
  const { join, leave, toggleWebcam, toggleMic, meetingId } = useMeeting({});

  return (
    &lt;View style={{ flex: 1 }}&gt;
      {meetingId ? (
        &lt;Text style={{ fontSize: 18, padding: 12 }}&gt;
          Meeting Id :{meetingId}
        &lt;/Text&gt;
      ) : null}
      &lt;ParticipantList /&gt;
      &lt;ControlsContainer
        join={join}
        leave={leave}
        toggleWebcam={toggleWebcam}
        toggleMic={toggleMic}
      /&gt;
    &lt;/View&gt;
  );
}
</code></pre><p>MeetingView Component</p><h3 id="step-5-render-participant-list">Step 5: Render Participant List</h3><p>After implementing the controls, the next step is to render the joined participants.</p><p>You can get all the joined  <code>participants</code>  from the  <code>useMeeting</code>  Hook.</p><pre><code class="language-js">function ParticipantView() {
  return null;
}

function ParticipantList({ participants }) {
  return participants.length &gt; 0 ? (
    &lt;FlatList
      data={participants}
      renderItem={({ item }) =&gt; {
        return &lt;ParticipantView participantId={item} /&gt;;
      }}
    /&gt;
  ) : (
    &lt;View
      style={{
        flex: 1,
        backgroundColor: "#F6F6FF",
        justifyContent: "center",
        alignItems: "center",
      }}
    &gt;
      &lt;Text style={{ fontSize: 20 }}&gt;Press Join button to enter meeting.&lt;/Text&gt;
    &lt;/View&gt;
  );
}
</code></pre><p>ParticipantList Component</p><pre><code class="language-js">function MeetingView() {
  // Get `participants` from useMeeting Hook
  const { join, leave, toggleWebcam, toggleMic, participants } = useMeeting({});
  const participantsArrId = [...participants.keys()];

  return (
    &lt;View style={{ flex: 1 }}&gt;
      &lt;ParticipantList participants={participantsArrId} /&gt;
      &lt;ControlsContainer
        join={join}
        leave={leave}
        toggleWebcam={toggleWebcam}
        toggleMic={toggleMic}
      /&gt;
    &lt;/View&gt;
  );
}
</code></pre><p>MeetingView Component</p><h3 id="step-6-handling-participants-media">Step 6: Handling Participant's Media</h3><p>Before Handling the Participant's Media, you need to understand a couple of concepts.</p><h4 id="a-useparticipant-hook">[a] <code>useParticipant</code> Hook</h4><p>The  <code>useParticipant</code>  hook is responsible for handling all the properties and events of one particular participant who joined the meeting. It will take  <code>participantId</code>  as argument.</p><pre><code class="language-js">const { webcamStream, webcamOn, displayName } = useParticipant(participantId);
</code></pre><p>useParticipant Hook Example</p><h4 id="b-mediastream-api">[b] MediaStream API</h4><p>The MediaStream API is beneficial for adding a MediaTrack to the  <code>RTCView</code>  component, enabling the playback of audio or video.</p><pre><code class="language-js">&lt;RTCView
  streamURL={new MediaStream([webcamStream.track]).toURL()}
  objectFit={"cover"}
  style={{
    height: 300,
    marginVertical: 8,
    marginHorizontal: 8,
  }}
/&gt;
</code></pre><p>useParticipant Hook Example</p><h4 id="c-rendering-participant-media">[c] Rendering Participant Media</h4><pre><code class="language-js">function ParticipantView({ participantId }) {
  const { webcamStream, webcamOn } = useParticipant(participantId);

  return webcamOn &amp;&amp; webcamStream ? (
    &lt;RTCView
      streamURL={new MediaStream([webcamStream.track]).toURL()}
      objectFit={"cover"}
      style={{
        height: 300,
        marginVertical: 8,
        marginHorizontal: 8,
      }}
    /&gt;
  ) : (
    &lt;View
      style={{
        backgroundColor: "grey",
        height: 300,
        justifyContent: "center",
        alignItems: "center",
      }}
    &gt;
      &lt;Text style={{ fontSize: 16 }}&gt;NO MEDIA&lt;/Text&gt;
    &lt;/View&gt;
  );
}
</code></pre><p>We hope this guide has been helpful in getting you started with the VideoSDK in your Expo app. If you have any further questions or need additional support, be sure to check out the VideoSDK documentation and community resources.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/react-native-expo-setup"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Start a Video &amp; Audio Call in React Native - Video SDK Docs | Video SDK</div><div class="kg-bookmark-description">Build customizable real-time video &amp; audio calling applications in React Native Android SDK using Video SDK add live Video &amp; Audio conferencing to your applications.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.videosdk.live/img/icons/favicon.ico" alt="How to Integrate VideoSDK with Expo (React Native)?"><span class="kg-bookmark-author">Video SDK logo</span></img></div></div><div class="kg-bookmark-thumbnail"><img src="https://docs.videosdk.live/img/videosdklive-thumbnail.jpg" alt="How to Integrate VideoSDK with Expo (React Native)?" onerror="this.style.display = 'none'"/></div></a></figure><h2 id="conclusion">Conclusion</h2><p>In this guide, we have covered the steps to integrate the VideoSDK with your Expo (React Native) project. By following these steps, you will be able to add real-time video communication features to your mobile application, allowing your users to connect and collaborate in new ways.</p><p>By integrating the VideoSDK, you can provide your users with a powerful and flexible video communication solution that is easy to set up and customize. With features like screen sharing, recording, and moderation tools, you can create a meeting experience that meets the needs of your users and your business.</p><p>We hope this guide has been helpful in getting you started with the VideoSDK in your Expo app. If you have any further questions or need additional support, be sure to check out the VideoSDK documentation and community resources.</p><p>Remember, VideoSDK offers a generous <strong>free tier</strong> that includes <strong>10,000 minutes</strong> allowing you to experiment and build your video call application without initial investment. Start your  <a href="https://www.videosdk.live/signup"><strong>free trial today</strong></a>  and unlock the potential streaming in your React Native app!</p>]]></content:encoded></item><item><title><![CDATA[What Is SIP Connect and How Does It Work with VideoSDK?]]></title><description><![CDATA[SIP Connect lets PSTN phone callers and softphone users join WebRTC-based VideoSDK meetings as audio participants. Learn how it works, the protocol stack behind it, and how to set it up with Twilio.]]></description><link>https://www.videosdk.live/blog/sip-connect</link><guid isPermaLink="false">66505ad620fab018df10e6a3</guid><category><![CDATA[SIP Protocol]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Wed, 15 Jan 2025 09:30:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/05/SIP-Connect-1.png" medium="image"/><content:encoded><![CDATA[<blockquote><strong>SIP Connect</strong>&nbsp;is VideoSDK's telephony bridge that lets PSTN phone callers and softphone users join WebRTC meeting rooms as audio participants. Each meeting receives a unique SIP URI at&nbsp;<code>sip.videosdk.live</code>, and inbound calls authenticate with dashboard-generated credentials. SIP Connect eliminates the need for a custom media gateway between traditional phone networks and WebRTC infrastructure.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2024/05/SIP-Connect-1.png" alt="What Is SIP Connect and How Does It Work with VideoSDK?"/><p>A PSTN caller should be able to reach a developer's <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> meeting room without custom gateway code. SIP Connect makes that possible by routing traditional phone signaling directly into VideoSDK's media infrastructure. The caller dials a phone number, the SIP trunk forwards the call to a VideoSDK SIP endpoint, and the caller joins the same session as browser and mobile SDK participants, no app install required.</p><p>This article defines SIP Connect, explains the <a href="https://www.videosdk.live/developer-hub/sip/mastering-sip-protocol-comprehensive-guide" rel="noreferrer">protocol</a> stack beneath it, walks through a complete Twilio implementation, and addresses the four misconceptions that cause the most debugging time for developers building phone dial-in features.</p><h2 id="what-is-sip-connect">What Is SIP Connect?</h2><p><a href="https://docs.videosdk.live/android/guide/sip-connect/quick-start" rel="noreferrer">SIP Connect</a> is defined as a VideoSDK feature that assigns each meeting a unique SIP URI and accepts authenticated inbound calls from PSTN networks, softphones, or SIP trunk providers, placing those callers as audio participants alongside WebRTC SDK users.</p><p>SIP Connect works by mapping a VideoSDK meeting ID to a SIP address in the format&nbsp;<code>sip:&lt;meeting-id&gt;@sip.videosdk.live</code>, validating inbound SIP INVITE requests against credentials generated in the VideoSDK dashboard, and bridging the resulting audio stream into VideoSDK's Selective Forwarding Unit (SFU) where WebRTC participants already exist.</p><p>SIP Connect is best known for enabling mixed-mode meetings: a customer calls from a landline, a clinician joins from a browser tab using the <a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">VideoSDK JavaScript SDK</a>, and a specialist joins from a mobile app using the <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start" rel="noreferrer">React Native SDK</a>. All three participants hear each other in real time without any of them needing to install extra software.</p><p>The underlying signaling standard is the Session Initiation Protocol, defined in&nbsp;<a href="https://www.rfc-editor.org/info/rfc3261/" rel="noreferrer nofollow">IETF RFC 3261</a>. VideoSDK uses SIP as the call setup and teardown layer. The <a href="https://www.videosdk.live/blog/what-is-rtp-protocol" rel="noreferrer">Real-time Transport Protocol (RTP)</a>signalling carries the actual audio media packets between the phone network and VideoSDK's bridge. These two protocols work together: SIP handles the conversation, RTP carries the sound.</p><p>The combination of <a href="https://www.videosdk.live/developer-hub/sip/sip-signalling-protocol" rel="noreferrer">SIP signalling</a> and RTP media transport is what separates phone-network communication from WebRTC. VideoSDK's SIP Connect bridge translates between both worlds transparently, so neither side needs to be aware of the other's protocol stack.</p><h2 id="the-protocol-stack-behind-sip-connect">The Protocol Stack Behind SIP Connect</h2><p>SIP Connect sits at the intersection of PSTN circuit-switched telephony and WebRTC IP-based communication, and understanding both architectures is required knowledge for any developer implementing PSTN dial-in.</p><h3 id="pstn-public-switched-telephone-network">PSTN (Public Switched Telephone Network)</h3><p><a href="https://en.wikipedia.org/wiki/Public_switched_telephone_network" rel="noreferrer">PSTN</a> is the global circuit-switched telephone infrastructure that has carried voice calls for over 150 years. PSTN works by reserving a dedicated physical path between caller and receiver for the duration of each call. This architecture delivers predictable audio quality on the voice side but limits scalability and carries higher per-minute costs compared to VoIP.</p><p>When a caller dials a phone number and reaches a VideoSDK meeting, the PSTN leg terminates at a SIP trunk provider (such as Twilio, Telnyx, or Plivo). The trunk provider converts the circuit-switched signal into an IP-based SIP session and forwards the INVITE request to VideoSDK's SIP server at&nbsp;<code>sip.videosdk.live</code>.</p><h3 id="voip-and-sip-trunking">VoIP and SIP Trunking</h3><p><a href="https://www.videosdk.live/developer-hub/sip/voip" rel="noreferrer">VoIP (Voice over Internet Protocol)</a> is defined as a technology that transmits voice as digital IP packets rather than using dedicated circuits. VoIP works by compressing analog audio using codecs such as G.711 (PCMU/PCMA), G.722, or Opus, then routing those packets over any IP network.</p><p>SIP trunking is the specific combination of VoIP with the SIP signaling protocol. A SIP trunk provider receives a PSTN call, terminates it as a VoIP session, and forwards it to a SIP address, in this case,&nbsp;<code>sip:&lt;meeting-id&gt;@sip.videosdk.live</code>. Twilio, Telnyx, and Plivo all support this routing pattern, as does any provider that supports outbound SIP dialing with digest authentication.</p><h3 id="codec-switching-and-automatic-transcoding">Codec Switching and Automatic Transcoding</h3><p><a href="https://www.videosdk.live/blog/what-is-codec-switching" rel="noreferrer">Codec switching</a> is the dynamic selection of an audio codec during or before a call, based on network conditions or endpoint capabilities. This step is critical for SIP Connect deployments because PSTN legs typically arrive encoded as G.711 (64 kbps, uncompressed PCM audio) while WebRTC clients prefer Opus (6-510 kbps, adaptive compression).</p><p>VideoSDK's bridge handles G.711-to-Opus transcoding automatically. Neither the developer's application code nor the WebRTC SDK clients manage codec negotiation. A PSTN caller encoded in G.711 is transcoded to Opus before the audio stream reaches browser or mobile SDK participants. This is the step that most SIP tutorials skip explaining, and it is the reason phone callers and WebRTC users hear each other clearly without any codec configuration in application code.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-11--2026--11_51_25-AM.png" class="kg-image" alt="What Is SIP Connect and How Does It Work with VideoSDK?" loading="lazy" width="1774" height="887"><figcaption><span style="white-space: pre-wrap;">Sip connect architecture diagram showing PSTN to WebRTC bridge via VideoSDK SFU</span></figcaption></img></figure><h2 id="how-does-sip-connect-work-with-videosdk">How Does SIP Connect Work with VideoSDK?</h2><p>SIP Connect joins external callers to VideoSDK meetings by binding each meeting ID to a unique SIP URI and authenticating inbound INVITE requests with credentials generated in the VideoSDK dashboard.</p><p>The end-to-end flow follows four stages:</p><ol><li><strong>Meeting creation.</strong>&nbsp;Your backend creates a VideoSDK room using the REST API and distributes the meeting ID to both SDK clients and phone-routing logic.</li><li><strong>SIP credential provisioning.</strong>&nbsp;You enable SIP on an API key in the VideoSDK dashboard and store the generated username and password on your SIP trunk or webhook server, never in client-side code.</li><li><strong>Inbound call routing.</strong>&nbsp;A PSTN caller dials your published phone number, or a softphone user dials&nbsp;<code>sip:&lt;meeting-id&gt;@sip.videosdk.live</code>. Your SIP trunk provider (such as Twilio) forwards the call to VideoSDK's SIP endpoint with those credentials.</li><li><strong>Media bridging.</strong>&nbsp;VideoSDK accepts the SIP session, negotiates audio codecs, and places the caller in the meeting alongside WebRTC participants who joined through JavaScript, React, React Native, or other SDK clients.</li></ol><p>Codec negotiation is the critical step competitors rarely explain. PSTN legs often arrive as G.711 (PCMU/PCMA) audio, while WebRTC clients prefer Opus. VideoSDK's bridge transcodes between these formats so both sides hear intelligible audio without manual codec configuration in your application layer.</p><p>VideoSDK SIP Connect is currently available in US and EU regions only. Teams deploying in Asia-Pacific or other regions should contact VideoSDK support before committing to a SIP dial-in product roadmap.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-8--2026--02_07_41-PM.png" class="kg-image" alt="What Is SIP Connect and How Does It Work with VideoSDK?" loading="lazy" width="1692" height="930"><figcaption><span style="white-space: pre-wrap;">How SIP Connect works with VideoSDK step-by-step</span></figcaption></img></figure><p>The bridge handles one meeting per SIP URI, which keeps routing deterministic for support lines and scheduled telehealth sessions.</p><h2 id="how-to-implement-sip-connect-with-videosdk">How to Implement SIP Connect with VideoSDK?</h2><p>With VideoSDK's SIP Connect feature, you can enable your users to join VideoSDK meetings via VOIP using third-party service providers. This allows for establishing a bridge between participants using our client SDKs and those joining via SIP, enhancing the accessibility and connectivity of your video meetings.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/05/Videosdk-s-SIP-diagram.png" class="kg-image" alt="What Is SIP Connect and How Does It Work with VideoSDK?" loading="lazy" width="1122" height="530"/></figure><h3 id="getting-sip-credentials">Getting SIP Credentials</h3><p>To use SIP Connect Protocol, you will first need to generate the credentials for the SIP. Go to the <a href="https://app.videosdk.live/">VideoSDK dashboard</a> and under the <a href="https://app.videosdk.live/api-keys">API Keys</a> sections, first enable the SIP for the desired API key. Afterward, you will be presented with the SIP username and password to establish a connection with our SIP servers.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/05/SIP-credentials-by-VideoSDK-1.gif" class="kg-image" alt="What Is SIP Connect and How Does It Work with VideoSDK?" loading="lazy" width="1920" height="1080"/></figure><div class="kg-card kg-callout-card kg-callout-card-grey"><div class="kg-callout-emoji">?</div><div class="kg-callout-text">This feature is currently available in US and EU regions only. If you want to enable SIP for another region. Please, contact us at <a href="mailto:support@videosdk.live">support@videosdk.live</a></div></div><h3 id="use-sip-to-join-an-individual-meeting">Use SIP to join an individual meeting</h3><p>Once you have the credentials, you can use any of the softphones like <a href="https://www.linphone.org/">Linphone</a>, or <a href="https://www.zoiper.com/">Zoiper</a>, or use a third-party service provider like Twilio to connect with a VideoSDK meeting by initiating an SIP call to <code>sip:&lt;meeting-id&gt;@sip.videosdk.live</code>.</p><p>For example, if you want to connect to <code>abcd-abcd-abcd</code> meeting then the SIP address will look like <code>sip:abcd-abcd-abcd@sip.videosdk.live</code>.</p><h3 id="integration-with-twilio-pstn">Integration with Twilio PSTN</h3><p>To utilize third-party PSTN (Public Switched Telephone Network) providers like Twilio for calls via SIP (Session Initiation Protocol), follow these steps:</p><ol><li>Log in to your Twilio account and navigate to the Phone Numbers section</li><li>Purchase a phone number and access its configuration settings</li><li>Set up a Webhook handler that will initiate a call to the VideoSDK SIP endpoint whenever an incoming call is received on the selected phone number</li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/05/Twilio-PSTN.png" class="kg-image" alt="What Is SIP Connect and How Does It Work with VideoSDK?" loading="lazy" width="2000" height="747"/></figure><h3 id="example-for-creating-webhook-using-express">Example for Creating Webhook using Express</h3><pre><code class="language-jsx">const express = require("express");
const VoiceResponse = require("twilio").twiml.VoiceResponse;
const urlencoded = require("body-parser").urlencoded;

const app = express();

// Parse incoming POST params with Express middleware
app.use(urlencoded({ extended: false }));

// Webhook route which will be called by twilio when a call is received
app.post("/incoming-call-handler", (request, response) =&gt; {
  console.log({ request });
  // Use the Twilio Node.js SDK to build an XML response
  const twiml = new VoiceResponse();

  const dial = twiml.dial();
  dial.sip(
    {
      username: "&lt;User name generated for dashboard&gt;",
      password: "&lt;Password generated from dashboard&gt;",
    },
    "sip:&lt;meetingId&gt;@sip.videosdk.live"
  );

  // Render the response as XML in reply to the webhook request
  response.type("text/xml");
  response.send(twiml.toString());
});

//Start the express app on port 8000
app.listen(8000, () =&gt; {
  console.log(`Server listening on port ${8000}.`);
});
</code></pre><h2 id="why-integrate-sip-in-communication-systems">Why Integrate SIP in Communication Systems?</h2><h3 id="improved-user-experience">Improved User Experience</h3><p>SIP integration elevates user interactions by enabling smooth transitions between various communication modes. Users can effortlessly shift from video to phone calls without disruptions, maintaining conversation flow and engagement.</p><h3 id="global-reach">Global Reach</h3><p>SIP allows businesses to connect with clients and teams worldwide, with international calls and enabling collaboration across geographical barriers.</p><h3 id="adaptability">Adaptability</h3><p>SIP's flexibility enables businesses to connect calls to video conferences and switch between media types, ensuring seamless and uninterrupted communication.</p><h3 id="cost-efficiency">Cost Efficiency</h3><p>Combining platforms through SIP protocol integration reduces hardware dependency and any subscription expenses, streamlining their operations and making them more cost-effective.</p><h2 id="why-use-sip-connect-real-world-use-cases">Why Use SIP Connect? Real-World Use Cases</h2><p>SIP Connect is the right integration for any platform that must serve callers on PSTN landlines, legacy VoIP systems, or enterprise telephony infrastructure that cannot or will not use a browser-based or mobile SDK client.</p><p><strong>Telehealth and patient communication.</strong>&nbsp;A patient calls a published clinic number from a landline. The call routes through a SIP trunk to the VideoSDK meeting room where the clinician is already connected via the web app. No app download, no link required on the patient's side. For populations with lower smartphone adoption, PSTN dial-in significantly increases session completion rates.</p><p><strong>Enterprise contact centers.</strong>&nbsp;Customer support teams often run on legacy PBX systems that route calls internally via SIP trunks. SIP Connect lets agents join VideoSDK-powered support sessions directly from their existing desk phones or soft clients without migrating the entire telephony stack.</p><p><strong>Financial services client calls.</strong>&nbsp;Regulatory environments in several markets require that client calls happen on recorded PSTN lines. SIP Connect enables a hybrid setup: the advisor joins via the VideoSDK browser SDK while the client calls in from a recorded PSTN line, and VideoSDK's session recording captures the full mixed audio stream.</p><p><strong>AI voice agent fallback.</strong>&nbsp;In VideoSDK's AI voice agent pipeline, a PSTN caller can reach an AI agent deployed on VideoSDK without the caller needing any internet connectivity. The call arrives via SIP trunk, the agent processes speech-to-text and text-to-speech within the same VideoSDK session, and the entire interaction runs over phone audio. This is a natural integration point for&nbsp;<a href="https://www.videosdk.live/voice-agents">VideoSDK's AI voice agent infrastructure</a>.</p><p><strong>Low-connectivity regions.</strong>&nbsp;G.711 voice calls operate reliably at very low network speeds. In rural or emerging-market deployments where WebRTC performance degrades below 200 kbps, a PSTN phone dial-in provides a reliable audio floor that browser-based WebRTC cannot match.</p><h2 id="common-misconceptions-about-sip-connect">Common Misconceptions About SIP Connect</h2><p>Developers new to SIP Connect consistently misunderstand the relationship between SIP and WebRTC, the scope of SIP credentials, and the video capabilities available to phone callers.</p><p><strong>Misconception: SIP Connect and WebRTC use the same protocol.</strong>&nbsp;Reality: SIP and WebRTC are separate protocol stacks that were designed independently. SIP is a text-based signaling protocol that runs over <a href="https://www.videosdk.live/developer-hub/websocket/websocket-udp#what-are-websocket-and-udp" rel="noreferrer">UDP</a> or <a href="https://www.videosdk.live/developer-hub/ils/tcp-vs-http#understanding-tcp-and-http" rel="noreferrer">TCP</a>. WebRTC uses ICE for connection establishment, DTLS for key negotiation, and SRTP for encrypted media delivery. VideoSDK's bridge translates between the two stacks so both sides can share a session, but neither side speaks the other's native protocol.</p><p><strong>Misconception: Any SIP provider works automatically without configuration.</strong>&nbsp;Reality: The SIP trunk provider must specifically support outbound SIP dialing with digest authentication. Providers that only support inbound PSTN call forwarding without a SIP trunking tier will not route calls to an external SIP URI. Before building the integration, verify that your chosen provider (Twilio, Telnyx, Plivo) offers SIP trunking as a distinct product feature and test SIP header compatibility during the pilot phase.</p><p><strong>Misconception: PSTN callers joining via SIP Connect can see and send video.</strong>&nbsp;Reality: Phone callers joining through SIP Connect participate in audio only. The SIP protocol and PSTN infrastructure do not carry video media streams. WebRTC SDK participants can continue publishing video to each other, but the phone caller transmits G.711 audio only and cannot send or receive video frames.</p><p><strong>Misconception: SIP credentials in VideoSDK are per-meeting.</strong>&nbsp;Reality: SIP credentials in VideoSDK are per-API-key, not per-meeting. The same username and password authenticate all SIP calls for a given API key. The specific meeting a caller joins is determined by the meeting ID in the SIP URI user part (<code>&lt;meeting-id&gt;@sip.videosdk.live</code>), not by separate per-meeting credentials. Rotating credentials at the API-key level rotates access for all SIP endpoints simultaneously.</p><h2 id="definitions-glossary">Definitions Glossary</h2><p><a href="https://videosdk.live/developer-hub/sip/what-is-a-sip-session" rel="noreferrer"><strong>SIP (Session Initiation Protocol)</strong></a><strong>:</strong>&nbsp;A text-based application-layer signaling protocol defined in IETF RFC 3261 that establishes, modifies, and terminates real-time communication sessions including voice calls, video conferences, and instant messaging.</p><p><a href="https://en.wikipedia.org/wiki/Public_switched_telephone_network" rel="noreferrer"><strong>PSTN (Public Switched Telephone Network)</strong></a><strong>the :</strong>&nbsp;The global circuit-switched telephone infrastructure that routes voice calls over physical copper wire, fiber, and radio links to any standard telephone number worldwide.</p><p><a href="https://en.wikipedia.org/wiki/SIP_URI_scheme" rel="noreferrer"><strong>SIP URI</strong></a><strong>:</strong>&nbsp;A SIP Uniform Resource Identifier that addresses a specific endpoint in a SIP network, formatted as&nbsp;<code>sip:user@domain</code>. VideoSDK assigns a SIP URI to each meeting in the format&nbsp;<code>sip:&lt;meeting-id&gt;@sip.videosdk.live</code>.</p><p><a href="https://videosdk.live/developer-hub/sip/sip-trunk" rel="noreferrer"><strong>SIP Trunk</strong></a><strong>:</strong>&nbsp;A VoIP service from a provider (Twilio, Telnyx, Plivo) that connects an organization's internal communication system to the PSTN and can forward calls to external SIP URIs using digest authentication.</p><p><a href="https://www.videosdk.live/developer-hub/webrtc/webrtc-sfu#what-is-sfu-selective-forwarding-unit" rel="noreferrer"><strong>SFU (Selective Forwarding Unit)</strong></a><strong>:</strong>&nbsp;A media server architecture that receives streams from all participants and selectively forwards them to others. VideoSDK runs an SFU that routes both WebRTC streams and SIP-bridged audio in a unified session.</p><p><a href="https://www.videosdk.live/blog/what-is-rtp-protocol" rel="noreferrer"><strong>RTP (Real-time Transport Protocol)</strong></a><strong>:</strong>&nbsp;The network protocol that carries actual audio and video media packets in both SIP and WebRTC sessions. SIP handles call signaling; RTP carries the media stream.</p><p><a href="https://www.videosdk.live/developer-hub/media-server/transcoding-vs-encoding#what-is-video-transcoding" rel="noreferrer"><strong>Codec Transcoding</strong></a><strong>:</strong>&nbsp;The real-time conversion of compressed audio from one format to another. VideoSDK transcodes G.711 audio from PSTN legs to Opus for WebRTC participants automatically, with no configuration required in application code.</p><h2 id="key-takeaways">Key Takeaways</h2><ul><li>SIP Connect is VideoSDK's PSTN bridge that lets callers from phone networks, softphones, and SIP trunk providers join WebRTC meeting rooms as audio participants without installing any app or client software.</li><li>Each VideoSDK meeting maps to a SIP URI formatted as&nbsp;<code>sip:&lt;meeting-id&gt;@sip.videosdk.live</code>. Inbound calls authenticate with per-API-key credentials generated in the VideoSDK dashboard.</li><li>VideoSDK automatically transcodes G.711 phone audio to Opus for WebRTC clients, eliminating manual codec configuration in application code.</li><li>Compatible SIP trunk providers include Twilio, Telnyx, and Plivo. Any provider that supports outbound SIP dialing with digest authentication will work.</li><li>Phone callers joining via SIP Connect participate in audio only. They cannot send or receive video through the SIP or PSTN layer.</li><li>SIP Connect is currently available in the US and EU regions only. Contact VideoSDK support at&nbsp;<a href="mailto:support@videosdk.live">support@videosdk.live</a>&nbsp;for other regions. </li><li>Start with the&nbsp;<a href="https://docs.videosdk.live/android/guide/sip-connect/quick-start">VideoSDK SIP Connect quickstart</a>&nbsp;to deploy your first PSTN dial-in in under an hour.</li></ul><h2 id="conclusion">Conclusion</h2><p>SIP Connect bridges two communication worlds that were never designed to interoperate: the PSTN phone network and WebRTC-based video infrastructure. By mapping each meeting to a SIP URI and handling G.711-to-Opus transcoding transparently, VideoSDK removes the integration work that normally makes PSTN dial-in a multi-week engineering project.</p><p>The four-stage flow (meeting creation, credential provisioning, trunk routing, media bridging) works with any SIP-compatible trunk provider and requires no custom media gateway code on your side. If your platform needs to serve landline callers, legacy VoIP users, or enterprise telephony systems, SIP Connect is the fastest path from a dial tone to a shared VideoSDK session. Follow the&nbsp;<a href="https://docs.videosdk.live/android/guide/sip-connect/quick-start">VideoSDK SIP Connect quickstart</a>&nbsp;to deploy your first sip connect dial-in today.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="what-is-sip-connect-protocol">What is SIP Connect protocol?</h3><p>SIP Connect protocol is VideoSDK's telephony bridge feature that maps each meeting ID to a SIP URI at&nbsp;<code>sip.videosdk.live</code>&nbsp;and accepts authenticated inbound SIP INVITE requests from PSTN networks or SIP trunk providers. Authenticated callers join the designated meeting as audio participants alongside WebRTC SDK users. The term refers both to VideoSDK's specific implementation and to the broader practice of bridging SIP endpoints into a WebRTC conferencing platform.</p><h3 id="how-does-sip-connect-work-with-videosdk-1">How does SIP Connect work with VideoSDK?</h3><p>SIP Connect works with VideoSDK by creating a SIP endpoint (<code>sip:&lt;meeting-id&gt;@sip.videosdk.live</code>) for each meeting, validating INVITE requests against dashboard-generated per-API-key credentials, transcoding G.711 phone audio to Opus for WebRTC participants, and routing the caller into the meeting SFU alongside SDK users. The process requires a SIP trunk provider (Twilio, Telnyx, Plivo) to bridge the PSTN phone call to the VideoSDK SIP server.</p><h3 id="how-do-i-join-a-videosdk-meeting-via-sip">How do I join a VideoSDK meeting via SIP?</h3><p>Joining a VideoSDK meeting via SIP requires dialing&nbsp;<code>sip:&lt;meeting-id&gt;@sip.videosdk.live</code>&nbsp;from a configured softphone (Linphone or Zoiper) using VideoSDK SIP credentials as the SIP account. For PSTN callers, a Twilio webhook (or compatible trunk provider) must be configured to forward inbound phone calls to the SIP URI with dashboard-generated credentials. The caller joins as an audio-only participant in the meeting room.</p><h3 id="can-pstn-callers-join-a-videosdk-video-meeting">Can PSTN callers join a VideoSDK video meeting?</h3><p>PSTN callers can join a VideoSDK meeting through SIP Connect and participate in audio alongside video SDK users. Phone callers dial in via a SIP trunk provider (Twilio, Telnyx, Plivo) which forwards the PSTN call to the VideoSDK SIP endpoint. Phone participants transmit and receive audio only. They cannot send or see video because PSTN and SIP carry no video media stream.</p><h3 id="what-is-the-difference-between-sip-and-webrtc">What is the difference between SIP and WebRTC?</h3><p>SIP is a call signaling protocol (IETF RFC 3261) that establishes, modifies, and terminates telephone and VoIP sessions. WebRTC is a browser and mobile SDK standard that handles real-time media delivery using ICE for connection discovery, DTLS for key exchange, and SRTP for encrypted media transport. The two protocols use different security models, codec sets, and signaling mechanisms. VideoSDK's SIP Connect bridge translates between them so callers on either system can share one session.</p><h3 id="which-sip-providers-are-compatible-with-videosdk-sip-connect">Which SIP providers are compatible with VideoSDK SIP Connect?</h3><p>Twilio, Telnyx, and Plivo are compatible with VideoSDK SIP Connect, along with any provider that supports outbound SIP dialing with digest authentication. The provider must be able to forward inbound PSTN calls to an external SIP URI, which is a feature of SIP trunking products specifically, not standard PSTN forwarding. Test your provider's SIP header compatibility during pilot deployment before routing production traffic.</p>]]></content:encoded></item><item><title><![CDATA[What is Simulcast? How Simulcast Works?]]></title><description><![CDATA[Explore simulcast technology: broadcasting multiple streams at varying qualities. Learn its applications in streaming, broadcasting, and optimizing network bandwidth efficiently.]]></description><link>https://www.videosdk.live/blog/what-is-simulcast</link><guid isPermaLink="false">66756e6720fab018df10ecc6</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 14 Jan 2025 11:15:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/06/what-is-simulcast.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>Simulcast is a real-time video technique where one sender encodes and transmits multiple quality layers of the same stream simultaneously, allowing selective forwarding units to route the best layer to each viewer based on bandwidth. In broadcasting, simulcast also means streaming identical content to multiple platforms at once. Developers use WebRTC simulcast to scale group calls without re-encoding at the server.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2024/06/what-is-simulcast.jpg" alt="What is Simulcast? How Simulcast Works?"/><p>A video call with twelve participants should not force every viewer to download a 1080p stream when half the room is on mobile LTE. Simulcast solves that bandwidth mismatch by sending low, medium, and high layers from the publisher while the SFU picks the right layer per receiver. This article defines simulcast for developers, separates WebRTC simulcast from multistreaming, explains layer selection in production SFUs, and shows how to choose between simulcast and scalable video coding for your app.</p><h2 id="what-is-simulcast">What is Simulcast?</h2>
<p>Simulcast is defined as a streaming method where a single media source is encoded into multiple independent RTP streams at different resolutions or bitrates and transmitted concurrently to a receiving infrastructure that selects which stream each endpoint consumes.</p><p>Simulcast works by running parallel encoders (or a single encoder configured for multiple spatial or temporal layers) on the publisher device, tagging each outgoing stream with distinct SSRC or RID identifiers so the Selective Forwarding Unit can forward one layer to each subscriber without transcoding.</p><p>The term carries a second meaning in content distribution. Platform simulcasting (multistreaming) broadcasts one live feed to several destinations such as YouTube, Twitch, and LinkedIn Live through a restreaming service. Both meanings share the core idea of simultaneous delivery, but <a href="https://www.videosdk.live/blog/webrtc" rel="noreferrer">WebRTC</a> simulcast operates at the RTP packet layer inside a single session, while multistreaming operates at the CDN and platform ingest layer across separate services.</p><p>According to <a href="https://datatracker.ietf.org/doc/html/rfc8829" rel="noreferrer">IETF RFC 8829</a>, RTP simulcast groups multiple encoded representations of the same source within one WebRTC peer connection, enabling bandwidth-efficient adaptive delivery in multiparty conferences.</p><p>This section established that simulcast spans both multi-layer WebRTC encoding and multi-platform broadcasting, with distinct technical stacks for each.</p><h2 id="what-is-twitch-simulcasting">What is Twitch Simulcasting?</h2>
<p>Twitch simulcasting involves broadcasting the same live stream concurrently across multiple platforms, such as Twitch, YouTube, and Facebook. This strategy expands reach, diversifies audience engagement, and maximizes content exposure, making it a popular choice for streamers looking to grow their viewer base and increase interaction across various social media channels.4</p><h2 id="how-simulcasting-works">How Simulcasting Works?</h2>
<p>The technical setup for simulcasting involves both hardware and software components that manage the distribution of streams to multiple destinations. At the core of this process is a simulcasting or multistreaming service, such as Restream or Castr, which integrates various streaming platforms into a single interface. These services typically allow users to connect their video source—be it a camera or screen capture—to the service, which then encodes and distributes the stream to selected platforms like LinkedIn, Twitch, and more.</p><p>To ensure the efficient management and optimization of these streams, companies often turn to data warehousing consulting to handle the large volumes of data generated and ensure that streaming quality remains high across multiple platforms.</p><h3 id="setting-up-a-simulcast">Setting Up a Simulcast:</h3>
<ol><li><strong>Choose a Simulcasting Service:</strong> Select a platform that supports the desired streaming destinations and offers features like chat aggregation and analytics. Restream and Castr are popular choices that cater to a range of streaming needs from amateur content creators to professional broadcasters.</li><li><strong>Connect Your Video Source</strong>: This could be anything from professional broadcasting equipment to a simple webcam setup. The key is ensuring that the video feed is stable and of high quality.</li><li><strong>Configure Streaming Destinations</strong>: In the simulcasting service, specify where you want your content to go. This might include setting up individual stream keys or API access for platforms like YouTube, Facebook, and others.</li><li><strong>Go Live</strong>: Once everything is set up, you can start streaming simultaneously across all chosen platforms, significantly expanding your content’s reach.<br/></li></ol><p>The process is designed to be as seamless as possible, minimizing the technical challenges and allowing content creators to focus more on their presentation and less on the logistics of distribution.</p><p>By utilizing these platforms, broadcasters can effectively amplify their presence across the internet, tapping into diverse audience pools without the need for multiple separate streams, which would require significantly more bandwidth and resources. This efficiency not only simplifies the workflow but also maximizes the potential viewership with minimal additional effort.</p><h2 id="benefits-of-simulcasting">Benefits of Simulcasting</h2>
<p>Simulcasting offers several strategic advantages for content creators, businesses, and brands aiming to maximize their digital footprint. The primary benefit is the expansion of audience reach. By broadcasting simultaneously across multiple platforms, you tap into diverse viewer segments, each with unique demographics and engagement patterns. This approach not only increases visibility but also enhances the potential for viewer interaction and content virality.</p><p>Cost-effectiveness is another significant advantage. Simulcasting allows you to produce a single stream that reaches multiple channels, reducing the resources and time typically required for separate productions. This unified strategy maximizes return on investment, as the same content serves multiple audience bases without additional production costs.</p><p>Furthermore, simulcasting improves engagement rates. Platforms like Facebook Live and YouTube have built-in features that promote real-time interaction, such as comments and shares. By leveraging these features across multiple platforms simultaneously, creators can engage with a broader audience, receive instant feedback, and foster a sense of community among viewers.</p><h2 id="key-considerations-and-best-practices">Key Considerations and Best Practices</h2>
<p>While the benefits of simulcasting are clear, achieving optimal results requires attention to several key considerations. One of the main challenges is managing multiple audience interactions simultaneously. Creators must be adept at engaging with comments and reactions across different platforms, which can be overwhelming without the right tools or strategies.</p><p>To effectively manage this, it’s crucial to use simulcasting services that offer centralized control panels for monitoring and interacting with audiences across all platforms. This setup helps maintain a consistent level of engagement and ensures that no viewer feels neglected.</p><h2 id="best-practices-for-simulcasting-include">Best practices for simulcasting include</h2>
<p>Testing all equipment and connections before going live to avoid technical issues that could disrupt the broadcast.<br>Crafting content that resonates across different platforms, considering the nuances of each audience.<br>Promoting the simulcast ahead of time on all platforms to maximize live viewership.<br>Analyzing performance metrics post-broadcast to understand viewer behavior and preferences, which can inform future simulcasts.<br>By adhering to these best practices and continuously refining your approach based on audience feedback and analytics, you can harness the full potential of simulcasting to reach a wider audience, engage more effectively with viewers, and achieve your broadcasting goals with increased efficiency and impact.</br></br></br></br></p><h2 id="conclusion">Conclusion</h2>
<p>Simulcasting represents a modern broadcasting strategy that leverages technology to multiply audience reach without proportionate increases in effort or expense. By broadcasting content simultaneously across multiple platforms, creators and brands can achieve unprecedented levels of engagement and exposure. However, the success of simulcasting depends on careful planning, understanding the technical requirements, and effectively engaging with diverse audiences. As we’ve discussed, the benefits of simulcasting are substantial, from increased reach and engagement to cost efficiency. By adopting best practices and continuously refining your simulcasting strategies, you can effectively utilize this powerful tool to expand your digital footprint and connect with a broader audience more effectively than ever before.</p><h2 id="faqs-for-simulcasting">FAQs for Simulcasting</h2>
<h3 id="1-what-is-simulcast-and-how-does-it-differ-from-other-broadcasting-methods">1. What is simulcast and how does it differ from other broadcasting methods?</h3>
<p>Simulcast refers to the simultaneous broadcast of the same content across multiple platforms or channels. Unlike traditional broadcasting, which might limit content distribution to a single channel, simulcasting enables reaching diverse audiences concurrently.</p><h3 id="2-why-is-simulcasting-important-in-the-context-of-broadcasting-and-media-distribution">2. Why is simulcasting important in the context of broadcasting and media distribution?</h3>
<p>Simulcasting is crucial because it allows broadcasters to extend their reach and engagement by delivering content to various platforms simultaneously. It enhances audience accessibility and flexibility, catering to diverse viewing habits and preferences.</p><h3 id="3-what-types-of-content-can-be-simulcasted">3. What types of content can be simulcasted?</h3>
<p>Virtually any live or prerecorded content can be simulcasted, including video streams, audio broadcasts, webinars, concerts, and educational sessions, among others.</p><h3 id="4-is-there-a-difference-between-simulcasting-in-traditional-media-versus-digital-platforms">4. Is there a difference between simulcasting in traditional media versus digital platforms?</h3>
<p>Simulcasting in traditional media typically involves broadcasting across multiple TV or radio stations simultaneously, whereas digital platforms extend to streaming services, social media, and websites, catering to online audiences.</p><h3 id="5-is-simulcasting-the-same-as-live-streaming">5. Is simulcasting the same as live streaming?</h3>
<p>While simulcasting often involves live streaming, it specifically refers to broadcasting the same content simultaneously across multiple platforms. Live streaming, on the other hand, can involve broadcasting unique content to a single platform in real time.</p>]]></content:encoded></item><item><title><![CDATA[Post-Call Transcription & Summary in React]]></title><description><![CDATA[Introduction

Post-call transcription and summary is a powerful feature provided by VideoSDK that allows users to generate detailed transcriptions and summaries of recorded meetings after they have concluded. This feature is particularly beneficial for capturing and documenting important information discussed during meetings, ensuring that nothing is missed and that there is a comprehensive record of the conversation.


How Post-Call Transcription Works

Post-call transcription involves processi]]></description><link>https://www.videosdk.live/react-transcription-blog/</link><guid isPermaLink="false">667a5bb420fab018df10f0fa</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 14 Jan 2025 09:45:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/07/Post-time-transcription-and-summary-4.png" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/Post-time-transcription-and-summary-4.png" alt="Post-Call Transcription & Summary in React"/><p>Post-call transcription and summary is a powerful feature provided by VideoSDK that allows users to generate detailed transcriptions and summaries of recorded meetings after they have concluded. This feature is particularly beneficial for capturing and documenting important information discussed during meetings, ensuring that nothing is missed and that there is a comprehensive record of the conversation.</p><h3 id="how-post-call-transcription-works">How Post-Call Transcription Works</h3><p><strong>Post-call transcription</strong> involves processing the recorded audio or video content of a meeting to produce a textual representation of the conversation. Here’s a step-by-step breakdown of how it works:</p><ol><li><strong>Recording the Meeting:</strong> During the meeting, the audio and video are recorded. This can include everything that was said and any shared content, such as presentations or screen shares.</li><li><strong>Uploading the Recording:</strong> Once the meeting is over, the recorded file is uploaded to the VideoSDK platform. This can be done automatically or manually, depending on the configuration.</li><li><strong>Transcription Processing:</strong> The uploaded recording is then processed by VideoSDK’s transcription engine. This engine uses advanced speech recognition technology to convert spoken words into written text.</li><li><strong>Retrieving the Transcription:</strong> After the transcription process is complete, the textual representation of the meeting is made available. This text can be accessed via the VideoSDK API and used in various applications.</li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/06/react-quick-start-fafbfbc2ed2d7cbfd4c5ee2e36296f9e-1.png" class="kg-image" alt="Post-Call Transcription & Summary in React" loading="lazy" width="2906" height="1446"/></figure><h3 id="benefits-of-post-call-transcription">Benefits of Post-Call Transcription</h3><ul><li><strong>Accurate Documentation:</strong> Provides a precise record of what was discussed, which is invaluable for meeting minutes, legal documentation, and reference.</li><li><strong>Enhanced Accessibility:</strong> Makes content accessible to those who may have missed the meeting or have hearing impairments.</li><li><strong>Easy Review and Analysis:</strong> Enables quick review of key points and decisions made during the meeting without having to re-watch the entire recording.</li></ul><h2 id="lets-get-started">Let's Get started </h2><p>VideoSDK empowers you to seamlessly integrate the video calling feature into your React application within minutes.</p><p>In this quickstart, you'll explore the group calling feature of VideoSDK. Follow the step-by-step guide to integrate it within your application.</p><h3 id="prerequisites%E2%80%8B">Prerequisites<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#prerequisites">​</a></h3><p>Before proceeding, ensure that your development environment meets the following requirements:</p><ul><li>VideoSDK Developer Account (Not having one, follow <strong><a href="https://app.videosdk.live/" rel="noopener noreferrer">VideoSDK Dashboard</a></strong>)</li><li>Basic understanding of React</li><li><strong><a href="https://www.npmjs.com/package/@videosdk.live/react-sdk" rel="noopener noreferrer">React VideoSDK</a></strong></li><li>Have Node and NPM installed on your device.</li><li>Basic understanding of Hooks (useState, useRef, useEffect)</li><li>React Context API (optional)</li><li>Generate a token from VideoSDK <a href="https://app.videosdk.live/api-keys">dashboard </a></li></ul><h2 id="getting-started-with-the-code%E2%80%8B">Getting Started with the Code!<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#getting-started-with-the-code">​</a></h2><p>Follow the steps to create the environment necessary to add video calls into your app. You can also find the code sample for <a href="https://github.com/videosdk-live/quickstart/tree/main/react-rtc" rel="noopener noreferrer">quickstart here</a>.</p><h3 id="create-new-react-app%E2%80%8B">Create new React App<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#create-new-react-app">​</a></h3><p>Create a new React App using the below command.</p><pre><code class="language-JS">$ npx create-react-app videosdk-rtc-react-app</code></pre><h3 id="install-videosdk%E2%80%8B">Install VideoSDK<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#install-videosdk">​</a></h3><p>Install the VideoSDK using the below-mentioned npm command. Make sure you are in your react app directory before you run this command.</p><figure class="kg-card kg-code-card"><pre><code class="language-JS">$ npm install "@videosdk.live/react-sdk"

//For the Participants Video
$ npm install "react-player"</code></pre><figcaption>Terminal</figcaption></figure><h3 id="structure-of-the-project%E2%80%8B">Structure of the project<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#structure-of-the-project">​</a></h3><p>Your project structure should look like this.</p><pre><code class="language-Project Structure">   root
   ├── node_modules
   ├── public
   ├── src
   │    ├── API.js
   │    ├── App.js
   │    ├── index.js
   .    .</code></pre><p>You are going to use functional components to leverage react's reusable component architecture. There will be components for users, videos and controls (mic, camera, leave) over the video.</p><h3 id="app-architecture%E2%80%8B">App Architecture<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#app-architecture">​</a></h3><p>The App will contain a <code>MeetingView</code> component which includes a <code>ParticipantView</code> component which will render the participant's name, video, audio, etc. It will also have a <code>Controls</code> component which will allow the user to perform operations like leave and toggle media.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/06/react-quick-start-fafbfbc2ed2d7cbfd4c5ee2e36296f9e.png" class="kg-image" alt="Post-Call Transcription & Summary in React" loading="lazy" width="1356" height="780"/></figure><p>You will be working on the following files:</p><ul><li>API.js: Responsible for handling API calls such as generating unique meetingId and token</li><li>App.js: Responsible for rendering <code>MeetingView</code> and joining the meeting.</li></ul><h3 id="step-1-get-started-with-apijs%E2%80%8B">Step 1: Get started with API.js<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#step-1-get-started-with-apijs">​</a></h3><p>Prior to moving on, you must create an API request to generate a unique meetingId. You will need an authentication token, which you can create either through the <a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples" rel="noopener noreferrer">videosdk-rtc-api-server-examples</a> or directly from the <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer">VideoSDK Dashboard</a> for developers.</p><figure class="kg-card kg-code-card"><pre><code class="language-JS">//This is the Auth token, you will use it to generate a meeting and connect to it
export const authToken = "&lt;Generated-from-dashbaord&gt;";
// API call to create a meeting
export const createMeeting = async ({ token }) =&gt; {
  const res = await fetch(`https://api.videosdk.live/v2/rooms`, {
    method: "POST",
    headers: {
      authorization: `${authToken}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({}),
  });
  //Destructuring the roomId from the response
  const { roomId } = await res.json();
  return roomId;
};</code></pre><figcaption>API.js</figcaption></figure><h3 id="step-2-wireframe-appjs-with-all-the-components%E2%80%8B">Step 2: Wireframe App.js with all the components<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#step-2-wireframe-appjs-with-all-the-components">​</a></h3><p>To build up wireframe of App.js, you need to use VideoSDK Hooks and Context Providers. VideoSDK provides MeetingProvider, MeetingConsumer, useMeeting and useParticipant hooks.</p><p>First you need to understand Context Provider and Consumer. Context is primarily used when some data needs to be accessible by many components at different nesting levels.</p><ul><li><strong>MeetingProvider</strong>: This is the Context Provider. It accepts value <code>config</code> and <code>token</code> as props. The Provider component accepts a value prop to be passed to consuming components that are descendants of this Provider. One Provider can be connected to many consumers. Providers can be nested to override values deeper within the tree.</li><li><strong>MeetingConsumer</strong>: This is the Context Consumer. All consumers that are descendants of a Provider will re-render whenever the Provider’s value prop changes.</li><li><strong>useMeeting</strong>: This is the meeting hook API. It includes all the information related to meeting such as join, leave, enable/disable mic or webcam etc.</li><li><strong>useParticipant</strong>: This is the participant hook API. It is responsible for handling all the events and props related to one particular participant such as name, webcamStream, micStream etc.</li></ul><p>The Meeting Context provides a way to listen for any changes that occur when a participant joins the meeting or makes modifications to their microphone, camera, and other settings.</p><p>Begin by making a few changes to the code in the App.js file.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import "./App.css";
import React, { useEffect, useMemo, useRef, useState } from "react";
import {
  MeetingProvider,
  MeetingConsumer,
  useMeeting,
  useParticipant,
} from "@videosdk.live/react-sdk";
import { authToken, createMeeting } from "./API";
import ReactPlayer from "react-player";

function JoinScreen({ getMeetingAndToken }) {
  return null;
}

function ParticipantView(props) {
  return null;
}

function Controls(props) {
  return null;
}

function MeetingView(props) {
  return null;
}

function App() {
  const [meetingId, setMeetingId] = useState(null);

  //Getting the meeting id by calling the api we just wrote
  const getMeetingAndToken = async (id) =&gt; {
    const meetingId =
      id == null ? await createMeeting({ token: authToken }) : id;
    setMeetingId(meetingId);
  };

  //This will set Meeting Id to null when meeting is left or ended
  const onMeetingLeave = () =&gt; {
    setMeetingId(null);
  };

  return authToken &amp;&amp; meetingId ? (
    &lt;MeetingProvider
      config={{
        meetingId,
        micEnabled: true,
        webcamEnabled: true,
        name: "C.V. Raman",
      }}
      token={authToken}
    &gt;
      &lt;MeetingView meetingId={meetingId} onMeetingLeave={onMeetingLeave} /&gt;
    &lt;/MeetingProvider&gt;
  ) : (
    &lt;JoinScreen getMeetingAndToken={getMeetingAndToken} /&gt;
  );
}

export default App;</code></pre><figcaption>App.js</figcaption></figure><p/><h3 id="step-3-implement-join-screen%E2%80%8B">Step 3: Implement Join Screen<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#step-3-implement-join-screen">​</a></h3><p>Join screen will serve as a medium to either schedule a new meeting or join an existing one.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">function JoinScreen({ getMeetingAndToken }) {
  const [meetingId, setMeetingId] = useState(null);
  const onClick = async () =&gt; {
    await getMeetingAndToken(meetingId);
  };
  return (
    &lt;div&gt;
      &lt;input
        type="text"
        placeholder="Enter Meeting Id"
        onChange={(e) =&gt; {
          setMeetingId(e.target.value);
        }}
      /&gt;
      &lt;button onClick={onClick}&gt;Join&lt;/button&gt;
      {" or "}
      &lt;button onClick={onClick}&gt;Create Meeting&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><figcaption>JoinScreen Component</figcaption></figure><h4 id="output">Output</h4><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/06/image_2024-06-26_164057583.png" class="kg-image" alt="Post-Call Transcription & Summary in React" loading="lazy" width="720" height="130"/></figure><h3 id="step-4-implement-meetingview-and-controls%E2%80%8B">Step 4: Implement MeetingView and Controls<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#step-4-implement-meetingview-and-controls">​</a></h3><p>Next step is to create <code>MeetingView</code> and <code>Controls</code> components to manage features such as join, leave, mute and unmute.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">function MeetingView(props) {
  const [joined, setJoined] = useState(null);
  //Get the method which will be used to join the meeting.
  //We will also get the participants list to display all participants
  const { join, participants } = useMeeting({
    //callback for when meeting is joined successfully
    onMeetingJoined: () =&gt; {
      setJoined("JOINED");
    },
    //callback for when meeting is left
    onMeetingLeft: () =&gt; {
      props.onMeetingLeave();
    },
  });
  const joinMeeting = () =&gt; {
    setJoined("JOINING");
    join();
  };

  return (
    &lt;div className="container"&gt;
      &lt;h3&gt;Meeting Id: {props.meetingId}&lt;/h3&gt;
      {joined &amp;&amp; joined == "JOINED" ? (
        &lt;div&gt;
          &lt;Controls /&gt;
          //For rendering all the participants in the meeting
          {[...participants.keys()].map((participantId) =&gt; (
            &lt;ParticipantView
              participantId={participantId}
              key={participantId}
            /&gt;
          ))}
        &lt;/div&gt;
      ) : joined &amp;&amp; joined == "JOINING" ? (
        &lt;p&gt;Joining the meeting...&lt;/p&gt;
      ) : (
        &lt;button onClick={joinMeeting}&gt;Join&lt;/button&gt;
      )}
    &lt;/div&gt;
  );
}</code></pre><figcaption>MeetingView</figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">function Controls() {
  const { leave, toggleMic, toggleWebcam } = useMeeting();
  return (
    &lt;div&gt;
      &lt;button onClick={() =&gt; leave()}&gt;Leave&lt;/button&gt;
      &lt;button onClick={() =&gt; toggleMic()}&gt;toggleMic&lt;/button&gt;
      &lt;button onClick={() =&gt; toggleWebcam()}&gt;toggleWebcam&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><figcaption>Controls Component</figcaption></figure><h3 id="step-5-configuring-transcription">Step 5: Configuring Transcription</h3><ul><li>In this step, we set up the configuration for post transcription and summary generation. We define the webhook URL where the webhooks will be received.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">function Controls() {
  const { leave, toggleMic, toggleWebcam, startRecording, stopRecording } =  useMeeting();

  // Webhook URL where, webhooks are received
  const webhookurl = "https://www.example.com";
  const transcription = {
    enabled: true, // Enables post transcription
    summary: {
      enabled: true, // Enables summary generation

      // Guides summary generation
      prompt:
        "Write summary in sections like Title, Agenda, Speakers, Action Items, Outlines, Notes and Summary",
    },
  };

  return (
    &lt;div&gt;
      &lt;button onClick={() =&gt; leave()}&gt;Leave&lt;/button&gt;
      &lt;button onClick={() =&gt; toggleMic()}&gt;toggleMic&lt;/button&gt;
      &lt;button onClick={() =&gt; toggleWebcam()}&gt;toggleWebcam&lt;/button&gt;
      //Start Post-Call Transcription with Recording
      &lt;button
        onClick={() =&gt; startRecording(webhookurl, null, null, transcription)}
      &gt;
        Start Recording
      &lt;/button&gt;
      //Stop Recording
      &lt;button onClick={() =&gt; stopRecording()}&gt;Stop Recording&lt;/button&gt;
    &lt;/div&gt;
  );
}
</code></pre><figcaption>App.js</figcaption></figure><p><strong>Output of Controls Component</strong></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/06/Screenshot-2024-06-27-111321-1.png" class="kg-image" alt="Post-Call Transcription & Summary in React" loading="lazy" width="787" height="131"/></figure><h3 id="step-6-implement-participant-view%E2%80%8B">Step 6: Implement Participant View<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#step-5-implement-participant-view">​</a></h3><p>Before implementing the participant view, you need to understand a couple of concepts.</p><p><strong>1. Forwarding Ref for mic and camera<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#1-forwarding-ref-for-mic-and-camera">​</a></strong></p><p>The <code>useRef</code> hook is responsible for referencing the audio and video components. It will be used to play and stop the audio and video of the participant.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">const webcamRef = useRef(null);
const micRef = useRef(null);</code></pre><figcaption>Forwarding Ref for mic and camera</figcaption></figure><p><strong>2. useParticipant Hook</strong><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#2-useparticipant-hook">​</a></p><p>The <code>useParticipant</code> hook is responsible for handling all the properties and events of one particular participant joined in the meeting. It will take participantId as argument.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">const { webcamStream, micStream, webcamOn, micOn } = useParticipant(
  props.participantId
);</code></pre><figcaption>useParticipant Hook</figcaption></figure><p><strong>3. MediaStream API</strong><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#3-mediastream-api">​</a></p><p>The MediaStream API is beneficial for adding a MediaTrack to the audio/video tag, enabling the playback of audio or video.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">const webcamRef = useRef(null);
const mediaStream = new MediaStream();
mediaStream.addTrack(webcamStream.track);

webcamRef.current.srcObject = mediaStream;
webcamRef.current
  .play()
  .catch((error) =&gt; console.error("videoElem.current.play() failed", error));</code></pre><figcaption>MediaStream API</figcaption></figure><p><strong>4. Implement ParticipantView<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#4-implement-participantview">​</a></strong></p><p>Now you can use both of the hooks and the API to create <code>ParticipantView</code></p><figure class="kg-card kg-code-card"><pre><code class="language-js">function ParticipantView(props) {
  const micRef = useRef(null);
  const { webcamStream, micStream, webcamOn, micOn, isLocal, displayName } =
    useParticipant(props.participantId);

  const videoStream = useMemo(() =&gt; {
    if (webcamOn &amp;&amp; webcamStream) {
      const mediaStream = new MediaStream();
      mediaStream.addTrack(webcamStream.track);
      return mediaStream;
    }
  }, [webcamStream, webcamOn]);

  useEffect(() =&gt; {
    if (micRef.current) {
      if (micOn &amp;&amp; micStream) {
        const mediaStream = new MediaStream();
        mediaStream.addTrack(micStream.track);

        micRef.current.srcObject = mediaStream;
        micRef.current
          .play()
          .catch((error) =&gt;
            console.error("videoElem.current.play() failed", error)
          );
      } else {
        micRef.current.srcObject = null;
      }
    }
  }, [micStream, micOn]);

  return (
    &lt;div&gt;
      &lt;p&gt;
        Participant: {displayName} | Webcam: {webcamOn ? "ON" : "OFF"} | Mic:{" "}
        {micOn ? "ON" : "OFF"}
      &lt;/p&gt;
      &lt;audio ref={micRef} autoPlay playsInline muted={isLocal} /&gt;
      {webcamOn &amp;&amp; (
        &lt;ReactPlayer
          //
          playsinline // extremely crucial prop
          pip={false}
          light={false}
          controls={false}
          muted={true}
          playing={true}
          //
          url={videoStream}
          //
          height={"300px"}
          width={"300px"}
          onError={(err) =&gt; {
            console.log(err, "participant video error");
          }}
        /&gt;
      )}
    &lt;/div&gt;
  );
}</code></pre><figcaption>ParticipantView</figcaption></figure><h2 id="final-output%E2%80%8B">Final Output<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#final-output">​</a></h2><p>You have completed the implementation of a customized video calling app in React.js using VideoSDK. To explore more features, go through Basic and Advanced features.</p><figure class="kg-card kg-video-card"><div class="kg-video-container"><video src="http://blogs.videosdk.live/content/media/2024/06/part1-1.mp4" poster="https://img.spacergif.org/v1/1920x1080/0a/spacer.png" width="1920" height="1080" playsinline="" preload="metadata" style="background: transparent url('https://assets.videosdk.live/static-assets/ghost/2024/06/media-thumbnail-ember748.jpg') 50% 50% / cover no-repeat;"/><div class="kg-video-overlay"><button class="kg-video-large-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button></div><div class="kg-video-player-container"><div class="kg-video-player"><button class="kg-video-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button><button class="kg-video-pause-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/><rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/></svg></button><span class="kg-video-current-time">0:00</span><div class="kg-video-time">/<span class="kg-video-duration"/></div><input type="range" class="kg-video-seek-slider" max="100" value="0"><button class="kg-video-playback-rate">1&#215;</button><button class="kg-video-unmute-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/></svg></button><button class="kg-video-mute-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/></svg></button><input type="range" class="kg-video-volume-slider" max="100" value="100"/></input></div></div></div></figure><h2 id="fetching-the-transcription-from-the-dashboard">Fetching the Transcription from the Dashboard</h2><p>Once the transcription is ready, you can fetch it from the VideoSDK dashboard. The dashboard provides a user-friendly interface where you can view, download, and manage your transcriptions.</p><figure class="kg-card kg-video-card"><div class="kg-video-container"><video src="http://blogs.videosdk.live/content/media/2024/06/part2.mp4" poster="https://img.spacergif.org/v1/2520x1080/0a/spacer.png" width="2520" height="1080" playsinline="" preload="metadata" style="background: transparent url('https://assets.videosdk.live/static-assets/ghost/2024/06/media-thumbnail-ember696.jpg') 50% 50% / cover no-repeat;"/><div class="kg-video-overlay"><button class="kg-video-large-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button></div><div class="kg-video-player-container"><div class="kg-video-player"><button class="kg-video-play-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/></svg></button><button class="kg-video-pause-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/><rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/></svg></button><span class="kg-video-current-time">0:00</span><div class="kg-video-time">/<span class="kg-video-duration"/></div><input type="range" class="kg-video-seek-slider" max="100" value="0"><button class="kg-video-playback-rate">1&#215;</button><button class="kg-video-unmute-icon"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/></svg></button><button class="kg-video-mute-icon kg-video-hide"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/></svg></button><input type="range" class="kg-video-volume-slider" max="100" value="100"/></input></div></div></div></figure><h2 id="conclusion">Conclusion</h2><p>Integrating post-call transcription and summary features into your React application using VideoSDK provides significant advantages for capturing and documenting meeting content. This guide has meticulously detailed the steps required to set up and implement these features, ensuring that every conversation during a meeting is accurately transcribed and easily accessible for future reference.</p>]]></content:encoded></item><item><title><![CDATA[Best Jitsi Competitors in 2025]]></title><description><![CDATA[Explore Jitsi's competition by comparing Jitsi with its competitors in the realm of real-time communication.]]></description><link>https://www.videosdk.live/blog/jitsi-competitors</link><guid isPermaLink="false">64b5257f9eadee0b8b9e71ec</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Tue, 14 Jan 2025 04:30:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2023/08/Jitsi-Meet-competitors.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2023/08/Jitsi-Meet-competitors.jpg" alt="Best Jitsi Competitors in 2025"/><p>Absolutely, when considering <strong>video communication API</strong>s, Jitsi could be among the choices you're evaluating. </p><p>Exploring <a href="https://www.videosdk.live/blog/jitsi-alternative">alternatives to Jitsi</a> presents a vast landscape. Navigating this array can be challenging. Before delving into video API options, define your project's budget, use case, and essential features.</p><p>To simplify this process, we've curated a list of the <strong>best competitors to Jitsi</strong>. This compilation is intended to aid you in streamlining your selection process and identifying the optimal video API solution that harmonizes with your application's unique needs. It's important to emphasize that our objective is to offer an impartial overview of each provider, allowing you to make a well-informed choice that aligns with your specific requirements and preferences.</p><h2 id="jitsi-meet">Jitsi Meet</h2>
<h3 id="key-points-about-jitsi">Key points about Jitsi</h3>
<ul><li>Indeed, Jitsi is a versatile open-source platform that allows users to tailor its usage according to their preferences and needs. </li><li>Jitsi Meet, one of its flagship projects, offers an array of features such as text sharing through Etherpad, room locking, text chatting (web only), raising hands, accessing YouTube videos during calls, audio-only calls, and integrations with third-party applications.</li><li>However, Jitsi Meet alone might <strong>lack</strong> certain crucial collaborative functionalities like <strong>screen sharing</strong>, <strong>recording</strong>, or <strong>telephone dial-in</strong> for conferences. </li><li>To access these features, setting up <strong>additional projects</strong> like <strong>Jibri</strong> and <strong>Jigsai</strong> is necessary, which can entail <strong>more time</strong>, <strong>resources</strong>, and <strong>coding efforts</strong>. </li><li>This could make Jitsi <strong>less suitable</strong> for users seeking a low-code option to quickly implement such features.</li><li>While Jitsi ensures end-to-end encryption for video calls, it's important to note that this encryption <strong>doesn't cover</strong> aspects like <strong>chat</strong> or <strong>polls</strong>. </li><li>For users placing a high emphasis on robust security, additional measures might be needed.</li><li>It's also worth considering that Jitsi can consume a <strong>notable amount of bandwidth</strong> due to the way Jitsi Videobridge functions. </li><li>For larger organizations requiring an SDK for frequent and lengthy video sessions involving a substantial number of participants, Jitsi might not fully meet their specific needs and could potentially be less satisfactory in comparison to more specialized solutions.</li></ul><h3 id="jitsi-pricing">Jitsi pricing</h3>
<ul><li>Jitsi is available for <strong>free</strong>, which means you can use its components without any payment.</li><li>However, it's important to note that dedicated technical support is not provided by the platform. </li><li>In case you encounter any issues or require assistance, you can seek help from the active community of contributors who participate in the Jitsi project.</li></ul><h2 id="direct-comparison-jitsi-vs-top-competitors">Direct Comparison: Jitsi vs Top Competitors</h2>
<p>The <strong>top Jitsi</strong> <strong>competitors </strong>are VideoSDK, 100ms, WebRTC, Daily, and LiveKit.</p><p>Let's compare Jitsi with each of the above competitors.</p><h2 id="1-jitsi-vs-videosdk">1. Jitsi vs VideoSDK</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/08/Jitsi-Meet-vs-Videosdk.jpg" class="kg-image" alt="Best Jitsi Competitors in 2025" loading="lazy" width="1429" height="525"/></figure><p>VideoSDK offers developers a seamless API that simplifies incorporating robust, scalable, and dependable audio-video capabilities into their applications. With only a few lines of code, developers can introduce live audio and video experiences to various platforms within minutes. One of the primary benefits of opting for the <a href="https://www.videosdk.live/">VideoSDK</a> is its remarkable ease of integration. This characteristic enables developers to concentrate their efforts on crafting innovative features that contribute to enhanced user engagement and retention.</p>
<!--kg-card-begin: html-->
<table border="2px black" cellspacing="0px" style="border-radius: 10px;">
    <tr>
        <td/>
        <td><strong>Jitsi pricing</strong></td>
        <td><strong>VideoSDK pricing</strong></td>
    </tr>
    <tr>
        <td><strong>Video calling</strong></td>
        <td>NA</td>
        <td>Starts from <strong>$2</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>Interactive live streaming</strong></td>
        <td>NA</td>
        <td>Starts from <strong>$1</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>RTMP</strong></td>
        <td>NA</td>
        <td>
            <strong>$15</strong> per 1,000 minutes, No limit on participants
        </td>
    </tr>
    <tr>
        <td><strong>Cloud Recording<strong/></strong></td>
        <td>NA</td>
        <td>
            <strong>$15</strong> per 1,000 minutes, No limit on participants
        </td>
    </tr>
</table>
<!--kg-card-end: html-->
<blockquote>Here's a detailed comparison of <a href="https://www.videosdk.live/jitsi-vs-videosdk">Jitsi vs VideoSDK</a>.</blockquote>
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Your Page Title</title>
	<!-- Include Tailwind CSS -->
	<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</link></meta></meta></head>

<body>
	<div class="relative w-full overflow-hidden rounded-2xl bg-gradient-to-b from-pink-700 to-purple-900 p-4 text-center shadow-xl">
		<h3 class="mx-auto text-3xl font-bold tracking-tight text-white sm:text-2xl" style="margin-top: 3px; margin-bottom: 12px;">
			Schedule a Demo with Our Live Video Expert!
		</h3>
		<p class="mx-auto mt-3 max-w-xl text-sm text-gray-400">
			Discover how VideoSDK can help you build a cutting-edge real-time video app.
			<span class="font-semibold text-lato"/>
		</p>
		<div class="mt-4 flex items-center justify-center">
			<a href="https://www.videosdk.live/contact" class="rounded-md bg-white px-8 py-3 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white" target="_blank" style="text-decoration: none;color: black;" data-faitracker-click-bind="true">
				Book a call
			</a>	
		</div>
		
	</div>
</body>

</html>
<!--kg-card-end: html-->
<h2 id="2-jitsi-vs-100ms">2. Jitsi vs 100ms</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/08/Jitsi-Meet-vs-100ms.jpg" class="kg-image" alt="Best Jitsi Competitors in 2025" loading="lazy" width="1429" height="525"/></figure><p><a href="https://www.videosdk.live/blog/100ms-alternative">100ms</a> offers a cloud-based platform that empowers developers to seamlessly integrate video and audio conferencing into a variety of applications, spanning web, Android, and iOS platforms. With a comprehensive suite of tools, including REST APIs, software development kits (SDKs), and an intuitive user-friendly dashboard, 100ms simplifies the process of capturing, distributing, recording, and presenting live interactive audio and video content. This platform serves as a valuable resource for enhancing user engagement and communication experiences across diverse applications.</p>
<!--kg-card-begin: html-->
<table border="2px black" cellspacing="0px" style="border-radius: 10px;">
    <tr>
        <td/>
        <td><strong>Jitsi pricing</strong></td>
        <td><strong>100ms pricing</strong></td>
    </tr>
    <tr>
        <td><strong>Video calling</strong></td>
        <td>NA</td>
        <td>Starts from <strong>$4</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>Interactive live streaming</strong></td>
        <td>NA</td>
        <td>Starts from <strong>$4</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>RTMP</strong></td>
        <td>NA</td>
        <td><strong>$40</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>Cloud Recording<strong/></strong></td>
        <td>NA</td>
        <td><strong>$13.5</strong> per 1,000 minutes</td>
    </tr>
</table>
<!--kg-card-end: html-->
<blockquote>Here's a detailed comparison of <a href="https://www.videosdk.live/100ms-vs-jitsi">Jitsi vs 100ms</a>.</blockquote><h2 id="3-jitsi-vs-webrtc">3. Jitsi vs WebRTC</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/08/Jitsi-Meet-vs-WebRTC.jpg" class="kg-image" alt="Best Jitsi Competitors in 2025" loading="lazy" width="1429" height="525"/></figure><p>WebRTC stands as an open-source initiative that equips web browsers with the prowess to seamlessly integrate Real-Time Communications (RTC) capabilities through intuitive JavaScript APIs. Through intricate optimization, the diverse components of <a href="https://www.videosdk.live/blog/webrtc-alternative">WebRTC</a> aptly fulfill the mission of enabling real-time communication functionalities within web browsers. Developers are thereby empowered to effortlessly embed an array of features, including audio and video calls, chat functionalities, file sharing, and more, directly into their web applications.</p>
<!--kg-card-begin: html-->
<table border="2px black" cellspacing="0px" style="border-radius: 10px;">
    <tr>
        <td/>
        <td><strong>Jitsi pricing</strong></td>
        <td><strong>WebRTC pricing</strong></td>
    </tr>
    <tr>
        <td><strong>Video calling</strong></td>
        <td>NA</td>
        <td>NA</td>
    </tr>
    <tr>
        <td><strong>Interactive live streaming</strong></td>
        <td>NA</td>
        <td>NA</td>
    </tr>
    <tr>
        <td><strong>RTMP</strong></td>
        <td>NA</td>
        <td>NA</td>
    </tr>
    <tr>
        <td><strong>Cloud Recording<strong/></strong></td>
        <td>NA</td>
        <td>NA</td>
    </tr>
</table>
<!--kg-card-end: html-->
<blockquote>Here's a detailed comparison of <a href="https://www.videosdk.live/webrtc-vs-jitsi">Jitsi vs WebRTC</a>.</blockquote><h2 id="4-jitsi-vs-daily">4. Jitsi vs Daily</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/08/Jitsi-Meet-vs-Daily.jpg" class="kg-image" alt="Best Jitsi Competitors in 2025" loading="lazy" width="1429" height="525"/></figure><p>Daily emerges as a developer-centric platform that grants developers the seamless capability to integrate real-time video and audio calls directly into their applications, all within the confines of web browsers. Armed with a suite of tools and features, <a href="https://www.videosdk.live/blog/daily-co-alternative">Daily</a> empowers developers to masterfully navigate the intricate backend intricacies of video calls, regardless of the diverse platforms they operate on.</p>
<!--kg-card-begin: html-->
<table border="2px black" cellspacing="0px" style="border-radius: 10px;">
    <tr>
        <td/>
        <td><strong>Jitsi pricing</strong></td>
        <td><strong>Daily pricing</strong></td>
    </tr>
    <tr>
        <td><strong>Video calling</strong></td>
        <td>NA</td>
        <td>Starts from <strong>$4</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>Interactive live streaming</strong></td>
        <td>NA</td>
        <td>Starts from <strong>$1.2</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>RTMP</strong></td>
        <td>NA</td>
        <td><strong>$15</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>Cloud Recording<strong/></strong></td>
        <td>NA</td>
        <td><strong>$13.49</strong> per 1,000 minutes</td>
    </tr>
</table>
<!--kg-card-end: html-->
<blockquote>Here's a detailed comparison of <a href="https://www.videosdk.live/jitsi-vs-daily">Jitsi vs Daily</a>.</blockquote><h2 id="5-jitsi-vs-livekit">5. Jitsi vs LiveKit</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/08/Jitsi-Meet-vs-LiveKit.jpg" class="kg-image" alt="Best Jitsi Competitors in 2025" loading="lazy" width="1429" height="525"/></figure><p>Livekit extends a comprehensive solution tailored for developers keen on seamlessly integrating live video and audio functionalities into their native applications. By leveraging its array of well-crafted software development kits (SDKs), <a href="https://www.videosdk.live/blog/livekit-alternative">Livekit</a> simplifies the process of infusing a diverse range of real-time communication features into your applications.</p>
<!--kg-card-begin: html-->
<table border="2px black" cellspacing="0px" style="border-radius: 10px;">
    <tr>
        <td/>
        <td><strong>Jitsi pricing</strong></td>
        <td><strong>LiveKit pricing</strong></td>
    </tr>
    <tr>
        <td><strong>Video calling</strong></td>
        <td>NA</td>
        <td>Starts from <strong>$20</strong> per 1,000 minutes</td>
    </tr>
    <tr>
        <td><strong>Interactive live streaming</strong></td>
        <td>NA</td>
        <td>
            <strong>$69</strong> per hour (upto 500 viewers only and doesn't support Full HD)
        </td>
    </tr>
    <tr>
        <td><strong>RTMP</strong></td>
        <td>NA</td>
        <td>No accurate data available</td>
    </tr>
    <tr>
        <td><strong>Cloud Recording</strong></td>
        <td>NA</td>
        <td>No accurate data available</td>
    </tr>
</table>
<!--kg-card-end: html-->
<blockquote>Here's a detailed comparison of <a href="https://www.videosdk.live/jitsi-vs-livekit">Jitsi vs LiveKit</a>.</blockquote><h2 id="have-you-determined-whether-jitsi-aligns-with-your-requirements-or-have-you-found-an-alternative">Have you determined whether Jitsi aligns with your requirements, or have you found an alternative?</h2>
<p>Absolutely, the alternatives to Jitsi that were discussed earlier provide a wide spectrum of solutions for developers looking to elevate in-app user experiences. However, if your objectives go beyond basic in-app communication and encompass a broader engagement strategy that integrates voice and video capabilities, solutions like <a href="https://www.videosdk.live/signup/">VideoSDK</a> might indeed align more closely with your requirements. These solutions offer the tools and features necessary to craft immersive and interactive experiences for your users, enabling you to provide a communication environment that goes beyond mere text-based interaction. By delving into these alternatives, you have the opportunity to enhance your application's user experience and create a more dynamic and engaging platform for your users.</p><p>Considering your unique requirements, budget constraints, and the essential features you're seeking, it's possible that Jitsi may not be the perfect match for your needs. To ensure that you make a well-informed decision, it's highly recommended to thoroughly explore the alternatives that were previously discussed. Some of these alternatives, such as VideoSDK, offer the advantage of free trial options. These trials provide an excellent opportunity to assess their capabilities in real-world projects, allowing you to gain valuable insights into how effectively they align with your requirements before committing fully. Furthermore, it's crucial to keep in mind that should your needs evolve over time, you retain the flexibility to transition away from Jitsi and opt for a solution that better aligns with your changing demands.</p>]]></content:encoded></item><item><title><![CDATA[How to Build an iOS Live Streaming App with VideoSDK]]></title><description><![CDATA[Learn to develop an iOS live-streaming app using VideoSDK. Master the process step-by-step for seamless video streaming on iOS devices.]]></description><link>https://www.videosdk.live/blog/ios-live-streaming-app</link><guid isPermaLink="false">662781052a88c204ca9d4bef</guid><category><![CDATA[iOS]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Mon, 13 Jan 2025 07:04:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/HTTP-Live-Stream-in-iOS-Video-Call-App.png" medium="image"/><content:encoded><![CDATA[<blockquote>An iOS live streaming app captures host audio and video through WebRTC, composites it into an HLS broadcast, and delivers playback URLs to viewers on any device. With VideoSDK's Swift SDK, you install the pod, create rooms via REST API, join meetings with RTCMTLVideoView, and start HLS with configurable layouts. Most teams ship a working prototype in one development sprint.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/HTTP-Live-Stream-in-iOS-Video-Call-App.png" alt="How to Build an iOS Live Streaming App with VideoSDK"/><p>A creator who taps "Go Live" and waits eight seconds for the first viewer frame loses the audience before the stream starts. iOS live streaming demands a pipeline that handles real-time host capture, server-side composition, and CDN-scale delivery without forcing your Swift team to operate FFmpeg clusters from day one. This article defines iOS live streaming architecture, compares leading SDK options, covers production trade-offs most tutorials skip, and walks through a complete VideoSDK integration you can run on a physical iPhone today.</p><h2 id="what-is-an-ios-live-streaming-app">What Is an iOS Live Streaming App?</h2><p>An iOS live streaming app is defined as a native Swift application that captures real-time audio and video from device cameras, transmits host media to a composition service, and publishes an <a href="https://www.videosdk.live/blog/what-is-http-live-streaming" rel="noreferrer">HTTP Live Streaming (HLS)</a> playback URL that viewers consume on iPhones, browsers, and smart TVs.</p><p>An iOS live streaming app works by separating hosts from viewers at the protocol layer. Hosts join a WebRTC conference room for sub-second media exchange with co-hosts or producers. The platform transcodes that room into an HLS manifest with adaptive bitrate segments. Viewers never join the WebRTC mesh. They request the HLS URL through a standard video player, which scales to thousands of concurrent watchers through CDN edge caching.</p><p>According to Apple's HTTP Live Streaming specification, HLS breaks video into small&nbsp;<code>.ts</code>&nbsp;or fMP4 segments listed in an&nbsp;<code>.m3u8</code>&nbsp;playlist that players refresh continuously during a broadcast <a href="https://developer.apple.com/documentation/http-live-streaming/hls-authoring-specification-for-apple-devices" rel="noreferrer">Apple HTTP Live Streaming specification</a>. WebRTC, standardized by the W3C and IETF, handles the low-latency host capture path on iOS through frameworks like VideoSDK RTC built on Google's WebRTC stack.</p><p>The distinction matters because many iOS tutorials teach video calling and label it live streaming. A true broadcast app adds HLS composition, playback URL distribution, and viewer-side players that your Swift UI never has to render as WebRTC tracks.</p><h2 id="how-does-live-streaming-work-on-ios">How Does Live Streaming Work on iOS?</h2><p>Live streaming on iOS follows a four-stage pipeline: capture, ingest, transcode, and deliver, with each stage handled by different system components.</p><h3 id="stage-1-media-capture">Stage 1: Media Capture</h3><p>The host device's camera and microphone feed into&nbsp;<code>AVCaptureSession</code>&nbsp;or an SDK wrapper that manages capture permissions, orientation, and codec selection. iOS requires&nbsp;<code>NSCameraUsageDescription</code>&nbsp;and&nbsp;<code>NSMicrophoneUsageDescription</code>&nbsp;entries in&nbsp;<code>Info.plist</code>&nbsp;before any capture starts. Without these keys, the system terminates the app on first camera access.</p><h3 id="stage-2-real-time-ingest">Stage 2: Real-Time Ingest</h3><p>Encoded media travels from the iPhone to a selective forwarding unit (SFU) or media server over WebRTC. VideoSDK's&nbsp;<code>VideoSDK.initMeeting()</code>&nbsp;call establishes this path, negotiates ICE candidates, and manages adaptive bitrate based on network conditions.</p><h3 id="stage-3-hls-composition">Stage 3: HLS Composition</h3><p>When the host taps start broadcast, the platform composites active participant streams into a single HLS output with a configurable layout (grid, speaker priority, portrait orientation). VideoSDK's&nbsp;<code>startHLS(config:)</code>&nbsp;method triggers server-side composition and returns state events through&nbsp;<code>onHlsStateChanged</code>.</p><h3 id="stage-4-viewer-delivery">Stage 4: Viewer Delivery</h3><p>The HLS manifest URL propagates to viewer clients through your backend, push notification, or in-app deep link. Viewers play the stream with&nbsp;<code>AVPlayer</code>&nbsp;on iOS or any HLS-compatible player on other platforms. CDN edge nodes cache segments so viewer count does not multiply load on the host device.</p><p>In practice, engineering teams that ship iOS live streaming apps report that 70% of post-launch bugs trace to missing HLS state handling, token exposure in client bundles, or assuming viewers join the same WebRTC room as hosts.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-8--2026--04_49_53-PM.png" class="kg-image" alt="How to Build an iOS Live Streaming App with VideoSDK" loading="lazy" width="1693" height="929"><figcaption><span style="white-space: pre-wrap;">How live streaming works on iOS pipeline diagram</span></figcaption></img></figure><h3 id="benefits-of-ios-live-streaming-app">Benefits of iOS live streaming app:</h3><ul><li><strong>Real-Time Engagement</strong>: Live streaming allows for instant interaction and engagement with the audience, fostering a sense of connection and community.</li><li><strong>Increased Reach</strong>: With live streaming, you can reach a wider audience, as viewers can tune in from anywhere in the world.</li><li><strong>Cost-Effective Marketing</strong>: Compared to traditional marketing methods, live streaming can be a cost-effective way to promote your brand, as it requires minimal equipment and can be done from anywhere. For businesses focusing on regional growth, <a href="https://blacksmith.agency/services/branding-agency/atlanta/" rel="noreferrer">atlanta branding</a> helps tailor live streaming content to local audiences, improving relevance, engagement, and brand recognition.</li><li><strong>Builds Trust and Authenticity</strong>: Live streaming provides an authentic and transparent way to connect with your audience, helping to build trust and credibility.</li></ul><h3 id="use-cases-of-ios-live-streaming-app">Use Cases of iOS live streaming app:</h3><ul><li><strong>Live Events and Webinars</strong>: Host live events or webinars to engage with your audience in real-time, share knowledge, and provide valuable information on specific topics. You can <a href="https://www.uniqode.com/qr-code-generator" rel="noopener noreferrer">create a QR code</a> to allow quick access to the event link or resources.</li><li><strong>Product Launches</strong>: Live stream product launches to showcase new products or services, demonstrate features, and answer audience questions in real time.</li><li><strong>Q&amp;A Sessions</strong>: Host live Q&amp;A sessions to interact with your audience, address their questions, and provide valuable insights or advice.</li></ul><h2 id="how-to-develop-a-live-streaming-app-with-videosdk"><strong>How to Develop a Live Streaming App</strong> with VideoSDK</h2><h3 id="getting-started-with-videosdk">Getting Started with VideoSDK</h3><p>VideoSDK enables the opportunity to integrate video &amp; audio calling into Web, Android, and iOS applications with so many different frameworks. It is the best infrastructure solution that provides programmable SDKs and REST APIs to build scalable video conferencing applications. This guide will get you running with the VideoSDK video &amp; audio calling in minutes.</p><h3 id="create-a-videosdk-account">Create a VideoSDK Account</h3><p>Go to your <a href="https://app.videosdk.live/login">VideoSDK dashboard</a> and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.</p><h3 id="generate-your-auth-token">Generate your Auth Token</h3><p>Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token is crucial in authorizing your application to use VideoSDK features. For a more visual understanding of the account creation and token generation process, consider referring to the <a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/server-setup">provided tutorial</a>.</p><h3 id="prerequisites-and-setup">Prerequisites and Setup</h3><ul><li>iOS 11.0+</li><li>Xcode 12.0+</li><li>Swift 5.0+</li></ul><p><strong>This App will contain two screens:</strong></p><p><strong>Join Screen</strong>: This screen allows the user to either create a meeting or join the predefined meeting.</p><p><strong>Meeting Screen</strong>: This screen basically contains local and remote participant views and some meeting controls such as Enable/Disable the mic &amp; Camera and Leave meeting.</p><h2 id="integrate-videosdk%E2%80%8B">Integrate VideoSDK​</h2><p>To install VideoSDK, you must initialize the pod on the project by running the following command:</p><pre><code class="language-swift">pod init</code></pre><p>It will create the pod file in your project folder, Open that file and add the dependency for the VideoSDK, like below:</p><pre><code class="language-swift">pod 'VideoSDKRTC', :git =&gt; 'https://github.com/videosdk-live/videosdk-rtc-ios-sdk.git'</code></pre><figure class="kg-card kg-image-card"><img src="https://cdn.videosdk.live/website-resources/docs-resources/ios_quickstart_podfile.png" class="kg-image" alt="How to Build an iOS Live Streaming App with VideoSDK" loading="lazy" width="1376" height="798"/></figure><p>then run the below code to install the pod:</p><pre><code class="language-swift">pod install</code></pre><p>then declare the permissions in Info.plist :</p><pre><code class="language-swift">&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
&lt;string&gt;Camera permission description&lt;/string&gt;
&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;Microphone permission description&lt;/string&gt;</code></pre><h3 id="project-structure">Project Structure</h3><pre><code class="language-swift">iOSQuickStartDemo
   ├── Models
        ├── RoomStruct.swift
        └── MeetingData.swift
   ├── ViewControllers
        ├── StartMeetingViewController.swift
        └── MeetingViewController.swift
   ├── AppDelegate.swift // Default
   ├── SceneDelegate.swift // Default
   └── APIService
           └── APIService.swift
   ├── Main.storyboard // Default
   ├── LaunchScreen.storyboard // Default
   └── Info.plist // Default
 Pods
     └── Podfile</code></pre><h3 id="create-models%E2%80%8B">Create models<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#create-models">​</a></h3><p>Create a swift file for <code>MeetingData</code> and <code>RoomStruct</code> class model for setting data in object pattern.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">import Foundation
struct MeetingData {
    let token: String
    let name: String
    let meetingId: String
    let micEnabled: Bool
    let cameraEnabled: Bool
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">MeetingData.swift</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-swift">import Foundation
struct RoomsStruct: Codable {
    let createdAt, updatedAt, roomID: String?
    let links: Links?
    let id: String?
    enum CodingKeys: String, CodingKey {
        case createdAt, updatedAt
        case roomID = "roomId"
        case links, id
    }
}

// MARK: - Links
struct Links: Codable {
    let getRoom, getSession: String?
    enum CodingKeys: String, CodingKey {
        case getRoom = "get_room"
        case getSession = "get_session"
    }
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">RoomStruct.swift</span></p></figcaption></figure><h2 id="essential-steps-for-building-the-video-calling">Essential Steps for Building the Video Calling</h2><p>This guide is designed to walk you through the process of integrating Chat with <a href="https://www.videosdk.live/">VideoSDK</a>. We'll cover everything from setting up the SDK to incorporating the visual cues into your app's interface, ensuring a smooth and efficient implementation process.</p><h3 id="step-1-get-started-with-apiclient%E2%80%8B">Step 1: Get started with APIClient<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#step-1--get-started-with-apiclient">​</a></h3><p>Before jumping to anything else, we have to write an API to generate a unique <code>meetingId</code>. You will require an <strong>authentication token;</strong> you can generate it either using <a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples" rel="noopener noreferrer">videosdk-server-api-example</a> or from the <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer">VideoSDK Dashboard</a> for developers.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">import Foundation

let TOKEN_STRING: String = "&lt;AUTH_TOKEN&gt;"

class APIService {

  class func createMeeting(token: String, completion: @escaping (Result&lt;String, Error&gt;) -&gt; Void) {

    let url = URL(string: "https://api.videosdk.live/v2/rooms")!

    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.addValue(TOKEN_STRING, forHTTPHeaderField: "authorization")

    URLSession.shared.dataTask(
      with: request,
      completionHandler: { (data: Data?, response: URLResponse?, error: Error?) in

        DispatchQueue.main.async {

          if let data = data, let utf8Text = String(data: data, encoding: .utf8) {
            do {
              let dataArray = try JSONDecoder().decode(RoomsStruct.self, from: data)

              completion(.success(dataArray.roomID ?? ""))
            } catch {
              print("Error while creating a meeting: \(error)")
              completion(.failure(error))
            }
          }
        }
      }
    ).resume()
  }
}
</code></pre><figcaption><p><span style="white-space: pre-wrap;">APIService.swift</span></p></figcaption></figure><h3 id="step-2-implement-join-screen%E2%80%8B">Step 2: Implement Join Screen<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#step-2--implement-join-screen">​</a></h3><p>The Join Screen will work as a medium to either schedule a new meeting or join an existing meeting.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">import Foundation
import UIKit

class StartMeetingViewController: UIViewController, UITextFieldDelegate {

  private var serverToken = ""

  /// MARK: outlet for create meeting button
  @IBOutlet weak var btnCreateMeeting: UIButton!

  /// MARK: outlet for join meeting button
  @IBOutlet weak var btnJoinMeeting: UIButton!

  /// MARK: outlet for meetingId textfield
  @IBOutlet weak var txtMeetingId: UITextField!

  /// MARK: Initialize the private variable with TOKEN_STRING &amp;
  /// setting the meeting id in the textfield
  override func viewDidLoad() {
    txtMeetingId.delegate = self
    serverToken = TOKEN_STRING
    txtMeetingId.text = "PROVIDE-STATIC-MEETING-ID"
  }

  /// MARK: method for joining meeting through seague named as "StartMeeting"
  /// after validating the serverToken in not empty
  func joinMeeting() {

    txtMeetingId.resignFirstResponder()

    if !serverToken.isEmpty {
      DispatchQueue.main.async {
        self.dismiss(animated: true) {
          self.performSegue(withIdentifier: "StartMeeting", sender: nil)
        }
      }
    } else {
      print("Please provide auth token to start the meeting.")
    }
  }

  /// MARK: outlet for create meeting button tap event
  @IBAction func btnCreateMeetingTapped(_ sender: Any) {
    print("show loader while meeting gets connected with server")
    joinRoom()
  }

  /// MARK: outlet for join meeting button tap event
  @IBAction func btnJoinMeetingTapped(_ sender: Any) {
    if (txtMeetingId.text ?? "").isEmpty {

      print("Please provide meeting id to start the meeting.")
      txtMeetingId.resignFirstResponder()
    } else {
      joinMeeting()
    }
  }

  // MARK: - method for creating room api call and getting meetingId for joining meeting

  func joinRoom() {

    APIService.createMeeting(token: self.serverToken) { result in
      if case .success(let meetingId) = result {
        DispatchQueue.main.async {
          self.txtMeetingId.text = meetingId
          self.joinMeeting()
        }
      }
    }
  }

  /// MARK: preparing to animate to meetingViewController screen
  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    guard let navigation = segue.destination as? UINavigationController,

      let meetingViewController = navigation.topViewController as? MeetingViewController
    else {
      return
    }

    meetingViewController.meetingData = MeetingData(
      token: serverToken,
      name: txtMeetingId.text ?? "Guest",
      meetingId: txtMeetingId.text ?? "",
      micEnabled: true,
      cameraEnabled: true
    )
  }
}
</code></pre><figcaption><p><span style="white-space: pre-wrap;">StartMeetingViewController.swift</span></p></figcaption></figure><h3 id="step-3-initialize-and-join-meeting%E2%80%8B">Step 3: Initialize and Join Meeting<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#step-3--initialize-and-join-meeting">​</a></h3><p>Using the provided <code>token</code> and <code>meetingId</code>, we will configure and initialize the meeting in <code>viewDidLoad()</code>.</p><p>Then, we'll add <strong>@IBOutlet</strong> for <code>localParticipantVideoView</code> and <code>remoteParticipantVideoView</code>, which can render local and remote participant media, respectively.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">class MeetingViewController: UIViewController {

import UIKit
import VideoSDKRTC
import WebRTC
import AVFoundation

class MeetingViewController: UIViewController {

// MARK: - Properties
// outlet for local participant container view
   @IBOutlet weak var localParticipantViewContainer: UIView!

// outlet for label for meeting Id
   @IBOutlet weak var lblMeetingId: UILabel!

// outlet for local participant video view
   @IBOutlet weak var localParticipantVideoView: RTCMTLVideoView!

// outlet for remote participant video view
   @IBOutlet weak var remoteParticipantVideoView: RTCMTLVideoView!

// outlet for remote participant no media label
   @IBOutlet weak var lblRemoteParticipantNoMedia: UILabel!

// outlet for remote participant container view
   @IBOutlet weak var remoteParticipantViewContainer: UIView!

// outlet for local participant no media label
   @IBOutlet weak var lblLocalParticipantNoMedia: UILabel!

// Meeting data - required to start
   var meetingData: MeetingData!

// current meeting reference
   private var meeting: Meeting?

    // MARK: - video participants including self to show in UI
    private var participants: [Participant] = []

        // MARK: - Lifecycle Events

        override func viewDidLoad() {
        super.viewDidLoad()
        // configure the VideoSDK with token
        VideoSDK.config(token: meetingData.token)

        // init meeting
        initializeMeeting()

        // set meeting id in button text
        lblMeetingId.text = "Meeting Id: \(meetingData.meetingId)"
      }

      override func viewWillAppear(_ animated: Bool) {
          super.viewWillAppear(animated)
          navigationController?.navigationBar.isHidden = true
      }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.navigationBar.isHidden = false
        NotificationCenter.default.removeObserver(self)
    }

        // MARK: - Meeting

        private func initializeMeeting() {

            // Initialize the VideoSDK
            meeting = VideoSDK.initMeeting(
                meetingId: meetingData.meetingId,
                participantName: meetingData.name,
                micEnabled: meetingData.micEnabled,
                webcamEnabled: meetingData.cameraEnabled
            )

            // Adding the listener to meeting
            meeting?.addEventListener(self)

            // joining the meeting
            meeting?.join()
        }
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">MeetingViewController.swift</span></p></figcaption></figure><h3 id="step-4-implement-controls%E2%80%8B">Step 4: Implement Controls<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#step-4--implement-controls">​</a></h3><p>After initializing the meeting in the previous step, we will now add <strong>@IBOutlet</strong> for <code>btnLeave</code>, <code>btnToggleVideo</code> and <code>btnToggleMic</code> which can control the media in the meeting. </p><p>Along with that we'll add one more <strong>@IBOutlet</strong> button <code>btnToggleHLS</code> using which we will start/stop HLS.</p><blockquote>Added a button to toggle HLS and code for the same, please check for grammar or typos.</blockquote><figure class="kg-card kg-code-card"><pre><code class="language-swift">class MeetingViewController: UIViewController {

...

    // outlet for leave button
    @IBOutlet weak var btnLeave: UIButton!

    // outlet for toggle video button
    @IBOutlet weak var btnToggleVideo: UIButton!

    // outlet for toggle audio button
    @IBOutlet weak var btnToggleMic: UIButton!
    
    // outlet for toggle HLS button
    @IBOutlet weak var btnToggleHLS: UIButton!

    // bool for mic
    var micEnabled = true
    // bool for video
    var videoEnabled = true
    // bool for hls state
    var hlsEnabled = false


    // outlet for leave button click event
    @IBAction func btnLeaveTapped(_ sender: Any) {
            DispatchQueue.main.async {
                self.meeting?.leave()
                self.dismiss(animated: true)
            }
        }

    // outlet for toggle mic button click event
    @IBAction func btnToggleMicTapped(_ sender: Any) {
        if micEnabled {
            micEnabled = !micEnabled // false
            self.meeting?.muteMic()
        } else {
            micEnabled = !micEnabled // true
            self.meeting?.unmuteMic()
        }
    }

    // outlet for toggle video button click event
    @IBAction func btnToggleVideoTapped(_ sender: Any) {
        if videoEnabled {
            videoEnabled = !videoEnabled // false
            self.meeting?.disableWebcam()
        } else {
            videoEnabled = !videoEnabled // true
            self.meeting?.enableWebcam()
        }
    }
    
      // outlet for toggle HLS button click event
    @IBAction func btnToggleHLSTapped(_ sender: Any) {
        if !hlsEnabled {
        		// sample config
             let config: HLSConfig = HLSConfig(layout: 
                            ConfigLayout(type: .GRID, 
                                         priority: .SPEAKER, 
                                         gridSize: 4), 
                                         theme: .DARK, 
                                         mode: .video_and_audio, 
                                         quality: .high, 
                                         orientation: .portrait)
          // start hls, you can use your custom configs as per your need
             self.meeting?.startHLS(config: config)
             self.hlsEnabled = true
        } else {
            self.meeting?.stopHLS()
            self.hlsEnabled = false
        }
    }

...

}</code></pre><figcaption><p><span style="white-space: pre-wrap;">MeetingViewController.swift</span></p></figcaption></figure><h3 id="step-5-implementing-meetingeventlistener%E2%80%8B">Step 5: Implementing <code>MeetingEventListener</code>​</h3><p>In this step, we'll create an extension for the <code>MeetingViewController</code> that implements the MeetingEventListener, which implements the <code>onMeetingJoined</code>, <code>onMeetingLeft</code>, <code>onParticipantJoined</code>, <code>onParticipantLeft</code>, <code>onParticipantChanged</code>, <code>onHlsStateChanged</code> etc. methods.</p><p>When HLS is started, it triggers the <code>onHlsStateChanged</code> event of the MeetingEventListener.</p><blockquote>Removed onspeakerchanged event and added onhlsstatechanged event and code for the same</blockquote><figure class="kg-card kg-code-card"><pre><code class="language-swift">
class MeetingViewController: UIViewController {

...

extension MeetingViewController: MeetingEventListener {

        /// Meeting started
        func onMeetingJoined() {

            // handle local participant on start
            guard let localParticipant = self.meeting?.localParticipant else { return }
            // add to list
            participants.append(localParticipant)

            // add event listener
            localParticipant.addEventListener(self)

            localParticipant.setQuality(.high)

            if(localParticipant.isLocal){
                self.localParticipantViewContainer.isHidden = false
            } else {
                self.remoteParticipantViewContainer.isHidden = false
            }
        }

        /// Meeting ended
        func onMeetingLeft() {
            // remove listeners
            meeting?.localParticipant.removeEventListener(self)
            meeting?.removeEventListener(self)
        }

        /// A new participant joined
        func onParticipantJoined(_ participant: Participant) {
            participants.append(participant)

            // add listener
            participant.addEventListener(self)

            participant.setQuality(.high)

            if(participant.isLocal){
                self.localParticipantViewContainer.isHidden = false
            } else {
                self.remoteParticipantViewContainer.isHidden = false
            }
        }

        /// A participant left from the meeting
        /// - Parameter participant: participant object
        func onParticipantLeft(_ participant: Participant) {
            participant.removeEventListener(self)
            guard let index = self.participants.firstIndex(where: { $0.id == participant.id }) else {
                return
            }
            // remove participant from list
            participants.remove(at: index)
            // hide from ui
            UIView.animate(withDuration: 0.5){
                if(!participant.isLocal){
                    self.remoteParticipantViewContainer.isHidden = true
                }
            }
        }
        
        /// HLS state changed event
        /// - Parameters state: HLSState and hlsUrl: HLSUrl if given
        func onHlsStateChanged(state: HLSState, hlsUrl: HLSUrl?) {
            switch(state) {
                case .HLS_STARTING:
                    print("HLS Starting")

                case .HLS_STARTED:
                    print("HLS Started")

                case .HLS_PLAYABLE:
                    print("HLS Playable")

                case .HLS_STOPPING:
                    print("HLS Stopping")

                case .HLS_STOPPED:
                    print("HLS Stopped")
                }
    }
}

...</code></pre><figcaption><p><span style="white-space: pre-wrap;">MeetingViewController.swift</span></p></figcaption></figure><h3 id="step-6-implementing-participanteventlistener">Step 6: Implementing <code>ParticipantEventListener</code></h3><p>In this stage, we'll add an extension for the <code>MeetingViewController</code> that implements the ParticipantEventListener, which implements the <code>onStreamEnabled</code> and <code>onStreamDisabled</code> methods for the audio and video of MediaStreams enabled or disabled.</p><p>The function update UI is frequently used to control or modify the user interface (enable/disable camera &amp; mic) by the MediaStream state.</p><pre><code class="language-swift">class MeetingViewController: UIViewController {

...

extension MeetingViewController: ParticipantEventListener {

/// Participant has enabled mic, video or screenshare
/// - Parameters:
/// - stream: enabled stream object
/// - participant: participant object
func onStreamEnabled(_ stream: MediaStream, forParticipant participant: Participant) {
    updateUI(participant: participant, forStream: stream, enabled: true)
 }

/// Participant has disabled mic, video or screenshare
/// - Parameters:
///   - stream: disabled stream object
///   - participant: participant object
        
func onStreamDisabled(_ stream: MediaStream, 
			forParticipant participant: Participant) {
            
  updateUI(participant: participant, forStream: stream, enabled: false)
 }
 
}

private extension MeetingViewController {

 func updateUI(participant: Participant, forStream stream: MediaStream, 							enabled: Bool) { // true
        switch stream.kind {
        case .state(value: .video):
            if let videotrack = stream.track as? RTCVideoTrack {
                if enabled {
                    DispatchQueue.main.async {
                        UIView.animate(withDuration: 0.5){
                        
                            if(participant.isLocal) {
                            
    	self.localParticipantViewContainer.isHidden = false
	self.localParticipantVideoView.isHidden = false       
	self.localParticipantVideoView.videoContentMode = .scaleAspectFill                            self.localParticipantViewContainer.bringSubviewToFront(self.localParticipantVideoView)                         									
    videotrack.add(self.localParticipantVideoView)
    self.lblLocalParticipantNoMedia.isHidden = true

} else {
		self.remoteParticipantViewContainer.isHidden = false
        	self.remoteParticipantVideoView.isHidden = false
                                self.remoteParticipantVideoView.videoContentMode = .scaleAspectFill
                                self.remoteParticipantViewContainer.bringSubviewToFront(self.remoteParticipantVideoView)
                                		        videotrack.add(self.remoteParticipantVideoView)
 self.lblRemoteParticipantNoMedia.isHidden = true
        }
     }
  }
} else {
         UIView.animate(withDuration: 0.5){
                if(participant.isLocal){
                
                    self.localParticipantViewContainer.isHidden = false
                    self.localParticipantVideoView.isHidden = true
                    self.lblLocalParticipantNoMedia.isHidden = false
                            videotrack.remove(self.localParticipantVideoView)
} else {
                   self.remoteParticipantViewContainer.isHidden = false
                   self.remoteParticipantVideoView.isHidden = true
                   self.lblRemoteParticipantNoMedia.isHidden = false
                            videotrack.remove(self.remoteParticipantVideoView)
      }
    }
  }
}

     case .state(value: .audio):
            if participant.isLocal {
                
               localParticipantViewContainer.layer.borderWidth = 4.0
               localParticipantViewContainer.layer.borderColor = enabled ? UIColor.clear.cgColor : UIColor.red.cgColor
            } else {
                remoteParticipantViewContainer.layer.borderWidth = 4.0
                remoteParticipantViewContainer.layer.borderColor = enabled ? UIColor.clear.cgColor : UIColor.red.cgColor
            }
        default:
            break
        }
    }
}

...
</code></pre><h3 id="known-issue%E2%80%8B">Known Issue<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#known-issue">​</a></h3><p>Please add the following line to the <code>MeetingViewController.swift</code> file's <code>viewDidLoad</code> method If you get your video out of the container, view like below image.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">override func viewDidLoad() {

  localParticipantVideoView.frame = CGRect(x: 10, y: 0, 
    		width: localParticipantViewContainer.frame.width, 
   		height: localParticipantViewContainer.frame.height)

  localParticipantVideoView.bounds = CGRect(x: 10, y: 0, 
  		width: localParticipantViewContainer.frame.width, 
        	height: localParticipantViewContainer.frame.height)

  localParticipantVideoView.clipsToBounds = true

  remoteParticipantVideoView.frame = CGRect(x: 10, y: 0, 
  		width: remoteParticipantViewContainer.frame.width, 
        	height: remoteParticipantViewContainer.frame.height)
        
  remoteParticipantVideoView.bounds = CGRect(x: 10, y: 0, 
  		width: remoteParticipantViewContainer.frame.width, 
    		height: remoteParticipantViewContainer.frame.height)
    
    remoteParticipantVideoView.clipsToBounds = true
}
</code></pre><figcaption><p><span style="white-space: pre-wrap;">MeetingViewController.swift</span></p></figcaption></figure><blockquote><strong>TIP:</strong><br>Stuck anywhere? Check out this <a href="https://github.com/videosdk-live/videosdk-rtc-ios-sdk-example" rel="noopener noreferrer">example code</a> on GitHub</br></blockquote><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/videosdk-live/videosdk-rtc-ios-sdk-example"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - videosdk-live/videosdk-rtc-ios-sdk-example: WebRTC based video conferencing SDK for iOS (Swift / Objective C)</div><div class="kg-bookmark-description">WebRTC based video conferencing SDK for iOS (Swift / Objective C) - videosdk-live/videosdk-rtc-ios-sdk-example</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="How to Build an iOS Live Streaming App with VideoSDK"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">videosdk-live</span></img></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/3d2f5eef43ad3d03fbe693ee2c8633053215e90252a63bddc775d8b8d8a7e380/videosdk-live/videosdk-rtc-ios-sdk-example" alt="How to Build an iOS Live Streaming App with VideoSDK" onerror="this.style.display = 'none'"/></div></a></figure><p>Now you have successfully created an iOS Live Streaming Application with the VideoSDK.</p><h2 id="conclusion">Conclusion</h2><p>VideoSDK offers a seamless solution for building iOS live-streaming applications. With its user-friendly interface and robust features, developers can efficiently create high-quality streaming experiences for users. With an iOS development agency like <a href="https://www.simpalm.com/services/iphone-app-development-company"><strong>Simpalm</strong></a><strong> </strong>can further enhance the development process, ensuring top-notch results.</p><p>Unlock the full potential of VideoSDK today and craft seamless video experiences! <a href="https://app.videosdk.live/dashboard"><strong>Sign up</strong></a> now to receive 10,000 free minutes and take your video app to new heights.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><h3 id="how-do-you-build-a-live-streaming-app-on-ios">How do you build a live streaming app on iOS?</h3><p>You build a live streaming app on iOS by installing a real-time SDK like VideoSDK, configuring camera and microphone permissions, creating meeting rooms via REST API, joining as a WebRTC host, and starting HLS broadcast with&nbsp;<code>startHLS()</code>. Viewers consume the resulting playback URL through&nbsp;<code>AVPlayer</code>&nbsp;or a web HLS player. The entire host integration takes one development sprint with the VideoSDK quickstart.</p><h3 id="what-is-the-difference-between-webrtc-and-hls-on-ios">What is the difference between WebRTC and HLS on iOS?</h3><p>The difference between WebRTC and HLS on iOS is latency and scale. WebRTC delivers sub-second two-way media between conference participants but does not scale to large audiences. HLS delivers 5 to 15 second delayed playback to thousands of viewers through CDN caching. Production iOS live streaming apps use WebRTC for hosts and HLS for viewers.</p><h3 id="can-you-live-stream-from-an-ios-app">Can you live stream from an iOS app?</h3><p>Yes, you can live stream from an iOS app using AVFoundation for capture combined with either a custom RTMP pipeline or an SDK like VideoSDK that handles WebRTC ingest and HLS output. Apple requires privacy usage descriptions for camera and microphone access. Physical device testing is mandatory because the Simulator lacks real capture hardware.</p><h3 id="what-sdk-should-i-use-for-ios-live-streaming">What SDK should I use for iOS live streaming?</h3><p>The best SDK for iOS live streaming depends on your team's constraints. VideoSDK is the right choice for Swift teams needing sub-10-minute integration with managed HLS composition. AWS IVS suits teams already on AWS infrastructure. Agora fits teams needing global RTC with separate transcoding services. Raw AVFoundation suits teams with dedicated media engineers.</p><h3 id="how-many-viewers-can-an-ios-hls-stream-support">How many viewers can an iOS HLS stream support?</h3><p>An iOS HLS stream supports thousands of concurrent viewers because viewer traffic routes through CDN edge nodes rather than the host iPhone. The host device sends one upstream WebRTC stream to the composition service. Viewer count does not increase load on the broadcaster's device. Exact capacity depends on your CDN configuration and VideoSDK plan [UPDATE: verify date].</p><h3 id="does-ios-support-rtmp-natively">Does iOS support RTMP natively?</h3><p>No, iOS does not support RTMP natively in AVFoundation or AVPlayer. RTMP ingest requires third-party libraries or an SDK that handles the RTMP handshake and packet framing. Most modern iOS live streaming apps use WebRTC for ingest and HLS for delivery instead of RTMP.</p><h3 id="how-do-you-handle-hls-state-changes-in-a-videosdk-ios-app">How do you handle HLS state changes in a VideoSDK iOS app?</h3><p>You handle HLS state changes by implementing&nbsp;<code>onHlsStateChanged</code>&nbsp;in your&nbsp;<code>MeetingEventListener</code>&nbsp;extension. The callback fires through states including&nbsp;<code>.HLS_STARTING</code>,&nbsp;<code>.HLS_STARTED</code>,&nbsp;<code>.HLS_PLAYABLE</code>, and&nbsp;<code>.HLS_STOPPED</code>. When the state reaches&nbsp;<code>.HLS_PLAYABLE</code>, extract the playback URL from the event and distribute it to viewer clients through your backend.</p>]]></content:encoded></item><item><title><![CDATA[Quality Comparison: VideoSDK vs Zoom in Web 1:1 Video Calls]]></title><description><![CDATA[If you're here, it's likely that the sudden news about Twilio Programmable Video has thrown a curveball into your quarterly plans. We get it - disruptions in your tech stack can be a game-changer. You might be considering Zoom as your next service provider, but between this twist, remember, it's not just a change but an opportunity to upgrade.

That's why we've conducted a comparison between VideoSDK and Zoom. Check the results before making your decision – let's ensure this unexpected turn beco]]></description><link>https://www.videosdk.live/blog/quality-comparison-videosdk-vs-zoom-in-web-1-1-video-calls</link><guid isPermaLink="false">65ab70ca6c68429b5fdf18a8</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 13 Jan 2025 06:17:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/01/VideoSDK-vs-Zoom-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2024/01/VideoSDK-vs-Zoom-1.png" alt="Quality Comparison: VideoSDK vs Zoom in Web 1:1 Video Calls"/><p>If you're here, it's likely that the sudden news about Twilio Programmable Video has thrown a curveball into your quarterly plans. We get it - disruptions in your tech stack can be a game-changer. You might be considering Zoom as your next service provider, but between this twist, remember, it's not just a change but an opportunity to upgrade. </p><p>That's why we've conducted a comparison between VideoSDK and Zoom. Check the results before making your decision – let's ensure this unexpected turn becomes a positive step forward.</p><h2 id="quality-is-the-core">Quality is the Core!</h2><p>When it comes to video calls, quality is everything. You can throw in a bunch of cool features or fancy tech, but if you lack quality, it's a deal-breaker. No arguments there! We understand this, and that's why in this blog, we're diving into the nitty-gritty of quality.</p><p>Numerous factors can affect the quality of a video call, with the most basic connection being tied to your network. While considering Zoom as your potential service provider, compromising on quality should never be on the table.</p><p>That's why we're putting VideoSDK against Zoom in a quality showdown under various network bandwidths. See for yourself how VideoSDK not only keeps up but outperforms standards previously set by Twilio and Zoom.</p><h2 id="setting-up-the-platform">Setting up the platform</h2><p>Before we jump into the comparison, let's quickly examine key parameters for our evaluation, including devices, configurations, network throttling, and more.</p><ul><li>We'll be covering standard one-to-one web video calls</li><li>Both the sender and receiver are using MacBook Pro devices. </li><li>In maintaining an unbiased assessment, VideoSDK and Zoom App configurations have been set to default. Since their default settings are almost identical.</li><li>Additionally, for measuring network bandwidth, we'll be using <a href="https://fast.com">fast.com</a></li></ul><h2 id="test-scenarios">Test Scenarios</h2><p>Now that we've covered the setup, let's cover what scenarios we'll be creating to compare call quality between <a href="https://www.videosdk.live/alternative/zoom-vs-videosdk">VideoSDK and Zoom</a>.</p><p>Firstly, we'll evaluate metrics under normal conditions to establish a baseline.</p><p>Following that, we'll introduce network bandwidth throttling from only the narrator's side, simulating various scenarios at - </p><ul><li>1mbps</li><li>500kbps</li><li>250kbps</li></ul><h2 id="results">Results</h2><p>Here's a look at the important metrics we followed in different network situations, showing how VideoSDK and Zoom tackled challenges. Watch Rajan in the next video showcasing VideoSDK, and Ahmed demonstrating how Zoom performed.</p><!--kg-card-begin: html--><div>
<video src="https://assets.videosdk.live/alternative-page/videosdk-quality-comparison.mp4" controls="true" width="100%"/>
</div>
<div>
<video src="https://assets.videosdk.live/alternative-page/zoom-videosdk-comparison.mp4" controls="true" width="100%"/>
</div><!--kg-card-end: html--><p>Let's break down the results, exploring how each handles FPS, latency, and packet loss under different network bandwidths.</p><h3 id="frames-per-second-fps">Frames Per Second (FPS)</h3><p>As shown in the video, we can see how VideoSDK outperformed Zoom at handling Frame Per Second at each bandwidth.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/01/VideoSDK-vs-Zoom---fps-1.png" class="kg-image" alt="Quality Comparison: VideoSDK vs Zoom in Web 1:1 Video Calls" loading="lazy" width="1280" height="638"/></figure><h3 id="latency">Latency</h3><p>VideoSDK clearly outperformed Zoom in managing latency by a considerable margin. This outcome was somewhat anticipated, given Zoom's lack of globally connected regions.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/VideoSDK-vs-Zoom---latency.png" class="kg-image" alt="Quality Comparison: VideoSDK vs Zoom in Web 1:1 Video Calls" loading="lazy" width="1280" height="638"/></figure><h3 id="packet-loss">Packet loss</h3><p>In another instance of the same issue, VideoSDK demonstrated superiority in handling packet loss compared to Zoom.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/VideoSDK-vs-Zoom---packet-loss-1.png" class="kg-image" alt="Quality Comparison: VideoSDK vs Zoom in Web 1:1 Video Calls" loading="lazy" width="1280" height="638"/></figure><h2 id="conclusion">Conclusion</h2><p>Upon reviewing the videos and closely tracking the metrics, it's evident that <a href="https://videosdk.live">VideoSDK</a> outperforms Zoom significantly, especially in low network conditions, across various quality aspects. However, it's important to note that Zoom faces limitations due to its approach to global latency issues. Zoom requires users to select servers before initiating meetings, which can lead to connectivity challenges, even in well-connected scenarios where users are connecting to servers thousands of kilometers away.</p><p>VideoSDK addresses this challenge effectively by allowing participants to connect to the nearest servers. With efficient server-to-server communication for data sharing, VideoSDK achieves lower latency at a higher quality, providing a robust solution to global latency issues.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/01/Conclusion.png" class="kg-image" alt="Quality Comparison: VideoSDK vs Zoom in Web 1:1 Video Calls" loading="lazy" width="1493" height="1203"/></figure>]]></content:encoded></item><item><title><![CDATA[Quality Comparison: VideoSDK vs Twilio in Web 1:1 Video Calls]]></title><description><![CDATA[If you're here, it's likely that the sudden news about Twilio Programmable Video has thrown a curveball into your quarterly plans. We get it - disruptions in your tech stack can be a game-changer. But worry not! VideoSDK is here, not just for migration but to enhance your experience – turning this unexpected twist into an opportunity for an upgrade.


Quality is the Core!

When it comes to video calls, quality is everything. You can throw in a bunch of cool features or fancy tech, but if you lac]]></description><link>https://www.videosdk.live/blog/comparing-call-quality-in-web-1-1-video-calls-videosdk-vs-twilio</link><guid isPermaLink="false">65ab57c16c68429b5fdf17fa</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Mon, 13 Jan 2025 06:17:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/01/VideoSDK-vs-Twilio-3.png" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2024/01/VideoSDK-vs-Twilio-3.png" alt="Quality Comparison: VideoSDK vs Twilio in Web 1:1 Video Calls"/><p>If you're here, it's likely that the sudden news about Twilio Programmable Video has thrown a curveball into your quarterly plans. We get it - disruptions in your tech stack can be a game-changer. But worry not! VideoSDK is here, not just for migration but to enhance your experience – turning this unexpected twist into an opportunity for an upgrade.</p><h2 id="quality-is-the-core">Quality is the Core!</h2><p>When it comes to video calls, quality is everything. You can throw in a bunch of cool features or fancy tech, but if you lack in quality, it's a deal-breaker. No arguments there! We understand this, and that's why in this blog, we're diving into the nitty-gritty of quality.</p><p>Numerous factors can affect the quality of a video call, with the most basic connection being tied to your network. Thus, while exploring options for migrating to different service providers, you must not compromise the quality. </p><p>That's why we're putting VideoSDK against Twilio in a quality showdown under various network bandwidths. See for yourself how VideoSDK not only keeps up but outperforms Twilio's standards.</p><h2 id="setting-up-the-platform">Setting up the platform</h2><p>Before we jump into the comparison, let's quickly examine key parameters for our evaluation, including devices, configurations, network throttling, and more.</p><ul><li>We'll be covering standard one-to-one web video calls</li><li>Both the sender and receiver are using MacBook Pro devices. </li><li>In maintaining an unbiased assessment, VideoSDK and Twilio configurations have been set to default. Since their default settings are almost identical.</li><li>Additionally, for measuring network bandwidth, we'll be using <a href="https://fast.com ">fast.com</a></li></ul><h2 id="test-scenarios">Test Scenarios</h2><p>Now that we've covered the setup, let us cover what scenarios we'll be creating to compare call quality between VideoSDK and Twilio.</p><p>Firstly, we'll evaluate metrics under normal conditions to establish a baseline.</p><p>Following that, we'll introduce network bandwidth throttling from only the narrator's side, simulating various scenarios at - </p><ul><li>1mbps</li><li>500kbps</li><li>250kbps</li></ul><h2 id="results">Results</h2><p>Here's a look at the important metrics we followed in different network situations, showing how VideoSDK and Twilio tackled challenges. Watch Rajan in the next video showcasing VideoSDK and Twilio demonstrating how they performed.</p><!--kg-card-begin: html--><div>
<video src="https://assets.videosdk.live/alternative-page/videosdk-quality-comparison.mp4" controls="true" width="100%"/>
</div>
<div>
<video src="https://assets.videosdk.live/alternative-page/twilio-quality-comparison.mp4" controls="true" width="100%"/>
</div><!--kg-card-end: html--><p>Let's break down the results, exploring how each handles FPS, latency, and packet loss under different network bandwidths.</p><h3 id="frames-per-second-fps">Frames Per Second (FPS)</h3><p>As shown in the video, VideoSDK outshines Twilio in managing Frames Per Second (FPS) at different bandwidths. The comparison highlights VideoSDK's ability to deliver smoother and more consistent frame rates that too at better resolutions.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/01/VideoSDK-vs-Twilio---fps-3.png" class="kg-image" alt="Quality Comparison: VideoSDK vs Twilio in Web 1:1 Video Calls" loading="lazy" width="1280" height="638"/></figure><h3 id="latency">Latency</h3><p>The latency battle between <a href="https://www.videosdk.live/alternative/twilio-vs-videosdk">VideoSDK and Twilio</a> is neck-to-neck, with VideoSDK performing slightly better at higher resolutions.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/VideoSDK-vs-Twilio---latency.png" class="kg-image" alt="Quality Comparison: VideoSDK vs Twilio in Web 1:1 Video Calls" loading="lazy" width="1280" height="638"/></figure><h3 id="packet-loss">Packet-loss</h3><p>Both VideoSDK and Twilio performed better at managing packet loss, with Twilio performing slightly better, but at the expense of lower bitrate and resolutions.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/VideoSDK-vs-Twilio---packet-loss.png" class="kg-image" alt="Quality Comparison: VideoSDK vs Twilio in Web 1:1 Video Calls" loading="lazy" width="1280" height="638"/></figure><h2 id="conclusion">Conclusion</h2><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/02/Twilio-conclusion.png" class="kg-image" alt="Quality Comparison: VideoSDK vs Twilio in Web 1:1 Video Calls" loading="lazy" width="1493" height="1203"/></figure><p>Upon reviewing the videos and closely tracking the metrics, it's evident that <a href="https://videosdk.live">VideoSDK</a> and Twilio engaged in a neck-to-neck battle. VideoSDK won at delivering superior resolutions, bitrate and FPS even under lower network bandwidth conditions. On the other hand, Twilio, while successfully mitigating packet loss and latency, compromised on the other at lower values. Despite these trade-offs, VideoSDK emerged as the provider offering an overall enhanced experience for viewers.</p>]]></content:encoded></item><item><title><![CDATA[How to Implement Low Latency Video Calls with VideoSDK?]]></title><description><![CDATA[Discover how to minimize latency in WebRTC applications using VideoSDK and implement low-latency video calls with step-by-step instructions.]]></description><link>https://www.videosdk.live/blog/implement-low-latency-video-calls</link><guid isPermaLink="false">669a0bfd20fab018df10f9ad</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Sun, 12 Jan 2025 13:03:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/07/Low-Latency-Integration.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="what-is-low-latency">What is Low Latency? </h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/Low-Latency-Integration.jpg" alt="How to Implement Low Latency Video Calls with VideoSDK?"/><p>Low latency refers to the minimal delay between the transmission and reception of data in a communication system. In the context of <a href="https://www.videosdk.live/developer-hub/webrtc">WebRTC</a> (Web Real-Time Communication), low latency is crucial for providing a seamless, real-time experience for users engaged in video calls, audio chats, or any form of live interaction over the web. The goal is to reduce the time it takes for data to travel from its source to its destination, ensuring that conversations flow naturally and actions appear instantaneous.</p><h2 id="factors-affecting-latency">Factors Affecting Latency </h2><p>Several key factors influence the latency in WebRTC applications. Network conditions play a significant role, with factors such as geographical distance between participants, internet connection speed, and network congestion all impacting the overall latency.</p><p>Additionally, the processing power of devices, the efficiency of encoding and decoding algorithms, and the performance of the WebRTC infrastructure can affect latency. By optimizing these elements, developers can work towards achieving the lowest possible latency for their WebRTC applications.</p><h2 id="low-latency-in-videosdk">Low Latency in VideoSDK</h2><p><a href="https://www.videosdk.live/">VideoSDK</a>, like other WebRTC-based solutions, aims to minimize latency as much as possible. However, the exact "lowest latency" can vary depending on several factors and real-world conditions. That said, here's what we can say about VideoSDK's latency performance:</p><ul><li><strong>Lowest possible latency</strong>: Can reach as low as 12 milliseconds in ideal scenarios with internal servers.</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/image-29.png" class="kg-image" alt="How to Implement Low Latency Video Calls with VideoSDK?" loading="lazy" width="492" height="459"/></figure><p>Our<strong> average latency</strong> can vary around less than 99 milliseconds end-to-end in optimal conditions.</p><h2 id="%E2%9A%99%EF%B8%8F-implementing-low-latency-video-calls-with-videosdk">⚙️ Implementing Low-Latency Video Calls with VideoSDK</h2><p>Now that we understand the factors affecting latency and VideoSDK's performance capabilities, let's walk through the process of setting up a low-latency video call using VideoSDK's &amp; <a href="https://www.writersofusa.com/script-writing" rel="noreferrer">video script writer</a> prebuilt solution. This approach allows you to quickly implement real-time communication while leveraging VideoSDK's optimized infrastructure for minimal latency.</p><h3 id="step-1-clone-the-repository">Step 1: Clone the Repository</h3><p>First, clone the VideoSDK examples repository and navigate to the JavaScript directory:</p><pre><code class="language-bash">git clone https://github.com/videosdk-live/videosdk-rtc-prebuilt-examples.git
cd videosdk-rtc-prebuilt-examples
cd javascript</code></pre><h3 id="step-2-generate-api-key">Step 2: Generate API Key</h3><p>To generate your API key, visit <a href="https://www.videosdk.live/">VideoSDK's Dashboard</a>. This key is essential for accessing VideoSDK's low-latency infrastructure and optimizing your real-time communication application.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/API-generation.gif" class="kg-image" alt="How to Implement Low Latency Video Calls with VideoSDK?" loading="lazy" width="600" height="338"/></figure><h3 id="step-3-configure-the-api-key">Step 3: Configure the API Key</h3><p>Open the <code>index.html</code> file and update it with your API key generated from the VideoSDK dashboard. Also, set the meeting ID and participant name:</p><pre><code class="language-js">// Set apikey, meetingId and participant name
const apiKey = "&lt;API KEY&gt;"; // generated from app.videosdk.live
const meetingId = "milkyway";
const name = "John Doe";</code></pre><p>Replace <code>&lt;API KEY&gt;</code> with your actual API key. This key is crucial for authenticating your application with VideoSDK's servers and ensuring secure, low-latency communication.</p><h3 id="step-4-setup-a-local-server">Step 4:  Setup a Local Server</h3><p>To run your application, you'll need a local HTTP server. If you don't have one installed, you can use <code>live-server</code>. Install it globally using npm:</p><pre><code class="language-terminal">npm install -g live-server
live-server</code></pre><p>This will launch your application in your default web browser, allowing you to test your low-latency video call implementation.</p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/realtime-stats.gif" class="kg-image" alt="How to Implement Low Latency Video Calls with VideoSDK?" loading="lazy" width="600" height="338"/></figure><h2 id="conclusion">Conclusion</h2><p>Implementing low-latency video calls is essential for delivering a seamless and real-time communication experience. VideoSDK offers a powerful and easy-to-use solution for developers looking to integrate high-quality video calls into their applications.</p><p>Remember that while this setup provides a great starting point, achieving the lowest possible latency in production environments may require further optimization based on your specific use case and the factors we discussed earlier. With VideoSDK, you can ensure that your video call application meets the highest standards of performance and reliability, providing your users with the best possible experience. </p><p>If you are new to VideoSDK, just <a href="https://app.videosdk.live/signup">Signup</a> and get 10,000? free minutes every month.</p>]]></content:encoded></item><item><title><![CDATA[What is Jitter Buffer?]]></title><description><![CDATA[Discover what a jitter buffer is and how it optimizes network communication. Learn its role in maintaining audio and video quality seamlessly.]]></description><link>https://www.videosdk.live/blog/what-is-jitter-buffer</link><guid isPermaLink="false">6676639120fab018df10ee53</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Sun, 12 Jan 2025 11:14:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/06/What-is-Jitter-Buffer_.png" medium="image"/><content:encoded><![CDATA[<!--kg-card-begin: markdown--><h2 id="introduction-to-jitter-and-jitter-buffers">Introduction to Jitter and Jitter Buffers</h2>
<!--kg-card-end: markdown--><img src="https://assets.videosdk.live/static-assets/ghost/2024/06/What-is-Jitter-Buffer_.png" alt="What is Jitter Buffer?"/><p>In the world of digital communications, particularly in systems like Voice over Internet Protocol (VoIP), data packets need to travel across networks to reach their destination. However, these packets sometimes face delays and may not arrive in the order they were sent. This disorder is known as “jitter,” which can significantly degrade the quality of voice and video communications. To manage this, a crucial component called a jitter buffer is deployed within the network infrastructure.</p><p>Jitter refers to the variability in packet delay at the receiving end of a conversation, which can result in garbled or scrambled communications. For VoIP systems, where clarity and timing are crucial, excessive jitter can make a conversation difficult to understand. Jitter buffers combat this issue by temporarily holding incoming packets to realign out-of-order packets into the correct order, thus smoothing out the voice transmission and ensuring a clearer conversation.</p><p>Understanding both jitter and the function of jitter buffers is essential for maintaining the integrity of VoIP communications. By effectively managing jitter, businesses and individuals can ensure high-quality audio and video transmissions, crucial for everything from business meetings to personal chats. As we dive deeper into the workings of jitter buffers, it’s important to recognize their role not just as a fix but as a proactive measure in network setup and maintenance.</p><!--kg-card-begin: markdown--><h2 id="understanding-jitter-and-jitter-buffers">Understanding Jitter and Jitter Buffers</h2>
<!--kg-card-end: markdown--><p>Jitter is a common challenge in network communications, affecting how data packets are transmitted over the internet. Particularly in Voice over Internet Protocol (VoIP) systems, jitter can cause packets to arrive at their destination at different intervals, which can severely impact the quality of the transmitted voice or video.</p><!--kg-card-begin: markdown--><h3 id="what-is-jitter">What is Jitter?</h3>
<!--kg-card-end: markdown--><p>Jitter in networking terms refers to the variation in time between packets arriving, caused by network congestion, timing drift, or route changes. This inconsistency can lead to choppy audio or video, echoes, and even dropped calls. The phenomenon becomes particularly problematic in real-time communications, where timing is crucial for the quality of the conversation.</p><!--kg-card-begin: markdown--><h3 id="role-of-jitter-buffers">Role of Jitter Buffers</h3>
<!--kg-card-end: markdown--><p>To mitigate the effects of jitter, jitter buffers are employed within the network infrastructure. A jitter buffer temporarily stores arriving packets to compensate for differences in packet arrival time before passing them to the user. This process allows the packets to be delivered in a more consistent flow, enhancing the overall quality of the voice or video call.</p><!--kg-card-begin: markdown--><h2 id="types-and-functions-of-jitter-buffers">Types and Functions of Jitter Buffers</h2>
<!--kg-card-end: markdown--><p>Jitter buffers are essential tools in network management, especially where VoIP and other real-time services are concerned. They come in two primary types: static and dynamic.</p><!--kg-card-begin: markdown--><h3 id="static-vs-dynamic-jitter-buffers">Static vs. Dynamic Jitter Buffers</h3>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h4 id="static-jitter-buffers">Static Jitter Buffers</h4>
<!--kg-card-end: markdown--><p>Static Jitter Buffers have a fixed size and delay capacity which are set during their configuration. They are simpler but less flexible, and they might not adapt well to changes in network conditions, which can vary widely throughout the day or even during a single call.</p><!--kg-card-begin: markdown--><h4 id="dynamic-jitter-buffers">Dynamic Jitter Buffers</h4>
<!--kg-card-end: markdown--><p>Dynamic Jitter Buffers on the other hand, adjust their buffer size based on the network conditions. This adaptability makes them more effective at handling jitter in environments where network performance is unpredictable. Dynamic buffers can improve the performance of VoIP applications by adjusting in real time to the current state of the network.</p><!--kg-card-begin: markdown--><h3 id="importance-of-jitter-buffer-in-voip">Importance of Jitter Buffer in VoIP</h3>
<!--kg-card-end: markdown--><p>In VoIP systems, the quality of voice transmission depends significantly on the consistency of packet delivery. Jitter buffers play a critical role in ensuring that voice packets are delivered smoothly and in sequence, thereby maintaining the clarity and understandability of the conversation. They are particularly vital in professional settings where high-quality communication is essential for effective collaboration and decision-making.</p><!--kg-card-begin: markdown--><h2 id="measuring-and-managing-jitter">Measuring and Managing Jitter</h2>
<!--kg-card-end: markdown--><p>Understanding and managing jitter involves measuring it accurately and implementing strategies to mitigate its effects. Effective jitter management can substantially improve the quality of VoIP communications and enhance user experience.</p><!--kg-card-begin: markdown--><h3 id="how-to-measure-jitter">How to Measure Jitter</h3>
<!--kg-card-end: markdown--><p>Jitter is typically measured by the average packet-to-packet delay time. Tools like ping tests and jitter calculators can help network administrators determine the current jitter levels on their networks. Understanding these metrics is crucial for setting up appropriate buffers and making informed decisions about network configurations.</p><!--kg-card-begin: markdown--><h3 id="strategies-to-reduce-jitter">Strategies to Reduce Jitter</h3>
<!--kg-card-end: markdown--><p>Several techniques can be employed to reduce jitter:</p><ol><li><strong>Quality of Service (QoS) Settings: </strong>By prioritizing VoIP and other real-time traffic over less time-sensitive data, QoS settings help maintain a stable and consistent packet flow.</li><li><strong>Network Infrastructure Optimization: </strong>Upgrading routers, switching to wired connections, and ensuring sufficient bandwidth are all critical steps in reducing jitter. Additionally, configuring network devices correctly to handle high-priority traffic effectively can prevent packets from being delayed or lost.</li></ol><p>By comprehending the types of jitter buffers and understanding how to measure and manage jitter, network administrators can significantly enhance the stability and clarity of VoIP calls. This section of the article provides a deeper insight into the technical solutions available to combat jitter, ensuring high-quality communication in various network environments.</p><!--kg-card-begin: markdown--><h3 id="common-issues-and-solutions-with-jitter-buffers">Common Issues and Solutions with Jitter Buffers</h3>
<!--kg-card-end: markdown--><p>While jitter buffers significantly enhance the quality of VoIP communications, they also introduce their own set of challenges. Understanding these issues and implementing effective solutions are crucial for maintaining optimal network performance.</p><!--kg-card-begin: markdown--><h3 id="challenges-with-jitter-buffers">Challenges with Jitter Buffers</h3>
<!--kg-card-end: markdown--><p>One of the main challenges with using jitter buffers is the additional latency they introduce into the communication stream. While they compensate for jitter by delaying the packet delivery slightly, this can sometimes lead to a perceptible delay in conversations. This delay, especially if improperly managed, can disrupt the natural flow of interactive communications such as video conferences or collaborative virtual workspaces.</p><p>Another issue arises from the balance between buffer size and delay. Larger buffers provide more room to smooth out packet delivery times but at the cost of increased delay. Conversely, smaller buffers reduce delay but might not compensate adequately for high levels of jitter, leading to degraded audio or video quality.</p><!--kg-card-begin: markdown--><h3 id="optimizing-jitter-buffer-settings">Optimizing Jitter Buffer Settings</h3>
<!--kg-card-end: markdown--><p>To address these issues, it's essential to optimize jitter buffer settings according to the specific needs and conditions of the network:</p><ol><li><strong>Dynamic Adaptation:</strong> Implementing adaptive jitter buffers that can adjust their size dynamically based on real-time network conditions can help balance the trade-off between delay and jitter compensation.</li><li><strong>Network Assessments:</strong> Regular network performance assessments can help identify the optimal buffer settings for current conditions. This includes monitoring network traffic patterns and adjusting buffer sizes to prevent both excessive delay and packet loss.</li></ol><!--kg-card-begin: markdown--><h2 id="conclusion-the-critical-role-of-jitter-buffers-in-voip">Conclusion: The Critical Role of Jitter Buffers in VoIP</h2>
<!--kg-card-end: markdown--><p>Jitter buffers are vital components in the architecture of modern VoIP systems, playing a critical role in ensuring high-quality, reliable communications. By compensating for jitter, these buffers help to maintain sound and video quality over IP networks, which is crucial for business communications, teleconferencing, and other real-time services.</p><p>The effective use of jitter buffers, however, requires a thorough understanding of both their benefits and their limitations. Network administrators must be adept at configuring these buffers correctly and adjusting them as network conditions change. With the right settings and strategies, jitter buffers can significantly improve the user experience by providing clear and uninterrupted communication.</p><p>As VoIP and other real-time communication technologies continue to evolve, the management of jitter and the optimization of jitter buffers will remain key areas of focus for ensuring seamless digital interactions. Understanding the mechanisms of jitter buffers and implementing them wisely is essential for any organization that relies on stable and clear digital communication platforms.</p><p>By addressing the common challenges associated with jitter buffers and optimizing their functionality, businesses can enhance their communication systems, leading to improved productivity and satisfaction among users.</p><!--kg-card-begin: markdown--><h2 id="frequently-asked-questionsfaqs-about-jitter-buffers">Frequently Asked Questions(FAQs) About Jitter Buffers</h2>
<!--kg-card-end: markdown--><!--kg-card-begin: markdown--><h3 id="1-what-is-a-jitter-buffer">1. What is a jitter buffer?</h3>
<!--kg-card-end: markdown--><p>A jitter buffer is a shared data area where voice packets can be collected, stored, and sent to the voice processor in evenly spaced intervals. By doing this, jitter buffers reduce the effects of jitter in VoIP communications, such as packet delay and out-of-order packet arrival, which are crucial for maintaining high-quality audio transmission.</p><!--kg-card-begin: markdown--><h3 id="2-how-does-a-jitter-buffer-improve-voip-call-quality">2. How does a jitter buffer improve VoIP call quality?</h3>
<!--kg-card-end: markdown--><p>Jitter buffers manage the timing of voice packet delivery, smoothing out the arrival time of these packets at the receiving end. This management helps to ensure that voice calls remain clear and free of distortions like echoing or choppiness, which are often caused by network irregularities.</p><!--kg-card-begin: markdown--><h3 id="3-are-there-different-types-of-jitter-buffers">3. Are there different types of jitter buffers?</h3>
<!--kg-card-end: markdown--><p>Yes, there are mainly two types of jitter buffers used in VoIP technologies: static and dynamic. Static jitter buffers have a fixed size that does not change during the call, while dynamic jitter buffers can adjust their size based on the changing conditions of the network traffic. The adaptability of dynamic buffers makes them more suitable for networks with highly variable delay patterns.</p><!--kg-card-begin: markdown--><h3 id="4-when-should-i-use-a-jitter-buffer">4. When should I use a jitter buffer?</h3>
<!--kg-card-end: markdown--><p>A jitter buffer should be used in any real-time audio or video communication setup, particularly in VoIP systems where timing and order of packet delivery are critical for quality. They are essential in environments where packet delivery is irregular and can significantly impact the communication experience.</p><!--kg-card-begin: markdown--><h3 id="5-can-jitter-buffers-eliminate-all-voip-issues">5. Can jitter buffers eliminate all VoIP issues?</h3>
<!--kg-card-end: markdown--><p>While jitter buffers effectively manage and mitigate many of the issues caused by jitter, they are not a cure-all solution. They do not address the root causes of jitter such as network congestion or inadequate bandwidth. To fully optimize VoIP performance, additional measures such as Quality of Service (QoS) adjustments and proper network configuration are necessary.</p><!--kg-card-begin: markdown--><h3 id="6-how-do-i-configure-a-jitter-buffer">6. How do I configure a jitter buffer?</h3>
<!--kg-card-end: markdown--><p>Configuring a jitter buffer typically involves setting its size and the delay it should introduce. This setup can be managed either automatically by dynamic jitter buffers or manually in the case of static buffers. The specific configuration steps can vary depending on the equipment and software in use, so consulting with a network professional or the documentation of the VoIP system is recommended.</p>]]></content:encoded></item><item><title><![CDATA[Post-call Transcription & Summary in JavaScript]]></title><description><![CDATA[Implement Post-call Transcription in JavaScript to convert audio calls into text seamlessly. Enhance accessibility, accuracy, and workflow efficiency effortlessly.]]></description><link>https://www.videosdk.live/blog/post-call-transcription-in-javascript</link><guid isPermaLink="false">6682a30020fab018df10f2a9</guid><category><![CDATA[JavaScript]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Sun, 12 Jan 2025 09:46:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/07/Post-time-transcription-and-summary-3.png" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/Post-time-transcription-and-summary-3.png" alt="Post-call Transcription & Summary in JavaScript"/><p>Post-call transcription and summary is a powerful feature provided by <a href="https://www.videosdk.live/">VideoSDK</a> that allows users to generate detailed transcriptions and summaries of recorded meetings after they have concluded. This feature is particularly beneficial for capturing and documenting important information discussed during meetings, ensuring that nothing is missed and that there is a comprehensive record of the conversation.</p><h3 id="how-post-call-transcription-works">How Post-Call Transcription Works?</h3><p><strong>Post-call transcription</strong> involves processing the recorded audio or video content of a meeting to produce a textual representation of the conversation. Here’s a step-by-step breakdown of how it works:</p><ol><li><strong>Recording the Meeting:</strong> During the meeting, the audio and video are recorded. This can include everything that was said and any shared content, such as presentations or screen shares.</li><li><strong>Uploading the Recording:</strong> Once the meeting is over, the recorded file is uploaded to the VideoSDK platform. This can be done automatically or manually, depending on the configuration.</li><li><strong>Transcription Processing:</strong> The uploaded recording is then processed by VideoSDK’s transcription engine. This engine uses advanced speech recognition technology to convert spoken words into written text.</li><li><strong>Retrieving the Transcription:</strong> After the transcription process is complete, the textual representation of the meeting is made available. This text can be accessed via the VideoSDK API and used in various applications.</li></ol><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/06/react-quick-start-fafbfbc2ed2d7cbfd4c5ee2e36296f9e-1.png" class="kg-image" alt="Post-call Transcription & Summary in JavaScript" loading="lazy" width="2906" height="1446"/></figure><h3 id="benefits-of-post-call-transcription">Benefits of Post-Call Transcription</h3><ul><li><strong>Accurate Documentation:</strong> Provides a precise record of what was discussed, which is invaluable for meeting minutes, legal documentation, and reference.</li><li><strong>Enhanced Accessibility:</strong> Makes content accessible to those who may have missed the meeting or have hearing impairments.</li><li><strong>Easy Review and Analysis:</strong> Enables quick review of key points and decisions made during the meeting without having to re-watch the entire recording.</li></ul><h2 id="lets-get-started">Let's Get started </h2><p>VideoSDK empowers you to seamlessly integrate the video calling feature into your React application within minutes.</p><p>In this quickstart, you'll explore the group calling feature of VideoSDK. Follow the step-by-step guide to integrate it within your application.</p><h3 id="prerequisites%E2%80%8B">Prerequisites<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#prerequisites">​</a></h3><p>Before proceeding, ensure that your development environment meets the following requirements:</p><ul><li>VideoSDK Developer Account (Not having one, follow <strong><a href="https://app.videosdk.live/" rel="noopener noreferrer">VideoSDK Dashboard</a></strong>)</li><li>Basic understanding of JavaScript.</li><li><strong><a href="https://www.npmjs.com/package/@videosdk.live/js-sdk">JavaScript VideoSDK</a></strong></li><li>Have Node and NPM installed on your device.</li><li>Generate a token from the VideoSDK <a href="https://app.videosdk.live/api-keys">dashboard </a></li></ul><h2 id="getting-started-with-the-code%E2%80%8B">Getting Started with the Code!<a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start#getting-started-with-the-code">​</a></h2><p>Follow the steps to create the environment necessary to add video calls to your app. You can also find the code sample for <a href="https://github.com/videosdk-live/quickstart/tree/main/js-rtc" rel="noopener noreferrer">quickstart here</a>.</p><p>First, create one empty project using <code>mkdir folder_name</code> on your preferred location.</p><h3 id="install-video-sdk%E2%80%8B">Install Video SDK<a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start#install-video-sdk">​</a></h3><p>Import VideoSDK using the <code>&lt;script&gt;</code> tag or Install it using the following npm command. Make sure you are in your app directory before you run this command.</p><pre><code class="language-html">&lt;html&gt;
  &lt;head&gt;
    &lt;!--.....--&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;!--.....--&gt;
    &lt;script src="https://sdk.videosdk.live/js-sdk/0.0.89/videosdk.js"&gt;&lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre><h2 id="structure-of-the-project%E2%80%8B">Structure of the project<a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start#structure-of-the-project">​</a></h2><p>Your project structure should look like this.</p><pre><code class="language-Structure">  root
   ├── index.html
   ├── config.js
   ├── index.js</code></pre><p>You will be working on the following files:</p><ul><li>index.html: Responsible for creating a basic UI.</li><li>config.js: Responsible for storing the token.</li><li>index.js: Responsible for rendering the meeting view and the join meeting functionality.</li></ul><h3 id="step-1-design-the-user-interface-ui%E2%80%8B">Step 1: Design the user interface (UI)<a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start#step-1--design-the-user-interface-ui">​</a></h3><p>Create an HTML file containing the screens, <code>join-screen</code> and <code>grid-screen</code>.</p><figure class="kg-card kg-code-card"><pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html&gt;

&lt;head&gt; &lt;/head&gt;

&lt;body&gt;
    &lt;div id="join-screen"&gt;
        &lt;!-- Create new Meeting Button --&gt;
        &lt;button id="createMeetingBtn"&gt;New Meeting&lt;/button&gt;
        OR
        &lt;!-- Join existing Meeting --&gt;
        &lt;input type="text" id="meetingIdTxt" placeholder="Enter Meeting id" /&gt;
        &lt;button id="joinBtn"&gt;Join Meeting&lt;/button&gt;
        &lt;select id="microphone-list"&gt;
        &lt;/select&gt;
        &lt;select id="speaker-list"&gt;&lt;/select&gt;
        &lt;select id="camera-list"&gt;&lt;/select&gt;
    &lt;/div&gt;

    &lt;!-- for Managing meeting status --&gt;
    &lt;div id="textDiv"&gt;&lt;/div&gt;

    &lt;div id="grid-screen" style="display: none"&gt;
        &lt;!-- To Display MeetingId --&gt;
        &lt;h3 id="meetingIdHeading"&gt;&lt;/h3&gt;
        &lt;!-- &lt;br&gt; --&gt;

        &lt;p id="micStatus" style="margin: 5px;"&gt;MIC | ON&lt;/p&gt;
        &lt;p id="cameraStatus" style="margin: 5px;"&gt;CAMERA | ON&lt;/p&gt;
        &lt;p id="recordingStatus" style="margin: 5px;"&gt;RECORDING | STOPPED&lt;/p&gt;

        &lt;!-- Controllers --&gt;
        &lt;button id="leaveBtn"&gt;Leave&lt;/button&gt;
        &lt;button id="toggleMicBtn"&gt;Toggle Mic&lt;/button&gt;
        &lt;button id="toggleWebCamBtn"&gt;Toggle WebCam&lt;/button&gt;
        &lt;button id="startRecording"&gt;Start Recording&lt;/button&gt;
        &lt;button id="stopRecording"&gt;Stop Recording&lt;/button&gt;

        &lt;!-- render Video --&gt;
        &lt;div class="row" id="videoContainer"&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;script src="https://sdk.videosdk.live/js-sdk/0.0.88/videosdk.js"&gt;&lt;/script&gt;
    &lt;script src="config.js"&gt;&lt;/script&gt;
    &lt;script src="index.js"&gt;&lt;/script&gt;
&lt;/body&gt;

&lt;/html&gt;</code></pre><figcaption>index.html</figcaption></figure><h4 id="output">Output</h4><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/image.png" class="kg-image" alt="Post-call Transcription & Summary in JavaScript" loading="lazy" width="1782" height="694"/></figure><h3 id="step-2-implement-join-screen%E2%80%8B">Step 2: Implement Join Screen<a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start#step-2--implement-join-screen">​</a></h3><p>Configure the token in the <code>config.js</code> file, which you can obtain from the <a href="https://app.videosdk.live/login" rel="noopener noreferrer">VideoSDK Dashbord</a>.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">// Auth token will be used to generate a meeting and connect to it
TOKEN = "Your_Token_Here";</code></pre><figcaption>config.js</figcaption></figure><p>Next, retrieve all the elements from the DOM and declare the following variables in the <code>index.js</code> file. Then, add an event listener to the join and create meeting buttons.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">// Getting Elements from DOM
const joinButton = document.getElementById("joinBtn");
const leaveButton = document.getElementById("leaveBtn");
const toggleMicButton = document.getElementById("toggleMicBtn");
const toggleWebCamButton = document.getElementById("toggleWebCamBtn");
const createButton = document.getElementById("createMeetingBtn");
const videoContainer = document.getElementById("videoContainer");
const textDiv = document.getElementById("textDiv");

// Declare Variables
let meeting = null;
let meetingId = "";
let isMicOn = false;
let isWebCamOn = false;

function initializeMeeting() {}

function createLocalParticipant() {}

function createVideoElement() {}

function createAudioElement() {}

function setTrack() {}

// Join Meeting Button Event Listener
joinButton.addEventListener("click", async () =&gt; {
  document.getElementById("join-screen").style.display = "none";
  textDiv.textContent = "Joining the meeting...";

  roomId = document.getElementById("meetingIdTxt").value;
  meetingId = roomId;

  initializeMeeting();
});

// Create Meeting Button Event Listener
createButton.addEventListener("click", async () =&gt; {
  document.getElementById("join-screen").style.display = "none";
  textDiv.textContent = "Please wait, we are joining the meeting";

  // API call to create meeting
  const url = `https://api.videosdk.live/v2/rooms`;
  const options = {
    method: "POST",
    headers: { Authorization: TOKEN, "Content-Type": "application/json" },
  };

  const { roomId } = await fetch(url, options)
    .then((response) =&gt; response.json())
    .catch((error) =&gt; alert("error", error));
  meetingId = roomId;

  initializeMeeting();
});</code></pre><figcaption>index.js</figcaption></figure><h3 id="step-3-initialize-the-meeting%E2%80%8B">Step 3: Initialize the meeting<a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start#step-3--initialize-meeting">​</a></h3><p>Following that, initialize the meeting using the <code>initMeeting()</code> function and proceed to join the meeting.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">// Initialize meeting
function initializeMeeting() {
  window.VideoSDK.config(TOKEN);

  meeting = window.VideoSDK.initMeeting({
    meetingId: meetingId, // required
    name: "Thomas Edison", // required
    micEnabled: true, // optional, default: true
    webcamEnabled: true, // optional, default: true
  });

  meeting.join();

  // Creating local participant
  createLocalParticipant();

  // Setting local participant stream
  meeting.localParticipant.on("stream-enabled", (stream) =&gt; {
    setTrack(stream, null, meeting.localParticipant, true);
  });

  // meeting joined event
  meeting.on("meeting-joined", () =&gt; {
    textDiv.style.display = "none";
    document.getElementById("grid-screen").style.display = "block";
    document.getElementById(
      "meetingIdHeading"
    ).textContent = `Meeting Id: ${meetingId}`;
  });

  // meeting left event
  meeting.on("meeting-left", () =&gt; {
    videoContainer.innerHTML = "";
  });

  // Remote participants Event
  // participant joined
  meeting.on("participant-joined", (participant) =&gt; {
    //  ...
  });

  // participant left
  meeting.on("participant-left", (participant) =&gt; {
    //  ...
  });
}</code></pre><figcaption>index.js</figcaption></figure><h4 id="output-1">Output</h4><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/image-3.png" class="kg-image" alt="Post-call Transcription & Summary in JavaScript" loading="lazy" width="890" height="330"/></figure><h3 id="step-4-create-the-media-elements%E2%80%8B">Step 4: Create the Media Elements<a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start#step-4--create-the-media-elements">​</a></h3><p>In this step, Create a function to generate audio and video elements for displaying both local and remote participants. Set the corresponding media track based on whether it's a video or audio stream.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">// creating video element
function createVideoElement(pId, name) {
  let videoFrame = document.createElement("div");
  videoFrame.setAttribute("id", `f-${pId}`);

  //create video
  let videoElement = document.createElement("video");
  videoElement.classList.add("video-frame");
  videoElement.setAttribute("id", `v-${pId}`);
  videoElement.setAttribute("playsinline", true);
  videoElement.setAttribute("width", "300");
  videoFrame.appendChild(videoElement);

  let displayName = document.createElement("div");
  displayName.innerHTML = `Name : ${name}`;

  videoFrame.appendChild(displayName);
  return videoFrame;
}

// creating audio element
function createAudioElement(pId) {
  let audioElement = document.createElement("audio");
  audioElement.setAttribute("autoPlay", "false");
  audioElement.setAttribute("playsInline", "true");
  audioElement.setAttribute("controls", "false");
  audioElement.setAttribute("id", `a-${pId}`);
  audioElement.style.display = "none";
  return audioElement;
}

// creating local participant
function createLocalParticipant() {
  let localParticipant = createVideoElement(
    meeting.localParticipant.id,
    meeting.localParticipant.displayName
  );
  videoContainer.appendChild(localParticipant);
}

// setting media track
function setTrack(stream, audioElement, participant, isLocal) {
  if (stream.kind == "video") {
    isWebCamOn = true;
    const mediaStream = new MediaStream();
    mediaStream.addTrack(stream.track);
    let videoElm = document.getElementById(`v-${participant.id}`);
    videoElm.srcObject = mediaStream;
    videoElm
      .play()
      .catch((error) =&gt;
        console.error("videoElem.current.play() failed", error)
      );
  }
  if (stream.kind == "audio") {
    if (isLocal) {
      isMicOn = true;
    } else {
      const mediaStream = new MediaStream();
      mediaStream.addTrack(stream.track);
      audioElement.srcObject = mediaStream;
      audioElement
        .play()
        .catch((error) =&gt; console.error("audioElem.play() failed", error));
    }
  }
}</code></pre><figcaption>index.js</figcaption></figure><h3 id="step-5-handle-participant-events%E2%80%8B">Step 5: Handle participant events<a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start#step-5--handle-participant-events">​</a></h3><p>Thereafter, implement the events related to the participants and the stream.</p><p>The following are the events to be executed in this step:</p><ol><li><code>participant-joined</code>: When a remote participant joins, this event will trigger. In the event callback, create video and audio elements previously defined for rendering their video and audio streams.</li><li><code>participant-left</code>: When a remote participant leaves, this event will trigger. In the event callback, remove the corresponding video and audio elements.</li><li><code>stream-enabled</code>: This event manages the media track of a specific participant by associating it with the appropriate video or audio element.</li></ol><figure class="kg-card kg-code-card"><pre><code class="language-js">// Initialize meeting
function initializeMeeting() {
  // ...

  // participant joined
  meeting.on("participant-joined", (participant) =&gt; {
    let videoElement = createVideoElement(
      participant.id,
      participant.displayName
    );
    let audioElement = createAudioElement(participant.id);
    // stream-enabled
    participant.on("stream-enabled", (stream) =&gt; {
      setTrack(stream, audioElement, participant, false);
    });
    videoContainer.appendChild(videoElement);
    videoContainer.appendChild(audioElement);
  });

  // participants left
  meeting.on("participant-left", (participant) =&gt; {
    let vElement = document.getElementById(`f-${participant.id}`);
    vElement.remove(vElement);

    let aElement = document.getElementById(`a-${participant.id}`);
    aElement.remove(aElement);
  });
}</code></pre><figcaption>index.js</figcaption></figure><h4 id="output-2">Output</h4><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/image-4.png" class="kg-image" alt="Post-call Transcription & Summary in JavaScript" loading="lazy" width="1105" height="767"/></figure><h3 id="step-6-implement-controls%E2%80%8B">Step 6: Implement Controls<a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start#step-6--implement-controls">​</a></h3><p>Next, implement the meeting controls such as toggleMic, toggleWebcam and leave the meeting.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">// leave Meeting Button Event Listener
leaveButton.addEventListener("click", async () =&gt; {
  meeting?.leave();
  document.getElementById("grid-screen").style.display = "none";
  document.getElementById("join-screen").style.display = "block";
});

// Toggle Mic Button Event Listener
toggleMicButton.addEventListener("click", async () =&gt; {
  if (isMicOn) {
    // Disable Mic in Meeting
    meeting?.muteMic();
  } else {
    // Enable Mic in Meeting
    meeting?.unmuteMic();
  }
  isMicOn = !isMicOn;
});

// Toggle Web Cam Button Event Listener
toggleWebCamButton.addEventListener("click", async () =&gt; {
  if (isWebCamOn) {
    // Disable Webcam in Meeting
    meeting?.disableWebcam();

    let vElement = document.getElementById(`f-${meeting.localParticipant.id}`);
    vElement.style.display = "none";
  } else {
    // Enable Webcam in Meeting
    meeting?.enableWebcam();

    let vElement = document.getElementById(`f-${meeting.localParticipant.id}`);
    vElement.style.display = "inline";
  }
  isWebCamOn = !isWebCamOn;
});</code></pre><figcaption>index.js</figcaption></figure><h3 id="step-7-configuring-transcription">Step 7: Configuring Transcription</h3><ul><li>In this step, we set up the configuration for post-transcription and summary generation. We define the webhook URL where the webhooks will be received.</li><li>In the <code>startRecording</code> function, we have passed the transcription object and the webhook URL, which will initiate the post-call transcription process.</li><li>Finally, when we call the <code>stopRecording</code> function, both the post-call transcription and the recording will be stopped.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">const webhookurl = "example.site";

const transcription = {
  enabled: true, // Enables post transcription
  summary: {
    enabled: true, // Enables summary generation

    // Guides summary generation
    prompt:
      "Write summary in sections like Title, Agenda, Speakers, Action Items, Outlines, Notes and Summary",
  },
};

// Start Recording with Post Transcription
startRecordingButton.addEventListener("click", () =&gt; {
  recordingStatus.textContent = "RECORDING | STARTING..."
  meeting.startRecording(webhookurl, null,  null, transcription);
})

// Stop Recording with Post Transcription
stopRecordingButton.addEventListener("click", () =&gt; {
  recordingStatus.textContent = "RECORDING | STOPPING..."
  meeting.stopRecording();
})</code></pre><figcaption>index.js</figcaption></figure><h2 id="run-your-code%E2%80%8B">Run your code<a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start#run-your-code">​</a></h2><p>Once you have completed all the steps mentioned above, run your application using the code block below.</p><pre><code class="language-bash">live-server --port=8000</code></pre><h2 id="final-output">Final Output</h2><p>You have completed the implementation of a customized video calling app in Javascript using VideoSDK. To explore more features, go through Basic and Advanced features.<a href="https://docs.videosdk.live/javascript/guide/video-and-audio-calling-api-sdk/quick-start#final-output">​</a></p><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/Untitled-video---Made-with-Clipchamp--2-.gif" class="kg-image" alt="Post-call Transcription & Summary in JavaScript" loading="lazy" width="1920" height="1080"/></figure><h2 id="fetching-the-transcription-from-the-dashboard">Fetching the Transcription from the Dashboard</h2><p>Once the transcription is ready, you can fetch it from the VideoSDK dashboard. The dashboard provides a user-friendly interface where you can view, download, and manage your Transcriptions &amp; Summary.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/20240702_171456-ezgif.com-resize.gif" class="kg-image" alt="Post-call Transcription & Summary in JavaScript" loading="lazy" width="1920" height="1080"><figcaption>To Access Transcription &amp; Summary Files</figcaption></img></figure><h2 id="conclusion">Conclusion</h2><p>Integrating post-call transcription and summary features into your React application using VideoSDK provides significant advantages for capturing and documenting meeting content. This guide has meticulously detailed the steps required to set up and implement these features, ensuring that every conversation during a meeting is accurately transcribed and easily accessible for future reference.</p>]]></content:encoded></item><item><title><![CDATA[How to Integrate Screen Share in iOS Video Call App?]]></title><description><![CDATA[Integrate screen sharing in your iOS video call app with VideoSDK. Elevate user experience with seamless screen sharing features.]]></description><link>https://www.videosdk.live/blog/integrate-screen-share-in-ios-video-call-app</link><guid isPermaLink="false">662781442a88c204ca9d4bfd</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[iOS]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Sat, 11 Jan 2025 12:50:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/Screen-SHare-in-iOS-video-Call-App.png" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/Screen-SHare-in-iOS-video-Call-App.png" alt="How to Integrate Screen Share in iOS Video Call App?"/><p>Integrating screen share in an <a href="https://www.videosdk.live/blog/ios-video-calling-sdk">iOS video call app</a> enhances user experience and collaboration. With this feature, users can seamlessly share their screen during calls, facilitating presentations, demonstrations, and remote assistance. Implementing screen sharing requires integrating APIs for capturing device screens, ensuring smooth transmission of visuals, and maintaining privacy controls.</p><p><strong>Benefits of Screen Share in iOS Video Call App:</strong></p><ol><li>Enhanced Collaboration: Screen share enables users to collaborate more effectively by sharing documents, presentations, or designs during video calls, fostering better understanding and teamwork.</li><li>Improved Communication: Visual aids facilitate clearer communication, especially for technical support, education, or remote work scenarios, leading to faster issue resolution and knowledge transfer.</li><li>Increased Productivity: With real-time sharing, teams can discuss projects or review documents without the need for additional tools or meetings, saving time and boosting productivity.</li></ol><p><strong>Use Cases of Screen Share in iOS Video Call App:</strong></p><ol><li>Business Meetings: Sales teams can share presentations or product demos with clients, enhancing engagement and closing deals more effectively.</li><li>Remote Work: Colleagues can collaborate on projects by sharing screens to discuss documents, designs, or code, replicating in-person collaboration remotely.</li><li>Technical Support: Customer support agents can visually guide users through troubleshooting steps by sharing screens, and resolving issues efficiently.</li></ol><p>This tutorial guides you through integrating this valuable feature into your JavaScript video call application using VideoSDK. We'll cover the steps required to leverage VideoSDK's capabilities and implement visual cues that highlight the active speaker within your app's interface.</p><h2 id="getting-started-with-videosdk">Getting Started with VideoSDK</h2><p>VideoSDK enables the opportunity to integrate video &amp; audio calling into Web, Android, and iOS applications with so many different frameworks. It is the best infrastructure solution that provides programmable SDKs and REST APIs to build scalable video conferencing applications. This guide will get you running with the VideoSDK video &amp; audio calling in minutes.</p><h3 id="create-a-videosdk-account">Create a VideoSDK Account</h3><p>Go to your <a href="https://app.videosdk.live/login">VideoSDK dashboard</a> and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.</p><h3 id="generate-your-auth-token">Generate your Auth Token</h3><p>Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token is crucial in authorizing your application to use VideoSDK features. For a more visual understanding of the account creation and token generation process, consider referring to the <a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/server-setup">provided tutorial</a>.</p><h3 id="prerequisites-and-setup">Prerequisites and Setup</h3><ul><li>iOS 11.0+</li><li>Xcode 12.0+</li><li>Swift 5.0+</li></ul><p>This App will contain two screens:</p><p><strong>Join Screen</strong>: This screen allows the user to either create a meeting or join the predefined meeting.</p><p><strong>Meeting Screen</strong>: This screen basically contains local and remote participant views and some meeting controls such as Enable/Disable the mic &amp; Camera and Leave meeting.</p><h2 id="integrate-videosdk%E2%80%8B">Integrate VideoSDK​</h2><p>To install VideoSDK, you must initialize the pod on the project by running the following command:</p><pre><code class="language-swift">pod init</code></pre><p>It will create the podfile in your project folder, Open that file and add the dependency for the VideoSDK, like below:</p><pre><code class="language-swift">pod 'VideoSDKRTC', :git =&gt; 'https://github.com/videosdk-live/videosdk-rtc-ios-sdk.git'</code></pre><figure class="kg-card kg-image-card"><img src="https://cdn.videosdk.live/website-resources/docs-resources/ios_quickstart_podfile.png" class="kg-image" alt="How to Integrate Screen Share in iOS Video Call App?" loading="lazy"/></figure><p>then run the below code to install the pod:</p><pre><code class="language-swift">pod install</code></pre><p>then declare the permissions in Info.plist :</p><pre><code class="language-swift">&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
&lt;string&gt;Camera permission description&lt;/string&gt;
&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;Microphone permission description&lt;/string&gt;</code></pre><h3 id="project-structure">Project Structure</h3><pre><code class="language-swift">iOSQuickStartDemo
   ├── Models
        ├── RoomStruct.swift
        └── MeetingData.swift
   ├── ViewControllers
        ├── StartMeetingViewController.swift
        └── MeetingViewController.swift
   ├── AppDelegate.swift // Default
   ├── SceneDelegate.swift // Default
   └── APIService
           └── APIService.swift
   ├── Main.storyboard // Default
   ├── LaunchScreen.storyboard // Default
   └── Info.plist // Default
 BroadcastExtension
   ├── SampleHandler.swift // Default
   ├── Atomic.swift
   └── SocketConnection.swift
   ├── DarwinNotification.swift
   ├── SampleUploader.swift
   └── Info.plist // Default
 Pods
     └── Podfile</code></pre><h3 id="create-models%E2%80%8B">Create models<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#create-models">​</a></h3><p>Create swift file for <code>MeetingData</code> and <code>RoomStruct</code> class model for setting data in object pattern.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">import Foundation
struct MeetingData {
    let token: String
    let name: String
    let meetingId: String
    let micEnabled: Bool
    let cameraEnabled: Bool
}</code></pre><figcaption>MeetingData.swift</figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-swift">import Foundation
struct RoomsStruct: Codable {
    let createdAt, updatedAt, roomID: String?
    let links: Links?
    let id: String?
    enum CodingKeys: String, CodingKey {
        case createdAt, updatedAt
        case roomID = "roomId"
        case links, id
    }
}

// MARK: - Links
struct Links: Codable {
    let getRoom, getSession: String?
    enum CodingKeys: String, CodingKey {
        case getRoom = "get_room"
        case getSession = "get_session"
    }
}</code></pre><figcaption>RoomStruct.swift</figcaption></figure><h2 id="essential-steps-for-building-the-video-calling">Essential Steps for Building the Video Calling</h2><p>This guide is designed to walk you through the process of integrating Screen Share with <a href="https://www.videosdk.live/">VideoSDK</a>. We'll cover everything from setting up the SDK to incorporating the visual cues into your app's interface, ensuring a smooth and efficient implementation process.</p><h3 id="step-1-get-started-with-apiclient%E2%80%8B">Step 1 : Get started with APIClient​</h3><p>Before jumping to anything else, we have to write an API to generate unique <code>meetingId</code>. You will require an <strong>authentication token;</strong> you can generate it either using <a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples" rel="noopener noreferrer">videosdk-server-api-example</a> or from the <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer">Video SDK Dashboard</a> for developers.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">import Foundation

let TOKEN_STRING: String = "&lt;AUTH_TOKEN&gt;"

class APIService {

  class func createMeeting(token: String, completion: @escaping (Result&lt;String, Error&gt;) -&gt; Void) {

    let url = URL(string: "https://api.videosdk.live/v2/rooms")!

    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.addValue(TOKEN_STRING, forHTTPHeaderField: "authorization")

    URLSession.shared.dataTask(
      with: request,
      completionHandler: { (data: Data?, response: URLResponse?, error: Error?) in

        DispatchQueue.main.async {

          if let data = data, let utf8Text = String(data: data, encoding: .utf8) {
            do {
              let dataArray = try JSONDecoder().decode(RoomsStruct.self, from: data)

              completion(.success(dataArray.roomID ?? ""))
            } catch {
              print("Error while creating a meeting: \(error)")
              completion(.failure(error))
            }
          }
        }
      }
    ).resume()
  }
}
</code></pre><figcaption>APIService.swift</figcaption></figure><h3 id="step-2-implement-join-screen%E2%80%8B">Step 2: Implement Join Screen<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#step-2--implement-join-screen">​</a></h3><p>The Join Screen will work as a medium to either schedule a new meeting or join an existing meeting.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">import Foundation
import UIKit

class StartMeetingViewController: UIViewController, UITextFieldDelegate {

  private var serverToken = ""

  /// MARK: outlet for create meeting button
  @IBOutlet weak var btnCreateMeeting: UIButton!

  /// MARK: outlet for join meeting button
  @IBOutlet weak var btnJoinMeeting: UIButton!

  /// MARK: outlet for meetingId textfield
  @IBOutlet weak var txtMeetingId: UITextField!

  /// MARK: Initialize the private variable with TOKEN_STRING &amp;
  /// setting the meeting id in the textfield
  override func viewDidLoad() {
    txtMeetingId.delegate = self
    serverToken = TOKEN_STRING
    txtMeetingId.text = "PROVIDE-STATIC-MEETING-ID"
  }

  /// MARK: method for joining meeting through seague named as "StartMeeting"
  /// after validating the serverToken in not empty
  func joinMeeting() {

    txtMeetingId.resignFirstResponder()

    if !serverToken.isEmpty {
      DispatchQueue.main.async {
        self.dismiss(animated: true) {
          self.performSegue(withIdentifier: "StartMeeting", sender: nil)
        }
      }
    } else {
      print("Please provide auth token to start the meeting.")
    }
  }

  /// MARK: outlet for create meeting button tap event
  @IBAction func btnCreateMeetingTapped(_ sender: Any) {
    print("show loader while meeting gets connected with server")
    joinRoom()
  }

  /// MARK: outlet for join meeting button tap event
  @IBAction func btnJoinMeetingTapped(_ sender: Any) {
    if (txtMeetingId.text ?? "").isEmpty {

      print("Please provide meeting id to start the meeting.")
      txtMeetingId.resignFirstResponder()
    } else {
      joinMeeting()
    }
  }

  // MARK: - method for creating room api call and getting meetingId for joining meeting

  func joinRoom() {

    APIService.createMeeting(token: self.serverToken) { result in
      if case .success(let meetingId) = result {
        DispatchQueue.main.async {
          self.txtMeetingId.text = meetingId
          self.joinMeeting()
        }
      }
    }
  }

  /// MARK: preparing to animate to meetingViewController screen
  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    guard let navigation = segue.destination as? UINavigationController,

      let meetingViewController = navigation.topViewController as? MeetingViewController
    else {
      return
    }

    meetingViewController.meetingData = MeetingData(
      token: serverToken,
      name: txtMeetingId.text ?? "Guest",
      meetingId: txtMeetingId.text ?? "",
      micEnabled: true,
      cameraEnabled: true
    )
  }
}
</code></pre><figcaption>StartMeetingViewController.swift</figcaption></figure><h3 id="step-3-initialize-and-join-meeting%E2%80%8B">Step 3: Initialize and Join Meeting<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#step-3--initialize-and-join-meeting">​</a></h3><p>Using the provided <code>token</code> and <code>meetingId</code>, we will configure and initialise the meeting in <code>viewDidLoad()</code>.</p><p>Then, we'll add <strong>@IBOutlet</strong> for <code>localParticipantVideoView</code> and <code>remoteParticipantVideoView</code>, which can render local and remote participant media, respectively.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">class MeetingViewController: UIViewController {

import UIKit
import VideoSDKRTC
import WebRTC
import AVFoundation

class MeetingViewController: UIViewController {

// MARK: - Properties
// outlet for local participant container view
   @IBOutlet weak var localParticipantViewContainer: UIView!

// outlet for label for meeting Id
   @IBOutlet weak var lblMeetingId: UILabel!

// outlet for local participant video view
   @IBOutlet weak var localParticipantVideoView: RTCMTLVideoView!

// outlet for remote participant video view
   @IBOutlet weak var remoteParticipantVideoView: RTCMTLVideoView!

// outlet for remote participant no media label
   @IBOutlet weak var lblRemoteParticipantNoMedia: UILabel!

// outlet for remote participant container view
   @IBOutlet weak var remoteParticipantViewContainer: UIView!

// outlet for local participant no media label
   @IBOutlet weak var lblLocalParticipantNoMedia: UILabel!

// Meeting data - required to start
   var meetingData: MeetingData!

// current meeting reference
   private var meeting: Meeting?

    // MARK: - video participants including self to show in UI
    private var participants: [Participant] = []

        // MARK: - Lifecycle Events

        override func viewDidLoad() {
        super.viewDidLoad()
        // configure the VideoSDK with token
        VideoSDK.config(token: meetingData.token)

        // init meeting
        initializeMeeting()

        // set meeting id in button text
        lblMeetingId.text = "Meeting Id: \(meetingData.meetingId)"
      }

      override func viewWillAppear(_ animated: Bool) {
          super.viewWillAppear(animated)
          navigationController?.navigationBar.isHidden = true
      }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.navigationBar.isHidden = false
        NotificationCenter.default.removeObserver(self)
    }

        // MARK: - Meeting

        private func initializeMeeting() {

            // Initialize the VideoSDK
            meeting = VideoSDK.initMeeting(
                meetingId: meetingData.meetingId,
                participantName: meetingData.name,
                micEnabled: meetingData.micEnabled,
                webcamEnabled: meetingData.cameraEnabled
            )

            // Adding the listener to meeting
            meeting?.addEventListener(self)

            // joining the meeting
            meeting?.join()
        }
}</code></pre><figcaption>MeetingViewController.swift</figcaption></figure><h3 id="step-4-implement-controls%E2%80%8B">Step 4: Implement Controls<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#step-4--implement-controls">​</a></h3><p>After initializing the meeting in the previous step, we will now add <strong>@IBOutlet</strong> for <code>btnLeave</code>, <code>btnToggleVideo</code> and <code>btnToggleMic</code> which can control the media in the meeting.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">class MeetingViewController: UIViewController {

...

    // outlet for leave button
    @IBOutlet weak var btnLeave: UIButton!

    // outlet for toggle video button
    @IBOutlet weak var btnToggleVideo: UIButton!

    // outlet for toggle audio button
    @IBOutlet weak var btnToggleMic: UIButton!

    // bool for mic
    var micEnabled = true
    // bool for video
    var videoEnabled = true


    // outlet for leave button click event
    @IBAction func btnLeaveTapped(_ sender: Any) {
            DispatchQueue.main.async {
                self.meeting?.leave()
                self.dismiss(animated: true)
            }
        }

    // outlet for toggle mic button click event
    @IBAction func btnToggleMicTapped(_ sender: Any) {
        if micEnabled {
            micEnabled = !micEnabled // false
            self.meeting?.muteMic()
        } else {
            micEnabled = !micEnabled // true
            self.meeting?.unmuteMic()
        }
    }

    // outlet for toggle video button click event
    @IBAction func btnToggleVideoTapped(_ sender: Any) {
        if videoEnabled {
            videoEnabled = !videoEnabled // false
            self.meeting?.disableWebcam()
        } else {
            videoEnabled = !videoEnabled // true
            self.meeting?.enableWebcam()
        }
    }

...

}</code></pre><figcaption>MeetingViewController.swift</figcaption></figure><h3 id="step-5-implementing-meetingeventlistener%E2%80%8B">Step 5: Implementing <code>MeetingEventListener​</code></h3><p>In this step, we'll create an extension for the <code>MeetingViewController</code> that implements the MeetingEventListener, which implements the <code>onMeetingJoined</code>, <code>onMeetingLeft</code>, <code>onParticipantJoined</code>, <code>onParticipantLeft</code>, <code>onParticipantChanged</code>, <code>onSpeakerChanged</code>, etc. methods.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">
class MeetingViewController: UIViewController {

...

extension MeetingViewController: MeetingEventListener {

        /// Meeting started
        func onMeetingJoined() {

            // handle local participant on start
            guard let localParticipant = self.meeting?.localParticipant else { return }
            // add to list
            participants.append(localParticipant)

            // add event listener
            localParticipant.addEventListener(self)

            localParticipant.setQuality(.high)

            if(localParticipant.isLocal){
                self.localParticipantViewContainer.isHidden = false
            } else {
                self.remoteParticipantViewContainer.isHidden = false
            }
        }

        /// Meeting ended
        func onMeetingLeft() {
            // remove listeners
            meeting?.localParticipant.removeEventListener(self)
            meeting?.removeEventListener(self)
        }

        /// A new participant joined
        func onParticipantJoined(_ participant: Participant) {
            participants.append(participant)

            // add listener
            participant.addEventListener(self)

            participant.setQuality(.high)

            if(participant.isLocal){
                self.localParticipantViewContainer.isHidden = false
            } else {
                self.remoteParticipantViewContainer.isHidden = false
            }
        }

        /// A participant left from the meeting
        /// - Parameter participant: participant object
        func onParticipantLeft(_ participant: Participant) {
            participant.removeEventListener(self)
            guard let index = self.participants.firstIndex(where: { $0.id == participant.id }) else {
                return
            }
            // remove participant from list
            participants.remove(at: index)
            // hide from ui
            UIView.animate(withDuration: 0.5){
                if(!participant.isLocal){
                    self.remoteParticipantViewContainer.isHidden = true
                }
            }
        }

        /// Called when speaker is changed
        /// - Parameter participantId: participant id of the speaker, nil when no one is speaking.
        func onSpeakerChanged(participantId: String?) {

            // show indication for active speaker
            if let participant = participants.first(where: { $0.id == participantId }) {
                self.showActiveSpeakerIndicator(participant.isLocal ? localParticipantViewContainer : remoteParticipantViewContainer, true)
            }

            // hide indication for others participants
            let otherParticipants = participants.filter { $0.id != participantId }
            for participant in otherParticipants {
                if participants.count &gt; 1 &amp;&amp; participant.isLocal {
                    showActiveSpeakerIndicator(localParticipantViewContainer, false)
                } else {
                    showActiveSpeakerIndicator(remoteParticipantViewContainer, false)
                }
            }
        }

        func showActiveSpeakerIndicator(_ view: UIView, _ show: Bool) {
            view.layer.borderWidth = 4.0
            view.layer.borderColor = show ? UIColor.blue.cgColor : 													UIColor.clear.cgColor
        }

}

...</code></pre><figcaption>MeetingViewController.swift</figcaption></figure><h3 id="step-6-implementing-participanteventlistener">Step 6: Implementing <code>ParticipantEventListener</code></h3><p>In this stage, we'll add an extension for the <code>MeetingViewController</code> that implements the ParticipantEventListener, which implements the <code>onStreamEnabled</code> and <code>onStreamDisabled</code> methods for the audio and video of MediaStreams enabled or disabled.</p><p>The function update UI is frequently used to control or modify the user interface (enable/disable camera &amp; mic) following the MediaStream state.</p><pre><code class="language-swift">class MeetingViewController: UIViewController {

...

extension MeetingViewController: ParticipantEventListener {

/// Participant has enabled mic, video or screenshare
/// - Parameters:
/// - stream: enabled stream object
/// - participant: participant object
func onStreamEnabled(_ stream: MediaStream, forParticipant participant: Participant) {
    updateUI(participant: participant, forStream: stream, enabled: true)
 }

/// Participant has disabled mic, video or screenshare
/// - Parameters:
///   - stream: disabled stream object
///   - participant: participant object
        
func onStreamDisabled(_ stream: MediaStream, 
			forParticipant participant: Participant) {
            
  updateUI(participant: participant, forStream: stream, enabled: false)
 }
 
}

private extension MeetingViewController {

 func updateUI(participant: Participant, forStream stream: MediaStream, 							enabled: Bool) { // true
        switch stream.kind {
        case .state(value: .video):
            if let videotrack = stream.track as? RTCVideoTrack {
                if enabled {
                    DispatchQueue.main.async {
                        UIView.animate(withDuration: 0.5){
                        
                            if(participant.isLocal) {
                            
    	self.localParticipantViewContainer.isHidden = false
	self.localParticipantVideoView.isHidden = false       
	self.localParticipantVideoView.videoContentMode = .scaleAspectFill                            self.localParticipantViewContainer.bringSubviewToFront(self.localParticipantVideoView)                         									
    videotrack.add(self.localParticipantVideoView)
    self.lblLocalParticipantNoMedia.isHidden = true

} else {
		self.remoteParticipantViewContainer.isHidden = false
        	self.remoteParticipantVideoView.isHidden = false
                                self.remoteParticipantVideoView.videoContentMode = .scaleAspectFill
                                self.remoteParticipantViewContainer.bringSubviewToFront(self.remoteParticipantVideoView)
                                		        videotrack.add(self.remoteParticipantVideoView)
 self.lblRemoteParticipantNoMedia.isHidden = true
        }
     }
  }
} else {
         UIView.animate(withDuration: 0.5){
                if(participant.isLocal){
                
                    self.localParticipantViewContainer.isHidden = false
                    self.localParticipantVideoView.isHidden = true
                    self.lblLocalParticipantNoMedia.isHidden = false
                            videotrack.remove(self.localParticipantVideoView)
} else {
                   self.remoteParticipantViewContainer.isHidden = false
                   self.remoteParticipantVideoView.isHidden = true
                   self.lblRemoteParticipantNoMedia.isHidden = false
                            videotrack.remove(self.remoteParticipantVideoView)
      }
    }
  }
}

     case .state(value: .audio):
            if participant.isLocal {
                
               localParticipantViewContainer.layer.borderWidth = 4.0
               localParticipantViewContainer.layer.borderColor = enabled ? UIColor.clear.cgColor : UIColor.red.cgColor
            } else {
                remoteParticipantViewContainer.layer.borderWidth = 4.0
                remoteParticipantViewContainer.layer.borderColor = enabled ? UIColor.clear.cgColor : UIColor.red.cgColor
            }
        default:
            break
        }
    }
}

...
</code></pre><h3 id="known-issue%E2%80%8B">Known Issue<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#known-issue">​</a></h3><p>Please add the following line in the <code>MeetingViewController.swift</code> file's <code>viewDidLoad</code> method If you get your video out of the container.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">override func viewDidLoad() {

  localParticipantVideoView.frame = CGRect(x: 10, y: 0, 
    		width: localParticipantViewContainer.frame.width, 
   		height: localParticipantViewContainer.frame.height)

  localParticipantVideoView.bounds = CGRect(x: 10, y: 0, 
  		width: localParticipantViewContainer.frame.width, 
        	height: localParticipantViewContainer.frame.height)

  localParticipantVideoView.clipsToBounds = true

  remoteParticipantVideoView.frame = CGRect(x: 10, y: 0, 
  		width: remoteParticipantViewContainer.frame.width, 
        	height: remoteParticipantViewContainer.frame.height)
        
  remoteParticipantVideoView.bounds = CGRect(x: 10, y: 0, 
  		width: remoteParticipantViewContainer.frame.width, 
    		height: remoteParticipantViewContainer.frame.height)
    
    remoteParticipantVideoView.clipsToBounds = true
}
</code></pre><figcaption>MeetingViewController.swift</figcaption></figure><blockquote><strong>TIP:</strong><br>Stuck anywhere? Check out this <a href="https://github.com/videosdk-live/videosdk-rtc-ios-sdk-example" rel="noopener noreferrer">example code</a> on GitHub</br></blockquote><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/videosdk-live/videosdk-rtc-ios-sdk-example"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - videosdk-live/videosdk-rtc-ios-sdk-example: WebRTC based video conferencing SDK for iOS (Swift / Objective C)</div><div class="kg-bookmark-description">WebRTC based video conferencing SDK for iOS (Swift / Objective C) - videosdk-live/videosdk-rtc-ios-sdk-example</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="How to Integrate Screen Share in iOS Video Call App?"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">videosdk-live</span></img></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/3d2f5eef43ad3d03fbe693ee2c8633053215e90252a63bddc775d8b8d8a7e380/videosdk-live/videosdk-rtc-ios-sdk-example" alt="How to Integrate Screen Share in iOS Video Call App?"/></div></a></figure><p/><h2 id="integrate-screen-share-in-video-app">Integrate Screen Share in Video App </h2><h3 id="step-1-open-target%E2%80%8B">Step 1: Open Target<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/handling-media/native-ios-screen-share#step-1--open-target">​</a></h3><p>Open your project with XCode, the select <strong>File &gt; New &gt; Target</strong> in menu bar.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step1-xcode-8cbf05258253368fa8095f10aa06459d.png" class="kg-image" alt="How to Integrate Screen Share in iOS Video Call App?" loading="lazy" width="801" height="580"/></figure><h3 id="step-2-select-target%E2%80%8B">Step 2: Select Target​</h3><p>Select <strong>Broadcast Upload Extension</strong> and click </p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step2-xcode-5270422797cc8941922cefadffb5238d.png" class="kg-image" alt="How to Integrate Screen Share in iOS Video Call App?" loading="lazy" width="769" height="555"/></figure><h3 id="step-3-configure-broadcast-upload-extension%E2%80%8B">Step 3: Configure Broadcast Upload Extension​</h3><p>Enter the extension's name in the <strong>Product Name</strong> field, choose the team from the dropdown, uncheck the "Include UI extension" field, and click "Finish."</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step3-xcode-458facd46d26cfa090fd8724b6ba831b.png" class="kg-image" alt="How to Integrate Screen Share in iOS Video Call App?" loading="lazy" width="789" height="567"/></figure><h3 id="step-4-activate-extension-scheme%E2%80%8B">Step 4: Activate Extension scheme​</h3><p>You will be prompted with a popup: <strong>Activate "Your-Extension-name" scheme?</strong> click on activate.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step4-xcode-6de6fa7fc079f920f52d8315b2717e9d.png" class="kg-image" alt="How to Integrate Screen Share in iOS Video Call App?" loading="lazy" width="510" height="490"/></figure><p>Now, the "Broadcast" folder will appear in the Xcode left side bar.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step5-xcode-79ba89532c028fb25376bf6d4953f0b2.png" class="kg-image" alt="How to Integrate Screen Share in iOS Video Call App?" loading="lazy" width="474" height="652"/></figure><h3 id="step-5-add-an-external-file-in-the-created-extension%E2%80%8B">Step 5: Add an External file in the created extension.​</h3><p>Open the <a href="https://github.com/videosdk-live/videosdk-rtc-ios-sdk-example/tree/main/VideoSDKScreenShare" rel="noopener noreferrer">videosdk-rtc-ios-sdk-example</a> repository, and copy the following files: <code>SampleUploader.swift</code>, <code>SocketConnection.swift</code>, <code>DarwinNotificationCenter.swift</code>, and <code>Atomic.swift</code> to your extension's folder. Ensure that these files are added to the target.</p><h3 id="step-6-update-samplehandlerswift-file%E2%80%8B">Step 6: Update <code>SampleHandler.swift</code> file​</h3><p>Open <a href="https://github.com/videosdk-live/videosdk-rtc-ios-sdk-example/blob/main/VideoSDKScreenShare/SampleHandler.swift" rel="noopener noreferrer">SampleHandler.swift</a>, and copy the content of the file. Paste this content into your extension's SampleHandler.swift file.</p><h3 id="step-7-add-capability-to-the-app%E2%80%8B">Step 7: Add Capability to the App​</h3><p>In Xcode, navigate to <strong>YourappName &gt; Signing &amp; Capabilities</strong>, and click on <strong>+Capability</strong> to configure the app group.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step8-xcode-60177a1783e9203570a06479c30492b8.png" class="kg-image" alt="How to Integrate Screen Share in iOS Video Call App?" loading="lazy" width="930" height="529"/></figure><p>Choose <strong>App Groups</strong> from the list.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step9-xcode-13aa5448218f78f473f060c6854874a2.png" class="kg-image" alt="How to Integrate Screen Share in iOS Video Call App?" loading="lazy" width="803" height="579"/></figure><p>After that, select or add the generated App Group ID that you have created before.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step10-xcode-80bd6f05c87acae9a9fbaa4a89f414f9.png" class="kg-image" alt="How to Integrate Screen Share in iOS Video Call App?" loading="lazy" width="1176" height="735"/></figure><h3 id="step-8-add-capability-in-extension%E2%80%8B">Step 8: Add Capability in Extension​</h3><p>Go to <strong>Your-Extension-Name &gt; Signing &amp; Capabilities</strong> and configure the <strong>App Group</strong> functionality which we had performed in previous steps. (Group ID should be same for both targets).</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step11-xcode-021329a0abd110f74fb1eba7d668fc79.png" class="kg-image" alt="How to Integrate Screen Share in iOS Video Call App?" loading="lazy" width="803" height="445"/></figure><h3 id="step-9-add-app-group-id-in-the-extension-file%E2%80%8B">Step 9: Add App Group ID in the Extension File​</h3><p>Go to the extension's <code>SampleHandler.swift</code> file and paste your group ID into the <code>appGroupIdentifier</code> constant.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step12-xcode-6f145ca7606a486596da66ebf5c31e36.png" class="kg-image" alt="How to Integrate Screen Share in iOS Video Call App?" loading="lazy" width="951" height="562"/></figure><h3 id="step-10-update-app-level-infoplist-file%E2%80%8B">Step 10: Update App level info.plist file​</h3><ol><li>Add a new key, <strong>RTCScreenSharingExtension</strong> in Info.plist with the extension's Bundle Identifier as the value.</li><li>Add a new key <strong>RTCAppGroupIdentifier</strong> in Info.plist with the extension's App groups Id as the value.</li></ol><p><strong>Note</strong>: For the extension's Bundle Identifier, go to <strong>TARGETS &gt; Your-Extension-Name &gt; Signing &amp; Capabilities</strong>.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step13-xcode-00cb59e564facb3c7f365235065f4561.png" class="kg-image" alt="How to Integrate Screen Share in iOS Video Call App?" loading="lazy" width="933" height="550"/></figure><blockquote>NOTE:<br>You can also check out the extension's <a href="https://github.com/videosdk-live/videosdk-rtc-ios-sdk-example/tree/main/VideoSDKScreenShare" rel="noopener noreferrer">example code</a> on Github.</br></blockquote><h2 id="integrate-screenshare-in-your-app%E2%80%8B">Integrate ScreenShare in your App​</h2><p>After successfully creating Broadcast Upload Extension using the above-listed steps, we can start using the <code>enableScreenShare</code> and <code>disableScreenShare</code> functions of the <code>Meeting</code> class.</p><h3 id="how-to-use-the-screenshare-functions">How to use the ScreenShare functions</h3><p>Use these functions in your app's Meeting Screen.</p><pre><code class="language-swift">@IBAction func ScreenShareButtonTapped(_ sender: Any) {
    Task {
      self.meeting?.enableScreenShare()
    }
}

@IBAction func StopScreenShareButtonTapped(_ sender: Any) {
    Task {
      self.meeting?.disableScreenShare()
    }
}</code></pre><blockquote><strong>CAUTION</strong>:<br>The function <code>enableScreenShare</code> and <code>disableScreenShare</code> are async functions; therefore use above syntax to call the ScreenShare functions.</br></blockquote><p>Calling the <code>enableScreenShare()</code> will prompt a <code>RPBroadcastPickerView</code> with the extension that was created using the above steps.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step23-xcode-e815d2c96e8061551e941055e32578b3.png" class="kg-image" alt="How to Integrate Screen Share in iOS Video Call App?" loading="lazy" width="307" height="504"/></figure><p>After clicking the <strong>Start Broadcast</strong> button, you will be able to get the screen share stream in the session.</p><ul><li>When the broadcast is started, it creates a Stream that has <code>MediaStream.kind = .share</code>. Using the stream kind, you can prompt a ScreenShare view for remote peers when ScreenShare is started by the local peer.</li><li>Similarly, you can use the same kind to dismiss the ScreenShare view on the remote peer when the ScreenShare is stopped.</li></ul><pre><code class="language-Swift">extension MeetingViewController: ParticipantEventListener {
    /// Participant has enabled mic, video or screenshare
    /// - Parameters:
    ///   - stream: enabled stream object
    ///   - participant: participant object
    func onStreamEnabled(_ stream: MediaStream, forParticipant participant: Participant) {
        
        if stream.kind == .share {
        // show screen share
            showScreenSharingView(true)
            screenSharingView.showMediastream(stream)
            return
        }
        
        // show stream in cell
        if let cell = self.cellForParticipant(participant) {
            cell.updateView(forStream: stream, enabled: true)
        }
        
        if participant.isLocal {
        // turn on controls for local participant
            self.buttonControlsView.updateButtons(forStream: stream, enabled: true)
        }
    }
    
    /// Participant has disabled mic, video or screenshare
    /// - Parameters:
    /// - stream: disabled stream object
    /// - participant: participant object
    func onStreamDisabled(_ stream: MediaStream, forParticipant participant: Participant) {
        
        if stream.kind == .share {
        // remove screen share
            showScreenSharingView(false)
            screenSharingView.hideMediastream(stream)
            return
        }
        
        // hide stream in cell
        if let cell = self.cellForParticipant(participant) {
            cell.updateView(forStream: stream, enabled: false)
        }
        
        if participant.isLocal {
        // turn off controls for local participant
            self.buttonControlsView.updateButtons(forStream: stream, enabled: false)
        }
    }
}</code></pre><h2 id="conclusion">Conclusion</h2><p>Integrating screen sharing into your iOS video call app with VideoSDK is a straightforward process that unlocks a powerful new feature for your users.  This functionality can streamline communication, boost productivity, and open doors for innovative use cases within your app.</p><p>Unlock the power of seamless video communication with VideoSDK! <a href="https://www.videosdk.live/signup">Sign up</a> now and dive into an extraordinary world of interactive video-calling experiences.</p><p>With VideoSDK, you get a generous 10,000 free minutes to kickstart your journey towards creating engaging and immersive connections. Whether you're building a social app, a collaboration tool, or an e-learning platform, our platform provides the tools you need to elevate your user experience to the next level.</p>]]></content:encoded></item><item><title><![CDATA[Build Flutter Live Streaming App for Android, iOS, and Web]]></title><description><![CDATA[In this tutorial, build an interactive live stream Flutter app. Developers must follow steps to build a robust app that incorporates video playback, chat functionality, user authentication, and backend infrastructure. ]]></description><link>https://www.videosdk.live/blog/flutter-live-streaming</link><guid isPermaLink="false">642d44dd2c7661a49f3824b4</guid><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Yash]]></dc:creator><pubDate>Sat, 11 Jan 2025 08:46:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2023/04/ils_flutter_blog.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<img src="https://assets.videosdk.live/static-assets/ghost/2023/04/ils_flutter_blog.jpg" alt="Build Flutter Live Streaming App for Android, iOS, and Web"/><p>Video calling has become a staple form of communication, but it often struggles with scalability when user numbers climb into the millions. Interactive live streaming offers a robust solution, providing a way to engage with a vast audience in near real-time.<br><br>Interactive live streaming enhances user experience with features like real-time comments, reactions (Emojis ?), and hand-raising, making it indispensable across industries such as gaming, social platforms, and education.</br></br></p><h3 id="why-choose-videosdk-for-your-flutter-live-streaming-app">Why Choose VideoSDK for Your Flutter Live Streaming App?</h3>
<p>VideoSDK integrates seamlessly with Flutter, allowing developers to add real-time communication capabilities to their apps while scaling effortlessly to accommodate millions of users. It combines the intimacy of video calls with the broad reach of live streaming.</p><h3 id="key-features-to-incorporate-in-your-flutter-live-streaming-app">Key Features to Incorporate in Your Flutter Live Streaming App</h3>
<p>Flutter is Google’s UI toolkit for building natively compiled applications for mobile, web, and desktop from a single codebase. It is particularly well-suited for developing high-performance apps. VideoSDK’s Flutter package comes loaded with over 15 features that are essential for a top-notch live streaming experience.</p><h2 id="step-by-step-guide-to-building-your-app">Step-by-Step Guide to Building Your App</h2>
<figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2023/04/image-5.png" class="kg-image" alt="Build Flutter Live Streaming App for Android, iOS, and Web" loading="lazy" width="1656" height="864"/></figure><p><strong>Pre-requisites:</strong></p><ul><li>Basic understanding of Flutter framework.</li><li>Video SDK Developer Account (Not having one? Follow <a href="https://app.videosdk.live/" rel="noopener noreferrer"><strong>VideoSDK Dashboard</strong></a>).</li><li>Video SDK <a href="https://pub.dev/packages/videosdk">Flutter Package</a>.</li></ul><p>So you are now ready to create a fresh flutter project </p><h3 id="a-create-and-configure-your-flutter-live-streaming-project">(a) <strong>Create and Configure Your Flutter Live Streaming Project</strong></h3><p>To create a new Flutter project, run the following command at your chosen location</p><pre><code class="language-shell">flutter create videosdk_flutter_ils_app</code></pre><p>Inside the terminal after navigating to the project directory, run the command.</p><pre><code class="language-shell">flutter pub add videosdk</code></pre><p><code>videosdk</code> package will now be added to the <strong>pubspec.yaml</strong>.</p><p>You'll need to add a few other packages</p><ul><li>HTTP - <code>http: ^0.13.5</code></li><li>flutter_vlc_player - <code>flutter_vlc_player: ^7.2.0</code></li></ul><h3 id="b-%E2%9A%99%EF%B8%8F-configure-flutter-live-streaming-project">(b) ⚙️ Configure Flutter Live Streaming Project</h3><p/><p><strong>For </strong>Flutter<strong> Android</strong></p><ul><li>You will need to update the <code>/android/app/src/main/AndroidManifest.xml</code> for the permissions you will be using to implement the audio and video features.</li></ul><pre><code class="language-xml">&lt;uses-feature android:name="android.hardware.camera" /&gt;
&lt;uses-feature android:name="android.hardware.camera.autofocus" /&gt;
&lt;uses-permission android:name="android.permission.CAMERA" /&gt;
&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
&lt;uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /&gt;
&lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /&gt;
&lt;uses-permission android:name="android.permission.INTERNET"/&gt;</code></pre><ul><li>App level <code>build.gradle</code> file at <code>/android/app/build.gradle</code> needs to be updated. You will need to increase <code>minSdkVersion</code> of <code>defaultConfig</code> up to <code>23</code></li></ul><p><strong>For Flutter iOS</strong></p><ul><li><code>Info.plist</code> file at <code>/ios/Runner/Info.plist</code> needs to be updated to add permissions for iOS.</li></ul><pre><code class="language-js">&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Camera Usage!&lt;/string&gt;
&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Microphone Usage!&lt;/string&gt;</code></pre><ul><li>You will need to uncomment the following line to define a global platform for your project in <code>/ios/Podfile</code></li></ul><pre><code># platform :ios, '11.0'</code></pre><h2 id="project-structure-for-flutter-live-streaming-app">Project Structure for Flutter Live Streaming App</h2><figure class="kg-card kg-code-card"><pre><code class="language-js">root
├── android
├── ios
├── lib
     ├── api_call.dart
     ├── ils_screen.dart
     ├── ils_speaker_view.dart
     ├── ils_viewer_view.dart
     ├── join_screen.dart
     ├── livestream_player.dart
     ├── main.dart
     ├── meeting_controls.dart
     ├── participant_tile.dart</code></pre><figcaption><p><span style="white-space: pre-wrap;">Project Structure</span></p></figcaption></figure><h3 id="step-1-get-started-flutter-live-streaming-with-apicalldart">STEP 1: Get Started Flutter Live Streaming with api_call.dart</h3><p>Before jumping to anything else, you will have to write a function to generate a unique meeting ID. To generate a meeting ID, you will need an Authentication Token. You can get an Authentication Token from <a href="https://app.videosdk.live/">VideoSDK Dashboard</a> (For Development) or <a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples">VideoSDK Authentication Server</a> (For Production).</p><pre><code class="language-js">import 'dart:convert';
import 'package:http/http.dart' as http;

//Auth token we will use to generate a meeting and connect to it
String token = "&lt;&lt; Authentication Token &gt;&gt;";

// API call to create meeting
Future&lt;String&gt; createMeeting() async {
  final http.Response httpResponse = await http.post(
    Uri.parse("https://api.videosdk.live/v2/rooms"),
    headers: {'Authorization': token},
  );

//Destructuring the roomId from the response
  return json.decode(httpResponse.body)['roomId'];
}</code></pre><h3 id="step-2-develop-the-join-screen-widget-for-flutter-live-streaming-app">STEP 2: <strong>Develop the Join Screen</strong> Widget for Flutter Live Streaming App</h3><p>Let's create <code>join_screen.dart</code> file in <code>lib</code> directory and create a JoinScreen<strong> StatelessWidget.</strong></p><p>The JoinScreen will consist of:</p><ul><li><strong>Create Meeting Button - </strong>This button will create a new meeting for the speaker and join it with the mode <code>CONFERENCE</code>.</li><li><strong>Meeting ID TextField - </strong>This text field will contain the meeting ID, you want to join.</li><li><strong>Join Meeting as Host Button - </strong>This button will join the meeting in <code>CONFERENCE</code> mode for the speakers, which you have provided.</li><li><strong>Join Meeting as Viewer Button - </strong>This button will join the meeting in <code>VIEWER</code> mode for the viewers, which you have provided.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import 'package:http/http.dart' as http;

import 'api_call.dart';
import 'ils_screen.dart';

class JoinScreen extends StatelessWidget {
  
  final _meetingIdController = TextEditingController();

  JoinScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      appBar: AppBar(
        title: const Text('VideoSDK ILS QuickStart'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(12.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            // Creating a new meeting
            ElevatedButton(
              onPressed: () =&gt; onCreateButtonPressed(context),
              child: const Text('Create Meeting'),
            ),
            const SizedBox(height: 40),
            TextField(
              style: const TextStyle(color: Colors.white),
              decoration: const InputDecoration(
                hintText: 'Enter Meeting Id',
                border: OutlineInputBorder(),
                hintStyle: TextStyle(color: Colors.white),
              ),
              controller: _meetingIdController,
            ),
            // Joining the meeting as host
            ElevatedButton(
              onPressed: () =&gt; onJoinButtonPressed(context, Mode.CONFERENCE),
              child: const Text('Join Meeting as Host'),
            ),
            // Joining the meeting as viewer
            ElevatedButton(
              onPressed: () =&gt; onJoinButtonPressed(context, Mode.VIEWER),
              child: const Text('Join Meeting as Viewer'),
            ),
          ],
        ),
      ),
    );
  }
  
  // Creates new Meeting Id and joins it in CONFERNCE mode.
  void onCreateButtonPressed(BuildContext context) async {
    // TODO: Implement 
  }

  // Join the provided meeting with given Mode and meetingId
  void onJoinButtonPressed(BuildContext context, Mode mode) {
	// TODO: Implement
  }
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">join_screen.dart</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">  // Creates new Meeting Id and joins it in CONFERNCE mode.
  void onCreateButtonPressed(BuildContext context) async {
    // Call createMeeting method
    final meetingId = await createMeeting();
   
    if (!context.mounted) return;
    Navigator.of(context).push(
      MaterialPageRoute(
        builder: (context) =&gt; ILSScreen(
          meetingId: meetingId,
          token: token,
          mode: Mode.CONFERENCE,
        ),
      ),
    );
   });
  }</code></pre><figcaption><p><span style="white-space: pre-wrap;">onCreateButtonPressed() implementation</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">  // Join the provided meeting with given Mode and meetingId
  void onJoinButtonPressed(BuildContext context, Mode mode) {
    String meetingId = _meetingIdController.text;
    var re = RegExp("\\w{4}\\-\\w{4}\\-\\w{4}");
    
    // Check meeting ID is not null or invaild
    if (meetingId.isNotEmpty &amp;&amp; re.hasMatch(meetingId)) {
      _meetingIdController.clear();
      // Navigate to ILSScreen
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (context) =&gt; ILSScreen(
            meetingId: meetingId,
            token: token,
            mode: mode,
          ),
        ),
      );
    } else {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
        content: Text("Please enter valid meeting id"),
      ));
    }
  }</code></pre><figcaption><p><span style="white-space: pre-wrap;">onJoinButtonPressed() implementation</span></p></figcaption></figure><ul><li>Update the app's home to JoinScreen in the <code>main.dart</code> file.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">import 'package:flutter/material.dart';
import 'join_screen.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'VideoSDK QuickStart',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: JoinScreen(),
    );
  }
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">main.dart</span></p></figcaption></figure><h4 id="output">Output</h4>
<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2023/04/flutter_ils_joining--3-.png" class="kg-image" alt="Build Flutter Live Streaming App for Android, iOS, and Web" loading="lazy" width="226" height="450"><figcaption><span style="white-space: pre-wrap;">JoinScreen</span></figcaption></img></figure><h3 id="step-3-flutter-live-streaming-screen-widget">STEP 3: Flutter Live Streaming Screen Widget</h3><p>Let's create <code>ils_screen.dart</code> file and create an <strong>ILSScreen </strong><code>StatefulWidget</code> which will take the <code>meetingId</code>, <code>token</code> and <code>mode</code> of the participant in the constructor.</p><p>You will create a new room using the <code>createRoom</code> method and render the <code>ILSSpeakerView</code> or <code>ILSViewerView</code> based on the past participant <code>mode</code>.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import './ils_speaker_view.dart';
import './ils_viewer_view.dart';

class ILSScreen extends StatefulWidget {
  final String meetingId;
  final String token;
  final Mode mode;

  const ILSScreen(
      {super.key,
      required this.meetingId,
      required this.token,
      required this.mode});

  @override
  State&lt;ILSScreen&gt; createState() =&gt; _ILSScreenState();
}

class _ILSScreenState extends State&lt;ILSScreen&gt; {
  late Room _room;
  bool isJoined = false;

  @override
  void initState() {
    // TODO: Implement
    super.initState();
  }

  // listening to room events
  void setMeetingEventListener() {
    // TODO: Implement
  }

  // onbackButton pressed leave the room
  Future&lt;bool&gt; _onWillPop() async {
    _room.leave();
    return true;
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () =&gt; _onWillPop(),
      child: Scaffold(
        backgroundColor: Colors.black,
        appBar: AppBar(
          title: const Text('VideoSDK ILS QuickStart'),
        ),
        //Showing the Speaker or Viewer View based on the mode
        body: isJoined
            ? widget.mode == Mode.CONFERENCE
                ? ILSSpeakerView(room: _room)
                : widget.mode == Mode.VIEWER
                    ? ILSViewerView(room: _room)
                    : null
            : const Center(
                  child: Text("Joining...",
                      style: TextStyle(color: Colors.white),
                    ),
                  ),
      ),
    );
  }
}
</code></pre><figcaption><p><span style="white-space: pre-wrap;">ils_screen.dart</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">@override
void initState() {
  // create room when widget loads
  _room = VideoSDK.createRoom(
    roomId: widget.meetingId,
    token: widget.token,
    displayName: "John Doe",
    micEnabled: true,
    camEnabled: true,
    defaultCameraIndex: 1, // Index of MediaDevices will be used to set default camera
    mode: widget.mode,
  );

  // setting the event listener for join and leave events
  setMeetingEventListener();
  
  // Joining room
  _room.join();
  
   super.initState();
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">initState() implementation</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">// listening to room events
void setMeetingEventListener() {

  // Setting the joining flag to true when meeting is joined
  _room.on(Events.roomJoined, () {
    if (widget.mode == Mode.CONFERENCE) {
      _room.localParticipant.pin();
    }
    setState(() {
      isJoined = true;
    });
  });

  //Handling navigation when meeting is left
  _room.on(Events.roomLeft, () {
    Navigator.popUntil(context, ModalRoute.withName('/'));
  });
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">setMeetingEventListener() implementation</span></p></figcaption></figure><h3 id="step-4-speakerview-widget-for-flutter-live-streaming-app">STEP 4: SpeakerView Widget for Flutter Live Streaming App</h3><p>Let's create the <code>ILSSpeakerView</code> which will show the <code>MeetingControls</code> and the <code>ParticipantTile</code> in grid.</p><ul><li>Let us start off by creating the <code>StatefulWidget</code> named <code>ParticipantTile</code> in <code>participant_tile.dart</code> file. It will consist of <code>RTCVideoView</code> which will show the participant's video stream.</li></ul><pre><code class="language-js">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class ParticipantTile extends StatefulWidget {
  final Participant participant;
  const ParticipantTile({super.key, required this.participant});

  @override
  State&lt;ParticipantTile&gt; createState() =&gt; _ParticipantTileState();
}

class _ParticipantTileState extends State&lt;ParticipantTile&gt; {
  Stream? videoStream;

  @override
  void initState() {
    // initialze video stream for the participant if they are present
    widget.participant.streams.forEach((key, Stream stream) {
      setState(() {
        if (stream.kind == 'video') {
          videoStream = stream;
        }
      });
    });
    _initStreamListeners();
    super.initState();
  }

  //Event listener for the video stream of the participant
  _initStreamListeners() {
    widget.participant.on(Events.streamEnabled, (Stream stream) {
      if (stream.kind == 'video') {
        setState(() =&gt; videoStream = stream);
      }
    });

    widget.participant.on(Events.streamDisabled, (Stream stream) {
      if (stream.kind == 'video') {
        setState(() =&gt; videoStream = null);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      //Rending the Video Stream of the participant
      child: videoStream != null
          ? RTCVideoView(
              videoStream?.renderer as RTCVideoRenderer,
              objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
            )
          : Container(
              color: Colors.grey.shade800,
              child: const Center(
                child: Icon(
                  Icons.person,
                  size: 100,
                ),
              ),
            ),
    );
  }
}</code></pre><ul><li>Next, let us add the <code>StatelessWidget</code> named <code>MeetingControls</code> in the <code>meeting_controls.dart</code> file. This widget will accept the callback handlers for all the meeting control buttons and the current HLS state of the meeting.</li></ul><pre><code class="language-js">import 'package:flutter/material.dart';

class MeetingControls extends StatelessWidget {
  final String hlsState;
  final void Function() onToggleMicButtonPressed;
  final void Function() onToggleCameraButtonPressed;
  final void Function() onHLSButtonPressed;

  const MeetingControls(
      {super.key,
      required this.hlsState,
      required this.onToggleMicButtonPressed,
      required this.onToggleCameraButtonPressed,
      required this.onHLSButtonPressed});

  @override
  Widget build(BuildContext context) {
    return Wrap(
      children: [
        ElevatedButton(
          onPressed: onToggleMicButtonPressed,
            child: const Text('Toggle Mic')),
        const SizedBox(width: 10),
        ElevatedButton(
            onPressed: onToggleCameraButtonPressed,
            child: const Text('Toggle WebCam')),
        const SizedBox(width: 10),
        ElevatedButton(
            onPressed: onHLSButtonPressed,
            child: Text(hlsState == "HLS_STOPPED"
                ? 'Start HLS'
                : hlsState == "HLS_STARTING"
                    ? "Starting HLS"
                    : hlsState == "HLS_STARTED" || hlsState == "HLS_PLAYABLE"
                        ? "Stop HLS"
                        : hlsState == "HLS_STOPPING"
                            ? "Stopping HLS"
                            : "Start HLS")),
      ],
    );
  }
}</code></pre><ul><li>Let's finally put all these widgets in the <code>StatefulWidget</code> named <code>ILSSpeakerView</code> in <code>ils_speaker_view.dart</code> file. This widget will listen to the <code>hlsStateChanged</code>, <code>participantJoined</code> and <code>participantLeft</code> events. It will render the participants and the meeting controls like leave, toggle mic and webcam as well as start and stop HLS.</li></ul><pre><code class="language-js">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import 'package:videosdk_flutter_quickstart/meeting_controls.dart';
import 'package:videosdk_flutter_quickstart/participant_tile.dart';

class ILSSpeakerView extends StatefulWidget {
  final Room room;
  const ILSSpeakerView({super.key, required this.room});

  @override
  State&lt;ILSSpeakerView&gt; createState() =&gt; _ILSSpeakerViewState();
}

class _ILSSpeakerViewState extends State&lt;ILSSpeakerView&gt; {
  var micEnabled = true;
  var camEnabled = true;
  String hlsState = "HLS_STOPPED";

  Map&lt;String, Participant&gt; participants = {};

  @override
  void initState() {
    super.initState();
    //Setting up the event listeners and initializing the participants and hls state
    setMeetingEventListener();
    participants.putIfAbsent(
        widget.room.localParticipant.id, () =&gt; widget.room.localParticipant);
    //filtering the CONFERENCE participants to be shown in the grid
    widget.room.participants.values.forEach((participant) {
      if (participant.mode == Mode.CONFERENCE) {
        participants.putIfAbsent(participant.id, () =&gt; participant);
      }
    });
    hlsState = widget.room.hlsState;
  }

  @override
  void setState(VoidCallback fn) {
    if (mounted) {
      super.setState(fn);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        children: [
          Row(
            children: [
              Expanded(
                  child: Text(
                widget.room.id,
                style: const TextStyle(color: Colors.white),
              )),
              ElevatedButton(
                onPressed: () =&gt; {
                  Clipboard.setData(ClipboardData(text: widget.room.id)),
                  ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
                    content: Text("Meeting Id Coppied"),
                  ))
                },
                child: const Text("Copy Meeting Id"),
              ),
              const SizedBox(width: 10),
              ElevatedButton(
                onPressed: () =&gt; {widget.room.leave()},
                style: ElevatedButton.styleFrom(
                  backgroundColor: Colors.red,
                ),
                child: const Text("Leave"),
              )
            ],
          ),
          const SizedBox(
            height: 20,
          ),
          //Showing the current HLS state
          Text(
            "Current HLS State: ${hlsState == "HLS_STARTED" || hlsState == "HLS_PLAYABLE" ? "Livestream is Started" : hlsState == "HLS_STARTING" ? "Livestream is starting" : hlsState == "HLS_STOPPING" ? "Livestream is stopping" : "Livestream is stopped"}",
            style: const TextStyle(color: Colors.white),
          ),
          //render all participants in the room
          Expanded(
            child: GridView.builder(
              gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                crossAxisCount: 1,
              ),
              itemBuilder: (context, index) {
                return ParticipantTile(
                    participant: participants.values.elementAt(index));
              },
              itemCount: participants.length,
            ),
          ),
          //Rending the meeting Controls
          MeetingControls(
            hlsState: hlsState,
            onToggleMicButtonPressed: () {
              micEnabled ? widget.room.muteMic() : widget.room.unmuteMic();
              micEnabled = !micEnabled;
            },
            onToggleCameraButtonPressed: () {
              camEnabled ? widget.room.disableCam() : widget.room.enableCam();
              camEnabled = !camEnabled;
            },
            //HLS handler which will start and stop HLS
            onHLSButtonPressed: () =&gt; {
              if (hlsState == "HLS_STOPPED")
                {
                  widget.room.startHls(config: {
                    "layout": {
                      "type": "SPOTLIGHT",
                      "priority": "PIN",
                      "GRID": 20,
                    },
                    "mode": "video-and-audio",
                    "theme": "DARK",
                    "quality": "high",
                    "orientation": "portrait",
                  })
                }
              else if (hlsState == "HLS_STARTED" || hlsState == "HLS_PLAYABLE")
                {widget.room.stopHls()}
            },
          ),
        ],
      ),
    );
  }

  // listening to room events for participants join, left and hls state changes
  void setMeetingEventListener() {
    widget.room.on(
      Events.participantJoined,
      (Participant participant) {
        //Adding only Conference participant to show in grid
        if (participant.mode == Mode.CONFERENCE) {
          setState(
            () =&gt; participants.putIfAbsent(participant.id, () =&gt; participant),
          );
        }
      },
    );

    widget.room.on(Events.participantLeft, (String participantId) {
      if (participants.containsKey(participantId)) {
        setState(
          () =&gt; participants.remove(participantId),
        );
      }
    });
    widget.room.on(
      Events.hlsStateChanged,
      (Map&lt;String, dynamic&gt; data) {
        setState(
          () =&gt; hlsState = data['status'],
        );
      },
    );
  }
}</code></pre><h4 id="output">Output</h4>
<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2023/04/flutter_ils_speaker_view--1-.png" class="kg-image" alt="Build Flutter Live Streaming App for Android, iOS, and Web" loading="lazy" width="226" height="450"><figcaption><span style="white-space: pre-wrap;">SpeakerView</span></figcaption></img></figure><h3 id="step-5-implementing-hls-for-flutter-live-streaming-app">STEP 5: <strong>Implementing HLS</strong> for Flutter Live Streaming app</h3><p>Let's create <code>StatefulWidget</code> named <code>ILSViewerView</code> in the <code>ils_viewer_view.dart</code> file.</p><p>ILSViewerView will listen to the <code>hlsStateChanged</code> event and if the HLS is started, it will show the live stream using the <code>flutter_vlc_player</code> library.</p><pre><code class="language-js">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import './livestream_player.dart';

class ILSViewerView extends StatefulWidget {
  final Room room;
  const ILSViewerView({super.key, required this.room});

  @override
  State&lt;ILSViewerView&gt; createState() =&gt; _ILSViewerViewState();
}

class _ILSViewerViewState extends State&lt;ILSViewerView&gt; {
  String hlsState = "HLS_STOPPED";
  String? downstreamUrl;

  @override
  void initState() {
    super.initState();
    //initialize the room's hls state and hls's downstreamUrl
    hlsState = widget.room.hlsState;
    downstreamUrl = widget.room.hlsDownstreamUrl;
    //add the hlsStateChanged event listener
    setMeetingEventListener();
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: Row(
              children: [
                Expanded(
                    child: Text(widget.room.id,
                        style: const TextStyle(color: Colors.white))),
                ElevatedButton(
                  onPressed: () =&gt;
                      {Clipboard.setData(ClipboardData(text: widget.room.id))},
                  child: const Text("Copy Meeting Id"),
                ),
                const SizedBox(width: 10),
                ElevatedButton(
                  onPressed: () =&gt; {widget.room.leave()},
                  style: ElevatedButton.styleFrom(
                    backgroundColor: Colors.red,
                  ),
                  child: const Text("Leave"),
                )
              ],
            ),
          ),
          //Show the livestream player if the downstreamUrl is present
          downstreamUrl != null
              ? LivestreamPlayer(downstreamUrl: downstreamUrl!)
              : const Text("Host has not started the HLS",
                  style: TextStyle(color: Colors.white)),
        ],
      ),
    );
  }

  void setMeetingEventListener() {
    // listening to hlsStateChanged events and updating the hlsState and downstremUrl
    widget.room.on(
      Events.hlsStateChanged,
      (Map&lt;String, dynamic&gt; data) {
        String status = data['status'];
        if (mounted) {
          setState(() {
            hlsState = status;
            if (status == "HLS_PLAYABLE" || status == "HLS_STOPPED") {
              downstreamUrl = data['downstreamUrl'];
            }
          });
        }
      },
    );
  }
}</code></pre><ul><li>Let us use the <code>flutter_vlc_player</code> library to play the HLS stream on the Viewer side. For these, you will create a <code>StatefulWidget</code> named <code>LivestreamPlayer</code> in the <code>livestream_player.dart</code> file.</li></ul><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:flutter_vlc_player/flutter_vlc_player.dart';

class LivestreamPlayer extends StatefulWidget {
  final String downstreamUrl;
  const LivestreamPlayer({
    Key? key,
    required this.downstreamUrl,
  }) : super(key: key);

  @override
  LivestreamPlayerState createState() =&gt; LivestreamPlayerState();
}

class LivestreamPlayerState extends State&lt;LivestreamPlayer&gt;
    with AutomaticKeepAliveClientMixin {
  late VlcPlayerController _controller;

  @override
  bool get wantKeepAlive =&gt; true;

  @override
  void initState() {
    super.initState();
    //initializing the player
    _controller = VlcPlayerController.network(widget.downstreamUrl,
        options: VlcPlayerOptions());
  }

  @override
  void dispose() async {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    super.build(context);
    //rendering the VlcPlayer
    return VlcPlayer(
      controller: _controller,
      aspectRatio: 9 / 16,
      placeholder: const Center(child: CircularProgressIndicator()),
    );
  }
}</code></pre><h4 id="output">Output</h4>
<figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2023/04/flutter_ils_viewer_view--1-.png" class="kg-image" alt="Build Flutter Live Streaming App for Android, iOS, and Web" loading="lazy" width="226" height="450"><figcaption><span style="white-space: pre-wrap;">ViewerView</span></figcaption></img></figure><h3 id="final-steps-testing-and-launching-your-app"><strong>Final Steps: Testing and Launching Your App</strong></h3><p>The app is all set to test. Make sure to update the <code>token</code> in <code>api_call.dart</code><br>Your app should look like this.</br></p>
<!--kg-card-begin: html-->
<center>
<video height="450px" src="https://cdn.videosdk.live/website-resources/docs-resources/flutter_ils_speaker_video.mp4" controls="" muted=""> </video> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 
<video height="450px" src="https://cdn.videosdk.live/website-resources/docs-resources/flutter_ils_viewer_video.mp4" controls="" muted=""/>
</center>
<!--kg-card-end: html-->
<p>You can check out <a href="https://github.com/videosdk-live/quickstart/tree/main/flutter-hls">the Complete Code HERE</a>.</p>
<!--kg-card-begin: html-->
<!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Your Page Title</title>
	<!-- Include Tailwind CSS -->
	<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</link></meta></meta></head>

<body>
	<div class="relative w-full overflow-hidden rounded-2xl bg-gradient-to-b from-pink-700 to-purple-900 p-4 text-center shadow-xl">
		<h2 class="mx-auto text-3xl font-bold tracking-tight text-white sm:text-2xl" style="margin-top: 3px; margin-bottom: 12px;">
			Schedule a Demo with Our Live Video Expert!
		</h2>
		<p class="mx-auto mt-3 max-w-xl text-sm text-gray-400">
			Discover how VideoSDK can help you build a cutting-edge real-time video app.
			<span class="font-semibold text-lato"/>
		</p>
		<div class="mt-4 flex items-center justify-center">
			<a href="https://www.videosdk.live/contact" class="rounded-md bg-white px-8 py-3 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white" target="_blank" style="text-decoration: none;color: black;" data-faitracker-click-bind="true">
				Book a call
			</a>	
		</div>
		
	</div>
</body>

</html>
<!--kg-card-end: html-->
<h2 id="conclusion-enhancing-your-app-with-additional-functionalities"><strong>Conclusion: Enhancing Your App with Additional Functionalities</strong></h2><p>With this, we successfully built the Flutter live streaming app using the video SDK in Flutter. If you wish to add functionalities like chat messaging, and screen sharing, you can always check out our <a href="https://docs.videosdk.live/" rel="noopener">Documentation</a>. If you face any difficulty with the implementation, you can connect with us on our <a href="https://discord.gg/Gpmj6eCq5u" rel="noopener">DISCORD Community</a>.</p><h2 id="more-flutter-resources">More Flutter Resources</h2>
<ul><li><a href="https://www.videosdk.live/blog/video-calling-in-flutter">Build a Flutter Video Calling App with Video SDK</a></li><li><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/getting-started">Video SDK Flutter SDK Integration Guide</a></li><li><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start">Flutter SDK QuickStart</a></li><li><a href="https://github.com/videosdk-live/videosdk-rtc-flutter-sdk-example">Flutter SDK Github Example</a></li><li><a href="https://www.videosdk.live/blog/video-calling-in-flutter">Build a Flutter Video Calling App with Video SDK</a></li><li><a href="https://youtu.be/4h57eVcaC34">Video Call Flutter app with Video SDK (Android &amp; IOS)</a></li><li><a href="https://pub.dev/packages/videosdk">Official Video SDK flutter plugin: (feel free to give it a star⭐)</a></li></ul>]]></content:encoded></item><item><title><![CDATA[How to Integrate Chat Feature using PubSub in iOS Video Call App?]]></title><description><![CDATA[Integrate real-time chat into the iOS video call app using PubSub for seamless communication. Enable users to chat while on call, enhancing user interaction.]]></description><link>https://www.videosdk.live/blog/integrate-chat-using-pubsub-in-ios-video-call-app</link><guid isPermaLink="false">66275e512a88c204ca9d4ae7</guid><category><![CDATA[iOS]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Sat, 11 Jan 2025 07:30:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/Chat-Feature-in-iOS-Video-Call-App.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/Chat-Feature-in-iOS-Video-Call-App.jpg" alt="How to Integrate Chat Feature using PubSub in iOS Video Call App?"/><p>Integrate Chat using PubSub in your <a href="https://www.videosdk.live/blog/ios-video-calling-sdk">iOS Video Call App</a> to enhance user communication and experience. With PubSub, real-time messaging becomes seamless, allowing users to exchange messages effortlessly during video calls. This integration adds a layer of interactivity, enabling users to chat, share information, and collaborate seamlessly while engaging in video conversations. By incorporating PubSub technology, your app ensures reliable message delivery and synchronization across all connected devices, enhancing the overall user experience.</p><p><strong>Benefits of Integrate Chat using PubSub in iOS Video Call App:</strong></p><ol><li><strong>Real-time Communication:</strong> PubSub integration enables real-time messaging within your iOS Video Call App, enhancing user interaction during video calls.</li><li><strong>Seamless Collaboration:</strong> Users can share information, exchange messages, and collaborate effectively while engaged in video conversations, fostering teamwork and productivity.</li><li><strong>Enhanced User Experience:</strong> The addition of PubSub technology enriches the app's functionality, providing a smoother and more interactive experience for users.</li><li><strong>Reliable Message Delivery:</strong> PubSub ensures reliable message delivery and synchronization across all connected devices, eliminating delays and ensuring messages are delivered promptly.</li><li><strong>Scalability:</strong> PubSub architecture allows your app to scale effortlessly, accommodating a growing user base without compromising performance.</li></ol><p><strong>Use Case of Integrate Chat using PubSub in iOS Video Call App:</strong></p><ul><li><strong>Real-time Collaboration:</strong> While discussing project details via video call, team members can use the integrated chat feature powered by PubSub to share documents, links, and updates instantly.</li><li><strong>Instant Feedback:</strong> Team members can provide instant feedback or ask questions via chat without interrupting the flow of the video call, enhancing communication efficiency.</li><li><strong>Document Sharing:</strong> With PubSub, users can seamlessly share project documents, screenshots, or any necessary files directly within the chat, facilitating collaboration and decision-making.</li></ul><p>In this guide, we'll walk you through the process of seamlessly adding chat features to your iOS video-calling application. From setting up the chat environment to handling chat interactions within your video call interfaces, we'll cover all the essential steps to improve your app's functionality and user experience.</p><h2 id="getting-started-with-videosdk">Getting Started with VideoSDK</h2><p>To integrate the Chat Feature, we must use the capabilities that VideoSDK offers. Before diving into the implementation steps, let's ensure you complete the necessary prerequisites.</p><h3 id="create-a-videosdk-account">Create a VideoSDK Account</h3><p>Go to your <a href="https://app.videosdk.live/login">VideoSDK dashboard</a> and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.</p><h3 id="generate-your-auth-token">Generate your Auth Token</h3><p>Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token is crucial in authorizing your application to use VideoSDK features. For a more visual understanding of the account creation and token generation process, consider referring to the <a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/server-setup">provided tutorial</a>.</p><h3 id="prerequisites-and-setup">Prerequisites and Setup</h3><ul><li>iOS 11.0+</li><li>Xcode 12.0+</li><li>Swift 5.0+</li></ul><p>This App will contain two screens:</p><p><strong>Join Screen</strong>: This screen allows the user to either create a meeting or join the predefined meeting.</p><p><strong>Meeting Screen</strong>: This screen basically contains local and remote participant views and some meeting controls such as Enable/Disable the microphone or Camera and Leave the meeting.</p><h2 id="integrate-videosdk%E2%80%8B">Integrate VideoSDK​</h2><p>To install VideoSDK, you must initialize the pod on the project by running the following command:</p><pre><code class="language-swift">pod init</code></pre><p>It will create the pod file in your project folder, Open that file and add the dependency for the VideoSDK, like below:</p><pre><code class="language-swift">pod 'VideoSDKRTC', :git =&gt; 'https://github.com/videosdk-live/videosdk-rtc-ios-sdk.git'</code></pre><figure class="kg-card kg-image-card"><img src="https://cdn.videosdk.live/website-resources/docs-resources/ios_quickstart_podfile.png" class="kg-image" alt="How to Integrate Chat Feature using PubSub in iOS Video Call App?" loading="lazy"/></figure><p>then run the below code to install the pod:</p><pre><code class="language-swift">pod install</code></pre><p>then declare the permissions in Info.plist :</p><pre><code class="language-swift">&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
&lt;string&gt;Camera permission description&lt;/string&gt;
&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;Microphone permission description&lt;/string&gt;</code></pre><h3 id="project-structure">Project Structure</h3><pre><code class="language-swift">iOSQuickStartDemo
   ├── Models
        ├── RoomStruct.swift
        └── MeetingData.swift
   ├── ViewControllers
        ├── StartMeetingViewController.swift
        └── MeetingViewController.swift
   ├── AppDelegate.swift // Default
   ├── SceneDelegate.swift // Default
   └── APIService
           └── APIService.swift
   ├── Main.storyboard // Default
   ├── LaunchScreen.storyboard // Default
   └── Info.plist // Default
 Pods
     └── Podfile</code></pre><h3 id="create-models%E2%80%8B">Create models<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#create-models">​</a></h3><p>Create a swift file for <code>MeetingData</code> and <code>RoomStruct</code> class model for setting data in object pattern.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">import Foundation
struct MeetingData {
    let token: String
    let name: String
    let meetingId: String
    let micEnabled: Bool
    let cameraEnabled: Bool
}</code></pre><figcaption>MeetingData.swift</figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-swift">import Foundation
struct RoomsStruct: Codable {
    let createdAt, updatedAt, roomID: String?
    let links: Links?
    let id: String?
    enum CodingKeys: String, CodingKey {
        case createdAt, updatedAt
        case roomID = "roomId"
        case links, id
    }
}

// MARK: - Links
struct Links: Codable {
    let getRoom, getSession: String?
    enum CodingKeys: String, CodingKey {
        case getRoom = "get_room"
        case getSession = "get_session"
    }
}</code></pre><figcaption>RoomStruct.swift</figcaption></figure><h2 id="essential-steps-for-building-the-video-calling">Essential Steps for Building the Video Calling</h2><p>This guide is designed to walk you through the process of integrating Chat with <a href="https://www.videosdk.live/">VideoSDK</a>. We'll cover everything from setting up the SDK to incorporating the visual cues into your app's interface, ensuring a smooth and efficient implementation process.</p><h3 id="step-1-get-started-with-apiclient%E2%80%8B">Step 1: Get started with APIClient<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#step-1--get-started-with-apiclient">​</a></h3><p>Before jumping to anything else, we have to write an API to generate a unique <code>meetingId</code>. You will require an <strong>authentication token;</strong> you can generate it either using <a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples" rel="noopener noreferrer">videosdk-server-api-example</a> or from the <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer">VideoSDK Dashboard</a> for developers.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">import Foundation

let TOKEN_STRING: String = "&lt;AUTH_TOKEN&gt;"

class APIService {

  class func createMeeting(token: String, completion: @escaping (Result&lt;String, Error&gt;) -&gt; Void) {

    let url = URL(string: "https://api.videosdk.live/v2/rooms")!

    var request = URLRequest(url: url)
    request.httpMethod = "POST"
    request.addValue(TOKEN_STRING, forHTTPHeaderField: "authorization")

    URLSession.shared.dataTask(
      with: request,
      completionHandler: { (data: Data?, response: URLResponse?, error: Error?) in

        DispatchQueue.main.async {

          if let data = data, let utf8Text = String(data: data, encoding: .utf8) {
            do {
              let dataArray = try JSONDecoder().decode(RoomsStruct.self, from: data)

              completion(.success(dataArray.roomID ?? ""))
            } catch {
              print("Error while creating a meeting: \(error)")
              completion(.failure(error))
            }
          }
        }
      }
    ).resume()
  }
}
</code></pre><figcaption>APIService.swift</figcaption></figure><h3 id="step-2-implement-join-screen%E2%80%8B">Step 2: Implement Join Screen<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#step-2--implement-join-screen">​</a></h3><p>The Join Screen will work as a medium to either schedule a new meeting or join an existing meeting.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">import Foundation
import UIKit

class StartMeetingViewController: UIViewController, UITextFieldDelegate {

  private var serverToken = ""

  /// MARK: outlet for create meeting button
  @IBOutlet weak var btnCreateMeeting: UIButton!

  /// MARK: outlet for join meeting button
  @IBOutlet weak var btnJoinMeeting: UIButton!

  /// MARK: outlet for meetingId textfield
  @IBOutlet weak var txtMeetingId: UITextField!

  /// MARK: Initialize the private variable with TOKEN_STRING &amp;
  /// setting the meeting id in the textfield
  override func viewDidLoad() {
    txtMeetingId.delegate = self
    serverToken = TOKEN_STRING
    txtMeetingId.text = "PROVIDE-STATIC-MEETING-ID"
  }

  /// MARK: method for joining meeting through seague named as "StartMeeting"
  /// after validating the serverToken in not empty
  func joinMeeting() {

    txtMeetingId.resignFirstResponder()

    if !serverToken.isEmpty {
      DispatchQueue.main.async {
        self.dismiss(animated: true) {
          self.performSegue(withIdentifier: "StartMeeting", sender: nil)
        }
      }
    } else {
      print("Please provide auth token to start the meeting.")
    }
  }

  /// MARK: outlet for create meeting button tap event
  @IBAction func btnCreateMeetingTapped(_ sender: Any) {
    print("show loader while meeting gets connected with server")
    joinRoom()
  }

  /// MARK: outlet for join meeting button tap event
  @IBAction func btnJoinMeetingTapped(_ sender: Any) {
    if (txtMeetingId.text ?? "").isEmpty {

      print("Please provide meeting id to start the meeting.")
      txtMeetingId.resignFirstResponder()
    } else {
      joinMeeting()
    }
  }

  // MARK: - method for creating room api call and getting meetingId for joining meeting

  func joinRoom() {

    APIService.createMeeting(token: self.serverToken) { result in
      if case .success(let meetingId) = result {
        DispatchQueue.main.async {
          self.txtMeetingId.text = meetingId
          self.joinMeeting()
        }
      }
    }
  }

  /// MARK: preparing to animate to meetingViewController screen
  override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    guard let navigation = segue.destination as? UINavigationController,

      let meetingViewController = navigation.topViewController as? MeetingViewController
    else {
      return
    }

    meetingViewController.meetingData = MeetingData(
      token: serverToken,
      name: txtMeetingId.text ?? "Guest",
      meetingId: txtMeetingId.text ?? "",
      micEnabled: true,
      cameraEnabled: true
    )
  }
}
</code></pre><figcaption>StartMeetingViewController.swift</figcaption></figure><h3 id="step-3-initialize-and-join-meeting%E2%80%8B">Step 3: Initialize and Join Meeting<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#step-3--initialize-and-join-meeting">​</a></h3><p>Using the provided <code>token</code> and <code>meetingId</code>, we will configure and initialize the meeting in <code>viewDidLoad()</code>.</p><p>Then, we'll add <strong>@IBOutlet</strong> for <code>localParticipantVideoView</code> and <code>remoteParticipantVideoView</code>, which can render local and remote participant media, respectively.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">class MeetingViewController: UIViewController {

import UIKit
import VideoSDKRTC
import WebRTC
import AVFoundation

class MeetingViewController: UIViewController {

// MARK: - Properties
// outlet for local participant container view
   @IBOutlet weak var localParticipantViewContainer: UIView!

// outlet for label for meeting Id
   @IBOutlet weak var lblMeetingId: UILabel!

// outlet for local participant video view
   @IBOutlet weak var localParticipantVideoView: RTCMTLVideoView!

// outlet for remote participant video view
   @IBOutlet weak var remoteParticipantVideoView: RTCMTLVideoView!

// outlet for remote participant no media label
   @IBOutlet weak var lblRemoteParticipantNoMedia: UILabel!

// outlet for remote participant container view
   @IBOutlet weak var remoteParticipantViewContainer: UIView!

// outlet for local participant no media label
   @IBOutlet weak var lblLocalParticipantNoMedia: UILabel!

// Meeting data - required to start
   var meetingData: MeetingData!

// current meeting reference
   private var meeting: Meeting?

    // MARK: - video participants including self to show in UI
    private var participants: [Participant] = []

        // MARK: - Lifecycle Events

        override func viewDidLoad() {
        super.viewDidLoad()
        // configure the VideoSDK with token
        VideoSDK.config(token: meetingData.token)

        // init meeting
        initializeMeeting()

        // set meeting id in button text
        lblMeetingId.text = "Meeting Id: \(meetingData.meetingId)"
      }

      override func viewWillAppear(_ animated: Bool) {
          super.viewWillAppear(animated)
          navigationController?.navigationBar.isHidden = true
      }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        navigationController?.navigationBar.isHidden = false
        NotificationCenter.default.removeObserver(self)
    }

        // MARK: - Meeting

        private func initializeMeeting() {

            // Initialize the VideoSDK
            meeting = VideoSDK.initMeeting(
                meetingId: meetingData.meetingId,
                participantName: meetingData.name,
                micEnabled: meetingData.micEnabled,
                webcamEnabled: meetingData.cameraEnabled
            )

            // Adding the listener to meeting
            meeting?.addEventListener(self)

            // joining the meeting
            meeting?.join()
        }
}</code></pre><figcaption>MeetingViewController.swift</figcaption></figure><h3 id="step-4-implement-controls%E2%80%8B">Step 4: Implement Controls<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#step-4--implement-controls">​</a></h3><p>After initializing the meeting in the previous step, we will now add <strong>@IBOutlet</strong> for <code>btnLeave</code>, <code>btnToggleVideo</code> and <code>btnToggleMic</code> which can control the media in the meeting.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">class MeetingViewController: UIViewController {

...

    // outlet for leave button
    @IBOutlet weak var btnLeave: UIButton!

    // outlet for toggle video button
    @IBOutlet weak var btnToggleVideo: UIButton!

    // outlet for toggle audio button
    @IBOutlet weak var btnToggleMic: UIButton!

    // bool for mic
    var micEnabled = true
    // bool for video
    var videoEnabled = true


    // outlet for leave button click event
    @IBAction func btnLeaveTapped(_ sender: Any) {
            DispatchQueue.main.async {
                self.meeting?.leave()
                self.dismiss(animated: true)
            }
        }

    // outlet for toggle mic button click event
    @IBAction func btnToggleMicTapped(_ sender: Any) {
        if micEnabled {
            micEnabled = !micEnabled // false
            self.meeting?.muteMic()
        } else {
            micEnabled = !micEnabled // true
            self.meeting?.unmuteMic()
        }
    }

    // outlet for toggle video button click event
    @IBAction func btnToggleVideoTapped(_ sender: Any) {
        if videoEnabled {
            videoEnabled = !videoEnabled // false
            self.meeting?.disableWebcam()
        } else {
            videoEnabled = !videoEnabled // true
            self.meeting?.enableWebcam()
        }
    }

...

}</code></pre><figcaption>MeetingViewController.swift</figcaption></figure><h3 id="step-5-implementing-meetingeventlistener%E2%80%8B">Step 5: Implementing <code>MeetingEventListener</code>​</h3><p>In this step, we'll create an extension of the <code>MeetingViewController</code> that implements the MeetingEventListener, which implements the <code>onMeetingJoined</code>, <code>onMeetingLeft</code>, <code>onParticipantJoined</code>, <code>onParticipantLeft</code>, <code>onParticipantChanged</code> etc. methods.</p><p>We'll create another extension of the <code>MeetingViewController</code> that implements the <code>PubSubMessageListener</code> that triggers when you receive a new message, it implements <code>onMessageReceived</code> method.</p><p>//Added pub-sub message listener.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">
class MeetingViewController: UIViewController {

...

extension MeetingViewController: MeetingEventListener {

        /// Meeting started
        func onMeetingJoined() {

            // handle local participant on start
            guard let localParticipant = self.meeting?.localParticipant else { return }
            // add to list
            participants.append(localParticipant)

            // add event listener
            localParticipant.addEventListener(self)

            localParticipant.setQuality(.high)

            if(localParticipant.isLocal){
                self.localParticipantViewContainer.isHidden = false
            } else {
                self.remoteParticipantViewContainer.isHidden = false
            }
        }

        /// Meeting ended
        func onMeetingLeft() {
            // remove listeners
            meeting?.localParticipant.removeEventListener(self)
            meeting?.removeEventListener(self)
        }

        /// A new participant joined
        func onParticipantJoined(_ participant: Participant) {
            participants.append(participant)

            // add listener
            participant.addEventListener(self)

            participant.setQuality(.high)

            if(participant.isLocal){
                self.localParticipantViewContainer.isHidden = false
            } else {
                self.remoteParticipantViewContainer.isHidden = false
            }
        }

        /// A participant left from the meeting
        /// - Parameter participant: participant object
        func onParticipantLeft(_ participant: Participant) {
            participant.removeEventListener(self)
            guard let index = self.participants.firstIndex(where: { $0.id == participant.id }) else {
                return
            }
            // remove participant from list
            participants.remove(at: index)
            // hide from ui
            UIView.animate(withDuration: 0.5){
                if(!participant.isLocal){
                    self.remoteParticipantViewContainer.isHidden = true
                }
            }
        }

}

extension MeetingViewController: PubSubMessageListener {
    
    func onMessageReceived(_ message: PubSubMessage) {
        print("Message Received:= " + message.message)
        
        /// Your ui code for showing the chat view
    }
}

...</code></pre><figcaption>MeetingViewController.swift</figcaption></figure><h3 id="step-6-implementing-participanteventlistener">Step 6: Implementing <code>ParticipantEventListener</code></h3><p>In this stage, we'll add an extension for the <code>MeetingViewController</code> that implements the ParticipantEventListener, which implements the <code>onStreamEnabled</code> and <code>onStreamDisabled</code> methods for the audio and video of MediaStreams enabled or disabled.</p><p>The function update UI is frequently used to control or modify the user interface (enable/disable camera &amp; mic) by the MediaStream state.</p><pre><code class="language-swift">class MeetingViewController: UIViewController {

...

extension MeetingViewController: ParticipantEventListener {

/// Participant has enabled mic, video or screenshare
/// - Parameters:
/// - stream: enabled stream object
/// - participant: participant object
func onStreamEnabled(_ stream: MediaStream, forParticipant participant: Participant) {
    updateUI(participant: participant, forStream: stream, enabled: true)
 }

/// Participant has disabled mic, video or screenshare
/// - Parameters:
///   - stream: disabled stream object
///   - participant: participant object
        
func onStreamDisabled(_ stream: MediaStream, 
			forParticipant participant: Participant) {
            
  updateUI(participant: participant, forStream: stream, enabled: false)
 }
 
}

private extension MeetingViewController {

 func updateUI(participant: Participant, forStream stream: MediaStream, 							enabled: Bool) { // true
        switch stream.kind {
        case .state(value: .video):
            if let videotrack = stream.track as? RTCVideoTrack {
                if enabled {
                    DispatchQueue.main.async {
                        UIView.animate(withDuration: 0.5){
                        
                            if(participant.isLocal) {
                            
    	self.localParticipantViewContainer.isHidden = false
	self.localParticipantVideoView.isHidden = false       
	self.localParticipantVideoView.videoContentMode = .scaleAspectFill                            self.localParticipantViewContainer.bringSubviewToFront(self.localParticipantVideoView)                         									
    videotrack.add(self.localParticipantVideoView)
    self.lblLocalParticipantNoMedia.isHidden = true

} else {
		self.remoteParticipantViewContainer.isHidden = false
        	self.remoteParticipantVideoView.isHidden = false
                                self.remoteParticipantVideoView.videoContentMode = .scaleAspectFill
                                self.remoteParticipantViewContainer.bringSubviewToFront(self.remoteParticipantVideoView)
                                		        videotrack.add(self.remoteParticipantVideoView)
 self.lblRemoteParticipantNoMedia.isHidden = true
        }
     }
  }
} else {
         UIView.animate(withDuration: 0.5){
                if(participant.isLocal){
                
                    self.localParticipantViewContainer.isHidden = false
                    self.localParticipantVideoView.isHidden = true
                    self.lblLocalParticipantNoMedia.isHidden = false
                            videotrack.remove(self.localParticipantVideoView)
} else {
                   self.remoteParticipantViewContainer.isHidden = false
                   self.remoteParticipantVideoView.isHidden = true
                   self.lblRemoteParticipantNoMedia.isHidden = false
                            videotrack.remove(self.remoteParticipantVideoView)
      }
    }
  }
}

     case .state(value: .audio):
            if participant.isLocal {
                
               localParticipantViewContainer.layer.borderWidth = 4.0
               localParticipantViewContainer.layer.borderColor = enabled ? UIColor.clear.cgColor : UIColor.red.cgColor
            } else {
                remoteParticipantViewContainer.layer.borderWidth = 4.0
                remoteParticipantViewContainer.layer.borderColor = enabled ? UIColor.clear.cgColor : UIColor.red.cgColor
            }
        default:
            break
        }
    }
}

...
</code></pre><h3 id="known-issue%E2%80%8B">Known Issue<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/quick-start#known-issue">​</a></h3><p>Please add the following line to the <code>MeetingViewController.swift</code> file's <code>viewDidLoad</code> method If you get your video out of the container, view like below image.</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">override func viewDidLoad() {

  localParticipantVideoView.frame = CGRect(x: 10, y: 0, 
    		width: localParticipantViewContainer.frame.width, 
   		height: localParticipantViewContainer.frame.height)

  localParticipantVideoView.bounds = CGRect(x: 10, y: 0, 
  		width: localParticipantViewContainer.frame.width, 
        	height: localParticipantViewContainer.frame.height)

  localParticipantVideoView.clipsToBounds = true

  remoteParticipantVideoView.frame = CGRect(x: 10, y: 0, 
  		width: remoteParticipantViewContainer.frame.width, 
        	height: remoteParticipantViewContainer.frame.height)
        
  remoteParticipantVideoView.bounds = CGRect(x: 10, y: 0, 
  		width: remoteParticipantViewContainer.frame.width, 
    		height: remoteParticipantViewContainer.frame.height)
    
    remoteParticipantVideoView.clipsToBounds = true
}
</code></pre><figcaption>MeetingViewController.swift</figcaption></figure><blockquote><strong>TIP:</strong><br>Stuck anywhere? Check out this <a href="https://github.com/videosdk-live/videosdk-rtc-ios-sdk-example" rel="noopener noreferrer">example code</a> on GitHub</br></blockquote><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/videosdk-live/videosdk-rtc-ios-sdk-example"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - videosdk-live/videosdk-rtc-ios-sdk-example: WebRTC based video conferencing SDK for iOS (Swift / Objective C)</div><div class="kg-bookmark-description">WebRTC based video conferencing SDK for iOS (Swift / Objective C) - videosdk-live/videosdk-rtc-ios-sdk-example</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="How to Integrate Chat Feature using PubSub in iOS Video Call App?"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">videosdk-live</span></img></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/3d2f5eef43ad3d03fbe693ee2c8633053215e90252a63bddc775d8b8d8a7e380/videosdk-live/videosdk-rtc-ios-sdk-example" alt="How to Integrate Chat Feature using PubSub in iOS Video Call App?"/></div></a></figure><p>After successfully integrating the VideoSDK into your iOS app, you've unlocked the power of high-quality video calling. This not only improves user experience but can encourage longer call duration and deeper engagement in your app. By adding a chat feature, you provide users with more flexibility and control during their calls.</p><h2 id="integrate-chat-feature-in-video-app">Integrate Chat Feature in Video App </h2><p>For communication or any kind of messaging between the participants, VideoSDK provides <code>pubSub</code> classes that use the Publish-Subscribe mechanism and can be used to develop a wide variety of functionalities. For example, participants could use it to send chat messages to each other, share files or other media, or even trigger actions like muting or unmuting audio or video.</p><p>Now we will see, how we can use PubSub to implement Chat functionality. If you are not familiar with the PubSub mechanism and <code>pubSub</code> class, you can <a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/pubsub">follow this guide</a>.</p><h3 id="implementing-group-chat">Implementing Group Chat</h3><ul><li>The first step in creating a group chat is choosing the topic that all the participants will publish and subscribe to send and receive the messages. We will be using <code>CHAT</code> as the topic for this one.</li><li>On the send button, publish the message that the sender typed in the <code>Text</code> field.</li></ul><blockquote>NOTE:<br>It is assumed that you have created a user interface along with the implementation of the meeting class and its event listeners. For reference checkout our iOS <a href="https://github.com/videosdk-live/videosdk-rtc-ios-sdk-example" rel="noopener noreferrer">example app</a> on how can you setup your app.</br></blockquote><pre><code class="language-swift">class MeetingViewController {
    //Button that will send the message when tapped
    @IBAction func sendMessageTapped(_ sender: Any) {
        let options = ["persist" : true]
        // publish message
        self.meeting?.pubsub.publish(topic: "CHAT", message: "How are you?", options: options)
    }
}</code></pre><ul><li>The next step would be to display the messages others send. For this, we have to <code>subscribe</code> to that topic i.e <code>CHAT</code> and display all the messages. When a message is received, the <code>onMessageReceived</code> event of the <code>PubSubMessageListener</code> is triggered.</li></ul><pre><code class="language-swift">extension MeetingViewController: MeetingEventListener {
    func onMeetingJoined() {
    //subscribe to the topic 'CHAT' when onMeetingJoined is triggered
    meeting?.pubsub.subscribe(topic: "CHAT", forListener: self)
    }
}
extension MeetingViewController: PubSubMessageListener {
    // read message when it is received
    func onMessageReceived(_ message: PubSubMessage) {
        print("Message Received: " + message.message)
    }
}</code></pre><p>The final step in the group chat would be <code>unsubscribe</code> to that topic, which you had previously subscribed to but no longer needed. Here we are <code>unsubscribe</code> to <code>CHAT</code> topic on activity destroy.</p><pre><code class="language-swift">extension MeetingViewController: MeetingEventListener {
    func onMeetingLeft() {
    //unsubscribe to the topic 'CHAT' when onMeetingLeft is triggered
    ////highlight-next-line
    meeting?.pubsub.unsubscribe(topic: "CHAT", forListener: self)
    }
}</code></pre><ul><li><strong>If you want to full guide about all features with chat, you can check our documentation:</strong></li></ul><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/chat-using-pubsub"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Chat messages with PubSub - Video SDK Docs | Video SDK</div><div class="kg-bookmark-description">PubSub features quick integrate in Javascript, React JS, Android, IOS, React Native, Flutter with Video SDK to add live video &amp; audio conferencing to your applications.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.videosdk.live/img/icons/favicon.ico" alt="How to Integrate Chat Feature using PubSub in iOS Video Call App?"><span class="kg-bookmark-author">Video SDK logo</span></img></div></div><div class="kg-bookmark-thumbnail"><img src="https://docs.videosdk.live/img/videosdklive-thumbnail.jpg" alt="How to Integrate Chat Feature using PubSub in iOS Video Call App?"/></div></a></figure><h3 id="integrate-private-chat">Integrate Private Chat</h3><p>In the above example, if you want to convert into a private chat between two participants, then all you have to do is pass the participantID of the participant in the <code>sendOnly</code> option as <code>["sendOnly" : ["ABCD"]]</code>. Here sendOnly accepts an array of participant IDs if you wish to send a message to.</p><pre><code class="language-swift">class MeetingViewController {
    //Button that will send the private message when tapped
    @IBAction func sendPrivateMessageTapped(_ sender: Any) {
        //adding sendOnly option
        let options = ["sendOnly" : ["ABCD"]]
        // publish message
        self.meeting?.pubsub.publish(topic: "CHAT", message: "How are you?", options: options)
    }
}</code></pre><h3 id="downloading-chat-messages%E2%80%8B">Downloading Chat Messages<a href="https://docs.videosdk.live/ios/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/chat-using-pubsub#downloading-chat-messages">​</a></h3><p>All the messages from the PubSub which where published with <code>persist : true</code> and can be downloaded as a <code>.csv</code> file. This file will be available in the VideoSDK dashboard as well as through the <a href="https://docs.videosdk.live/api-reference/realtime-communication/fetch-session-using-sessionid">Sessions API</a>.</p><h2 id="conclusion">Conclusion</h2><p>By integrating chat functionality using PubSub, you've added a valuable layer of communication to your video call application with VideoSDK.live. This guide has equipped you with the knowledge to implement this valuable addition to your iOS app. This integration improves engagement and fosters better communication among users. By leveraging PubSub, developers can create a robust and scalable chat feature that complements the video calling experience.</p><p>Unlock the full potential of VideoSDK today and craft seamless video experiences! <strong><strong><a href="https://app.videosdk.live/dashboard">Sign up</a></strong></strong> now to receive 10,000 free minutes and take your video app to new heights.</p>]]></content:encoded></item><item><title><![CDATA[Integrate HLS Player in React JS Video Calling App: Complete Guide]]></title><description><![CDATA[Integrate HLS Player seamlessly into your React JS video calling app for smooth, high-quality streaming.]]></description><link>https://www.videosdk.live/blog/implement-hls-player-in-react-js</link><guid isPermaLink="false">6618f8102a88c204ca9d0980</guid><category><![CDATA[React]]></category><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Sat, 11 Jan 2025 06:54:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/HLS-player-React.png" medium="image"/><content:encoded><![CDATA[<blockquote>Implementing an HLS player in React JS requires loading&nbsp;<code>.m3u8</code>&nbsp;playlists through hls.js or Safari native HLS support inside a&nbsp;<code>&lt;video&gt;</code>&nbsp;element managed with&nbsp;<code>useRef</code>&nbsp;and&nbsp;<code>useEffect</code>. VideoSDK exposes playback URLs through the&nbsp;<code>useMeeting</code>&nbsp;hook after a host starts HLS broadcasting. Viewers join in VIEWER mode and attach the returned stream URL to an HLS-capable player component.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/HLS-player-React.png" alt="Integrate HLS Player in React JS Video Calling App: Complete Guide"/><p>A webinar host starts a live session. Two hundred attendees join as viewers. Thirty seconds later, half the audience sees a frozen frame while the other half watches smoothly. The difference is rarely React itself. It is how HLS segments arrive, how the player buffers them, and whether the viewer path uses WebRTC or HTTP Live Streaming. This guide defines HLS in a React context, compares player libraries, covers production pitfalls teams hit after the demo works, and walks through a full VideoSDK integration with host and viewer modes.</p><h3 id="advantages-of-using-hls-player">Advantages of Using HLS Player:</h3><ul><li><strong>Seamless Streaming</strong>: HLS ensures smooth video playback by adapting to network fluctuations, and delivering uninterrupted communication during video calls.</li><li><strong>Cross-Platform Compatibility</strong>: HLS is supported across different devices and platforms, enabling users to engage in video calls seamlessly regardless of their device type.</li><li><strong>Improved User Experience</strong>: With HLS, users experience minimal buffering and faster load times, enhancing their overall satisfaction with the video calling app.</li><li><strong>Scalability:</strong> HLS supports scalable streaming, allowing your app to accommodate a growing user base without compromising on performance.</li><li><a href="https://www.videosdk.live/blog/what-is-adaptive-bitrate-streaming"><strong>Adaptive Bitrate Streaming</strong></a>: HLS automatically adjusts the video quality based on the user's network speed, ensuring optimal viewing experience under varying conditions.</li></ul><h3 id="practical-applications-of-hls-player">Practical Applications of HLS Player:</h3><ul><li><strong>Virtual Meetings</strong>: HLS integration enables businesses to conduct virtual meetings with remote teams or clients, fostering collaboration regardless of geographical barriers.</li><li><strong>Online Education</strong>: Educational platforms can leverage HLS to deliver high-quality video lectures and interactive sessions, facilitating remote learning for students worldwide.</li><li><strong>Telehealth Services</strong>: Healthcare providers can use HLS-enabled video calling apps to offer remote consultations and medical advice, improving access to healthcare services.</li><li><strong>Live Events</strong>: Event organizers can live stream conferences, concerts, or sports events using HLS, reaching a wider audience and enhancing attendee engagement.</li><li><strong>Customer Support</strong>: Companies can integrate HLS into their customer support systems to provide real-time video assistance and troubleshooting, enhancing customer satisfaction and loyalty.</li></ul><p>Let's build the React HLS player with an integrated using <a href="https://www.videosdk.live/">VideoSDK</a>. With VideoSDK's robust APIs and SDKs, you can effortlessly incorporate React HLS streaming capabilities into your application, ensuring smooth and high-quality video playback for all users.</p><h2 id="how-does-hls-streaming-work-in-a-react-application">How Does HLS Streaming Work in a React Application?</h2><p>HLS streaming in a React application follows a four-stage pipeline: ingest from the host, transcoding into adaptive segments, CDN distribution, and client-side playback through a JavaScript HLS engine.</p><h3 id="ingest-and-transcoding">Ingest and Transcoding</h3><p>When a host calls&nbsp;<code>startHls()</code>&nbsp;through VideoSDK's&nbsp;<code>useMeeting</code>&nbsp;hook, the platform captures the conference layout (speakers, spotlight mode, pinned participants) and encodes it into HLS-compatible segments. The host continues interacting through WebRTC. Viewers never connect to the raw WebRTC session.</p><h3 id="manifest-and-segment-delivery">Manifest and Segment Delivery</h3><p>The platform generates a master playlist (<code>.m3u8</code>) listing available quality variants and a media playlist pointing to segment files. CDNs cache these segments at edge nodes. React clients poll or refresh the manifest to discover new segments during live playback.</p><h3 id="client-playback-layer">Client Playback Layer</h3><p>The React viewer component checks&nbsp;<code>Hls.isSupported()</code>. If true, hls.js attaches to the video element and manages buffer levels, quality switching, and error recovery. If false (Safari), the native&nbsp;<code>&lt;video src="...m3u8"&gt;</code>&nbsp;path handles playback directly.</p><h3 id="state-synchronization">State Synchronization</h3><p>VideoSDK exposes&nbsp;<code>hlsState</code>&nbsp;and&nbsp;<code>hlsUrls</code>&nbsp;through&nbsp;<code>useMeeting</code>. The viewer UI renders a waiting message until&nbsp;<code>hlsState</code>&nbsp;equals&nbsp;<code>HLS_PLAYABLE</code>, then mounts the player. This prevents attaching hls.js to an empty or stale URL.</p><p>Typical HLS live latency ranges from 10 to 30 seconds behind the real-time source, depending on segment duration, CDN hops, and player buffer settings [UPDATE: verify date]. Teams building React live apps must treat that delay as a fixed constraint, not a bug to patch with smaller buffers alone.</p><h2 id="getting-started-with-videosdk-and-hls"><strong>Getting Started with VideoSDK and HLS</strong></h2><p>To take advantage of the React HLS player functionality, we must use the capabilities that the VideoSDK offers. Before diving into the implementation steps, let's ensure, that you have completed the necessary prerequisites.</p><h3 id="a-create-a-videosdk-account">[a] Create a VideoSDK Account</h3><p>Go to your <a href="https://app.videosdk.live/dashboard/">VideoSDK dashboard</a> and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.</p><h3 id="b-generate-your-auth-token">[b] Generate your Auth Token</h3><p>Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token is crucial in authorizing your application to use VideoSDK features.</p><p>For a more visual understanding of the account creation and token generation process, consider referring to the <a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/authentication-and-token">provided tutorial</a>.</p><h3 id="c-prerequisites-and-setup">[c] Prerequisites and Setup</h3><p>Before proceeding, ensure that your development environment meets the following requirements:</p><ul><li>VideoSDK Developer Account (Not having one?) Follow <a href="https://app.videosdk.live/" rel="noopener noreferrer"><strong>VideoSDK Dashboard</strong></a>.</li><li><a href="https://www.npmjs.com/package/@videosdk.live/react-sdk" rel="noopener noreferrer"><strong>React VideoSDK</strong></a></li><li>Make sure Node and NPM are installed on your device.</li><li>Basic understanding of Hooks (useState, useRef, useEffect)</li><li>React Context API (optional)</li></ul><p>Follow the steps to create the environment necessary to add video calls to your app. You can also find the code sample for <a href="https://github.com/videosdk-live/quickstart/tree/main/react-rtc" rel="noopener noreferrer">Quickstart here</a>.<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#create-new-react-app" rel="noopener noreferrer">​</a></p><h3 id="creating-and-configuring-your-react-app">Creating and Configuring Your React App</h3><pre><code class="language-js">$ npx create-react-app videosdk-rtc-react-app</code></pre><h2 id="install-videosdk%E2%80%8B">Install VideoSDK<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#install-videosdk">​</a></h2><p>It is necessary to set up VideoSDK within your project before going into the details of integrating the HLS feature. Installing VideoSDK using NPM or Yarn will depend on the needs of your project.</p><ul><li>For NPM</li></ul><pre><code class="language-js">$ npm install "@videosdk.live/react-sdk"

//For the Participants Video
$ npm install "react-player"</code></pre><ul><li>For Yarn</li></ul><pre><code class="language-js">$ yarn add "@videosdk.live/react-sdk"

//For the Participants Video
$ yarn add "react-player"</code></pre><p>You are going to use functional components to leverage React's reusable component architecture. There will be components for users, videos and controls (mic, camera, leave) over the video.</p><h3 id="structure-of-the-project%E2%80%8B">Structure of the project<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-ILS#structure-of-the-project">​</a></h3><p>Your project structure should look like this.</p><pre><code class="language-js">   root
   ├── node_modules
   ├── public
   ├── src
   │    ├── API.js
   │    ├── App.js
   │    ├── index.js
   ├── package.json
   .    .</code></pre><p>You are going to use functional components to leverage react's reusable component architecture. There will be components for users, videos and controls (mic, camera, leave) over the video.</p><h3 id="app-architecture%E2%80%8B">App Architecture<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-ILS#app-architecture">​</a></h3><p>The App will contain a container component which includes a user component with videos. Each video component will have control buttons for the mic, camera, leave a meeting, and HLS.</p><p>You will be working on these files:</p><ul><li>API.js: Responsible for handling API calls such as generating unique meetingId and token</li><li>App.js: Responsible for rendering the container and joining the meeting.</li></ul><h4 id="architecture-for-speaker">Architecture for Speaker</h4>
<figure class="kg-card kg-image-card"><img src="https://cdn.videosdk.live/website-resources/docs-resources/react_quick_start_ils_speaker_arch.png" class="kg-image" alt="Integrate HLS Player in React JS Video Calling App: Complete Guide" loading="lazy" width="1324" height="844"/></figure><h4 id="architecture-for-viewer">Architecture for Viewer</h4>
<figure class="kg-card kg-image-card"><img src="https://cdn.videosdk.live/website-resources/docs-resources/react_quick_start_ils_viewer_arch.png" class="kg-image" alt="Integrate HLS Player in React JS Video Calling App: Complete Guide" loading="lazy" width="1324" height="844"/></figure><h2 id="implementing-hls-player-in-react-js">Implementing HLS Player in React JS</h2><p>To add video capability to your React application, you must first complete a sequence of prerequisites.</p><h3 id="step-1-get-started-with-apijs">Step 1: Get started with API.js</h3><p>Before moving on, you must create an API request to generate a unique meetingId. You will need an authentication token, which you can create either through the <a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples" rel="noopener noreferrer">videosdk-rtc-api-server-examples</a> or directly from the <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer">VideoSDK Dashboard</a> for developers.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">//This is the Auth token, you will use it to generate a meeting and connect to it
export const authToken = "&lt;Generated-from-dashbaord&gt;";
// API call to create a meeting
export const createMeeting = async ({ token }) =&gt; {
  const res = await fetch(`https://api.videosdk.live/v2/rooms`, {
    method: "POST",
    headers: {
      authorization: `${authToken}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({}),
  });
  //Destructuring the roomId from the response
  const { roomId } = await res.json();
  return roomId;
};</code></pre><figcaption><p><span style="white-space: pre-wrap;">API.js</span></p></figcaption></figure><h3 id="step-2-wireframe-appjs-with-all-the-components%E2%80%8B">Step 2: Wireframe App.js with all the components<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#step-2-wireframe-appjs-with-all-the-components">​</a></h3><p>To build up a wireframe of App.js, you need to use VideoSDK Hooks and Context Providers. VideoSDK provides MeetingProvider, MeetingConsumer, useMeeting, and useParticipant hooks.</p><p>First, you need to understand the <strong>Context of </strong>provider can connect with<strong>Provider</strong> and Consumer. Context is primarily used when some data needs to be accessible by many components at different nesting levels.</p><ul><li><strong>MeetingProvider</strong>: This is the Context Provider. It accepts value <code>config</code> and <code>token</code> as props. The Provider component accepts a value prop to be passed to consuming components that are descendants of this Provider. One provider can connect with many consumers. Providers can be nested to override values deeper within the tree.</li><li><strong>MeetingConsumer</strong>: This is the Context Consumer. All consumers that are descendants of a Provider will re-render whenever the Provider’s value prop changes.</li><li><strong>useMeeting</strong>: This is the meeting hook API. It includes all the information related to meetings such as join/leave, enable/disable the mic or webcam, etc.</li><li><strong>useParticipant</strong>: This is the participant hook API. It is responsible for handling all the events and props related to one particular participant such as <strong>name</strong>, <strong>webcamStream</strong>, <strong>micStream</strong>, etc.</li></ul><p>The Meeting Context provides a way to listen for any changes that occur when a participant joins the meeting or makes modifications to their microphone, camera, and other settings.</p><p>Begin by making a few changes to the code in the <strong>App.js</strong> file.</p><pre><code class="language-js">import "./App.css";
import React, { useEffect, useMemo, useRef, useState } from "react";
import {
  MeetingProvider,
  MeetingConsumer,
  useMeeting,
  useParticipant,
} from "@videosdk.live/react-sdk";
import { authToken, createMeeting } from "./API";
import ReactPlayer from "react-player";

function JoinScreen({ getMeetingAndToken }) {
  return null;
}

function ParticipantView(props) {
  return null;
}

function Controls(props) {
  return null;
}

function MeetingView(props) {
  return null;
}

function App() {
  const [meetingId, setMeetingId] = useState(null);

  //Getting the meeting id by calling the api we just wrote
  const getMeetingAndToken = async (id) =&gt; {
    const meetingId =
      id == null ? await createMeeting({ token: authToken }) : id;
    setMeetingId(meetingId);
  };

  //This will set Meeting Id to null when meeting is left or ended
  const onMeetingLeave = () =&gt; {
    setMeetingId(null);
  };

  return authToken &amp;&amp; meetingId ? (
    &lt;MeetingProvider
      config={{
        meetingId,
        micEnabled: true,
        webcamEnabled: true,
        name: "C.V. Raman",
      }}
      token={authToken}
    &gt;
      &lt;MeetingView meetingId={meetingId} onMeetingLeave={onMeetingLeave} /&gt;
    &lt;/MeetingProvider&gt;
  ) : (
    &lt;JoinScreen getMeetingAndToken={getMeetingAndToken} /&gt;
  );
}

export default App;</code></pre><h3 id="step-3-implement-join-screen">Step 3: Implement Join Screen</h3><p>The join screen will serve as a medium to either schedule a new meeting or join an existing one as a host or a viewer.</p><p>This functionality will have 3 buttons:</p><ol><li><strong>Join as Host</strong>: When this button is clicked, the person will join the meeting with the entered <code>meetingId</code> as <code>HOST</code>.</li><li><strong>Join as Viewer</strong>: When this button is clicked, the person will join the meeting with the entered <code>meetingId</code> as <code>VIEWER</code>.</li><li><strong>Create Meeting</strong>: When this button is clicked, the person will join a new meeting as <code>HOST</code>.</li></ol><pre><code class="language-js">function JoinScreen({ getMeetingAndToken, setMode }) {
  const [meetingId, setMeetingId] = useState(null);
  //Set the mode of joining participant and set the meeting id or generate new one
  const onClick = async (mode) =&gt; {
    setMode(mode);
    await getMeetingAndToken(meetingId);
  };
  return (
    &lt;div className="container"&gt;
      &lt;button onClick={() =&gt; onClick("CONFERENCE")}&gt;Create Meeting&lt;/button&gt;
      &lt;br /&gt;
      &lt;br /&gt;
      {" or "}
      &lt;br /&gt;
      &lt;br /&gt;
      &lt;input
        type="text"
        placeholder="Enter Meeting Id"
        onChange={(e) =&gt; {
          setMeetingId(e.target.value);
        }}
      /&gt;
      &lt;br /&gt;
      &lt;br /&gt;
      &lt;button onClick={() =&gt; onClick("CONFERENCE")}&gt;Join as Host&lt;/button&gt;
      {" | "}
      &lt;button onClick={() =&gt; onClick("VIEWER")}&gt;Join as Viewer&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><h4 id="output">Output</h4>
<figure class="kg-card kg-image-card"><img src="https://cdn.videosdk.live/website-resources/docs-resources/quick_start_react_ils_join_screen.png" class="kg-image" alt="Integrate HLS Player in React JS Video Calling App: Complete Guide" loading="lazy" width="326" height="256"/></figure><h3 id="step-4-implement-meetingview-and-controls">Step 4: Implement MeetingView and Controls</h3><p><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start#step-4-implement-meetingview-and-controls">​</a>The next step is to create a container to manage features such as join, leave, mute, unmute, start, and stop HLS for the HOST and to display an HLS Player for the viewer.</p><p>You need to determine the mode of the <code>localParticipant</code>, if its <code>CONFERENCE</code>, display the <code>SpeakerView</code> component otherwise shows the <code>ViewerView</code> component.</p><pre><code class="language-js">function Container(props) {
  const [joined, setJoined] = useState(null);
  //Get the method which will be used to join the meeting.
  const { join } = useMeeting();
  const mMeeting = useMeeting({
    //callback for when a meeting is joined successfully
    onMeetingJoined: () =&gt; {
      setJoined("JOINED");
    },
    //callback for when a meeting is left
    onMeetingLeft: () =&gt; {
      props.onMeetingLeave();
    },
    //callback for when there is an error in a meeting
    onError: (error) =&gt; {
      alert(error.message);
    },
  });
  const joinMeeting = () =&gt; {
    setJoined("JOINING");
    join();
  };

  return (
    &lt;div className="container"&gt;
      &lt;h3&gt;Meeting Id: {props.meetingId}&lt;/h3&gt;
      {joined &amp;&amp; joined == "JOINED" ? (
        mMeeting.localParticipant.mode == Constants.modes.CONFERENCE ? (
          &lt;SpeakerView /&gt;
        ) : mMeeting.localParticipant.mode == Constants.modes.VIEWER ? (
          &lt;ViewerView /&gt;
        ) : null
      ) : joined &amp;&amp; joined == "JOINING" ? (
        &lt;p&gt;Joining the meeting...&lt;/p&gt;
      ) : (
        &lt;button onClick={joinMeeting}&gt;Join&lt;/button&gt;
      )}
    &lt;/div&gt;
  );
}</code></pre><h3 id="step-5-implement-speakerview%E2%80%8B">Step 5: Implement SpeakerView<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-ILS#step-5-implement-speakerview">​</a></h3><p>The next step is to create <code>SpeakerView</code> and <code>Controls</code> components to manage features such as join, leave, mute, and unmute.</p><ul><li>You have to retrieve all the <code>participants</code> using the <code>useMeeting</code> hook and filter them based on the mode set to <code>CONFERENCE</code> ensuring that only Speakers are displayed on the screen.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">function SpeakerView() {
  //Get the participants and HLS State from useMeeting
  const { participants, hlsState } = useMeeting();

  //Filtering the host/speakers from all the participants
  const speakers = useMemo(() =&gt; {
    const speakerParticipants = [...participants.values()].filter(
      (participant) =&gt; {
        return participant.mode == Constants.modes.CONFERENCE;
      }
    );
    return speakerParticipants;
  }, [participants]);
  return (
    &lt;div&gt;
      &lt;p&gt;Current HLS State: {hlsState}&lt;/p&gt;
      {/* Controls for the meeting */}
      &lt;Controls /&gt;

      {/* Rendring all the HOST participants */}
      {speakers.map((participant) =&gt; (
        &lt;ParticipantView participantId={participant.id} key={participant.id} /&gt;
      ))}
    &lt;/div&gt;
  );
}

function Container(){
  ...

  const mMeeting = useMeeting({
    onMeetingJoined: () =&gt; {
      //Pin the local participant if he joins in CONFERENCE mode
      if (mMeetingRef.current.localParticipant.mode == "CONFERENCE") {
        mMeetingRef.current.localParticipant.pin();
      }
      setJoined("JOINED");
    },
    ...
  });

  //Create a ref to meeting object so that when used inside the
  //Callback functions, meeting state is maintained
  const mMeetingRef = useRef(mMeeting);
  useEffect(() =&gt; {
    mMeetingRef.current = mMeeting;
  }, [mMeeting]);

  return &lt;&gt;...&lt;/&gt;;
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">SpeakerView</span></p></figcaption></figure><ul><li>You have to add the <code>Controls</code> component which will allow the participant to toggle their media.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">function Controls() {
  const { leave, toggleMic, toggleWebcam, startHls, stopHls } = useMeeting();
  return (
    &lt;div&gt;
      &lt;button onClick={() =&gt; leave()}&gt;Leave&lt;/button&gt;
      &amp;emsp;|&amp;emsp;
      &lt;button onClick={() =&gt; toggleMic()}&gt;toggleMic&lt;/button&gt;
      &lt;button onClick={() =&gt; toggleWebcam()}&gt;toggleWebcam&lt;/button&gt;
      &amp;emsp;|&amp;emsp;
      &lt;button
        onClick={() =&gt; {
          //Start the HLS in SPOTLIGHT mode and PIN as
          //priority so only speakers are visible in the HLS stream
          startHls({
            layout: {
              type: "SPOTLIGHT",
              priority: "PIN",
              gridSize: "20",
            },
            theme: "LIGHT",
            mode: "video-and-audio",
            quality: "high",
            orientation: "landscape",
          });
        }}
      &gt;
        Start HLS
      &lt;/button&gt;
      &lt;button onClick={() =&gt; stopHls()}&gt;Stop HLS&lt;/button&gt;
    &lt;/div&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">Controls Component</span></p></figcaption></figure><ul><li>You need to then create the <code>ParticipantView</code> to display the participant's name and media. To play the media, use the <code>webcamStream</code> and <code>micStream</code> from the <code>useParticipant</code> hook.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">function ParticipantView(props) {
  const micRef = useRef(null);
  const { webcamStream, micStream, webcamOn, micOn, isLocal, displayName } =
    useParticipant(props.participantId);

  const videoStream = useMemo(() =&gt; {
    if (webcamOn &amp;&amp; webcamStream) {
      const mediaStream = new MediaStream();
      mediaStream.addTrack(webcamStream.track);
      return mediaStream;
    }
  }, [webcamStream, webcamOn]);

  //Playing the audio in the &lt;audio&gt;
  useEffect(() =&gt; {
    if (micRef.current) {
      if (micOn &amp;&amp; micStream) {
        const mediaStream = new MediaStream();
        mediaStream.addTrack(micStream.track);

        micRef.current.srcObject = mediaStream;
        micRef.current
          .play()
          .catch((error) =&gt;
            console.error("videoElem.current.play() failed", error)
          );
      } else {
        micRef.current.srcObject = null;
      }
    }
  }, [micStream, micOn]);

  return (
    &lt;div&gt;
      &lt;p&gt;
        Participant: {displayName} | Webcam: {webcamOn ? "ON" : "OFF"} | Mic:{" "}
        {micOn ? "ON" : "OFF"}
      &lt;/p&gt;
      &lt;audio ref={micRef} autoPlay playsInline muted={isLocal} /&gt;
      {webcamOn &amp;&amp; (
        &lt;ReactPlayer
          //
          playsinline // extremely crucial prop
          pip={false}
          light={false}
          controls={false}
          muted={true}
          playing={true}
          //
          url={videoStream}
          //
          height={"300px"}
          width={"300px"}
          onError={(err) =&gt; {
            console.log(err, "participant video error");
          }}
        /&gt;
      )}
    &lt;/div&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">ParticipantView</span></p></figcaption></figure><h4 id="output-of-speakerview-component%E2%80%8B">Output Of SpeakerView Component<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-ILS#output-of-speakerview-component">​</a></h4><figure class="kg-card kg-image-card"><img src="https://cdn.videosdk.live/website-resources/docs-resources/quick_start_react_ils_speaker.png" class="kg-image" alt="Integrate HLS Player in React JS Video Calling App: Complete Guide" loading="lazy" width="578" height="448"/></figure><h3 id="step-6-implement-viewerview-with-hls-player%E2%80%8B">Step 6: Implement ViewerView with HLS Player<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-ILS#step-6-implement-viewerview">​</a></h3><p>When the host initiates the live streaming, viewers will be able to watch it. To implement the player view, you have to use <code>hls.js</code>. It will help play the HLS stream.</p><p>Begin by adding this package.</p><pre><code class="language-js">$ npm install hls.js</code></pre><p>or</p><pre><code class="language-js">$ yarn add hls.js</code></pre><p>With <code>hls.js</code> installed, you can now get the <code>hlsUrls</code> from the <code>useMeeting</code> hook which will be used to play the HLS in the player.</p><pre><code class="language-js">//importing hls.js
import Hls from "hls.js";

function ViewerView() {
  // States to store downstream url and current HLS state
  const playerRef = useRef(null);
  //Getting the hlsUrls
  const { hlsUrls, hlsState } = useMeeting();

  //Playing the HLS stream when the playbackHlsUrl is present and it is playable
  useEffect(() =&gt; {
    if (hlsUrls.playbackHlsUrl &amp;&amp; hlsState == "HLS_PLAYABLE") {
      if (Hls.isSupported()) {
        const hls = new Hls({
          maxLoadingDelay: 1, // max video loading delay used in automatic start level selection
          defaultAudioCodec: "mp4a.40.2", // default audio codec
          maxBufferLength: 0, // If buffer length is/becomes less than this value, a new fragment will be loaded
          maxMaxBufferLength: 1, // Hls.js will never exceed this value
          startLevel: 0, // Start playback at the lowest quality level
          startPosition: -1, // set -1 playback will start from intialtime = 0
          maxBufferHole: 0.001, // 'Maximum' inter-fragment buffer hole tolerance that hls.js can cope with when searching for the next fragment to load.
          highBufferWatchdogPeriod: 0, // if media element is expected to play and if currentTime has not moved for more than highBufferWatchdogPeriod and if there are more than maxBufferHole seconds buffered upfront, hls.js will jump buffer gaps, or try to nudge playhead to recover playback.
          nudgeOffset: 0.05, // In case playback continues to stall after first playhead nudging, currentTime will be nudged evenmore following nudgeOffset to try to restore playback. media.currentTime += (nb nudge retry -1)*nudgeOffset
          nudgeMaxRetry: 1, // Max nb of nudge retries before hls.js raise a fatal BUFFER_STALLED_ERROR
          maxFragLookUpTolerance: .1, // This tolerance factor is used during fragment lookup.
          liveSyncDurationCount: 1, // if set to 3, playback will start from fragment N-3, N being the last fragment of the live playlist
          abrEwmaFastLive: 1, // Fast bitrate Exponential moving average half-life, used to compute average bitrate for Live streams.
          abrEwmaSlowLive: 3, // Slow bitrate Exponential moving average half-life, used to compute average bitrate for Live streams.
          abrEwmaFastVoD: 1, // Fast bitrate Exponential moving average half-life, used to compute average bitrate for VoD streams
          abrEwmaSlowVoD: 3, // Slow bitrate Exponential moving average half-life, used to compute average bitrate for VoD streams
          maxStarvationDelay: 1, // ABR algorithm will always try to choose a quality level that should avoid rebuffering
        });

        let player = document.querySelector("#hlsPlayer");

        hls.loadSource(hlsUrls.playbackHlsUrl);
        hls.attachMedia(player);
      } else {
        if (typeof playerRef.current?.play === "function") {
          playerRef.current.src = hlsUrls.playbackHlsUrl;
          playerRef.current.play();
        }
      }
    }
  }, [hlsUrls, hlsState, playerRef.current]);

  return (
    &lt;div&gt;
      {/* Showing message if HLS is not started or is stopped by HOST */}
      {hlsState != "HLS_PLAYABLE" ? (
        &lt;div&gt;
          &lt;p&gt;HLS has not started yet or is stopped&lt;/p&gt;
        &lt;/div&gt;
      ) : (
        hlsState == "HLS_PLAYABLE" &amp;&amp; (
          &lt;div&gt;
            &lt;video
              ref={playerRef}
              id="hlsPlayer"
              autoPlay={true}
              controls
              style={{ width: "100%", height: "100%" }}
              playsinline
              playsInline
              muted={true}
              playing
              onError={(err) =&gt; {
                console.log(err, "hls video error");
              }}
            &gt;&lt;/video&gt;
          &lt;/div&gt;
        )
      )}
    &lt;/div&gt;
  );
}

</code></pre><h4 id="output-of-viewerview%E2%80%8B">Output of ViewerView<a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/quick-start-ILS#output-of-viewerview">​</a></h4><figure class="kg-card kg-image-card"><img src="https://cdn.videosdk.live/website-resources/docs-resources/quick_start_react_ils_viewer.png" class="kg-image" alt="Integrate HLS Player in React JS Video Calling App: Complete Guide" loading="lazy" width="1132" height="664"/></figure><p>Congrats! You have completed the implementation of a customized live-streaming app in ReactJS using VideoSDK. To explore more features, go through Basic and Advanced features.</p><p>For, more reference, check our docs:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/recording-and-live-streaming/interactive-livestream"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Interactive Livestream - Video SDK Docs | Video SDK</div><div class="kg-bookmark-description">Interactive Livestream features quick integrate in Javascript, React JS, Android, IOS, React Native, Flutter with Video SDK to add live video &amp; audio conferencing to your applications.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.videosdk.live/img/icons/favicon.ico" alt="Integrate HLS Player in React JS Video Calling App: Complete Guide"><span class="kg-bookmark-author">Video SDK logo</span></img></div></div><div class="kg-bookmark-thumbnail"><img src="https://docs.videosdk.live/img/videosdklive-thumbnail.jpg" alt="Integrate HLS Player in React JS Video Calling App: Complete Guide" onerror="this.style.display = 'none'"/></div></a></figure><h2 id="%E2%9C%A8-want-to-add-more-features-to-react-js-video-calling-app">✨ Want to Add More Features to React JS Video Calling App?</h2><p>If you found this guide helpful and want to explore more features for your React JS video calling app, check out these additional resources:</p><ul><li>Active Speaker Indication: <a href="https://www.videosdk.live/blog/integrate-active-speaker-indication-in-react-js" rel="nofollow noopener">Link</a></li><li>RTMP Live Stream: <a href="https://www.videosdk.live/blog/integrate-rtmp-livestream-in-react-js" rel="nofollow noopener">Link</a></li><li>Image Capture: <a href="https://www.videosdk.live/blog/integrate-image-capture-in-react-js" rel="nofollow noopener">Link</a></li><li>Screen Share: <a href="https://www.videosdk.live/blog/integrate-screen-share-in-react-js" rel="nofollow noopener">Link</a></li><li>Chat Feature: <a href="https://www.videosdk.live/blog/integrate-chat-feature-in-react-js" rel="nofollow noopener">Link</a></li><li>Collaborative Whiteboard: <a href="https://www.videosdk.live/blog/integrate-whiteboard-in-react-js" rel="nofollow noopener">Link</a></li><li>Picture-in-Picture (PiP) Mode: <a href="https://www.videosdk.live/blog/integrate-picture-in-picture-pip-in-react-js" rel="nofollow noopener">Link</a></li></ul><h2 id="wrap-up">Wrap-up</h2><p>Integrating the HLS player into your React JS video calling app using VideoSDK offers a powerful solution for seamless streaming and enhanced user experience. With the help of VideoSDK, you can easily implement HLS playback, ensuring smooth and reliable video communication for your users. </p><p>With HLS.js library integration and VideoSDK's APIs, you can build a feature-rich video-calling application that meets the demands of modern communication. </p><p>And, If you are new here and want to build an interactive react app with free resources, you can <a href="https://www.videosdk.live/signup">Sign up with VideoSDK</a> and get? <em>10000 free minutes every month.</em> This will help your new video-calling app go to the next level without any costs associated with initial usage, allowing you to focus on building and scaling your application effectively.</p><h2 id="frequently-asked-questions">Frequently Asked Questions</h2><p>Developers searching for HLS React integration most often ask the seven questions below about native support, library choice, VideoSDK workflow, and latency limits.</p><h3 id="how-do-you-implement-an-hls-player-in-react-js">How do you implement an HLS player in React JS?</h3><p>You implement an HLS player in React JS by installing hls.js, creating a&nbsp;<code>&lt;video&gt;</code>&nbsp;element with&nbsp;<code>useRef</code>, and using&nbsp;<code>useEffect</code>&nbsp;to call&nbsp;<code>hls.loadSource()</code>&nbsp;and&nbsp;<code>hls.attachMedia()</code>&nbsp;when your stream URL is ready. On Safari, assign the&nbsp;<code>.m3u8</code>&nbsp;URL directly to the video&nbsp;<code>src</code>&nbsp;attribute because Safari supports HLS natively.</p><h3 id="does-react-support-hls-playback-out-of-the-box">Does React support HLS playback out of the box?</h3><p>React does not support HLS playback out of the box because HLS is a media delivery protocol, not a React feature. You add HLS support by integrating hls.js or a wrapper like React Player, plus feature detection for Safari's native HLS capability.</p><h3 id="what-is-the-difference-between-hlsjs-and-react-player-for-hls">What is the difference between hls.js and React Player for HLS?</h3><p>hls.js is a low-level HLS engine that attaches directly to a video element and exposes full buffer, ABR, and error event configuration. React Player is a higher-level component that supports multiple URL types including HLS, with simpler props but less granular live-stream tuning.</p><h3 id="how-does-videosdk-hls-work-in-a-react-app">How does VideoSDK HLS work in a React app?</h3><p>VideoSDK HLS works by letting a host in CONFERENCE mode call&nbsp;<code>startHls()</code>&nbsp;to begin broadcasting the meeting as an HLS stream. Viewers in VIEWER mode receive&nbsp;<code>hlsUrls.playbackHlsUrl</code>&nbsp;through the&nbsp;<code>useMeeting</code>&nbsp;hook and play that URL in an hls.js-powered player when&nbsp;<code>hlsState</code>&nbsp;reaches&nbsp;<code>HLS_PLAYABLE</code>.</p><h3 id="can-you-reduce-hls-latency-below-5-seconds-in-react">Can you reduce HLS latency below 5 seconds in React?</h3><p>You can reduce HLS latency partially by shortening segment durations and tuning hls.js buffer settings, but standard HLS in React typically remains 10 to 30 seconds behind the live source. For sub-5-second audience delay, use WebRTC or a low-latency streaming mode instead of standard HLS segments.</p><h3 id="why-do-viewers-join-as-viewer-mode-instead-of-conference-mode">Why do viewers join as VIEWER mode instead of CONFERENCE mode?</h3><p>Viewers join as VIEWER mode instead of CONFERENCE mode because VIEWER mode consumes the HLS broadcast without publishing WebRTC media back to the session. This keeps server resources and client bandwidth predictable when hundreds or thousands of people watch a small host panel.</p><h3 id="is-hlsjs-free-to-use-in-commercial-react-applications">Is hls.js free to use in commercial React applications?</h3><p>hls.js is free to use in commercial React applications under its Apache 2.0 open-source license. VideoSDK offers separate pricing for the managed streaming infrastructure that generates HLS URLs, with free tier minutes available for development.</p>]]></content:encoded></item><item><title><![CDATA[How to Migrate Twilio Video to VideoSDK]]></title><description><![CDATA[This migration guide provides a step-by-step transition from Twilio Video to VideoSDK for your real-time communication needs.]]></description><link>https://www.videosdk.live/blog/migrate-twilio-video-to-videosdk</link><guid isPermaLink="false">6571c9a2cbe3c80e020ebb14</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Fri, 10 Jan 2025 14:48:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2023/12/migration_to_videosdk_720.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2023/12/migration_to_videosdk_720.jpg" alt="How to Migrate Twilio Video to VideoSDK"/><p>Integrating video calls into apps (using JavaScript, React, Android, iOS) is a common need, and developers often look for real-time voice and video features. Twilio Video and <a href="https://www.videosdk.live/">VideoSDK</a> are popular platforms, but with Twilio discontinuing Programmable Video, it's crucial to find a reliable alternative. VideoSDK emerges as a <a href="https://www.videosdk.live/blog/twilio-video-competitors">top competitors of Twilio Video</a>, providing a user-friendly API for the seamless integration of robust audio-video features into your apps with minimal code. Its quick integration allows you to focus on enhancing user experience effortlessly.</p><!--kg-card-begin: html--><!DOCTYPE html>
<html lang="en">

<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>Your Page Title</title>
	<!-- Include Tailwind CSS -->
	<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</link></meta></meta></head>

<body>
	<div class="relative w-full overflow-hidden rounded-2xl bg-gradient-to-b from-pink-700 to-purple-900 p-4 text-center shadow-xl">
		<h2 class="mx-auto text-3xl font-bold tracking-tight text-white sm:text-2xl" style="margin-top: 3px; margin-bottom: 12px;">
			Schedule a Demo with Our Live Video Expert!
		</h2>
		<p class="mx-auto mt-3 max-w-xl text-sm text-gray-400">
			Discover how VideoSDK can help you build a cutting-edge real time video app.
			<span class="font-semibold text-lato"/>
		</p>
		<div class="mt-4 flex items-center justify-center">
			<a href="https://www.videosdk.live/contact" class="rounded-md bg-white px-8 py-3 text-sm font-semibold text-gray-900 shadow-sm hover:bg-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-white" target="_blank" style="text-decoration: none;color: black;" data-faitracker-click-bind="true">
				Book a call
			</a>
		</div>
	</div>
</body>

</html><!--kg-card-end: html--><h3 id="videosdk-key-features">VideoSDK Key Features:</h3><p><strong>High Scalability: Reaching New Heights</strong></p><p>Supports up to 300 attendees, and 50 presenters, with global reach and &lt;99ms latency, ensuring uninterrupted large-scale collaborations.</p><p><strong>Adaptive Bitrate</strong>: <strong>A Symphony of Quality</strong></p><p>Offers adaptive bitrate technology for optimal audio-video experiences, auto-adjusting stream quality based on bandwidth and network conditions.</p><p><strong>Customizable SDK</strong>: <strong>Tailored Perfection</strong></p><p>Fully customize UI with end-to-end SDK, accelerate time-to-market with code samples, and build interactive features using PubSub for a tailored user experience.</p><p><strong>Quality Recordings</strong>: <strong>Cinematic Memories</strong></p><p>Supports 1080p video recording with programmable layouts and custom templates. Store recordings on VideoSDK cloud or popular providers like AWS, GCP, or Azure.</p><p><strong>Detailed Analytics</strong>: <strong>Peek Behind the Curtains</strong></p><p>Access in-depth video call metrics for comprehensive session analysis, including participant interactions and duration.</p><p><strong>Cross-Platform Streaming</strong>: <strong>Be Everywhere</strong></p><p>Stream live events on platforms like YouTube, LinkedIn, Facebook, etc., with built-in RTMP support.</p><p><strong>Seamless Scaling</strong>: <strong>Grow Without Limits</strong></p><p>Effortlessly scale live audio/video from a few users to over 10,000 within your web app, reaching millions through RTMP output.</p><p><strong>Platform Support</strong>: <strong>Across the Universe</strong></p><p>Build live video apps for specific platforms and run seamlessly across browsers, devices, and operating systems with minimal development effort.</p><p><strong>And here's the most exciting par</strong>t – <strong>it's FREE</strong> for every developer to kickstart their journey! VideoSDK not only provides a cutting-edge solution but also boasts a pricing structure that effortlessly aligns with the growth of your business. Enjoy a guaranteed <strong>10,000 FREE</strong> minutes<strong> </strong>every month, ensuring that you not only get top-notch quality but also incredible value for your investment.</p><p>We're here to assist you in transitioning from <strong>Twilio Video</strong> to VideoSDK, ensuring a smooth journey as you migrate for powerful voice, video, and streaming integrations. Let's simplify the process together.</p><h2 id="twilio-video-to-videosdk-migration-guide">Twilio Video to <strong>VideoSDK</strong> Migration Guide:</h2><p><strong>Javascript: </strong>Smooth Transition Code</p><p>This migration guide provides a step-by-step transition from using <a href="https://docs.videosdk.live/tutorials/migration-guide-from-twilio-to-videosdk-js-sdk">Twilio Video to VideoSDK on Javascript </a>for your real-time communication needs. The process involves understanding key concepts, setup differences, installation procedures, and code adjustments.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.videosdk.live/tutorials/migration-guide-from-twilio-to-videosdk-js-sdk"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Migration Guide From Twilio Video to Video SDK - Javascript | Video SDK</div><div class="kg-bookmark-description">Explore the seamless transition from Twilio to Video SDK for javascript with our comprehensive migration guide. Elevate your video communication with expert insights and step-by-step instructions.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.videosdk.live/img/icons/favicon.ico" alt="How to Migrate Twilio Video to VideoSDK"><span class="kg-bookmark-author">Video SDK logo</span></img></div></div><div class="kg-bookmark-thumbnail"><img src="https://docs.videosdk.live/img/videosdklive-thumbnail.jpg" alt="How to Migrate Twilio Video to VideoSDK"/></div></a></figure><p><strong>React: </strong>Elevate Your React Experience</p><p>This migration guide provides a step-by-step transition from using <a href="https://docs.videosdk.live/tutorials/migration-guide-from-twilio-to-videosdk-web-edition">Twilio Video to VideoSDK on React</a> for your real-time communication needs. The process involves understanding key concepts, setup differences, installation procedures, and code adjustments.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.videosdk.live/tutorials/migration-guide-from-twilio-to-videosdk-web-edition"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Migration Guide From Twilio Video to Video SDK - React | Video SDK</div><div class="kg-bookmark-description">Easily migrate from Twilio to VideoSDK on React. Our guide provides concise steps for seamless integration, enhancing your app’s video capabilities effortlessly.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.videosdk.live/img/icons/favicon.ico" alt="How to Migrate Twilio Video to VideoSDK"><span class="kg-bookmark-author">Video SDK logo</span></img></div></div><div class="kg-bookmark-thumbnail"><img src="https://docs.videosdk.live/img/videosdklive-thumbnail.jpg" alt="How to Migrate Twilio Video to VideoSDK"/></div></a></figure><p><strong>Android: </strong>Androids, Assemble!</p><p>This migration guide provides a step-by-step transition from using <a href="https://docs.videosdk.live/tutorials/migration-guide-from-twilio-to-videosdk-android-sdk">Twilio Video to VideoSDK on Android</a> for your real-time communication needs. The process involves understanding key concepts, setup differences, installation procedures, and code adjustments.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.videosdk.live/tutorials/migration-guide-from-twilio-to-videosdk-android-sdk"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Migration Guide From Twilio Video to Video SDK - Android | Video SDK</div><div class="kg-bookmark-description">Explore the seamless transition from Twilio to Video SDK for android with our comprehensive migration guide. Elevate your video communication with expert insights and step-by-step instructions.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.videosdk.live/img/icons/favicon.ico" alt="How to Migrate Twilio Video to VideoSDK"><span class="kg-bookmark-author">Video SDK logo</span></img></div></div><div class="kg-bookmark-thumbnail"><img src="https://docs.videosdk.live/img/videosdklive-thumbnail.jpg" alt="How to Migrate Twilio Video to VideoSDK"/></div></a></figure><h3 id="features-map-choosing-excellence-over-good">Features Map: Choosing Excellence Over Good</h3><p>Choose wisely! Delve into the feature map, comparing Twilio Video and VideoSDK. Understand the unique offerings and capabilities of each, aiding your decision-making process based on project requirements.</p><h2 id="faqs">FAQs</h2><p/><p><strong>Q1: Why should I migrate to VideoSDK?</strong></p><p>VideoSDK not only matches Twilio Video but exceeds it with features like high scalability, adaptive bitrate, customizable SDK, and more. It's a strategic move for future-proofing your real-time communication apps.</p><p><br><strong>Q2: Is the migration process complicated?</strong></br></p><p>Not at all! We provide detailed migration guides for Javascript, React, and Android, ensuring a smooth transition without headaches. You'll be up and running in no time.</p><p><br><strong>Q3: What makes VideoSDK stand out?</strong></br></p><p>VideoSDK offers not just quality features but also a generous FREE tier, providing 10,000 minutes every month. It's a cost-effective solution without compromising on excellence.<br/></p><h3 id="conclusion">Conclusion</h3><p>In conclusion, migrating from Twilio Video to VideoSDK marks a strategic move in ensuring the continued success and advancement of your real-time communication applications. With Twilio discontinuing Programmable Video, the transition becomes imperative, and VideoSDK emerges as an exceptional alternative, offering a seamless integration experience across JavaScript, React, Android, and iOS platforms.</p><p>Do you have any questions about switching to VideoSDK? We’d love to help. Contact our <a href="https://www.videosdk.live/support">support team</a> or jump into our <a href="https://discord.com/invite/Qfm8j4YAUJ">Discord community</a> to get started.</p>]]></content:encoded></item><item><title><![CDATA[How to Implement Chat Feature in Flutter Video Call App?]]></title><description><![CDATA[Explore the step-by-step guide on Flutter's video call app with VideoSDK, which enables real-time chat alongside video calls, enhancing collaboration.]]></description><link>https://www.videosdk.live/blog/implement-chat-feature-in-flutter-video-call-app</link><guid isPermaLink="false">661fa3e82a88c204ca9d43aa</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Fri, 10 Jan 2025 09:25:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/Chat-Feature-in-Flutter-Video-Call-App.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/Chat-Feature-in-Flutter-Video-Call-App.jpg" alt="How to Implement Chat Feature in Flutter Video Call App?"/><p>Whether it's sharing important information, asking questions, or simply chatting, participants can engage with each other effortlessly during the video call sessions, integrating a real time chat feature into your <a href="https://www.videosdk.live/blog/video-calling-in-flutter">Flutter video call app</a> improves participant collaboration and communication. You can implement real-time messaging capabilities, using the PubSub (Publish-Subscribe) mechanism, ensuring efficient and scalable message distribution across meetings. </p><p>In this guide, we'll navigate the process of seamlessly integrating real time chat capabilities into your existing flutter video chat app. From establishing the chat environment to managing real time chat interactions within your video call interfaces, we'll cover all the essential steps to augment your app's functionality and user experience.</p><h3 id="benefits-of-implement-chat-feature-in-flutter-video-call-app">Benefits of Implement Chat Feature in Flutter Video Call App</h3><ul><li><strong>Enhanced Collaboration:</strong> Chat enables participants to communicate ideas, share files, and ask questions, fostering collaboration and teamwork.</li><li><strong>Real-time Feedback:</strong> During video calls, users can provide immediate feedback, ask questions, or clarify doubts improving communication efficiency.</li><li><strong>Documentation:</strong> Chat transcripts record discussions and decisions made during meetings, facilitating post-meeting review and follow-up.</li><li><strong>Increased Engagement:</strong> Chat encourages active participation from all participants, even those who might be hesitant to speak up during video calls.</li></ul><h2 id="getting-started-with-videosdk">Getting Started with VideoSDK</h2><p>We must use the capabilities that VideoSDK offers. Before diving into the implementation steps and building the Flutter chat app, let's ensure you complete the necessary prerequisites to integrate the real time chat feature.</p><h3 id="create-a-videosdk-account">Create a VideoSDK Account</h3><p>Go to your <a href="https://app.videosdk.live/dashboard/">VideoSDK dashboard</a> and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.</p><h3 id="generate-your-auth-token">Generate your Auth Token</h3><p>Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token is crucial in authorizing your application to use VideoSDK features. For a more visual understanding of the account creation and token generation process, consider referring to the <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/authentication-and-tokens#1-generating-token-from-dashboard">provided tutorial</a>.</p><h3 id="prerequisites%E2%80%8B">Prerequisites<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#prerequisites">​</a></h3><p>Before proceeding, ensure that your development environment meets the following requirements:</p><ul><li>VideoSDK Developer Account (if you do not have one, follow <a href="https://app.videosdk.live/" rel="noopener noreferrer"><strong>VideoSDK Dashboard</strong></a>)</li><li>The basic understanding of Flutter and Having installed it on your device.</li><li><strong><a href="https://pub.dev/packages/videosdk" rel="noopener noreferrer">Flutter VideoSDK</a></strong></li></ul><h2 id="install-videosdk%E2%80%8B">Install VideoSDK<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#install-video-sdk">​</a></h2><p>Install the VideoSDK using the below-mentioned flutter command. Make sure you are in your Flutter chat app directory before you run this command.</p><pre><code class="language-dart">$ flutter pub add videosdk

//run this command to add http library to perform network call to generate roomId
$ flutter pub add http</code></pre><h3 id="videosdk-compatibility">VideoSDK Compatibility</h3><!--kg-card-begin: html--><table style="border: 1px solid black;">
<thead>
<tr>
<th style="border:1px solid white;">Android and iOS app</th>
<th style="border:1px solid white;">Web</th>
<th style="border:1px solid white;">Desktop app</th>
<th style="border:1px solid white;">Safari browser</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border:1px solid white;"><center> ✅ </center></td>
<td style="border:1px solid white;"><center> ✅ </center></td>
<td style="border:1px solid white;"><center> ✅ </center></td>
<td style="border:1px solid white;"><center> ❌ </center></td>
</tr>
</tbody>
</table>
<!--kg-card-end: html--><h3 id="structure-of-the-project%E2%80%8B">Structure of the project<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#structure-of-the-project">​</a></h3><p>Your project structure should look like this.</p><pre><code class="language-dart">    root
    ├── android
    ├── ios
    ├── lib
         ├── api_call.dart
         ├── join_screen.dart
         ├── main.dart
         ├── meeting_controls.dart
         ├── meeting_screen.dart
         ├── participant_tile.dart</code></pre><p>We are going to create flutter widgets (JoinScreen, MeetingScreen, MeetingControls, and ParticipantTile).</p><h3 id="app-structure%E2%80%8B">App Structure<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#app-structure">​</a></h3><p>The app widget will contain <code>JoinScreen</code> and <code>MeetingScreen</code> widget. <code>MeetingScreen</code> will have <code>MeetingControls</code> and <code>ParticipantTile</code> widget.</p><figure class="kg-card kg-image-card"><img src="https://cdn.videosdk.live/website-resources/docs-resources/flutter_quick_start_arch.png" class="kg-image" alt="How to Implement Chat Feature in Flutter Video Call App?" loading="lazy"/></figure><h3 id="configure-project">Configure Project</h3><h4 id="for-android%E2%80%8B"><br>For Android<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#for-android">​</a></br></h4><ul><li>Update <code>/android/app/src/main/AndroidManifest.xml</code> for the permissions we will be using to implement the audio and video features.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">&lt;uses-feature android:name="android.hardware.camera" /&gt;
&lt;uses-feature android:name="android.hardware.camera.autofocus" /&gt;
&lt;uses-permission android:name="android.permission.CAMERA" /&gt;
&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
&lt;uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /&gt;
&lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /&gt;
&lt;uses-permission android:name="android.permission.INTERNET"/&gt;
&lt;uses-permission android:name="android.permission.FOREGROUND_SERVICE"/&gt;
&lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;</code></pre><figcaption>AndroidManifest.xml</figcaption></figure><ul><li>Also, you will need to set your build settings to Java 8 because the official WebRTC jar now uses static methods in <code>EglBase</code> an interface. Just add this to your app-level <code>/android/app/build.gradle</code>.</li></ul><pre><code class="language-dart">android {
    //...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}</code></pre><ul><li>If necessary, in the same <code>build.gradle</code> you will need to increase <code>minSdkVersion</code> of <code>defaultConfig</code> up to <code>23</code> (currently, the default Flutter generator sets it to <code>16</code>).</li><li>If necessary, in the same <code>build.gradle</code> you will need to increase <code>compileSdkVersion</code> and <code>targetSdkVersion</code> up to <code>33</code> (currently, the default Flutter generator sets it to <code>30</code>).</li></ul><h4 id="for-ios%E2%80%8B">For iOS<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#for-ios">​</a></h4><ul><li>Add the following entries which allow your app to access the camera and microphone of your <code>/ios/Runner/Info.plist</code> file :</li></ul><pre><code class="language-dart">&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Camera Usage!&lt;/string&gt;
&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Microphone Usage!&lt;/string&gt;</code></pre><ul><li>Uncomment the following line to define a global platform for your project in <code>/ios/Podfile</code> :</li></ul><pre><code class="language-dart"># platform :ios, '12.0'</code></pre><h4 id="for-macos%E2%80%8B">For MacOS<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#for-macos">​</a></h4><ul><li>Add the following entries to your <code>/macos/Runner/Info.plist</code> file that allows your app to access the camera and microphone:</li></ul><pre><code class="language-dart">&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Camera Usage!&lt;/string&gt;
&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Microphone Usage!&lt;/string&gt;</code></pre><ul><li>Add the following entries to your <code>/macos/Runner/DebugProfile.entitlements</code> file that allows your app to access the camera, microphone, and open outgoing network connections:</li></ul><pre><code class="language-dart">&lt;key&gt;com.apple.security.network.client&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;com.apple.security.device.camera&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;com.apple.security.device.microphone&lt;/key&gt;
&lt;true/&gt;</code></pre><ul><li>Add the following entries to your <code>/macos/Runner/Release.entitlements</code> file that allows your app to access the camera, microphone, and open outgoing network connections:</li></ul><pre><code class="language-dart">&lt;key&gt;com.apple.security.network.server&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;com.apple.security.network.client&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;com.apple.security.device.camera&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;com.apple.security.device.microphone&lt;/key&gt;
&lt;true/&gt;</code></pre><h2 id="essential-steps-to-implement-video-calling-functionality">Essential Steps to Implement Video Calling Functionality</h2><p>After successfully integrating VideoSDK into your Flutter chat app, you have laid the foundation for real-time audio and video communication. Now, let's take it a step further by integrating the real time chat feature. This will allow users to send messages during a call, providing a convenient way to share quick messages, links, or information.</p><h3 id="step-1-get-started-with-apicalldart%E2%80%8B">Step 1: Get started with <code>api_call.dart</code><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-1-get-started-with-api_calldart">​</a></h3><p>Before jumping to anything else, you will write a function to generate a unique meetingId. You will require an authentication token, you can generate it either by using <a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples" rel="noopener noreferrer">videosdk-rtc-api-server-examples</a> or by generating it from the <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer">VideoSDK Dashboard</a> for development.</p><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'dart:convert';
import 'package:http/http.dart' as http;

//Auth token we will use to generate a meeting and connect to it
String token = "&lt;Generated-from-dashboard&gt;";

// API call to create meeting
Future&lt;String&gt; createMeeting() async {
  final http.Response httpResponse = await http.post(
    Uri.parse("https://api.videosdk.live/v2/rooms"),
    headers: {'Authorization': token},
  );

//Destructuring the roomId from the response
  return json.decode(httpResponse.body)['roomId'];
}</code></pre><figcaption>api_call.dart</figcaption></figure><h3 id="step-2-creating-the-joinscreen%E2%80%8B">Step 2: Creating the JoinScreen<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-2--creating-the-joinscreen">​</a></h3><p>Let's create <code>join_screen.dart</code> file in <code>lib</code> directory and create JoinScreen <code>StatelessWidget</code>.</p><p>The JoinScreen will consist of:</p><ul><li><strong>Create Meeting Button</strong>: This button will create a new meeting for you.</li><li><strong>Meeting ID TextField</strong>: This text field will contain the meeting ID, you want to join.</li><li><strong>Join Meeting Button</strong>: This button will join the meeting, which you have provided.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'api_call.dart';
import 'meeting_screen.dart';

class JoinScreen extends StatelessWidget {
  final _meetingIdController = TextEditingController();

  JoinScreen({super.key});

  void onCreateButtonPressed(BuildContext context) async {
    // call api to create meeting and then navigate to MeetingScreen with meetingId,token
    await createMeeting().then((meetingId) {
      if (!context.mounted) return;
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (context) =&gt; MeetingScreen(
            meetingId: meetingId,
            token: token,
          ),
        ),
      );
    });
  }

  void onJoinButtonPressed(BuildContext context) {
    String meetingId = _meetingIdController.text;
    var re = RegExp("\\w{4}\\-\\w{4}\\-\\w{4}");
    // check meeting id is not null or invaild
    // if meeting id is vaild then navigate to MeetingScreen with meetingId,token
    if (meetingId.isNotEmpty &amp;&amp; re.hasMatch(meetingId)) {
      _meetingIdController.clear();
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (context) =&gt; MeetingScreen(
            meetingId: meetingId,
            token: token,
          ),
        ),
      );
    } else {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
        content: Text("Please enter valid meeting id"),
      ));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('VideoSDK QuickStart'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(12.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () =&gt; onCreateButtonPressed(context),
              child: const Text('Create Meeting'),
            ),
            Container(
              margin: const EdgeInsets.fromLTRB(0, 8.0, 0, 8.0),
              child: TextField(
                decoration: const InputDecoration(
                  hintText: 'Meeting Id',
                  border: OutlineInputBorder(),
                ),
                controller: _meetingIdController,
              ),
            ),
            ElevatedButton(
              onPressed: () =&gt; onJoinButtonPressed(context),
              child: const Text('Join Meeting'),
            ),
          ],
        ),
      ),
    );
  }
}</code></pre><figcaption>join_screen.dart</figcaption></figure><ul><li>Update the home screen of the app in the <code>main.dart</code></li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'join_screen.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'VideoSDK QuickStart',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: JoinScreen(),
    );
  }
}</code></pre><figcaption>main.dart</figcaption></figure><h3 id="step-3-creating-the-meetingcontrols%E2%80%8B">Step 3: Creating the MeetingControls<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-3--creating-the-meetingcontrols">​</a></h3><p>Let's create <code>meeting_controls.dart</code> file and create MeetingControls <code>StatelessWidget</code>.</p><p>The MeetingControls will consist of:</p><ul><li><strong>Leave Button</strong>: This button will leave the meeting.</li><li><strong>Toggle Mic Button</strong>: This button will unmute or mute the mic.</li><li><strong>Toggle Camera Button</strong>: This button will enable or disable the camera.</li></ul><p>MeetingControls will accept 3 functions in the constructor.</p><ul><li><strong><code>onLeaveButtonPressed</code></strong>: invoked when the Leave button is pressed.</li><li><strong><code>onToggleMicButtonPressed</code></strong>: invoked when the toggle mic button is pressed.</li><li><strong><code>onToggleCameraButtonPressed</code></strong>: invoked when the toggle Camera button is pressed.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/material.dart';

class MeetingControls extends StatelessWidget {
  final void Function() onToggleMicButtonPressed;
  final void Function() onToggleCameraButtonPressed;
  final void Function() onLeaveButtonPressed;

  const MeetingControls(
      {super.key,
      required this.onToggleMicButtonPressed,
      required this.onToggleCameraButtonPressed,
      required this.onLeaveButtonPressed});

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        ElevatedButton(
            onPressed: onLeaveButtonPressed, child: const Text('Leave')),
        ElevatedButton(
            onPressed: onToggleMicButtonPressed, child: const Text('Toggle Mic')),
        ElevatedButton(
            onPressed: onToggleCameraButtonPressed,
            child: const Text('Toggle WebCam')),
      ],
    );
  }
}</code></pre><figcaption>meeting_controls.dart</figcaption></figure><h3 id="step-4-creating-participanttile%E2%80%8B">Step 4: Creating ParticipantTile<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-4--creating-participanttile">​</a></h3><p>Let's create <code>participant_tile.dart</code> file and create ParticipantTile <code>StatefulWidget</code>.</p><p>The ParticipantTile will consist of:</p><ul><li><strong>RTCVideoView</strong>: This will show the participant's video stream.</li></ul><p>ParticipantTile will accept <code>Participant</code> in constructor</p><ul><li><strong>participant:</strong> participant of the meeting.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class ParticipantTile extends StatefulWidget {
  final Participant participant;
  const ParticipantTile({super.key, required this.participant});

  @override
  State&lt;ParticipantTile&gt; createState() =&gt; _ParticipantTileState();
}

class _ParticipantTileState extends State&lt;ParticipantTile&gt; {
  Stream? videoStream;

  @override
  void initState() {
    // initial video stream for the participant
    widget.participant.streams.forEach((key, Stream stream) {
      setState(() {
        if (stream.kind == 'video') {
          videoStream = stream;
        }
      });
    });
    _initStreamListeners();
    super.initState();
  }

  _initStreamListeners() {
    widget.participant.on(Events.streamEnabled, (Stream stream) {
      if (stream.kind == 'video') {
        setState(() =&gt; videoStream = stream);
      }
    });

    widget.participant.on(Events.streamDisabled, (Stream stream) {
      if (stream.kind == 'video') {
        setState(() =&gt; videoStream = null);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: videoStream != null
          ? RTCVideoView(
              videoStream?.renderer as RTCVideoRenderer,
              objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
            )
          : Container(
              color: Colors.grey.shade800,
              child: const Center(
                child: Icon(
                  Icons.person,
                  size: 100,
                ),
              ),
            ),
    );
  }
}</code></pre><figcaption>participant_tile.dart</figcaption></figure><h3 id="step-5-creating-the-meetingscreen%E2%80%8B">Step 5: Creating the MeetingScreen<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-5--creating-the-meetingscreen">​</a></h3><p>Let's create <code>meeting_screen.dart</code> file and create MeetingScreen <code>StatefulWidget</code>.</p><p>MeetingScreen will accept meetingId and token in the constructor.</p><ul><li><strong>meetingID:</strong> meetingId, you want to join</li><li><strong>token</strong>: VideoSDK Auth token.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import './participant_tile.dart';

class MeetingScreen extends StatefulWidget {
  final String meetingId;
  final String token;

  const MeetingScreen(
      {super.key, required this.meetingId, required this.token});

  @override
  State&lt;MeetingScreen&gt; createState() =&gt; _MeetingScreenState();
}

class _MeetingScreenState extends State&lt;MeetingScreen&gt; {
  late Room _room;
  var micEnabled = true;
  var camEnabled = true;

  Map&lt;String, Participant&gt; participants = {};

  @override
  void initState() {
    // create room
    _room = VideoSDK.createRoom(
      roomId: widget.meetingId,
      token: widget.token,
      displayName: "John Doe",
      micEnabled: micEnabled,
      camEnabled: camEnabled
    );

    setMeetingEventListener();

    // Join room
    _room.join();

    super.initState();
  }

  // listening to meeting events
  void setMeetingEventListener() {
    _room.on(Events.roomJoined, () {
      setState(() {
        participants.putIfAbsent(
            _room.localParticipant.id, () =&gt; _room.localParticipant);
      });
    });

    _room.on(
      Events.participantJoined,
      (Participant participant) {
        setState(
          () =&gt; participants.putIfAbsent(participant.id, () =&gt; participant),
        );
      },
    );

    _room.on(Events.participantLeft, (String participantId) {
      if (participants.containsKey(participantId)) {
        setState(
          () =&gt; participants.remove(participantId),
        );
      }
    });

    _room.on(Events.roomLeft, () {
      participants.clear();
      Navigator.popUntil(context, ModalRoute.withName('/'));
    });
  }

  // onbackButton pressed leave the room
  Future&lt;bool&gt; _onWillPop() async {
    _room.leave();
    return true;
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () =&gt; _onWillPop(),
      child: Scaffold(
        appBar: AppBar(
          title: const Text('VideoSDK QuickStart'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              Text(widget.meetingId),
              //render all participant
              Expanded(
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: GridView.builder(
                    gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                      crossAxisSpacing: 10,
                      mainAxisSpacing: 10,
                      mainAxisExtent: 300,
                    ),
                    itemBuilder: (context, index) {
                      return ParticipantTile(
                        key: Key(participants.values.elementAt(index).id),
                          participant: participants.values.elementAt(index));
                    },
                    itemCount: participants.length,
                  ),
                ),
              ),
              MeetingControls(
                onToggleMicButtonPressed: () {
                  micEnabled ? _room.muteMic() : _room.unmuteMic();
                  micEnabled = !micEnabled;
                },
                onToggleCameraButtonPressed: () {
                  camEnabled ? _room.disableCam() : _room.enableCam();
                  camEnabled = !camEnabled;
                },
                onLeaveButtonPressed: () {
                  _room.leave()
                },
              ),
            ],
          ),
        ),
      ),
      home: JoinScreen(),
    );
  }
}</code></pre><figcaption>meeting_screen.dart</figcaption></figure><blockquote><strong>CAUTION</strong><br>If you get <code>webrtc/webrtc.h </code> file not found error at a runtime in iOS, then check the solution <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/known-issues#issue--1" rel="noopener noreferrer">here</a>.</br></blockquote><blockquote><strong>TIP</strong>:<br>You can checkout the complete <a href="https://github.com/videosdk-live/quickstart/tree/main/flutter-rtc" rel="noopener noreferrer">quick start example here</a>.</br></blockquote><h2 id="integrate-chat-feature">Integrate Chat Feature</h2><p>For communication or any kind of messaging between the participants, VideoSDK provides <code>pubSub</code> mechanism and can be used to develop a wide variety of functionalities. For example, participants could use it to send messages to each other, share files or other media, or even trigger actions like muting or unmuting audio or video.</p><p>Now we will see, how we can use PubSub to implement real time chat functionality. If you are not familiar with the PubSub mechanism, you can <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/pubsub">follow this guide</a>.</p><h3 id="group-chat">Group Chat</h3><p>The first step in creating a group chat is choosing the topic that all the participants will publish and subscribe to send and receive the messages. We will be using <code>CHAT</code> this as the topic for this one. So let us create a message input and send button to publish the messages using the <code>pubSub</code> from the <code>Room</code> object.</p><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class ChatView extends StatefulWidget {
  final Room room;
  ...
}

class _ChatViewState extends State&lt;ChatView&gt; {

  final msgTextController = TextEditingController();


  @override
  void initState() {
    ...

    // Subscribing 'CHAT' Topic
    widget.room.pubSub
      .subscribe("CHAT", messageHandler)
      .then((value) =&gt; setState((() =&gt; messages = value)));
  }

  //Handler which will be called when new mesasge is received
  void messageHandler(PubSubMessage message) {
    setState(() =&gt; messages!.messages.add(message));
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children:[
        Row(
          children: [
            Expanded(
              child: TextField(
                style: TextStyle(
                  fontSize:16,
                  fontWeight: FontWeight.w500,
                ),
                controller: msgTextController,
                onChanged: (value) =&gt; setState(() {
                  msgTextController.text;
                }),
                decoration: const InputDecoration(
                  hintText: "Write your message",
                  border: InputBorder.none,
                ),
              ),
            ),
            ElevatedButton(
              onPressed:(){
                if(!msgTextController.text.trim().isEmpty){
                  widget.room.pubSub
                        .publish(
                          "CHAT",
                          msgTextController.text,
                          const PubSubPublishOptions(
                              persist: true),
                        )
                        .then(
                            (value) =&gt; msgTextController.clear())
                }
              },
              child: const Text("Send Message"),
            ),
          ],
        ),
      ]
    );
  }

}</code></pre><p>The final step in the group chat would be to display the messages others send. For this will use the <code>messages</code> and display all the messages by subscribing to the topic <code>CHAT</code>.</p><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class ChatView extends StatefulWidget {
  final Room room;
  ...
}

class _ChatViewState extends State&lt;ChatView&gt; {

  // PubSubMessages
  PubSubMessages? messages;

  @override
  void initState() {
    ...

    // Subscribing 'CHAT' Topic
    widget.room.pubSub
      .subscribe("CHAT", messageHandler)
      .then((value) =&gt; setState((() =&gt; messages = value)));
  }

  //Handler which will be called when new mesasge is received
  void messageHandler(PubSubMessage message) {
    setState(() =&gt; messages!.messages.add(message));
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children:[
        Expanded(
          child: messages == null
              ? const Center(child: CircularProgressIndicator())
              : SingleChildScrollView(
                  reverse: true,
                  child: Column(
                    children: messages!.messages
                        .map(
                          (message) =&gt; Text(
                            message.message
                          ),
                        )
                        .toList(),
                  ),
                ),
        ),

        ...
        //Send Message code Here
      ]
    );
  }

  @override
  void dispose() {
    // Unsubscribe
    widget.room.pubSub.unsubscribe("CHAT", messageHandler);
    super.dispose();
  }
}</code></pre><p>Now let us open this <code>ChatView</code> widget on a button click from our meeting screen.</p><pre><code class="language-dart">import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import './participant_tile.dart';
import './ChatView.dart';

class MeetingScreen extends StatefulWidget {
  final String meetingId;
  final String token;

  const MeetingScreen(
      {super.key, required this.meetingId, required this.token});

  @override
  State&lt;MeetingScreen&gt; createState() =&gt; _MeetingScreenState();
}

class _MeetingScreenState extends State&lt;MeetingScreen&gt; {
   
  // Other code here... 
  
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () =&gt; _onWillPop(),
      child: Scaffold(
        appBar: AppBar(
          title: const Text('VideoSDK QuickStart'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              // Other meeting widgets ...
              
              ElevatedButton(
                onPressed: (){
                	showModalBottomSheet(
                    context: context,
                    isScrollControlled: true,
                    builder: (context) =&gt; ChatView(
                        key: const Key("ChatScreen"),
                        meeting: widget.room),
                    ));
                },
                child: const Text('Open')),
            ],
          ),
        ),
      ),
      home: JoinScreen(),
    );
  }
}</code></pre><h3 id="private-chat">Private Chat</h3><p>In the above example, if you want to convert into a private chat between two participants, then all you have to do is pass <code>sendOnly</code> parameter in <code>PubSubPublishOptions</code>.</p><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class ChatView extends StatefulWidget {
  final Room room;
  ...
}

class _ChatViewState extends State&lt;ChatView&gt; {

  //...

  @override
  Widget build(BuildContext context) {
    return Column(
      children:[
        Row(
          children: [
            Expanded(
              child: TextField(
                style: TextStyle(
                  fontSize:16,
                  fontWeight: FontWeight.w500,
                ),
                controller: msgTextController,
                onChanged: (value) =&gt; setState(() {
                  msgTextController.text;
                }),
                decoration: const InputDecoration(
                  hintText: "Write your message",
                  border: InputBorder.none,
                ),
              ),
            ),
            ElevatedButton(
              onPressed:(){
                if(!msgTextController.text.trim().isEmpty){
                  // Pass the participantId of the participant to whom you want to send the message.
                  widget.room.pubSub
                        .publish(
                          "CHAT",
                          msgTextController.text,
                          const PubSubPublishOptions(
                            persist: true, sendOnly: ["xyz"]),
                        )
                        .then(
                            (value) =&gt; msgTextController.clear())
                }
              },
              child: const Text("Send Message"),
            ),
          ],
        ),
      ]
    );
  }

}</code></pre><h3 id="displaying-the-latest-message-notification">Displaying the Latest Message Notification</h3><p>You may want to show the notification to the user when a new message arrives. So let's continue our example and add an alert for the new images.</p><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class ChatView extends StatefulWidget {
  final Room room;
  ...
}

class _ChatViewState extends State&lt;ChatView&gt; {

  @override
  void initState() {
    ...
  }

  //Handler which will be called when new mesasge is received
  void messageHandler(PubSubMessage message) {
    //Show snackbar on new message
    if(context.mounted){
      ScaffoldMessenger.of(context).showSnackBar(SnackBar(
        content: Text(
          message.message,
          overflow: TextOverflow.fade,
        ),
      ));
    }
    setState(() =&gt; messages!.messages.add(message));
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children:[
        ...
      ]
    );
  }

  @override
  void dispose() {
    ...
  }
}</code></pre><h3 id="downloading-chat-messages">Downloading Chat Messages</h3><p>All the messages from the PubSub were published  <code>persist : true</code> and can be downloaded as a <code>.csv</code> file. This file will be available in the VideoSDK dashboard as well as through the <a href="https://docs.videosdk.live/api-reference/realtime-communication/fetch-session-using-sessionid">Sessions API</a>.</p><p>In Flutter's real-time chat feature, combine real-time voice and video with asynchronous text messaging, accommodating various communication preferences and scenarios with the functionality provided by <a href="https://www.videosdk.live/">VideoSDK</a>. With the guidance offered in this tutorial, you can develop a user-friendly video-calling platform that enables users to connect in innovative ways.</p><p>Now if you have just started to build or integrate new features with VideoSDK, you can unlock the full potential of VideoSDK today and build personalized video experiences! Just <a href="https://app.videosdk.live/dashboard">Sign up</a> now and receive <strong>10,000 free minutes</strong> and take your video app to new heights.</p>]]></content:encoded></item><item><title><![CDATA[How to Integrate Screen Share in Android(Java) Video Chat App?]]></title><description><![CDATA[This Expert guide is about your Android video app with the powerful Screen Share feature integration in Android(Java) using VideoSDK.]]></description><link>https://www.videosdk.live/blog/how-to-integrate-screen-share-in-java-video-chat-app-for-android</link><guid isPermaLink="false">65fd0f0b2a88c204ca9cef67</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[Android]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Thu, 09 Jan 2025 12:55:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/Screen-Share--Java-2.png" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/Screen-Share--Java-2.png" alt="How to Integrate Screen Share in Android(Java) Video Chat App?"/><p>Ever need to show others exactly what's on your mobile screen during a video call? If your answer is 'Yes!', then you need to know that this very important feature is called Screen Sharing. Screen sharing is the process of showing your smartphone screen to the other participants. It enables everyone in the conference to view precisely what you see on your screen, which is useful for presentations, demos, and collaborations. </p><p>Integrating the Screen Share feature into your video app offers various possibilities for improved collaboration and communication. Whether delivering presentations or collaborating on projects, the Screen Share functionality allows users to easily share their displays during video calls. </p><p>Android developers may create compelling and interactive video experiences for users by following the steps below and leveraging VideoSDK's capabilities. Start implementing the Screen Share feature immediately to transform your video app's functionality and user engagement.</p><h2 id="goals">Goals</h2><p>By the End of this Article:</p><ol><li>Create a <a href="https://www.videosdk.live/signup">VideoSDK account</a> and generate your VideoSDK auth token.</li><li>Integrate the VideoSDK library and dependencies into your project.</li><li>Implement core functionalities for video calls using VideoSDK</li><li>Enable/Disable Screen Share Functionality</li></ol><h2 id="getting-started-with-videosdk">Getting Started with VideoSDK</h2><p>To take advantage of the screen share functionality, we will need to use the capabilities that the VideoSDK offers. Before we dive into the implementation steps, let's make sure you complete the necessary prerequisites.</p><h3 id="create-a-videosdk-account">Create a VideoSDK Account</h3><p>Go to your <a href="https://app.videosdk.live/dashboard/">VideoSDK dashboard</a> and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.</p><h3 id="generate-your-auth-token">Generate your Auth Token</h3><p>Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token plays a crucial role in authorizing your application to use VideoSDK features.</p><p>For a more visual understanding of the account creation and token generation process, consider referring to the <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/authentication-and-token#1-generating-token-from-dashboard">provided tutorial</a>.</p><h3 id="prerequisites-and-setup">Prerequisites and Setup</h3><p>Make sure your development environment meets the following requirements:</p><ul><li>Java Development Kit is supported.</li><li>Android Studio version 3.0 or later.</li><li>Android SDK API level 21 or higher.</li><li>A mobile device with Android 5.0 or later version.</li></ul><h2 id="integrate-videosdk">Integrate VideoSDK</h2><p>Following the account creation and token generation steps, we'll guide you through the process of adding the VideoSDK library and other dependencies to your project. We'll also ensure your app has the required permissions to access features like audio recording, camera usage, and internet connectivity, all crucial for a seamless video experience.</p><h3 id="step-a-add-the-repositories-to-the-projects-settingsgradle-file">Step (a): Add the repositories to the project's <code>settings.gradle</code> file.</h3><pre><code class="language-xml">dependencyResolutionManagement{
  repositories {
    // ...
    google()
    mavenCentral()
    maven { url 'https://jitpack.io' }
    maven { url "https://maven.aliyun.com/repository/jcenter" }
  }
}
</code></pre><h3 id="step-b-include-the-following-dependency-within-your-applications-buildgradle-file">Step (b): Include the following dependency within your application's <code>build.gradle</code> file:</h3><pre><code class="language-xml">dependencies {
  implementation 'live.videosdk:rtc-android-sdk:0.1.26'

  // library to perform Network call to generate a meeting id
  implementation 'com.amitshekhar.android:android-networking:1.0.2'

  // Other dependencies specific to your app
}
</code></pre><blockquote>If your project has set <code>android.useAndroidX=true</code>, then set <code>android.enableJetifier=true</code> in the <code>gradle.properties</code> file to migrate your project to AndroidX and avoid duplicate class conflict.</blockquote><h3 id="step-c-add-permissions-to-your-project">Step (c): Add permissions to your project</h3><p>In <code>/app/Manifests/AndroidManifest.xml</code>, add the following permissions after <code>&lt;/application&gt;</code>.</p><pre><code class="language-xml">&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.INTERNET" /&gt;
&lt;uses-permission android:name="android.permission.CAMERA" /&gt;
</code></pre><p>These permissions are essential for enabling core functionalities like audio recording, internet connectivity for real-time communication, and camera access for video streams within your video application.</p><h2 id="essential-steps-for-building-the-video-calling-functionality">Essential Steps for Building the Video Calling Functionality</h2><p>We'll now delve into the functionalities that make your video application after set up your project with VideoSDK. This section outlines the essential steps for implementing core functionalities within your app.</p><p>This section will guide you through four key aspects:</p><h3 id="step-1-generate-a-meetingid">Step 1: Generate a <code>meetingId</code></h3><p>Now, we can create the <code>meetingId</code> from the VideoSDK's rooms API. You can refer to this <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/setup-call/initialize-meeting#generating-meeting-id">documentation</a> to generate meetingId.</p><h3 id="step-2-initializing-the-meeting">Step 2: Initializing the Meeting</h3><p>After getting <code>meetingId</code> , the next step involves initializing the meeting for that we need to,</p><ol><li>Initialize VideoSDK.</li><li>Configure <strong>VideoSDK</strong> with a token.</li><li>Initialize the meeting with required params such as <code>meetingId</code>, <code>participantName</code>, <code>micEnabled</code>, <code>webcamEnabled</code> and more.</li><li>Add <code>MeetingEventListener</code> for listening events such as Meeting Join/Left and Participant Join/Left.</li><li>Join the room with <code>meeting.join()</code> a method.</li></ol><p>Please copy the .xml file of the <code>MeetingActivity</code> from <a href="https://github.com/videosdk-live/quickstart/blob/main/android-rtc/Videosdk_android_kotlin_quickstart/app/src/main/res/layout/activity_meeting.xml"><strong>here</strong></a>.</p><pre><code class="language-Java">public class MeetingActivity extends AppCompatActivity {
  // declare the variables we will be using to handle the meeting
  private Meeting meeting;
  private boolean micEnabled = true;
  private boolean webcamEnabled = true;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_meeting);

    final String token = ""; // Replace with the token you generated from the VideoSDK Dashboard
    final String meetingId = ""; // Replace with the meetingId you have generated
    final String participantName = "John Doe";

    // 1. Initialize VideoSDK
    VideoSDK.initialize(applicationContext);

    // 2. Configuration VideoSDK with Token
    VideoSDK.config(token);

    // 3. Initialize VideoSDK Meeting
    meeting = VideoSDK.initMeeting(
            MeetingActivity.this, meetingId, participantName,
            micEnabled, webcamEnabled,null, null, false, null, null);

    // 4. Add event listener for listening upcoming events
    meeting.addEventListener(meetingEventListener);

    // 5. Join VideoSDK Meeting
    meeting.join();

    ((TextView)findViewById(R.id.tvMeetingId)).setText(meetingId);
  }

  // creating the MeetingEventListener
  private final MeetingEventListener meetingEventListener = new MeetingEventListener() {
    @Override
    public void onMeetingJoined() {
      Log.d("#meeting", "onMeetingJoined()");
    }

    @Override
    public void onMeetingLeft() {
      Log.d("#meeting", "onMeetingLeft()");
      meeting = null;
      if (!isDestroyed()) finish();
    }

    @Override
    public void onParticipantJoined(Participant participant) {
      Toast.makeText(MeetingActivity.this, participant.getDisplayName() + " joined", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onParticipantLeft(Participant participant) {
      Toast.makeText(MeetingActivity.this, participant.getDisplayName() + " left", Toast.LENGTH_SHORT).show();
    }
  };
}</code></pre><h3 id="step-3-handle-local-participant-media">Step 3: Handle Local Participant Media</h3><p>After successfully entering the meeting, it's time to manage the webcam and microphone for the local participant (you).</p><p>To enable or disable the webcam, we'll use the <code>Meeting</code> class methods <code>enableWebcam()</code> and <code>disableWebcam()</code>, respectively. Similarly, to mute or unmute the microphone, we'll utilize the methods <code>muteMic()</code> and <code>unmuteMic()</code></p><pre><code class="language-Java">public class MeetingActivity extends AppCompatActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_meeting);
    //...Meeting Setup is Here

    // actions
    setActionListeners();
  }

  private void setActionListeners() {
    // toggle mic
    findViewById(R.id.btnMic).setOnClickListener(view -&gt; {
      if (micEnabled) {
        // this will mute the local participant's mic
        meeting.muteMic();
        Toast.makeText(MeetingActivity.this, "Mic Disabled", Toast.LENGTH_SHORT).show();
      } else {
        // this will unmute the local participant's mic
        meeting.unmuteMic();
        Toast.makeText(MeetingActivity.this, "Mic Enabled", Toast.LENGTH_SHORT).show();
      }
      micEnabled=!micEnabled;
    });

    // toggle webcam
    findViewById(R.id.btnWebcam).setOnClickListener(view -&gt; {
      if (webcamEnabled) {
        // this will disable the local participant webcam
        meeting.disableWebcam();
        Toast.makeText(MeetingActivity.this, "Webcam Disabled", Toast.LENGTH_SHORT).show();
      } else {
        // this will enable the local participant webcam
        meeting.enableWebcam();
        Toast.makeText(MeetingActivity.this, "Webcam Enabled", Toast.LENGTH_SHORT).show();
      }
      webcamEnabled=!webcamEnabled;
    });

    // leave meeting
    findViewById(R.id.btnLeave).setOnClickListener(view -&gt; {
      // this will make the local participant leave the meeting
      meeting.leave();
    });
  }
}</code></pre><h3 id="step-4-handling-the-participants-view">Step 4: Handling the Participants' View</h3><p>To display a list of participants in your video UI, we'll utilize a <code>RecyclerView</code>.</p><p><strong>(a)</strong> This involves creating a new layout for the participant view named <code>item_remote_peer.xml</code> in the <code>res/layout</code> folder. You can copy <code>item_remote_peer.xml </code>file from <a href="https://github.com/videosdk-live/quickstart/blob/main/android-rtc/Videosdk_android_kotlin_quickstart/app/src/main/res/layout/item_remote_peer.xml">here</a>.</p><p><strong>(b)</strong> Create a RecyclerView adapter <code>ParticipantAdapter</code> which will be responsible for displaying the participant list. Within this adapter, define a <code>PeerViewHolder</code> class that extends <code>RecyclerView.ViewHolder</code>.</p><pre><code class="language-Java">public class ParticipantAdapter extends RecyclerView.Adapter&lt;ParticipantAdapter.PeerViewHolder&gt; {

  @NonNull
  @Override
  public PeerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
      return new PeerViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_remote_peer, parent, false));
  }

  @Override
  public void onBindViewHolder(@NonNull PeerViewHolder holder, int position) {
  }

  @Override
  public int getItemCount() {
      return 0;
  }

  static class PeerViewHolder extends RecyclerView.ViewHolder {
    // 'VideoView' to show Video Stream
    public VideoView participantView;
    public TextView tvName;
    public View itemView;

    PeerViewHolder(@NonNull View view) {
        super(view);
        itemView = view;
        tvName = view.findViewById(R.id.tvName);
        participantView = view.findViewById(R.id.participantView);
    }
  }
}</code></pre><p><strong>(c)</strong> Now, we will render a list of <code>Participant</code> for the meeting. We will initialize this list in the constructor of the <code>ParticipantAdapter</code></p><pre><code class="language-Java">public class ParticipantAdapter extends RecyclerView.Adapter&lt;ParticipantAdapter.PeerViewHolder&gt; {

  // creating a empty list which will store all participants
  private final List&lt;Participant&gt; participants = new ArrayList&lt;&gt;();

  public ParticipantAdapter(Meeting meeting) {
    // adding the local participant(You) to the list
    participants.add(meeting.getLocalParticipant());

    // adding Meeting Event listener to get the participant join/leave event in the meeting.
    meeting.addEventListener(new MeetingEventListener() {
      @Override
      public void onParticipantJoined(Participant participant) {
        // add participant to the list
        participants.add(participant);
        notifyItemInserted(participants.size() - 1);
      }

      @Override
      public void onParticipantLeft(Participant participant) {
        int pos = -1;
        for (int i = 0; i &lt; participants.size(); i++) {
          if (participants.get(i).getId().equals(participant.getId())) {
            pos = i;
            break;
          }
        }
        // remove participant from the list
        participants.remove(participant);

        if (pos &gt;= 0) {
          notifyItemRemoved(pos);
        }
      }
    });
  }

  // replace getItemCount() method with following.
  // this method returns the size of total number of participants
  @Override
  public int getItemCount() {
    return participants.size();
  }
  //...
}</code></pre><p><strong>(d)</strong> We have listed our participants. Let's set up the view holder to display a participant video.</p><pre><code class="language-Java">public class ParticipantAdapter extends RecyclerView.Adapter&lt;ParticipantAdapter.PeerViewHolder&gt; {

  // replace onBindViewHolder() method with following.
  @Override
  public void onBindViewHolder(@NonNull PeerViewHolder holder, int position) {
    Participant participant = participants.get(position);

    holder.tvName.setText(participant.getDisplayName());

    // adding the initial video stream for the participant into the 'VideoView'
    for (Map.Entry&lt;String, Stream&gt; entry : participant.getStreams().entrySet()) {
      Stream stream = entry.getValue();
      if (stream.getKind().equalsIgnoreCase("video")) {
        holder.participantView.setVisibility(View.VISIBLE);
        VideoTrack videoTrack = (VideoTrack) stream.getTrack();
        holder.participantView.addTrack(videoTrack)
        break;
      }
    }
    // add Listener to the participant which will update start or stop the video stream of that participant
    participant.addEventListener(new ParticipantEventListener() {
      @Override
      public void onStreamEnabled(Stream stream) {
        if (stream.getKind().equalsIgnoreCase("video")) {
          holder.participantView.setVisibility(View.VISIBLE);
          VideoTrack videoTrack = (VideoTrack) stream.getTrack();
          holder.participantView.addTrack(videoTrack)
        }
      }

      @Override
      public void onStreamDisabled(Stream stream) {
        if (stream.getKind().equalsIgnoreCase("video")) {
          holder.participantView.removeTrack();
          holder.participantView.setVisibility(View.GONE);
        }
      }
    });
  }
}</code></pre><p><strong>(e)</strong> Now, add this adapter to the <code>MeetingActivity</code></p><pre><code class="language-Java">@Override
protected void onCreate(Bundle savedInstanceState) {
  //Meeting Setup...
  //...
  final RecyclerView rvParticipants = findViewById(R.id.rvParticipants);
  rvParticipants.setLayoutManager(new GridLayoutManager(this, 2));
  rvParticipants.setAdapter(new ParticipantAdapter(meeting));
}</code></pre><h2 id="screen-share-feature-integration">Screen Share Feature Integration</h2><p>The screen share feature enhances the collaborative experience in video conferences by allowing participants to share their screens with others. Integrating screen share functionality into your video app using VideoSDK is straightforward and can significantly enhance the usability and effectiveness of your application.</p><p>Let's walk through the steps to enable screen-sharing functionality using VideoSDK.</p><h3 id="how-does-screen-share-work%E2%80%8B">How does Screen Share work?<a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/handling-media/screen-share#how-screen-share-works">​</a></h3><p>The following diagram shows the flow of screen sharing in Android using VideoSDK :</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/flow_diagram-babfdcf534c77239e38b3a11d005def6.png" class="kg-image" alt="How to Integrate Screen Share in Android(Java) Video Chat App?" loading="lazy" width="674" height="826"/></figure><h3 id="enable-screen-sharing">Enable Screen Sharing</h3><p>To initiate screen sharing, utilize the <code>enableScreenShare()</code> function within the Meeting class. This enables the local participants to share their mobile screens with other participants seamlessly.</p><ul><li>You can pass customized screen share track in <code>enableScreenShare()</code> by using <a href="https://docs.videosdk.live/android/guide/video-and-audio-calling-api-sdk/render-media/optimize-video-track#custom-screen-share-track">Custom Screen Share Track</a>.</li><li>Screen Share stream of the participant can be accessed from the <code>onStreamEnabled</code> event of <code>ParticipantEventListener</code>.</li></ul><!--kg-card-begin: markdown--><h4 id="screenshare-permission%E2%80%8B">Screenshare permission​</h4>
<!--kg-card-end: markdown--><ul><li>Before commencing screen sharing, it's crucial to address screen share permissions. The participant's screen share stream is facilitated through the <code>MediaProjection</code> API, compatible only with <code>Build.VERSION_CODES.LOLLIPOP</code> or higher.</li><li>To attain permission for screen sharing, acquire an instance of the <code>MediaProjectionManager</code> and invoke the <code>createScreenCaptureIntent()</code> method within an activity. This prompts a dialog for the user to authorize screen projection. </li></ul><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/user_permission-d3adf623ea99e011b2b069031f2570be.jpg" class="kg-image" alt="How to Integrate Screen Share in Android(Java) Video Chat App?" loading="lazy"/></figure><ul><li>Following the permission grant, proceed to call the <code>enableScreenShare()</code> method.</li></ul><pre><code class="language-java">private void enableScreenShare() {
    MediaProjectionManager mediaProjectionManager =
        (MediaProjectionManager) getApplication().getSystemService(
            Context.MEDIA_PROJECTION_SERVICE);
    startActivityForResult(
        mediaProjectionManager.createScreenCaptureIntent(), CAPTURE_PERMISSION_REQUEST_CODE);
}

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode != CAPTURE_PERMISSION_REQUEST_CODE)
        return;
    if (resultCode == Activity.RESULT_OK) {
        // Enabling screen share
        meeting.enableScreenShare(data);
    }
}
</code></pre><!--kg-card-begin: markdown--><h4 id="customize-notification">Customize notification</h4>
<!--kg-card-end: markdown--><ul><li>Upon initiating screen sharing, the presenter will receive a notification featuring a predefined title and message. Notification with pre-defined title and message will look like this:</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/03/notification-screenshare-android.jpg" class="kg-image" alt="How to Integrate Screen Share in Android(Java) Video Chat App?" loading="lazy" width="600" height="531"/></figure><ul><li>You can Customise those titles, messages, and icons as per your requirements using <code>&lt;meta-data&gt;</code> specified in <code>app/src/main/AndroidManifest.xml</code>.</li><li>The notification appearance can be customized to align with specific requirements by modifying the titles, messages, and icons using <code>&lt;meta-data&gt;</code> specified in <code>app/src/main/AndroidManifest.xml</code>.</li></ul><pre><code class="language-java">&lt;application&gt;
  &lt;meta-data
    android:name="notificationTitle"
    android:value="@string/notificationTitle"
  /&gt;
  &lt;meta-data
    android:name="notificationContent"
    android:value="@string/notificationContent"
  /&gt;
  &lt;meta-data
    android:name="notificationIcon"
    android:resource="@mipmap/ic_launcher_round"
  /&gt;
&lt;/application&gt;</code></pre><h3 id="disable-screen-sharing">Disable Screen Sharing</h3><p>You have to employ the <code>disableScreenShare()</code> function from the <code>Meeting</code> class. This action enables the local participant to halt sharing their mobile screen with other participants.</p><pre><code class="language-java">private void disableScreenShare(){
    // Disabling screen share
    meeting.disableScreenShare();
}</code></pre><h3 id="events-associated-with-screen-sharing"><strong>Events Associated with Screen Sharing</strong></h3><!--kg-card-begin: markdown--><h4 id="events-associated-with-enablescreenshare%E2%80%8B">Events associated with <code>enableScreenShare</code>​</h4>
<!--kg-card-end: markdown--><ul><li>The participant who shares their mobile screen will receive a callback on <a href="https://docs.videosdk.live/android/api/sdk-reference/participant-class/participant-event-listener-class#onstreamenabled"><code>onStreamEnabled()</code></a> of the <a href="https://docs.videosdk.live/android/api/sdk-reference/participant-class/introduction"><code>Participant</code></a> with <code>Stream</code> object.</li><li>While other Participants will receive <a href="https://docs.videosdk.live/android/api/sdk-reference/meeting-class/meeting-event-listener-class#onpresenterchanged"><code>onPresenterChanged()</code></a> callback of the <a href="https://docs.videosdk.live/android/api/sdk-reference/meeting-class/introduction"><code>Meeting</code></a> class with the participantId as <code>presenterId</code> who started the screen share.</li><li>The participant who shared their mobile screen will receive a callback on <a href="https://docs.videosdk.live/android/api/sdk-reference/participant-class/participant-event-listener-class#onstreamdisabled"><code>onStreamDisabled()</code></a> of the <a href="https://docs.videosdk.live/android/api/sdk-reference/participant-class/introduction"><code>Participant</code></a> with Stream object.</li><li>While other Participants will receive <a href="https://docs.videosdk.live/android/api/sdk-reference/meeting-class/meeting-event-listener-class#onpresenterchanged"><code>onPresenterChanged()</code></a> callback of the <a href="https://docs.videosdk.live/android/api/sdk-reference/meeting-class/introduction"><code>Meeting</code></a> class with the <code>presenterId</code> as <code>null</code> indicating there is no presenter.</li></ul><!--kg-card-begin: markdown--><h4 id="events-associated-with-disablescreenshare%E2%80%8B">Events associated with <code>disableScreenShare</code>​</h4>
<!--kg-card-end: markdown--><pre><code class="language-java">private void setLocalListeners() {
    meeting.getLocalParticipant().addEventListener(new ParticipantEventListener() {
        //Callback for when the participant starts a stream
        @Override
        public void onStreamEnabled(Stream stream) {
            if (stream.getKind().equalsIgnoreCase("share")) {
                Log.d("VideoSDK","Share Stream On: onStreamEnabled" + stream);
            }
        }

        //Callback for when the participant stops a stream
        @Override
        public void onStreamDisabled(Stream stream) {
            if (stream.getKind().equalsIgnoreCase("share")) {
                Log.d("VideoSDK","Share Stream Off: onStreamDisabled" + stream);
            }
        }
    });
}

private final MeetingEventListener meetingEventListener = new MeetingEventListener() {
    //Callback for when the presenter changes
    @Override
    public void onPresenterChanged(String participantId) {
      if(participantId != null){
        Log.d("VideoSDK",participantId + "started screen share");
      }else{
        Log.d("VideoSDK","some one stopped screen share");
      }
    }
};</code></pre><p>That's it. Following these steps will allow you to effortlessly implement screen-share capability into your video app, increasing its adaptability and usefulness for users across a wide range of use cases. </p><p>For an in-depth exploration of the code snippets along with thorough explanations, I highly recommend delving into the <a href="https://github.com/videosdk-live/videosdk-rtc-android-kotlin-sdk-example" rel="noopener noreferrer">GitHub repository</a>. By navigating through the repository, you'll gain access to the complete set of code snippets, accompanied by detailed explanations that shed light on their functionality and implementation.</p><h2 id="conclusion"><strong>Conclusion</strong></h2><p>We have discussed the essential steps for integrating the screen share feature into your Android video app using VideoSDK. By following these steps, You may improve the collaborative experience of your video apps, allowing users to effortlessly exchange information during video conferences. </p><p>Screen sharing feature not only increases user engagement but also extends the number of use cases for video communication services, making them more adaptable and beneficial to users. Adding the screen-sharing functionality to your video app now opens up new avenues for collaboration and communication. </p><p><a href="https://www.videosdk.live/signup"><strong>Sign up with VideoSDK</strong></a> today and Get <strong>10000 Free Minutes to </strong>take your video app to the next level!</p>]]></content:encoded></item><item><title><![CDATA[Integrate Pre-Call Check in React]]></title><description><![CDATA[Discover how to implement Precall Integration in React SDK. Our comprehensive guide helps you enhance your app's communication capabilities, ensuring smooth and efficient user interactions.]]></description><link>https://www.videosdk.live/blog/precall-integration-in-react</link><guid isPermaLink="false">6683fe8420fab018df10f5bb</guid><category><![CDATA[React]]></category><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Thu, 09 Jan 2025 09:45:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/07/Pre-Call-Check-React.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://assets.videosdk.live/static-assets/ghost/2024/07/Pre-Call-Check-React.jpg" alt="Integrate Pre-Call Check in React"/><p>Picture this: before diving into the depths of a video call, imagine giving your setup a quick check-up, like a tech-savvy doctor ensuring all systems are a go. That's essentially what a precall experience does- it’s like your extensive debug session before the main code execution—a crucial step in ensuring your app's performance is top-notch.</p><h2 id="why-is-it-necessary%E2%80%8B"><strong>Why is it necessary?</strong><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/setup-call/precall#why-is-it-necessary">​</a></h2><p>Why invest time and effort into crafting a precall experience, you wonder? Well, picture this scenario: your users eagerly join a video call, only to encounter a myriad of technical difficulties—muted microphones, pixelated cameras, and laggy connections. Not exactly the smooth user experience you had in mind, right?</p><p>By integrating a robust precall process into your app, developers become the unsung heroes, preemptively addressing potential pitfalls and ensuring that users step into their video calls with confidence.</p><h2 id="step-by-step-guide-integrating-precall-feature%E2%80%8B"><strong>Step-by-Step Guide: Integrating Precall Feature</strong><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/setup-call/precall#step-by-step-guide-integrating-precall-feature">​</a></h2><h3 id="step-1-check-permissions%E2%80%8B"><strong>Step 1: Check Permissions</strong><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/setup-call/precall#step-1-check-permissions">​</a></h3><ul><li>Begin by ensuring that your application has the necessary permissions to access user devices such as cameras, microphones, and speakers.</li><li>Utilize the <code>checkPermissions()</code> method of the <code>useMediaDevice</code> hook to verify if permissions are granted.</li></ul><pre><code class="language-js">import { useMediaDevice } from "@videosdk.live/react-sdk";

const { checkPermissions } = useMediaDevice();

const checkMediaPermission = async () =&gt; {
  //These methods return a Promise that resolve to a Map&lt;string, boolean&gt; object.
  const checkAudioPermission = await checkPermissions("audio"); //For getting audio permission
  const checkVideoPermission = await checkPermissions("video"); //For getting video permission
  const checkAudioVideoPermission = await checkPermissions("audio_video"); //For getting both audio and video permissions
  // Output: Map object for both audio and video permission:
  /*
        Map(2)
        0 : {"audio" =&gt; true}
            key: "audio"
            value: true
        1 : {"video" =&gt; true}
            key: "video"
            value: true
    */
};</code></pre><ul><li>When microphone and camera permissions are blocked, rendering device lists is not possible:</li></ul><!--kg-card-begin: html--><video src="https://cdn.videosdk.live/website-resources/docs-resources/precall_no_permissions.mp4" preload="auto" autoplay="" controls="" loop="" style="width: 100%; height: 100%;"/><!--kg-card-end: html--><h3 id="step-2-request-permissions-if-necessary%E2%80%8B"><strong>Step 2: Request Permissions (if necessary)</strong><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/setup-call/precall#step-2-request-permissions-if-necessary">​</a></h3><ul><li>If permissions are not granted, use the <code>requestPermission()</code> method of the <code>useMediaDevice</code> hook to prompt users to grant access to their devices.</li></ul><blockquote>NOTE<br>In case permissions are blocked by the user, the browser's permission request dialogue cannot be re-rendered programmatically. In such cases, consider providing guidance to users on</br></blockquote><pre><code class="language-js">const requestAudioVideoPermission = async () =&gt; {
  try {
    //These methods return a Promise that resolve to a Map&lt;string, boolean&gt; object.
    const requestAudioPermission = await requestPermission("audio"); //For Requesting Audio Permission
    const requestVideoPermission = await requestPermission("video"); //For Requesting Video Permission
    const requestAudioVideoPermission = await requestPermission("audio_video"); //For Requesting Audio and Video Permissions
  } catch (ex) {
    console.log("Error in requestPermission ", ex);
  }
};</code></pre><ul><li>Requesting permissions if not already granted:</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/image-19.png" class="kg-image" alt="Integrate Pre-Call Check in React" loading="lazy" width="1920" height="1019"/></figure><h3 id="step-3-render-device-lists%E2%80%8B"><strong>Step 3: Render Device Lists</strong><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/setup-call/precall#step-3-render-device-lists">​</a></h3><ul><li>Once you have the necessary permissions, Fetch and render lists of available camera, microphone, and speaker devices using the <code>getCameras()</code>, <code>getMicrophones()</code>, and <code>getPlaybackDevices()</code> methods of the <code>useMediaDevice</code> hook respectively.</li><li>Enable users to select their preferred devices from these lists.</li></ul><pre><code class="language-js">const getMediaDevices = async () =&gt; {
  try {
    //Method to get all available webcams.
    //It returns a Promise that is resolved with an array of CameraDeviceInfo objects describing the video input devices.
    let webcams = await getCameras();
    //Method to get all available Microphones.
    //It returns a Promise that is resolved with an array of MicrophoneDeviceInfo objects describing the audio input devices.
    let mics = await getMicrophones();
    //Method to get all available speakers.
    //It returns a Promise that is resolved with an array of PlaybackDeviceInfo objects describing the playback devices.
    let speakers = await getPlaybackDevices();
  } catch (err) {
    console.log("Error in getting audio or video devices", err);
  }
};</code></pre><ul><li>Displaying device lists once permissions are granted:</li></ul><!--kg-card-begin: html--><video src="https://cdn.videosdk.live/website-resources/docs-resources/precall_render_device_list.mp4" preload="auto" autoplay="" controls="" loop="" style="width: 100%; height: 100%;"/><!--kg-card-end: html--><h3 id="step-4-handle-device-changes%E2%80%8B"><strong>Step 4: Handle Device Changes</strong><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/setup-call/precall#step-4-handle-device-changes">​</a></h3><ul><li>Implement the <code>OnDeviceChanged</code> callback of the <code>useMediaDevice</code> hook to dynamically re-render device lists whenever new devices are attached or removed from the system.</li><li>Ensure that users can seamlessly interact with newly connected devices without disruptions.</li></ul><pre><code class="language-js">const {
    ...
  } = useMediaDevice({ onDeviceChanged });

//Fetch camera, mic and speaker devices again using this function.
function onDeviceChanged(devices) {
    console.log("Device Changed", devices)
}</code></pre><ul><li>Dynamically updating device lists when new devices are connected or disconnected:</li></ul><!--kg-card-begin: html--><video src="https://cdn.videosdk.live/website-resources/docs-resources/precall_on_device_change.mp4" preload="auto" autoplay="" controls="" loop="" style="width: 100%; height: 100%;"/><!--kg-card-end: html--><h3 id="step-5-create-media-tracks%E2%80%8B"><strong>Step 5: Create Media Tracks</strong><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/setup-call/precall#step-5-create-media-tracks">​</a></h3><ul><li>Upon user selection of devices, create media tracks for the selected microphone and camera using the <code>createMicrophoneAudioTrack()</code> and <code>createCameraVideoTrack()</code> methods.</li><li>Ensure that these tracks originate from the user-selected devices for accurate testing.</li></ul><pre><code class="language-js">import {
  createCameraVideoTrack,
  createMicrophoneAudioTrack,
} from "@videosdk.live/react-sdk";

//For Getting Audio Tracks
const getMediaTracks = async () =&gt; {
  try {
    //Returns a MediaStream object, containing the Audio Stream from the selected Mic Device.
    const customAudioStream = await createMicrophoneAudioTrack({
      // Here, selectedMicId should be the microphone id of the device selected by the user.
      microphoneId: selectedMicId,
    });
    //To retrive audio tracks that will be displayed to the user from the stream.
    const audioTracks = stream?.getAudioTracks();
    const audioTrack = audioTracks.length ? audioTracks[0] : null;
  } catch (error) {
    console.log("Error in getting Audio Track", error);
  }

  //For Getting Video Tracks
  try {
    //Returns a MediaStream object, containing the Video Stream from the selected Webcam Device.
    const customVideoStream = await createCameraVideoTrack({
      // Here, selectedWebcamId should be the webcam id of the device selected by the user.
      cameraId: selectedWebcamId,
      encoderConfig: encoderConfig ? encoderConfig : "h540p_w960p",
      optimizationMode: "motion",
      multiStream: false,
    });
    //To retrive video tracks that will be displayed to the user from the stream.
    const videoTracks = stream?.getVideoTracks();
    const videoTrack = videoTracks.length ? videoTracks[0] : null;
  } catch (error) {
    console.log("Error in getting Video Track", error);
  }
};</code></pre><ul><li>Rendering Media Tracks when necessary permissions are available:</li></ul><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/07/image-24.png" class="kg-image" alt="Integrate Pre-Call Check in React" loading="lazy" width="1920" height="879"/></figure><h3 id="step-6-testing-microphone%E2%80%8B"><strong>Step 6: Testing Microphone</strong><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/setup-call/precall#step-6-testing-microphone">​</a></h3><ul><li>The process of testing microphone device provides valuable insights into microphone quality and ensures users can optimize their audio setup for clear communication.</li><li>To facilitate this functionality, incorporate a recording feature that enables users to capture audio for a specified duration. After recording, users can playback the audio to evaluate microphone performance accurately.</li><li>For implementing this functionality, you can refer to the official guide of <a href="https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder" rel="noopener noreferrer">MediaRecorder</a> for comprehensive instructions and best practices.</li></ul><!--kg-card-begin: html--><video src="https://cdn.videosdk.live/website-resources/docs-resources/precall_test_mic.mp4" preload="auto" autoplay="" controls="" loop="" style="width: 100%; height: 100%;"/><!--kg-card-end: html--><h3 id="step-7-testing-speakers%E2%80%8B"><strong>Step 7: Testing Speakers</strong><a href="https://docs.videosdk.live/react/guide/video-and-audio-calling-api-sdk/setup-call/precall#step-7-testing-speakers">​</a></h3><ul><li>Testing the speaker device allows users to assess audio playback clarity and fidelity, enabling them to fine-tune settings for optimal sound quality in calls and meetings.</li><li>To facilitate effective speaker testing, integrate sound playback functionality into your application.</li><li>This functionality empowers users to play a predefined audio sample, providing a precise evaluation of their speaker output quality.</li></ul><h2 id="conclusion">Conclusion</h2><p>Incorporating a robust precall experience into your video calling application is essential for ensuring seamless and high-quality communication. By proactively addressing potential technical issues before the call begins, you can significantly enhance the user experience and prevent common pitfalls such as muted microphones, pixelated cameras, and laggy connections.</p><p>This guide has provided a comprehensive step-by-step approach to integrating the precall feature into your app. From checking and requesting permissions to rendering device lists and creating media tracks, each step is designed to ensure that users can confidently join their video calls with optimized settings. </p>]]></content:encoded></item><item><title><![CDATA[How to Implement Screen Share in Flutter Video Call App for iOS?]]></title><description><![CDATA[Integrate screen sharing into your Flutter video call app for iOS with VideoSDK. Empower users to collaborate and present seamlessly.]]></description><link>https://www.videosdk.live/blog/implement-screen-share-flutter-video-call-app-for-ios</link><guid isPermaLink="false">661dfe012a88c204ca9d3ed4</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Thu, 09 Jan 2025 09:20:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/Screen-Share-Flutter-iOS.png" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/Screen-Share-Flutter-iOS.png" alt="How to Implement Screen Share in Flutter Video Call App for iOS?"/><p>Implement screen-sharing functionality into your <a href="https://www.videosdk.live/blog/video-calling-in-flutter">Flutter video call app for iOS</a> to enhance user experience and collaboration. With screen sharing, users can seamlessly share their screen content during video calls, fostering effective communication and teamwork. Utilizing Flutter's versatile framework, integrate a user-friendly interface that allows users to initiate screen sharing with just a few taps. VideoSDK offers easy-to-use APIs and <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/concept-and-architecture">comprehensive documentation</a>, simplifying the integration process for developers.</p><p><strong>Benefits of Implementing Screen Share in Flutter iOS Video Call App:</strong></p><ol><li><strong>Enhanced Collaboration:</strong> Screen sharing facilitates real-time sharing of information, fostering better collaboration among users.</li><li><strong>Improved Communication:</strong> Visual demonstrations and presentations help convey complex ideas more effectively, leading to clearer communication.</li><li><strong>Increased Productivity:</strong> With the ability to share screens, teams can work together more efficiently, reducing misunderstandings and saving time.</li><li><strong>Interactive Learning:</strong> Educators and trainers can use screen sharing to demonstrate concepts, conduct workshops, and engage learners interactively.</li><li><strong>Client Presentations:</strong> Professionals can showcase designs, reports, or demos directly to clients, enhancing engagement and understanding.</li></ol><p><strong>Use cases of Screen Share in Flutter iOS Video Call App:</strong></p><ol><li><strong>Remote Work:</strong> Teams working remotely can collaborate effectively by sharing screens and&nbsp;<a href="https://visme.co/blog/presentation-slides/" rel="noreferrer">presentation slides</a>&nbsp;during meetings, brainstorming sessions, and code reviews.</li><li><strong>Education:</strong> Teachers can use screen sharing to present slideshows, demonstrate software, or conduct virtual experiments for remote students.</li><li><strong>Technical Support:</strong> IT professionals can troubleshoot software issues by remotely accessing and viewing users' screens to identify and resolve problems.</li></ol><p>In this article, we'll explore how to integrate screen sharing into your Flutter video calling app for iOS using VideoSDK. We'll cover everything from managing permissions to leveraging VideoSDK's tools and seamlessly integrating the feature into your app's interface.</p><h2 id="getting-started-with-videosdk">Getting Started with VideoSDK</h2><p>To take advantage of Screen Share for iOS, we must use the capabilities that the VideoSDK offers. Before diving into the implementation steps, let's ensure you complete the necessary prerequisites.</p><h3 id="create-a-videosdk-account">Create a VideoSDK Account</h3><p>Go to your <a href="https://app.videosdk.live/dashboard/">VideoSDK dashboard</a> and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.</p><h3 id="generate-your-auth-token">Generate your Auth Token</h3><p>Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token is crucial in authorizing your application to use VideoSDK features.</p><p>For a more visual understanding of the account creation and token generation process, consider referring to the <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/authentication-and-tokens#1-generating-token-from-dashboard">provided tutorial</a>.</p><h3 id="prerequisites%E2%80%8B">Prerequisites<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#prerequisites">​</a></h3><p>Before proceeding, ensure that your development environment meets the following requirements:</p><ul><li>VideoSDK Developer Account (if you do not have one, follow <a href="https://app.videosdk.live/" rel="noopener noreferrer"><strong>VideoSDK Dashboard</strong></a>)</li><li>The basic understanding of Flutter.</li><li><a href="https://pub.dev/packages/videosdk" rel="noopener noreferrer"><strong>Flutter Video SDK</strong></a></li><li>Have Flutter installed on your device.</li></ul><h2 id="install-videosdk%E2%80%8B">Install VideoSDK<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#install-video-sdk">​</a></h2><p>Install the VideoSDK using the below-mentioned flutter command. Make sure you are in your Flutter app directory before you run this command.</p><pre><code class="language-dart">$ flutter pub add videosdk

//run this command to add http library to perform network call to generate roomId
$ flutter pub add http</code></pre><h3 id="videosdk-compatibility">VideoSDK Compatibility</h3>
<!--kg-card-begin: html-->
<table style="border: 1px solid black;">
<thead>
<tr>
<th style="border:1px solid white;">Android and iOS app</th>
<th style="border:1px solid white;">Web</th>
<th style="border:1px solid white;">Desktop app</th>
<th style="border:1px solid white;">Safari browser</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border:1px solid white;"><center> ✅ </center></td>
<td style="border:1px solid white;"><center> ✅ </center></td>
<td style="border:1px solid white;"><center> ✅ </center></td>
<td style="border:1px solid white;"><center> ❌ </center></td>
</tr>
</tbody>
</table>

<!--kg-card-end: html-->
<h3 id="structure-of-the-project%E2%80%8B">Structure of the project<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#structure-of-the-project">​</a></h3><p>Your project structure should look like this.</p><pre><code class="language-dart">    root
    ├── android
    ├── ios
    ├── lib
         ├── api_call.dart
         ├── join_screen.dart
         ├── main.dart
         ├── meeting_controls.dart
         ├── meeting_screen.dart
         ├── participant_tile.dart</code></pre><p>We are going to create flutter widgets (JoinScreen, MeetingScreen, MeetingControls, and ParticipantTile).</p><h3 id="app-structure%E2%80%8B">App Structure<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#app-structure">​</a></h3><p>The app widget will contain <code>JoinScreen</code> and <code>MeetingScreen</code> widget. <code>MeetingScreen</code> will have <code>MeetingControls</code> and <code>ParticipantTile</code> widget.</p><figure class="kg-card kg-image-card"><img src="https://cdn.videosdk.live/website-resources/docs-resources/flutter_quick_start_arch.png" class="kg-image" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" loading="lazy" width="1920" height="1080"/></figure><h3 id="configure-project-for-ios%E2%80%8B">Configure Project For iOS<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#for-ios">​</a></h3><ul><li>Add the following entries that allow your app to access the camera and microphone in your <code>/ios/Runner/Info.plist</code> file:</li></ul><pre><code class="language-dart">&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Camera Usage!&lt;/string&gt;
&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Microphone Usage!&lt;/string&gt;</code></pre><ul><li>Uncomment the following line to define a global platform for your project in <code>/ios/Podfile</code> :</li></ul><pre><code class="language-dart"># platform :ios, '12.0'</code></pre><h2 id="essential-steps-to-implement-video-calling-functionality">Essential Steps to Implement Video Calling Functionality</h2><p>Before diving into the specifics of screen-sharing implementation, it's crucial to ensure you have VideoSDK properly installed and configured within your Flutter project. Refer to VideoSDK's documentation for detailed installation instructions. Once you have a functional video calling setup, you can proceed with adding the screen-sharing feature.</p><h3 id="step-1-get-started-with-apicalldart%E2%80%8B">Step 1: Get started with <code>api_call.dart</code><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-1-get-started-with-api_calldart">​</a></h3><p>Before jumping to anything else, you will write a function to generate a unique meetingId. You will require an authentication token, you can generate it either by using <a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples" rel="noopener noreferrer">videosdk-rtc-api-server-examples</a> or by generating it from the <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer">VideoSDK Dashboard</a> for development.</p><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'dart:convert';
import 'package:http/http.dart' as http;

//Auth token we will use to generate a meeting and connect to it
String token = "&lt;Generated-from-dashboard&gt;";

// API call to create meeting
Future&lt;String&gt; createMeeting() async {
  final http.Response httpResponse = await http.post(
    Uri.parse("https://api.videosdk.live/v2/rooms"),
    headers: {'Authorization': token},
  );

//Destructuring the roomId from the response
  return json.decode(httpResponse.body)['roomId'];
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">api_call.dart</span></p></figcaption></figure><h3 id="step-2-creating-the-joinscreen%E2%80%8B">Step 2: Creating the JoinScreen<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-2--creating-the-joinscreen">​</a></h3><p>Let's create <code>join_screen.dart</code> file in <code>lib</code> directory and create JoinScreen <code>StatelessWidget</code>.</p><p>The JoinScreen will consist of:</p><ul><li><strong>Create Meeting Button</strong>: This button will create a new meeting for you.</li><li><strong>Meeting ID TextField</strong>: This text field will contain the meeting ID, you want to join.</li><li><strong>Join Meeting Button</strong>: This button will join the meeting, which you have provided.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'api_call.dart';
import 'meeting_screen.dart';

class JoinScreen extends StatelessWidget {
  final _meetingIdController = TextEditingController();

  JoinScreen({super.key});

  void onCreateButtonPressed(BuildContext context) async {
    // call api to create meeting and then navigate to MeetingScreen with meetingId,token
    await createMeeting().then((meetingId) {
      if (!context.mounted) return;
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (context) =&gt; MeetingScreen(
            meetingId: meetingId,
            token: token,
          ),
        ),
      );
    });
  }

  void onJoinButtonPressed(BuildContext context) {
    String meetingId = _meetingIdController.text;
    var re = RegExp("\\w{4}\\-\\w{4}\\-\\w{4}");
    // check meeting id is not null or invaild
    // if meeting id is vaild then navigate to MeetingScreen with meetingId,token
    if (meetingId.isNotEmpty &amp;&amp; re.hasMatch(meetingId)) {
      _meetingIdController.clear();
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (context) =&gt; MeetingScreen(
            meetingId: meetingId,
            token: token,
          ),
        ),
      );
    } else {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
        content: Text("Please enter valid meeting id"),
      ));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('VideoSDK QuickStart'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(12.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () =&gt; onCreateButtonPressed(context),
              child: const Text('Create Meeting'),
            ),
            Container(
              margin: const EdgeInsets.fromLTRB(0, 8.0, 0, 8.0),
              child: TextField(
                decoration: const InputDecoration(
                  hintText: 'Meeting Id',
                  border: OutlineInputBorder(),
                ),
                controller: _meetingIdController,
              ),
            ),
            ElevatedButton(
              onPressed: () =&gt; onJoinButtonPressed(context),
              child: const Text('Join Meeting'),
            ),
          ],
        ),
      ),
    );
  }
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">join_screen.dart</span></p></figcaption></figure><ul><li>Update the home screen of the app in the <code>main.dart</code></li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'join_screen.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'VideoSDK QuickStart',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: JoinScreen(),
    );
  }
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">main.dart</span></p></figcaption></figure><h3 id="step-3-creating-the-meetingcontrols%E2%80%8B">Step 3: Creating the MeetingControls<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-3--creating-the-meetingcontrols">​</a></h3><p>Let's create <code>meeting_controls.dart</code> file and create MeetingControls <code>StatelessWidget</code>.</p><p>The MeetingControls will consist of:</p><ul><li><strong>Leave Button</strong>: This button will leave the meeting.</li><li><strong>Toggle Mic Button</strong>: This button will unmute or mute the mic.</li><li><strong>Toggle Camera Button</strong>: This button will enable or disable the camera.</li></ul><p>MeetingControls will accept 3 functions in the constructor</p><ul><li><strong><code>onLeaveButtonPressed</code></strong>: invoked when the Leave button pressed</li><li><strong><code>onToggleMicButtonPressed</code></strong>: invoked when the toggle mic button pressed</li><li><strong><code>onToggleCameraButtonPressed</code></strong>: invoked when the toggle Camera button pressed</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/material.dart';

class MeetingControls extends StatelessWidget {
  final void Function() onToggleMicButtonPressed;
  final void Function() onToggleCameraButtonPressed;
  final void Function() onLeaveButtonPressed;

  const MeetingControls(
      {super.key,
      required this.onToggleMicButtonPressed,
      required this.onToggleCameraButtonPressed,
      required this.onLeaveButtonPressed});

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        ElevatedButton(
            onPressed: onLeaveButtonPressed, child: const Text('Leave')),
        ElevatedButton(
            onPressed: onToggleMicButtonPressed, child: const Text('Toggle Mic')),
        ElevatedButton(
            onPressed: onToggleCameraButtonPressed,
            child: const Text('Toggle WebCam')),
      ],
    );
  }
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">meeting_controls.dart</span></p></figcaption></figure><h3 id="step-4-creating-participanttile%E2%80%8B">Step 4: Creating ParticipantTile<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-4--creating-participanttile">​</a></h3><p>Let's create <code>participant_tile.dart</code> file and create ParticipantTile <code>StatefulWidget</code>.</p><p>The ParticipantTile will consist of:</p><ul><li><strong>RTCVideoView</strong>: This will show the participant's video stream.</li></ul><p>ParticipantTile will accept <code>Participant</code> in constructor</p><ul><li><strong>participant:</strong> participant of the meeting.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class ParticipantTile extends StatefulWidget {
  final Participant participant;
  const ParticipantTile({super.key, required this.participant});

  @override
  State&lt;ParticipantTile&gt; createState() =&gt; _ParticipantTileState();
}

class _ParticipantTileState extends State&lt;ParticipantTile&gt; {
  Stream? videoStream;

  @override
  void initState() {
    // initial video stream for the participant
    widget.participant.streams.forEach((key, Stream stream) {
      setState(() {
        if (stream.kind == 'video') {
          videoStream = stream;
        }
      });
    });
    _initStreamListeners();
    super.initState();
  }

  _initStreamListeners() {
    widget.participant.on(Events.streamEnabled, (Stream stream) {
      if (stream.kind == 'video') {
        setState(() =&gt; videoStream = stream);
      }
    });

    widget.participant.on(Events.streamDisabled, (Stream stream) {
      if (stream.kind == 'video') {
        setState(() =&gt; videoStream = null);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: videoStream != null
          ? RTCVideoView(
              videoStream?.renderer as RTCVideoRenderer,
              objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
            )
          : Container(
              color: Colors.grey.shade800,
              child: const Center(
                child: Icon(
                  Icons.person,
                  size: 100,
                ),
              ),
            ),
    );
  }
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">participant_tile.dart</span></p></figcaption></figure><h3 id="step-5-creating-the-meetingscreen%E2%80%8B">Step 5: Creating the MeetingScreen<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-5--creating-the-meetingscreen">​</a></h3><p>Let's create <code>meeting_screen.dart</code> file and create MeetingScreen <code>StatefulWidget</code>.</p><p>MeetingScreen will accept meetingId and token in the constructor</p><ul><li><strong>meetingId:</strong> meetingId, you want to join</li><li><strong>token</strong>: VideoSdk Auth token</li></ul><p>Your app should look like this after the implementation.</p><p>If you get <code>webrtc/webrtc.h </code> file not found error at runtime in ios then check the solution <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/known-issues#issue--1" rel="noopener noreferrer">here</a>.</p><p><strong>TIP:</strong> You can check out the complete <a href="https://github.com/videosdk-live/quickstart/tree/main/flutter-rtc" rel="noopener noreferrer">quick start example here</a>.</p><h2 id="integrate-screen-share-feature">Integrate Screen Share Feature</h2><p>Screen sharing in a meeting is the process of sharing your device screen with other participants in the meeting. It allows everyone in the meeting to see exactly what you are seeing on your screen, which can be helpful for presentations, demonstrations, or collaborations.</p><h3 id="why-integrate-screen-sharing-with-videosdk">Why Integrate Screen Sharing with VideoSDK?</h3><p>Integrating screen sharing into your Flutter video calling app using videoSDK presents several compelling reasons:</p><ol><li><strong>Simplified Development</strong>: With VideoSDK, the intricate tasks of screen capture and transmission are effortlessly managed, saving you valuable development time and resources.</li><li><strong>Native Functionality</strong>: Harnessing the power of the iOS Media Projection API, VideoSDK ensures a seamless and efficient screen-sharing experience for your users, providing them with a native feel and optimal performance.</li><li><strong>Seamless Integration</strong>: The integration process with VideoSDK is intuitive and hassle-free, enabling you to seamlessly incorporate screen-sharing functionality into your existing video call features without extensive modifications.</li><li><strong>Robust Features</strong>: VideoSDK offers a robust screen-sharing solution equipped with essential features such as permission handling and in-app sharing capabilities, guaranteeing a reliable and user-friendly experience.</li></ol><p>By embracing screen sharing through VideoSDK, you elevate the functionality and appeal of your Flutter video-calling app, providing users with an enriched communication experience.</p><blockquote><strong>NOTE:</strong><br>Flutter iOS screenshare is available from the SDK version 1.0.5 and above and the deployment target for iOS app should be <strong>iOS 14 or newer</strong></br></blockquote><p>iOS requires you to add a Broadcast Upload Extension to capture the screen of the device.</p><h3 id="step-1-open-target%E2%80%8B">Step 1: Open Target<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/extras/flutter-ios-screen-share#step-1--open-target">​</a></h3><p>Open your project with Xcode and select <strong>File &gt; New &gt; Target</strong> in the menu bar.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step1-xcode-8cbf05258253368fa8095f10aa06459d.png" class="kg-image" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" loading="lazy" width="801" height="580"/></figure><h3 id="step-2-select-target%E2%80%8B">Step 2: Select Target<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/extras/flutter-ios-screen-share#step-2--select-target">​</a></h3><p>Choose <strong>Broadcast Upload Extension</strong>, and click next.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step2-xcode-5270422797cc8941922cefadffb5238d.png" class="kg-image" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" loading="lazy" width="769" height="555"/></figure><h3 id="step-3-configure-broadcast-upload-extension%E2%80%8B">Step 3: Configure Broadcast Upload Extension<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/extras/flutter-ios-screen-share#step-3--configure-broadcast-upload-extension">​</a></h3><p>Enter the extension name in the <strong>Product Name</strong> field, choose a team from the dropdown, Uncheck the include UI extension field, and click finish.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step3-xcode-458facd46d26cfa090fd8724b6ba831b.png" class="kg-image" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" loading="lazy" width="789" height="567"/></figure><h3 id="step-4-activate-extension-scheme%E2%80%8B">Step 4: Activate Extension scheme<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/extras/flutter-ios-screen-share#step-4--activate-extension-scheme">​</a></h3><p>You will be prompted to <strong>Activate the "Your-Extension-name" scheme?</strong> pop-up, click activate.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step4-xcode-6de6fa7fc079f920f52d8315b2717e9d.png" class="kg-image" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" loading="lazy" width="510" height="490"/></figure><p>Now, the broadcast folder will appear in Xcode left sidebar.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step5-xcode-79ba89532c028fb25376bf6d4953f0b2.png" class="kg-image" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" loading="lazy" width="474" height="652"/></figure><h3 id="step-5-add-external-file-in-created-extension%E2%80%8B">Step 5: Add External file in Created Extension<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/extras/flutter-ios-screen-share#step-5--add-external-file-in-created-extension">​</a></h3><p>Open <a href="https://github.com/videosdk-live/videosdk-rtc-flutter-sdk-example/tree/main/ios/FlutterBroadcast" rel="noopener noreferrer">videosdk-rtc-flutter-sdk-example</a>, Copy <code>SampleUploader.swift</code>, <code>SocketConnection.swift</code>, <code>DarwinNotificationCenter.swift</code>, and <code>Atomic.swift</code> files to your extension's folder and make sure they're added to the target.</p><h3 id="step-6-update-samplehandlerswift-file%E2%80%8B">Step 6: Update <code>SampleHandler.swift</code> file<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/extras/flutter-ios-screen-share#step-6--update-samplehandlerswift-file">​</a></h3><p>Open <a href="https://github.com/videosdk-live/videosdk-rtc-flutter-sdk-example/blob/main/ios/FlutterBroadcast/SampleHandler.swift" rel="noopener noreferrer">SampleHandler.swift</a> and Copy <code>SampleHandler.swift</code> file content and paste it into your extensions <code>SampleHandler.swift</code> file.</p><h3 id="step-7-add-capability-in-the-app%E2%80%8B">Step 7: Add Capability in the App<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/extras/flutter-ios-screen-share#step-7--add-capability-in-app">​</a></h3><p>In Xcode, go to <strong>YourappName &gt; Signing &amp; Capabilities</strong>. and click on <strong>+Capability</strong> to configure the app group.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step8-xcode-60177a1783e9203570a06479c30492b8.png" class="kg-image" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" loading="lazy" width="930" height="529"/></figure><p>Select <strong>App Groups</strong> from the list:</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step9-xcode-13aa5448218f78f473f060c6854874a2.png" class="kg-image" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" loading="lazy" width="803" height="579"/></figure><p>After that, you have to select or add the generated app group ID that you have created before.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step10-xcode-80bd6f05c87acae9a9fbaa4a89f414f9.png" class="kg-image" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" loading="lazy" width="1176" height="735"/></figure><h3 id="step-8-add-capability-in-extension%E2%80%8B">Step 8: Add Capability in Extension<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/extras/flutter-ios-screen-share#step-8--add-capability-in-extension">​</a></h3><p>Go to <strong>Your-Extension-Name &gt; Signing &amp; Capabilities</strong> and configure <strong>App Group</strong> functionality, which we had performed in previous steps. (The group ID should be the same for both targets.)</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step11-xcode-021329a0abd110f74fb1eba7d668fc79.png" class="kg-image" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" loading="lazy" width="803" height="445"/></figure><h3 id="step-9-add-app-group-id-to-extension-file%E2%80%8B">Step 9: Add App Group ID to Extension File<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/extras/flutter-ios-screen-share#step-9--add-app-group-id-in-extension-file">​</a></h3><p>Go to the extensions <code>SampleHandler.swift</code> file and paste your group Id in <code>appGroupIdentifier</code> constant.</p><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step12-xcode-6f145ca7606a486596da66ebf5c31e36.png" class="kg-image" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" loading="lazy" width="951" height="562"/></figure><h3 id="step-10-update-app-level-infoplist-file%E2%80%8B">Step 10: Update App level info.plist file<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/extras/flutter-ios-screen-share#step-10--update-app-level-infoplist-file">​</a></h3><ol><li>Add a new key, <strong>RTCScreenSharingExtension</strong> in <strong>Info.plist</strong> with the extension's Bundle Identifier as the value.</li><li>Add a new key, <strong>RTCAppGroupIdentifier</strong> in <strong>Info.plist</strong> with the extension's app group ID as the value.</li></ol><blockquote><strong>Note</strong> : For extension's Bundle Identifier, go to <strong>TARGETS &gt; Your-Extension-Name &gt; Signing &amp; Capabilities</strong> .</blockquote><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step13-xcode-00cb59e564facb3c7f365235065f4561.png" class="kg-image" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" loading="lazy" width="933" height="550"/></figure><blockquote>NOTE: You can also check out the extension <a href="https://github.com/videosdk-live/videosdk-rtc-flutter-sdk-example/tree/main/ios/FlutterBroadcast" rel="noopener noreferrer">example code</a> on GitHub.</blockquote><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/videosdk-live/videosdk-rtc-flutter-sdk-example/tree/main/ios/FlutterBroadcast"><div class="kg-bookmark-content"><div class="kg-bookmark-title">videosdk-rtc-flutter-sdk-example/ios/FlutterBroadcast at main · videosdk-live/videosdk-rtc-flutter-sdk-example</div><div class="kg-bookmark-description">WebRTC based video conferencing SDK for Flutter (Android / iOS) - videosdk-live/videosdk-rtc-flutter-sdk-example</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="How to Implement Screen Share in Flutter Video Call App for iOS?"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">videosdk-live</span></img></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/de9f710aa0874a5467b708c1c752532d36ee6c1d7ea72f118df3eb47b3260ba6/videosdk-live/videosdk-rtc-flutter-sdk-example" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" onerror="this.style.display = 'none'"/></div></a></figure><h3 id="enable-screen-share%E2%80%8B">Enable Screen Share<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/extras/flutter-ios-screen-share#enable-screen-share">​</a></h3><ul><li>To start screen sharing, just call <code>room.enableScreenShare()</code> method.</li></ul><pre><code class="language-dart">ElevatedButton(
    child: Text("Start ScreenSharing"),
    onPressed: () {
        room.enableScreenShare();
    },
),</code></pre><figure class="kg-card kg-image-card"><img src="https://docs.videosdk.live/assets/images/step23-xcode-e815d2c96e8061551e941055e32578b3.png" class="kg-image" alt="How to Implement Screen Share in Flutter Video Call App for iOS?" loading="lazy" width="307" height="504"/></figure><p>After clicking the <strong>Start Broadcast</strong> button, we will be able to get the screen stream in session.</p><h3 id="disable-screen-share%E2%80%8B">Disable Screen Share<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/extras/flutter-ios-screen-share#disable-screen-share">​</a></h3><p>By using <code>room.disableScreenShare()</code> function, a participant can stop publishing screen streams to other participants</p><pre><code class="language-dart">ElevatedButton(
    child: Text("Stop ScreenSharing"),
    onPressed: () {
        room.disableScreenShare();
    },
),</code></pre><h3 id="events-associated-with-screen-share%E2%80%8B">Events associated with Screen Share<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/handling-media/screen-share#events-associated-with-enablescreenshare">​</a></h3><h4 id="events-associated-with-enable-screenshare%E2%80%8B">Events associated with Enable ScreenShare​</h4>
<p>Every Participant will receive a callback on <a href="https://docs.videosdk.live/flutter/api/sdk-reference/participant-class/events#streamenabled"><code>Events.streamEnabled</code></a> of the <a href="https://docs.videosdk.live/flutter/api/sdk-reference/participant-class/introduction"><code>Participant</code></a> object with <code>Stream</code> object.</p><ul><li>Every Remote Participant will receive <a href="https://docs.videosdk.live/flutter/api/sdk-reference/room-class/events#presenterchanged"><code>Events.presenterChanged</code></a> callback on the <a href="https://docs.videosdk.live/flutter/api/sdk-reference/room-class/introduction"><code>Room</code></a> object with the participantId as <code>presenterId</code> who started the screen share.</li></ul><h4 id="events-associated-with-disable-screenshare%E2%80%8B">Events associated with Disable ScreenShare​</h4>
<ul><li>Every Participant will receive a callback on <a href="https://docs.videosdk.live/flutter/api/sdk-reference/participant-class/events#streamdisabled"><code>Events.streamDisabled</code></a> of the <a href="https://docs.videosdk.live/flutter/api/sdk-reference/participant-class/introduction"><code>Participant</code></a> object with <code>Stream</code> object.</li><li>Every Remote Participant will receive <a href="https://docs.videosdk.live/flutter/api/sdk-reference/room-class/events#presenterchanged"><code>Events.presenterChanged</code></a> callback on the <a href="https://docs.videosdk.live/flutter/api/sdk-reference/room-class/introduction"><code>Room</code></a> object with the <code>presenterId</code> as <code>null</code>.</li></ul><h3 id="example%E2%80%8B">Example<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/handling-media/screen-share#rendering-screen-share-stream">​</a></h3><p>To render the screen share, you will need to know <code>participantId</code> who is presenting the screen, which can be found in the <code>presenterId</code> property of <code>Room</code> object.</p><p>We will listen for the <code>Events.presenterChanged</code> on <code>Room</code> object to check if some other participant starts screen share, <code>Events.streamEnabled</code> and <code>Events.streamDisabled</code> on the <code>localParticipant</code>'s object to identify if the local participant is presenting or not.</p><pre><code class="language-dart">import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import './participant_tile.dart';
import './screen_share_view.dart';

class MeetingScreen extends StatefulWidget {
  final String meetingId;
  final String token;

  const MeetingScreen(
      {super.key, required this.meetingId, required this.token});

  @override
  State&lt;MeetingScreen&gt; createState() =&gt; _MeetingScreenState();
}

class _MeetingScreenState extends State&lt;MeetingScreen&gt; {
  late Room _room;
  var micEnabled = true;
  var camEnabled = true;
  String? _presenterId;

  Map&lt;String, Participant&gt; participants = {};

  @override
  void initState() {
    // create room
    _room = VideoSDK.createRoom(
      roomId: widget.meetingId,
      token: widget.token,
      displayName: "John Doe",
      micEnabled: micEnabled,
      camEnabled: camEnabled
    );

    setMeetingEventListener();

    // Join room
    _room.join();

    super.initState();
  }

  // listening to meeting events
  void setMeetingEventListener() {
   // ...

   //Listening if remote participant starts presenting
    _room.on(Events.presenterChanged, (String? presenterId) {
      setState(() =&gt; {_presenterId = presenterId});
    });

    //Listening if local participant starts presenting
    _room.localParticipant.on(Events.streamEnabled, (Stream stream) {
      if (stream.kind == "share") {
        setState(() =&gt; {_presenterId = _room.localParticipant.id});
      }
    });

    _room.localParticipant.on(Events.streamDisabled, (Stream stream) {
      if (stream.kind == "share") {
        setState(() =&gt; {_presenterId = null});
      }
    });
  }

  // onbackButton pressed leave the room
  Future&lt;bool&gt; _onWillPop() async {
    _room.leave();
    return true;
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () =&gt; _onWillPop(),
      child: Scaffold(
        appBar: AppBar(
          title: const Text('VideoSDK QuickStart'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              Text(widget.meetingId),
              //render all participant
              // ...
              
              //we will render the screenshare view if the presenterId is not null
              if (_presenterId != null)
                ScreenShareView(
                  participant: _presenterId == _room.localParticipant.id
                      ? _room.localParticipant
                      : _room.participants[_presenterId],
                ),
                // MeetingControls
                // ....
              ElevatedButton(
                  onPressed: () {
                    if (_presenterId != null) {
                      _room.disableScreenShare();
                    } else {
                      _room.enableScreenShare();
                    }
                  },
                  child: const Text('Toggle Screnshare')),
            ],
          ),
        ),
      ),
      home: JoinScreen(),
    );
  }
}</code></pre><p>Now that we know if there is an active presenter, let us get the screen share stream from the <code>Participant</code> object and render it.</p><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class ScreenShareView extends StatelessWidget {
  final Participant? participant;

  ScreenShareView({super.key, required this.participant}) {
  //intialize the shareStream
    participant?.streams.forEach((key, value) {
      if (value.kind == "share") {
        shareStream = value;
      }
    });
  }
  Stream? shareStream;

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.grey.shade800,
      height: 300,
      width: 200,
      //show the screen share stream
      child: shareStream != null
          ? RTCVideoView(
              shareStream?.renderer as RTCVideoRenderer,
              objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
            )
          : null,
    );
  }
}</code></pre><h2 id="conclusion">Conclusion</h2><p>By integrating screen sharing into your Flutter video calling app using VideoSDK, you provide users with a powerful tool to enhance communication and collaboration. This feature proves beneficial across various scenarios, from business presentations to technical demonstrations, making your app a versatile and invaluable platform. </p><p>With <a href="https://www.videosdk.live/">VideoSDK's </a>seamless integration capabilities, incorporating screen sharing becomes not only feasible but also streamlined. This allows you to focus more on crafting a remarkable user interface and experience. Whether users need to share slides, collaborate on projects, or provide remote assistance, your app becomes their go-to solution. Empower users with the ability to connect, communicate, and collaborate effectively, all within a single, user-friendly platform.</p><p>Unlock the full potential of VideoSDK and create seamless video experiences today! <a href="https://app.videosdk.live/dashboard"><strong>Sign up now</strong></a> and get 10,000 free minutes to elevate your video app to the next level.</p>]]></content:encoded></item><item><title><![CDATA[How to Integrate Chat Feature in React Native Video Call App?]]></title><description><![CDATA[This article explores the integration of a chat feature into a React Native video call app using VideoSDK, aiming to create more immersive and engaging user experiences.]]></description><link>https://www.videosdk.live/blog/integrate-chat-feature-in-react-native-video-call-app</link><guid isPermaLink="false">660f88a72a88c204ca9cfd4e</guid><category><![CDATA[Developer Blog]]></category><category><![CDATA[React Native]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Thu, 09 Jan 2025 05:55:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/Chat-Feature-React-Native-1.png" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/Chat-Feature-React-Native-1.png" alt="How to Integrate Chat Feature in React Native Video Call App?"/><p>Participants in a multi-participant video call may find it difficult to engage in meaningful talks without interrupting each other. It is also challenging to enhance programs with real-time messaging capabilities, which facilitate communication between participants during video chats. In this environment, the goal is to create more immersive and engaging user experiences, with services such as chat emerging as essential components. </p><p>It enables users to share messages, transfer files, and swap data without disrupting the audio or video feeds. This is especially handy when participants want to ask questions, provide feedback, or provide relevant information during a video chat. This article will walk you through the process of implementing a chat feature into a React Native video call app with VideoSDK.</p><h2 id="getting-started-with-videosdk">Getting Started with VideoSDK</h2><h3 id="goals">Goals</h3><p>By the End of this Article, we'll:</p><ol><li>Create a <a href="https://app.videosdk.live/signup">VideoSDK account</a> and generate your VideoSDK auth token.</li><li>Integrate the VideoSDK library and dependencies into your project.</li><li>Implement core functionalities for video calls using VideoSDK.</li><li>Enable the Chat feature in your app.</li></ol><p>To take advantage of the chat functionality, we must use the capabilities that the VideoSDK offers. Before diving into the implementation steps, ensure you complete the necessary prerequisites.</p><h3 id="create-a-videosdk-account">Create a VideoSDK Account</h3><p>Go to your <a href="https://app.videosdk.live/dashboard/">VideoSDK dashboard</a> and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.</p><h3 id="generate-your-auth-token">Generate your Auth Token</h3><p>Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token is crucial in authorizing your application to use VideoSDK features.</p><p>For a more visual understanding of the account creation and token generation process, consider referring to the <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/authentication-and-token">provided tutorial</a>.</p><h3 id="prerequisites-and-setup">Prerequisites and Setup</h3><p>Make sure your development environment meets the following requirements:</p><ul><li>Node.js v12+</li><li>NPM v6+ (comes installed with newer Node versions)</li><li>Android Studio or Xcode installed</li></ul><h2 id="%E2%AC%87%EF%B8%8F-install-videosdk-config">⬇️ Install VideoSDK Config.</h2><p>It is necessary to set up VideoSDK within your project before going into the details of integrating the Chat feature. Installing VideoSDK using NPM or Yarn will depend on the needs of your project.</p><ul><li>For NPM </li></ul><pre><code class="language-js">npm install "@videosdk.live/react-native-sdk"  "@videosdk.live/react-native-incallmanager"</code></pre><ul><li>For Yarn</li></ul><pre><code class="language-js">yarn add "@videosdk.live/react-native-sdk" "@videosdk.live/react-native-incallmanager"</code></pre><h3 id="project-configuration">Project Configuration</h3><p>Before integrating the Chat functionality, ensure that your project is correctly prepared to handle the integration. This setup consists of a sequence of steps for configuring rights, dependencies, and platform-specific parameters so that VideoSDK can function seamlessly inside your application context.</p><h4 id="android-setup">Android Setup</h4>
<ul><li>Add the required permissions in the <code>AndroidManifest.xml</code> file.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">&lt;manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.cool.app"
&gt;
    &lt;!-- Give all the required permissions to app --&gt;
    &lt;uses-permission android:name="android.permission.INTERNET" /&gt;
    &lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
    &lt;!-- Needed to communicate with already-paired Bluetooth devices. (Legacy up to Android 11) --&gt;
    &lt;uses-permission
        android:name="android.permission.BLUETOOTH"
        android:maxSdkVersion="30" /&gt;
    &lt;uses-permission
        android:name="android.permission.BLUETOOTH_ADMIN"
        android:maxSdkVersion="30" /&gt;

    &lt;!-- Needed to communicate with already-paired Bluetooth devices. (Android 12 upwards)--&gt;
    &lt;uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /&gt;

    &lt;uses-permission android:name="android.permission.CAMERA" /&gt;
    &lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /&gt;
    &lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
    &lt;uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /&gt;
    &lt;uses-permission android:name="android.permission.FOREGROUND_SERVICE"/&gt;
    &lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;

    &lt;application&gt;
   &lt;meta-data
      android:name="live.videosdk.rnfgservice.notification_channel_name"
      android:value="Meeting Notification"
     /&gt;
    &lt;meta-data
    android:name="live.videosdk.rnfgservice.notification_channel_description"
    android:value="Whenever meeting started notification will appear."
    /&gt;
    &lt;meta-data
    android:name="live.videosdk.rnfgservice.notification_color"
    android:resource="@color/red"
    /&gt;
    &lt;service android:name="live.videosdk.rnfgservice.ForegroundService" android:foregroundServiceType="mediaProjection"&gt;&lt;/service&gt;
    &lt;service android:name="live.videosdk.rnfgservice.ForegroundServiceTask"&gt;&lt;/service&gt;
  &lt;/application&gt;
&lt;/manifest&gt;</code></pre><figcaption><p><span style="white-space: pre-wrap;">AndroidManifest.xml</span></p></figcaption></figure><ul><li>Update your <code>colors.xml</code> file for internal dependencies.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">&lt;resources&gt;
  &lt;item name="red" type="color"&gt;
    #FC0303
  &lt;/item&gt;
  &lt;integer-array name="androidcolors"&gt;
    &lt;item&gt;@color/red&lt;/item&gt;
  &lt;/integer-array&gt;
&lt;/resources&gt;</code></pre><figcaption><p><span style="white-space: pre-wrap;">android/app/src/main/res/values/colors.xml</span></p></figcaption></figure><ul><li>Link the necessary VideoSDK Dependencies.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">  dependencies {
   implementation project(':rnwebrtc')
   implementation project(':rnfgservice')
  }</code></pre><figcaption><p><span style="white-space: pre-wrap;">android/app/build.gradle</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">include ':rnwebrtc'
project(':rnwebrtc').projectDir = new File(rootProject.projectDir, '../node_modules/@videosdk.live/react-native-webrtc/android')

include ':rnfgservice'
project(':rnfgservice').projectDir = new File(rootProject.projectDir, '../node_modules/@videosdk.live/react-native-foreground-service/android')</code></pre><figcaption><p><span style="white-space: pre-wrap;">android/settings.gradle</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">import live.videosdk.rnwebrtc.WebRTCModulePackage;
import live.videosdk.rnfgservice.ForegroundServicePackage;

public class MainApplication extends Application implements ReactApplication {
  private static List&lt;ReactPackage&gt; getPackages() {
      @SuppressWarnings("UnnecessaryLocalVariable")
      List&lt;ReactPackage&gt; packages = new PackageList(this).getPackages();
      // Packages that cannot be autolinked yet can be added manually here, for example:

      packages.add(new ForegroundServicePackage());
      packages.add(new WebRTCModulePackage());

      return packages;
  }
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">MainApplication.java</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">/* This one fixes a weird WebRTC runtime problem on some devices. */
android.enableDexingArtifactTransform.desugaring=false</code></pre><figcaption><p><span style="white-space: pre-wrap;">android/gradle.properties</span></p></figcaption></figure><ul><li>Include the following line in your <code>proguard-rules.pro</code> file (optional: if you are using Proguard)</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">-keep class org.webrtc.** { *; }</code></pre><figcaption><p><span style="white-space: pre-wrap;">android/app/proguard-rules.pro</span></p></figcaption></figure><ul><li>In your <code>build.gradle</code> file, update the minimum OS/SDK version to <code>23</code>.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-js">buildscript {
  ext {
      minSdkVersion = 23
  }
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">build.gradle</span></p></figcaption></figure><h4 id="ios-setup%E2%80%8B">iOS Setup​</h4>
<blockquote>IMPORTANT: Ensure that you are using CocoaPods version 1.10 or later.</blockquote><ol><li>To update CocoaPods, you can reinstall the <code>gem</code> using the following command:</li></ol><pre><code class="language-swift">$ sudo gem install cocoapods</code></pre><p><strong>2.</strong> Manually link react-native-incall-manager (if it is not linked automatically).</p><p>Select <code>Your_Xcode_Project/TARGETS/BuildSettings</code>, in Header Search Paths, add <code>"$(SRCROOT)/../node_modules/@videosdk.live/react-native-incall-manager/ios/RNInCallManager"</code></p><p><strong>3.</strong> Change the path of <code>react-native-webrtc</code> using the following command:</p><pre><code class="language-swift">pod ‘react-native-webrtc’, :path =&gt; ‘../node_modules/@videosdk.live/react-native-webrtc’</code></pre><p><strong>4. </strong>Change the version of your platform.</p><p>You need to change the platform field in the Podfile to 12.0 or above because <strong>react-native-webrtc</strong> doesn't support iOS versions earlier than 12.0. Update the line: platform: ios, ‘12.0’.</p><p><strong>5. </strong>Install pods.</p><p>After updating the version, you need to install the pods by running the following command:</p><pre><code class="language-swift">Pod install</code></pre><p><strong>6. </strong>Add “<strong>libreact-native-webrtc.a</strong>” binary.</p><p>Add the "<strong>libreact-native-webrtc.a</strong>" binary to the "Link Binary With Libraries" section in the target of your main project folder.</p><p><strong>7. </strong>Declare permissions in <strong>Info.plist</strong>:</p><p>Add the following lines to your <strong>info.plist</strong> file located at (project folder/ios/projectname/info.plist):</p><figure class="kg-card kg-code-card"><pre><code class="language-swift">&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
&lt;string&gt;Camera permission description&lt;/string&gt;
&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;Microphone permission description&lt;/string&gt;</code></pre><figcaption><p><span style="white-space: pre-wrap;">ios/projectname/info.plist</span></p></figcaption></figure><h4 id="register-service">Register Service</h4>
<p>Register VideoSDK services in your root <code>index.js</code> file for the initialization service.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import { AppRegistry } from "react-native";
import App from "./App";
import { name as appName } from "./app.json";
import { register } from "@videosdk.live/react-native-sdk";

register();

AppRegistry.registerComponent(appName, () =&gt; App);</code></pre><figcaption><p><span style="white-space: pre-wrap;">index.js</span></p></figcaption></figure><h2 id="essential-steps-for-implement-the-video-calling-functionality">Essential Steps for Implement the Video Calling Functionality</h2><h3 id="step-1-get-started-with-apijs%E2%80%8B">Step 1: Get started with api.js<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start#step-1--get-started-with-apijs">​</a></h3><p>Before moving on, you must create an API request to generate a unique meetingId. You will need an authentication token, which you can create either through the <a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples" rel="noopener noreferrer">videosdk-rtc-api-server-examples</a> or directly from the <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer">VideoSDK Dashboard</a> for developers.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">export const token = "&lt;Generated-from-dashbaord&gt;";
// API call to create meeting
export const createMeeting = async ({ token }) =&gt; {
  const res = await fetch(`https://api.videosdk.live/v2/rooms`, {
    method: "POST",
    headers: {
      authorization: `${token}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({}),
  });

  const { roomId } = await res.json();
  return roomId;
};</code></pre><figcaption><p><span style="white-space: pre-wrap;">api.js</span></p></figcaption></figure><h3 id="step-2-wireframe-appjs-with-all-the-components%E2%80%8B">Step 2: Wireframe App.js with all the components<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start#step-2-wireframe-appjs-with-all-the-components">​</a></h3><p>To build up a wireframe of App.js, you need to use VideoSDK Hooks and Context Providers. VideoSDK provides MeetingProvider, MeetingConsumer, useMeeting, and useParticipant hooks.</p><p>First, you need to understand the <strong>Context Provider</strong> and Consumer. Context is primarily used when some data needs to be accessible by many components at different nesting levels.</p><ul><li><strong>MeetingProvider</strong>: This is the Context Provider. It accepts value <code>config</code> and <code>token</code> as props. The Provider component accepts a value prop to be passed to consuming components that are descendants of this Provider. One Provider can be connected to many consumers. Providers can be nested to override values deeper within the tree.</li><li><strong>MeetingConsumer</strong>: This is the Context Consumer. All consumers that are descendants of a Provider will re-render whenever the Provider’s value prop changes.</li><li><strong>useMeeting</strong>: This is the meeting hook API. It includes all the information related to meetings such as join, leave, enable/disable the mic or webcam, etc.</li><li><strong>useParticipant</strong>: This is the participant hook API. It is responsible for handling all the events and props related to one particular participant such as <strong>name</strong>, <strong>webcamStream</strong>, <strong>micStream</strong>, etc.</li></ul><p>The Meeting Context provides a way to listen for any changes that occur when a participant joins the meeting or makes modifications to their microphone, camera, and other settings.</p><p>Begin by making a few changes to the code in the <strong>App.js</strong> file.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">import React, { useState } from "react";
import {
  SafeAreaView,
  TouchableOpacity,
  Text,
  TextInput,
  View,
  FlatList,
} from "react-native";
import {
  MeetingProvider,
  useMeeting,
  useParticipant,
  MediaStream,
  RTCView,
} from "@videosdk.live/react-native-sdk";
import { createMeeting, token } from "./api";

function JoinScreen(props) {
  return null;
}

function ControlsContainer() {
  return null;
}

function MeetingView() {
  return null;
}

export default function App() {
  const [meetingId, setMeetingId] = useState(null);

  const getMeetingId = async (id) =&gt; {
    const meetingId = id == null ? await createMeeting({ token }) : id;
    setMeetingId(meetingId);
  };

  return meetingId ? (
    &lt;SafeAreaView style={{ flex: 1, backgroundColor: "#F6F6FF" }}&gt;
      &lt;MeetingProvider
        config={{
          meetingId,
          micEnabled: false,
          webcamEnabled: true,
          name: "Test User",
        }}
        token={token}
      &gt;
        &lt;MeetingView /&gt;
      &lt;/MeetingProvider&gt;
    &lt;/SafeAreaView&gt;
  ) : (
    &lt;JoinScreen getMeetingId={getMeetingId} /&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">App.js</span></p></figcaption></figure><h3 id="step-3-implement-join-screen%E2%80%8B">Step 3: Implement Join Screen<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start#step-3--implement-join-screen">​</a></h3><p>The join screen will serve as a medium to either schedule a new meeting or join an existing one.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">function JoinScreen(props) {
  const [meetingVal, setMeetingVal] = useState("");
  return (
    &lt;SafeAreaView
      style={{
        flex: 1,
        backgroundColor: "#F6F6FF",
        justifyContent: "center",
        paddingHorizontal: 6 * 10,
      }}
    &gt;
      &lt;TouchableOpacity
        onPress={() =&gt; {
          props.getMeetingId();
        }}
        style={{ backgroundColor: "#1178F8", padding: 12, borderRadius: 6 }}
      &gt;
        &lt;Text style={{ color: "white", alignSelf: "center", fontSize: 18 }}&gt;
          Create Meeting
        &lt;/Text&gt;
      &lt;/TouchableOpacity&gt;

      &lt;Text
        style={{
          alignSelf: "center",
          fontSize: 22,
          marginVertical: 16,
          fontStyle: "italic",
          color: "grey",
        }}
      &gt;
        ---------- OR ----------
      &lt;/Text&gt;
      &lt;TextInput
        value={meetingVal}
        onChangeText={setMeetingVal}
        placeholder={"XXXX-XXXX-XXXX"}
        style={{
          padding: 12,
          borderWidth: 1,
          borderRadius: 6,
          fontStyle: "italic",
        }}
      /&gt;
      &lt;TouchableOpacity
        style={{
          backgroundColor: "#1178F8",
          padding: 12,
          marginTop: 14,
          borderRadius: 6,
        }}
        onPress={() =&gt; {
          props.getMeetingId(meetingVal);
        }}
      &gt;
        &lt;Text style={{ color: "white", alignSelf: "center", fontSize: 18 }}&gt;
          Join Meeting
        &lt;/Text&gt;
      &lt;/TouchableOpacity&gt;
    &lt;/SafeAreaView&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">JoinScreen Component</span></p></figcaption></figure><h3 id="step-4-implement-controls%E2%80%8B">Step 4: Implement Controls<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start#step-4--implement-controls">​</a></h3><p>The next step is to create a <code>ControlsContainer</code> component to manage features such as Join or leave a Meeting and Enable or Disable the Webcam/Mic.</p><p>In this step, the <code>useMeeting</code> hook is utilized to acquire all the required methods such as <code>join()</code>, <code>leave()</code>, <code>toggleWebcam</code> and <code>toggleMic</code>.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">const Button = ({ onPress, buttonText, backgroundColor }) =&gt; {
  return (
    &lt;TouchableOpacity
      onPress={onPress}
      style={{
        backgroundColor: backgroundColor,
        justifyContent: "center",
        alignItems: "center",
        padding: 12,
        borderRadius: 4,
      }}
    &gt;
      &lt;Text style={{ color: "white", fontSize: 12 }}&gt;{buttonText}&lt;/Text&gt;
    &lt;/TouchableOpacity&gt;
  );
};

function ControlsContainer({ join, leave, toggleWebcam, toggleMic }) {
  return (
    &lt;View
      style={{
        padding: 24,
        flexDirection: "row",
        justifyContent: "space-between",
      }}
    &gt;
      &lt;Button
        onPress={() =&gt; {
          join();
        }}
        buttonText={"Join"}
        backgroundColor={"#1178F8"}
      /&gt;
      &lt;Button
        onPress={() =&gt; {
          toggleWebcam();
        }}
        buttonText={"Toggle Webcam"}
        backgroundColor={"#1178F8"}
      /&gt;
      &lt;Button
        onPress={() =&gt; {
          toggleMic();
        }}
        buttonText={"Toggle Mic"}
        backgroundColor={"#1178F8"}
      /&gt;
      &lt;Button
        onPress={() =&gt; {
          leave();
        }}
        buttonText={"Leave"}
        backgroundColor={"#FF0000"}
      /&gt;
    &lt;/View&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">ControlsContainer Component</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">function ParticipantList() {
  return null;
}
function MeetingView() {
  const { join, leave, toggleWebcam, toggleMic, meetingId } = useMeeting({});

  return (
    &lt;View style={{ flex: 1 }}&gt;
      {meetingId ? (
        &lt;Text style={{ fontSize: 18, padding: 12 }}&gt;
          Meeting Id :{meetingId}
        &lt;/Text&gt;
      ) : null}
      &lt;ParticipantList /&gt;
      &lt;ControlsContainer
        join={join}
        leave={leave}
        toggleWebcam={toggleWebcam}
        toggleMic={toggleMic}
      /&gt;
    &lt;/View&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">MeetingView Component</span></p></figcaption></figure><h3 id="step-5-render-participant-list%E2%80%8B">Step 5: Render Participant List<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start#step-5--render-participant-list">​</a></h3><p>After implementing the controls, the next step is to render the joined participants.</p><p>You can get all the joined <code>participants</code> from the <code>useMeeting</code> Hook.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">function ParticipantView() {
  return null;
}

function ParticipantList({ participants }) {
  return participants.length &gt; 0 ? (
    &lt;FlatList
      data={participants}
      renderItem={({ item }) =&gt; {
        return &lt;ParticipantView participantId={item} /&gt;;
      }}
    /&gt;
  ) : (
    &lt;View
      style={{
        flex: 1,
        backgroundColor: "#F6F6FF",
        justifyContent: "center",
        alignItems: "center",
      }}
    &gt;
      &lt;Text style={{ fontSize: 20 }}&gt;Press Join button to enter meeting.&lt;/Text&gt;
    &lt;/View&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">ParticipantList Component</span></p></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-js">function MeetingView() {
  // Get `participants` from useMeeting Hook
  const { join, leave, toggleWebcam, toggleMic, participants } = useMeeting({});
  const participantsArrId = [...participants.keys()];

  return (
    &lt;View style={{ flex: 1 }}&gt;
      &lt;ParticipantList participants={participantsArrId} /&gt;
      &lt;ControlsContainer
        join={join}
        leave={leave}
        toggleWebcam={toggleWebcam}
        toggleMic={toggleMic}
      /&gt;
    &lt;/View&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">MeetingView Component</span></p></figcaption></figure><h3 id="step-6-handling-participants-media%E2%80%8B">Step 6: Handling Participant's Media<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/quick-start#step-6--handling-participants-media">​</a></h3><p>Before Handling the Participant's Media, you need to understand a couple of concepts.</p><h4 id="1-useparticipant-hook">1. useParticipant Hook</h4>
<p>The <code>useParticipant</code> hook is responsible for handling all the properties and events of one particular participant who joined the meeting. It will take <code>participantId</code> as argument.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">const { webcamStream, webcamOn, displayName } = useParticipant(participantId);</code></pre><figcaption><p><span style="white-space: pre-wrap;">useParticipant Hook Example</span></p></figcaption></figure><h4 id="2-mediastream-api">2. MediaStream API</h4>
<p>The MediaStream API is beneficial for adding a MediaTrack to the <code>RTCView</code> component, enabling the playback of audio or video.</p><figure class="kg-card kg-code-card"><pre><code class="language-js">&lt;RTCView
  streamURL={new MediaStream([webcamStream.track]).toURL()}
  objectFit={"cover"}
  style={{
    height: 300,
    marginVertical: 8,
    marginHorizontal: 8,
  }}
/&gt;</code></pre><figcaption><p><span style="white-space: pre-wrap;">useParticipant Hook Example</span></p></figcaption></figure><h4 id="rendering-participant-media">Rendering Participant Media</h4>
<figure class="kg-card kg-code-card"><pre><code class="language-js">function ParticipantView({ participantId }) {
  const { webcamStream, webcamOn } = useParticipant(participantId);

  return webcamOn &amp;&amp; webcamStream ? (
    &lt;RTCView
      streamURL={new MediaStream([webcamStream.track]).toURL()}
      objectFit={"cover"}
      style={{
        height: 300,
        marginVertical: 8,
        marginHorizontal: 8,
      }}
    /&gt;
  ) : (
    &lt;View
      style={{
        backgroundColor: "grey",
        height: 300,
        justifyContent: "center",
        alignItems: "center",
      }}
    &gt;
      &lt;Text style={{ fontSize: 16 }}&gt;NO MEDIA&lt;/Text&gt;
    &lt;/View&gt;
  );
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">ParticipantView Component</span></p></figcaption></figure><p>Congratulations! By following these steps, you're on your way to unlocking the video within your application. Now, we are moving forward to integrate the feature that builds immersive video experiences for your users!</p><h2 id="integrate-chat-feature">Integrate Chat Feature</h2><p>For communication or any kind of messaging between participants, VideoSDK provides the <code>usePubSub</code> hook, which utilizes the Publish-Subscribe mechanism. It can be employed to develop a wide variety of functionalities. For example, participants could use it to send chat messages to each other, share files or other media, or even trigger actions like muting or unmuting audio or video.</p><p>This guide focuses on using PubSub to implement Chat functionality. If you are not familiar with the PubSub mechanism and <code>usePubSub</code> hook, you can <a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/pubsub">follow this guide</a>.</p><h3 id="implementing-chat%E2%80%8B">Implementing Chat<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/chat-using-pubsub#implementing-chat">​</a></h3><p>The initial step in setting up a group chat involves selecting a topic to which all participants will publish and subscribe, facilitating the exchange of messages. In the following example, <strong>CHAT</strong> is used as the topic. Next, obtain the <code>publish()</code> method and the messages array from the <code>usePubSub</code> hook.</p><p><strong>Step 1:</strong>  Add another button in <code>ControlsContainer</code> to enable chat functionality and open the Chat Modal.</p><pre><code class="language-js">// MeetingView component to manage the meeting and chat functionality
function MeetingView() {
  const [modalVisible, setModalVisible] = useState(false);

  // Function to toggle the visibility of the modal
  const toggleModal = () =&gt; {
    setModalVisible(!modalVisible);
  };

  return (
    &lt;View style={{ flex: 1 }}&gt;
      {/* Other components for the meeting view */}
      &lt;ChatView modalVisible={modalVisible} toggleModal={toggleModal} /&gt;
      &lt;ControlsContainer
        // other props, join, leave etc.
        enableChat={() =&gt; {
          toggleModal();
        }}
      /&gt;
    &lt;/View&gt;
  );
}


function ControlsContainer({ enableChat }) {
  return (
    // Container for control buttons
    &lt;View
      style={{
        padding: 24,
        flexDirection: "row",
        justifyContent: "space-between",
      }}
    &gt;
      {/* Button to enable chat */}
      &lt;Button
        onPress={() =&gt; {
          enableChat();
        }}
        buttonText={"Chat"}
        backgroundColor={"#1178F8"}
      /&gt;
    &lt;/View&gt;
  );
}

</code></pre><p><strong>Step 2:</strong> Add React Native Modal component to handle chat functionality.</p><pre><code class="language-js">import {
  TextInput,
  Modal,
  Pressable,
} from "react-native";
import {
  usePubSub,
} from "@videosdk.live/react-native-sdk";

// ChatView component for displaying chat messages and input
function ChatView({ modalVisible, toggleModel }) {
  // Destructure publish method from usePubSub hook
  const { publish, messages } = usePubSub("CHAT");

  // State to store the user typed message
  const [message, setMessage] = useState("");

  // Function to handle sending messages
  const handleSendMessage = () =&gt; {
    // Publish the message using the publish method
    publish(message, { persist: true });
    // Clear the message input after sending
    setMessage("");
  };

  return (
    &lt;View
      style={{
        flex: 1,
        justifyContent: "center",
        alignItems: "center",
        marginTop: 22,
      }}
    &gt;
      &lt;Modal animationType="slide" visible={modalVisible}&gt;
        &lt;SafeAreaView
          style={{
            flex: 1,
            backgroundColor: "#050A0E",
            justifyContent: "space-between",
          }}
        &gt;
          &lt;Pressable
            style={{
              height: 40,
              aspectRatio: 1,
              backgroundColor: "#5568FE",
              justifyContent: "center",
              alignItems: "center",
              borderRadius: 24,
              marginTop: 12,
              marginLeft: 12,
            }}
            onPress={toggleModel}
          &gt;
            &lt;Text style={{ fontWeight: "bold", fontSize: 24 }}&gt;X&lt;/Text&gt;
          &lt;/Pressable&gt;
          &lt;View&gt;
            {/* Render chat messages */}
            {messages.map((message) =&gt; {
              return (
                &lt;Text
                  style={{
                    fontSize: 12,
                    color: "#FFFFFF",
                    marginVertical: 8,
                    marginHorizontal: 12,
                  }}
                &gt;
                  {message.senderName} says {message.message}
                &lt;/Text&gt;
              );
            })}

            &lt;View
              style={{
                paddingHorizontal: 12,
              }}
            &gt;
              {/* Render text input container */}
              &lt;TextInputContainer
                message={message}
                setMessage={setMessage}
                sendMessage={handleSendMessage}
              /&gt;
            &lt;/View&gt;
          &lt;/View&gt;
        &lt;/SafeAreaView&gt;
      &lt;/Modal&gt;
    &lt;/View&gt;
  );
}</code></pre><p><strong>Step 3:</strong> Implement the TextInputContainer component for inputting and sending messages.</p><pre><code class="language-js">// TextInputContainer component for inputting and sending messages
function TextInputContainer({ sendMessage, setMessage, message }) {
  // Function to render the text input UI
  const textInput = () =&gt; {
    return (
      &lt;View
        style={{
          height: 40,
          marginBottom: 14,
          flexDirection: "row",
          borderRadius: 10,
          backgroundColor: "#404B53",
        }}
      &gt;
        &lt;View
          style={{
            flexDirection: "row",
            flex: 2,
            justifyContent: "center",
            alignItems: "center",
          }}
        &gt;
          {/* TextInput for typing messages */}
          &lt;TextInput
            multiline
            value={message}
            placeholder={"Write your message"}
            style={{
              flex: 1,
              color: "white",
              marginLeft: 12,
              margin: 4,
              padding: 4,
            }}
            numberOfLines={2}
            onChangeText={setMessage}
            selectionColor={"white"}
            placeholderTextColor={"#9FA0A7"}
          /&gt;
        &lt;/View&gt;

        &lt;View
          style={{
            justifyContent: "center",
            alignItems: "center",
            backgroundColor: message.length &gt; 0 ? "#5568FE" : "transparent",
            margin: 4,
            padding: 4,
            borderRadius: 8,
          }}
        &gt;
          {/* Button to send the message */}
          &lt;TouchableOpacity
            onPress={sendMessage}
            style={{
              height: 40,
              aspectRatio: 1,
              justifyContent: "center",
              alignItems: "center",
              paddingVertical: 8,
              paddingVertical: 4,
            }}
          &gt;
            &lt;Text&gt;Send&lt;/Text&gt;
          &lt;/TouchableOpacity&gt;
        &lt;/View&gt;
      &lt;/View&gt;
    );
  };

  return &lt;&gt;{textInput()}&lt;/&gt;;
}</code></pre><h3 id="private-chat">Private Chat</h3><p>In the following example, to convert the chat into a private conversation between two participants, you can set the <code>sendOnly</code> property. This property ensures that messages are only sent to the intended recipient, making the chat interaction exclusive and private between the two users involved.</p><pre><code class="language-js">import { SafeAreaView, TouchableOpacity, TextInput, Text } from "react-native";

function ChatView() {
  // destructure publish method from usePubSub hook
  const { publish, messages } = usePubSub("CHAT");

  // State to store the user typed message
  const [message, setMessage] = useState("");

  const handleSendMessage = () =&gt; {
    // Sending the Message using the publish method
    // Pass the participantId of the participant to whom you want to send the message.
    // hightlight-next-line
    publish(message, { persist: true, sendOnly: ['XYZ'] });
    // Clearing the message input
    setMessage("");
  };

 //...
}</code></pre><h3 id="downloading-chat-messages%E2%80%8B">Downloading Chat Messages<a href="https://docs.videosdk.live/react-native/guide/video-and-audio-calling-api-sdk/collaboration-in-meeting/chat-using-pubsub#downloading-chat-messages">​</a></h3><p>All the messages from PubSub published  <code>persist : true</code> can be downloaded as an <code>.csv</code> file. This file will be accessible in the VideoSDK dashboard and through the <a href="https://docs.videosdk.live/api-reference/realtime-communication/fetch-session-using-sessionid">Sessions API</a>.</p><h2 id="%E2%9C%A8-want-to-add-more-features-to-react-native-video-calling-app">✨ Want to Add More Features to React Native Video Calling App?</h2><p>If you found this guide helpful and want to explore more features for your React Native video-calling app,</p><p><strong>Check out these additional resources:</strong></p><ul><li>Active Speaker Indication: <a href="https://www.videosdk.live/blog/active-speaker-indication-in-react-native-video-call-app">Link</a></li><li>RTMP Live Stream: <a href="https://www.videosdk.live/blog/integrate-rtmp-in-react-native-video-app">Link</a></li><li>Image Capture Feature: <a href="https://www.videosdk.live/blog/integrate-image-capture-in-react-native-for-android-app">Link</a></li><li>Screen Share Feature in Android: <a href="https://www.videosdk.live/blog/integrate-screen-share-in-react-native-android-video-call-app">Link</a></li><li>Screen Share Feature in iOS: <a href="https://www.videosdk.live/blog/integrate-screen-share-in-react-native-ios-video-call-app">Link</a></li><li>Picture-in-Picture (PiP) Mode: <a href="https://www.videosdk.live/blog/picture-in-picture-pip-in-react-native">Link</a></li></ul><h2 id="conclusion">Conclusion</h2><p>Congratulations!, you have integrated Screen Sharing successfully and unlocked the full potential of real-time communication, enabling users to engage in seamless conversations during video calls. Integrating a chat feature into a React Native video call app using VideoSDK can significantly enhance the user experience.</p><p>If you are new here and want to build an interactive React Native app with free resources, you can <a href="https://www.videosdk.live/signup">Sign up with VideoSDK</a> and get ? <em>10000 free minutes every month</em>. This will help your new video-calling app go to the next level without any costs associated with initial usage, allowing you to focus on building and scaling your application effectively.</p>]]></content:encoded></item><item><title><![CDATA[How to Integrate RTMP Live Stream in Flutter Video Call App?]]></title><description><![CDATA[Learn how to integrate RTMP Live Stream into your Flutter video calling app and transform it into a real-time video calling platform with VideoSDK.
]]></description><link>https://www.videosdk.live/blog/integrate-rtmp-livestream-in-flutter-video-call-app</link><guid isPermaLink="false">661e69322a88c204ca9d413b</guid><category><![CDATA[Flutter]]></category><category><![CDATA[Developer Blog]]></category><dc:creator><![CDATA[Kishan Nakrani]]></dc:creator><pubDate>Wed, 08 Jan 2025 12:30:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/RTMP-Live-Stream-in-Flutter-Video-Call-App.jpg" medium="image"/><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/RTMP-Live-Stream-in-Flutter-Video-Call-App.jpg" alt="How to Integrate RTMP Live Stream in Flutter Video Call App?"/><p>Integrate <a href="https://www.videosdk.live/blog/what-is-rtmp">real-time messaging protocol</a> (RTMP) livestream functionality seamlessly into your <a href="https://www.videosdk.live/blog/video-calling-in-flutter">Flutter video call application</a> for a dynamic and engaging user experience. With RTMP support, users can effortlessly stream live video content, fostering interactive communication within your app. Enable users to broadcast their video feeds in real-time, creating vibrant and immersive virtual gatherings. Implementing RTMP in your Flutter app ensures smooth and efficient live streaming, enhancing the overall quality of video calls.</p><p><strong>Benefits of RTMP Livestream:</strong></p><ol><li><strong>Improved Communication</strong>: RTMP enhances communication by allowing users to share live video content, fostering collaboration and information sharing.</li><li><strong>High-Quality Streaming:</strong> RTMP ensures high-quality video streaming with minimal latency, providing users with a seamless viewing experience.</li><li><strong>Scalability:</strong> With RTMP support, your app can accommodate a large number of simultaneous viewers, making it suitable for hosting virtual events of varying sizes.</li><li><strong>Enhanced User Engagement:</strong> RTMP livestreaming facilitates real-time interaction, keeping users engaged and connected during video calls.</li></ol><p><strong>Use Cases of RTMP Livestream:</strong></p><ol><li><strong>Virtual Events</strong>: Host virtual conferences, concerts, or seminars where participants can stream live video content to engage with the audience in real-time.</li><li><strong>Educational Platforms</strong>: Enable teachers to conduct live lectures and interactive sessions, allowing students to stream video content and ask questions in real-time.</li><li><strong>Remote Work</strong>: Facilitate remote meetings and conferences where participants can share live video presentations and collaborate effectively</li></ol><p>This tutorial VideoSDK provides clear instructions and code examples to help you seamlessly integrate RTMP live streaming into your Flutter video-calling app.</p><h2 id="getting-started-with-videosdk">Getting Started with VideoSDK</h2><p>To integrate RTMP, we must use the capabilities of VideoSDK and what it offers. Before diving into the implementation steps, let's ensure you complete the necessary prerequisites.</p><h3 id="create-a-videosdk-account">Create a VideoSDK Account</h3><p>Go to your <a href="https://app.videosdk.live/dashboard/">VideoSDK dashboard</a> and sign up if you don't have an account. This account gives you access to the required Video SDK token, which acts as an authentication key that allows your application to interact with VideoSDK functionality.</p><h3 id="generate-your-auth-token">Generate your Auth Token</h3><p>Visit your VideoSDK dashboard and navigate to the "API Key" section to generate your auth token. This token is crucial in authorizing your application to use VideoSDK features.</p><p>For a more visual understanding of the account creation and token generation process, consider referring to the <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/authentication-and-tokens#1-generating-token-from-dashboard">provided tutorial</a>.</p><h3 id="prerequisites%E2%80%8B">Prerequisites<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#prerequisites">​</a></h3><p>Before proceeding, ensure that your development environment meets the following requirements:</p><ul><li>Video SDK Developer Account (if you do not have one, follow <a href="https://app.videosdk.live/" rel="noopener noreferrer"><strong>VideoSDK Dashboard</strong></a>)</li><li>The basic understanding of Flutter.</li><li><strong><a href="https://pub.dev/packages/videosdk" rel="noopener noreferrer">Flutter VideoSDK</a></strong></li><li>Have Flutter installed on your device.</li></ul><h2 id="install-videosdk%E2%80%8B">Install VideoSDK<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#install-video-sdk">​</a></h2><p>Install the VideoSDK using the below-mentioned flutter command. Make sure you are in your Flutter app directory before you run this command.</p><pre><code class="language-dart">$ flutter pub add videosdk

//run this command to add http library to perform network call to generate roomId
$ flutter pub add http</code></pre><h3 id="videosdk-compatibility">VideoSDK Compatibility</h3><!--kg-card-begin: html--><table style="border: 1px solid black;">
<thead>
<tr>
<th style="border:1px solid white;">Android and iOS app</th>
<th style="border:1px solid white;">Web</th>
<th style="border:1px solid white;">Desktop app</th>
<th style="border:1px solid white;">Safari browser</th>
</tr>
</thead>
<tbody>
<tr>
<td style="border:1px solid white;"><center> ✅ </center></td>
<td style="border:1px solid white;"><center> ✅ </center></td>
<td style="border:1px solid white;"><center> ✅ </center></td>
<td style="border:1px solid white;"><center> ❌ </center></td>
</tr>
</tbody>
</table>
<!--kg-card-end: html--><h3 id="structure-of-the-project%E2%80%8B">Structure of the project<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#structure-of-the-project">​</a></h3><p>Your project structure should look like this.</p><pre><code class="language-dart">    root
    ├── android
    ├── ios
    ├── lib
         ├── api_call.dart
         ├── join_screen.dart
         ├── main.dart
         ├── meeting_controls.dart
         ├── meeting_screen.dart
         ├── participant_tile.dart</code></pre><p>We are going to create flutter widgets (JoinScreen, MeetingScreen, MeetingControls, and ParticipantTile).</p><h3 id="app-structure%E2%80%8B">App Structure<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#app-structure">​</a></h3><p>The app widget will contain <code>JoinScreen</code> and <code>MeetingScreen</code> widget. <code>MeetingScreen</code> will have <code>MeetingControls</code> and <code>ParticipantTile</code> widget.</p><figure class="kg-card kg-image-card"><img src="https://cdn.videosdk.live/website-resources/docs-resources/flutter_quick_start_arch.png" class="kg-image" alt="How to Integrate RTMP Live Stream in Flutter Video Call App?" loading="lazy"/></figure><h3 id="configure-project">Configure Project</h3><h4 id="for-android%E2%80%8B"><br>For Android<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#for-android">​</a></br></h4><ul><li>Update <code>/android/app/src/main/AndroidManifest.xml</code> for the permissions we will be using to implement the audio and video features.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">&lt;uses-feature android:name="android.hardware.camera" /&gt;
&lt;uses-feature android:name="android.hardware.camera.autofocus" /&gt;
&lt;uses-permission android:name="android.permission.CAMERA" /&gt;
&lt;uses-permission android:name="android.permission.RECORD_AUDIO" /&gt;
&lt;uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /&gt;
&lt;uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" /&gt;
&lt;uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /&gt;
&lt;uses-permission android:name="android.permission.INTERNET"/&gt;
&lt;uses-permission android:name="android.permission.FOREGROUND_SERVICE"/&gt;
&lt;uses-permission android:name="android.permission.WAKE_LOCK" /&gt;</code></pre><figcaption>AndroidManifest.xml</figcaption></figure><ul><li>Also, you will need to set your build settings to Java 8 because the official WebRTC jar now uses static methods in <code>EglBase</code> the interface. Just add this to your app-level <code>/android/app/build.gradle</code>.</li></ul><pre><code class="language-dart">android {
    //...
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}</code></pre><ul><li>If necessary, in the same <code>build.gradle</code> you will need to increase <code>minSdkVersion</code> of <code>defaultConfig</code> up to <code>23</code> (currently default Flutter generator set to <code>16</code>).</li><li>If necessary, in the same <code>build.gradle</code> you will need to increase <code>compileSdkVersion</code> and <code>targetSdkVersion</code> up to <code>33</code> (currently, the default Flutter generator set to <code>30</code>).</li></ul><h4 id="for-ios%E2%80%8B">For iOS<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#for-ios">​</a></h4><ul><li>Add the following entries which allow your app to access the camera and microphone of your <code>/ios/Runner/Info.plist</code> file :</li><li>Uncomment the following line to define a global platform for your project in <code>/ios/Podfile</code> :</li></ul><pre><code class="language-dart">&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Camera Usage!&lt;/string&gt;
&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Microphone Usage!&lt;/string&gt;</code></pre><pre><code class="language-dart"># platform :ios, '12.0'</code></pre><h4 id="for-macos%E2%80%8B">For MacOS<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#for-macos">​</a></h4><ul><li>Add the following entries to your <code>/macos/Runner/Info.plist</code> file that allows your app to access the camera and microphone:</li></ul><pre><code class="language-dart">&lt;key&gt;NSCameraUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Camera Usage!&lt;/string&gt;
&lt;key&gt;NSMicrophoneUsageDescription&lt;/key&gt;
&lt;string&gt;$(PRODUCT_NAME) Microphone Usage!&lt;/string&gt;</code></pre><ul><li>Add the following entries to your <code>/macos/Runner/DebugProfile.entitlements</code> file that allows your app to access the camera, microphone, and open outgoing network connections:</li></ul><pre><code class="language-dart">&lt;key&gt;com.apple.security.network.client&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;com.apple.security.device.camera&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;com.apple.security.device.microphone&lt;/key&gt;
&lt;true/&gt;</code></pre><ul><li>Add the following entries to your <code>/macos/Runner/Release.entitlements</code> file that allows your app to access the camera, microphone, and open outgoing network connections:</li></ul><pre><code class="language-dart">&lt;key&gt;com.apple.security.network.server&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;com.apple.security.network.client&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;com.apple.security.device.camera&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;com.apple.security.device.microphone&lt;/key&gt;
&lt;true/&gt;</code></pre><h2 id="essential-steps-to-implement-video-calling-functionality">Essential Steps to Implement Video Calling Functionality</h2><p>Before diving into the specifics of screen sharing implementation, it's crucial to ensure you have VideoSDK properly installed and configured within your Flutter project. Refer to <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start">VideoSDK's documentation</a> for detailed installation instructions. Once you have a functional video calling setup, you can proceed with adding the screen-sharing feature.</p><h3 id="step-1-get-started-with-apicalldart%E2%80%8B">Step 1: Get started with <code>api_call.dart</code><a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-1-get-started-with-api_calldart">​</a></h3><p>Before jumping to anything else, you will write a function to generate a unique meetingId. You will require an authentication token, you can generate it either by using <a href="https://github.com/videosdk-live/videosdk-rtc-api-server-examples" rel="noopener noreferrer">videosdk-rtc-api-server-examples</a> or by generating it from the <a href="https://app.videosdk.live/api-keys" rel="noopener noreferrer">VideoSDK Dashboard</a> for development.</p><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'dart:convert';
import 'package:http/http.dart' as http;

//Auth token we will use to generate a meeting and connect to it
String token = "&lt;Generated-from-dashboard&gt;";

// API call to create meeting
Future&lt;String&gt; createMeeting() async {
  final http.Response httpResponse = await http.post(
    Uri.parse("https://api.videosdk.live/v2/rooms"),
    headers: {'Authorization': token},
  );

//Destructuring the roomId from the response
  return json.decode(httpResponse.body)['roomId'];
}</code></pre><figcaption>api_call.dart</figcaption></figure><h3 id="step-2-creating-the-joinscreen%E2%80%8B">Step 2: Creating the JoinScreen<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-2--creating-the-joinscreen">​</a></h3><p>Let's create <code>join_screen.dart</code> file in <code>lib</code> directory and create JoinScreen <code>StatelessWidget</code>.</p><p>The JoinScreen will consist of:</p><ul><li><strong>Create Meeting Button</strong>: This button will create a new meeting for you.</li><li><strong>Meeting ID TextField</strong>: This text field will contain the meeting ID, you want to join.</li><li><strong>Join Meeting Button</strong>: This button will join the meeting, which you have provided.</li><li>Update the home screen of the app in the <code>main.dart</code></li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'api_call.dart';
import 'meeting_screen.dart';

class JoinScreen extends StatelessWidget {
  final _meetingIdController = TextEditingController();

  JoinScreen({super.key});

  void onCreateButtonPressed(BuildContext context) async {
    // call api to create meeting and then navigate to MeetingScreen with meetingId,token
    await createMeeting().then((meetingId) {
      if (!context.mounted) return;
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (context) =&gt; MeetingScreen(
            meetingId: meetingId,
            token: token,
          ),
        ),
      );
    });
  }

  void onJoinButtonPressed(BuildContext context) {
    String meetingId = _meetingIdController.text;
    var re = RegExp("\\w{4}\\-\\w{4}\\-\\w{4}");
    // check meeting id is not null or invaild
    // if meeting id is vaild then navigate to MeetingScreen with meetingId,token
    if (meetingId.isNotEmpty &amp;&amp; re.hasMatch(meetingId)) {
      _meetingIdController.clear();
      Navigator.of(context).push(
        MaterialPageRoute(
          builder: (context) =&gt; MeetingScreen(
            meetingId: meetingId,
            token: token,
          ),
        ),
      );
    } else {
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
        content: Text("Please enter valid meeting id"),
      ));
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('VideoSDK QuickStart'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(12.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton(
              onPressed: () =&gt; onCreateButtonPressed(context),
              child: const Text('Create Meeting'),
            ),
            Container(
              margin: const EdgeInsets.fromLTRB(0, 8.0, 0, 8.0),
              child: TextField(
                decoration: const InputDecoration(
                  hintText: 'Meeting Id',
                  border: OutlineInputBorder(),
                ),
                controller: _meetingIdController,
              ),
            ),
            ElevatedButton(
              onPressed: () =&gt; onJoinButtonPressed(context),
              child: const Text('Join Meeting'),
            ),
          ],
        ),
      ),
    );
  }
}</code></pre><figcaption>join_screen.dart</figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'join_screen.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'VideoSDK QuickStart',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: JoinScreen(),
    );
  }
}</code></pre><figcaption>main.dart</figcaption></figure><h3 id="step-3-creating-the-meetingcontrols%E2%80%8B">Step 3: Creating the MeetingControls<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-3--creating-the-meetingcontrols">​</a></h3><p>Let's create <code>meeting_controls.dart</code> file and create MeetingControls <code>StatelessWidget</code>.</p><p>The MeetingControls will consist of:</p><ul><li><strong>Leave Button</strong>: This button will leave the meeting.</li><li><strong>Toggle Mic Button</strong>: This button will unmute or mute the mic.</li><li><strong>Toggle Camera Button</strong>: This button will enable or disable the camera.</li></ul><p>MeetingControls will accept 3 functions in the constructor</p><ul><li><strong>onLeaveButtonPressed</strong>: invoked when the Leave button is pressed.</li><li><strong>onToggleMicButtonPressed</strong>: invoked when the toggle mic button is pressed.</li><li><strong>onToggleCameraButtonPressed</strong>: invoked when the toggle Camera button is pressed.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/material.dart';

class MeetingControls extends StatelessWidget {
  final void Function() onToggleMicButtonPressed;
  final void Function() onToggleCameraButtonPressed;
  final void Function() onLeaveButtonPressed;

  const MeetingControls(
      {super.key,
      required this.onToggleMicButtonPressed,
      required this.onToggleCameraButtonPressed,
      required this.onLeaveButtonPressed});

  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        ElevatedButton(
            onPressed: onLeaveButtonPressed, child: const Text('Leave')),
        ElevatedButton(
            onPressed: onToggleMicButtonPressed, child: const Text('Toggle Mic')),
        ElevatedButton(
            onPressed: onToggleCameraButtonPressed,
            child: const Text('Toggle WebCam')),
      ],
    );
  }
}</code></pre><figcaption>meeting_controls.dart</figcaption></figure><h3 id="step-4-creating-participanttile%E2%80%8B">Step 4: Creating ParticipantTile<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-4--creating-participanttile">​</a></h3><p>Let's create <code>participant_tile.dart</code> file and create ParticipantTile <code>StatefulWidget</code>.</p><p>The ParticipantTile will consist of:</p><ul><li><strong>RTCVideoView</strong>: This will show the participant's video stream.</li></ul><p>ParticipantTile will accept <code>Participant</code> in constructor</p><ul><li><strong>participant:</strong> participant of the meeting.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class ParticipantTile extends StatefulWidget {
  final Participant participant;
  const ParticipantTile({super.key, required this.participant});

  @override
  State&lt;ParticipantTile&gt; createState() =&gt; _ParticipantTileState();
}

class _ParticipantTileState extends State&lt;ParticipantTile&gt; {
  Stream? videoStream;

  @override
  void initState() {
    // initial video stream for the participant
    widget.participant.streams.forEach((key, Stream stream) {
      setState(() {
        if (stream.kind == 'video') {
          videoStream = stream;
        }
      });
    });
    _initStreamListeners();
    super.initState();
  }

  _initStreamListeners() {
    widget.participant.on(Events.streamEnabled, (Stream stream) {
      if (stream.kind == 'video') {
        setState(() =&gt; videoStream = stream);
      }
    });

    widget.participant.on(Events.streamDisabled, (Stream stream) {
      if (stream.kind == 'video') {
        setState(() =&gt; videoStream = null);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: videoStream != null
          ? RTCVideoView(
              videoStream?.renderer as RTCVideoRenderer,
              objectFit: RTCVideoViewObjectFit.RTCVideoViewObjectFitCover,
            )
          : Container(
              color: Colors.grey.shade800,
              child: const Center(
                child: Icon(
                  Icons.person,
                  size: 100,
                ),
              ),
            ),
    );
  }
}</code></pre><figcaption>participant_tile.dart</figcaption></figure><h3 id="step-5-creating-the-meetingscreen%E2%80%8B">Step 5: Creating the MeetingScreen<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/quick-start#step-5--creating-the-meetingscreen">​</a></h3><p>Let's create <code>meeting_screen.dart</code> file and create MeetingScreen <code>StatefulWidget</code>.</p><p>MeetingScreen will accept meetingId and token in the constructor.</p><ul><li><strong>meetingID:</strong> meetingId, you want to join</li><li><strong>token</strong>: VideoSDK Auth token.</li></ul><figure class="kg-card kg-code-card"><pre><code class="language-dart">import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import './participant_tile.dart';

class MeetingScreen extends StatefulWidget {
  final String meetingId;
  final String token;

  const MeetingScreen(
      {super.key, required this.meetingId, required this.token});

  @override
  State&lt;MeetingScreen&gt; createState() =&gt; _MeetingScreenState();
}

class _MeetingScreenState extends State&lt;MeetingScreen&gt; {
  late Room _room;
  var micEnabled = true;
  var camEnabled = true;

  Map&lt;String, Participant&gt; participants = {};

  @override
  void initState() {
    // create room
    _room = VideoSDK.createRoom(
      roomId: widget.meetingId,
      token: widget.token,
      displayName: "John Doe",
      micEnabled: micEnabled,
      camEnabled: camEnabled
    );

    setMeetingEventListener();

    // Join room
    _room.join();

    super.initState();
  }

  // listening to meeting events
  void setMeetingEventListener() {
    _room.on(Events.roomJoined, () {
      setState(() {
        participants.putIfAbsent(
            _room.localParticipant.id, () =&gt; _room.localParticipant);
      });
    });

    _room.on(
      Events.participantJoined,
      (Participant participant) {
        setState(
          () =&gt; participants.putIfAbsent(participant.id, () =&gt; participant),
        );
      },
    );

    _room.on(Events.participantLeft, (String participantId) {
      if (participants.containsKey(participantId)) {
        setState(
          () =&gt; participants.remove(participantId),
        );
      }
    });

    _room.on(Events.roomLeft, () {
      participants.clear();
      Navigator.popUntil(context, ModalRoute.withName('/'));
    });
  }

  // onbackButton pressed leave the room
  Future&lt;bool&gt; _onWillPop() async {
    _room.leave();
    return true;
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () =&gt; _onWillPop(),
      child: Scaffold(
        appBar: AppBar(
          title: const Text('VideoSDK QuickStart'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              Text(widget.meetingId),
              //render all participant
              Expanded(
                child: Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: GridView.builder(
                    gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                      crossAxisSpacing: 10,
                      mainAxisSpacing: 10,
                      mainAxisExtent: 300,
                    ),
                    itemBuilder: (context, index) {
                      return ParticipantTile(
                        key: Key(participants.values.elementAt(index).id),
                          participant: participants.values.elementAt(index));
                    },
                    itemCount: participants.length,
                  ),
                ),
              ),
              MeetingControls(
                onToggleMicButtonPressed: () {
                  micEnabled ? _room.muteMic() : _room.unmuteMic();
                  micEnabled = !micEnabled;
                },
                onToggleCameraButtonPressed: () {
                  camEnabled ? _room.disableCam() : _room.enableCam();
                  camEnabled = !camEnabled;
                },
                onLeaveButtonPressed: () {
                  _room.leave()
                },
              ),
            ],
          ),
        ),
      ),
      home: JoinScreen(),
    );
  }
}</code></pre><figcaption>meeting_screen.dart</figcaption></figure><blockquote><strong>CAUTION</strong><br>If you get <code>webrtc/webrtc.h file not found</code> error at a runtime in iOS, then check the solution <a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/known-issues#issue--1" rel="noopener noreferrer">here</a>.</br></blockquote><blockquote><strong>TIP</strong>:<br>You can checkout the complete <a href="https://github.com/videosdk-live/quickstart/tree/main/flutter-rtc" rel="noopener noreferrer">quick start example here</a>.</br></blockquote><h2 id="integrate-rtmp-livestream-feature">Integrate RTMP Livestream Feature</h2><p>RTMP is a popular protocol for live streaming video content from a VideoSDK to platforms such as YouTube, Twitch, Facebook, and others.</p><p>By providing the platform-specific stream key and stream URL, the VideoSDK can connect to the platform's RTMP server and transmit the live video stream.</p><p>VideoSDK allows you to live stream your meeting to a platform that supports RTMP ingestion just by providing the platform-specific stream key and stream URL, we can connect to the platform's RTMP server and transmit the live video stream.</p><p>VideoSDK also allows you to configure the livestream layouts in numerous ways, like by simply setting different prebuilt layouts in the configuration or by providing your own custom template to do the live stream according to your layout choice.</p><p>After installing videoSDK, you can unlock the power of live streaming by following these steps:</p><h3 id="start-livestream">Start Livestream</h3><p><code>startLivestream()</code> can be used to start an RTMP live stream of the meeting, which can be accessed from the <code>Room</code> object. This method accepts two parameters:</p><ul><li><code>1. outputs</code>: This parameter accepts an array of objects that contains the RTMP <code>url</code> and <code>streamKey</code> of the platforms, you want to start the live stream.</li><li><code>2. config (optional)</code>: This parameter will define what the live stream layout should look like.</li></ul><pre><code class="language-dart">var outputs = [
  {
    url: "rtmp://a.rtmp.youtube.com/live2",
    streamKey: "&lt;STREAM_KEY&gt;",
  },
  {
    url: "rtmps://",
    streamKey: "&lt;STREAM_KEY&gt;",
  },
];
Map&lt;String, dynamic&gt; config = {
  // Layout Configuration
  layout: {
    type: "GRID", // "SPOTLIGHT" | "SIDEBAR",  Default : "GRID"
    priority: "SPEAKER", // "PIN", Default : "SPEAKER"
    gridSize: 4, // MAX : 4
  },

  // Theme of livestream
  theme: "DARK", //  "LIGHT" | "DEFAULT"
};

room.startLivestream(outputs,config:config);</code></pre><h3 id="stop-live-stream">Stop Live Stream</h3><ul><li><code>stopLivestream()</code> is used to stop the meeting live stream which can be accessed from the <code>Room</code> object.</li></ul><h3 id="event-associated-with-livestream%E2%80%8B">Event associated with Livestream<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/recording-and-live-streaming/rtmp-livestream#event-associated-with-livestream">​</a></h3><p><strong>livestreamStateChanged</strong>: Whenever the livestream state changes, then <code>livestreamStateChanged</code> the event will trigger.</p><pre><code class="language-dart">import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';

class MeetingScreen extends StatefulWidget {
  ...
}

class _MeetingScreenState extends State&lt;MeetingScreen&gt; {
  late Room room;

  @override
  void initState() {
    ...

    setupRoomEventListener();
  }

  @override
  Widget build(BuildContext context) {
    return YourMeetingWidget();
  }

  void setupRoomEventListener() {
  	//...
    room.on(Events.livestreamStateChanged, (String status) {
      //Status can be :: LIVESTREAM_STARTING
      //Status can be :: LIVESTREAM_STARTED
      //Status can be :: LIVESTREAM_STOPPING
      //Status can be :: LIVESTREAM_STOPPED
      log("Meeting Livestream status : $status");
    });
  }
}</code></pre><h2 id="example">Example</h2><ul><li>Let's create <code>LiveStreamControls</code> widget which will help to toggle RTMP LiveStream.</li></ul><pre><code class="language-dart">import 'package:flutter/material.dart';

class LiveStreamControls extends StatelessWidget {
  final String liveStreamState;
  final void Function() onToggleLiveStreamButtonPressed;

  const LiveStreamControls({
    super.key,
    required this.liveStreamState,
    required this.onToggleLiveStreamButtonPressed,
  });

  @override
  Widget build(BuildContext context) {
    return Wrap(
      children: [
        ElevatedButton(
            onPressed: onToggleLiveStreamButtonPressed,
            child: Text(liveStreamState == "LIVESTREAM_STOPPED"
                ? 'Start LiveStream'
                : liveStreamState == "LIVESTREAM_STARTING"
                    ? "Starting LiveStream"
                    : liveStreamState == "LIVESTREAM_STARTED"
                        ? "Stop LiveStream"
                        : liveStreamState == "LIVESTREAM_STOPPING"
                            ? "Stopping LiveStream"
                            : "Start LiveStream")),
      ],
    );
  }
}
</code></pre><ul><li>Now, we will add <code>LiveStreamControls</code> widget in <code>MeetingScreen</code> after <code>MeetingControls</code> widget.</li><li>Also, we will listen to <code>liveStreamStateChanged</code> event when the meeting's livestream status changed.</li></ul><pre><code class="language-dart">import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:videosdk/videosdk.dart';
import './participant_tile.dart';
import './livestream_controls.dart';

class MeetingScreen extends StatefulWidget {
  //...
}

class _MeetingScreenState extends State&lt;MeetingScreen&gt; {
  late Room _room;
  var micEnabled = true;
  var camEnabled = true;
  String liveStreamState = "LIVESTREAM_STOPPED";

  Map&lt;String, Participant&gt; participants = {};

  @override
  void initState() {
    // create room
    //...
  }

  // listening to meeting events
  void setMeetingEventListener() {
    // ...
	widget.room.on(
      Events.liveStreamStateChanged,
      (String status) {
        setState(
          () =&gt; liveStreamState = status,
        );
      },
    );
  }

  // onbackButton pressed leave the room
  Future&lt;bool&gt; _onWillPop() async {
    _room.leave();
    return true;
  }

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () =&gt; _onWillPop(),
      child: Scaffold(
        appBar: AppBar(
          title: const Text('VideoSDK QuickStart'),
        ),
        body: Padding(
          padding: const EdgeInsets.all(8.0),
          child: Column(
            children: [
              // ...,
              LiveStreamControls(
                onToggleLiveStreamButtonPressed: () {
                  if (liveStreamState == "LIVESTREAM_STOPPED") {
                    var outputs = [
                      {
                        "url": "&lt;URL&gt;",
                        "streamKey": "&lt;Stream-Key&gt;",
                      }
                    ];
                    var liveStreamConfig = {
                      'layout': {
                        'type': 'GRID',
                        'priority': 'SPEAKER',
                        'gridSize': 4,
                      },
                      'theme': "LIGHT",
                    };
                    widget.room.startLivestream(outputs,config: liveStreamConfig);
                  } else if (liveStreamState == "LIVESTREAM_STARTED") {
                    widget.room.stopLivestream();
                  }
                },
                liveStreamState: liveStreamState,
                ),
            ],
          ),
        ),
      ),
      home: JoinScreen(),
    );
  }
}</code></pre><h3 id="custom-template%E2%80%8B">Custom Template<a href="https://docs.videosdk.live/flutter/guide/video-and-audio-calling-api-sdk/recording-and-live-streaming/rtmp-livestream#custom-template">​</a></h3><p>With VideoSDK, you can also use your own custom designed layout template to live stream the meetings. To use the custom template, you need to create a template, for which you can <a href="https://docs.videosdk.live/react/guide/interactive-live-streaming/custom-template">follow this guide</a>. Once you have set up the template, you can use the <a href="https://docs.videosdk.live/api-reference/realtime-communication/start-livestream">REST API to start</a> the live stream with the <code>templateURL</code> parameter.</p><h2 id="conclusion">Conclusion</h2><p>Integrating RTMP livestream functionality into your Flutter video call app offers numerous benefits and opens up a wide range of use cases. With seamless RTMP support, users can engage in high-quality, real-time video streaming, enhancing communication and collaboration within your application. Embrace the versatility and scalability of RTMP in your Flutter app to elevate user engagement, foster meaningful connections, and provide a platform for diverse multimedia experiences.</p><p>Unlock the full potential of VideoSDK and craft seamless video experiences effortlessly. Sign up with VideoSDK today and receive 10,000 free minutes to propel your video app to the next level.</p>]]></content:encoded></item><item><title><![CDATA[React Native App Development: A Practical Guide for Teams]]></title><description><![CDATA[React Native allows developers to build native iOS and Android applications using a single JavaScript codebase. This guide covers how the framework operates under the hood, the performance trade-offs, and production patterns that actually work.]]></description><link>https://www.videosdk.live/blog/react-native</link><guid isPermaLink="false">66210a2a2a88c204ca9d4483</guid><dc:creator><![CDATA[Video SDK Team]]></dc:creator><pubDate>Wed, 08 Jan 2025 12:29:00 GMT</pubDate><media:content url="https://assets.videosdk.live/static-assets/ghost/2024/04/pexels-realtoughcandy-11035471.jpg" medium="image"/><content:encoded><![CDATA[<blockquote>React Native is a cross-platform mobile development framework created by Meta. It allows developers to build native iOS and Android applications using a single JavaScript codebase. For engineering teams, this reduces time-to-market and simplifies maintenance while delivering a user experience indistinguishable from natively built applications.</blockquote><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/pexels-realtoughcandy-11035471.jpg" alt="React Native App Development: A Practical Guide for Teams"/><p>Pick the wrong mobile framework, and your team will spend months rewriting code for different platforms. <a href="https://reactnative.dev/" rel="noreferrer">React Native</a> solves this by letting you write JavaScript that renders into real native UI components. You get the speed of web development with the performance of native apps. This guide covers how the framework operates under the hood, the performance trade-offs you must consider, and the production patterns that actually work when deploying your application to millions of users.</p><h2 id="what-is-react-native">What is React Native?</h2><p>React Native is defined as an open-source UI software framework used to develop cross-platform applications for mobile and desktop environments. React Native works by invoking native rendering APIs in Objective-C for iOS or Java for Android through an asynchronous JavaScript bridge.</p><p>Unlike hybrid frameworks that render web views inside a native wrapper, React Native translates your JavaScript components into their native platform equivalents. A text element in your code becomes an actual native text view on the device. This approach provides a massive performance advantage over older cross-platform solutions because the user interacts with authentic OS-level interface elements.</p><p>Developers choose this framework because it unites two previously distinct worlds. You can maintain a single codebase for multiple platforms, drastically cutting down on engineering hours. At the same time, the end user interacts with a fully native interface. This balance of developer velocity and user experience has made it the default choice for many technology companies.</p><p>According to the 2023 Stack Overflow Developer Survey, React Native remains one of the <a href="https://medium.com/@Nectarbitss/why-react-native-is-still-the-best-choice-for-cross-platform-app-development-in-2025-40d0ea2716bb" rel="noreferrer">most popular mobile frameworks</a> globally. Its ecosystem includes thousands of community-maintained libraries, meaning you rarely have to build complex features from scratch. Because the framework shares a design paradigm with React for the web, engineering organizations can often share frontend engineers across web and mobile teams seamlessly.</p><h3 id="how-does-react-native-work">How does react native work?</h3><figure class="kg-card kg-image-card"><img src="https://assets.videosdk.live/static-assets/ghost/2024/04/image-5.png" class="kg-image" alt="React Native App Development: A Practical Guide for Teams" loading="lazy" width="1365" height="603"/></figure><h3 id="who-uses-react-native">Who Uses React Native?</h3><p>From tech startups to big corporations, React Native has been adopted by a variety of companies looking to streamline their mobile development processes. Companies like Instagram, Tesla, and Airbnb have utilized React Native to enhance their mobile applications, leveraging its ability to integrate seamlessly with existing code while providing a native user experience​.</p><h3 id="why-react-native-is-popular">Why React Native is Popular</h3><p>One of the main reasons for React Native's popularity is its efficiency in <a href="https://www.empat.tech/services/custom-mobile-app-development-services" rel="noreferrer">developing mobile applications</a>. Developers can use hot reloading features, which allow them to see the results of their latest changes instantly without recompiling the entire application. This feature not only speeds up the development process but also makes it more dynamic and responsive to changes.</p><p>Furthermore, React Native supports components and APIs that enable interaction with device functionality like the camera and location services, making it highly versatile for comprehensive app development. The framework’s focus on user interface (UI) renders applications that are not only highly functional but also visually appealing​ (<a href="https://reactnative.dev/docs/getting-started" rel="noreferrer">ReactNativeLearn</a>)​​ (<a href="https://reactnativecentral.com/react-native-essentials-flexbox-guide/" rel="noreferrer">React Native Central</a>)​.</p><h3 id="key-features-of-react-native">Key Features of React Native</h3><p>React Native is lauded for its rich set of features that cater to both developers and users:</p><ul><li><strong>Cross-Platform Development</strong>: Code written in React Native can be deployed on both iOS and Android, which reduces the time and cost associated with app development.</li><li><strong>Native Components</strong>: React Native uses components that are native to the user’s device platform, which ensures that the look and feel of the app conforms to the norms of the device’s OS.</li><li><strong>JavaScript Interface</strong>: Utilizing JavaScript, one of the most popular programming languages, React Native makes it easier for web developers to transition into mobile development, leveraging their existing skills​ (<a href="https://www.reactnative.express/" rel="noreferrer">React Native Express</a>)​​ (<a href="https://blog.logrocket.com/react-native-track-player-complete-guide/" rel="noreferrer">LogRocket Blog</a>)​.</li></ul><p>As the mobile development landscape continues to evolve, React Native stands out as a powerful tool that simplifies the creation of robust, efficient, and aesthetically pleasing mobile applications. It not only helps in faster development cycles but also maintains high performance and native aesthetics, making it a preferred choice for many developers around the world.</p><h2 id="setting-up-your-development-environment">Setting Up Your Development Environment</h2><p>To start developing with React Native, the first critical step is setting up your development environment. This process ensures you have all necessary tools and dependencies installed, enabling you to create and run React Native applications on your computer. Below we'll go through how to prepare your development environment for both iOS and Android platforms.</p><h3 id="installation-and-environment-setup">Installation and Environment Setup</h3><ul><li><strong>Node.js and Watchman</strong>: Begin by installing Node.js, which includes npm (Node Package Manager). This is essential as it helps manage the packages required for React Native development. Additionally, install Watchman, a tool developed by Facebook for watching changes in the filesystem. It's particularly useful in development for hot reloading​ (<a href="https://reactnative.dev/docs/environment-setup" rel="noreferrer">ReactNativeLearn</a>)​.</li><li><strong>React Native CLI</strong>: While you can use Expo CLI for a managed app development experience, installing React Native CLI allows for more control and is necessary for apps that require custom native code. Use npm to install the React Native CLI globally on your system </li></ul><pre><code class="language-js">npm install -g react-native-cli</code></pre><ul><li><strong>Java Development Kit (JDK)</strong>: Install JDK if you are planning to develop Android applications. It’s used to compile your app’s code.</li></ul><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://assets.videosdk.live/static-assets/ghost/2026/06/ChatGPT-Image-Jun-5--2026--01_06_30-PM.png" class="kg-image" alt="React Native App Development: A Practical Guide for Teams" loading="lazy" width="1536" height="1024"><figcaption><span style="white-space: pre-wrap;">React Native architecture diagram</span></figcaption></img></figure><h3 id="tools-and-editors-for-react-native-app">Tools and Editors for React Native app</h3><ol><li><strong>Code Editor</strong>: A reliable code editor is crucial. Visual Studio Code (VS Code) is highly recommended for React Native development due to its robust ecosystem of extensions and built-in support for JavaScript and React Native.</li><li><strong>Android Studio and Xcode</strong>: For Android development, Android Studio provides the necessary SDKs and tools to build your apps. It also includes an emulator to test your apps. For iOS development, Xcode is indispensable as it contains the iOS SDK, simulator, and other tools needed for iOS app development​ (<a href="https://reactnative.dev/docs/environment-setup" rel="noreferrer">ReactNativeLearn</a>)​.</li><li><strong>iOS and Android Emulators</strong>: After installing Android Studio and Xcode, set up the emulators. These allow you to run and test your applications on different virtual devices without needing actual hardware.</li></ol><h3 id="preparing-the-devices-for-react-native-app">Preparing the Devices for React Native app</h3><ul><li><strong>Android Device Preparation</strong>: If you choose to use a physical Android device, enable USB debugging found in the developer options. This setting allows your development environment to interface with your device, enabling live application testing​ (<a href="https://reactnative.dev/docs/environment-setup" rel="noreferrer">ReactNativeLearn</a>)​.</li><li><strong>iOS Simulator Setup</strong>: With Xcode installed, access the iOS simulator through the Xcode development environment. It simulates iOS devices on your Mac, allowing for straightforward app testing and debugging.</li></ul><h3 id="running-your-first-react-native-app">Running Your First React Native App</h3><p>Once your environment is configured, you can start your first project and test it:</p><p><strong>Creating a New App</strong>:</p><pre><code class="language-bash">react-native init MyNewProject</code></pre><p>This command sets up a new React Native project with all necessary files and folders.</p><p><strong>Running the App</strong>:</p><ul><li>For Android:</li></ul><pre><code class="language-bash">react-native run-android</code></pre><ul><li>For iOS:</li></ul><pre><code class="language-bash">react-native run-ios </code></pre><p>These commands compile the app and launch it on the respective simulator or physical device, giving you a firsthand look at how your app appears and operates on mobile devices​ (<a href="https://reactnative.dev/docs/environment-setup" rel="noreferrer">ReactNativeLearn</a>)​.</p><h2 id="basic-components-and-api-for-react-native-app">Basic Components and API for React Native app</h2><p>Building React Native applications involves using a variety of components and APIs that enable you to create feature-rich, interactive, and efficient mobile apps. In this section, we will explore the core components of React Native and how to work with external APIs within your applications.</p><h4 id="core-components">Core Components</h4><p>React Native offers several built-in components that are essential for any <a href="https://www.suffescom.com/mobile-app-development-company">mobile app development</a>. These components are the building blocks that you will use to construct the user interface of your app:</p><ol><li><strong>View</strong>: The most fundamental component for building a UI, <code>View</code> is a container that supports layout with flexbox, style, some touch handling, and accessibility controls. It is similar to the <code>div</code> in web development​​.</li><li><strong>Text</strong>: To display text in your app, you use the <code>Text</code> component. It supports nesting, styling, and touch handling. It is essential for any kind of text representation in your app​​.</li><li><strong>Image</strong>: The <code>Image</code> component is used to display different types of images, including network images, static resources, temporary local images, and images from local disk, like the camera roll​​.</li><li><strong>ScrollView</strong>: For creating a scrolling view within your app, <code>ScrollView</code> is used. It can host multiple components and views that can be scrolled using gestures​​.</li><li><strong>TextInput</strong>: To capture user input, <code>TextInput</code> is a component that allows users to input text into an app. It's essential for forms, search bars, and anything else that requires the user to enter text​ ​.</li><li><strong>Button</strong>: A simple touchable button is provided by the <code>Button</code> component. It comes with a few customization options, like title, color, and a simple handler for user taps​​.</li></ol><h3 id="working-with-apis">Working with APIs</h3><p>React Native enables developers to integrate a wide range of APIs to extend the functionality of apps. Here’s how you can work with APIs:</p><p><strong>Fetching Data</strong>: To fetch data from the web, you can use the <code>fetch</code> function, which works similarly to how it works in modern web browsers. Here is a basic example of using fetch to retrieve data from an API:javascript.</p><pre><code class="language-javascript">fetch('https://api.example.com/data')
  .then((response) =&gt; response.json())
  .then((json) =&gt; console.log(json))
  .catch((error) =&gt; console.error(error));</code></pre><p><strong>Integrating Third-Party APIs</strong>: React Native allows the integration of third-party APIs for added functionalities such as Google Maps or social media services. This usually involves installing a third-party library and linking it to your React Native project​​.</p><p><strong>Using Native Modules</strong>: Sometimes, you might need functionality that is not available in JavaScript APIs. In such cases, React Native allows you to create your own native modules in Java (for Android) or Objective-C/Swift (for iOS)​ (<a href="https://blog.risingstack.com/a-definitive-react-native-guide-for-react-developers/" rel="noreferrer">RisingStack Engineering</a>)​.</p><p>Understanding and utilizing these components and APIs will allow you to create versatile and robust applications. React Native's component-based structure also helps in managing the codebase and reusing code across different parts of your app, making the development process efficient and modular.</p><h2 id="advanced-features-and-techniques-for-react-native-app">Advanced Features and Techniques for React Native app</h2><p>As you become more familiar with the basics of React Native, you can begin to explore more advanced features and techniques that will allow you to build sophisticated and high-performing mobile applications. This part of the article covers navigation and routing, state management, and performance optimization in React Native.</p><h4 id="navigation-and-routing">Navigation and Routing</h4><p>Handling navigation is a fundamental aspect of mobile development. React Native does not include a built-in library for navigation, so developers typically use third-party solutions such as React Navigation. Here's how you can set up and use React Navigation in your app:</p><ol><li><strong>Installation</strong>: Install React Navigation via npm or yarn:</li></ol><pre><code class="language-bash">npm install @react-navigation/native</code></pre><pre><code class="language-bash">yarn add @react-navigation/native</code></pre><ol><li>You also need to install dependencies that link into the native platform, <code>react-native-screens</code> and <code>react-native-safe-area-context</code>.</li><li><strong>Setting Up a Navigator</strong>: React Navigation offers various types of navigators, such as stack, tab, and drawer navigators. Here's a simple example of setting up a stack navigator:</li></ol><pre><code class="language-javascript">import { createStackNavigator } from '@react-navigation/stack';
const Stack = createStackNavigator();

function MyStack() {
  return (
    &lt;Stack.Navigator&gt;
      &lt;Stack.Screen name="Home" component={HomeScreen} /&gt;
      &lt;Stack.Screen name="Details" component={DetailsScreen} /&gt;
    &lt;/Stack.Navigator&gt;
  );
}</code></pre><ol><li>This setup enables navigation between the Home and Details screens​ (<a href="https://blog.risingstack.com/a-definitive-react-native-guide-for-react-developers/" rel="noreferrer">RisingStack Engineering</a>)​.</li></ol><h4 id="state-management">State Management</h4><p>For complex applications, managing state can become cumbersome with React's built-in state management alone. Many React Native developers turn to external libraries such as Redux or Context API to make state management more manageable:</p><ol><li><strong>Using Redux</strong>: Redux provides a predictable state container for JavaScript apps, helping you write applications that behave consistently. It's especially useful in large-scale applications where state management can get complicated​ (<a href="https://blog.risingstack.com/a-definitive-react-native-guide-for-react-developers/" rel="noreferrer">RisingStack Engineering</a>)​.</li><li><strong>Context API</strong>: For simpler or medium-scale applications, the Context API might be sufficient. It allows you to share values between components without having to explicitly pass a prop through every level of the tree​.</li></ol><h3 id="performance-optimization">Performance Optimization</h3><p>Optimizing the performance of a React Native app is crucial for maintaining a smooth and responsive user experience. Here are some strategies to enhance your app’s performance:</p><ol><li><strong>Reduce Render Cycles</strong>: Use React’s <code>shouldComponentUpdate</code>, <code>React.memo</code>, or <code>PureComponent</code> to prevent unnecessary re-renders of your components.</li><li><strong>Optimize Images</strong>: Large images can significantly impact performance. You should <a href="https://picsart.com/photo-editor/" rel="noreferrer">edit photos</a> to resize them to the smallest size needed and convert them to appropriate image formats, while also considering lazy loading images only when necessary. (<a href="https://www.freecodecamp.org/news/react-native-guide/" rel="noreferrer">FreeCodeCamp</a>)​​ (<a href="https://reactnativecentral.com/react-native-essentials-flexbox-guide/" rel="noreferrer">React Native Central</a>)​.</li><li><strong>Use Native Modules Wisely</strong>: When you need more performance, native modules can be written in native code to optimize specific parts of your application, such as heavy computation tasks or animation​ (<a href="https://www.reactnative.express/" rel="noreferrer">React Native Express</a>)​.</li></ol><p>Understanding these advanced features and techniques will not only improve the quality of your applications but also your efficiency as a developer. As you incorporate these practices, you’ll find that your React Native apps perform better and offer a more seamless user experience.</p><h2 id="building-and-deploying-your-react-native-app">Building and Deploying Your React Native App</h2><p>After developing your React Native app, the next crucial steps are building it for production and deploying it to app stores. This process involves several important stages, from ensuring your app meets platform-specific guidelines to actual publication in the App Store and Google Play Store. Here's a comprehensive guide to building and deploying your React Native application.</p><h4 id="building-for-android-and-ios">Building for Android and iOS</h4><p>Building a React Native app for Android and iOS involves different processes due to the distinct nature of each platform. Here are the essential steps for each:</p><h3 id="android">Android:</h3><ul><li><strong>Generating a Signed APK</strong>: Android requires that all apps be digitally signed with a certificate before they can be installed. To generate a signed APK, you need to create a keystore file, then configure your app’s <code>gradle</code> files to include the keystore details.</li><li><strong>Running the Build</strong>: Use the following command to create an APK file</li></ul><pre><code class="language-bash">cd android &amp;&amp; ./gradlew assembleRelease</code></pre><p>This command compiles the release version of your app for Android, ready to be distributed on the Play Store​ (<a href="https://reactnative.dev/docs/environment-setup" rel="noreferrer">ReactNativeLearn</a>)​.</p><h3 id="ios">iOS:</h3><ul><li><strong>Xcode Build Settings</strong>: Open your app’s project file in Xcode, and ensure all build settings are correctly configured for the target iOS devices. This includes setting the device orientations, version number, and build identifier.</li><li><strong>Archiving the App</strong>: Use Xcode to archive the iOS app. This process prepares your app for distribution, either through the App Store or via other means like ad-hoc distribution.</li><li><strong>Export the IPA</strong>: Once archived, you can export the packaged IPA file from Xcode, which is ready for submission to the App Store​ (<a href="https://reactnative.dev/docs/environment-setup" rel="noreferrer">ReactNativeLearn</a>)​.</li></ul><h3 id="deployment">Deployment</h3><p>Deploying your app to the App Store and Google Play requires following specific guidelines provided by each platform:</p><p><strong>Google Play Store</strong>:</p><ul><li><strong>Create a Developer Account</strong>: You will need a Google Developer Account to submit apps to the Google Play Store. This involves a one-time registration fee.</li><li><strong>Prepare Store Listing</strong>: This includes details like app title, description, screenshots, and privacy policies.</li><li><strong>Upload APK and Publish</strong>: Once your APK is ready and all listing details are set, upload the APK through the Google Play Console and submit it for review​ (<a href="https://reactnative.dev/docs/environment-setup" rel="noreferrer">ReactNativeLearn</a>)​​ (<a href="https://blog.risingstack.com/a-definitive-react-native-guide-for-react-developers/" rel="noreferrer">RisingStack Engineering</a>)​.</li></ul><p><strong>Apple App Store</strong>:</p><ul><li><strong>Apple Developer Program</strong>: Enrollment in the Apple Developer Program is necessary to submit apps to the App Store and requires an annual fee.</li><li><strong>Prepare App Store Listing</strong>: Similar to Google Play, you’ll need to provide your app’s metadata, screenshots, and a preview video.</li><li><strong>Submit for Review</strong>: Using Xcode, submit your app for review. Apple’s review process can take from a few days to a couple of weeks, depending on the app’s complexity and adherence to guidelines​ (<a href="https://reactnative.dev/docs/environment-setup" rel="noreferrer">ReactNativeLearn</a>)​​ (<a href="https://blog.risingstack.com/a-definitive-react-native-guide-for-react-developers/" rel="noreferrer">RisingStack Engineering</a>)​.</li></ul><h3 id="maintaining-and-updating-your-app">Maintaining and Updating Your App</h3><p>After your app is live, maintaining and regularly updating it is crucial to keep it relevant and functional. Monitor user feedback and crash reports to address any issues and regularly update the app with improvements and new features. Both the Google Play Store and Apple App Store provide tools to analyze app performance and user engagement, which can help guide your updates​ (<a href="https://www.freecodecamp.org/news/react-native-guide/" rel="noreferrer">FreeCodeCamp</a>)​​​.</p><h3 id="examples-of-applications-built-with-react-native">Examples of applications built with React Native</h3><p>React Native, a highly favored technology among developers globally, powers numerous cross-platform applications. Below are some prominent examples:</p><table>
<thead>
<tr>
<th>Application</th>
<th>App Store Link</th>
<th>Google Play Link</th>
</tr>
</thead>
<tbody>
<tr>
<td>Facebook</td>
<td><a href="https://apps.apple.com/us/app/facebook/id284882215">Facebook on the App Store</a></td>
<td><a href="https://play.google.com/store/apps/details?id=com.facebook.katana">Facebook on Google Play</a></td>
</tr>
<tr>
<td>Pinterest</td>
<td><a href="https://apps.apple.com/us/app/pinterest/id429047995">Pinterest on the App Store</a></td>
<td><a href="https://play.google.com/store/apps/details?id=com.pinterest">Pinterest on Google Play</a></td>
</tr>
<tr>
<td>Oculus</td>
<td><a href="https://apps.apple.com/us/app/oculus/id1366478176">Oculus on the App Store</a></td>
<td><a href="https://play.google.com/store/apps/details?id=com.oculus.twilight">Oculus on Google Play</a></td>
</tr>
<tr>
<td>Salesforce</td>
<td><a href="https://apps.apple.com/us/app/salesforce/id404249815">Salesforce on the App Store</a></td>
<td><a href="https://play.google.com/store/apps/details?id=com.salesforce.chatter">Salesforce on Google Play</a></td>
</tr>
<tr>
<td>Airbnb</td>
<td><a href="https://apps.apple.com/us/app/airbnb/id401626263">Airbnb on the App Store</a></td>
<td><a href="https://play.google.com/store/apps/details?id=com.airbnb.android">Airbnb on Google Play</a></td>
</tr>
<tr>
<td>Coinbase</td>
<td><a href="https://apps.apple.com/us/app/coinbase-buy-sell-bitcoin/id886427730">Coinbase on the App Store</a></td>
<td><a href="https://play.google.com/store/apps/details?id=com.coinbase.android">Coinbase on Google Play</a></td>
</tr>
<tr>
<td>Shopify</td>
<td><a href="https://apps.apple.com/us/app/shopify-point-of-sale-pos/id507131708">Shopify on the App Store</a></td>
<td><a href="https://play.google.com/store/apps/details?id=com.shopify.mpos">Shopify on Google Play</a></td>
</tr>
</tbody>
</table>
<p>By carefully following these steps, you can ensure that your React Native app is well-prepared for release, helping to facilitate a smooth approval process on both the Google Play Store and Apple App Store. Successful deployment is not just about building a functional app but also about crafting an engaging store presence and maintaining a strong update cycle.</p><h3 id="community-and-resources">Community and Resources</h3><p>In the dynamic world of software development, continuous learning and community engagement are key to staying updated with the latest trends and advancements. React Native, being a widely-used and rapidly evolving framework, has a robust ecosystem of resources and a supportive community. This section will guide you through the best ways to engage with the React Native community and highlight the most valuable resources for further learning and growth.</p><h4 id="community-support">Community Support</h4><p>The React Native community is active and welcoming, offering several platforms for developers to interact, share knowledge, and solve problems together:</p><ol><li><strong>GitHub</strong>: The React Native repository on GitHub is not just a place to access its source code. It's also a hub where developers report issues, suggest features, and contribute to the project. Engaging here allows you to directly influence the development of React Native​.</li><li><strong>React Native Community on Discord and Reddit</strong>: These platforms host vibrant communities where you can ask questions, share your projects, and get feedback from fellow developers. They are ideal for real-time communication and getting to know other developers in the field​​.</li><li><strong>Conferences and Meetups</strong>: Attend React Native-specific events, conferences, and meetups to learn from experienced speakers, network with professionals, and discover new opportunities. Events like Chain React and React Native EU are popular among developers​ (<a href="https://reactnative.dev/docs/getting-started" rel="noreferrer">ReactNativeLearn</a>)​​ (<a href="https://blog.risingstack.com/a-definitive-react-native-guide-for-react-developers/" rel="noreferrer">RisingStack Engineering</a>)​.</li></ol><h4 id="learning-resources">Learning Resources</h4><p>To deepen your knowledge and skills in React Native, here are some of the top resources:</p><ol><li><strong>Official Documentation</strong>: The React Native <a href="https://reactnative.dev/docs/getting-started">official documentation</a> is the most authoritative resource for learning about the framework. It is comprehensive and regularly updated with the latest features and best practices​ (<a href="https://reactnative.dev/docs/getting-started" rel="noreferrer">ReactNativeLearn</a>)​.</li><li><strong>Online Courses and Tutorials</strong>: Platforms like Coursera, Udemy, and freeCodeCamp offer a range of tutorials and courses that cover everything from basic to advanced React Native development. These resources are great for structured learning and often include hands-on projects to practice what you learn​ ​​(<a href="https://www.reactnative.express/" rel="noreferrer">React Native Express</a>)​.</li><li><strong>Books and Blogs</strong>: Consider reading books like "Learning React Native" by Bonnie Eisenman or blogs from major React contributors. These can provide deeper insights into the framework and its use in real-world applications​​​ (<a href="https://blog.logrocket.com/react-native-track-player-complete-guide/" rel="noreferrer">LogRocket Blog</a>)​.</li><li><strong>Podcasts and Videos</strong>: Listening to podcasts like "React Native Radio" and watching tutorial videos on YouTube are excellent ways to stay updated and learn new concepts in a more digestible format. They can be particularly useful for visual learners and those who prefer audio-visual content​ (<a href="https://www.freecodecamp.org/news/react-native-guide/" rel="noreferrer">FreeCodeCamp</a>)​​ (<a href="https://reactnativecentral.com/react-native-essentials-flexbox-guide/" rel="noreferrer">React Native Central</a>)​.</li></ol><p>By engaging with the community and utilizing a variety of learning resources, you can stay at the forefront of React Native development. This will not only enhance your technical skills but also keep you inspired and motivated as you see what others in the community are achieving. Whether you're troubleshooting a complex problem or looking for the next big idea, the React Native community and the wealth of available resources will support you on your development journey.</p><h2 id="frequently-asked-questions-about-react-native">Frequently Asked Questions About React Native</h2><p>This section addresses some of the most commonly asked questions about React Native, providing clear and concise answers that are essential for both beginners and experienced developers.</p><h4 id="what-is-the-difference-between-react-and-react-native">What is the difference between React and React Native?</h4><p>React and React Native are both open-source libraries developed by Facebook, but they serve different purposes. React, also known as React.js, is a JavaScript library for building user interfaces primarily for web applications. It follows the component-based architecture, which allows developers to create reusable UI components.</p><